QAbstractScrollArea: fix sizeHint when widget is not visible

QTable/QTreeView did not follow the documentation and returned
their needed size with scrollbars within viewportSizeHint().
Then sizeHint() also took the size of the scrollbars into account
when the policy was set to ScrollBarAlwaysOn.
This lead to different results when the widget was shown/hidden and/or
the scrollbar was visible or not.
Fix it by only adding the additional size when the scrollbars are
really visible. Also use header->isHidden() instead of isVisible() in
QTreeView the same way it is done in QTableView.

[ChangeLog][QtWidgets][QAbstractScrollArea] QTableView/QTreeView are
now reporting their viewportSizeHint() correctly taking into account
its scroll bars visibility and visibilityPolicy.

Task-number: QTBUG-69120
Change-Id: If50959a9f7429275e3e33122644c978fb64972ba
Reviewed-by: Samuel Gaist <samuel.gaist@idiap.ch>
Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@qt.io>
bb10
Christian Ehrlicher 2018-07-29 21:31:57 +02:00
parent 80cc6bcec4
commit 3e59a88e89
5 changed files with 103 additions and 9 deletions

View File

@ -1111,8 +1111,6 @@ QSize QTableView::viewportSizeHint() const
Q_D(const QTableView);
QSize result( (d->verticalHeader->isHidden() ? 0 : d->verticalHeader->width()) + d->horizontalHeader->length(),
(d->horizontalHeader->isHidden() ? 0 : d->horizontalHeader->height()) + d->verticalHeader->length());
result += QSize(verticalScrollBar()->isVisible() ? verticalScrollBar()->width() : 0,
horizontalScrollBar()->isVisible() ? horizontalScrollBar()->height() : 0);
return result;
}

View File

@ -2686,11 +2686,7 @@ QSize QTreeView::viewportSizeHint() const
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);
result += QSize(0, d->header->isHidden() ? 0 : d->header->height());
return result;
}

View File

@ -1604,8 +1604,10 @@ QSize QAbstractScrollArea::sizeHint() const
if (!d->sizeHint.isValid() || d->sizeAdjustPolicy == QAbstractScrollArea::AdjustToContents) {
const int f = 2 * d->frameWidth;
const QSize frame( f, f );
const QSize scrollbars(d->vbarpolicy == Qt::ScrollBarAlwaysOn ? d->vbar->sizeHint().width() : 0,
d->hbarpolicy == Qt::ScrollBarAlwaysOn ? d->hbar->sizeHint().height() : 0);
const bool vbarHidden = d->vbar->isHidden() || d->vbarpolicy == Qt::ScrollBarAlwaysOff;
const bool hbarHidden = d->hbar->isHidden() || d->hbarpolicy == Qt::ScrollBarAlwaysOff;
const QSize scrollbars(vbarHidden ? 0 : d->vbar->sizeHint().width(),
hbarHidden ? 0 : d->hbar->sizeHint().height());
d->sizeHint = frame + scrollbars + viewportSizeHint();
}
return d->sizeHint;

View File

@ -83,6 +83,8 @@ private slots:
void setItemData();
void cellWidget();
void cellWidgetGeometry();
void sizeHint_data();
void sizeHint();
void task231094();
void task219380_removeLastRow();
void task262056_sortDuplicate();
@ -1450,6 +1452,56 @@ void tst_QTableWidget::cellWidgetGeometry()
QCOMPARE(tw.visualItemRect(item).top(), le->geometry().top());
}
void tst_QTableWidget::sizeHint_data()
{
QTest::addColumn<int>("scrollBarPolicy");
QTest::addColumn<QSize>("viewSize");
QTest::newRow("ScrollBarAlwaysOn") << static_cast<int>(Qt::ScrollBarAlwaysOn) << QSize();
QTest::newRow("ScrollBarAlwaysOff") << static_cast<int>(Qt::ScrollBarAlwaysOff) << QSize();
// make sure the scrollbars are shown by resizing the view to 40x40
QTest::newRow("ScrollBarAsNeeded (40x40)") << static_cast<int>(Qt::ScrollBarAsNeeded) << QSize(40, 40);
QTest::newRow("ScrollBarAsNeeded (1000x1000)") << static_cast<int>(Qt::ScrollBarAsNeeded) << QSize(1000, 1000);
}
void tst_QTableWidget::sizeHint()
{
QFETCH(int, scrollBarPolicy);
QFETCH(QSize, viewSize);
QTableWidget view(2, 2);
view.setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContents);
view.setVerticalScrollBarPolicy(static_cast<Qt::ScrollBarPolicy>(scrollBarPolicy));
view.setHorizontalScrollBarPolicy(static_cast<Qt::ScrollBarPolicy>(scrollBarPolicy));
for (int r = 0 ; r < view.rowCount(); ++r)
for (int c = 0 ; c < view.columnCount(); ++c)
view.setItem(r, c, new QTableWidgetItem(QString("%1/%2").arg(r).arg(c)));
view.show();
QVERIFY(QTest::qWaitForWindowExposed(&view));
if (viewSize.isValid()) {
view.resize(viewSize);
view.setColumnWidth(0, 100);
view.setRowHeight(0, 100);
QTRY_COMPARE(view.size(), viewSize);
}
auto sizeHint = view.sizeHint();
view.hide();
QCOMPARE(view.sizeHint(), sizeHint);
view.horizontalHeader()->hide();
view.show();
sizeHint = view.sizeHint();
view.hide();
QCOMPARE(view.sizeHint(), sizeHint);
view.verticalHeader()->hide();
view.show();
sizeHint = view.sizeHint();
view.hide();
QCOMPARE(view.sizeHint(), sizeHint);
}
void tst_QTableWidget::task231094()
{
QTableWidget tw(5, 3);

View File

@ -115,6 +115,8 @@ private slots:
void changeDataWithSorting();
void changeDataWithStableSorting_data();
void changeDataWithStableSorting();
void sizeHint_data();
void sizeHint();
void sortedIndexOfChild_data();
void sortedIndexOfChild();
@ -2621,6 +2623,50 @@ void tst_QTreeWidget::changeDataWithStableSorting()
QCOMPARE(layoutChangedSpy.count(), reorderingExpected ? 1 : 0);
}
void tst_QTreeWidget::sizeHint_data()
{
QTest::addColumn<int>("scrollBarPolicy");
QTest::addColumn<QSize>("viewSize");
QTest::newRow("ScrollBarAlwaysOn") << static_cast<int>(Qt::ScrollBarAlwaysOn) << QSize();
QTest::newRow("ScrollBarAlwaysOff") << static_cast<int>(Qt::ScrollBarAlwaysOff) << QSize();
// make sure the scrollbars are shown by resizing the view to 40x40
QTest::newRow("ScrollBarAsNeeded (40x40)") << static_cast<int>(Qt::ScrollBarAsNeeded) << QSize(40, 40);
QTest::newRow("ScrollBarAsNeeded (1000x1000)") << static_cast<int>(Qt::ScrollBarAsNeeded) << QSize(1000, 1000);
}
void tst_QTreeWidget::sizeHint()
{
QFETCH(int, scrollBarPolicy);
QFETCH(QSize, viewSize);
QTreeWidget view;
view.setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContents);
view.setVerticalScrollBarPolicy(static_cast<Qt::ScrollBarPolicy>(scrollBarPolicy));
view.setHorizontalScrollBarPolicy(static_cast<Qt::ScrollBarPolicy>(scrollBarPolicy));
view.setColumnCount(2);
for (int i = 0 ; i < view.columnCount(); ++i)
view.addTopLevelItem(new QTreeWidgetItem(QStringList{"foo","bar"}));
view.show();
QVERIFY(QTest::qWaitForWindowExposed(&view));
if (viewSize.isValid()) {
view.resize(viewSize);
view.setColumnWidth(0, 100);
QTRY_COMPARE(view.size(), viewSize);
}
auto sizeHint = view.sizeHint();
view.hide();
QCOMPARE(view.sizeHint(), sizeHint);
view.header()->hide();
view.show();
sizeHint = view.sizeHint();
view.hide();
QCOMPARE(view.sizeHint(), sizeHint);
}
void tst_QTreeWidget::itemOperatorLessThan()
{
QTreeWidget tw;