summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThorbjørn Lund Martsum <tmartsum@gmail.com>2017-09-01 20:45:27 +0200
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2021-08-10 10:00:25 +0000
commit003fa58eef0e2773376313b8aff19342dd61f4eb (patch)
tree610a9d947e65d8ca17e7d3cce04e537a2b9efccc
parent9fcd65d4e40b78cced668374ff2b9a3d38e2be3a (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.cpp42
-rw-r--r--tests/auto/widgets/itemviews/qlistview/tst_qlistview.cpp42
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);