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 | |
32 | #include <qcoreapplication.h> |
33 | #include <qdebug.h> |
34 | #include <qstackedwidget.h> |
35 | #include <qpushbutton.h> |
36 | #include <QHBoxLayout> |
37 | #include <qlineedit.h> |
38 | |
39 | class tst_QStackedWidget : public QObject |
40 | { |
41 | Q_OBJECT |
42 | |
43 | public: |
44 | tst_QStackedWidget(); |
45 | virtual ~tst_QStackedWidget(); |
46 | |
47 | private slots: |
48 | void getSetCheck(); |
49 | void testMinimumSize(); |
50 | void dynamicPages(); |
51 | }; |
52 | |
53 | tst_QStackedWidget::tst_QStackedWidget() |
54 | { |
55 | } |
56 | |
57 | tst_QStackedWidget::~tst_QStackedWidget() |
58 | { |
59 | } |
60 | |
61 | // Testing that stackedwidget respect the minimum size of it's contents (task 95319) |
62 | void tst_QStackedWidget::testMinimumSize() |
63 | { |
64 | QWidget w; |
65 | QStackedWidget sw(&w); |
66 | QPushButton button("Text" , &sw); |
67 | sw.addWidget(w: &button); |
68 | QHBoxLayout hboxLayout; |
69 | hboxLayout.addWidget(&sw); |
70 | w.setLayout(&hboxLayout); |
71 | w.show(); |
72 | QVERIFY(w.minimumSize() != QSize(0, 0)); |
73 | } |
74 | |
75 | // Testing get/set functions |
76 | void tst_QStackedWidget::getSetCheck() |
77 | { |
78 | QStackedWidget obj1; |
79 | // int QStackedWidget::currentIndex() |
80 | // void QStackedWidget::setCurrentIndex(int) |
81 | obj1.setCurrentIndex(0); |
82 | QCOMPARE(-1, obj1.currentIndex()); |
83 | obj1.setCurrentIndex(INT_MIN); |
84 | QCOMPARE(-1, obj1.currentIndex()); |
85 | obj1.setCurrentIndex(INT_MAX); |
86 | QCOMPARE(-1, obj1.currentIndex()); |
87 | |
88 | // QWidget * QStackedWidget::currentWidget() |
89 | // void QStackedWidget::setCurrentWidget(QWidget *) |
90 | QWidget *var2 = new QWidget(); |
91 | obj1.addWidget(w: var2); |
92 | obj1.setCurrentWidget(var2); |
93 | QCOMPARE(var2, obj1.currentWidget()); |
94 | |
95 | // Disabled, task to fix is 128939. |
96 | #if 0 |
97 | // Layouts assert on any unknown widgets here, 0-pointers included. |
98 | // This seems wrong behavior, since the setCurrentIndex(int), which |
99 | // is really a convenience function for setCurrentWidget(QWidget*), |
100 | // has no problem handling out-of-bounds indices. |
101 | // ("convenience function" => "just another way of achieving the |
102 | // same goal") |
103 | obj1.setCurrentWidget((QWidget *)0); |
104 | QCOMPARE(obj1.currentWidget(), var2); |
105 | #endif |
106 | delete var2; |
107 | } |
108 | |
109 | // QTBUG-18242, a widget that deletes its children in hideEvent(). |
110 | // This caused a crash in QStackedLayout::setCurrentIndex() since |
111 | // the focus widget was destroyed while hiding the previous page. |
112 | class TestPage : public QWidget |
113 | { |
114 | public: |
115 | TestPage (bool staticWidgets = false) : QWidget(0), m_staticWidgets(staticWidgets) |
116 | { |
117 | new QVBoxLayout (this); |
118 | } |
119 | |
120 | ~TestPage() { |
121 | destroyWidgets(); |
122 | } |
123 | |
124 | void setN(int n) |
125 | { |
126 | m_n = n; |
127 | if (m_staticWidgets) |
128 | createWidgets(); |
129 | } |
130 | |
131 | virtual void showEvent (QShowEvent *) |
132 | { |
133 | if (!m_staticWidgets) |
134 | createWidgets(); |
135 | } |
136 | |
137 | virtual void hideEvent (QHideEvent *) |
138 | { |
139 | if (!m_staticWidgets) |
140 | destroyWidgets(); |
141 | } |
142 | |
143 | private: |
144 | void createWidgets() { |
145 | for (int i = 0; i < m_n; ++i) { |
146 | QLineEdit *le = new QLineEdit(this); |
147 | le->setObjectName(QLatin1String("lineEdit" ) + QString::number(i)); |
148 | layout ()->addWidget(w: le); |
149 | m_les << le; |
150 | } |
151 | } |
152 | |
153 | void destroyWidgets() |
154 | { |
155 | qDeleteAll(c: m_les); |
156 | m_les.clear (); |
157 | } |
158 | |
159 | int m_n; |
160 | const bool m_staticWidgets; |
161 | QList<QLineEdit*> m_les; |
162 | }; |
163 | |
164 | void tst_QStackedWidget::dynamicPages() |
165 | { |
166 | if (QGuiApplication::platformName().startsWith(s: QLatin1String("wayland" ), cs: Qt::CaseInsensitive)) |
167 | QSKIP("Wayland: This fails. Figure out why." ); |
168 | |
169 | QStackedWidget stackedWidget; |
170 | QStackedWidget *sw = &stackedWidget; |
171 | |
172 | TestPage *w1 = new TestPage(true); |
173 | w1->setN(3); |
174 | |
175 | TestPage *w2 = new TestPage; |
176 | w2->setN(3); |
177 | |
178 | sw->addWidget(w: w1); |
179 | sw->addWidget(w: w2); |
180 | |
181 | QLineEdit *le11 = w1->findChild<QLineEdit*>(aName: QLatin1String("lineEdit1" )); |
182 | le11->setFocus(); // set focus to second widget in the page |
183 | sw->resize(w: 200, h: 200); |
184 | sw->show(); |
185 | qApp->setActiveWindow(sw); |
186 | QVERIFY(QTest::qWaitForWindowActive(sw)); |
187 | QTRY_COMPARE(QApplication::focusWidget(), le11); |
188 | |
189 | sw->setCurrentIndex(1); |
190 | QLineEdit *le22 = w2->findChild<QLineEdit*>(aName: QLatin1String("lineEdit2" )); |
191 | le22->setFocus(); |
192 | QTRY_COMPARE(QApplication::focusWidget(), le22); |
193 | // Going back should move focus back to le11 |
194 | sw->setCurrentIndex(0); |
195 | QTRY_COMPARE(QApplication::focusWidget(), le11); |
196 | |
197 | } |
198 | |
199 | QTEST_MAIN(tst_QStackedWidget) |
200 | #include "tst_qstackedwidget.moc" |
201 | |