diff options
author | Thorbjørn Lund Martsum <tmartsum@gmail.com> | 2017-09-01 20:45:27 +0200 |
---|---|---|
committer | Qt Cherry-pick Bot <cherrypick_bot@qt-project.org> | 2021-08-10 10:00:25 +0000 |
commit | 003fa58eef0e2773376313b8aff19342dd61f4eb (patch) | |
tree | 610a9d947e65d8ca17e7d3cce04e537a2b9efccc | |
parent | 9fcd65d4e40b78cced668374ff2b9a3d38e2be3a (diff) |
QListView: fix AdjustToContents (sizeAdjustPolicy)
Unlike an acceptable effect in QTableView + QTreeView
setAdjustPolicy(QAbstractScrollArea::AdjustToContents)
unfortunately didn't work for QListViews (and QListWidget).
This patch corrects QListViews AdjustToContents
behavior.
[ChangeLog][QtWidgets][QListView] A more correct implementation
of QListView::viewportSizeHint has been made. That
implies that setting the sizeAdjustPolicy to AdjustToContent
on QListView and QListWidget will now cause the view to
size after the contents and avoid scrollbars.
Task-number: QTBUG-58749
Change-Id: I1675115f2348e2fcf0b2c39b451ef337e10eb872
Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@qt.io>
(cherry picked from commit 7502598ef5bfa3f1a6d4f435bc2b91914e3acc61)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
-rw-r--r-- | src/widgets/itemviews/qlistview.cpp | 42 | ||||
-rw-r--r-- | tests/auto/widgets/itemviews/qlistview/tst_qlistview.cpp | 42 |
2 files changed, 83 insertions, 1 deletions
diff --git a/src/widgets/itemviews/qlistview.cpp b/src/widgets/itemviews/qlistview.cpp index 9b3221f84e..68d5d7612f 100644 --- a/src/widgets/itemviews/qlistview.cpp +++ b/src/widgets/itemviews/qlistview.cpp @@ -3487,7 +3487,47 @@ int QListView::visualIndex(const QModelIndex &index) const */ QSize QListView::viewportSizeHint() const { - return QAbstractItemView::viewportSizeHint(); + Q_D(const QListView); + // We don't have a nice simple size hint for invalid or wrapping list views. + if (!d->model) + return QAbstractItemView::viewportSizeHint(); + const int rc = d->model->rowCount(); + if (rc == 0 || isWrapping()) + return QAbstractItemView::viewportSizeHint(); + + QStyleOptionViewItem option; + initViewItemOption(&option); + + if (uniformItemSizes()) { + QSize sz = d->cachedItemSize; + if (!sz.isValid()) { + QModelIndex idx = d->model->index(0, d->column, d->root); + sz = d->itemSize(option, idx); + } + sz.setHeight(rc * sz.height()); + return sz; + } + + // Using AdjustToContents with a high number of rows will normally not make sense, so we limit + // this to default 1000 (that is btw the default for QHeaderView::resizeContentsPrecision()) + // (By setting the property _q_resizeContentPrecision the user can however override this). + int maximumRows = 1000; + const QVariant userOverrideValue = property("_q_resizeContentPrecision"); + if (userOverrideValue.isValid() && userOverrideValue.toInt() > 0) { + maximumRows = userOverrideValue.toInt(); + } + const int rowCount = qMin(rc, maximumRows); + + int h = 0; + int w = 0; + + for (int row = 0; row < rowCount; ++row) { + QModelIndex idx = d->model->index(row, d->column, d->root); + QSize itemSize = d->itemSize(option, idx); + h += itemSize.height(); + w = qMax(w, itemSize.width()); + } + return QSize(w, h); } QT_END_NAMESPACE diff --git a/tests/auto/widgets/itemviews/qlistview/tst_qlistview.cpp b/tests/auto/widgets/itemviews/qlistview/tst_qlistview.cpp index 7bd14729d8..74198d1cc4 100644 --- a/tests/auto/widgets/itemviews/qlistview/tst_qlistview.cpp +++ b/tests/auto/widgets/itemviews/qlistview/tst_qlistview.cpp @@ -38,6 +38,8 @@ #include <QTimer> #include <QtMath> #include <QProxyStyle> +#include <QVBoxLayout> +#include <QDialog> #include <QtTest/private/qtesthelpers_p.h> #include <QtWidgets/private/qlistview_p.h> @@ -166,6 +168,7 @@ private slots: void taskQTBUG_39902_mutualScrollBars(); void horizontalScrollingByVerticalWheelEvents(); void taskQTBUG_7232_AllowUserToControlSingleStep(); + void taskQTBUG_58749_adjustToContent(); void taskQTBUG_51086_skippingIndexesInSelectedIndexes(); void taskQTBUG_47694_indexOutOfBoundBatchLayout(); void itemAlignment(); @@ -2527,6 +2530,45 @@ void tst_QListView::taskQTBUG_7232_AllowUserToControlSingleStep() QCOMPARE(hStep1, lv.horizontalScrollBar()->singleStep()); } +void tst_QListView::taskQTBUG_58749_adjustToContent() +{ + QStandardItemModel model; + model.setRowCount(20); + model.setColumnCount(1); + const QString rowStr = QStringLiteral("Row number txt:"); + for (int u = 0; u < model.rowCount(); ++u) + model.setData(model.index(u, 0), rowStr + QString::number(u)); + + QDialog w; // It really should work for QWidget, too, but sometimes an event (like move) + // is needed to get the resize triggered. + QVBoxLayout *l = new QVBoxLayout(&w); + l->setSizeConstraint(QLayout::SetFixedSize); + auto *view = new QListView; + view->setModel(&model); + view->setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContents); + l->addWidget(view); + l->setSizeConstraint(QLayout::SetFixedSize); + w.show(); + QVERIFY(QTest::qWaitForWindowExposed(&w)); + + const QString longText = "Here we have a row text that is somewhat longer ..."; + + QFontMetrics fm(w.font(), &w); + QRect r = fm.boundingRect(model.data(model.index(0, 0)).toString()); + const int longTextWidth = fm.horizontalAdvance(longText); + QVERIFY(w.height() > r.height() * model.rowCount()); + // We have a width longer than the width for the given index data. + QVERIFY(w.width() > r.width()); + // but ... the width should not have a width matching the much longer text. + QVERIFY(w.width() < longTextWidth); + + // use the long text and make sure the width is adjusted. + model.setData(model.index(0, 0), longText); + QApplication::processEvents(); + QVERIFY(w.width() > longTextWidth); + QVERIFY(view->width() >= longTextWidth); +} + void tst_QListView::taskQTBUG_51086_skippingIndexesInSelectedIndexes() { QStandardItemModel data(10, 1); |