📄 qlistview.cpp
字号:
{ Q_Q(QListView); const bool useItemSize = !gridSize.isValid(); const int gap = useItemSize ? spacing : 0; const QPoint topLeft = initDynamicLayout(bounds, spacing, first); int segStartPosition; int segEndPosition; int deltaFlowPosition; int deltaSegPosition; int deltaSegHint; int flowPosition; int segPosition; if (flow == QListView::LeftToRight) { segStartPosition = bounds.left() + spacing; segEndPosition = bounds.right(); deltaFlowPosition = gridSize.width(); // dx deltaSegPosition = (useItemSize ? batchSavedDeltaSeg : gridSize.height()); // dy deltaSegHint = gridSize.height(); flowPosition = topLeft.x(); segPosition = topLeft.y(); } else { // flow == QListView::TopToBottom segStartPosition = bounds.top() + spacing; segEndPosition = bounds.bottom(); deltaFlowPosition = gridSize.height(); // dy deltaSegPosition = (useItemSize ? batchSavedDeltaSeg : gridSize.width()); // dx deltaSegHint = gridSize.width(); flowPosition = topLeft.y(); segPosition = topLeft.x(); } if (moved.count() != items.count()) moved.resize(items.count()); QRect rect(QPoint(0, 0), topLeft); QListViewItem *item = 0; for (int row = first; row <= last; ++row) { item = &items[row]; if (hiddenRows.contains(row)) { item->invalidate(); } else { // if we are not using a grid, we need to find the deltas if (useItemSize) { if (flow == QListView::LeftToRight) deltaFlowPosition = item->w + gap; else deltaFlowPosition = item->h + gap; } else { item->w = qMin<int>(gridSize.width(), item->w); item->h = qMin<int>(gridSize.height(), item->h); } // create new segment if (wrap && flowPosition + deltaFlowPosition > segEndPosition && flowPosition > segStartPosition) { flowPosition = segStartPosition; segPosition += deltaSegPosition; if (useItemSize) deltaSegPosition = 0; } // We must delay calculation of the seg adjustment, as this item // may have caused a wrap to occur if (useItemSize) { if (flow == QListView::LeftToRight) { deltaSegHint = item->h + gap; } else { deltaSegHint = item->w + gap; } deltaSegPosition = qMax(deltaSegPosition, deltaSegHint); } // set the position of the item if (!moved.testBit(row)) { if (flow == QListView::LeftToRight) { item->x = flowPosition; item->y = segPosition; } else { // TopToBottom item->y = flowPosition; item->x = segPosition; } } rect |= item->rect(); // let the contents contain the new item // prepare for next item flowPosition += deltaFlowPosition; // current position + item width + gap } } batchSavedDeltaSeg = deltaSegPosition; batchStartRow = last + 1; bool done = (last >= model->rowCount(root) - 1); // resize the content area if (done || !bounds.contains(item->rect())) q->resizeContents(rect.width(), rect.height()); // resize tree int insertFrom = first; if (done || first == 0) { initBspTree(rect.size()); insertFrom = 0; } // insert items in tree for (int row = insertFrom; row <= last; ++row) tree.insertLeaf(items.at(row).rect(), row); // if the new items are visble, update the viewport QRect changedRect(topLeft, rect.bottomRight()); if (clipRect().intersects(changedRect)) viewport->update();}/*! \internal Finds the set of items intersecting with \a area. In this function, itemsize is counted from topleft to the start of the next item.*/void QListViewPrivate::intersectingStaticSet(const QRect &area) const{ if (!model) return; intersectVector.clear(); int segStartPosition; int segEndPosition; int flowStartPosition; int flowEndPosition; if (flow == QListView::LeftToRight) { segStartPosition = area.top(); segEndPosition = area.bottom(); flowStartPosition = area.left(); flowEndPosition = area.right(); } else { segStartPosition = area.left(); segEndPosition = area.right(); flowStartPosition = area.top(); flowEndPosition = area.bottom(); } if (segmentPositions.isEmpty() || flowPositions.isEmpty()) return; const int segLast = segmentPositions.count() - 1; Q_ASSERT(segLast > -1); int seg = qBinarySearch<int>(segmentPositions, segStartPosition, 0, segLast); for (; seg <= segLast && segmentPositions.at(seg) <= segEndPosition; ++seg) { int first = segmentStartRows.at(seg); int last = (seg < segLast ? segmentStartRows.at(seg + 1) : batchStartRow) - 1; int row = qBinarySearch<int>(flowPositions, flowStartPosition, first, last); for (; row <= last && flowPositions.at(row) <= flowEndPosition; ++row) { if (hiddenRows.contains(row)) continue; QModelIndex index = model->index(row, column, root); if (index.isValid()) intersectVector.append(index); else qWarning("intersectingStaticSet: row %d was invalid", row); } }}void QListViewPrivate::intersectingDynamicSet(const QRect &area) const{ intersectVector.clear(); QListViewPrivate *that = const_cast<QListViewPrivate*>(this); QBspTree::Data data(static_cast<void*>(that)); that->tree.climbTree(area, &QListViewPrivate::addLeaf, data);}void QListViewPrivate::createItems(int to){ Q_Q(QListView); int count = items.count(); QSize size; QStyleOptionViewItem option = q->viewOptions(); QModelIndex root = q->rootIndex(); for (int row = count; row < to; ++row) { size = itemSize(option, model->index(row, column, root)); QListViewItem item(QRect(0, 0, size.width(), size.height()), row); // default pos items.append(item); }}void QListViewPrivate::drawItems(QPainter *painter, const QVector<QModelIndex> &indexes) const{ Q_Q(const QListView); QStyleOptionViewItem option = q->viewOptions(); option.state &= ~QStyle::State_MouseOver; QVector<QModelIndex>::const_iterator it = indexes.begin(); QListViewItem item = indexToListViewItem(*it); for (; it != indexes.end(); ++it) { item = indexToListViewItem(*it); option.rect = viewItemRect(item); delegate->paint(painter, option, *it); }}QRect QListViewPrivate::itemsRect(const QVector<QModelIndex> &indexes) const{ QVector<QModelIndex>::const_iterator it = indexes.begin(); QListViewItem item = indexToListViewItem(*it); QRect rect(item.x, item.y, item.w, item.h); for (; it != indexes.end(); ++it) { item = indexToListViewItem(*it); rect |= viewItemRect(item); } return rect;}QListViewItem QListViewPrivate::indexToListViewItem(const QModelIndex &index) const{ Q_Q(const QListView); if (!index.isValid() || hiddenRows.contains(index.row())) return QListViewItem(); if (movement != QListView::Static) if (index.row() < items.count()) return items.at(index.row()); else return QListViewItem(); // movement == Static if (flowPositions.isEmpty() || segmentPositions.isEmpty()) return QListViewItem(); if (index.row() >= flowPositions.count()) return QListViewItem(); int l = segmentStartRows.count() - 1; int s = qBinarySearch<int>(segmentStartRows, index.row(), 0, l); QPoint pos; if (flow == QListView::LeftToRight) { pos.setX(flowPositions.at(index.row())); pos.setY(segmentPositions.at(s)); } else { // TopToBottom pos.setY(flowPositions.at(index.row())); pos.setX(segmentPositions.at(s)); } QSize size = (uniformItemSizes && cachedItemSize.isValid()) ? cachedItemSize : itemSize(q->viewOptions(), index); return QListViewItem(QRect(pos, size), index.row());}int QListViewPrivate::itemIndex(const QListViewItem &item) const{ int i = item.indexHint; if (movement == QListView::Static || i >= items.count() || items.at(i) == item) return i; int j = i; int c = items.count(); bool a = true; bool b = true; while (a || b) { if (a) { if (items.at(i) == item) { items.at(i).indexHint = i; return i; } a = ++i < c; } if (b) { if (items.at(j) == item) { items.at(j).indexHint = j; return j; } b = --j > -1; } } return -1;}void QListViewPrivate::addLeaf(QVector<int> &leaf, const QRect &area, uint visited, QBspTree::Data data){ QListViewItem *vi; QListViewPrivate *_this = static_cast<QListViewPrivate *>(data.ptr); for (int i = 0; i < leaf.count(); ++i) { int idx = leaf.at(i); if (idx < 0) continue; vi = &_this->items[idx]; Q_ASSERT(vi); if (vi->rect().intersects(area) && vi->visited != visited) { QModelIndex index = _this->listViewItemToIndex(*vi); Q_ASSERT(index.isValid()); _this->intersectVector.append(index); vi->visited = visited; } }}void QListViewPrivate::insertItem(int index, QListViewItem &item){ items.insert(index + 1, 1, item); // insert after idx tree.insertLeaf(item.rect(), index);}void QListViewPrivate::removeItem(int index){ tree.removeLeaf(items.at(index).rect(), index); items.remove(index, 1);}void QListViewPrivate::moveItem(int index, const QPoint &dest){ Q_Q(QListView); // does not impact on the bintree itself or the contents rect QListViewItem *item = &items[index]; QRect rect = item->rect(); // move the item without removing it from the tree tree.removeLeaf(rect, index); item->move(dest); tree.insertLeaf(QRect(dest, rect.size()), index); // resize the contents area int w = rect.x() + rect.width(); int h = rect.y() + rect.height(); w = w > contentsSize.width() ? w : contentsSize.width(); h = h > contentsSize.height() ? h : contentsSize.height(); q->resizeContents(w, h); if (moved.count() != items.count()) moved.resize(items.count()); moved.setBit(index, true);}QPoint QListViewPrivate::snapToGrid(const QPoint &pos) const{ int x = pos.x() - (pos.x() % gridSize.width()); int y = pos.y() - (pos.y() % gridSize.height()); return QPoint(x, y);}QRect QListViewPrivate::mapToViewport(const QRect &rect) const{ Q_Q(const QListView); if (!rect.isValid()) return rect; QRect result = rect; // If the listview is in "listbox-mode", the items are as wide as the view. if (!wrap && movement == QListView::Static && flow == QListView::TopToBottom) { if (q_func()->isRightToLeft()) { // Adjust the rect by expanding the left edge result.setLeft(result.right() - qMax(contentsSize.width(), viewport->width())); } else { // Adjust the rect by expanding the right edge result.setWidth(qMax(contentsSize.width(), viewport->width())); } } int dx = -q->horizontalOffset(); int dy = -q->verticalOffset(); result.adjust(dx, dy, dx, dy); return result;}QPoint QListViewPrivate::draggedItemsDelta() const{ return (movement == QListView::Snap ? snapToGrid(draggedItemsPos) - snapToGrid(pressedPosition) : draggedItemsPos - pressedPosition);}QRect QListViewPrivate::draggedItemsRect() const{ QRect rect = itemsRect(draggedItems); rect.translate(draggedItemsDelta()); return rect;}QModelIndex QListViewPrivate::closestIndex(const QPoint &target, const QVector<QModelIndex> &candidates) const{ int distance = 0; int shortest = -1; QModelIndex closest; QVector<QModelIndex>::const_iterator it = candidates.begin(); for (; it != candidates.end(); ++it) { if (!(*it).isValid()) continue; distance = (indexToListViewItem(*it).rect().center() - target).manhattanLength(); if (distance < shortest || shortest == -1) { shortest = distance; closest = *it; } } return closest;}QSize QListViewPrivate::itemSize(const QStyleOptionViewItem &option, const QModelIndex &index) const{ if (!uniformItemSizes) return delegate->sizeHint(option, index); if (!cachedItemSize.isValid()) { // the last item is probaly the largest, so we use its size int row = model->rowCount(root) - 1; QModelIndex sample = model->index(row, column, root); cachedItemSize = delegate->sizeHint(option, sample); } return cachedItemSize;}#endif // QT_NO_LISTVIEW
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -