diff options
Diffstat (limited to 'src/widgets/itemviews/qtreeview.cpp')
-rw-r--r-- | src/widgets/itemviews/qtreeview.cpp | 144 |
1 files changed, 115 insertions, 29 deletions
diff --git a/src/widgets/itemviews/qtreeview.cpp b/src/widgets/itemviews/qtreeview.cpp index 6aefbb5367..38f0aa6a9e 100644 --- a/src/widgets/itemviews/qtreeview.cpp +++ b/src/widgets/itemviews/qtreeview.cpp @@ -335,6 +335,7 @@ void QTreeView::setHeader(QHeaderView *header) this, SLOT(updateGeometries())); setSortingEnabled(d->sortingEnabled); + d->updateGeometry(); } /*! @@ -1526,6 +1527,23 @@ void QTreeViewPrivate::calcLogicalIndices(QVector<int> *logicalIndices, QVector< } } +/*! + \internal + Get sizeHint width for single index (providing existing hint and style option) and index in viewIndex i. +*/ +int QTreeViewPrivate::widthHintForIndex(const QModelIndex &index, int hint, const QStyleOptionViewItem &option, int i) const +{ + QWidget *editor = editorForIndex(index).widget.data(); + if (editor && persistent.contains(editor)) { + hint = qMax(hint, editor->sizeHint().width()); + int min = editor->minimumSize().width(); + int max = editor->maximumSize().width(); + hint = qBound(min, hint, max); + } + int xhint = delegateForIndex(index)->sizeHint(option, index).width(); + hint = qMax(hint, xhint + (index.column() == 0 ? indentationForItem(i) : 0)); + return hint; +} /*! Draws the row in the tree view that contains the model item \a index, @@ -2400,16 +2418,11 @@ void QTreeView::scrollContentsBy(int dx, int dy) dx = isRightToLeft() ? -dx : dx; if (dx) { + int oldOffset = d->header->offset(); + d->header->d_func()->setScrollOffset(horizontalScrollBar(), horizontalScrollMode()); if (horizontalScrollMode() == QAbstractItemView::ScrollPerItem) { - int oldOffset = d->header->offset(); - if (horizontalScrollBar()->value() == horizontalScrollBar()->maximum()) - d->header->setOffsetToLastSection(); - else - d->header->setOffsetToSectionPosition(horizontalScrollBar()->value()); int newOffset = d->header->offset(); dx = isRightToLeft() ? newOffset - oldOffset : oldOffset - newOffset; - } else { - d->header->setOffset(horizontalScrollBar()->value()); } } @@ -2552,7 +2565,7 @@ void QTreeView::columnCountChanged(int oldCount, int newCount) /*! Resizes the \a column given to the size of its contents. - \sa columnWidth(), setColumnWidth() + \sa columnWidth(), setColumnWidth(), sizeHintForColumn(), QHeaderView::resizeContentsPrecision() */ void QTreeView::resizeColumnToContents(int column) { @@ -2619,6 +2632,35 @@ void QTreeView::selectAll() } /*! + \reimp +*/ +QSize QTreeView::viewportSizeHint() const +{ + Q_D(const QTreeView); + d->executePostedLayout(); // Make sure that viewItems are up to date. + + if (d->viewItems.size() == 0) + return QAbstractItemView::viewportSizeHint(); + + // Get rect for last item + const QRect deepestRect = visualRect(d->viewItems.last().index); + + if (!deepestRect.isValid()) + return QAbstractItemView::viewportSizeHint(); + + QSize result = QSize(d->header->length(), deepestRect.bottom() + 1); + + // add size for header + result += QSize(0, d->header->isVisible() ? d->header->height() : 0); + + // add size for scrollbars + result += QSize(verticalScrollBar()->isVisible() ? verticalScrollBar()->width() : 0, + horizontalScrollBar()->isVisible() ? horizontalScrollBar()->height() : 0); + + return result; +} + +/*! \since 4.2 Expands all expandable items. @@ -2740,7 +2782,6 @@ void QTreeView::updateGeometries() QRect vg = d->viewport->geometry(); QRect geometryRect(vg.left(), vg.top() - hint.height(), vg.width(), hint.height()); d->header->setGeometry(geometryRect); - //d->header->setOffset(horizontalScrollBar()->value()); // ### bug ??? QMetaObject::invokeMethod(d->header, "updateGeometries"); d->updateScrollBars(); d->geometryRecursionBlock = false; @@ -2760,7 +2801,7 @@ void QTreeView::updateGeometries() if a larger column width is required by either the view's header or the item delegate, that width will be used instead. - \sa QWidget::sizeHint, header() + \sa QWidget::sizeHint, header(), QHeaderView::resizeContentsPrecision() */ int QTreeView::sizeHintForColumn(int column) const { @@ -2773,28 +2814,58 @@ int QTreeView::sizeHintForColumn(int column) const QStyleOptionViewItem option = d->viewOptions(); const QVector<QTreeViewItem> viewItems = d->viewItems; - int start = 0; - int end = viewItems.count(); - if(end > 1000) { //if we have too many item this function would be too slow. - //we get a good approximation by only iterate over 1000 items. - start = qMax(0, d->firstVisibleItem() - 100); - end = qMin(end, start + 900); - } + const int maximumProcessRows = d->header->resizeContentsPrecision(); // To avoid this to take forever. - for (int i = start; i < end; ++i) { + int offset = 0; + int start = d->firstVisibleItem(&offset); + int end = d->lastVisibleItem(start, offset); + + int rowsProcessed = 0; + + for (int i = start; i <= end; ++i) { if (viewItems.at(i).spanning) continue; // we have no good size hint QModelIndex index = viewItems.at(i).index; index = index.sibling(index.row(), column); - QWidget *editor = d->editorForIndex(index).widget.data(); - if (editor && d->persistent.contains(editor)) { - w = qMax(w, editor->sizeHint().width()); - int min = editor->minimumSize().width(); - int max = editor->maximumSize().width(); - w = qBound(min, w, max); + w = d->widthHintForIndex(index, w, option, i); + ++rowsProcessed; + if (rowsProcessed == maximumProcessRows) + break; + } + + --end; + int actualBottom = viewItems.size() - 1; + + if (maximumProcessRows == 0) + rowsProcessed = 0; // skip the while loop + + while (rowsProcessed != maximumProcessRows && (start > 0 || end < actualBottom)) { + int idx = -1; + + if ((rowsProcessed % 2 && start > 0) || end == actualBottom) { + while (start > 0) { + --start; + if (viewItems.at(start).spanning) + continue; + idx = start; + break; + } + } else { + while (end < actualBottom) { + ++end; + if (viewItems.at(end).spanning) + continue; + idx = end; + break; + } } - int hint = d->delegateForIndex(index)->sizeHint(option, index).width(); - w = qMax(w, hint + (column == 0 ? d->indentationForItem(i) : 0)); + if (idx < 0) + continue; + + QModelIndex index = viewItems.at(idx).index; + index = index.sibling(index.row(), column); + w = d->widthHintForIndex(index, w, option, idx); + ++rowsProcessed; } return w; } @@ -3314,7 +3385,7 @@ int QTreeViewPrivate::coordinateForItem(int item) const if (verticalScrollMode == QAbstractItemView::ScrollPerPixel) { if (uniformRowHeights) return (item * defaultItemHeight) - vbar->value(); - // ### optimize (spans or caching) + // ### optimize (maybe do like QHeaderView by letting items have startposition) int y = 0; for (int i = 0; i < viewItems.count(); ++i) { if (i == item) @@ -3481,7 +3552,7 @@ int QTreeViewPrivate::firstVisibleItem(int *offset) const *offset = -(value % defaultItemHeight); return value / defaultItemHeight; } - int y = 0; // ### optimize (use spans ?) + int y = 0; // ### (maybe do like QHeaderView by letting items have startposition) for (int i = 0; i < viewItems.count(); ++i) { y += itemHeight(i); // the height value is cached if (y > value) { @@ -3493,6 +3564,21 @@ int QTreeViewPrivate::firstVisibleItem(int *offset) const return -1; } +int QTreeViewPrivate::lastVisibleItem(int firstVisual, int offset) const +{ + if (firstVisual < 0 || offset < 0) + firstVisual = firstVisibleItem(&offset); + int y = - offset; + int value = viewport->height(); + + for (int i = firstVisual; i < viewItems.count(); ++i) { + y += itemHeight(i); // the height value is cached + if (y > value) + return i; + } + return viewItems.size() - 1; +} + int QTreeViewPrivate::columnAt(int x) const { return header->logicalIndexAt(x); @@ -3535,7 +3621,7 @@ void QTreeViewPrivate::updateScrollBars() int contentsHeight = 0; if (uniformRowHeights) { contentsHeight = defaultItemHeight * viewItems.count(); - } else { // ### optimize (spans or caching) + } else { // ### (maybe do like QHeaderView by letting items have startposition) for (int i = 0; i < viewItems.count(); ++i) contentsHeight += itemHeight(i); } |