Check scrollbar visibility when computing QListView margins

When the listview setWordWrap is true and ScrollBarPolicy is
ScrollBarAsNeeded, if the text needs a newline display and the
vbar is not shown, the width of the item was subtracted from
the width of the scrollbar.

In most cases, the listview needs to reserve the size of the scrollbar.
But if the flow is TopToBottom and the vertical scrollbar is not
visible, the width of the vertical scrollbar cannot be reserved.

Fixes: QTBUG-92366
Pick-to: 5.15 6.0 6.1
Change-Id: I73cce691099a253d409019dbb3fe9a16e1830bb1
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
This commit is contained in:
Chen Bin 2021-04-02 13:40:08 +08:00
parent 2be9e6cc26
commit aeef92c3c3
2 changed files with 55 additions and 1 deletions

View File

@ -1797,7 +1797,7 @@ void QListViewPrivate::prepareItemsLayout()
// maximumViewportSize() already takes scrollbar into account if policy is
// Qt::ScrollBarAlwaysOn but scrollbar extent must be deduced if policy
// is Qt::ScrollBarAsNeeded
int verticalMargin = vbarpolicy==Qt::ScrollBarAsNeeded
int verticalMargin = (vbarpolicy == Qt::ScrollBarAsNeeded) && (flow == QListView::LeftToRight || vbar->isVisible())
? q->style()->pixelMetric(QStyle::PM_ScrollBarExtent, nullptr, vbar) + frameAroundContents
: 0;
int horizontalMargin = hbarpolicy==Qt::ScrollBarAsNeeded

View File

@ -169,6 +169,7 @@ private slots:
void itemAlignment();
void internalDragDropMove_data();
void internalDragDropMove();
void spacingWithWordWrap();
};
// Testing get/set functions
@ -2710,6 +2711,59 @@ void tst_QListView::internalDragDropMove()
}
}
/*!
Verify fix for QTBUG-92366
*/
void tst_QListView::spacingWithWordWrap()
{
const int listViewResizeCount = 200;
QWidget window;
window.resize(300, 200);
QListView lv(&window);
lv.setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
lv.setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
lv.setFlow(QListView::TopToBottom);
lv.setWordWrap(true);
lv.setSpacing(0);
lv.setGeometry(0, 0, 200, 150);
QStandardItem *it1 = new QStandardItem("qqqqqqqqqqqqqqqqqqqqq-ttttttttttttttttt");
QStandardItem *it2 = new QStandardItem("qqqqqqqqqqqqqqqq-tttttttttttt");
QStandardItemModel model;
lv.setModel(&model);
model.appendRow(it1);
model.appendRow(it2);
window.show();
QVERIFY(QTest::qWaitForWindowExposed(&window));
QVERIFY(!lv.verticalScrollBar()->isVisible());
for (int i = 0; i < listViewResizeCount; ++i) {
lv.resize(lv.width() + 1, lv.height());
QRect rectForRowOne = lv.visualRect(model.index(0, 0));
QRect rectForRowTwo = lv.visualRect(model.index(1, 0));
QCOMPARE(rectForRowOne.y() + rectForRowOne.height(), rectForRowTwo.y());
}
lv.resize(200, 150);
const QStringList &stringList = generateList(QStringLiteral("Test_Abnormal_Spacing"), 30);
for (const QString &item_string : stringList) {
QStandardItem *item = new QStandardItem(item_string);
model.appendRow(item);
}
// test whether the height of item is correct if the vbar is shown.
QTRY_VERIFY(lv.verticalScrollBar()->isVisible());
for (int i = 0; i < listViewResizeCount; ++i) {
lv.resize(lv.width() + 1, lv.height());
QRect rectForRowOne = lv.visualRect(model.index(0, 0));
QRect rectForRowTwo = lv.visualRect(model.index(1, 0));
QCOMPARE(rectForRowOne.y() + rectForRowOne.height(), rectForRowTwo.y());
}
}
QTEST_MAIN(tst_QListView)
#include "tst_qlistview.moc"