QHeaderView: respect min/maximumSectionSize property
QHeaderView::resizeSection() did not check if the given section size is inside the min/max property bounds. Also on calling setMin/MaximumSectionSize() the current section sizes were not checked if they are inside the new given bounds. This is a small behavior change when a user is setting the section size via resizeSection() without respecting the min/maxSectionSizes. Task-number: QTBUG-64173 Change-Id: Ia9c9eebf058d60c776ab5f8f8336642013ec553f Reviewed-by: Thorbjørn Lund Martsum <tmartsum@gmail.com>
This commit is contained in:
parent
1c0ac8c4b8
commit
20604ea554
@ -886,6 +886,10 @@ void QHeaderView::resizeSection(int logical, int size)
|
||||
if (logical < 0 || logical >= count() || size < 0 || size > maxSizeSection)
|
||||
return;
|
||||
|
||||
// make sure to not exceed bounds when setting size programmatically
|
||||
if (size > 0)
|
||||
size = qBound(minimumSectionSize(), size, maximumSectionSize());
|
||||
|
||||
if (isSectionHidden(logical)) {
|
||||
d->hiddenSectionSize.insert(logical, size);
|
||||
return;
|
||||
@ -1661,9 +1665,25 @@ void QHeaderView::setMinimumSectionSize(int size)
|
||||
Q_D(QHeaderView);
|
||||
if (size < -1 || size > maxSizeSection)
|
||||
return;
|
||||
// larger new min size - check current section sizes
|
||||
const bool needSizeCheck = size > d->minimumSectionSize;
|
||||
d->minimumSectionSize = size;
|
||||
if (d->minimumSectionSize > maximumSectionSize())
|
||||
d->maximumSectionSize = size;
|
||||
setMaximumSectionSize(size);
|
||||
|
||||
if (needSizeCheck) {
|
||||
if (d->hasAutoResizeSections()) {
|
||||
d->doDelayedResizeSections();
|
||||
} else {
|
||||
for (int visual = 0; visual < d->sectionCount(); ++visual) {
|
||||
if (d->isVisualIndexHidden(visual))
|
||||
continue;
|
||||
if (d->headerSectionSize(visual) < d->minimumSectionSize)
|
||||
resizeSection(logicalIndex(visual), size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -1700,7 +1720,22 @@ void QHeaderView::setMaximumSectionSize(int size)
|
||||
if (minimumSectionSize() > size)
|
||||
d->minimumSectionSize = size;
|
||||
|
||||
// smaller new max size - check current section sizes
|
||||
const bool needSizeCheck = size < d->maximumSectionSize;
|
||||
d->maximumSectionSize = size;
|
||||
|
||||
if (needSizeCheck) {
|
||||
if (d->hasAutoResizeSections()) {
|
||||
d->doDelayedResizeSections();
|
||||
} else {
|
||||
for (int visual = 0; visual < d->sectionCount(); ++visual) {
|
||||
if (d->isVisualIndexHidden(visual))
|
||||
continue;
|
||||
if (d->headerSectionSize(visual) > d->maximumSectionSize)
|
||||
resizeSection(logicalIndex(visual), size);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -3431,9 +3466,11 @@ void QHeaderViewPrivate::resizeSections(QHeaderView::ResizeMode globalMode, bool
|
||||
int logicalIndex = q->logicalIndex(i);
|
||||
sectionSize = qMax(viewSectionSizeHint(logicalIndex),
|
||||
q->sectionSizeHint(logicalIndex));
|
||||
if (sectionSize > q->maximumSectionSize())
|
||||
sectionSize = q->maximumSectionSize();
|
||||
}
|
||||
sectionSize = qBound(q->minimumSectionSize(),
|
||||
sectionSize,
|
||||
q->maximumSectionSize());
|
||||
|
||||
section_sizes.append(sectionSize);
|
||||
lengthToStretch -= sectionSize;
|
||||
}
|
||||
|
@ -239,13 +239,15 @@ private slots:
|
||||
void testStreamWithHide();
|
||||
void testStylePosition();
|
||||
void stretchAndRestoreLastSection();
|
||||
|
||||
void testMinMaxSectionSizeStretched();
|
||||
void testMinMaxSectionSizeNotStretched();
|
||||
void sizeHintCrash();
|
||||
|
||||
protected:
|
||||
void setupTestData(bool use_reset_model = false);
|
||||
void additionalInit();
|
||||
void calculateAndCheck(int cppline, const int precalced_comparedata[]);
|
||||
void testMinMaxSectionSize(bool stretchLastSection);
|
||||
|
||||
QWidget *topLevel;
|
||||
QHeaderView *view;
|
||||
@ -402,6 +404,7 @@ void tst_QHeaderView::init()
|
||||
QCOMPARE(view->length(), 0);
|
||||
QCOMPARE(view->sizeHint(), QSize(0,0));
|
||||
QCOMPARE(view->sectionSizeHint(0), -1);
|
||||
view->setMinimumSectionSize(0); // system default min size can be to large
|
||||
|
||||
/*
|
||||
model = new QStandardItemModel(1, 1);
|
||||
@ -1604,6 +1607,7 @@ static QByteArray savedState()
|
||||
QStandardItemModel m(4, 4);
|
||||
QHeaderView h1(Qt::Horizontal);
|
||||
h1.setModel(&m);
|
||||
h1.setMinimumSectionSize(0); // system default min size can be to large
|
||||
h1.swapSections(0, 2);
|
||||
h1.resizeSection(1, 10);
|
||||
h1.setSortIndicatorShown(true);
|
||||
@ -2194,6 +2198,7 @@ void tst_QHeaderView::task248050_hideRow()
|
||||
//this is the sequence of events that make the task fail
|
||||
protected_QHeaderView header(Qt::Vertical);
|
||||
QStandardItemModel model(0, 1);
|
||||
header.setMinimumSectionSize(0); // system default min size can be to large
|
||||
header.setStretchLastSection(false);
|
||||
header.setDefaultSectionSize(17);
|
||||
header.setModel(&model);
|
||||
@ -3182,5 +3187,76 @@ void tst_QHeaderView::stretchAndRestoreLastSection()
|
||||
QCOMPARE(header.sectionSize(9), someOtherSectionSize);
|
||||
}
|
||||
|
||||
void tst_QHeaderView::testMinMaxSectionSizeStretched()
|
||||
{
|
||||
testMinMaxSectionSize(true);
|
||||
}
|
||||
|
||||
void tst_QHeaderView::testMinMaxSectionSizeNotStretched()
|
||||
{
|
||||
testMinMaxSectionSize(false);
|
||||
}
|
||||
|
||||
static void waitFor(const std::function<bool()> &func)
|
||||
{
|
||||
for (int i = 0; i < 100; i++)
|
||||
{
|
||||
if (func())
|
||||
return;
|
||||
QTest::qWait(10);
|
||||
}
|
||||
}
|
||||
|
||||
void tst_QHeaderView::testMinMaxSectionSize(bool stretchLastSection)
|
||||
{
|
||||
QStandardItemModel m(5, 5);
|
||||
QTableView tv;
|
||||
tv.setModel(&m);
|
||||
tv.show();
|
||||
|
||||
const int sectionSizeMin = 20;
|
||||
const int sectionSizeMax = 40;
|
||||
const int defaultSectionSize = 30;
|
||||
|
||||
QVERIFY(QTest::qWaitForWindowExposed(&tv));
|
||||
|
||||
QHeaderView &header = *tv.horizontalHeader();
|
||||
header.setMinimumSectionSize(sectionSizeMin);
|
||||
header.setMaximumSectionSize(sectionSizeMax);
|
||||
header.setDefaultSectionSize(defaultSectionSize);
|
||||
header.setStretchLastSection(stretchLastSection);
|
||||
|
||||
// check defaults
|
||||
QCOMPARE(header.sectionSize(0), defaultSectionSize);
|
||||
QCOMPARE(header.sectionSize(3), defaultSectionSize);
|
||||
|
||||
// do not go above maxSectionSize
|
||||
header.resizeSection(0, sectionSizeMax + 1);
|
||||
QCOMPARE(header.sectionSize(0), sectionSizeMax);
|
||||
|
||||
// do not go below minSectionSize
|
||||
header.resizeSection(0, sectionSizeMin - 1);
|
||||
QCOMPARE(header.sectionSize(0), sectionSizeMin);
|
||||
|
||||
// change section size on max change
|
||||
header.setMinimumSectionSize(sectionSizeMin);
|
||||
header.setMaximumSectionSize(sectionSizeMax);
|
||||
header.resizeSection(0, sectionSizeMax);
|
||||
QCOMPARE(header.sectionSize(0), sectionSizeMax);
|
||||
header.setMaximumSectionSize(defaultSectionSize);
|
||||
waitFor([this, &header, defaultSectionSize]() { return header.sectionSize(0) == defaultSectionSize; });
|
||||
QCOMPARE(header.sectionSize(0), defaultSectionSize);
|
||||
|
||||
// change section size on min change
|
||||
header.setMinimumSectionSize(sectionSizeMin);
|
||||
header.setMaximumSectionSize(sectionSizeMax);
|
||||
header.resizeSection(0, sectionSizeMin);
|
||||
QCOMPARE(header.sectionSize(0), sectionSizeMin);
|
||||
header.setMinimumSectionSize(defaultSectionSize);
|
||||
waitFor([this, &header, defaultSectionSize]() { return header.sectionSize(0) == defaultSectionSize; });
|
||||
QCOMPARE(header.sectionSize(0), defaultSectionSize);
|
||||
}
|
||||
|
||||
|
||||
QTEST_MAIN(tst_QHeaderView)
|
||||
#include "tst_qheaderview.moc"
|
||||
|
@ -426,6 +426,9 @@ public:
|
||||
this, SLOT(slotCurrentChanged(QModelIndex,QModelIndex)));
|
||||
connect(selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
|
||||
this, SLOT(itemSelectionChanged(QItemSelection,QItemSelection)));
|
||||
// Allow small sections in this test, since this test was made before we correctly enforced minimum sizes.
|
||||
horizontalHeader()->setMinimumSectionSize(0);
|
||||
verticalHeader()->setMinimumSectionSize(0);
|
||||
}
|
||||
|
||||
// enum CursorAction and moveCursor() are protected in QTableView.
|
||||
@ -738,6 +741,8 @@ void tst_QTableView::headerSections()
|
||||
QHeaderView *vheader = view.verticalHeader();
|
||||
|
||||
view.setModel(&model);
|
||||
hheader->setMinimumSectionSize(columnWidth);
|
||||
vheader->setMinimumSectionSize(rowHeight);
|
||||
view.show();
|
||||
|
||||
hheader->doItemsLayout();
|
||||
@ -1147,6 +1152,9 @@ void tst_QTableView::moveCursor()
|
||||
QtTestTableView view;
|
||||
|
||||
view.setModel(&model);
|
||||
// we have to make sure that PgUp/PgDown can scroll to the bottom/top
|
||||
view.resize(view.horizontalHeader()->length() + 50,
|
||||
view.verticalHeader()->length() + 50);
|
||||
view.hideRow(hideRow);
|
||||
view.hideColumn(hideColumn);
|
||||
if (moveColumn.first != moveColumn.second)
|
||||
@ -2085,6 +2093,8 @@ void tst_QTableView::visualRect()
|
||||
|
||||
QTableView view;
|
||||
view.setModel(&model);
|
||||
view.horizontalHeader()->setMinimumSectionSize(0);
|
||||
view.verticalHeader()->setMinimumSectionSize(0);
|
||||
// Make sure that it has 1 pixel between each cell.
|
||||
view.setGridStyle(Qt::SolidLine);
|
||||
for (int i = 0; i < view.verticalHeader()->count(); ++i)
|
||||
@ -3533,6 +3543,9 @@ void tst_QTableView::editSpanFromDirections()
|
||||
|
||||
TableViewWithCursorExposed view;
|
||||
view.setModel(model.data());
|
||||
// we have to make sure that PgUp/PgDown can scroll to the bottom/top
|
||||
view.resize(view.horizontalHeader()->length() + 50,
|
||||
view.verticalHeader()->length() + 50);
|
||||
view.setSpan(row, column, rowSpan, columnSpan);
|
||||
view.show();
|
||||
QVERIFY(QTest::qWaitForWindowActive(&view));
|
||||
@ -3978,7 +3991,7 @@ void tst_QTableView::mouseWheel_data()
|
||||
<< 10 + qApp->wheelScrollLines() << 10 + qApp->wheelScrollLines();
|
||||
QTest::newRow("scroll down per pixel")
|
||||
<< int(QAbstractItemView::ScrollPerPixel) << -120
|
||||
<< 10 + qApp->wheelScrollLines() * 89 << 10 + qApp->wheelScrollLines() * 28;
|
||||
<< 10 + qApp->wheelScrollLines() * 91 << 10 + qApp->wheelScrollLines() * 46;
|
||||
}
|
||||
|
||||
void tst_QTableView::mouseWheel()
|
||||
@ -3992,16 +4005,17 @@ void tst_QTableView::mouseWheel()
|
||||
QWidget topLevel;
|
||||
QtTestTableView view(&topLevel);
|
||||
view.resize(500, 500);
|
||||
for (int r = 0; r < 100; ++r)
|
||||
view.setRowHeight(r, 50);
|
||||
for (int c = 0; c < 100; ++c)
|
||||
view.setColumnWidth(c, 100);
|
||||
topLevel.show();
|
||||
|
||||
QVERIFY(QTest::qWaitForWindowExposed(&topLevel));
|
||||
|
||||
view.setModel(&model);
|
||||
|
||||
for (int r = 0; r < 100; ++r)
|
||||
view.setRowHeight(r, 50);
|
||||
for (int c = 0; c < 100; ++c)
|
||||
view.setColumnWidth(c, 100);
|
||||
|
||||
view.setHorizontalScrollMode((QAbstractItemView::ScrollMode)scrollMode);
|
||||
view.setVerticalScrollMode((QAbstractItemView::ScrollMode)scrollMode);
|
||||
view.horizontalScrollBar()->setValue(10);
|
||||
|
Loading…
Reference in New Issue
Block a user