1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the test suite of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:GPL-EXCEPT$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU
19** General Public License version 3 as published by the Free Software
20** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
21** included in the packaging of this file. Please review the following
22** information to ensure the GNU General Public License requirements will
23** be met: https://www.gnu.org/licenses/gpl-3.0.html.
24**
25** $QT_END_LICENSE$
26**
27****************************************************************************/
28
29
30#include <QtTest/QtTest>
31#include <qtabwidget.h>
32#include <qtabbar.h>
33#include <qdebug.h>
34#include <qapplication.h>
35#include <qlabel.h>
36#include <QtWidgets/qboxlayout.h>
37
38#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
39# include <qt_windows.h>
40#define Q_CHECK_PAINTEVENTS \
41 if (::SwitchDesktop(::GetThreadDesktop(::GetCurrentThreadId())) == 0) \
42 QSKIP("desktop is not visible, this test would fail");
43#else
44#define Q_CHECK_PAINTEVENTS
45#endif
46
47class QTabWidgetChild:public QTabWidget {
48 public:
49 QTabWidgetChild():tabCount(0) {
50 QVERIFY(tabBar() != NULL);
51 QWidget *w = new QWidget;
52 int index = addTab(widget: w, "test");
53 QCOMPARE(tabCount, 1);
54 removeTab(index);
55 QCOMPARE(tabCount, 0);
56
57 // Test bad arguments
58 // This will assert, so don't do it :)
59 //setTabBar(NULL);
60 };
61
62 protected:
63 virtual void tabInserted(int /*index */ ) {
64 tabCount++;
65 };
66 virtual void tabRemoved(int /*index */ ) {
67 tabCount--;
68 };
69 int tabCount;
70};
71
72class tst_QTabWidget:public QObject {
73 Q_OBJECT
74
75private slots:
76 void init();
77 void cleanup();
78
79 void getSetCheck();
80 void testChild();
81 void addRemoveTab();
82 void tabPosition();
83 void tabEnabled();
84 void tabHidden();
85 void tabText();
86 void tabShape();
87 void tabTooltip();
88 void tabIcon();
89 void indexOf();
90 void currentWidget();
91 void currentIndex();
92 void cornerWidget();
93 void removeTab();
94 void clear();
95 void keyboardNavigation();
96 void paintEventCount();
97 void minimumSizeHint();
98 void heightForWidth_data();
99 void heightForWidth();
100 void tabBarClicked();
101 void moveCurrentTab();
102 void autoHide();
103
104 private:
105 int addPage();
106 void removePage(int index);
107 QTabWidget *tw;
108};
109
110// Testing get/set functions
111void tst_QTabWidget::getSetCheck()
112{
113 QTabWidget obj1;
114 QWidget *w1 = new QWidget;
115 QWidget *w2 = new QWidget;
116 QWidget *w3 = new QWidget;
117 QWidget *w4 = new QWidget;
118 QWidget *w5 = new QWidget;
119
120 obj1.addTab(widget: w1, "Page 1");
121 obj1.addTab(widget: w2, "Page 2");
122 obj1.addTab(widget: w3, "Page 3");
123 obj1.addTab(widget: w4, "Page 4");
124 obj1.addTab(widget: w5, "Page 5");
125
126 // TabShape QTabWidget::tabShape()
127 // void QTabWidget::setTabShape(TabShape)
128 obj1.setTabShape(QTabWidget::TabShape(QTabWidget::Rounded));
129 QCOMPARE(QTabWidget::TabShape(QTabWidget::Rounded), obj1.tabShape());
130 obj1.setTabShape(QTabWidget::TabShape(QTabWidget::Triangular));
131 QCOMPARE(QTabWidget::TabShape(QTabWidget::Triangular), obj1.tabShape());
132
133 // int QTabWidget::currentIndex()
134 // void QTabWidget::setCurrentIndex(int)
135 obj1.setCurrentIndex(0);
136 QCOMPARE(0, obj1.currentIndex());
137 obj1.setCurrentIndex(INT_MIN);
138 QCOMPARE(0, obj1.currentIndex());
139 obj1.setCurrentIndex(INT_MAX);
140 QCOMPARE(0, obj1.currentIndex());
141 obj1.setCurrentIndex(4);
142 QCOMPARE(4, obj1.currentIndex());
143
144 // QWidget * QTabWidget::currentWidget()
145 // void QTabWidget::setCurrentWidget(QWidget *)
146 obj1.setCurrentWidget(w1);
147 QCOMPARE(w1, obj1.currentWidget());
148 obj1.setCurrentWidget(w5);
149 QCOMPARE(w5, obj1.currentWidget());
150 obj1.setCurrentWidget((QWidget *)0);
151 QCOMPARE(w5, obj1.currentWidget()); // current not changed
152}
153
154void tst_QTabWidget::init()
155{
156 tw = new QTabWidget(0);
157 QCOMPARE(tw->count(), 0);
158 QCOMPARE(tw->currentIndex(), -1);
159 QVERIFY(!tw->currentWidget());
160}
161
162void tst_QTabWidget::cleanup()
163{
164 delete tw;
165 tw = 0;
166}
167
168void tst_QTabWidget::testChild()
169{
170 QTabWidgetChild t;
171}
172
173#define LABEL "TEST"
174#define TIP "TIP"
175int tst_QTabWidget::addPage()
176{
177 QWidget *w = new QWidget();
178 return tw->addTab(widget: w, LABEL);
179}
180
181void tst_QTabWidget::removePage(int index)
182{
183 QWidget *w = tw->widget(index);
184 tw->removeTab(index);
185 delete w;
186}
187
188/**
189 * Tests:
190 * addTab(...) which really calls -> insertTab(...)
191 * widget(...)
192 * removeTab(...);
193 * If this fails then many others probably will too.
194 */
195void tst_QTabWidget::addRemoveTab()
196{
197 // Test bad arguments
198 tw->addTab(NULL, LABEL);
199 QCOMPARE(tw->count(), 0);
200 tw->removeTab(index: -1);
201 QCOMPARE(tw->count(), 0);
202 QVERIFY(!tw->widget(-1));
203
204 QWidget *w = new QWidget();
205 int index = tw->addTab(widget: w, LABEL);
206 // return value
207 QCOMPARE(tw->indexOf(w), index);
208
209 QCOMPARE(tw->count(), 1);
210 QCOMPARE(tw->widget(index), w);
211 QCOMPARE(tw->tabText(index), QString(LABEL));
212
213 removePage(index);
214 QCOMPARE(tw->count(), 0);
215}
216
217void tst_QTabWidget::tabPosition()
218{
219 tw->setTabPosition(QTabWidget::North);
220 QCOMPARE(tw->tabPosition(), QTabWidget::North);
221 tw->setTabPosition(QTabWidget::South);
222 QCOMPARE(tw->tabPosition(), QTabWidget::South);
223 tw->setTabPosition(QTabWidget::East);
224 QCOMPARE(tw->tabPosition(), QTabWidget::East);
225 tw->setTabPosition(QTabWidget::West);
226 QCOMPARE(tw->tabPosition(), QTabWidget::West);
227}
228
229void tst_QTabWidget::tabEnabled()
230{
231 // Test bad arguments
232 QVERIFY(!tw->isTabEnabled(-1));
233 tw->setTabEnabled(index: -1, enabled: false);
234
235 int index = addPage();
236
237 tw->setTabEnabled(index, enabled: true);
238 QVERIFY(tw->isTabEnabled(index));
239 QVERIFY(tw->widget(index)->isEnabled());
240 tw->setTabEnabled(index, enabled: false);
241 QVERIFY(!tw->isTabEnabled(index));
242 QVERIFY(!tw->widget(index)->isEnabled());
243 tw->setTabEnabled(index, enabled: true);
244 QVERIFY(tw->isTabEnabled(index));
245 QVERIFY(tw->widget(index)->isEnabled());
246
247 removePage(index);
248}
249
250void tst_QTabWidget::tabHidden()
251{
252 // Test bad arguments
253 QVERIFY(!tw->isTabVisible(-1));
254 tw->setTabVisible(index: -1, visible: false);
255 QVERIFY(!tw->isTabVisible(tw->count()));
256 tw->setTabVisible(index: tw->count(), visible: false);
257
258 const int index = addPage();
259
260 tw->setTabVisible(index, visible: true);
261 QVERIFY(tw->isTabVisible(index));
262 tw->setTabVisible(index, visible: false);
263 QVERIFY(!tw->isTabVisible(index));
264 tw->setTabVisible(index, visible: true);
265 QVERIFY(tw->isTabVisible(index));
266
267 removePage(index);
268
269 for (int i = 0; i < tw->count(); ++i) {
270 QVERIFY(tw->isTabVisible(i));
271 }
272}
273
274void tst_QTabWidget::tabText()
275{
276 // Test bad arguments
277 QCOMPARE(tw->tabText(-1), QString(""));
278 tw->setTabText(index: -1, LABEL);
279
280 int index = addPage();
281
282 tw->setTabText(index, text: "new");
283 QCOMPARE(tw->tabText(index), QString("new"));
284 tw->setTabText(index, LABEL);
285 QCOMPARE(tw->tabText(index), QString(LABEL));
286
287 removePage(index);
288}
289
290void tst_QTabWidget::tabShape()
291{
292 int index = addPage();
293
294 tw->setTabShape(QTabWidget::Rounded);
295 QCOMPARE(tw->tabShape(), QTabWidget::Rounded);
296 tw->setTabShape(QTabWidget::Triangular);
297 QCOMPARE(tw->tabShape(), QTabWidget::Triangular);
298 tw->setTabShape(QTabWidget::Rounded);
299 QCOMPARE(tw->tabShape(), QTabWidget::Rounded);
300
301 removePage(index);
302}
303
304void tst_QTabWidget::tabTooltip()
305{
306 // Test bad arguments
307 QCOMPARE(tw->tabToolTip(-1), QString(""));
308 tw->setTabText(index: -1, TIP);
309
310 int index = addPage();
311
312 tw->setTabToolTip(index, tip: "tip");
313 QCOMPARE(tw->tabToolTip(index), QString("tip"));
314 tw->setTabToolTip(index, TIP);
315 QCOMPARE(tw->tabToolTip(index), QString(TIP));
316
317 removePage(index);
318}
319
320void tst_QTabWidget::tabIcon()
321{
322 // Test bad arguments
323 QVERIFY(tw->tabToolTip(-1).isNull());
324 tw->setTabIcon(index: -1, icon: QIcon());
325
326 int index = addPage();
327
328 QIcon icon;
329 tw->setTabIcon(index, icon);
330 QVERIFY(tw->tabIcon(index).isNull());
331
332 removePage(index);
333}
334
335void tst_QTabWidget::indexOf()
336{
337 // Test bad arguments
338 QCOMPARE(tw->indexOf(NULL), -1);
339
340 int index = addPage();
341 QWidget *w = tw->widget(index);
342 QCOMPARE(tw->indexOf(w), index);
343
344 removePage(index);
345}
346
347void tst_QTabWidget::currentWidget()
348{
349 // Test bad arguments
350 tw->setCurrentWidget(NULL);
351 QVERIFY(!tw->currentWidget());
352
353 int index = addPage();
354 QWidget *w = tw->widget(index);
355 QCOMPARE(tw->currentWidget(), w);
356 QCOMPARE(tw->currentIndex(), index);
357
358 tw->setCurrentWidget(NULL);
359 QCOMPARE(tw->currentWidget(), w);
360 QCOMPARE(tw->currentIndex(), index);
361
362 int index2 = addPage();
363 QWidget *w2 = tw->widget(index: index2);
364 Q_UNUSED(w2);
365 QCOMPARE(tw->currentWidget(), w);
366 QCOMPARE(tw->currentIndex(), index);
367
368 removePage(index: index2);
369 removePage(index);
370}
371
372/**
373 * setCurrentWidget(..) calls setCurrentIndex(..)
374 * currentChanged(..) SIGNAL
375 */
376void tst_QTabWidget::currentIndex()
377{
378 // Test bad arguments
379 QSignalSpy spy(tw, SIGNAL(currentChanged(int)));
380 QCOMPARE(tw->currentIndex(), -1);
381 tw->setCurrentIndex(-1);
382 QCOMPARE(tw->currentIndex(), -1);
383 QCOMPARE(spy.count(), 0);
384
385 int firstIndex = addPage();
386 tw->setCurrentIndex(firstIndex);
387 QCOMPARE(tw->currentIndex(), firstIndex);
388 QCOMPARE(spy.count(), 1);
389 QList<QVariant> arguments = spy.takeFirst();
390 QCOMPARE(arguments.at(0).toInt(), firstIndex);
391
392 int index = addPage();
393 QCOMPARE(tw->currentIndex(), firstIndex);
394 tw->setCurrentIndex(index);
395 QCOMPARE(tw->currentIndex(), index);
396 QCOMPARE(spy.count(), 1);
397 arguments = spy.takeFirst();
398 QCOMPARE(arguments.at(0).toInt(), index);
399
400 removePage(index);
401 QCOMPARE(tw->currentIndex(), firstIndex);
402 QCOMPARE(spy.count(), 1);
403 arguments = spy.takeFirst();
404 QCOMPARE(arguments.at(0).toInt(), firstIndex);
405
406 removePage(index: firstIndex);
407 QCOMPARE(tw->currentIndex(), -1);
408 QCOMPARE(spy.count(), 1);
409 arguments = spy.takeFirst();
410 QCOMPARE(arguments.at(0).toInt(), -1);
411}
412
413void tst_QTabWidget::cornerWidget()
414{
415 // Test bad arguments
416 tw->setCornerWidget(NULL, corner: Qt::TopRightCorner);
417
418 QVERIFY(!tw->cornerWidget(Qt::TopLeftCorner));
419 QVERIFY(!tw->cornerWidget(Qt::TopRightCorner));
420 QVERIFY(!tw->cornerWidget(Qt::BottomLeftCorner));
421 QVERIFY(!tw->cornerWidget(Qt::BottomRightCorner));
422
423 QWidget *w = new QWidget(0);
424 tw->setCornerWidget(w, corner: Qt::TopLeftCorner);
425 QCOMPARE(w->parent(), (QObject *)tw);
426 QCOMPARE(tw->cornerWidget(Qt::TopLeftCorner), w);
427 tw->setCornerWidget(w, corner: Qt::TopRightCorner);
428 QCOMPARE(tw->cornerWidget(Qt::TopRightCorner), w);
429 tw->setCornerWidget(w, corner: Qt::BottomLeftCorner);
430 QCOMPARE(tw->cornerWidget(Qt::BottomLeftCorner), w);
431 tw->setCornerWidget(w, corner: Qt::BottomRightCorner);
432 QCOMPARE(tw->cornerWidget(Qt::BottomRightCorner), w);
433
434 tw->setCornerWidget(w: 0, corner: Qt::TopRightCorner);
435 QVERIFY(!tw->cornerWidget(Qt::TopRightCorner));
436 QCOMPARE(w->isHidden(), true);
437}
438
439//test that the QTabWidget::count() is correct at the moment the currentChanged signal is emit
440class RemoveTabObject : public QObject
441{
442 Q_OBJECT
443 public:
444 RemoveTabObject(QTabWidget *_tw) : tw(_tw), count(-1) {
445 connect(sender: tw, SIGNAL(currentChanged(int)), receiver: this, SLOT(currentChanged()));
446 }
447
448 QTabWidget *tw;
449 int count;
450 public slots:
451 void currentChanged() { count = tw->count(); }
452};
453
454void tst_QTabWidget::removeTab()
455{
456 tw->show();
457 QCOMPARE(tw->count(), 0);
458 RemoveTabObject ob(tw);
459 tw->addTab(widget: new QLabel("1"), "1");
460 QCOMPARE(ob.count, 1);
461 tw->addTab(widget: new QLabel("2"), "2");
462 tw->addTab(widget: new QLabel("3"), "3");
463 tw->addTab(widget: new QLabel("4"), "4");
464 tw->addTab(widget: new QLabel("5"), "5");
465 QCOMPARE(ob.count, 1);
466 QCOMPARE(tw->count(), 5);
467
468 tw->setCurrentIndex(4);
469 QCOMPARE(ob.count,5);
470 tw->removeTab(index: 4);
471 QCOMPARE(ob.count, 4);
472 QCOMPARE(tw->count(), 4);
473 QCOMPARE(tw->currentIndex(), 3);
474
475 tw->setCurrentIndex(1);
476 tw->removeTab(index: 1);
477 QCOMPARE(ob.count, 3);
478 QCOMPARE(tw->count(), 3);
479 QCOMPARE(tw->currentIndex(), 1);
480
481 delete tw->widget(index: 1);
482 QCOMPARE(tw->count(), 2);
483 QCOMPARE(ob.count, 2);
484 QCOMPARE(tw->currentIndex(), 1);
485 delete tw->widget(index: 1);
486 QCOMPARE(tw->count(), 1);
487 QCOMPARE(ob.count, 1);
488 tw->removeTab(index: 0);
489 QCOMPARE(tw->count(), 0);
490 QCOMPARE(ob.count, 0);
491}
492
493void tst_QTabWidget::clear()
494{
495 tw->addTab(widget: new QWidget, "1");
496 tw->addTab(widget: new QWidget, "2");
497 tw->addTab(widget: new QWidget, "3");
498 tw->addTab(widget: new QWidget, "4");
499 tw->addTab(widget: new QWidget, "5");
500 tw->setCurrentIndex(4);
501 tw->clear();
502 QCOMPARE(tw->count(), 0);
503 QCOMPARE(tw->currentIndex(), -1);
504}
505
506void tst_QTabWidget::keyboardNavigation()
507{
508 int firstIndex = addPage();
509 addPage();
510 addPage();
511 tw->setCurrentIndex(firstIndex);
512 QCOMPARE(tw->currentIndex(), firstIndex);
513
514 QTest::keyClick(widget: tw, key: Qt::Key_Tab, modifier: Qt::ControlModifier);
515 QCOMPARE(tw->currentIndex(), 1);
516 QTest::keyClick(widget: tw, key: Qt::Key_Tab, modifier: Qt::ControlModifier);
517 QCOMPARE(tw->currentIndex(), 2);
518 QTest::keyClick(widget: tw, key: Qt::Key_Tab, modifier: Qt::ControlModifier);
519 QCOMPARE(tw->currentIndex(), 0);
520 tw->setTabEnabled(index: 1, enabled: false);
521 QTest::keyClick(widget: tw, key: Qt::Key_Tab, modifier: Qt::ControlModifier);
522 QCOMPARE(tw->currentIndex(), 2);
523
524 QTest::keyClick(widget: tw, key: Qt::Key_Tab, modifier: Qt::ControlModifier | Qt::ShiftModifier);
525 QCOMPARE(tw->currentIndex(), 0);
526 QTest::keyClick(widget: tw, key: Qt::Key_Tab, modifier: Qt::ControlModifier | Qt::ShiftModifier);
527 QCOMPARE(tw->currentIndex(), 2);
528 tw->setTabEnabled(index: 1, enabled: true);
529 QTest::keyClick(widget: tw, key: Qt::Key_Tab, modifier: Qt::ControlModifier | Qt::ShiftModifier);
530 QCOMPARE(tw->currentIndex(), 1);
531 QTest::keyClick(widget: tw, key: Qt::Key_Tab, modifier: Qt::ControlModifier | Qt::ShiftModifier);
532 QCOMPARE(tw->currentIndex(), 0);
533 QTest::keyClick(widget: tw, key: Qt::Key_Tab, modifier: Qt::ControlModifier | Qt::ShiftModifier);
534 QCOMPARE(tw->currentIndex(), 2);
535 QTest::keyClick(widget: tw, key: Qt::Key_Tab, modifier: Qt::ControlModifier);
536 QCOMPARE(tw->currentIndex(), 0);
537
538 // Disable all and try to go to the next. It should not move anywhere, and more importantly
539 // it should not loop forever. (a naive "search for the first enabled tabbar") implementation
540 // might do that)
541 tw->setTabEnabled(index: 0, enabled: false);
542 tw->setTabEnabled(index: 1, enabled: false);
543 tw->setTabEnabled(index: 2, enabled: false);
544 QTest::keyClick(widget: tw, key: Qt::Key_Tab, modifier: Qt::ControlModifier);
545 // TODO: Disabling the current tab will move current tab to the next,
546 // but what if next tab is also disabled. We should look into this.
547 QVERIFY(tw->currentIndex() < 3 && tw->currentIndex() >= 0);
548}
549
550class PaintCounter : public QWidget
551{
552public:
553 PaintCounter() :count(0) { setAttribute(Qt::WA_OpaquePaintEvent); }
554 int count;
555protected:
556 void paintEvent(QPaintEvent*) {
557 ++count;
558 }
559};
560
561
562void tst_QTabWidget::paintEventCount()
563{
564 if (QGuiApplication::platformName().startsWith(s: QLatin1String("wayland"), cs: Qt::CaseInsensitive))
565 QSKIP("Wayland: This fails. Figure out why.");
566
567 Q_CHECK_PAINTEVENTS
568
569 PaintCounter *tab1 = new PaintCounter;
570 PaintCounter *tab2 = new PaintCounter;
571
572 tw->addTab(widget: tab1, "one");
573 tw->addTab(widget: tab2, "two");
574
575 QCOMPARE(tab1->count, 0);
576 QCOMPARE(tab2->count, 0);
577 QCOMPARE(tw->currentIndex(), 0);
578
579 tw->show();
580 QVERIFY(QTest::qWaitForWindowExposed(tw));
581 // Wait for extra paint events that happen at least on macOS
582 QTest::qWait(ms: 1000);
583
584 // Mac, Windows and Windows CE get multiple repaints on the first show, so use those as a starting point.
585 static const int MaxInitialPaintCount =
586#if defined(Q_OS_WIN)
587 2;
588#elif defined(Q_OS_MAC)
589 5;
590#else
591 2;
592#endif
593 QVERIFY(tab1->count <= MaxInitialPaintCount);
594 QCOMPARE(tab2->count, 0);
595
596 const int initalPaintCount = tab1->count;
597
598 tw->setCurrentIndex(1);
599
600 QTest::qWait(ms: 100);
601
602 QCOMPARE(tab1->count, initalPaintCount);
603 QCOMPARE(tab2->count, 1);
604
605 tw->setCurrentIndex(0);
606
607 QTest::qWait(ms: 100);
608
609 QCOMPARE(tab1->count, initalPaintCount + 1);
610 QCOMPARE(tab2->count, 1);
611}
612
613void tst_QTabWidget::minimumSizeHint()
614{
615 QTabWidget tw;
616 QWidget *page = new QWidget;
617 QVBoxLayout *lay = new QVBoxLayout;
618
619 QLabel *label = new QLabel(QLatin1String("XXgypq lorem ipsum must be long, must be long. lorem ipsumMMMW"));
620 lay->addWidget(label);
621
622 page->setLayout(lay);
623
624 tw.addTab(widget: page, QLatin1String("page1"));
625
626 tw.show();
627 QVERIFY(QTest::qWaitForWindowExposed(&tw));
628 tw.resize(tw.minimumSizeHint());
629
630 QSize minSize = label->minimumSizeHint();
631 QSize actSize = label->geometry().size();
632 QVERIFY(minSize.width() <= actSize.width());
633 QVERIFY(minSize.height() <= actSize.height());
634}
635
636void tst_QTabWidget::heightForWidth_data()
637{
638 QTest::addColumn<int>(name: "tabPosition");
639 QTest::newRow(dataTag: "West") << int(QTabWidget::West);
640 QTest::newRow(dataTag: "North") << int(QTabWidget::North);
641 QTest::newRow(dataTag: "East") << int(QTabWidget::East);
642 QTest::newRow(dataTag: "South") << int(QTabWidget::South);
643}
644
645void tst_QTabWidget::heightForWidth()
646{
647 QFETCH(int, tabPosition);
648
649 QWidget *window = new QWidget;
650 QVBoxLayout *lay = new QVBoxLayout(window);
651 lay->setContentsMargins(left: 0, top: 0, right: 0, bottom: 0);
652 lay->setSpacing(0);
653 QTabWidget *tabWid = new QTabWidget(window);
654 QWidget *w = new QWidget;
655 tabWid->addTab(widget: w, QLatin1String("HFW page"));
656 tabWid->setTabPosition(QTabWidget::TabPosition(tabPosition));
657 QVBoxLayout *lay2 = new QVBoxLayout(w);
658 QLabel *label = new QLabel("Label with wordwrap turned on makes it trade height for width."
659 " Make it a really long text so that it spans on several lines"
660 " when the label is on its narrowest."
661 " I don't like to repeat myself."
662 " I don't like to repeat myself."
663 " I don't like to repeat myself."
664 " I don't like to repeat myself."
665 );
666 label->setWordWrap(true);
667 lay2->addWidget(label);
668 lay2->setContentsMargins(left: 0, top: 0, right: 0, bottom: 0);
669
670 lay->addWidget(tabWid);
671 int h = window->heightForWidth(160);
672 window->resize(w: 160, h);
673 window->show();
674
675 QVERIFY(QTest::qWaitForWindowExposed(window));
676 QVERIFY(label->height() >= label->heightForWidth(label->width()));
677
678 delete window;
679}
680
681void tst_QTabWidget::tabBarClicked()
682{
683 QTabWidget tabWidget;
684 tabWidget.addTab(widget: new QWidget(&tabWidget), "0");
685 QSignalSpy clickSpy(&tabWidget, SIGNAL(tabBarClicked(int)));
686 QSignalSpy doubleClickSpy(&tabWidget, SIGNAL(tabBarDoubleClicked(int)));
687
688 QCOMPARE(clickSpy.count(), 0);
689 QCOMPARE(doubleClickSpy.count(), 0);
690
691 QTabBar &tabBar = *tabWidget.tabBar();
692 Qt::MouseButton button = Qt::LeftButton;
693 while (button <= Qt::MaxMouseButton) {
694 const QPoint tabPos = tabBar.tabRect(index: 0).center();
695
696 QTest::mouseClick(widget: &tabBar, button, stateKey: {}, pos: tabPos);
697 QCOMPARE(clickSpy.count(), 1);
698 QCOMPARE(clickSpy.takeFirst().takeFirst().toInt(), 0);
699 QCOMPARE(doubleClickSpy.count(), 0);
700
701 QTest::mouseDClick(widget: &tabBar, button, stateKey: {}, pos: tabPos);
702 QCOMPARE(clickSpy.count(), 1);
703 QCOMPARE(clickSpy.takeFirst().takeFirst().toInt(), 0);
704 QCOMPARE(doubleClickSpy.count(), 1);
705 QCOMPARE(doubleClickSpy.takeFirst().takeFirst().toInt(), 0);
706
707 const QPoint barPos(tabBar.tabRect(index: 0).right() + 5, tabBar.tabRect(index: 0).center().y());
708
709 QTest::mouseClick(widget: &tabBar, button, stateKey: {}, pos: barPos);
710 QCOMPARE(clickSpy.count(), 1);
711 QCOMPARE(clickSpy.takeFirst().takeFirst().toInt(), -1);
712 QCOMPARE(doubleClickSpy.count(), 0);
713
714 QTest::mouseDClick(widget: &tabBar, button, stateKey: {}, pos: barPos);
715 QCOMPARE(clickSpy.count(), 1);
716 QCOMPARE(clickSpy.takeFirst().takeFirst().toInt(), -1);
717 QCOMPARE(doubleClickSpy.count(), 1);
718 QCOMPARE(doubleClickSpy.takeFirst().takeFirst().toInt(), -1);
719
720 button = Qt::MouseButton(button << 1);
721 }
722}
723
724void tst_QTabWidget::moveCurrentTab()
725{
726 QTabWidget tabWidget;
727 QWidget* firstTab = new QWidget(&tabWidget);
728 QWidget* secondTab = new QWidget(&tabWidget);
729 tabWidget.addTab(widget: firstTab, "0");
730 tabWidget.addTab(widget: secondTab, "1");
731
732 QCOMPARE(tabWidget.currentIndex(), 0);
733 QCOMPARE(tabWidget.currentWidget(), firstTab);
734
735 tabWidget.setCurrentIndex(1);
736
737 QCOMPARE(tabWidget.currentIndex(), 1);
738 QCOMPARE(tabWidget.currentWidget(), secondTab);
739
740 tabWidget.tabBar()->moveTab(from: 1, to: 0);
741
742 QCOMPARE(tabWidget.currentIndex(), 0);
743 QCOMPARE(tabWidget.currentWidget(), secondTab);
744}
745
746void tst_QTabWidget::autoHide()
747{
748 QTabWidget tabWidget;
749 QWidget* firstTab = new QWidget(&tabWidget);
750 tabWidget.addTab(widget: firstTab, "0");
751 const auto sizeHint1 = tabWidget.sizeHint();
752 const auto minSizeHint1 = tabWidget.minimumSizeHint();
753 const auto heightForWidth1 = tabWidget.heightForWidth(width: 20);
754
755 QWidget* secondTab = new QWidget(&tabWidget);
756 tabWidget.addTab(widget: secondTab, "1");
757 const auto sizeHint2 = tabWidget.sizeHint();
758 const auto minSizeHint2 = tabWidget.minimumSizeHint();
759 const auto heightForWidth2 = tabWidget.heightForWidth(width: 20);
760
761 tabWidget.setTabBarAutoHide(true);
762 // size should not change
763 QCOMPARE(sizeHint2, tabWidget.sizeHint());
764 QCOMPARE(minSizeHint2, tabWidget.minimumSizeHint());
765 QCOMPARE(heightForWidth2, tabWidget.heightForWidth(20));
766
767 tabWidget.removeTab(index: 1);
768 // this size should change now since the tab should be hidden
769 QVERIFY(sizeHint1.height() > tabWidget.sizeHint().height());
770 QVERIFY(minSizeHint1.height() > tabWidget.sizeHint().height());
771 QVERIFY(heightForWidth1 > tabWidget.heightForWidth(20));
772}
773
774QTEST_MAIN(tst_QTabWidget)
775#include "tst_qtabwidget.moc"
776

source code of qtbase/tests/auto/widgets/widgets/qtabwidget/tst_qtabwidget.cpp