📄 qtreeview.cpp
字号:
} } return height;}/*! \reimp*/void QTreeView::horizontalScrollbarAction(int action){ QAbstractItemView::horizontalScrollbarAction(action);}/*! \reimp*/bool QTreeView::isIndexHidden(const QModelIndex &index) const{ return (isColumnHidden(index.column()) || isRowHidden(index.row(), index.parent()));}/* private implementation*/void QTreeViewPrivate::initialize(){ Q_Q(QTreeView); q->setSelectionBehavior(QAbstractItemView::SelectRows); q->setSelectionMode(QAbstractItemView::SingleSelection); QHeaderView *header = new QHeaderView(Qt::Horizontal, q); header->setMovable(true); header->setStretchLastSection(true); q->setHeader(header);}void QTreeViewPrivate::expand(int i, bool emitSignal){ Q_Q(QTreeView); if (!model || i == -1 || viewItems.at(i).expanded) return; q->setState(QAbstractItemView::ExpandingState); QModelIndex index = viewItems.at(i).index; expandedIndexes.append(index); viewItems[i].expanded = true; layout(i); // make sure we expand children that were previously expanded if (model->hasChildren(index)) reexpandChildren(index); q->setState(QAbstractItemView::NoState); if (emitSignal) emit q->expanded(index);}void QTreeViewPrivate::collapse(int item, bool emitSignal){ Q_Q(QTreeView); if (!model || item == -1 || expandedIndexes.isEmpty()) return; q->setState(QAbstractItemView::CollapsingState); int total = viewItems.at(item).total; QModelIndex modelIndex = viewItems.at(item).index; int index = expandedIndexes.indexOf(modelIndex); if (index == -1 || viewItems.at(item).expanded == false) return; // nothing to do expandedIndexes.remove(index); viewItems[item].expanded = false; index = item; QModelIndex parent = modelIndex; while (parent.isValid() && parent != root) { Q_ASSERT(index > -1); viewItems[index].total -= total; parent = parent.parent(); index = viewIndex(parent); } viewItems.remove(item + 1, total); // collapse q->setState(QAbstractItemView::NoState); if (emitSignal) emit q->collapsed(modelIndex);}void QTreeViewPrivate::layout(int i){ Q_Q(QTreeView); QModelIndex current; QModelIndex parent = modelIndex(i); int count = 0; if (model->hasChildren(parent)) count = model->rowCount(parent); if (i == -1) viewItems.resize(count); else viewItems.insert(i + 1, count, QTreeViewItem()); // expand int first = i + 1; int level = (i >= 0 ? viewItems.at(i).level + 1 : 0); int hidden = 0; int last = 0; int firstColumn = 0; while (q->isColumnHidden(firstColumn) && firstColumn < q->header()->count()) ++firstColumn; for (int j = first; j < first + count; ++j) { current = model->index(j - first, firstColumn, parent); if (q->isRowHidden(current.row(), parent)) { // slow with lots of hidden rows ++hidden; last = j - hidden; } else { last = j - hidden; viewItems[last].index = current; viewItems[last].level = level; } } // remove hidden items if (hidden > 0) viewItems.remove(last + 1, hidden); // collapse QModelIndex root = q->rootIndex(); while (parent != root) { Q_ASSERT(i > -1); viewItems[i].total += count - hidden; parent = parent.parent(); i = viewIndex(parent); }}int QTreeViewPrivate::pageUp(int i) const{ int index = item(coordinate(i) - viewport->height()); return index == -1 ? 0 : index;}int QTreeViewPrivate::pageDown(int i) const{ int index = item(coordinate(i) + viewport->height()); return index == -1 ? viewItems.count() - 1 : index;}int QTreeViewPrivate::indentation(int i) const{ if (i < 0 || i >= viewItems.count()) return 0; int level = viewItems.at(i).level; if (rootDecoration) ++level; return level * indent;}/*! \internal Returns the y coordinate for item Note: if this is ever changed to not estimate then update item()*/int QTreeViewPrivate::coordinate(int item) const{ Q_Q(const QTreeView); int scrollbarValue = q->verticalScrollBar()->value(); int topViewItemIndex = itemAt(scrollbarValue); if (topViewItemIndex == -1) { const_cast<QTreeViewPrivate*>(this)->updateScrollbars(); scrollbarValue = q->verticalScrollBar()->value(); topViewItemIndex = itemAt(scrollbarValue); } Q_ASSERT(topViewItemIndex != -1); int viewItemIndex = topViewItemIndex; // first item (may start above the page) int viewItemHeight = height(viewItemIndex); int topItemCoordinate = topItemDelta(scrollbarValue, viewItemHeight); int viewItemCoordinate = topItemCoordinate; int viewportHeight = viewport->height(); if (viewItemIndex <= item) { // search in the visible area first while (viewItemCoordinate < viewportHeight && viewItemIndex < viewItems.count()) { if (viewItemIndex == item) return viewItemCoordinate; // item is visible - actual y in viewport viewItemCoordinate += height(viewItemIndex); ++viewItemIndex; } // the item is below the viewport if (editors.isEmpty()) // optimized; estimate the coordinate return viewItemCoordinate + (itemHeight * (item - viewItemIndex)); // non-optimized for (;viewItemIndex < viewItems.count(); ++viewItemIndex) { if (viewItemIndex == item) return viewItemCoordinate; viewItemCoordinate += height(viewItemIndex); } // below the last item in the view // Q_ASSERT(false); return viewItemCoordinate; } // the item is above the viewport if (editors.isEmpty()) // optimized; estimate the coordinate return viewItemCoordinate - (itemHeight * (viewItemIndex - item)); // non-optimized viewItemCoordinate = topItemCoordinate; viewItemIndex = topViewItemIndex; for (; viewItemIndex >= 0; --viewItemIndex) { if (viewItemIndex == item) return viewItemCoordinate; viewItemCoordinate -= height(viewItemIndex); } // above the first item in the view // Q_ASSERT(false); return viewItemCoordinate;}/*! \internal Returns the visual index at \a coordinate or -1 \sa modelIndex()*/int QTreeViewPrivate::item(int yCoordinate) const{ Q_Q(const QTreeView); int scrollbarValue = q->verticalScrollBar()->value(); int viewItemIndex = itemAt(scrollbarValue); if (viewItemIndex < 0) // couldn't find first visible item return -1; int viewItemHeight = height(viewItemIndex); int viewportHeight = viewport->height(); int y = topItemDelta(scrollbarValue, viewItemHeight); if (yCoordinate >= y) { // search for item in viewport while (y < viewportHeight && viewItemIndex < viewItems.count()) { y += height(viewItemIndex); if (yCoordinate < y) return viewItemIndex; ++viewItemIndex; } } if (itemHeight <= 0) return -1; // item is above the viewport - find via binary search // If coordinate() is ever changed to not estimate // the value then change this to just walk the tree int start = 0; int end = viewItems.count(); int i = (start + end + 1) >> 1; while (end - start > 0) { if (yCoordinate < coordinate(i)) end = i - 1; else start = i; i = (start + end + 1) >> 1; } return (i < viewItems.count() ? i : -1);}int QTreeViewPrivate::viewIndex(const QModelIndex &index) const{ Q_Q(const QTreeView); if (!index.isValid()) return -1; int totalCount = viewItems.count(); QModelIndex parent = index.parent(); // A quick check near the last item to see if we are just incrimenting int start = lastViewedItem > 2 ? lastViewedItem - 2 : 0; int end = lastViewedItem < totalCount - 2 ? lastViewedItem + 2 : totalCount; for (int i = start; i < end; ++i) { const QModelIndex idx = viewItems.at(i).index; if (idx.row() == index.row()) { if (idx.internalId() == index.internalId() || idx.parent() == parent) {// ignore column lastViewedItem = i; return i; } } } // NOTE: this function is slow if the item is outside the visible area // search in visible items first and below int t = itemAt(q->verticalScrollBar()->value()); t = t > 100 ? t - 100 : 0; // start 100 items above the visible area for (int i = t; i < totalCount; ++i) { const QModelIndex idx = viewItems.at(i).index; if (idx.row() == index.row()) { if (idx.internalId() == index.internalId() || idx.parent() == parent) {// ignore column lastViewedItem = i; return i; } } } // search from top to first visible for (int j = 0; j < t; ++j) { const QModelIndex idx = viewItems.at(j).index; if (idx.row() == index.row()) { if (idx.internalId() == index.internalId() || idx.parent() == parent) { // ignore column lastViewedItem = j; return j; } } } // nothing found return -1;}QModelIndex QTreeViewPrivate::modelIndex(int i) const{ return ((i < 0 || i >= viewItems.count()) ? (QModelIndex)root : viewItems.at(i).index);}int QTreeViewPrivate::itemAt(int value) const{ int i = value / verticalStepsPerItem; return (i < 0 || i >= viewItems.count()) ? -1 : i;}int QTreeViewPrivate::topItemDelta(int value, int iheight) const{ int above = (value % verticalStepsPerItem) * iheight; // what's left; in "item units" return -(above / verticalStepsPerItem); // above the page}int QTreeViewPrivate::columnAt(int x) const{ return header->logicalIndexAt(x);}void QTreeViewPrivate::relayout(const QModelIndex &parent){ Q_Q(QTreeView); // do a local relayout of the items if (parent.isValid()) { int parentViewIndex = viewIndex(parent); if (parentViewIndex > -1 && viewItems.at(parentViewIndex).expanded) { collapse(parentViewIndex, false); // remove the current layout expand(parentViewIndex, false); // do the relayout q->updateGeometries(); viewport->update(); } } else { viewItems.clear(); q->doItemsLayout(); }}void QTreeViewPrivate::reexpandChildren(const QModelIndex &parent){ if (!model) return; // FIXME: this is slow: optimize QVector<QPersistentModelIndex> o = expandedIndexes; for (int j = 0; j < o.count(); ++j) { QModelIndex index = o.at(j); if (!index.isValid()){ int k = expandedIndexes.indexOf(index); if (k >= 0) expandedIndexes.remove(k); } else if (model->parent(index) == parent) { int v = viewIndex(index); if (v < 0) continue; int k = expandedIndexes.indexOf(index); expandedIndexes.remove(k); expand(v, false); } }}void QTreeViewPrivate::updateScrollbars(){ Q_Q(QTreeView); QSize viewportSize = viewport->size(); // TODO why is there an assert when you remove this if in the file dialog? if (!viewport->isVisible()) { q->verticalScrollBar()->setRange(0, 0); q->verticalScrollBar()->setPageStep(0); return; } // set page step size int verticalScrollBarValue = q->verticalScrollBar()->value(); int itemsInViewport = 0; if (uniformRowHeights) { itemsInViewport = viewportSize.height() / itemHeight; } else { int topItemInViewport = qMax(0, itemAt(verticalScrollBarValue)); int h = height(topItemInViewport); int y = topItemDelta(verticalScrollBarValue, h); int i = topItemInViewport; for (; y < viewportSize.height() && i < viewItems.count(); ++i) y += height(i); itemsInViewport = i - topItemInViewport; } q->verticalScrollBar()->setPageStep(itemsInViewport * verticalStepsPerItem); // set the scroller range int y = viewportSize.height(); int i = viewItems.count(); while (y > 0 && i > 0) // subtract the bottom screen y -= height(--i);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -