1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2016 The Qt Company Ltd. |
4 | ** Copyright (C) 2012 Thorbjørn Lund Martsum - tmartsum[at]gmail.com |
5 | ** Contact: https://www.qt.io/licensing/ |
6 | ** |
7 | ** This file is part of the test suite of the Qt Toolkit. |
8 | ** |
9 | ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ |
10 | ** Commercial License Usage |
11 | ** Licensees holding valid commercial Qt licenses may use this file in |
12 | ** accordance with the commercial license agreement provided with the |
13 | ** Software or, alternatively, in accordance with the terms contained in |
14 | ** a written agreement between you and The Qt Company. For licensing terms |
15 | ** and conditions see https://www.qt.io/terms-conditions. For further |
16 | ** information use the contact form at https://www.qt.io/contact-us. |
17 | ** |
18 | ** GNU General Public License Usage |
19 | ** Alternatively, this file may be used under the terms of the GNU |
20 | ** General Public License version 3 as published by the Free Software |
21 | ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT |
22 | ** included in the packaging of this file. Please review the following |
23 | ** information to ensure the GNU General Public License requirements will |
24 | ** be met: https://www.gnu.org/licenses/gpl-3.0.html. |
25 | ** |
26 | ** $QT_END_LICENSE$ |
27 | ** |
28 | ****************************************************************************/ |
29 | |
30 | #include <QDesktopWidget> |
31 | #include <QHeaderView> |
32 | #include <QProxyStyle> |
33 | #include <QSignalSpy> |
34 | #include <QSortFilterProxyModel> |
35 | #include <QStandardItemModel> |
36 | #include <QStringListModel> |
37 | #include <QTableView> |
38 | #include <QTest> |
39 | #include <QTreeWidget> |
40 | #include <QtWidgets/private/qheaderview_p.h> |
41 | |
42 | using BoolList = QVector<bool>; |
43 | using IntList = QVector<int>; |
44 | using ResizeVec = QVector<QHeaderView::ResizeMode>; |
45 | |
46 | class TestStyle : public QProxyStyle |
47 | { |
48 | Q_OBJECT |
49 | public: |
50 | void drawControl(ControlElement element, const QStyleOption *option, |
51 | QPainter *painter, const QWidget *widget) const override |
52 | { |
53 | if (element == CE_HeaderSection) { |
54 | if (const QStyleOptionHeader * = qstyleoption_cast<const QStyleOptionHeader *>(opt: option)) |
55 | lastPosition = header->position; |
56 | } |
57 | QProxyStyle::drawControl(element, option, painter, widget); |
58 | } |
59 | mutable QStyleOptionHeader::SectionPosition lastPosition = QStyleOptionHeader::Beginning; |
60 | }; |
61 | |
62 | class : public QHeaderView |
63 | { |
64 | Q_OBJECT |
65 | public: |
66 | (Qt::Orientation orientation) : QHeaderView(orientation) |
67 | { |
68 | resizeSections(); |
69 | } |
70 | |
71 | void testEvent(); |
72 | void testhorizontalOffset(); |
73 | void testverticalOffset(); |
74 | void testVisualRegionForSelection(); |
75 | friend class tst_QHeaderView; |
76 | }; |
77 | |
78 | class XResetModel : public QStandardItemModel |
79 | { |
80 | Q_OBJECT |
81 | public: |
82 | bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()) override |
83 | { |
84 | blockSignals(b: true); |
85 | bool r = QStandardItemModel::removeRows(row, count, parent); |
86 | blockSignals(b: false); |
87 | beginResetModel(); |
88 | endResetModel(); |
89 | return r; |
90 | } |
91 | bool insertRows(int row, int count, const QModelIndex &parent = QModelIndex()) override |
92 | { |
93 | blockSignals(b: true); |
94 | bool r = QStandardItemModel::insertRows(row, count, parent); |
95 | blockSignals(b: false); |
96 | beginResetModel(); |
97 | endResetModel(); |
98 | return r; |
99 | } |
100 | }; |
101 | |
102 | class : public QObject |
103 | { |
104 | Q_OBJECT |
105 | |
106 | public: |
107 | tst_QHeaderView(); |
108 | static void initMain(); |
109 | |
110 | private slots: |
111 | void initTestCase(); |
112 | void cleanupTestCase(); |
113 | void init(); |
114 | void cleanup(); |
115 | void getSetCheck(); |
116 | void visualIndex(); |
117 | |
118 | void visualIndexAt_data(); |
119 | void visualIndexAt(); |
120 | |
121 | void noModel(); |
122 | void emptyModel(); |
123 | void removeRows(); |
124 | void removeCols(); |
125 | |
126 | void clickable(); |
127 | void movable(); |
128 | void hidden(); |
129 | void stretch(); |
130 | |
131 | void sectionSize_data(); |
132 | void sectionSize(); |
133 | |
134 | void length(); |
135 | void offset(); |
136 | void sectionSizeHint(); |
137 | void logicalIndex(); |
138 | void logicalIndexAt(); |
139 | void swapSections(); |
140 | |
141 | void moveSection_data(); |
142 | void moveSection(); |
143 | |
144 | void resizeMode(); |
145 | |
146 | void resizeSection_data(); |
147 | void resizeSection(); |
148 | |
149 | void resizeAndMoveSection_data(); |
150 | void resizeAndMoveSection(); |
151 | void resizeHiddenSection_data(); |
152 | void resizeHiddenSection(); |
153 | void resizeAndInsertSection_data(); |
154 | void resizeAndInsertSection(); |
155 | void resizeWithResizeModes_data(); |
156 | void resizeWithResizeModes(); |
157 | void moveAndInsertSection_data(); |
158 | void moveAndInsertSection(); |
159 | void highlightSections(); |
160 | void showSortIndicator(); |
161 | void sortIndicatorTracking(); |
162 | void removeAndInsertRow(); |
163 | void unhideSection(); |
164 | void testEvent(); |
165 | void headerDataChanged(); |
166 | void currentChanged(); |
167 | void horizontalOffset(); |
168 | void verticalOffset(); |
169 | void stretchSectionCount(); |
170 | void hiddenSectionCount(); |
171 | void focusPolicy(); |
172 | void moveSectionAndReset(); |
173 | void moveSectionAndRemove(); |
174 | void saveRestore(); |
175 | void restoreQt4State(); |
176 | void restoreToMoreColumns(); |
177 | void restoreToMoreColumnsNoMovedColumns(); |
178 | void restoreBeforeSetModel(); |
179 | void defaultSectionSizeTest(); |
180 | void defaultSectionSizeTestStyles(); |
181 | |
182 | void defaultAlignment_data(); |
183 | void defaultAlignment(); |
184 | |
185 | void globalResizeMode_data(); |
186 | void globalResizeMode(); |
187 | |
188 | void sectionPressedSignal_data(); |
189 | void sectionPressedSignal(); |
190 | void () { sectionPressedSignal_data(); } |
191 | void sectionClickedSignal(); |
192 | |
193 | void defaultSectionSize_data(); |
194 | void defaultSectionSize(); |
195 | |
196 | void oneSectionSize(); |
197 | |
198 | void hideAndInsert_data(); |
199 | void hideAndInsert(); |
200 | |
201 | void removeSection(); |
202 | void preserveHiddenSectionWidth(); |
203 | void invisibleStretchLastSection(); |
204 | void noSectionsWithNegativeSize(); |
205 | |
206 | void emptySectionSpan(); |
207 | void task236450_hidden_data(); |
208 | void task236450_hidden(); |
209 | void task248050_hideRow(); |
210 | void QTBUG6058_reset(); |
211 | void QTBUG7833_sectionClicked(); |
212 | void checkLayoutChangeEmptyModel(); |
213 | void QTBUG8650_crashOnInsertSections(); |
214 | void QTBUG12268_hiddenMovedSectionSorting(); |
215 | void QTBUG14242_hideSectionAutoSize(); |
216 | void QTBUG50171_visualRegionForSwappedItems(); |
217 | void QTBUG53221_assertShiftHiddenRow(); |
218 | void QTBUG75615_sizeHintWithStylesheet(); |
219 | void ensureNoIndexAtLength(); |
220 | void offsetConsistent(); |
221 | void sectionsDontSortWhenNotClickingInThem(); |
222 | |
223 | void initialSortOrderRole(); |
224 | |
225 | void () { setupTestData(); } |
226 | void () { setupTestData(); } |
227 | void () { setupTestData(); } |
228 | void () { setupTestData(); } |
229 | void () { setupTestData(); } |
230 | void () { setupTestData(); } |
231 | void () { setupTestData(true); } |
232 | void () { setupTestData(true); } |
233 | void () { setupTestData(true); } |
234 | void () { setupTestData(); } |
235 | void logicalIndexAtTest(); |
236 | void visualIndexAtTest(); |
237 | void hideShowTest(); |
238 | void swapSectionsTest(); |
239 | void moveSectionTest(); |
240 | void defaultSizeTest(); |
241 | void removeTest(); |
242 | void insertTest(); |
243 | void mixedTests(); |
244 | void resizeToContentTest(); |
245 | void testStreamWithHide(); |
246 | void testStylePosition(); |
247 | void stretchAndRestoreLastSection(); |
248 | void testMinMaxSectionSize_data(); |
249 | void testMinMaxSectionSize(); |
250 | void sizeHintCrash(); |
251 | void testResetCachedSizeHint(); |
252 | void statusTips(); |
253 | void testRemovingColumnsViaLayoutChanged(); |
254 | void testModelMovingColumns(); |
255 | |
256 | protected: |
257 | void setupTestData(bool use_reset_model = false); |
258 | void additionalInit(); |
259 | void calculateAndCheck(int cppline, const int precalced_comparedata[]); |
260 | void (bool stretchLastSection); |
261 | |
262 | QWidget * = nullptr; |
263 | QHeaderView * = nullptr; |
264 | QStandardItemModel * = nullptr; |
265 | QTableView * = nullptr; |
266 | bool = false; |
267 | bool = false; |
268 | QElapsedTimer ; |
269 | }; |
270 | |
271 | void tst_QHeaderView::initMain() |
272 | { |
273 | #ifdef Q_OS_WIN |
274 | // Ensure minimum size constraints of framed windows on High DPI screens |
275 | QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); |
276 | #endif |
277 | } |
278 | |
279 | class QtTestModel: public QAbstractTableModel |
280 | { |
281 | Q_OBJECT |
282 | public: |
283 | QtTestModel(int rc, int cc, QObject *parent = nullptr) |
284 | : QAbstractTableModel(parent), rows(rc), cols(cc) {} |
285 | int rowCount(const QModelIndex &) const override { return rows; } |
286 | int columnCount(const QModelIndex &) const override { return cols; } |
287 | bool isEditable(const QModelIndex &) const { return true; } |
288 | QVariant (int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override |
289 | { |
290 | if (section < 0 || (role != Qt::DisplayRole && role != Qt::StatusTipRole)) |
291 | return QVariant(); |
292 | const int row = (orientation == Qt::Vertical ? section : 0); |
293 | const int col = (orientation == Qt::Horizontal ? section : 0); |
294 | if (orientation == Qt::Vertical && row >= rows) |
295 | return QVariant(); |
296 | if (orientation == Qt::Horizontal && col >= cols) |
297 | return QVariant(); |
298 | if (m_bMultiLine) |
299 | return QString("%1\n%1" ).arg(a: section); |
300 | return QLatin1Char('[') + QString::number(row) + QLatin1Char(',') |
301 | + QString::number(col) + QLatin1String(",0] -- Header" ); |
302 | } |
303 | QVariant data(const QModelIndex &idx, int role = Qt::DisplayRole) const override |
304 | { |
305 | if (role != Qt::DisplayRole) |
306 | return QVariant(); |
307 | if (idx.row() < 0 || idx.column() < 0 || idx.column() >= cols || idx.row() >= rows) { |
308 | wrongIndex = true; |
309 | qWarning(msg: "Invalid modelIndex [%d,%d,%p]" , idx.row(), idx.column(), idx.internalPointer()); |
310 | } |
311 | return QLatin1Char('[') + QString::number(idx.row()) + QLatin1Char(',') |
312 | + QString::number(idx.column()) + QLatin1String(",0]" ); |
313 | } |
314 | |
315 | void insertOneColumn(int col) |
316 | { |
317 | beginInsertColumns(parent: QModelIndex(), first: col, last: col); |
318 | --cols; |
319 | endInsertColumns(); |
320 | } |
321 | |
322 | void removeFirstRow() |
323 | { |
324 | beginRemoveRows(parent: QModelIndex(), first: 0, last: 0); |
325 | --rows; |
326 | endRemoveRows(); |
327 | } |
328 | |
329 | void removeLastRow() |
330 | { |
331 | beginRemoveRows(parent: QModelIndex(), first: rows - 1, last: rows - 1); |
332 | --rows; |
333 | endRemoveRows(); |
334 | } |
335 | |
336 | void removeAllRows() |
337 | { |
338 | beginRemoveRows(parent: QModelIndex(), first: 0, last: rows - 1); |
339 | rows = 0; |
340 | endRemoveRows(); |
341 | } |
342 | |
343 | void removeOneColumn(int col) |
344 | { |
345 | beginRemoveColumns(parent: QModelIndex(), first: col, last: col); |
346 | --cols; |
347 | endRemoveColumns(); |
348 | } |
349 | |
350 | void removeLastColumn() |
351 | { |
352 | beginRemoveColumns(parent: QModelIndex(), first: cols - 1, last: cols - 1); |
353 | --cols; |
354 | endRemoveColumns(); |
355 | } |
356 | |
357 | void removeAllColumns() |
358 | { |
359 | beginRemoveColumns(parent: QModelIndex(), first: 0, last: cols - 1); |
360 | cols = 0; |
361 | endRemoveColumns(); |
362 | } |
363 | |
364 | void moveColumn(int from, int to) |
365 | { |
366 | beginMoveColumns(sourceParent: QModelIndex(), sourceFirst: from, sourceLast: from, destinationParent: QModelIndex(), destinationColumn: to); |
367 | endMoveColumns(); |
368 | } |
369 | |
370 | void cleanup() |
371 | { |
372 | emit layoutAboutToBeChanged(); |
373 | cols = 3; |
374 | rows = 3; |
375 | emit layoutChanged(); |
376 | } |
377 | |
378 | void emitLayoutChanged() |
379 | { |
380 | emit layoutAboutToBeChanged(); |
381 | emit layoutChanged(); |
382 | } |
383 | |
384 | void emitLayoutChangedWithRemoveFirstRow() |
385 | { |
386 | emit layoutAboutToBeChanged(); |
387 | QModelIndexList milNew; |
388 | const auto milOld = persistentIndexList(); |
389 | milNew.reserve(alloc: milOld.size()); |
390 | for (int i = 0; i < milOld.size(); ++i) |
391 | milNew += QModelIndex(); |
392 | changePersistentIndexList(from: milOld, to: milNew); |
393 | emit layoutChanged(); |
394 | } |
395 | |
396 | void (bool bEnable) |
397 | { |
398 | beginResetModel(); |
399 | m_bMultiLine = bEnable; |
400 | endResetModel(); |
401 | } |
402 | |
403 | int rows = 0; |
404 | int cols = 0; |
405 | mutable bool wrongIndex = false; |
406 | bool m_bMultiLine = false; |
407 | }; |
408 | |
409 | // Testing get/set functions |
410 | void tst_QHeaderView::() |
411 | { |
412 | protected_QHeaderView obj1(Qt::Horizontal); |
413 | // bool QHeaderView::highlightSections() |
414 | // void QHeaderView::setHighlightSections(bool) |
415 | obj1.setHighlightSections(false); |
416 | QCOMPARE(false, obj1.highlightSections()); |
417 | obj1.setHighlightSections(true); |
418 | QCOMPARE(true, obj1.highlightSections()); |
419 | |
420 | // bool QHeaderView::stretchLastSection() |
421 | // void QHeaderView::setStretchLastSection(bool) |
422 | obj1.setStretchLastSection(false); |
423 | QCOMPARE(false, obj1.stretchLastSection()); |
424 | obj1.setStretchLastSection(true); |
425 | QCOMPARE(true, obj1.stretchLastSection()); |
426 | |
427 | // int QHeaderView::defaultSectionSize() |
428 | // void QHeaderView::setDefaultSectionSize(int) |
429 | obj1.setMinimumSectionSize(0); |
430 | obj1.setDefaultSectionSize(-1); |
431 | QVERIFY(obj1.defaultSectionSize() >= 0); |
432 | obj1.setDefaultSectionSize(0); |
433 | QCOMPARE(0, obj1.defaultSectionSize()); |
434 | obj1.setDefaultSectionSize(99999); |
435 | QCOMPARE(99999, obj1.defaultSectionSize()); |
436 | |
437 | // int QHeaderView::minimumSectionSize() |
438 | // void QHeaderView::setMinimumSectionSize(int) |
439 | obj1.setMinimumSectionSize(-1); |
440 | QVERIFY(obj1.minimumSectionSize() >= 0); |
441 | obj1.setMinimumSectionSize(0); |
442 | QCOMPARE(0, obj1.minimumSectionSize()); |
443 | obj1.setMinimumSectionSize(99999); |
444 | QCOMPARE(99999, obj1.minimumSectionSize()); |
445 | obj1.setMinimumSectionSize(-1); |
446 | QVERIFY(obj1.minimumSectionSize() < 100); |
447 | |
448 | // int QHeaderView::offset() |
449 | // void QHeaderView::setOffset(int) |
450 | obj1.setOffset(0); |
451 | QCOMPARE(0, obj1.offset()); |
452 | obj1.setOffset(std::numeric_limits<int>::min()); |
453 | QCOMPARE(std::numeric_limits<int>::min(), obj1.offset()); |
454 | obj1.setOffset(std::numeric_limits<int>::max()); |
455 | QCOMPARE(std::numeric_limits<int>::max(), obj1.offset()); |
456 | |
457 | } |
458 | |
459 | tst_QHeaderView::() |
460 | { |
461 | qRegisterMetaType<Qt::SortOrder>(typeName: "Qt::SortOrder" ); |
462 | } |
463 | |
464 | void tst_QHeaderView::() |
465 | { |
466 | m_tableview = new QTableView; |
467 | qDebug().noquote().nospace() |
468 | << "default min section size is " |
469 | << QString::number(m_tableview->verticalHeader()->minimumSectionSize()) |
470 | << QLatin1Char('/') |
471 | << m_tableview->horizontalHeader()->minimumSectionSize() |
472 | << " (v/h)" ; |
473 | } |
474 | |
475 | void tst_QHeaderView::() |
476 | { |
477 | delete m_tableview; |
478 | } |
479 | |
480 | void tst_QHeaderView::() |
481 | { |
482 | topLevel = new QWidget; |
483 | view = new QHeaderView(Qt::Vertical, topLevel); |
484 | // Some initial value tests before a model is added |
485 | QCOMPARE(view->length(), 0); |
486 | QCOMPARE(view->sizeHint(), QSize(0,0)); |
487 | QCOMPARE(view->sectionSizeHint(0), -1); |
488 | view->setMinimumSectionSize(0); // system default min size can be to large |
489 | |
490 | /* |
491 | model = new QStandardItemModel(1, 1); |
492 | view->setModel(model); |
493 | //qDebug() << view->count(); |
494 | view->sizeHint(); |
495 | */ |
496 | |
497 | int rows = 4; |
498 | int columns = 4; |
499 | model = new QStandardItemModel(rows, columns); |
500 | /* |
501 | for (int row = 0; row < rows; ++row) { |
502 | for (int column = 0; column < columns; ++column) { |
503 | QModelIndex index = model->index(row, column, QModelIndex()); |
504 | model->setData(index, QVariant((row+1) * (column+1))); |
505 | } |
506 | } |
507 | */ |
508 | |
509 | QSignalSpy spy(view, &QHeaderView::sectionCountChanged); |
510 | view->setModel(model); |
511 | QCOMPARE(spy.count(), 1); |
512 | view->resize(w: 200,h: 200); |
513 | } |
514 | |
515 | void tst_QHeaderView::() |
516 | { |
517 | m_tableview->setUpdatesEnabled(true); |
518 | if (view && view->parent() != m_tableview) |
519 | delete view; |
520 | view = nullptr; |
521 | delete model; |
522 | model = nullptr; |
523 | delete topLevel; |
524 | topLevel = nullptr; |
525 | } |
526 | |
527 | void tst_QHeaderView::() |
528 | { |
529 | QHeaderView emptyView(Qt::Vertical); |
530 | QCOMPARE(emptyView.count(), 0); |
531 | } |
532 | |
533 | void tst_QHeaderView::() |
534 | { |
535 | QtTestModel testmodel(0, 0); |
536 | view->setModel(&testmodel); |
537 | QVERIFY(!testmodel.wrongIndex); |
538 | QCOMPARE(view->count(), testmodel.rows); |
539 | view->setModel(model); |
540 | } |
541 | |
542 | void tst_QHeaderView::() |
543 | { |
544 | QtTestModel model(10, 10); |
545 | |
546 | QHeaderView vertical(Qt::Vertical); |
547 | QHeaderView horizontal(Qt::Horizontal); |
548 | |
549 | vertical.setModel(&model); |
550 | horizontal.setModel(&model); |
551 | vertical.show(); |
552 | horizontal.show(); |
553 | QCOMPARE(vertical.count(), model.rows); |
554 | QCOMPARE(horizontal.count(), model.cols); |
555 | |
556 | model.removeLastRow(); |
557 | QVERIFY(!model.wrongIndex); |
558 | QCOMPARE(vertical.count(), model.rows); |
559 | QCOMPARE(horizontal.count(), model.cols); |
560 | |
561 | model.removeAllRows(); |
562 | QVERIFY(!model.wrongIndex); |
563 | QCOMPARE(vertical.count(), model.rows); |
564 | QCOMPARE(horizontal.count(), model.cols); |
565 | } |
566 | |
567 | |
568 | void tst_QHeaderView::() |
569 | { |
570 | QtTestModel model(10, 10); |
571 | |
572 | QHeaderView vertical(Qt::Vertical); |
573 | QHeaderView horizontal(Qt::Horizontal); |
574 | vertical.setModel(&model); |
575 | horizontal.setModel(&model); |
576 | vertical.show(); |
577 | horizontal.show(); |
578 | QCOMPARE(vertical.count(), model.rows); |
579 | QCOMPARE(horizontal.count(), model.cols); |
580 | |
581 | model.removeLastColumn(); |
582 | QVERIFY(!model.wrongIndex); |
583 | QCOMPARE(vertical.count(), model.rows); |
584 | QCOMPARE(horizontal.count(), model.cols); |
585 | |
586 | model.removeAllColumns(); |
587 | QVERIFY(!model.wrongIndex); |
588 | QCOMPARE(vertical.count(), model.rows); |
589 | QCOMPARE(horizontal.count(), model.cols); |
590 | } |
591 | |
592 | void tst_QHeaderView::() |
593 | { |
594 | QCOMPARE(view->sectionsMovable(), false); |
595 | view->setSectionsMovable(false); |
596 | QCOMPARE(view->sectionsMovable(), false); |
597 | view->setSectionsMovable(true); |
598 | QCOMPARE(view->sectionsMovable(), true); |
599 | |
600 | QCOMPARE(view->isFirstSectionMovable(), true); |
601 | view->setFirstSectionMovable(false); |
602 | QCOMPARE(view->isFirstSectionMovable(), false); |
603 | view->setFirstSectionMovable(true); |
604 | QCOMPARE(view->isFirstSectionMovable(), true); |
605 | } |
606 | |
607 | void tst_QHeaderView::() |
608 | { |
609 | QCOMPARE(view->sectionsClickable(), false); |
610 | view->setSectionsClickable(false); |
611 | QCOMPARE(view->sectionsClickable(), false); |
612 | view->setSectionsClickable(true); |
613 | QCOMPARE(view->sectionsClickable(), true); |
614 | } |
615 | |
616 | void tst_QHeaderView::() |
617 | { |
618 | //hideSection() & showSection call setSectionHidden |
619 | // Test bad arguments |
620 | QCOMPARE(view->isSectionHidden(-1), false); |
621 | QCOMPARE(view->isSectionHidden(view->count()), false); |
622 | QCOMPARE(view->isSectionHidden(999999), false); |
623 | |
624 | view->setSectionHidden(logicalIndex: -1, hide: true); |
625 | view->setSectionHidden(logicalIndex: view->count(), hide: true); |
626 | view->setSectionHidden(logicalIndex: 999999, hide: true); |
627 | view->setSectionHidden(logicalIndex: -1, hide: false); |
628 | view->setSectionHidden(logicalIndex: view->count(), hide: false); |
629 | view->setSectionHidden(logicalIndex: 999999, hide: false); |
630 | |
631 | // Hidden sections shouldn't have visual properties (except position) |
632 | int pos = view->defaultSectionSize(); |
633 | view->setSectionHidden(logicalIndex: 1, hide: true); |
634 | QCOMPARE(view->sectionSize(1), 0); |
635 | QCOMPARE(view->sectionPosition(1), pos); |
636 | view->resizeSection(logicalIndex: 1, size: 100); |
637 | QCOMPARE(view->sectionViewportPosition(1), pos); |
638 | QCOMPARE(view->sectionSize(1), 0); |
639 | view->setSectionHidden(logicalIndex: 1, hide: false); |
640 | QCOMPARE(view->isSectionHidden(0), false); |
641 | QCOMPARE(view->sectionSize(0), view->defaultSectionSize()); |
642 | |
643 | // d->hiddenSectionSize could go out of sync when a new model |
644 | // was set which has fewer sections than before and some of them |
645 | // were hidden |
646 | QStandardItemModel model2(model->rowCount() - 1, model->columnCount()); |
647 | |
648 | for (int i = 0; i < model->rowCount(); ++i) |
649 | view->setSectionHidden(logicalIndex: i, hide: true); |
650 | view->setModel(&model2); |
651 | QVERIFY(view->sectionsHidden()); |
652 | for (int i = 0; i < model2.rowCount(); ++i) |
653 | QVERIFY(view->isSectionHidden(i)); |
654 | |
655 | view->setModel(model); |
656 | for (int i = 0; i < model2.rowCount(); ++i) |
657 | QVERIFY(view->isSectionHidden(i)); |
658 | QCOMPARE(view->isSectionHidden(model->rowCount() - 1), false); |
659 | for (int i = 0; i < model->rowCount(); ++i) |
660 | view->setSectionHidden(logicalIndex: i, hide: false); |
661 | } |
662 | |
663 | void tst_QHeaderView::() |
664 | { |
665 | // Show before resize and setStretchLastSection |
666 | QSize viewSize(500, 500); |
667 | view->resize(viewSize); |
668 | view->setStretchLastSection(true); |
669 | QCOMPARE(view->stretchLastSection(), true); |
670 | topLevel->show(); |
671 | QVERIFY(QTest::qWaitForWindowExposed(topLevel)); |
672 | QCOMPARE(view->width(), viewSize.width()); |
673 | QCOMPARE(view->visualIndexAt(view->viewport()->height() - 5), 3); |
674 | |
675 | view->setSectionHidden(logicalIndex: 3, hide: true); |
676 | QCOMPARE(view->visualIndexAt(view->viewport()->height() - 5), 2); |
677 | |
678 | view->setStretchLastSection(false); |
679 | QCOMPARE(view->stretchLastSection(), false); |
680 | } |
681 | |
682 | void tst_QHeaderView::() |
683 | { |
684 | //this ensures that if there is only one section, it gets a correct width (more than 0) |
685 | QHeaderView view (Qt::Vertical); |
686 | QtTestModel model(1, 1); |
687 | |
688 | view.setSectionResizeMode(QHeaderView::Interactive); |
689 | view.setModel(&model); |
690 | view.show(); |
691 | QVERIFY(QTest::qWaitForWindowExposed(&view)); |
692 | |
693 | QVERIFY(view.sectionSize(0) > 0); |
694 | } |
695 | |
696 | |
697 | void tst_QHeaderView::() |
698 | { |
699 | QTest::addColumn<IntList>(name: "boundsCheck" ); |
700 | QTest::addColumn<IntList>(name: "defaultSizes" ); |
701 | QTest::addColumn<int>(name: "initialDefaultSize" ); |
702 | QTest::addColumn<int>(name: "lastVisibleSectionSize" ); |
703 | QTest::addColumn<int>(name: "persistentSectionSize" ); |
704 | |
705 | QTest::newRow(dataTag: "data set one" ) |
706 | << (IntList{ -1, 0, 4, 9999 }) |
707 | << (IntList{ 10, 30, 30 }) |
708 | << 30 |
709 | << 300 |
710 | << 20; |
711 | } |
712 | |
713 | void tst_QHeaderView::() |
714 | { |
715 | #if defined Q_OS_QNX |
716 | QSKIP("The section size is dpi dependent on QNX" ); |
717 | #elif defined Q_OS_WINRT |
718 | QSKIP("Fails on WinRT - QTBUG-68297" ); |
719 | #endif |
720 | QFETCH(const IntList, boundsCheck); |
721 | QFETCH(const IntList, defaultSizes); |
722 | QFETCH(int, initialDefaultSize); |
723 | QFETCH(int, lastVisibleSectionSize); |
724 | QFETCH(int, persistentSectionSize); |
725 | |
726 | // bounds check |
727 | for (int val : boundsCheck) |
728 | view->sectionSize(logicalIndex: val); |
729 | |
730 | // default size |
731 | QCOMPARE(view->defaultSectionSize(), initialDefaultSize); |
732 | for (int def : defaultSizes) { |
733 | view->setDefaultSectionSize(def); |
734 | QCOMPARE(view->defaultSectionSize(), def); |
735 | } |
736 | |
737 | view->setDefaultSectionSize(initialDefaultSize); |
738 | for (int s = 0; s < view->count(); ++s) |
739 | QCOMPARE(view->sectionSize(s), initialDefaultSize); |
740 | view->doItemsLayout(); |
741 | |
742 | // stretch last section |
743 | view->setStretchLastSection(true); |
744 | int lastSection = view->count() - 1; |
745 | |
746 | //test that when hiding the last column, |
747 | //resizing the new last visible columns still works |
748 | view->hideSection(alogicalIndex: lastSection); |
749 | view->resizeSection(logicalIndex: lastSection - 1, size: lastVisibleSectionSize); |
750 | QCOMPARE(view->sectionSize(lastSection - 1), lastVisibleSectionSize); |
751 | view->showSection(alogicalIndex: lastSection); |
752 | |
753 | // turn off stretching |
754 | view->setStretchLastSection(false); |
755 | QCOMPARE(view->sectionSize(lastSection), initialDefaultSize); |
756 | |
757 | // test persistence |
758 | int sectionCount = view->count(); |
759 | for (int i = 0; i < sectionCount; ++i) |
760 | view->resizeSection(logicalIndex: i, size: persistentSectionSize); |
761 | QtTestModel model(sectionCount * 2, sectionCount * 2); |
762 | view->setModel(&model); |
763 | for (int j = 0; j < sectionCount; ++j) |
764 | QCOMPARE(view->sectionSize(j), persistentSectionSize); |
765 | for (int k = sectionCount; k < view->count(); ++k) |
766 | QCOMPARE(view->sectionSize(k), initialDefaultSize); |
767 | } |
768 | |
769 | void tst_QHeaderView::() |
770 | { |
771 | // Test bad arguments |
772 | QCOMPARE(view->visualIndex(999999), -1); |
773 | QCOMPARE(view->visualIndex(-1), -1); |
774 | QCOMPARE(view->visualIndex(1), 1); |
775 | view->setSectionHidden(logicalIndex: 1, hide: true); |
776 | QCOMPARE(view->visualIndex(1), 1); |
777 | QCOMPARE(view->visualIndex(2), 2); |
778 | |
779 | view->setSectionHidden(logicalIndex: 1, hide: false); |
780 | QCOMPARE(view->visualIndex(1), 1); |
781 | QCOMPARE(view->visualIndex(2), 2); |
782 | } |
783 | |
784 | void tst_QHeaderView::() |
785 | { |
786 | QTest::addColumn<IntList>(name: "hidden" ); |
787 | QTest::addColumn<IntList>(name: "from" ); |
788 | QTest::addColumn<IntList>(name: "to" ); |
789 | QTest::addColumn<IntList>(name: "coordinate" ); |
790 | QTest::addColumn<IntList>(name: "visual" ); |
791 | |
792 | const IntList coordinateList{ -1, 0, 31, 91, 99999 }; |
793 | |
794 | QTest::newRow(dataTag: "no hidden, no moved sections" ) |
795 | << IntList() |
796 | << IntList() |
797 | << IntList() |
798 | << coordinateList |
799 | << (IntList{ -1, 0, 1, 3, -1 }); |
800 | |
801 | QTest::newRow(dataTag: "no hidden, moved sections" ) |
802 | << IntList() |
803 | << (IntList{ 0 }) |
804 | << (IntList{ 1 }) |
805 | << coordinateList |
806 | << (IntList{ -1, 0, 1, 3, -1 }); |
807 | |
808 | QTest::newRow(dataTag: "hidden, no moved sections" ) |
809 | << (IntList{ 0 }) |
810 | << IntList() |
811 | << IntList() |
812 | << coordinateList |
813 | << (IntList{ -1, 1, 2, 3, -1 }); |
814 | } |
815 | |
816 | void tst_QHeaderView::() |
817 | { |
818 | #if defined Q_OS_QNX |
819 | QSKIP("The section size is dpi dependent on QNX" ); |
820 | #elif defined Q_OS_WINRT |
821 | QSKIP("Fails on WinRT - QTBUG-68297" ); |
822 | #endif |
823 | QFETCH(const IntList, hidden); |
824 | QFETCH(const IntList, from); |
825 | QFETCH(const IntList, to); |
826 | QFETCH(const IntList, coordinate); |
827 | QFETCH(const IntList, visual); |
828 | |
829 | view->setStretchLastSection(true); |
830 | topLevel->show(); |
831 | QVERIFY(QTest::qWaitForWindowExposed(topLevel)); |
832 | |
833 | for (int i : hidden) |
834 | view->setSectionHidden(logicalIndex: i, hide: true); |
835 | |
836 | for (int j = 0; j < from.count(); ++j) |
837 | view->moveSection(from: from.at(i: j), to: to.at(i: j)); |
838 | |
839 | for (int k = 0; k < coordinate.count(); ++k) |
840 | QTRY_COMPARE(view->visualIndexAt(coordinate.at(k)), visual.at(k)); |
841 | } |
842 | |
843 | void tst_QHeaderView::() |
844 | { |
845 | view->setStretchLastSection(true); |
846 | topLevel->show(); |
847 | QVERIFY(QTest::qWaitForWindowExposed(topLevel)); |
848 | |
849 | //minimumSectionSize should be the size of the last section of the widget is not tall enough |
850 | int length = view->minimumSectionSize(); |
851 | for (int i = 0; i < view->count() - 1; i++) |
852 | length += view->sectionSize(logicalIndex: i); |
853 | |
854 | length = qMax(a: length, b: view->viewport()->height()); |
855 | QCOMPARE(length, view->length()); |
856 | |
857 | view->setStretchLastSection(false); |
858 | topLevel->show(); |
859 | QVERIFY(QTest::qWaitForWindowExposed(topLevel)); |
860 | |
861 | QVERIFY(length != view->length()); |
862 | |
863 | // layoutChanged might mean rows have been removed |
864 | QtTestModel model(10, 10); |
865 | view->setModel(&model); |
866 | int oldLength = view->length(); |
867 | model.cleanup(); |
868 | QCOMPARE(model.rows, view->count()); |
869 | QVERIFY(oldLength != view->length()); |
870 | } |
871 | |
872 | void tst_QHeaderView::() |
873 | { |
874 | QCOMPARE(view->offset(), 0); |
875 | view->setOffset(10); |
876 | QCOMPARE(view->offset(), 10); |
877 | view->setOffset(0); |
878 | QCOMPARE(view->offset(), 0); |
879 | |
880 | // Test odd arguments |
881 | view->setOffset(-1); |
882 | } |
883 | |
884 | void tst_QHeaderView::() |
885 | { |
886 | QCOMPARE(view->sectionSizeHint(-1), -1); |
887 | QCOMPARE(view->sectionSizeHint(99999), -1); |
888 | QVERIFY(view->sectionSizeHint(0) >= 0); |
889 | } |
890 | |
891 | void tst_QHeaderView::() |
892 | { |
893 | // Test bad arguments |
894 | QCOMPARE(view->logicalIndex(-1), -1); |
895 | QCOMPARE(view->logicalIndex(99999), -1); |
896 | } |
897 | |
898 | void tst_QHeaderView::() |
899 | { |
900 | // Test bad arguments |
901 | view->logicalIndexAt(position: -1); |
902 | view->logicalIndexAt(position: 99999); |
903 | QCOMPARE(view->logicalIndexAt(0), 0); |
904 | QCOMPARE(view->logicalIndexAt(1), 0); |
905 | |
906 | topLevel->show(); |
907 | QVERIFY(QTest::qWaitForWindowExposed(topLevel)); |
908 | view->setStretchLastSection(true); |
909 | // First item |
910 | QCOMPARE(view->logicalIndexAt(0), 0); |
911 | QCOMPARE(view->logicalIndexAt(view->sectionSize(0)-1), 0); |
912 | QCOMPARE(view->logicalIndexAt(view->sectionSize(0)+1), 1); |
913 | // Last item |
914 | int last = view->length() - 1;//view->viewport()->height() - 10; |
915 | QCOMPARE(view->logicalIndexAt(last), 3); |
916 | // Not in widget |
917 | int outofbounds = view->length() + 1;//view->viewport()->height() + 1; |
918 | QCOMPARE(view->logicalIndexAt(outofbounds), -1); |
919 | |
920 | view->moveSection(from: 0,to: 1); |
921 | // First item |
922 | QCOMPARE(view->logicalIndexAt(0), 1); |
923 | QCOMPARE(view->logicalIndexAt(view->sectionSize(0)-1), 1); |
924 | QCOMPARE(view->logicalIndexAt(view->sectionSize(0)+1), 0); |
925 | // Last item |
926 | QCOMPARE(view->logicalIndexAt(last), 3); |
927 | view->moveSection(from: 1,to: 0); |
928 | |
929 | } |
930 | |
931 | void tst_QHeaderView::() |
932 | { |
933 | view->swapSections(first: -1, second: 1); |
934 | view->swapSections(first: 99999, second: 1); |
935 | view->swapSections(first: 1, second: -1); |
936 | view->swapSections(first: 1, second: 99999); |
937 | |
938 | IntList logical{ 0, 1, 2, 3 }; |
939 | |
940 | QSignalSpy spy1(view, &QHeaderView::sectionMoved); |
941 | |
942 | QCOMPARE(view->sectionsMoved(), false); |
943 | view->swapSections(first: 1, second: 1); |
944 | QCOMPARE(view->sectionsMoved(), false); |
945 | view->swapSections(first: 1, second: 2); |
946 | QCOMPARE(view->sectionsMoved(), true); |
947 | view->swapSections(first: 2, second: 1); |
948 | QCOMPARE(view->sectionsMoved(), true); |
949 | for (int i = 0; i < view->count(); ++i) |
950 | QCOMPARE(view->logicalIndex(i), logical.at(i)); |
951 | QCOMPARE(spy1.count(), 4); |
952 | |
953 | logical = { 3, 1, 2, 0 }; |
954 | view->swapSections(first: 3, second: 0); |
955 | QCOMPARE(view->sectionsMoved(), true); |
956 | for (int j = 0; j < view->count(); ++j) |
957 | QCOMPARE(view->logicalIndex(j), logical.at(j)); |
958 | QCOMPARE(spy1.count(), 6); |
959 | } |
960 | |
961 | void tst_QHeaderView::() |
962 | { |
963 | QTest::addColumn<IntList>(name: "hidden" ); |
964 | QTest::addColumn<IntList>(name: "from" ); |
965 | QTest::addColumn<IntList>(name: "to" ); |
966 | QTest::addColumn<BoolList>(name: "moved" ); |
967 | QTest::addColumn<IntList>(name: "logical" ); |
968 | QTest::addColumn<int>(name: "count" ); |
969 | |
970 | QTest::newRow(dataTag: "bad args, no hidden" ) |
971 | << IntList() |
972 | << (IntList{ -1, 1, 99999, 1 }) |
973 | << (IntList{ 1, -1, 1, 99999 }) |
974 | << (BoolList{ false, false, false, false }) |
975 | << (IntList{ 0, 1, 2, 3 }) |
976 | << 0; |
977 | |
978 | QTest::newRow(dataTag: "good args, no hidden" ) |
979 | << IntList() |
980 | << (IntList{ 1, 1, 2, 1 }) |
981 | << (IntList{ 1, 2, 1, 2 }) |
982 | << (BoolList{ false, true, true, true }) |
983 | << (IntList{ 0, 2, 1, 3 }) |
984 | << 3; |
985 | |
986 | QTest::newRow(dataTag: "hidden sections" ) |
987 | << (IntList{ 0, 3 }) |
988 | << (IntList{ 1, 1, 2, 1 }) |
989 | << (IntList{ 1, 2, 1, 2 }) |
990 | << (BoolList{ false, true, true, true }) |
991 | << (IntList{ 0, 2, 1, 3 }) |
992 | << 3; |
993 | } |
994 | |
995 | void tst_QHeaderView::() |
996 | { |
997 | QFETCH(const IntList, hidden); |
998 | QFETCH(const IntList, from); |
999 | QFETCH(const IntList, to); |
1000 | QFETCH(const BoolList, moved); |
1001 | QFETCH(const IntList, logical); |
1002 | QFETCH(int, count); |
1003 | |
1004 | QCOMPARE(from.count(), to.count()); |
1005 | QCOMPARE(from.count(), moved.count()); |
1006 | QCOMPARE(view->count(), logical.count()); |
1007 | |
1008 | QSignalSpy spy1(view, &QHeaderView::sectionMoved); |
1009 | QCOMPARE(view->sectionsMoved(), false); |
1010 | |
1011 | for (int h : hidden) |
1012 | view->setSectionHidden(logicalIndex: h, hide: true); |
1013 | |
1014 | for (int i = 0; i < from.count(); ++i) { |
1015 | view->moveSection(from: from.at(i), to: to.at(i)); |
1016 | QCOMPARE(view->sectionsMoved(), moved.at(i)); |
1017 | } |
1018 | |
1019 | for (int j = 0; j < view->count(); ++j) |
1020 | QCOMPARE(view->logicalIndex(j), logical.at(j)); |
1021 | |
1022 | QCOMPARE(spy1.count(), count); |
1023 | } |
1024 | |
1025 | void tst_QHeaderView::resizeAndMoveSection_data() |
1026 | { |
1027 | QTest::addColumn<IntList>(name: "logicalIndexes" ); |
1028 | QTest::addColumn<IntList>(name: "sizes" ); |
1029 | QTest::addColumn<int>(name: "logicalFrom" ); |
1030 | QTest::addColumn<int>(name: "logicalTo" ); |
1031 | |
1032 | QTest::newRow(dataTag: "resizeAndMove-1" ) |
1033 | << (IntList{ 0, 1 }) |
1034 | << (IntList{ 20, 40 }) |
1035 | << 0 << 1; |
1036 | |
1037 | QTest::newRow(dataTag: "resizeAndMove-2" ) |
1038 | << (IntList{ 0, 1, 2, 3 }) |
1039 | << (IntList{ 20, 60, 10, 80 }) |
1040 | << 0 << 2; |
1041 | |
1042 | QTest::newRow(dataTag: "resizeAndMove-3" ) |
1043 | << (IntList{ 0, 1, 2, 3 }) |
1044 | << (IntList{ 100, 60, 40, 10 }) |
1045 | << 0 << 3; |
1046 | |
1047 | QTest::newRow(dataTag: "resizeAndMove-4" ) |
1048 | << (IntList{ 0, 1, 2, 3 }) |
1049 | << (IntList{ 10, 40, 80, 30 }) |
1050 | << 1 << 2; |
1051 | |
1052 | QTest::newRow(dataTag: "resizeAndMove-5" ) |
1053 | << (IntList{ 2, 3 }) |
1054 | << (IntList{ 100, 200}) |
1055 | << 3 << 2; |
1056 | } |
1057 | |
1058 | void tst_QHeaderView::resizeAndMoveSection() |
1059 | { |
1060 | QFETCH(const IntList, logicalIndexes); |
1061 | QFETCH(const IntList, sizes); |
1062 | QFETCH(int, logicalFrom); |
1063 | QFETCH(int, logicalTo); |
1064 | |
1065 | // Save old visual indexes and sizes |
1066 | IntList oldVisualIndexes; |
1067 | IntList oldSizes; |
1068 | for (int logical : logicalIndexes) { |
1069 | oldVisualIndexes.append(t: view->visualIndex(logicalIndex: logical)); |
1070 | oldSizes.append(t: view->sectionSize(logicalIndex: logical)); |
1071 | } |
1072 | |
1073 | // Resize sections |
1074 | for (int i = 0; i < logicalIndexes.size(); ++i) { |
1075 | int logical = logicalIndexes.at(i); |
1076 | view->resizeSection(logicalIndex: logical, size: sizes.at(i)); |
1077 | } |
1078 | |
1079 | // Move sections |
1080 | int visualFrom = view->visualIndex(logicalIndex: logicalFrom); |
1081 | int visualTo = view->visualIndex(logicalIndex: logicalTo); |
1082 | view->moveSection(from: visualFrom, to: visualTo); |
1083 | QCOMPARE(view->visualIndex(logicalFrom), visualTo); |
1084 | |
1085 | // Check that sizes are still correct |
1086 | for (int i = 0; i < logicalIndexes.size(); ++i) { |
1087 | int logical = logicalIndexes.at(i); |
1088 | QCOMPARE(view->sectionSize(logical), sizes.at(i)); |
1089 | } |
1090 | |
1091 | // Move sections back |
1092 | view->moveSection(from: visualTo, to: visualFrom); |
1093 | |
1094 | // Check that sizes are still correct |
1095 | for (int i = 0; i < logicalIndexes.size(); ++i) { |
1096 | int logical = logicalIndexes.at(i); |
1097 | QCOMPARE(view->sectionSize(logical), sizes.at(i)); |
1098 | } |
1099 | |
1100 | // Put everything back as it was |
1101 | for (int i = 0; i < logicalIndexes.size(); ++i) { |
1102 | int logical = logicalIndexes.at(i); |
1103 | view->resizeSection(logicalIndex: logical, size: oldSizes.at(i)); |
1104 | QCOMPARE(view->visualIndex(logical), oldVisualIndexes.at(i)); |
1105 | } |
1106 | } |
1107 | |
1108 | void tst_QHeaderView::() |
1109 | { |
1110 | QTest::addColumn<int>(name: "section" ); |
1111 | QTest::addColumn<int>(name: "initialSize" ); |
1112 | QTest::addColumn<int>(name: "finalSize" ); |
1113 | |
1114 | QTest::newRow(dataTag: "section 0 resize 50 to 20" ) |
1115 | << 0 << 50 << 20; |
1116 | |
1117 | QTest::newRow(dataTag: "section 1 resize 50 to 20" ) |
1118 | << 1 << 50 << 20; |
1119 | |
1120 | QTest::newRow(dataTag: "section 2 resize 50 to 20" ) |
1121 | << 2 << 50 << 20; |
1122 | |
1123 | QTest::newRow(dataTag: "section 3 resize 50 to 20" ) |
1124 | << 3 << 50 << 20; |
1125 | } |
1126 | |
1127 | void tst_QHeaderView::() |
1128 | { |
1129 | QFETCH(int, section); |
1130 | QFETCH(int, initialSize); |
1131 | QFETCH(int, finalSize); |
1132 | |
1133 | view->resizeSection(logicalIndex: section, size: initialSize); |
1134 | view->setSectionHidden(logicalIndex: section, hide: true); |
1135 | QCOMPARE(view->sectionSize(section), 0); |
1136 | |
1137 | view->resizeSection(logicalIndex: section, size: finalSize); |
1138 | QCOMPARE(view->sectionSize(section), 0); |
1139 | |
1140 | view->setSectionHidden(logicalIndex: section, hide: false); |
1141 | QCOMPARE(view->sectionSize(section), finalSize); |
1142 | } |
1143 | |
1144 | void tst_QHeaderView::resizeAndInsertSection_data() |
1145 | { |
1146 | QTest::addColumn<int>(name: "section" ); |
1147 | QTest::addColumn<int>(name: "size" ); |
1148 | QTest::addColumn<int>(name: "insert" ); |
1149 | QTest::addColumn<int>(name: "compare" ); |
1150 | QTest::addColumn<int>(name: "expected" ); |
1151 | |
1152 | QTest::newRow(dataTag: "section 0 size 50 insert 0" ) |
1153 | << 0 << 50 << 0 << 1 << 50; |
1154 | |
1155 | QTest::newRow(dataTag: "section 1 size 50 insert 1" ) |
1156 | << 0 << 50 << 1 << 0 << 50; |
1157 | |
1158 | QTest::newRow(dataTag: "section 1 size 50 insert 0" ) |
1159 | << 1 << 50 << 0 << 2 << 50; |
1160 | |
1161 | } |
1162 | |
1163 | void tst_QHeaderView::resizeAndInsertSection() |
1164 | { |
1165 | QFETCH(int, section); |
1166 | QFETCH(int, size); |
1167 | QFETCH(int, insert); |
1168 | QFETCH(int, compare); |
1169 | QFETCH(int, expected); |
1170 | |
1171 | view->setStretchLastSection(false); |
1172 | |
1173 | view->resizeSection(logicalIndex: section, size); |
1174 | QCOMPARE(view->sectionSize(section), size); |
1175 | |
1176 | model->insertRow(arow: insert); |
1177 | |
1178 | QCOMPARE(view->sectionSize(compare), expected); |
1179 | } |
1180 | |
1181 | void tst_QHeaderView::() |
1182 | { |
1183 | QTest::addColumn<int>(name: "size" ); |
1184 | QTest::addColumn<IntList>(name: "sections" ); |
1185 | QTest::addColumn<ResizeVec>(name: "modes" ); |
1186 | QTest::addColumn<IntList>(name: "expected" ); |
1187 | |
1188 | QTest::newRow(dataTag: "stretch first section" ) |
1189 | << 600 |
1190 | << (IntList{ 100, 100, 100, 100 }) |
1191 | << (ResizeVec |
1192 | { QHeaderView::Stretch, |
1193 | QHeaderView::Interactive, |
1194 | QHeaderView::Interactive, |
1195 | QHeaderView::Interactive }) |
1196 | << (IntList{ 300, 100, 100, 100 }); |
1197 | } |
1198 | |
1199 | void tst_QHeaderView::() |
1200 | { |
1201 | QFETCH(int, size); |
1202 | QFETCH(const IntList, sections); |
1203 | QFETCH(const ResizeVec, modes); |
1204 | QFETCH(const IntList, expected); |
1205 | |
1206 | view->setStretchLastSection(false); |
1207 | for (int i = 0; i < sections.count(); ++i) { |
1208 | view->resizeSection(logicalIndex: i, size: sections.at(i)); |
1209 | view->setSectionResizeMode(logicalIndex: i, mode: modes.at(i)); |
1210 | } |
1211 | topLevel->show(); |
1212 | QVERIFY(QTest::qWaitForWindowExposed(topLevel)); |
1213 | view->resize(w: size, h: size); |
1214 | for (int j = 0; j < expected.count(); ++j) |
1215 | QCOMPARE(view->sectionSize(j), expected.at(j)); |
1216 | } |
1217 | |
1218 | void tst_QHeaderView::moveAndInsertSection_data() |
1219 | { |
1220 | QTest::addColumn<int>(name: "from" ); |
1221 | QTest::addColumn<int>(name: "to" ); |
1222 | QTest::addColumn<int>(name: "insert" ); |
1223 | QTest::addColumn<IntList>(name: "mapping" ); |
1224 | |
1225 | QTest::newRow(dataTag: "move from 1 to 3, insert 0" ) |
1226 | << 1 << 3 << 0 <<(IntList{ 0, 1, 3, 4, 2 }); |
1227 | |
1228 | } |
1229 | |
1230 | void tst_QHeaderView::moveAndInsertSection() |
1231 | { |
1232 | QFETCH(int, from); |
1233 | QFETCH(int, to); |
1234 | QFETCH(int, insert); |
1235 | QFETCH(IntList, mapping); |
1236 | |
1237 | view->setStretchLastSection(false); |
1238 | view->moveSection(from, to); |
1239 | model->insertRow(arow: insert); |
1240 | |
1241 | for (int i = 0; i < mapping.count(); ++i) |
1242 | QCOMPARE(view->logicalIndex(i), mapping.at(i)); |
1243 | } |
1244 | |
1245 | void tst_QHeaderView::() |
1246 | { |
1247 | // resizeMode must not be called with an invalid index |
1248 | int last = view->count() - 1; |
1249 | view->setSectionResizeMode(QHeaderView::Interactive); |
1250 | QCOMPARE(view->sectionResizeMode(last), QHeaderView::Interactive); |
1251 | QCOMPARE(view->sectionResizeMode(1), QHeaderView::Interactive); |
1252 | view->setSectionResizeMode(QHeaderView::Stretch); |
1253 | QCOMPARE(view->sectionResizeMode(last), QHeaderView::Stretch); |
1254 | QCOMPARE(view->sectionResizeMode(1), QHeaderView::Stretch); |
1255 | view->setSectionResizeMode(QHeaderView::Custom); |
1256 | QCOMPARE(view->sectionResizeMode(last), QHeaderView::Custom); |
1257 | QCOMPARE(view->sectionResizeMode(1), QHeaderView::Custom); |
1258 | |
1259 | // test when sections have been moved |
1260 | view->setStretchLastSection(false); |
1261 | for (int i = 0; i < (view->count() - 1); ++i) |
1262 | view->setSectionResizeMode(logicalIndex: i, mode: QHeaderView::Interactive); |
1263 | int logicalIndex = view->count() / 2; |
1264 | view->setSectionResizeMode(logicalIndex, mode: QHeaderView::Stretch); |
1265 | view->moveSection(from: view->visualIndex(logicalIndex), to: 0); |
1266 | for (int i = 0; i < (view->count() - 1); ++i) { |
1267 | if (i == logicalIndex) |
1268 | QCOMPARE(view->sectionResizeMode(i), QHeaderView::Stretch); |
1269 | else |
1270 | QCOMPARE(view->sectionResizeMode(i), QHeaderView::Interactive); |
1271 | } |
1272 | } |
1273 | |
1274 | void tst_QHeaderView::() |
1275 | { |
1276 | QTest::addColumn<int>(name: "initial" ); |
1277 | QTest::addColumn<IntList>(name: "logical" ); |
1278 | QTest::addColumn<IntList>(name: "size" ); |
1279 | QTest::addColumn<ResizeVec>(name: "mode" ); |
1280 | QTest::addColumn<int>(name: "resized" ); |
1281 | QTest::addColumn<IntList>(name: "expected" ); |
1282 | |
1283 | QTest::newRow(dataTag: "bad args" ) |
1284 | << 100 |
1285 | << (IntList{ -1, -1, 99999, 99999, 4 }) |
1286 | << (IntList{ -1, 0, 99999, -1, -1 }) |
1287 | << (ResizeVec{ |
1288 | QHeaderView::Interactive, |
1289 | QHeaderView::Interactive, |
1290 | QHeaderView::Interactive, |
1291 | QHeaderView::Interactive }) |
1292 | << 0 |
1293 | << (IntList{ 0, 0, 0, 0, 0 }); |
1294 | } |
1295 | |
1296 | void tst_QHeaderView::() |
1297 | { |
1298 | QFETCH(int, initial); |
1299 | QFETCH(const IntList, logical); |
1300 | QFETCH(const IntList, size); |
1301 | QFETCH(const ResizeVec, mode); |
1302 | QFETCH(int, resized); |
1303 | QFETCH(const IntList, expected); |
1304 | |
1305 | view->resize(w: 400, h: 400); |
1306 | |
1307 | topLevel->show(); |
1308 | QVERIFY(QTest::qWaitForWindowExposed(topLevel)); |
1309 | view->setSectionsMovable(true); |
1310 | view->setStretchLastSection(false); |
1311 | |
1312 | for (int i = 0; i < logical.count(); ++i) |
1313 | if (logical.at(i) > -1 && logical.at(i) < view->count()) // for now |
1314 | view->setSectionResizeMode(logicalIndex: logical.at(i), mode: mode.at(i)); |
1315 | |
1316 | for (int j = 0; j < logical.count(); ++j) |
1317 | view->resizeSection(logicalIndex: logical.at(i: j), size: initial); |
1318 | |
1319 | QSignalSpy spy(view, &QHeaderView::sectionResized); |
1320 | |
1321 | for (int k = 0; k < logical.count(); ++k) |
1322 | view->resizeSection(logicalIndex: logical.at(i: k), size: size.at(i: k)); |
1323 | |
1324 | QCOMPARE(spy.count(), resized); |
1325 | |
1326 | for (int l = 0; l < logical.count(); ++l) |
1327 | QCOMPARE(view->sectionSize(logical.at(l)), expected.at(l)); |
1328 | } |
1329 | |
1330 | void tst_QHeaderView::() |
1331 | { |
1332 | view->setHighlightSections(true); |
1333 | QCOMPARE(view->highlightSections(), true); |
1334 | view->setHighlightSections(false); |
1335 | QCOMPARE(view->highlightSections(), false); |
1336 | } |
1337 | |
1338 | void tst_QHeaderView::() |
1339 | { |
1340 | view->setSortIndicatorShown(true); |
1341 | QCOMPARE(view->isSortIndicatorShown(), true); |
1342 | QCOMPARE(view->sortIndicatorOrder(), Qt::DescendingOrder); |
1343 | view->setSortIndicator(logicalIndex: 1, order: Qt::AscendingOrder); |
1344 | QCOMPARE(view->sortIndicatorOrder(), Qt::AscendingOrder); |
1345 | view->setSortIndicator(logicalIndex: 1, order: Qt::DescendingOrder); |
1346 | QCOMPARE(view->sortIndicatorOrder(), Qt::DescendingOrder); |
1347 | view->setSortIndicatorShown(false); |
1348 | QCOMPARE(view->isSortIndicatorShown(), false); |
1349 | |
1350 | view->setSortIndicator(logicalIndex: 999999, order: Qt::DescendingOrder); |
1351 | // Don't segfault baby :) |
1352 | view->setSortIndicatorShown(true); |
1353 | |
1354 | view->setSortIndicator(logicalIndex: 0, order: Qt::DescendingOrder); |
1355 | // Don't assert baby :) |
1356 | } |
1357 | |
1358 | void tst_QHeaderView::() |
1359 | { |
1360 | QtTestModel model(10, 10); |
1361 | QHeaderView hv(Qt::Horizontal); |
1362 | |
1363 | hv.setModel(&model); |
1364 | hv.show(); |
1365 | hv.setSortIndicatorShown(true); |
1366 | hv.setSortIndicator(logicalIndex: 1, order: Qt::DescendingOrder); |
1367 | |
1368 | model.removeOneColumn(col: 8); |
1369 | QCOMPARE(hv.sortIndicatorSection(), 1); |
1370 | |
1371 | model.removeOneColumn(col: 2); |
1372 | QCOMPARE(hv.sortIndicatorSection(), 1); |
1373 | |
1374 | model.insertOneColumn(col: 2); |
1375 | QCOMPARE(hv.sortIndicatorSection(), 1); |
1376 | |
1377 | model.insertOneColumn(col: 1); |
1378 | QCOMPARE(hv.sortIndicatorSection(), 2); |
1379 | |
1380 | model.removeOneColumn(col: 0); |
1381 | QCOMPARE(hv.sortIndicatorSection(), 1); |
1382 | |
1383 | model.removeOneColumn(col: 1); |
1384 | QCOMPARE(hv.sortIndicatorSection(), -1); |
1385 | } |
1386 | |
1387 | void tst_QHeaderView::removeAndInsertRow() |
1388 | { |
1389 | // Check if logicalIndex returns the correct value after we have removed a row |
1390 | // we might as well te |
1391 | for (int i = 0; i < model->rowCount(); ++i) |
1392 | QCOMPARE(i, view->logicalIndex(i)); |
1393 | |
1394 | while (model->removeRow(arow: 0)) { |
1395 | for (int i = 0; i < model->rowCount(); ++i) |
1396 | QCOMPARE(i, view->logicalIndex(i)); |
1397 | } |
1398 | |
1399 | for (int pass = 0; pass < 5; pass++) { |
1400 | for (int i = 0; i < model->rowCount(); ++i) |
1401 | QCOMPARE(i, view->logicalIndex(i)); |
1402 | model->insertRow(arow: 0); |
1403 | } |
1404 | |
1405 | while (model->removeRows(row: 0, count: 2)) { |
1406 | for (int i = 0; i < model->rowCount(); ++i) |
1407 | QCOMPARE(i, view->logicalIndex(i)); |
1408 | } |
1409 | |
1410 | for (int pass = 0; pass < 3; pass++) { |
1411 | model->insertRows(row: 0, count: 2); |
1412 | for (int i = 0; i < model->rowCount(); ++i) { |
1413 | QCOMPARE(i, view->logicalIndex(i)); |
1414 | } |
1415 | } |
1416 | |
1417 | for (int pass = 0; pass < 3; pass++) { |
1418 | model->insertRows(row: 3, count: 2); |
1419 | for (int i = 0; i < model->rowCount(); ++i) |
1420 | QCOMPARE(i, view->logicalIndex(i)); |
1421 | } |
1422 | |
1423 | // Insert at end |
1424 | for (int pass = 0; pass < 3; pass++) { |
1425 | int rowCount = model->rowCount(); |
1426 | model->insertRows(row: rowCount, count: 1); |
1427 | for (int i = 0; i < rowCount; ++i) |
1428 | QCOMPARE(i, view->logicalIndex(i)); |
1429 | } |
1430 | |
1431 | } |
1432 | void tst_QHeaderView::() |
1433 | { |
1434 | // You should not necessarily expect the same size back again, so the best test we can do is to test if it is larger than 0 after a unhide. |
1435 | QCOMPARE(view->sectionsHidden(), false); |
1436 | view->setSectionHidden(logicalIndex: 0, hide: true); |
1437 | QCOMPARE(view->sectionsHidden(), true); |
1438 | QCOMPARE(view->sectionSize(0), 0); |
1439 | view->setSectionResizeMode(QHeaderView::Interactive); |
1440 | view->setSectionHidden(logicalIndex: 0, hide: false); |
1441 | QVERIFY(view->sectionSize(0) > 0); |
1442 | |
1443 | view->setSectionHidden(logicalIndex: 0, hide: true); |
1444 | QCOMPARE(view->sectionSize(0), 0); |
1445 | view->setSectionHidden(logicalIndex: 0, hide: true); |
1446 | QCOMPARE(view->sectionSize(0), 0); |
1447 | view->setSectionResizeMode(QHeaderView::Stretch); |
1448 | view->setSectionHidden(logicalIndex: 0, hide: false); |
1449 | QVERIFY(view->sectionSize(0) > 0); |
1450 | |
1451 | } |
1452 | |
1453 | void tst_QHeaderView::() |
1454 | { |
1455 | protected_QHeaderView x(Qt::Vertical); |
1456 | x.testEvent(); |
1457 | protected_QHeaderView y(Qt::Horizontal); |
1458 | y.testEvent(); |
1459 | } |
1460 | |
1461 | |
1462 | void protected_QHeaderView::() |
1463 | { |
1464 | // No crashy please |
1465 | QHoverEvent enterEvent(QEvent::HoverEnter, QPoint(), QPoint()); |
1466 | event(e: &enterEvent); |
1467 | QHoverEvent eventLeave(QEvent::HoverLeave, QPoint(), QPoint()); |
1468 | event(e: &eventLeave); |
1469 | QHoverEvent eventMove(QEvent::HoverMove, QPoint(), QPoint()); |
1470 | event(e: &eventMove); |
1471 | } |
1472 | |
1473 | void tst_QHeaderView::() |
1474 | { |
1475 | // This shouldn't assert because view is Vertical |
1476 | view->headerDataChanged(orientation: Qt::Horizontal, logicalFirst: -1, logicalLast: -1); |
1477 | #if 0 |
1478 | // This will assert |
1479 | view->headerDataChanged(Qt::Vertical, -1, -1); |
1480 | #endif |
1481 | |
1482 | // No crashing please |
1483 | view->headerDataChanged(orientation: Qt::Horizontal, logicalFirst: 0, logicalLast: 1); |
1484 | view->headerDataChanged(orientation: Qt::Vertical, logicalFirst: 0, logicalLast: 1); |
1485 | } |
1486 | |
1487 | void tst_QHeaderView::() |
1488 | { |
1489 | view->setCurrentIndex(QModelIndex()); |
1490 | } |
1491 | |
1492 | void tst_QHeaderView::() |
1493 | { |
1494 | protected_QHeaderView x(Qt::Vertical); |
1495 | x.testhorizontalOffset(); |
1496 | protected_QHeaderView y(Qt::Horizontal); |
1497 | y.testhorizontalOffset(); |
1498 | } |
1499 | |
1500 | void tst_QHeaderView::() |
1501 | { |
1502 | protected_QHeaderView x(Qt::Vertical); |
1503 | x.testverticalOffset(); |
1504 | protected_QHeaderView y(Qt::Horizontal); |
1505 | y.testverticalOffset(); |
1506 | } |
1507 | |
1508 | void protected_QHeaderView::() |
1509 | { |
1510 | if (orientation() == Qt::Horizontal) { |
1511 | QCOMPARE(horizontalOffset(), 0); |
1512 | setOffset(10); |
1513 | QCOMPARE(horizontalOffset(), 10); |
1514 | } |
1515 | else |
1516 | QCOMPARE(horizontalOffset(), 0); |
1517 | } |
1518 | |
1519 | void protected_QHeaderView::() |
1520 | { |
1521 | if (orientation() == Qt::Vertical) { |
1522 | QCOMPARE(verticalOffset(), 0); |
1523 | setOffset(10); |
1524 | QCOMPARE(verticalOffset(), 10); |
1525 | } |
1526 | else |
1527 | QCOMPARE(verticalOffset(), 0); |
1528 | } |
1529 | |
1530 | void tst_QHeaderView::() |
1531 | { |
1532 | view->setStretchLastSection(false); |
1533 | QCOMPARE(view->stretchSectionCount(), 0); |
1534 | view->setStretchLastSection(true); |
1535 | QCOMPARE(view->stretchSectionCount(), 0); |
1536 | |
1537 | view->setSectionResizeMode(logicalIndex: 0, mode: QHeaderView::Stretch); |
1538 | QCOMPARE(view->stretchSectionCount(), 1); |
1539 | } |
1540 | |
1541 | void tst_QHeaderView::() |
1542 | { |
1543 | model->clear(); |
1544 | model->insertRows(row: 0, count: 10); |
1545 | // Hide every other one |
1546 | for (int i = 0; i < 10; i++) |
1547 | view->setSectionHidden(logicalIndex: i, hide: (i & 1) == 0); |
1548 | |
1549 | QCOMPARE(view->hiddenSectionCount(), 5); |
1550 | |
1551 | view->setSectionResizeMode(QHeaderView::Stretch); |
1552 | QCOMPARE(view->hiddenSectionCount(), 5); |
1553 | |
1554 | // Remove some rows and make sure they are now still counted |
1555 | model->removeRow(arow: 9); |
1556 | model->removeRow(arow: 8); |
1557 | model->removeRow(arow: 7); |
1558 | model->removeRow(arow: 6); |
1559 | QCOMPARE(view->count(), 6); |
1560 | QCOMPARE(view->hiddenSectionCount(), 3); |
1561 | model->removeRows(row: 0, count: 5); |
1562 | QCOMPARE(view->count(), 1); |
1563 | QCOMPARE(view->hiddenSectionCount(), 0); |
1564 | QVERIFY(view->count() >= view->hiddenSectionCount()); |
1565 | } |
1566 | |
1567 | void tst_QHeaderView::() |
1568 | { |
1569 | if (QGuiApplication::platformName().startsWith(s: QLatin1String("wayland" ), cs: Qt::CaseInsensitive)) |
1570 | QSKIP("Wayland: This fails. Figure out why." ); |
1571 | |
1572 | QHeaderView view(Qt::Horizontal); |
1573 | QCOMPARE(view.focusPolicy(), Qt::NoFocus); |
1574 | |
1575 | QTreeWidget widget; |
1576 | QCOMPARE(widget.header()->focusPolicy(), Qt::NoFocus); |
1577 | QVERIFY(!widget.focusProxy()); |
1578 | QVERIFY(!widget.hasFocus()); |
1579 | QVERIFY(!widget.header()->focusProxy()); |
1580 | QVERIFY(!widget.header()->hasFocus()); |
1581 | |
1582 | widget.show(); |
1583 | widget.setFocus(Qt::OtherFocusReason); |
1584 | QApplication::setActiveWindow(&widget); |
1585 | widget.activateWindow(); |
1586 | QVERIFY(QTest::qWaitForWindowActive(&widget)); |
1587 | QVERIFY(widget.hasFocus()); |
1588 | QVERIFY(!widget.header()->hasFocus()); |
1589 | |
1590 | widget.setFocusPolicy(Qt::NoFocus); |
1591 | widget.clearFocus(); |
1592 | QTRY_VERIFY(!widget.hasFocus()); |
1593 | QVERIFY(!widget.header()->hasFocus()); |
1594 | |
1595 | QTest::keyPress(widget: &widget, key: Qt::Key_Tab); |
1596 | |
1597 | QCoreApplication::processEvents(); |
1598 | QCoreApplication::processEvents(); |
1599 | |
1600 | QVERIFY(!widget.hasFocus()); |
1601 | QVERIFY(!widget.header()->hasFocus()); |
1602 | } |
1603 | |
1604 | class SimpleModel : public QAbstractItemModel |
1605 | { |
1606 | Q_OBJECT |
1607 | public: |
1608 | using QAbstractItemModel::QAbstractItemModel; |
1609 | QModelIndex parent(const QModelIndex &/*child*/) const override |
1610 | { |
1611 | return QModelIndex(); |
1612 | } |
1613 | QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override |
1614 | { |
1615 | return hasIndex(row, column, parent) ? createIndex(arow: row, acolumn: column) : QModelIndex(); |
1616 | } |
1617 | int rowCount(const QModelIndex & /*parent*/ = QModelIndex()) const override |
1618 | { |
1619 | return 8; |
1620 | } |
1621 | int columnCount(const QModelIndex &/*parent*/ = QModelIndex()) const override |
1622 | { |
1623 | return m_col_count; |
1624 | } |
1625 | QVariant data(const QModelIndex &index, int role) const override |
1626 | { |
1627 | if (!index.isValid()) |
1628 | return QVariant(); |
1629 | if (role == Qt::DisplayRole) |
1630 | return QString::number(index.row()) + QLatin1Char(',') + QString::number(index.column()); |
1631 | return QVariant(); |
1632 | } |
1633 | void setColumnCount(int c) |
1634 | { |
1635 | m_col_count = c; |
1636 | } |
1637 | private: |
1638 | int m_col_count = 3; |
1639 | }; |
1640 | |
1641 | void tst_QHeaderView::moveSectionAndReset() |
1642 | { |
1643 | SimpleModel m; |
1644 | QHeaderView v(Qt::Horizontal); |
1645 | v.setModel(&m); |
1646 | int cc = 2; |
1647 | for (cc = 2; cc < 4; ++cc) { |
1648 | m.setColumnCount(cc); |
1649 | int movefrom = 0; |
1650 | int moveto; |
1651 | for (moveto = 1; moveto < cc; ++moveto) { |
1652 | v.moveSection(from: movefrom, to: moveto); |
1653 | m.setColumnCount(cc - 1); |
1654 | v.reset(); |
1655 | for (int i = 0; i < cc - 1; ++i) |
1656 | QCOMPARE(v.logicalIndex(v.visualIndex(i)), i); |
1657 | } |
1658 | } |
1659 | } |
1660 | |
1661 | void tst_QHeaderView::moveSectionAndRemove() |
1662 | { |
1663 | QStandardItemModel m; |
1664 | QHeaderView v(Qt::Horizontal); |
1665 | |
1666 | v.setModel(&m); |
1667 | v.model()->insertColumns(column: 0, count: 3); |
1668 | v.moveSection(from: 0, to: 1); |
1669 | |
1670 | QCOMPARE(v.count(), 3); |
1671 | v.model()->removeColumns(column: 0, count: v.model()->columnCount()); |
1672 | QCOMPARE(v.count(), 0); |
1673 | } |
1674 | |
1675 | static QByteArray savedState() |
1676 | { |
1677 | QStandardItemModel m(4, 4); |
1678 | QHeaderView h1(Qt::Horizontal); |
1679 | h1.setModel(&m); |
1680 | h1.setMinimumSectionSize(0); // system default min size can be to large |
1681 | h1.swapSections(first: 0, second: 2); |
1682 | h1.resizeSection(logicalIndex: 1, size: 10); |
1683 | h1.setSortIndicatorShown(true); |
1684 | h1.setSortIndicator(logicalIndex: 2, order: Qt::DescendingOrder); |
1685 | h1.setSectionHidden(logicalIndex: 3, hide: true); |
1686 | return h1.saveState(); |
1687 | } |
1688 | |
1689 | void tst_QHeaderView::() |
1690 | { |
1691 | QStandardItemModel m(4, 4); |
1692 | const QByteArray s1 = savedState(); |
1693 | |
1694 | QHeaderView h2(Qt::Vertical); |
1695 | QSignalSpy spy(&h2, &QHeaderView::sortIndicatorChanged); |
1696 | |
1697 | h2.setModel(&m); |
1698 | QVERIFY(h2.restoreState(s1)); |
1699 | |
1700 | QCOMPARE(spy.count(), 1); |
1701 | QCOMPARE(spy.at(0).at(0).toInt(), 2); |
1702 | |
1703 | QCOMPARE(h2.logicalIndex(0), 2); |
1704 | QCOMPARE(h2.logicalIndex(2), 0); |
1705 | QCOMPARE(h2.sectionSize(1), 10); |
1706 | QCOMPARE(h2.sortIndicatorSection(), 2); |
1707 | QCOMPARE(h2.sortIndicatorOrder(), Qt::DescendingOrder); |
1708 | QCOMPARE(h2.isSortIndicatorShown(), true); |
1709 | QVERIFY(!h2.isSectionHidden(2)); |
1710 | QVERIFY(h2.isSectionHidden(3)); |
1711 | QCOMPARE(h2.hiddenSectionCount(), 1); |
1712 | |
1713 | QByteArray s2 = h2.saveState(); |
1714 | QCOMPARE(s1, s2); |
1715 | |
1716 | QVERIFY(!h2.restoreState(QByteArrayLiteral("Garbage" ))); |
1717 | } |
1718 | |
1719 | void tst_QHeaderView::() |
1720 | { |
1721 | #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) |
1722 | // QTBUG-40462 |
1723 | // Setting from Qt4, where information about multiple sections were grouped together in one |
1724 | // sectionItem object |
1725 | QStandardItemModel m(4, 10); |
1726 | QHeaderView h2(Qt::Vertical); |
1727 | QByteArray settings_qt4 = |
1728 | QByteArray::fromHex(hexEncoded: "000000ff00000000000000010000000100000000010000000000000000000000000000" |
1729 | "0000000003e80000000a0101000100000000000000000000000064ffffffff00000081" |
1730 | "0000000000000001000003e80000000a00000000" ); |
1731 | QVERIFY(h2.restoreState(settings_qt4)); |
1732 | int sectionItemsLengthTotal = 0; |
1733 | for (int i = 0; i < h2.count(); ++i) |
1734 | sectionItemsLengthTotal += h2.sectionSize(logicalIndex: i); |
1735 | QCOMPARE(sectionItemsLengthTotal, h2.length()); |
1736 | |
1737 | // Buggy setting where sum(sectionItems) != length. Check false is returned and this corrupted |
1738 | // state isn't restored |
1739 | QByteArray settings_buggy_length = |
1740 | QByteArray::fromHex(hexEncoded: "000000ff000000000000000100000000000000050100000000000000000000000a4000" |
1741 | "000000010000000600000258000000fb0000000a010100010000000000000000000000" |
1742 | "0064ffffffff00000081000000000000000a000000d30000000100000000000000c800" |
1743 | "000001000000000000008000000001000000000000005c00000001000000000000003c" |
1744 | "0000000100000000000002580000000100000000000000000000000100000000000002" |
1745 | "580000000100000000000002580000000100000000000003c000000001000000000000" |
1746 | "03e8" ); |
1747 | int old_length = h2.length(); |
1748 | QByteArray old_state = h2.saveState(); |
1749 | // Check setting is correctly recognized as corrupted |
1750 | QVERIFY(!h2.restoreState(settings_buggy_length)); |
1751 | // Check nothing has been actually restored |
1752 | QCOMPARE(h2.length(), old_length); |
1753 | QCOMPARE(h2.saveState(), old_state); |
1754 | #else |
1755 | QSKIP("Qt4 compatibility no longer needed in Qt6" ) |
1756 | #endif |
1757 | } |
1758 | |
1759 | void tst_QHeaderView::restoreToMoreColumns() |
1760 | { |
1761 | // Restore state onto a model with more columns |
1762 | const QByteArray s1 = savedState(); |
1763 | QHeaderView h4(Qt::Horizontal); |
1764 | QStandardItemModel fiveColumnsModel(1, 5); |
1765 | h4.setModel(&fiveColumnsModel); |
1766 | QCOMPARE(fiveColumnsModel.columnCount(), 5); |
1767 | QCOMPARE(h4.count(), 5); |
1768 | QVERIFY(h4.restoreState(s1)); |
1769 | QCOMPARE(fiveColumnsModel.columnCount(), 5); |
1770 | QCOMPARE(h4.count(), 5); |
1771 | QCOMPARE(h4.sectionSize(1), 10); |
1772 | for (int i = 0; i < h4.count(); ++i) |
1773 | QVERIFY(h4.sectionSize(i) > 0 || h4.isSectionHidden(i)); |
1774 | QVERIFY(!h4.isSectionHidden(2)); |
1775 | QVERIFY(h4.isSectionHidden(3)); |
1776 | QCOMPARE(h4.hiddenSectionCount(), 1); |
1777 | QCOMPARE(h4.sortIndicatorSection(), 2); |
1778 | QCOMPARE(h4.sortIndicatorOrder(), Qt::DescendingOrder); |
1779 | QCOMPARE(h4.logicalIndex(0), 2); |
1780 | QCOMPARE(h4.logicalIndex(1), 1); |
1781 | QCOMPARE(h4.logicalIndex(2), 0); |
1782 | QCOMPARE(h4.visualIndex(0), 2); |
1783 | QCOMPARE(h4.visualIndex(1), 1); |
1784 | QCOMPARE(h4.visualIndex(2), 0); |
1785 | |
1786 | // Repainting shouldn't crash |
1787 | h4.show(); |
1788 | QVERIFY(QTest::qWaitForWindowExposed(&h4)); |
1789 | } |
1790 | |
1791 | void tst_QHeaderView::restoreToMoreColumnsNoMovedColumns() |
1792 | { |
1793 | // Given a model with 2 columns, for saving state |
1794 | QHeaderView h1(Qt::Horizontal); |
1795 | QStandardItemModel model1(1, 2); |
1796 | h1.setModel(&model1); |
1797 | QCOMPARE(h1.visualIndex(0), 0); |
1798 | QCOMPARE(h1.visualIndex(1), 1); |
1799 | QCOMPARE(h1.logicalIndex(0), 0); |
1800 | QCOMPARE(h1.logicalIndex(1), 1); |
1801 | const QByteArray savedState = h1.saveState(); |
1802 | |
1803 | // And a model with 3 columns, to apply that state upon |
1804 | QHeaderView h2(Qt::Horizontal); |
1805 | QStandardItemModel model2(1, 3); |
1806 | h2.setModel(&model2); |
1807 | QCOMPARE(h2.visualIndex(0), 0); |
1808 | QCOMPARE(h2.visualIndex(1), 1); |
1809 | QCOMPARE(h2.visualIndex(2), 2); |
1810 | QCOMPARE(h2.logicalIndex(0), 0); |
1811 | QCOMPARE(h2.logicalIndex(1), 1); |
1812 | QCOMPARE(h2.logicalIndex(2), 2); |
1813 | |
1814 | // When calling restoreState() |
1815 | QVERIFY(h2.restoreState(savedState)); |
1816 | |
1817 | // Then the index mapping should still be as default |
1818 | QCOMPARE(h2.visualIndex(0), 0); |
1819 | QCOMPARE(h2.visualIndex(1), 1); |
1820 | QCOMPARE(h2.visualIndex(2), 2); |
1821 | QCOMPARE(h2.logicalIndex(0), 0); |
1822 | QCOMPARE(h2.logicalIndex(1), 1); |
1823 | QCOMPARE(h2.logicalIndex(2), 2); |
1824 | |
1825 | // And repainting shouldn't crash |
1826 | h2.show(); |
1827 | QVERIFY(QTest::qWaitForWindowExposed(&h2)); |
1828 | } |
1829 | |
1830 | void tst_QHeaderView::() |
1831 | { |
1832 | QHeaderView h2(Qt::Horizontal); |
1833 | const QByteArray s1 = savedState(); |
1834 | // First restore |
1835 | QVERIFY(h2.restoreState(s1)); |
1836 | // Then setModel |
1837 | QStandardItemModel model(4, 4); |
1838 | h2.setModel(&model); |
1839 | |
1840 | // Check the result |
1841 | QCOMPARE(h2.logicalIndex(0), 2); |
1842 | QCOMPARE(h2.logicalIndex(2), 0); |
1843 | QCOMPARE(h2.sectionSize(1), 10); |
1844 | QCOMPARE(h2.sortIndicatorSection(), 2); |
1845 | QCOMPARE(h2.sortIndicatorOrder(), Qt::DescendingOrder); |
1846 | QCOMPARE(h2.isSortIndicatorShown(), true); |
1847 | QVERIFY(!h2.isSectionHidden(2)); |
1848 | QVERIFY(h2.isSectionHidden(3)); |
1849 | QCOMPARE(h2.hiddenSectionCount(), 1); |
1850 | } |
1851 | |
1852 | void tst_QHeaderView::() |
1853 | { |
1854 | #if defined Q_OS_WINRT |
1855 | QSKIP("Fails on WinRT - QTBUG-73309" ); |
1856 | #endif |
1857 | |
1858 | // Setup |
1859 | QTableView qtv; |
1860 | QHeaderView *hv = qtv.verticalHeader(); |
1861 | hv->setMinimumSectionSize(10); |
1862 | hv->setDefaultSectionSize(99); // Set it to a value different from defaultSize. |
1863 | QStandardItemModel amodel(4, 4); |
1864 | qtv.setModel(&amodel); |
1865 | QCOMPARE(hv->sectionSize(0), 99); |
1866 | QCOMPARE(hv->visualIndexAt(50), 0); // <= also make sure that indexes are calculated |
1867 | hv->setDefaultSectionSize(40); // Set it to a value different from defaultSize. |
1868 | QCOMPARE(hv->visualIndexAt(50), 1); |
1869 | |
1870 | const int defaultSize = 26; |
1871 | hv->setDefaultSectionSize(defaultSize + 1); // Set it to a value different from defaultSize. |
1872 | |
1873 | // no hidden Sections |
1874 | hv->resizeSection(logicalIndex: 1, size: 0); |
1875 | hv->setDefaultSectionSize(defaultSize); |
1876 | QCOMPARE(hv->sectionSize(1), defaultSize); |
1877 | |
1878 | // with hidden sections |
1879 | hv->resizeSection(logicalIndex: 1, size: 0); |
1880 | hv->hideSection(alogicalIndex: 2); |
1881 | hv->setDefaultSectionSize(defaultSize); |
1882 | |
1883 | QVERIFY(hv->sectionSize(0) == defaultSize); // trivial case. |
1884 | QVERIFY(hv->sectionSize(1) == defaultSize); // just sized 0. Now it should be 10 |
1885 | QVERIFY(hv->sectionSize(2) == 0); // section is hidden. It should not be resized. |
1886 | } |
1887 | |
1888 | class : public QProxyStyle |
1889 | { |
1890 | Q_OBJECT |
1891 | public: |
1892 | using QProxyStyle::QProxyStyle; |
1893 | int (PixelMetric metric, const QStyleOption *option = nullptr, |
1894 | const QWidget *widget = nullptr) const override |
1895 | { |
1896 | if (metric == QStyle::PM_HeaderDefaultSectionSizeHorizontal) |
1897 | return horizontalSectionSize; |
1898 | else |
1899 | return QProxyStyle::pixelMetric(metric, option, widget); |
1900 | } |
1901 | int = 100; |
1902 | }; |
1903 | |
1904 | void tst_QHeaderView::() |
1905 | { |
1906 | TestHeaderViewStyle style1; |
1907 | TestHeaderViewStyle style2; |
1908 | style1.horizontalSectionSize = 100; |
1909 | style2.horizontalSectionSize = 200; |
1910 | |
1911 | QHeaderView hv(Qt::Horizontal); |
1912 | hv.setStyle(&style1); |
1913 | QCOMPARE(hv.defaultSectionSize(), style1.horizontalSectionSize); |
1914 | hv.setStyle(&style2); |
1915 | QCOMPARE(hv.defaultSectionSize(), style2.horizontalSectionSize); |
1916 | hv.setDefaultSectionSize(70); |
1917 | QCOMPARE(hv.defaultSectionSize(), 70); |
1918 | hv.setStyle(&style1); |
1919 | QCOMPARE(hv.defaultSectionSize(), 70); |
1920 | hv.resetDefaultSectionSize(); |
1921 | QCOMPARE(hv.defaultSectionSize(), style1.horizontalSectionSize); |
1922 | hv.setStyle(&style2); |
1923 | QCOMPARE(hv.defaultSectionSize(), style2.horizontalSectionSize); |
1924 | } |
1925 | |
1926 | void tst_QHeaderView::() |
1927 | { |
1928 | QTest::addColumn<Qt::Orientation>(name: "direction" ); |
1929 | QTest::addColumn<Qt::Alignment>(name: "initial" ); |
1930 | QTest::addColumn<Qt::Alignment>(name: "alignment" ); |
1931 | |
1932 | QTest::newRow(dataTag: "horizontal right aligned" ) |
1933 | << Qt::Horizontal |
1934 | << Qt::Alignment(Qt::AlignCenter) |
1935 | << Qt::Alignment(Qt::AlignRight); |
1936 | |
1937 | QTest::newRow(dataTag: "horizontal left aligned" ) |
1938 | << Qt::Horizontal |
1939 | << Qt::Alignment(Qt::AlignCenter) |
1940 | << Qt::Alignment(Qt::AlignLeft); |
1941 | |
1942 | QTest::newRow(dataTag: "vertical right aligned" ) |
1943 | << Qt::Vertical |
1944 | << Qt::Alignment(Qt::AlignLeft|Qt::AlignVCenter) |
1945 | << Qt::Alignment(Qt::AlignRight); |
1946 | |
1947 | QTest::newRow(dataTag: "vertical left aligned" ) |
1948 | << Qt::Vertical |
1949 | << Qt::Alignment(Qt::AlignLeft|Qt::AlignVCenter) |
1950 | << Qt::Alignment(Qt::AlignLeft); |
1951 | } |
1952 | |
1953 | void tst_QHeaderView::() |
1954 | { |
1955 | QFETCH(Qt::Orientation, direction); |
1956 | QFETCH(Qt::Alignment, initial); |
1957 | QFETCH(Qt::Alignment, alignment); |
1958 | |
1959 | SimpleModel m; |
1960 | |
1961 | QHeaderView (direction); |
1962 | header.setModel(&m); |
1963 | |
1964 | QCOMPARE(header.defaultAlignment(), initial); |
1965 | header.setDefaultAlignment(alignment); |
1966 | QCOMPARE(header.defaultAlignment(), alignment); |
1967 | } |
1968 | |
1969 | void tst_QHeaderView::() |
1970 | { |
1971 | QTest::addColumn<Qt::Orientation>(name: "direction" ); |
1972 | QTest::addColumn<QHeaderView::ResizeMode>(name: "mode" ); |
1973 | QTest::addColumn<int>(name: "insert" ); |
1974 | |
1975 | QTest::newRow(dataTag: "horizontal ResizeToContents 0" ) |
1976 | << Qt::Horizontal |
1977 | << QHeaderView::ResizeToContents |
1978 | << 0; |
1979 | } |
1980 | |
1981 | void tst_QHeaderView::() |
1982 | { |
1983 | QFETCH(Qt::Orientation, direction); |
1984 | QFETCH(QHeaderView::ResizeMode, mode); |
1985 | QFETCH(int, insert); |
1986 | |
1987 | QStandardItemModel m(4, 4); |
1988 | QHeaderView h(direction); |
1989 | h.setModel(&m); |
1990 | |
1991 | h.setSectionResizeMode(mode); |
1992 | m.insertRow(arow: insert); |
1993 | for (int i = 0; i < h.count(); ++i) |
1994 | QCOMPARE(h.sectionResizeMode(i), mode); |
1995 | } |
1996 | |
1997 | |
1998 | void tst_QHeaderView::() |
1999 | { |
2000 | QTest::addColumn<Qt::Orientation>(name: "direction" ); |
2001 | QTest::addColumn<bool>(name: "clickable" ); |
2002 | QTest::addColumn<int>(name: "count" ); |
2003 | |
2004 | QTest::newRow(dataTag: "horizontal unclickable 0" ) |
2005 | << Qt::Horizontal |
2006 | << false |
2007 | << 0; |
2008 | |
2009 | QTest::newRow(dataTag: "horizontal clickable 1" ) |
2010 | << Qt::Horizontal |
2011 | << true |
2012 | << 1; |
2013 | } |
2014 | |
2015 | void tst_QHeaderView::() |
2016 | { |
2017 | QFETCH(Qt::Orientation, direction); |
2018 | QFETCH(bool, clickable); |
2019 | QFETCH(int, count); |
2020 | |
2021 | QStandardItemModel m(4, 4); |
2022 | QHeaderView h(direction); |
2023 | |
2024 | h.setModel(&m); |
2025 | h.show(); |
2026 | h.setSectionsClickable(clickable); |
2027 | |
2028 | QSignalSpy spy(&h, &QHeaderView::sectionPressed); |
2029 | |
2030 | QCOMPARE(spy.count(), 0); |
2031 | QTest::mousePress(widget: h.viewport(), button: Qt::LeftButton, stateKey: Qt::NoModifier, pos: QPoint(5, 5)); |
2032 | QCOMPARE(spy.count(), count); |
2033 | } |
2034 | |
2035 | void tst_QHeaderView::() |
2036 | { |
2037 | QFETCH(Qt::Orientation, direction); |
2038 | QFETCH(bool, clickable); |
2039 | QFETCH(int, count); |
2040 | |
2041 | QStandardItemModel m(4, 4); |
2042 | QHeaderView h(direction); |
2043 | |
2044 | h.setModel(&m); |
2045 | h.show(); |
2046 | h.setSectionsClickable(clickable); |
2047 | h.setSortIndicatorShown(true); |
2048 | |
2049 | QSignalSpy spy(&h, &QHeaderView::sectionClicked); |
2050 | QSignalSpy spy2(&h, &QHeaderView::sortIndicatorChanged); |
2051 | |
2052 | QCOMPARE(spy.count(), 0); |
2053 | QCOMPARE(spy2.count(), 0); |
2054 | QTest::mouseClick(widget: h.viewport(), button: Qt::LeftButton, stateKey: Qt::NoModifier, pos: QPoint(5, 5)); |
2055 | QCOMPARE(spy.count(), count); |
2056 | QCOMPARE(spy2.count(), count); |
2057 | |
2058 | //now let's try with the sort indicator hidden (the result should be the same |
2059 | spy.clear(); |
2060 | spy2.clear(); |
2061 | h.setSortIndicatorShown(false); |
2062 | QTest::mouseClick(widget: h.viewport(), button: Qt::LeftButton, stateKey: Qt::NoModifier, pos: QPoint(5, 5)); |
2063 | QCOMPARE(spy.count(), count); |
2064 | QCOMPARE(spy2.count(), count); |
2065 | } |
2066 | |
2067 | void tst_QHeaderView::() |
2068 | { |
2069 | QTest::addColumn<Qt::Orientation>(name: "direction" ); |
2070 | QTest::addColumn<int>(name: "oldDefaultSize" ); |
2071 | QTest::addColumn<int>(name: "newDefaultSize" ); |
2072 | |
2073 | //QTest::newRow("horizontal,-5") << int(Qt::Horizontal) << 100 << -5; |
2074 | QTest::newRow(dataTag: "horizontal, 0" ) << Qt::Horizontal << 100 << 0; |
2075 | QTest::newRow(dataTag: "horizontal, 5" ) << Qt::Horizontal << 100 << 5; |
2076 | QTest::newRow(dataTag: "horizontal,25" ) << Qt::Horizontal << 100 << 5; |
2077 | } |
2078 | |
2079 | void tst_QHeaderView::() |
2080 | { |
2081 | QFETCH(Qt::Orientation, direction); |
2082 | QFETCH(int, oldDefaultSize); |
2083 | QFETCH(int, newDefaultSize); |
2084 | |
2085 | QStandardItemModel m(4, 4); |
2086 | QHeaderView h(direction); |
2087 | |
2088 | h.setModel(&m); |
2089 | h.setMinimumSectionSize(0); |
2090 | |
2091 | QCOMPARE(h.defaultSectionSize(), oldDefaultSize); |
2092 | h.setDefaultSectionSize(newDefaultSize); |
2093 | QCOMPARE(h.defaultSectionSize(), newDefaultSize); |
2094 | h.reset(); |
2095 | for (int i = 0; i < h.count(); ++i) |
2096 | QCOMPARE(h.sectionSize(i), newDefaultSize); |
2097 | } |
2098 | |
2099 | void tst_QHeaderView::hideAndInsert_data() |
2100 | { |
2101 | QTest::addColumn<Qt::Orientation>(name: "direction" ); |
2102 | QTest::addColumn<int>(name: "hide" ); |
2103 | QTest::addColumn<int>(name: "insert" ); |
2104 | QTest::addColumn<int>(name: "hidden" ); |
2105 | |
2106 | QTest::newRow(dataTag: "horizontal, 0, 0" ) << Qt::Horizontal << 0 << 0 << 1; |
2107 | } |
2108 | |
2109 | void tst_QHeaderView::hideAndInsert() |
2110 | { |
2111 | QFETCH(Qt::Orientation, direction); |
2112 | QFETCH(int, hide); |
2113 | QFETCH(int, insert); |
2114 | QFETCH(int, hidden); |
2115 | |
2116 | QStandardItemModel m(4, 4); |
2117 | QHeaderView h(direction); |
2118 | h.setModel(&m); |
2119 | h.setSectionHidden(logicalIndex: hide, hide: true); |
2120 | |
2121 | if (direction == Qt::Vertical) |
2122 | m.insertRow(arow: insert); |
2123 | else |
2124 | m.insertColumn(acolumn: insert); |
2125 | |
2126 | for (int i = 0; i < h.count(); ++i) |
2127 | QCOMPARE(h.isSectionHidden(i), i == hidden); |
2128 | } |
2129 | |
2130 | void tst_QHeaderView::() |
2131 | { |
2132 | const int hidden = 3; //section that will be hidden |
2133 | |
2134 | QStringListModel model({ "0" , "1" , "2" , "3" , "4" , "5" , "6" }); |
2135 | QHeaderView view(Qt::Vertical); |
2136 | view.setModel(&model); |
2137 | view.hideSection(alogicalIndex: hidden); |
2138 | view.hideSection(alogicalIndex: 1); |
2139 | model.removeRow(arow: 1); |
2140 | view.show(); |
2141 | |
2142 | for(int i = 0; i < view.count(); i++) { |
2143 | if (i == (hidden - 1)) { //-1 because we removed a row in the meantime |
2144 | QCOMPARE(view.sectionSize(i), 0); |
2145 | QVERIFY(view.isSectionHidden(i)); |
2146 | } else { |
2147 | QCOMPARE(view.sectionSize(i), view.defaultSectionSize() ); |
2148 | QVERIFY(!view.isSectionHidden(i)); |
2149 | } |
2150 | } |
2151 | } |
2152 | |
2153 | void tst_QHeaderView::() |
2154 | { |
2155 | QStringListModel model({ "0" , "1" , "2" , "3" }); |
2156 | QHeaderView view(Qt::Vertical); |
2157 | view.setModel(&model); |
2158 | view.resizeSection(logicalIndex: 0, size: 100); |
2159 | view.resizeSection(logicalIndex: 1, size: 10); |
2160 | view.resizeSection(logicalIndex: 2, size: 50); |
2161 | view.setSectionResizeMode(logicalIndex: 3, mode: QHeaderView::Stretch); |
2162 | view.show(); |
2163 | |
2164 | view.hideSection(alogicalIndex: 2); |
2165 | model.removeRow(arow: 1); |
2166 | view.showSection(alogicalIndex: 1); |
2167 | QCOMPARE(view.sectionSize(0), 100); |
2168 | QCOMPARE(view.sectionSize(1), 50); |
2169 | |
2170 | view.hideSection(alogicalIndex: 1); |
2171 | model.insertRow(arow: 1); |
2172 | view.showSection(alogicalIndex: 2); |
2173 | QCOMPARE(view.sectionSize(0), 100); |
2174 | QCOMPARE(view.sectionSize(1), view.defaultSectionSize()); |
2175 | QCOMPARE(view.sectionSize(2), 50); |
2176 | } |
2177 | |
2178 | void tst_QHeaderView::() |
2179 | { |
2180 | #ifdef Q_OS_WINRT |
2181 | QSKIP("Fails on WinRT - QTBUG-68297" ); |
2182 | #endif |
2183 | int count = 6; |
2184 | QStandardItemModel model(1, count); |
2185 | QHeaderView view(Qt::Horizontal); |
2186 | view.setModel(&model); |
2187 | int height = view.height(); |
2188 | |
2189 | view.resize(w: view.defaultSectionSize() * (count / 2), h: height); // don't show all sections |
2190 | view.show(); |
2191 | view.setStretchLastSection(true); |
2192 | // stretch section is not visible; it should not be stretched |
2193 | for (int i = 0; i < count; ++i) |
2194 | QCOMPARE(view.sectionSize(i), view.defaultSectionSize()); |
2195 | |
2196 | view.resize(w: view.defaultSectionSize() * (count + 1), h: height); // give room to stretch |
2197 | |
2198 | // stretch section is visible; it should be stretched |
2199 | for (int i = 0; i < count - 1; ++i) |
2200 | QCOMPARE(view.sectionSize(i), view.defaultSectionSize()); |
2201 | QCOMPARE(view.sectionSize(count - 1), view.defaultSectionSize() * 2); |
2202 | } |
2203 | |
2204 | void tst_QHeaderView::() |
2205 | { |
2206 | QStandardItemModel m(4, 4); |
2207 | QHeaderView h(Qt::Horizontal); |
2208 | h.setModel(&m); |
2209 | h.resizeSection(logicalIndex: 1, size: -5); |
2210 | QVERIFY(h.sectionSize(1) >= 0); // Sections with negative sizes not well defined. |
2211 | } |
2212 | |
2213 | void tst_QHeaderView::() |
2214 | { |
2215 | QHeaderViewPrivate::SectionItem section; |
2216 | QCOMPARE(section.sectionSize(), 0); |
2217 | } |
2218 | |
2219 | void tst_QHeaderView::() |
2220 | { |
2221 | QTest::addColumn<IntList>(name: "hide1" ); |
2222 | QTest::addColumn<IntList>(name: "hide2" ); |
2223 | |
2224 | QTest::newRow(dataTag: "set 1" ) << (IntList{ 1, 3 }) |
2225 | << (IntList{ 1, 5 }); |
2226 | |
2227 | QTest::newRow(dataTag: "set 2" ) << (IntList{ 2, 3 }) |
2228 | << (IntList{ 1, 5 }); |
2229 | |
2230 | QTest::newRow(dataTag: "set 3" ) << (IntList{ 0, 2, 4 }) |
2231 | << (IntList{ 2, 3, 5 }); |
2232 | |
2233 | } |
2234 | |
2235 | void tst_QHeaderView::() |
2236 | { |
2237 | QFETCH(const IntList, hide1); |
2238 | QFETCH(const IntList, hide2); |
2239 | |
2240 | QStringListModel model({ "0" , "1" , "2" , "3" , "4" , "5" }); |
2241 | protected_QHeaderView view(Qt::Vertical); |
2242 | view.setModel(&model); |
2243 | view.show(); |
2244 | |
2245 | for (int i : hide1) |
2246 | view.hideSection(alogicalIndex: i); |
2247 | |
2248 | QCOMPARE(view.hiddenSectionCount(), hide1.count()); |
2249 | for (int i = 0; i < 6; i++) |
2250 | QCOMPARE(!view.isSectionHidden(i), !hide1.contains(i)); |
2251 | |
2252 | view.setDefaultSectionSize(2); |
2253 | view.scheduleDelayedItemsLayout(); |
2254 | view.executeDelayedItemsLayout(); //force to do a relayout |
2255 | |
2256 | QCOMPARE(view.hiddenSectionCount(), hide1.count()); |
2257 | for (int i = 0; i < 6; i++) { |
2258 | QCOMPARE(!view.isSectionHidden(i), !hide1.contains(i)); |
2259 | view.setSectionHidden(logicalIndex: i, hide: hide2.contains(t: i)); |
2260 | } |
2261 | |
2262 | QCOMPARE(view.hiddenSectionCount(), hide2.count()); |
2263 | for (int i = 0; i < 6; i++) |
2264 | QCOMPARE(!view.isSectionHidden(i), !hide2.contains(i)); |
2265 | } |
2266 | |
2267 | void tst_QHeaderView::() |
2268 | { |
2269 | //this is the sequence of events that make the task fail |
2270 | protected_QHeaderView (Qt::Vertical); |
2271 | QStandardItemModel model(0, 1); |
2272 | header.setMinimumSectionSize(0); // system default min size can be to large |
2273 | header.setStretchLastSection(false); |
2274 | header.setDefaultSectionSize(17); |
2275 | header.setModel(&model); |
2276 | header.doItemsLayout(); |
2277 | |
2278 | model.setRowCount(3); |
2279 | |
2280 | QCOMPARE(header.sectionPosition(2), 17*2); |
2281 | |
2282 | header.hideSection(alogicalIndex: 1); |
2283 | QCOMPARE(header.sectionPosition(2), 17); |
2284 | |
2285 | QTest::qWait(ms: 100); |
2286 | //the size of the section shouldn't have changed |
2287 | QCOMPARE(header.sectionPosition(2), 17); |
2288 | } |
2289 | |
2290 | |
2291 | //returns 0 if everything is fine. |
2292 | static int (const QHeaderView *view, const IntList &expected) |
2293 | { |
2294 | if (view->count() != expected.count()) |
2295 | return 1; |
2296 | |
2297 | for (int i = 0; i < expected.count(); i++) { |
2298 | if (view->logicalIndex(visualIndex: i) != expected.at(i)) |
2299 | return i + 10; |
2300 | if (view->visualIndex(logicalIndex: expected.at(i)) != i) |
2301 | return i + 100; |
2302 | } |
2303 | return 0; |
2304 | } |
2305 | |
2306 | |
2307 | void tst_QHeaderView::() |
2308 | { |
2309 | if (QGuiApplication::platformName().startsWith(s: QLatin1String("wayland" ), cs: Qt::CaseInsensitive)) |
2310 | QSKIP("Wayland: This fails. Figure out why." ); |
2311 | |
2312 | QStringListModel model1({ "0" , "1" , "2" , "3" , "4" , "5" }); |
2313 | QStringListModel model2({ "a" , "b" , "c" }); |
2314 | QSortFilterProxyModel proxy; |
2315 | |
2316 | QHeaderView view(Qt::Vertical); |
2317 | view.setModel(&proxy); |
2318 | view.show(); |
2319 | QVERIFY(QTest::qWaitForWindowExposed(&view)); |
2320 | QVERIFY(QTest::qWaitForWindowActive(&view)); |
2321 | |
2322 | proxy.setSourceModel(&model1); |
2323 | view.swapSections(first: 0, second: 2); |
2324 | view.swapSections(first: 1, second: 4); |
2325 | IntList expectedOrder{2, 4, 0, 3, 1, 5}; |
2326 | QTRY_COMPARE(checkHeaderViewOrder(&view, expectedOrder) , 0); |
2327 | |
2328 | proxy.setSourceModel(&model2); |
2329 | expectedOrder = {2, 0, 1}; |
2330 | QTRY_COMPARE(checkHeaderViewOrder(&view, expectedOrder) , 0); |
2331 | |
2332 | proxy.setSourceModel(&model1); |
2333 | expectedOrder = {2, 0, 1, 3, 4, 5}; |
2334 | QTRY_COMPARE(checkHeaderViewOrder(&view, expectedOrder) , 0); |
2335 | } |
2336 | |
2337 | void tst_QHeaderView::() |
2338 | { |
2339 | QTableView tv; |
2340 | QStandardItemModel *sim = new QStandardItemModel(&tv); |
2341 | QSortFilterProxyModel *proxyModel = new QSortFilterProxyModel(&tv); |
2342 | proxyModel->setSourceModel(sim); |
2343 | proxyModel->setDynamicSortFilter(true); |
2344 | proxyModel->setSortCaseSensitivity(Qt::CaseInsensitive); |
2345 | |
2346 | QList<QStandardItem *> row; |
2347 | for (char i = 0; i < 12; i++) |
2348 | row.append(t: new QStandardItem(QString(QLatin1Char('A' + i)))); |
2349 | sim->appendRow(items: row); |
2350 | row.clear(); |
2351 | for (char i = 12; i > 0; i--) |
2352 | row.append(t: new QStandardItem(QString(QLatin1Char('A' + i)))); |
2353 | sim->appendRow(items: row); |
2354 | |
2355 | tv.setSortingEnabled(true); |
2356 | tv.horizontalHeader()->setSortIndicatorShown(true); |
2357 | tv.horizontalHeader()->setSectionsClickable(true); |
2358 | tv.horizontalHeader()->setStretchLastSection(true); |
2359 | tv.horizontalHeader()->setSectionResizeMode(QHeaderView::Interactive); |
2360 | |
2361 | tv.setModel(proxyModel); |
2362 | const int section4Size = tv.horizontalHeader()->sectionSize(logicalIndex: 4) + 1; |
2363 | const int section5Size = section4Size + 1; |
2364 | tv.horizontalHeader()->resizeSection(logicalIndex: 4, size: section4Size); |
2365 | tv.horizontalHeader()->resizeSection(logicalIndex: 5, size: section5Size); |
2366 | tv.setColumnHidden(column: 5, hide: true); |
2367 | tv.setColumnHidden(column: 6, hide: true); |
2368 | tv.horizontalHeader()->swapSections(first: 8, second: 10); |
2369 | tv.sortByColumn(column: 1, order: Qt::AscendingOrder); |
2370 | |
2371 | QCOMPARE(tv.isColumnHidden(5), true); |
2372 | QCOMPARE(tv.isColumnHidden(6), true); |
2373 | QCOMPARE(tv.horizontalHeader()->sectionsMoved(), true); |
2374 | QCOMPARE(tv.horizontalHeader()->logicalIndex(8), 10); |
2375 | QCOMPARE(tv.horizontalHeader()->logicalIndex(10), 8); |
2376 | QCOMPARE(tv.horizontalHeader()->sectionSize(4), section4Size); |
2377 | tv.setColumnHidden(column: 5, hide: false); // unhide, section size must be properly restored |
2378 | QCOMPARE(tv.horizontalHeader()->sectionSize(5), section5Size); |
2379 | tv.setColumnHidden(column: 5, hide: true); |
2380 | |
2381 | QSignalSpy clickedSpy(tv.horizontalHeader(), &QHeaderView::sectionClicked); |
2382 | QSignalSpy pressedSpy(tv.horizontalHeader(), &QHeaderView::sectionPressed); |
2383 | |
2384 | |
2385 | QTest::mouseClick(widget: tv.horizontalHeader()->viewport(), button: Qt::LeftButton, stateKey: Qt::NoModifier, |
2386 | pos: QPoint(tv.horizontalHeader()->sectionViewportPosition(logicalIndex: 11) + |
2387 | tv.horizontalHeader()->sectionSize(logicalIndex: 11) / 2, 5)); |
2388 | QCOMPARE(clickedSpy.count(), 1); |
2389 | QCOMPARE(pressedSpy.count(), 1); |
2390 | QCOMPARE(clickedSpy.at(0).at(0).toInt(), 11); |
2391 | QCOMPARE(pressedSpy.at(0).at(0).toInt(), 11); |
2392 | |
2393 | QTest::mouseClick(widget: tv.horizontalHeader()->viewport(), button: Qt::LeftButton, stateKey: Qt::NoModifier, |
2394 | pos: QPoint(tv.horizontalHeader()->sectionViewportPosition(logicalIndex: 8) + |
2395 | tv.horizontalHeader()->sectionSize(logicalIndex: 0) / 2, 5)); |
2396 | |
2397 | QCOMPARE(clickedSpy.count(), 2); |
2398 | QCOMPARE(pressedSpy.count(), 2); |
2399 | QCOMPARE(clickedSpy.at(1).at(0).toInt(), 8); |
2400 | QCOMPARE(pressedSpy.at(1).at(0).toInt(), 8); |
2401 | |
2402 | QTest::mouseClick(widget: tv.horizontalHeader()->viewport(), button: Qt::LeftButton, stateKey: Qt::NoModifier, |
2403 | pos: QPoint(tv.horizontalHeader()->sectionViewportPosition(logicalIndex: 0) + |
2404 | tv.horizontalHeader()->sectionSize(logicalIndex: 0) / 2, 5)); |
2405 | |
2406 | QCOMPARE(clickedSpy.count(), 3); |
2407 | QCOMPARE(pressedSpy.count(), 3); |
2408 | QCOMPARE(clickedSpy.at(2).at(0).toInt(), 0); |
2409 | QCOMPARE(pressedSpy.at(2).at(0).toInt(), 0); |
2410 | } |
2411 | |
2412 | void tst_QHeaderView::() |
2413 | { |
2414 | QtTestModel tm(0, 11); |
2415 | QTableView tv; |
2416 | tv.verticalHeader()->setStretchLastSection(true); |
2417 | tv.setModel(&tm); |
2418 | |
2419 | const int section4Size = tv.horizontalHeader()->sectionSize(logicalIndex: 4) + 1; |
2420 | const int section5Size = section4Size + 1; |
2421 | tv.horizontalHeader()->resizeSection(logicalIndex: 4, size: section4Size); |
2422 | tv.horizontalHeader()->resizeSection(logicalIndex: 5, size: section5Size); |
2423 | tv.setColumnHidden(column: 5, hide: true); |
2424 | tv.setColumnHidden(column: 6, hide: true); |
2425 | tv.horizontalHeader()->swapSections(first: 8, second: 10); |
2426 | |
2427 | tv.sortByColumn(column: 1, order: Qt::AscendingOrder); |
2428 | tm.emitLayoutChanged(); |
2429 | |
2430 | QCOMPARE(tv.isColumnHidden(5), true); |
2431 | QCOMPARE(tv.isColumnHidden(6), true); |
2432 | QCOMPARE(tv.horizontalHeader()->sectionsMoved(), true); |
2433 | QCOMPARE(tv.horizontalHeader()->logicalIndex(8), 10); |
2434 | QCOMPARE(tv.horizontalHeader()->logicalIndex(10), 8); |
2435 | QCOMPARE(tv.horizontalHeader()->sectionSize(4), section4Size); |
2436 | tv.setColumnHidden(column: 5, hide: false); // unhide, section size must be properly restored |
2437 | QCOMPARE(tv.horizontalHeader()->sectionSize(5), section5Size); |
2438 | tv.setColumnHidden(column: 5, hide: true); |
2439 | |
2440 | // adjust |
2441 | tm.rows = 3; |
2442 | tm.emitLayoutChanged(); |
2443 | |
2444 | // remove the row used for QPersistenModelIndexes |
2445 | tm.emitLayoutChangedWithRemoveFirstRow(); |
2446 | QCOMPARE(tv.isColumnHidden(5), true); |
2447 | QCOMPARE(tv.isColumnHidden(6), true); |
2448 | QCOMPARE(tv.horizontalHeader()->sectionsMoved(), true); |
2449 | QCOMPARE(tv.horizontalHeader()->logicalIndex(8), 10); |
2450 | QCOMPARE(tv.horizontalHeader()->logicalIndex(10), 8); |
2451 | QCOMPARE(tv.horizontalHeader()->sectionSize(4), section4Size); |
2452 | tv.setColumnHidden(column: 5, hide: false); // unhide, section size must be properly restored |
2453 | QCOMPARE(tv.horizontalHeader()->sectionSize(5), section5Size); |
2454 | tv.setColumnHidden(column: 5, hide: true); |
2455 | } |
2456 | |
2457 | void tst_QHeaderView::() |
2458 | { |
2459 | QStringList ; |
2460 | QHeaderView view(Qt::Horizontal); |
2461 | QStandardItemModel model(2, 2); |
2462 | view.setModel(&model); |
2463 | view.moveSection(from: 1, to: 0); |
2464 | view.hideSection(alogicalIndex: 0); |
2465 | |
2466 | model.insertColumn(column: 0, items: { new QStandardItem("c" ) }); |
2467 | } |
2468 | |
2469 | static void setModelTexts(QStandardItemModel *model) |
2470 | { |
2471 | const int columnCount = model->columnCount(); |
2472 | for (int i = 0, rowCount = model->rowCount(); i < rowCount; ++i) { |
2473 | const QString prefix = QLatin1String("item [" ) + QString::number(i) + QLatin1Char(','); |
2474 | for (int j = 0; j < columnCount; ++j) |
2475 | model->setData(index: model->index(row: i, column: j), value: prefix + QString::number(j) + QLatin1Char(']')); |
2476 | } |
2477 | } |
2478 | |
2479 | void tst_QHeaderView::() |
2480 | { |
2481 | QTableView view; // ### this test fails on QTableView &view = *m_tableview; !? + shadowing view member |
2482 | QStandardItemModel model(4, 3); |
2483 | setModelTexts(&model); |
2484 | view.setModel(&model); |
2485 | view.horizontalHeader()->setSectionsMovable(true); |
2486 | view.setSortingEnabled(true); |
2487 | view.sortByColumn(column: 1, order: Qt::AscendingOrder); |
2488 | view.horizontalHeader()->moveSection(from: 0,to: 2); |
2489 | view.setColumnHidden(column: 1, hide: true); |
2490 | view.show(); |
2491 | QVERIFY(QTest::qWaitForWindowExposed(&view)); |
2492 | QCOMPARE(view.horizontalHeader()->hiddenSectionCount(), 1); |
2493 | QTest::mouseClick(widget: view.horizontalHeader()->viewport(), button: Qt::LeftButton); |
2494 | QCOMPARE(view.horizontalHeader()->hiddenSectionCount(), 1); |
2495 | } |
2496 | |
2497 | void tst_QHeaderView::() |
2498 | { |
2499 | QTableView qtv; |
2500 | QStandardItemModel amodel(4, 4); |
2501 | qtv.setModel(&amodel); |
2502 | QHeaderView *hv = qtv.verticalHeader(); |
2503 | hv->setDefaultSectionSize(25); |
2504 | hv->setSectionResizeMode(QHeaderView::ResizeToContents); |
2505 | qtv.show(); |
2506 | |
2507 | hv->hideSection(alogicalIndex: 0); |
2508 | int afterlength = hv->length(); |
2509 | |
2510 | int calced_length = 0; |
2511 | for (int u = 0; u < hv->count(); ++u) |
2512 | calced_length += hv->sectionSize(logicalIndex: u); |
2513 | |
2514 | QCOMPARE(calced_length, afterlength); |
2515 | } |
2516 | |
2517 | void tst_QHeaderView::() |
2518 | { |
2519 | protected_QHeaderView (Qt::Horizontal); |
2520 | QtTestModel model(2, 3); |
2521 | headerView.setModel(&model); |
2522 | headerView.swapSections(first: 1, second: 2); |
2523 | headerView.hideSection(alogicalIndex: 0); |
2524 | headerView.testVisualRegionForSelection(); |
2525 | } |
2526 | |
2527 | class QTBUG53221_Model : public QAbstractItemModel |
2528 | { |
2529 | Q_OBJECT |
2530 | public: |
2531 | void insertRowAtBeginning() |
2532 | { |
2533 | Q_EMIT layoutAboutToBeChanged(); |
2534 | m_displayNames.insert(i: 0, QStringLiteral("Item %1" ).arg(a: m_displayNames.count())); |
2535 | // Rows are always inserted at the beginning, so move all others. |
2536 | const auto pl = persistentIndexList(); |
2537 | // The vertical header view will have a persistent index stored here on the second call to insertRowAtBeginning. |
2538 | for (const QModelIndex &persIndex : pl) |
2539 | changePersistentIndex(from: persIndex, to: index(row: persIndex.row() + 1, column: persIndex.column(), persIndex.parent())); |
2540 | Q_EMIT layoutChanged(); |
2541 | } |
2542 | |
2543 | QVariant data(const QModelIndex &index, int role) const override |
2544 | { |
2545 | return (role == Qt::DisplayRole) ? m_displayNames.at(i: index.row()) : QVariant(); |
2546 | } |
2547 | |
2548 | QModelIndex index(int row, int column, const QModelIndex &) const override { return createIndex(arow: row, acolumn: column); } |
2549 | QModelIndex parent(const QModelIndex &) const override { return QModelIndex(); } |
2550 | int rowCount(const QModelIndex &) const override { return m_displayNames.count(); } |
2551 | int columnCount(const QModelIndex &) const override { return 1; } |
2552 | |
2553 | private: |
2554 | QStringList m_displayNames; |
2555 | }; |
2556 | |
2557 | void tst_QHeaderView::() |
2558 | { |
2559 | QTableView tableView; |
2560 | QTBUG53221_Model modelTableView; |
2561 | tableView.setModel(&modelTableView); |
2562 | |
2563 | modelTableView.insertRowAtBeginning(); |
2564 | tableView.setRowHidden(row: 0, hide: true); |
2565 | QCOMPARE(tableView.verticalHeader()->isSectionHidden(0), true); |
2566 | modelTableView.insertRowAtBeginning(); |
2567 | QCOMPARE(tableView.verticalHeader()->isSectionHidden(0), false); |
2568 | QCOMPARE(tableView.verticalHeader()->isSectionHidden(1), true); |
2569 | modelTableView.insertRowAtBeginning(); |
2570 | QCOMPARE(tableView.verticalHeader()->isSectionHidden(0), false); |
2571 | QCOMPARE(tableView.verticalHeader()->isSectionHidden(1), false); |
2572 | QCOMPARE(tableView.verticalHeader()->isSectionHidden(2), true); |
2573 | } |
2574 | |
2575 | void tst_QHeaderView::() |
2576 | { |
2577 | QTableView tableView; |
2578 | QStandardItemModel model(1, 1); |
2579 | tableView.setModel(&model); |
2580 | tableView.show(); |
2581 | |
2582 | const auto = tableView.horizontalHeader(); |
2583 | const auto oldSizeHint = headerView->sizeHint(); |
2584 | QVERIFY(oldSizeHint.isValid()); |
2585 | |
2586 | tableView.setStyleSheet("QTableView QHeaderView::section { height: 100px;}" ); |
2587 | QCOMPARE(headerView->sizeHint().width(), oldSizeHint.width()); |
2588 | QCOMPARE(headerView->sizeHint().height(), 100); |
2589 | |
2590 | tableView.setStyleSheet("QTableView QHeaderView::section { width: 100px;}" ); |
2591 | QCOMPARE(headerView->sizeHint().height(), oldSizeHint.height()); |
2592 | QCOMPARE(headerView->sizeHint().width(), 100); |
2593 | } |
2594 | |
2595 | void protected_QHeaderView::() |
2596 | { |
2597 | QRegion r = visualRegionForSelection(selection: QItemSelection(model()->index(row: 1, column: 0), model()->index(row: 1, column: 2))); |
2598 | QCOMPARE(r.boundingRect().contains(QRect(1, 1, length() - 2, 1)), true); |
2599 | } |
2600 | |
2601 | void tst_QHeaderView::() |
2602 | { |
2603 | QTableView qtv; |
2604 | QStandardItemModel amodel(4, 4); |
2605 | qtv.setModel(&amodel); |
2606 | QHeaderView *hv = qtv.verticalHeader(); |
2607 | QCOMPARE(hv->visualIndexAt(hv->length()), -1); |
2608 | hv->resizeSection(logicalIndex: hv->count() - 1, size: 0); |
2609 | QCOMPARE(hv->visualIndexAt(hv->length()), -1); |
2610 | } |
2611 | |
2612 | void tst_QHeaderView::() |
2613 | { |
2614 | // Ensure that a hidden section 'far away' |
2615 | // does not affect setOffsetToSectionPosition .. |
2616 | const int sectionToHide = 513; |
2617 | QTableView qtv; |
2618 | QStandardItemModel amodel(1000, 4); |
2619 | qtv.setModel(&amodel); |
2620 | QHeaderView *hv = qtv.verticalHeader(); |
2621 | for (int u = 0; u < 100; u += 2) |
2622 | hv->resizeSection(logicalIndex: u, size: 0); |
2623 | hv->setOffsetToSectionPosition(150); |
2624 | int offset1 = hv->offset(); |
2625 | hv->hideSection(alogicalIndex: sectionToHide); |
2626 | hv->setOffsetToSectionPosition(150); |
2627 | int offset2 = hv->offset(); |
2628 | QCOMPARE(offset1, offset2); |
2629 | // Ensure that hidden indexes (still) is considered. |
2630 | hv->resizeSection(logicalIndex: sectionToHide, size: hv->sectionSize(logicalIndex: 200) * 2); |
2631 | hv->setOffsetToSectionPosition(800); |
2632 | offset1 = hv->offset(); |
2633 | hv->showSection(alogicalIndex: sectionToHide); |
2634 | hv->setOffsetToSectionPosition(800); |
2635 | offset2 = hv->offset(); |
2636 | QVERIFY(offset2 > offset1); |
2637 | } |
2638 | |
2639 | void tst_QHeaderView::() |
2640 | { |
2641 | QTableView qtv; |
2642 | QStandardItemModel amodel(1000, 4); |
2643 | qtv.setModel(&amodel); |
2644 | QHeaderView *hv = qtv.horizontalHeader(); |
2645 | hv->setSectionsClickable(true); |
2646 | hv->setFirstSectionMovable(true); |
2647 | hv->setSectionsMovable(false); |
2648 | |
2649 | enum { DefaultYOffset = 5, OutOfRangeYOffset = 10000 }; |
2650 | |
2651 | const auto pressOnSection = [&](int section, int yOffset = DefaultYOffset) |
2652 | { |
2653 | QTest::mousePress(widget: hv->viewport(), button: Qt::LeftButton, stateKey: Qt::NoModifier, |
2654 | pos: QPoint(hv->sectionViewportPosition(logicalIndex: section) + hv->sectionSize(logicalIndex: section) / 2, yOffset)); |
2655 | }; |
2656 | const auto moveOntoSection = [&](int section, int yOffset = DefaultYOffset) |
2657 | { |
2658 | QTest::mouseMove(widget: hv->viewport(), |
2659 | pos: QPoint(hv->sectionViewportPosition(logicalIndex: section) + hv->sectionSize(logicalIndex: section) / 2, yOffset)); |
2660 | }; |
2661 | const auto releaseOnSection = [&](int section, int yOffset = DefaultYOffset) |
2662 | { |
2663 | QTest::mouseRelease(widget: hv->viewport(), button: Qt::LeftButton, stateKey: Qt::NoModifier, |
2664 | pos: QPoint(hv->sectionViewportPosition(logicalIndex: section) + hv->sectionSize(logicalIndex: section) / 2, yOffset)); |
2665 | }; |
2666 | |
2667 | hv->setSortIndicator(logicalIndex: -1, order: Qt::AscendingOrder); |
2668 | QCOMPARE(hv->sortIndicatorSection(), -1); |
2669 | |
2670 | pressOnSection(0); |
2671 | releaseOnSection(0); |
2672 | // RESULT: sorting |
2673 | QCOMPARE(hv->sortIndicatorSection(), 0); |
2674 | |
2675 | hv->setSortIndicator(logicalIndex: -1, order: Qt::AscendingOrder); |
2676 | QCOMPARE(hv->sortIndicatorSection(), -1); |
2677 | |
2678 | pressOnSection(0); |
2679 | moveOntoSection(1); |
2680 | releaseOnSection(1); |
2681 | // RESULT: no sorting |
2682 | QCOMPARE(hv->sortIndicatorSection(), -1); |
2683 | |
2684 | pressOnSection(0); |
2685 | moveOntoSection(1); |
2686 | moveOntoSection(2); |
2687 | releaseOnSection(2); |
2688 | // RESULT: no sorting |
2689 | QCOMPARE(hv->sortIndicatorSection(), -1); |
2690 | |
2691 | pressOnSection(0); |
2692 | moveOntoSection(1); |
2693 | moveOntoSection(0); |
2694 | releaseOnSection(0); |
2695 | // RESULT: sorting by 0 |
2696 | QCOMPARE(hv->sortIndicatorSection(), 0); |
2697 | |
2698 | pressOnSection(0); |
2699 | moveOntoSection(1); |
2700 | releaseOnSection(1); |
2701 | // RESULT: no change, still sorting by 0 |
2702 | QCOMPARE(hv->sortIndicatorSection(), 0); |
2703 | |
2704 | auto sortOrder = hv->sortIndicatorOrder(); |
2705 | pressOnSection(1); |
2706 | moveOntoSection(0); |
2707 | releaseOnSection(0); |
2708 | // RESULT: no change, still sorting by 0 |
2709 | QCOMPARE(hv->sortIndicatorSection(), 0); |
2710 | QCOMPARE(hv->sortIndicatorOrder(), sortOrder); |
2711 | |
2712 | pressOnSection(1); |
2713 | moveOntoSection(0); |
2714 | moveOntoSection(1); |
2715 | releaseOnSection(1); |
2716 | // RESULT: sorting by 1 |
2717 | QCOMPARE(hv->sortIndicatorSection(), 1); |
2718 | |
2719 | pressOnSection(1); |
2720 | moveOntoSection(0); |
2721 | releaseOnSection(0); |
2722 | // RESULT: no change, still sorting by 1 |
2723 | QCOMPARE(hv->sortIndicatorSection(), 1); |
2724 | |
2725 | hv->setSortIndicator(logicalIndex: -1, order: Qt::AscendingOrder); |
2726 | QCOMPARE(hv->sortIndicatorSection(), -1); |
2727 | |
2728 | pressOnSection(0); |
2729 | releaseOnSection(0, OutOfRangeYOffset); |
2730 | // RESULT: no sorting |
2731 | QCOMPARE(hv->sortIndicatorSection(), -1); |
2732 | |
2733 | pressOnSection(0); |
2734 | moveOntoSection(0, OutOfRangeYOffset); |
2735 | releaseOnSection(0, OutOfRangeYOffset); |
2736 | // RESULT: no sorting |
2737 | QCOMPARE(hv->sortIndicatorSection(), -1); |
2738 | |
2739 | pressOnSection(0); |
2740 | moveOntoSection(0, OutOfRangeYOffset); |
2741 | moveOntoSection(0); |
2742 | releaseOnSection(0); |
2743 | // RESULT: sorting by 0 |
2744 | QCOMPARE(hv->sortIndicatorSection(), 0); |
2745 | |
2746 | pressOnSection(1); |
2747 | releaseOnSection(1, OutOfRangeYOffset); |
2748 | // RESULT: no change, still sorting by 0 |
2749 | QCOMPARE(hv->sortIndicatorSection(), 0); |
2750 | |
2751 | pressOnSection(1); |
2752 | moveOntoSection(1, OutOfRangeYOffset); |
2753 | releaseOnSection(1, OutOfRangeYOffset); |
2754 | // RESULT: no change, still sorting by 0 |
2755 | QCOMPARE(hv->sortIndicatorSection(), 0); |
2756 | |
2757 | pressOnSection(1); |
2758 | moveOntoSection(1, OutOfRangeYOffset); |
2759 | moveOntoSection(1); |
2760 | releaseOnSection(1); |
2761 | // RESULT: sorting by 1 |
2762 | QCOMPARE(hv->sortIndicatorSection(), 1); |
2763 | |
2764 | pressOnSection(2); |
2765 | moveOntoSection(1); |
2766 | moveOntoSection(2); |
2767 | moveOntoSection(2, OutOfRangeYOffset); |
2768 | releaseOnSection(2, OutOfRangeYOffset); |
2769 | // RESULT: no change, still sorting by 1 |
2770 | QCOMPARE(hv->sortIndicatorSection(), 1); |
2771 | } |
2772 | |
2773 | void tst_QHeaderView::() |
2774 | { |
2775 | QTableView view; // ### Shadowing member view (of type QHeaderView) |
2776 | QStandardItemModel model(4, 3); |
2777 | setModelTexts(&model); |
2778 | QStandardItem *ascendingItem = new QStandardItem(); |
2779 | QStandardItem *descendingItem = new QStandardItem(); |
2780 | ascendingItem->setData(value: Qt::AscendingOrder, role: Qt::InitialSortOrderRole); |
2781 | descendingItem->setData(value: Qt::DescendingOrder, role: Qt::InitialSortOrderRole); |
2782 | model.setHorizontalHeaderItem(column: 1, item: ascendingItem); |
2783 | model.setHorizontalHeaderItem(column: 2, item: descendingItem); |
2784 | view.setModel(&model); |
2785 | view.setSortingEnabled(true); |
2786 | view.sortByColumn(column: 0, order: Qt::AscendingOrder); |
2787 | view.show(); |
2788 | QVERIFY(QTest::qWaitForWindowExposed(&view)); |
2789 | |
2790 | const int column1Pos = view.horizontalHeader()->sectionViewportPosition(logicalIndex: 1) + 5; // +5 not to be on the handle |
2791 | QTest::mouseClick(widget: view.horizontalHeader()->viewport(), button: Qt::LeftButton, stateKey: Qt::NoModifier, pos: QPoint(column1Pos, 0)); |
2792 | QCOMPARE(view.horizontalHeader()->sortIndicatorSection(), 1); |
2793 | QCOMPARE(view.horizontalHeader()->sortIndicatorOrder(), Qt::AscendingOrder); |
2794 | |
2795 | const int column2Pos = view.horizontalHeader()->sectionViewportPosition(logicalIndex: 2) + 5; // +5 not to be on the handle |
2796 | QTest::mouseClick(widget: view.horizontalHeader()->viewport(), button: Qt::LeftButton, stateKey: Qt::NoModifier, pos: QPoint(column2Pos, 0)); |
2797 | QCOMPARE(view.horizontalHeader()->sortIndicatorSection(), 2); |
2798 | QCOMPARE(view.horizontalHeader()->sortIndicatorOrder(), Qt::DescendingOrder); |
2799 | |
2800 | const int column0Pos = view.horizontalHeader()->sectionViewportPosition(logicalIndex: 0) + 5; // +5 not to be on the handle |
2801 | QTest::mouseClick(widget: view.horizontalHeader()->viewport(), button: Qt::LeftButton, stateKey: Qt::NoModifier, pos: QPoint(column0Pos, 0)); |
2802 | QCOMPARE(view.horizontalHeader()->sortIndicatorSection(), 0); |
2803 | QCOMPARE(view.horizontalHeader()->sortIndicatorOrder(), Qt::AscendingOrder); |
2804 | } |
2805 | |
2806 | const bool block_some_signals = true; // The test should also work with this set to false |
2807 | const int rowcount = 500; |
2808 | const int colcount = 10; |
2809 | |
2810 | static inline QString istr(int n, bool comma = true) |
2811 | { |
2812 | QString s; |
2813 | s.setNum(n); |
2814 | if (comma) |
2815 | s += ", " ; |
2816 | return s; |
2817 | } |
2818 | |
2819 | void tst_QHeaderView::calculateAndCheck(int cppline, const int precalced_comparedata[]) |
2820 | { |
2821 | qint64 endtimer = timer.elapsed(); |
2822 | const bool silentmode = true; |
2823 | if (!silentmode) |
2824 | qDebug().nospace() << "(Time:" << endtimer << ")" ; |
2825 | |
2826 | QString sline; |
2827 | sline.setNum(n: cppline - 1); |
2828 | |
2829 | const int p1 = 3133777; // just a prime (maybe not that random ;) ) |
2830 | const int p2 = 135928393; // just a random large prime - a bit less than signed 32-bit |
2831 | |
2832 | int sum_visual = 0; |
2833 | int sum_logical = 0; |
2834 | int sum_size = 0; |
2835 | int sum_hidden_size = 0; |
2836 | int sum_lookup_visual = 0; |
2837 | int sum_lookup_logical = 0; |
2838 | |
2839 | int chk_visual = 1; |
2840 | int chk_logical = 1; |
2841 | int chk_sizes = 1; |
2842 | int chk_hidden_size = 1; |
2843 | int chk_lookup_visual = 1; |
2844 | int chk_lookup_logical = 1; |
2845 | |
2846 | int = 0; |
2847 | int lastindex = view->count() - 1; |
2848 | |
2849 | // calculate information based on index |
2850 | for (int i = 0; i <= lastindex; ++i) { |
2851 | int visual = view->visualIndex(logicalIndex: i); |
2852 | int logical = view->logicalIndex(visualIndex: i); |
2853 | int ssize = view->sectionSize(logicalIndex: i); |
2854 | |
2855 | sum_visual += visual; |
2856 | sum_logical += logical; |
2857 | sum_size += ssize; |
2858 | |
2859 | if (visual >= 0) { |
2860 | chk_visual %= p2; |
2861 | chk_visual *= (visual + 1) * (i + 1) * p1; |
2862 | } |
2863 | |
2864 | if (logical >= 0) { |
2865 | chk_logical %= p2; |
2866 | chk_logical *= (logical + 1) * (i + 1 + (logical != i) ) * p1; |
2867 | } |
2868 | |
2869 | if (ssize >= 0) { |
2870 | chk_sizes %= p2; |
2871 | chk_sizes *= ( (ssize + 2) * (i + 1) * p1); |
2872 | } |
2873 | |
2874 | if (view->isSectionHidden(logicalIndex: i)) { |
2875 | view->showSection(alogicalIndex: i); |
2876 | int hiddensize = view->sectionSize(logicalIndex: i); |
2877 | sum_hidden_size += hiddensize; |
2878 | chk_hidden_size %= p2; |
2879 | chk_hidden_size += ( (hiddensize + 1) * (i + 1) * p1); |
2880 | // (hiddensize + 1) in the above to differ between hidden and size 0 |
2881 | // Though it can be changed (why isn't sections with size 0 hidden?) |
2882 | |
2883 | view->hideSection(alogicalIndex: i); |
2884 | } |
2885 | } |
2886 | |
2887 | // lookup indexes by pixel position |
2888 | const int max_lookup_count = 500; |
2889 | int lookup_to = view->height() + 1; |
2890 | if (lookup_to > max_lookup_count) |
2891 | lookup_to = max_lookup_count; // We limit this lookup - not to spend years when testing. |
2892 | // Notice that lookupTest also has its own extra test |
2893 | for (int u = 0; u < max_lookup_count; ++u) { |
2894 | int visu = view->visualIndexAt(position: u); |
2895 | int logi = view->logicalIndexAt(position: u); |
2896 | sum_lookup_visual += logi; |
2897 | sum_lookup_logical += visu; |
2898 | chk_lookup_visual %= p2; |
2899 | chk_lookup_visual *= ( (u + 1) * p1 * (visu + 2)); |
2900 | chk_lookup_logical %= p2; |
2901 | chk_lookup_logical *= ( (u + 1) * p1 * (logi + 2)); |
2902 | } |
2903 | header_lenght = view->length(); |
2904 | |
2905 | // visual and logical indexes. |
2906 | int sum_to_last_index = (lastindex * (lastindex + 1)) / 2; // == 0 + 1 + 2 + 3 + ... + lastindex |
2907 | |
2908 | const bool write_calced_data = false; // Do not write calculated output (unless the test fails) |
2909 | if (write_calced_data) { |
2910 | qDebug().nospace() << "(" << cppline - 1 << ")" // << " const int precalced[] = " |
2911 | << " {" << chk_visual << ", " << chk_logical << ", " << chk_sizes << ", " << chk_hidden_size |
2912 | << ", " << chk_lookup_visual << ", " << chk_lookup_logical << ", " << header_lenght << "};" ; |
2913 | } |
2914 | |
2915 | const bool sanity_checks = true; |
2916 | if (sanity_checks) { |
2917 | QString msg = QString("sanity problem at " ) + sline; |
2918 | const QScopedArrayPointer<char> holder(QTest::toString(str: msg)); |
2919 | const auto verifytext = holder.data(); |
2920 | |
2921 | QVERIFY2(m_tableview->model()->rowCount() == view->count() , verifytext); |
2922 | QVERIFY2(view->visualIndex(lastindex + 1) <= 0, verifytext); // there is no such index in model |
2923 | QVERIFY2(view->logicalIndex(lastindex + 1) <= 0, verifytext); // there is no such index in model. |
2924 | QVERIFY2(view->logicalIndex(lastindex + 1) <= 0, verifytext); // there is no such index in model. |
2925 | QVERIFY2(lastindex < 0 || view->visualIndex(0) >= 0, verifytext); // no rows or legal index |
2926 | QVERIFY2(lastindex < 0 || view->logicalIndex(0) >= 0, verifytext); // no rows or legal index |
2927 | QVERIFY2(lastindex < 0 || view->visualIndex(lastindex) >= 0, verifytext); // no rows or legal index |
2928 | QVERIFY2(lastindex < 0 || view->logicalIndex(lastindex) >= 0, verifytext); // no rows or legal index |
2929 | QVERIFY2(view->visualIndexAt(-1) == -1, verifytext); |
2930 | QVERIFY2(view->logicalIndexAt(-1) == -1, verifytext); |
2931 | QVERIFY2(view->visualIndexAt(view->length()) == -1, verifytext); |
2932 | QVERIFY2(view->logicalIndexAt(view->length()) == -1, verifytext); |
2933 | QVERIFY2(sum_visual == sum_logical, verifytext); |
2934 | QVERIFY2(sum_to_last_index == sum_logical, verifytext); |
2935 | } |
2936 | |
2937 | // Semantic test |
2938 | const bool check_semantics = true; // Otherwise there is no 'real' test |
2939 | if (!check_semantics) |
2940 | return; |
2941 | |
2942 | const int *x = precalced_comparedata; |
2943 | |
2944 | QString msg = "semantic problem at " + QString(__FILE__) + " (" + sline + ")" ; |
2945 | msg += "\nThe *expected* result was : {" + istr(n: x[0]) + istr(n: x[1]) + istr(n: x[2]) + istr(n: x[3]) |
2946 | + istr(n: x[4]) + istr(n: x[5]) + istr(n: x[6], comma: false) + QLatin1Char('}'); |
2947 | msg += "\nThe calculated result was : {" ; |
2948 | msg += istr(n: chk_visual) + istr(n: chk_logical) + istr(n: chk_sizes) + istr(n: chk_hidden_size) |
2949 | + istr(n: chk_lookup_visual) + istr(n: chk_lookup_logical) + istr(n: header_lenght, comma: false) + "};" ; |
2950 | |
2951 | const QScopedArrayPointer<char> holder(QTest::toString(str: msg)); |
2952 | const auto verifytext = holder.data(); |
2953 | |
2954 | QVERIFY2(chk_visual == x[0], verifytext); |
2955 | QVERIFY2(chk_logical == x[1], verifytext); |
2956 | QVERIFY2(chk_sizes == x[2], verifytext); |
2957 | QVERIFY2(chk_hidden_size == x[3], verifytext); |
2958 | QVERIFY2(chk_lookup_visual == x[4], verifytext); |
2959 | QVERIFY2(chk_lookup_logical == x[5], verifytext); |
2960 | QVERIFY2(header_lenght == x[6], verifytext); |
2961 | } |
2962 | |
2963 | void tst_QHeaderView::(bool also_use_reset_model) |
2964 | { |
2965 | QTest::addColumn<bool>(name: "updates_enabled" ); |
2966 | QTest::addColumn<bool>(name: "special_prepare" ); |
2967 | QTest::addColumn<bool>(name: "reset_model" ); |
2968 | |
2969 | if (also_use_reset_model) { |
2970 | QTest::newRow(dataTag: "no_updates+normal+reset" ) << false << false << true; |
2971 | QTest::newRow(dataTag: "hasupdates+normal+reset" ) << true << false << true; |
2972 | QTest::newRow(dataTag: "no_updates+special+reset" ) << false << true << true; |
2973 | QTest::newRow(dataTag: "hasupdates+special+reset" ) << true << true << true; |
2974 | } |
2975 | |
2976 | QTest::newRow(dataTag: "no_updates+normal" ) << false << false << false; |
2977 | QTest::newRow(dataTag: "hasupdates+normal" ) << true << false << false; |
2978 | QTest::newRow(dataTag: "no_updates+special" ) << false << true << false; |
2979 | QTest::newRow(dataTag: "hasupdates+special" ) << true << true << false; |
2980 | } |
2981 | |
2982 | void tst_QHeaderView::() |
2983 | { |
2984 | m_tableview->setVerticalHeader(view); |
2985 | |
2986 | QFETCH(bool, updates_enabled); |
2987 | QFETCH(bool, special_prepare); |
2988 | QFETCH(bool, reset_model); |
2989 | |
2990 | m_using_reset_model = reset_model; |
2991 | m_special_prepare = special_prepare; |
2992 | |
2993 | if (m_using_reset_model) { |
2994 | XResetModel *m = new XResetModel(); |
2995 | m_tableview->setModel(m); |
2996 | delete model; |
2997 | model = m; |
2998 | } else { |
2999 | m_tableview->setModel(model); |
3000 | } |
3001 | |
3002 | const int default_section_size = 25; |
3003 | view->setDefaultSectionSize(default_section_size); // Important - otherwise there will be semantic changes |
3004 | |
3005 | model->clear(); |
3006 | |
3007 | if (special_prepare) { |
3008 | |
3009 | for (int u = 0; u <= rowcount; ++u) // ensures fragmented spans in e.g Qt 4.7 |
3010 | model->setRowCount(u); |
3011 | |
3012 | model->setColumnCount(colcount); |
3013 | view->swapSections(first: 0, second: rowcount - 1); |
3014 | view->swapSections(first: 0, second: rowcount - 1); // No real change - setup visual and log-indexes |
3015 | view->hideSection(alogicalIndex: rowcount - 1); |
3016 | view->showSection(alogicalIndex: rowcount - 1); // No real change - (maybe init hidden vector) |
3017 | } else { |
3018 | model->setColumnCount(colcount); |
3019 | model->setRowCount(rowcount); |
3020 | } |
3021 | |
3022 | QString s; |
3023 | for (int i = 0; i < model->rowCount(); ++i) { |
3024 | model->setData(index: model->index(row: i, column: 0), value: QVariant(i)); |
3025 | s.setNum(n: i); |
3026 | s += QLatin1Char('.'); |
3027 | s += 'a' + (i % 25); |
3028 | model->setData(index: model->index(row: i, column: 1), value: QVariant(s)); |
3029 | } |
3030 | m_tableview->setUpdatesEnabled(updates_enabled); |
3031 | view->blockSignals(b: block_some_signals); |
3032 | timer.start(); |
3033 | } |
3034 | |
3035 | void tst_QHeaderView::() |
3036 | { |
3037 | additionalInit(); |
3038 | |
3039 | view->swapSections(first: 4, second: 9); // Make sure that visual and logical Indexes are not just the same. |
3040 | |
3041 | int check1 = 0; |
3042 | int check2 = 0; |
3043 | for (int u = 0; u < model->rowCount(); ++u) { |
3044 | view->resizeSection(logicalIndex: u, size: 10 + u % 30); |
3045 | int v = view->visualIndexAt(position: u * 29); |
3046 | view->visualIndexAt(position: u * 29); |
3047 | check1 += v; |
3048 | check2 += u * v; |
3049 | } |
3050 | view->resizeSection(logicalIndex: 0, size: 0); // Make sure that we have a 0 size section - before the result set |
3051 | view->setSectionHidden(logicalIndex: 6, hide: true); // Make sure we have a real hidden section before result set |
3052 | |
3053 | //qDebug() << "logicalIndexAtTest" << check1 << check2; |
3054 | const int precalced_check1 = 106327; |
3055 | const int precalced_check2 = 29856418; |
3056 | QCOMPARE(precalced_check1, check1); |
3057 | QCOMPARE(precalced_check2, check2); |
3058 | |
3059 | const int precalced_results[] = { 1145298384, -1710423344, -650981936, 372919464, -1544372176, -426463328, 12124 }; |
3060 | calculateAndCheck(__LINE__, precalced_comparedata: precalced_results); |
3061 | } |
3062 | |
3063 | void tst_QHeaderView::() |
3064 | { |
3065 | additionalInit(); |
3066 | |
3067 | view->swapSections(first: 4, second: 9); // Make sure that visual and logical Indexes are not just the same. |
3068 | int check1 = 0; |
3069 | int check2 = 0; |
3070 | |
3071 | for (int u = 0; u < model->rowCount(); ++u) { |
3072 | view->resizeSection(logicalIndex: u, size: 3 + u % 17); |
3073 | int v = view->visualIndexAt(position: u * 29); |
3074 | check1 += v; |
3075 | check2 += u * v; |
3076 | } |
3077 | |
3078 | view->resizeSection(logicalIndex: 1, size: 0); // Make sure that we have a 0 size section - before the result set |
3079 | view->setSectionHidden(logicalIndex: 5, hide: true); // Make sure we have a real hidden section before result set |
3080 | |
3081 | //qDebug() << "visualIndexAtTest" << check1 << check2; |
3082 | const int precalced_check1 = 72665; |
3083 | const int precalced_check2 = 14015890; |
3084 | QCOMPARE(precalced_check1, check1); |
3085 | QCOMPARE(precalced_check2, check2); |
3086 | |
3087 | const int precalced_results[] = { 1145298384, -1710423344, -1457520212, 169223959, 557466160, -324939600, 5453 }; |
3088 | calculateAndCheck(__LINE__, precalced_comparedata: precalced_results); |
3089 | } |
3090 | |
3091 | void tst_QHeaderView::() |
3092 | { |
3093 | additionalInit(); |
3094 | |
3095 | for (int u = model->rowCount(); u >= 0; --u) |
3096 | if (u % 8 != 0) |
3097 | view->hideSection(alogicalIndex: u); |
3098 | |
3099 | for (int u = model->rowCount(); u >= 0; --u) |
3100 | if (u % 3 == 0) |
3101 | view->showSection(alogicalIndex: u); |
3102 | |
3103 | view->setSectionHidden(logicalIndex: model->rowCount(), hide: true); // invalid hide (should be ignored) |
3104 | view->setSectionHidden(logicalIndex: -1, hide: true); // invalid hide (should be ignored) |
3105 | |
3106 | const int precalced_results[] = { -1523279360, -1523279360, -1321506816, 2105322423, 1879611280, 1879611280, 5225 }; |
3107 | calculateAndCheck(__LINE__, precalced_comparedata: precalced_results); |
3108 | } |
3109 | |
3110 | void tst_QHeaderView::() |
3111 | { |
3112 | additionalInit(); |
3113 | |
3114 | for (int u = 0; u < rowcount / 2; ++u) |
3115 | view->swapSections(first: u, second: rowcount - u - 1); |
3116 | |
3117 | for (int u = 0; u < rowcount; u += 2) |
3118 | view->swapSections(first: u, second: u + 1); |
3119 | |
3120 | view->swapSections(first: 0, second: model->rowCount()); // invalid swapsection (should be ignored) |
3121 | |
3122 | const int precalced_results[] = { -1536450048, -1774641430, -1347156568, 1, 1719705216, -240077576, 12500 }; |
3123 | calculateAndCheck(__LINE__, precalced_comparedata: precalced_results); |
3124 | } |
3125 | |
3126 | void tst_QHeaderView::() |
3127 | { |
3128 | additionalInit(); |
3129 | |
3130 | for (int u = 1; u < 5; ++u) |
3131 | view->moveSection(from: u, to: model->rowCount() - u); |
3132 | |
3133 | view->moveSection(from: 2, to: model->rowCount() / 2); |
3134 | view->moveSection(from: 0, to: 10); |
3135 | view->moveSection(from: 0, to: model->rowCount() - 10); |
3136 | |
3137 | view->moveSection(from: 0, to: model->rowCount()); // invalid move (should be ignored) |
3138 | |
3139 | const int precalced_results[] = { 645125952, 577086896, -1347156568, 1, 1719705216, 709383416, 12500 }; |
3140 | calculateAndCheck(__LINE__, precalced_comparedata: precalced_results); |
3141 | } |
3142 | |
3143 | void tst_QHeaderView::() |
3144 | { |
3145 | additionalInit(); |
3146 | |
3147 | view->hideSection(alogicalIndex: rowcount / 2); |
3148 | int restore_to = view->defaultSectionSize(); |
3149 | view->setDefaultSectionSize(restore_to + 5); |
3150 | |
3151 | const int precalced_results[] = { -1523279360, -1523279360, -1739688320, -1023807777, 997629696, 997629696, 14970 }; |
3152 | calculateAndCheck(__LINE__, precalced_comparedata: precalced_results); |
3153 | |
3154 | view->setDefaultSectionSize(restore_to); |
3155 | } |
3156 | |
3157 | void tst_QHeaderView::() |
3158 | { |
3159 | additionalInit(); |
3160 | |
3161 | view->swapSections(first: 0, second: 5); |
3162 | model->removeRows(row: 0, count: 1); // remove one row |
3163 | model->removeRows(row: 4, count: 10); |
3164 | model->setRowCount(model->rowCount() / 2 - 1); |
3165 | |
3166 | if (m_using_reset_model) { |
3167 | const int precalced_results[] = { 1741224292, -135269187, -569519837, 1, 1719705216, -1184395000, 6075 }; |
3168 | calculateAndCheck(__LINE__, precalced_comparedata: precalced_results); |
3169 | } else { |
3170 | const int precalced_results[] = { 289162397, 289162397, -569519837, 1, 1719705216, 1719705216, 6075 }; |
3171 | calculateAndCheck(__LINE__, precalced_comparedata: precalced_results); |
3172 | } |
3173 | } |
3174 | |
3175 | void tst_QHeaderView::() |
3176 | { |
3177 | additionalInit(); |
3178 | |
3179 | view->swapSections(first: 0, second: model->rowCount() - 1); |
3180 | model->insertRows(row: 0, count: 1); // insert one row |
3181 | model->insertRows(row: 4, count: 10); |
3182 | model->setRowCount(model->rowCount() * 2 - 1); |
3183 | |
3184 | if (m_using_reset_model) { |
3185 | const int precalced_results[] = { 2040508069, -1280266538, -150350734, 1, 1719705216, 1331312784, 25525 }; |
3186 | calculateAndCheck(__LINE__, precalced_comparedata: precalced_results); |
3187 | } else { |
3188 | const int precalced_results[] = { -1909447021, 339092083, -150350734, 1, 1719705216, -969712728, 25525 }; |
3189 | calculateAndCheck(__LINE__, precalced_comparedata: precalced_results); |
3190 | } |
3191 | } |
3192 | |
3193 | void tst_QHeaderView::() |
3194 | { |
3195 | additionalInit(); |
3196 | |
3197 | model->setRowCount(model->rowCount() + 10); |
3198 | |
3199 | for (int u = 0; u < model->rowCount(); u += 2) |
3200 | view->swapSections(first: u, second: u + 1); |
3201 | |
3202 | view->moveSection(from: 0, to: 5); |
3203 | |
3204 | for (int u = model->rowCount(); u >= 0; --u) { |
3205 | if (u % 5 != 0) { |
3206 | view->hideSection(alogicalIndex: u); |
3207 | QVERIFY(view->isSectionHidden(u)); |
3208 | } |
3209 | if (u % 3 != 0) { |
3210 | view->showSection(alogicalIndex: u); |
3211 | QVERIFY(!view->isSectionHidden(u)); |
3212 | } |
3213 | } |
3214 | |
3215 | model->insertRows(row: 3, count: 7); |
3216 | model->removeRows(row: 8, count: 3); |
3217 | model->setRowCount(model->rowCount() - 10); |
3218 | |
3219 | // the upper is not visible (when m_using_reset_model is true) |
3220 | // the lower 11 are modified due to insert/removeRows |
3221 | for (int u = model->rowCount() - 1; u >= 11; --u) { |
3222 | // when using reset, the hidden rows will *not* move |
3223 | const int calcMod = m_using_reset_model ? u : u - 4; // 7 added, 3 removed |
3224 | if (calcMod % 5 != 0 && calcMod % 3 == 0) { |
3225 | QVERIFY(view->isSectionHidden(u)); |
3226 | } |
3227 | if (calcMod % 3 != 0) { |
3228 | QVERIFY(!view->isSectionHidden(u)); |
3229 | } |
3230 | } |
3231 | if (m_using_reset_model) { |
3232 | const int precalced_results[] = { 898296472, 337096378, -543340640, -1964432121, -1251526424, -568618976, 9250 }; |
3233 | calculateAndCheck(__LINE__, precalced_comparedata: precalced_results); |
3234 | } else { |
3235 | const int precalced_results[] = { 1911338224, 1693514365, -613398968, -1912534953, 1582159424, -1851079000, 9300 }; |
3236 | calculateAndCheck(__LINE__, precalced_comparedata: precalced_results); |
3237 | } |
3238 | } |
3239 | |
3240 | void tst_QHeaderView::() |
3241 | { |
3242 | additionalInit(); |
3243 | |
3244 | QModelIndex idx = model->index(row: 2, column: 2); |
3245 | model->setData(index: idx, value: QVariant("A normal string" )); |
3246 | |
3247 | idx = model->index(row: 1, column: 3); |
3248 | model->setData(index: idx, value: QVariant("A normal longer string to test resize" )); |
3249 | |
3250 | QHeaderView *hh = m_tableview->horizontalHeader(); |
3251 | hh->resizeSections(mode: QHeaderView::ResizeToContents); |
3252 | QVERIFY(hh->sectionSize(3) > hh->sectionSize(2)); |
3253 | |
3254 | for (int u = 0; u < 10; ++u) |
3255 | view->resizeSection(logicalIndex: u, size: 1); |
3256 | |
3257 | view->resizeSections(mode: QHeaderView::ResizeToContents); |
3258 | QVERIFY(view->sectionSize(1) > 1); |
3259 | QVERIFY(view->sectionSize(2) > 1); |
3260 | |
3261 | // Check minimum section size |
3262 | hh->setMinimumSectionSize(150); |
3263 | model->setData(index: idx, value: QVariant("i" )); |
3264 | hh->resizeSections(mode: QHeaderView::ResizeToContents); |
3265 | QCOMPARE(hh->sectionSize(3), 150); |
3266 | hh->setMinimumSectionSize(-1); |
3267 | |
3268 | // Check maximumSection size |
3269 | hh->setMaximumSectionSize(200); |
3270 | model->setData(index: idx, value: QVariant("This is a even longer string that is expected to be more than 200 pixels" )); |
3271 | hh->resizeSections(mode: QHeaderView::ResizeToContents); |
3272 | QCOMPARE(hh->sectionSize(3), 200); |
3273 | hh->setMaximumSectionSize(-1); |
3274 | |
3275 | view->setDefaultSectionSize(25); // To make sure our precalced data are correct. We do not know font height etc. |
3276 | |
3277 | const int precalced_results[] = { -1523279360, -1523279360, -1347156568, 1, 1719705216, 1719705216, 12500 }; |
3278 | calculateAndCheck(__LINE__, precalced_comparedata: precalced_results); |
3279 | } |
3280 | |
3281 | void tst_QHeaderView::() |
3282 | { |
3283 | #ifndef QT_NO_DATASTREAM |
3284 | m_tableview->setVerticalHeader(view); |
3285 | m_tableview->setModel(model); |
3286 | view->setDefaultSectionSize(25); |
3287 | view->hideSection(alogicalIndex: 2); |
3288 | view->swapSections(first: 1, second: 2); |
3289 | |
3290 | QByteArray s = view->saveState(); |
3291 | view->swapSections(first: 1, second: 2); |
3292 | view->setDefaultSectionSize(30); // To make sure our precalced data are correct. |
3293 | view->restoreState(state: s); |
3294 | |
3295 | const int precalced_results[] = { -1116614432, -1528653200, -1914165644, 244434607, -1111214068, 750357900, 75}; |
3296 | calculateAndCheck(__LINE__, precalced_comparedata: precalced_results); |
3297 | #else |
3298 | QSKIP("Datastream required for testStreamWithHide. Skipping this test." ); |
3299 | #endif |
3300 | } |
3301 | |
3302 | void tst_QHeaderView::() |
3303 | { |
3304 | topLevel->show(); |
3305 | QVERIFY(QTest::qWaitForWindowExposed(topLevel)); |
3306 | |
3307 | protected_QHeaderView * = static_cast<protected_QHeaderView *>(view); |
3308 | |
3309 | TestStyle proxy; |
3310 | header->setStyle(&proxy); |
3311 | |
3312 | QImage image(1, 1, QImage::Format_ARGB32); |
3313 | QPainter p(&image); |
3314 | |
3315 | // 0, 1, 2, 3 |
3316 | header->paintSection(painter: &p, rect: view->rect(), logicalIndex: 0); |
3317 | QCOMPARE(proxy.lastPosition, QStyleOptionHeader::Beginning); |
3318 | header->paintSection(painter: &p, rect: view->rect(), logicalIndex: 1); |
3319 | QCOMPARE(proxy.lastPosition, QStyleOptionHeader::Middle); |
3320 | header->paintSection(painter: &p, rect: view->rect(), logicalIndex: 2); |
3321 | QCOMPARE(proxy.lastPosition, QStyleOptionHeader::Middle); |
3322 | header->paintSection(painter: &p, rect: view->rect(), logicalIndex: 3); |
3323 | QCOMPARE(proxy.lastPosition, QStyleOptionHeader::End); |
3324 | |
3325 | // (0),2,1,3 |
3326 | view->setSectionHidden(logicalIndex: 0, hide: true); |
3327 | view->swapSections(first: 1, second: 2); |
3328 | header->paintSection(painter: &p, rect: view->rect(), logicalIndex: 1); |
3329 | QCOMPARE(proxy.lastPosition, QStyleOptionHeader::Middle); |
3330 | header->paintSection(painter: &p, rect: view->rect(), logicalIndex: 2); |
3331 | QCOMPARE(proxy.lastPosition, QStyleOptionHeader::Beginning); |
3332 | header->paintSection(painter: &p, rect: view->rect(), logicalIndex: 3); |
3333 | QCOMPARE(proxy.lastPosition, QStyleOptionHeader::End); |
3334 | |
3335 | // (1),2,0,(3) |
3336 | view->setSectionHidden(logicalIndex: 3, hide: true); |
3337 | view->setSectionHidden(logicalIndex: 0, hide: false); |
3338 | view->setSectionHidden(logicalIndex: 1, hide: true); |
3339 | view->swapSections(first: 0, second: 1); |
3340 | header->paintSection(painter: &p, rect: view->rect(), logicalIndex: 0); |
3341 | QCOMPARE(proxy.lastPosition, QStyleOptionHeader::End); |
3342 | header->paintSection(painter: &p, rect: view->rect(), logicalIndex: 2); |
3343 | QCOMPARE(proxy.lastPosition, QStyleOptionHeader::Beginning); |
3344 | |
3345 | // (1),2,(0),(3) |
3346 | view->setSectionHidden(logicalIndex: 0, hide: true); |
3347 | header->paintSection(painter: &p, rect: view->rect(), logicalIndex: 2); |
3348 | QCOMPARE(proxy.lastPosition, QStyleOptionHeader::OnlyOneSection); |
3349 | } |
3350 | |
3351 | void tst_QHeaderView::() |
3352 | { |
3353 | QTreeView treeView; |
3354 | QStandardItemModel *model = new QStandardItemModel(&treeView); |
3355 | model->appendRow(aitem: new QStandardItem("QTBUG-48543" )); |
3356 | treeView.setModel(model); |
3357 | treeView.header()->sizeHintForColumn(column: 0); |
3358 | treeView.header()->sizeHintForRow(row: 0); |
3359 | } |
3360 | |
3361 | void tst_QHeaderView::stretchAndRestoreLastSection() |
3362 | { |
3363 | QStandardItemModel m(10, 10); |
3364 | QTableView tv; |
3365 | tv.setModel(&m); |
3366 | tv.showMaximized(); |
3367 | |
3368 | const int minimumSectionSize = 20; |
3369 | const int defaultSectionSize = 30; |
3370 | const int someOtherSectionSize = 40; |
3371 | const int biggerSizeThanAnySection = 50; |
3372 | |
3373 | QVERIFY(QTest::qWaitForWindowExposed(&tv)); |
3374 | |
3375 | QHeaderView & = *tv.horizontalHeader(); |
3376 | // set minimum size before resizeSections() is called |
3377 | // which is done inside setStretchLastSection |
3378 | header.setMinimumSectionSize(minimumSectionSize); |
3379 | header.setDefaultSectionSize(defaultSectionSize); |
3380 | header.resizeSection(logicalIndex: 9, size: someOtherSectionSize); |
3381 | header.setStretchLastSection(true); |
3382 | |
3383 | // Default last section is larger |
3384 | QCOMPARE(header.sectionSize(8), defaultSectionSize); |
3385 | QVERIFY(header.sectionSize(9) >= biggerSizeThanAnySection); |
3386 | |
3387 | // Moving last section away (restore old last section 9 - and make 8 larger) |
3388 | header.swapSections(first: 9, second: 8); |
3389 | QCOMPARE(header.sectionSize(9), someOtherSectionSize); |
3390 | QVERIFY(header.sectionSize(8) >= biggerSizeThanAnySection); |
3391 | |
3392 | // Make section 9 the large one again |
3393 | header.hideSection(alogicalIndex: 8); |
3394 | QVERIFY(header.sectionSize(9) >= biggerSizeThanAnySection); |
3395 | |
3396 | // Show section 8 again - and make that one the last one. |
3397 | header.showSection(alogicalIndex: 8); |
3398 | QVERIFY(header.sectionSize(8) > biggerSizeThanAnySection); |
3399 | QCOMPARE(header.sectionSize(9), someOtherSectionSize); |
3400 | |
3401 | // Swap the sections so the logical indexes are equal to visible indexes again. |
3402 | header.moveSection(from: 9, to: 8); |
3403 | QCOMPARE(header.sectionSize(8), defaultSectionSize); |
3404 | QVERIFY(header.sectionSize(9) >= biggerSizeThanAnySection); |
3405 | |
3406 | // Append sections |
3407 | m.setColumnCount(15); |
3408 | QCOMPARE(header.sectionSize(9), someOtherSectionSize); |
3409 | QVERIFY(header.sectionSize(14) >= biggerSizeThanAnySection); |
3410 | |
3411 | // Truncate sections (remove sections with the last section) |
3412 | m.setColumnCount(10); |
3413 | QVERIFY(header.sectionSize(9) >= biggerSizeThanAnySection); |
3414 | for (int u = 0; u < 9; ++u) |
3415 | QCOMPARE(header.sectionSize(u), defaultSectionSize); |
3416 | |
3417 | // Insert sections |
3418 | m.insertColumns(column: 2, count: 2); |
3419 | QCOMPARE(header.sectionSize(9), defaultSectionSize); |
3420 | QCOMPARE(header.sectionSize(10), defaultSectionSize); |
3421 | QVERIFY(header.sectionSize(11) >= biggerSizeThanAnySection); |
3422 | |
3423 | // Append an extra section and check restore |
3424 | m.setColumnCount(m.columnCount() + 1); |
3425 | QCOMPARE(header.sectionSize(11), someOtherSectionSize); |
3426 | QVERIFY(header.sectionSize(12) >= biggerSizeThanAnySection); |
3427 | |
3428 | // Remove some sections but not the last one. |
3429 | m.removeColumns(column: 2, count: 2); |
3430 | QCOMPARE(header.sectionSize(9), someOtherSectionSize); |
3431 | QVERIFY(header.sectionSize(10) >= biggerSizeThanAnySection); |
3432 | for (int u = 0; u < 9; ++u) |
3433 | QCOMPARE(header.sectionSize(u), defaultSectionSize); |
3434 | |
3435 | // Empty the header and start over with some more tests |
3436 | m.setColumnCount(0); |
3437 | m.setColumnCount(10); |
3438 | QVERIFY(header.sectionSize(9) >= biggerSizeThanAnySection); |
3439 | |
3440 | // Check resize of the last section |
3441 | header.resizeSection(logicalIndex: 9, size: someOtherSectionSize); |
3442 | QVERIFY(header.sectionSize(9) >= biggerSizeThanAnySection); // It should still be stretched |
3443 | header.swapSections(first: 9, second: 8); |
3444 | QCOMPARE(header.sectionSize(9), someOtherSectionSize); |
3445 | |
3446 | // Restore the order |
3447 | header.swapSections(first: 9, second: 8); |
3448 | QVERIFY(header.sectionSize(9) >= biggerSizeThanAnySection); |
3449 | |
3450 | // Hide the last 3 sections and test stretch last section on swap/move |
3451 | // when hidden sections with a larger visual index exists. |
3452 | header.hideSection(alogicalIndex: 7); |
3453 | header.hideSection(alogicalIndex: 8); |
3454 | header.hideSection(alogicalIndex: 9); |
3455 | QVERIFY(header.sectionSize(6) >= biggerSizeThanAnySection); |
3456 | header.moveSection(from: 2, to: 7); |
3457 | QVERIFY(header.sectionSize(2) >= biggerSizeThanAnySection); |
3458 | header.swapSections(first: 1, second: 8); |
3459 | QCOMPARE(header.sectionSize(2), defaultSectionSize); |
3460 | QVERIFY(header.sectionSize(1) >= biggerSizeThanAnySection); |
3461 | |
3462 | // Inserting sections 2 |
3463 | m.setColumnCount(0); |
3464 | m.setColumnCount(10); |
3465 | header.resizeSection(logicalIndex: 1, size: someOtherSectionSize); |
3466 | header.swapSections(first: 1, second: 9); |
3467 | m.insertColumns(column: 9, count: 2); |
3468 | header.swapSections(first: 1, second: 11); |
3469 | QCOMPARE(header.sectionSize(1), someOtherSectionSize); |
3470 | |
3471 | // Clear and re-add. This triggers a different code path than seColumnCount(0) |
3472 | m.clear(); |
3473 | m.setColumnCount(3); |
3474 | QVERIFY(header.sectionSize(2) >= biggerSizeThanAnySection); |
3475 | |
3476 | // Test import/export of the original (not stretched) sectionSize. |
3477 | m.setColumnCount(0); |
3478 | m.setColumnCount(10); |
3479 | header.resizeSection(logicalIndex: 9, size: someOtherSectionSize); |
3480 | QVERIFY(header.sectionSize(9) >= biggerSizeThanAnySection); |
3481 | QByteArray b = header.saveState(); |
3482 | m.setColumnCount(0); |
3483 | m.setColumnCount(10); |
3484 | header.restoreState(state: b); |
3485 | header.setStretchLastSection(false); |
3486 | QCOMPARE(header.sectionSize(9), someOtherSectionSize); |
3487 | } |
3488 | |
3489 | void tst_QHeaderView::() |
3490 | { |
3491 | QTest::addColumn<bool>(name: "stretchLastSection" ); |
3492 | QTest::addRow(format: "stretched" ) << true; |
3493 | QTest::addRow(format: "not stretched" ) << false; |
3494 | } |
3495 | |
3496 | void tst_QHeaderView::() |
3497 | { |
3498 | QFETCH(bool, stretchLastSection); |
3499 | |
3500 | QStandardItemModel m(5, 5); |
3501 | QTableView tv; |
3502 | tv.setModel(&m); |
3503 | tv.show(); |
3504 | |
3505 | const int sectionSizeMin = 20; |
3506 | const int sectionSizeMax = 40; |
3507 | const int defaultSectionSize = 30; |
3508 | |
3509 | QVERIFY(QTest::qWaitForWindowExposed(&tv)); |
3510 | |
3511 | QHeaderView & = *tv.horizontalHeader(); |
3512 | header.setMinimumSectionSize(sectionSizeMin); |
3513 | header.setMaximumSectionSize(sectionSizeMax); |
3514 | // check bounds for default section size |
3515 | header.setDefaultSectionSize(sectionSizeMin - 1); |
3516 | QCOMPARE(header.defaultSectionSize(), sectionSizeMin); |
3517 | header.setDefaultSectionSize(sectionSizeMax + 1); |
3518 | QCOMPARE(header.defaultSectionSize(), sectionSizeMax); |
3519 | |
3520 | header.setDefaultSectionSize(defaultSectionSize); |
3521 | QCOMPARE(header.defaultSectionSize(), defaultSectionSize); |
3522 | header.setStretchLastSection(stretchLastSection); |
3523 | QCOMPARE(header.stretchLastSection(), stretchLastSection); |
3524 | |
3525 | // check defaults |
3526 | QCOMPARE(header.sectionSize(0), defaultSectionSize); |
3527 | QCOMPARE(header.sectionSize(3), defaultSectionSize); |
3528 | |
3529 | // do not go above maxSectionSize |
3530 | header.resizeSection(logicalIndex: 0, size: sectionSizeMax + 1); |
3531 | QCOMPARE(header.sectionSize(0), sectionSizeMax); |
3532 | |
3533 | // do not go below minSectionSize |
3534 | header.resizeSection(logicalIndex: 0, size: sectionSizeMin - 1); |
3535 | QCOMPARE(header.sectionSize(0), sectionSizeMin); |
3536 | |
3537 | // change section size on max change |
3538 | header.setMinimumSectionSize(sectionSizeMin); |
3539 | header.setMaximumSectionSize(sectionSizeMax); |
3540 | header.resizeSection(logicalIndex: 0, size: sectionSizeMax); |
3541 | QCOMPARE(header.sectionSize(0), sectionSizeMax); |
3542 | header.setMaximumSectionSize(defaultSectionSize); |
3543 | QTRY_COMPARE(header.sectionSize(0), defaultSectionSize); |
3544 | |
3545 | // change section size on min change |
3546 | header.setMinimumSectionSize(sectionSizeMin); |
3547 | header.setMaximumSectionSize(sectionSizeMax); |
3548 | header.resizeSection(logicalIndex: 0, size: sectionSizeMin); |
3549 | QCOMPARE(header.sectionSize(0), sectionSizeMin); |
3550 | header.setMinimumSectionSize(defaultSectionSize); |
3551 | QTRY_COMPARE(header.sectionSize(0), defaultSectionSize); |
3552 | } |
3553 | |
3554 | void tst_QHeaderView::() |
3555 | { |
3556 | QtTestModel model(10, 10); |
3557 | QTableView tv; |
3558 | tv.setModel(&model); |
3559 | tv.show(); |
3560 | QVERIFY(QTest::qWaitForWindowExposed(&tv)); |
3561 | |
3562 | QSize s1 = tv.horizontalHeader()->sizeHint(); |
3563 | model.setMultiLineHeader(true); |
3564 | QSize s2 = tv.horizontalHeader()->sizeHint(); |
3565 | model.setMultiLineHeader(false); |
3566 | QSize s3 = tv.horizontalHeader()->sizeHint(); |
3567 | QCOMPARE(s1, s3); |
3568 | QVERIFY(s1 != s2); |
3569 | } |
3570 | |
3571 | |
3572 | class : public QHeaderView |
3573 | { |
3574 | Q_OBJECT |
3575 | public: |
3576 | using QHeaderView::QHeaderView; |
3577 | QString ; |
3578 | bool = false; |
3579 | protected: |
3580 | bool (QEvent *e) override |
3581 | { |
3582 | if (e->type() == QEvent::StatusTip) { |
3583 | gotStatusTipEvent = true; |
3584 | statusTipText = static_cast<QStatusTipEvent *>(e)->tip(); |
3585 | } |
3586 | return QHeaderView::event(e); |
3587 | } |
3588 | }; |
3589 | |
3590 | void tst_QHeaderView::() |
3591 | { |
3592 | if (QGuiApplication::platformName().startsWith(s: QLatin1String("wayland" ), cs: Qt::CaseInsensitive)) |
3593 | QSKIP("Wayland: This fails. Figure out why." ); |
3594 | |
3595 | StatusTipHeaderView (Qt::Horizontal); |
3596 | QtTestModel model(5, 5); |
3597 | headerView.setModel(&model); |
3598 | headerView.viewport()->setMouseTracking(true); |
3599 | headerView.setGeometry(QRect(QPoint(QApplication::desktop()->geometry().center() - QPoint(250, 250)), |
3600 | QSize(500, 500))); |
3601 | headerView.show(); |
3602 | QApplication::setActiveWindow(&headerView); |
3603 | QVERIFY(QTest::qWaitForWindowActive(&headerView)); |
3604 | |
3605 | // Ensure it is moved away first and then moved to the relevant section |
3606 | QTest::mouseMove(widget: QApplication::desktop(), |
3607 | pos: headerView.rect().bottomLeft() + QPoint(20, 20)); |
3608 | QPoint centerPoint = QRect(headerView.sectionPosition(logicalIndex: 0), 0, |
3609 | headerView.sectionSize(logicalIndex: 0), headerView.height()).center(); |
3610 | QTest::mouseMove(window: headerView.windowHandle(), pos: centerPoint); |
3611 | QTRY_VERIFY(headerView.gotStatusTipEvent); |
3612 | QCOMPARE(headerView.statusTipText, QLatin1String("[0,0,0] -- Header" )); |
3613 | |
3614 | headerView.gotStatusTipEvent = false; |
3615 | headerView.statusTipText.clear(); |
3616 | centerPoint = QRect(headerView.sectionPosition(logicalIndex: 1), 0, |
3617 | headerView.sectionSize(logicalIndex: 1), headerView.height()).center(); |
3618 | QTest::mouseMove(window: headerView.windowHandle(), pos: centerPoint); |
3619 | QTRY_VERIFY(headerView.gotStatusTipEvent); |
3620 | QCOMPARE(headerView.statusTipText, QLatin1String("[0,1,0] -- Header" )); |
3621 | } |
3622 | |
3623 | void tst_QHeaderView::testRemovingColumnsViaLayoutChanged() |
3624 | { |
3625 | const int persistentSectionSize = 101; |
3626 | |
3627 | QtTestModel model(5, 5); |
3628 | view->setModel(&model); |
3629 | for (int i = 0; i < model.cols; ++i) |
3630 | view->resizeSection(logicalIndex: i, size: persistentSectionSize + i); |
3631 | model.cleanup(); // down to 3 via layoutChanged (not columnsRemoved) |
3632 | for (int j = 0; j < model.cols; ++j) |
3633 | QCOMPARE(view->sectionSize(j), persistentSectionSize + j); |
3634 | // The main point of this test is that the section-size restoring code didn't go out of bounds. |
3635 | } |
3636 | |
3637 | void tst_QHeaderView::testModelMovingColumns() |
3638 | { |
3639 | QtTestModel model(10, 10); |
3640 | QHeaderView hv(Qt::Horizontal); |
3641 | hv.setModel(&model); |
3642 | hv.resizeSections(mode: QHeaderView::ResizeToContents); |
3643 | hv.show(); |
3644 | |
3645 | QPersistentModelIndex index3 = model.index(row: 0, column: 3); |
3646 | model.moveColumn(from: 3, to: 1); |
3647 | QCOMPARE(index3.column(), 1); |
3648 | } |
3649 | |
3650 | QTEST_MAIN(tst_QHeaderView) |
3651 | #include "tst_qheaderview.moc" |
3652 | |