1 /*
2 This file is part of the KDE libraries
3 SPDX-FileCopyrightText: 2009 Daniel Calviño Sánchez <danxuliu@gmail.com>
4
5 SPDX-License-Identifier: LGPL-2.0-or-later
6 */
7
8 #include "kselectaction_unittest.h"
9 #include <QComboBox>
10 #include <QMainWindow>
11 #include <QStandardItemModel>
12 #include <QTest>
13 #include <kselectaction.h>
14 #include <qtoolbar.h>
15
QTEST_MAIN(KSelectAction_UnitTest)16 QTEST_MAIN(KSelectAction_UnitTest)
17
18 void KSelectAction_UnitTest::testSetToolTipBeforeRequestingComboBoxWidget()
19 {
20 KSelectAction selectAction(QStringLiteral("selectAction"), nullptr);
21 selectAction.setToolBarMode(KSelectAction::ComboBoxMode);
22 selectAction.setToolTip(QStringLiteral("Test"));
23 selectAction.setEnabled(false); // also test disabling the action
24
25 QWidget parent;
26 QWidget *widget = selectAction.requestWidget(&parent);
27
28 QVERIFY(widget);
29 QComboBox *comboBox = qobject_cast<QComboBox *>(widget);
30 QVERIFY(comboBox);
31 QCOMPARE(comboBox->toolTip(), QStringLiteral("Test"));
32 QCOMPARE(comboBox->isEnabled(), false);
33 }
34
testSetToolTipAfterRequestingComboBoxWidget()35 void KSelectAction_UnitTest::testSetToolTipAfterRequestingComboBoxWidget()
36 {
37 KSelectAction selectAction(QStringLiteral("selectAction"), nullptr);
38 selectAction.setToolBarMode(KSelectAction::ComboBoxMode);
39
40 QWidget parent;
41 QWidget *widget = selectAction.requestWidget(&parent);
42
43 selectAction.setToolTip(QStringLiteral("Test"));
44 selectAction.setEnabled(false); // also test disabling the action
45
46 QVERIFY(widget);
47 QComboBox *comboBox = qobject_cast<QComboBox *>(widget);
48 QVERIFY(comboBox);
49 QCOMPARE(comboBox->toolTip(), QStringLiteral("Test"));
50 QCOMPARE(comboBox->isEnabled(), false);
51 }
52
testSetToolTipBeforeRequestingToolButtonWidget()53 void KSelectAction_UnitTest::testSetToolTipBeforeRequestingToolButtonWidget()
54 {
55 KSelectAction selectAction(QStringLiteral("selectAction"), nullptr);
56 selectAction.setToolBarMode(KSelectAction::MenuMode);
57 selectAction.setToolTip(QStringLiteral("Test"));
58
59 QToolBar toolBar;
60 // Don't use requestWidget, as it needs a releaseWidget when used in MenuMode
61 //(in ComboBoxMode the widget is released automatically when it is
62 // destroyed). When the action is added to the QToolBar, it requests and
63 // releases the widget as needed.
64 toolBar.addAction(&selectAction);
65 QWidget *widget = toolBar.widgetForAction(&selectAction);
66
67 QVERIFY(widget);
68 QToolButton *toolButton = qobject_cast<QToolButton *>(widget);
69 QVERIFY(toolButton);
70 QCOMPARE(toolButton->toolTip(), QStringLiteral("Test"));
71 }
72
testSetToolTipAfterRequestingToolButtonWidget()73 void KSelectAction_UnitTest::testSetToolTipAfterRequestingToolButtonWidget()
74 {
75 KSelectAction selectAction(QStringLiteral("selectAction"), nullptr);
76 selectAction.setToolBarMode(KSelectAction::MenuMode);
77
78 QToolBar toolBar;
79 // Don't use requestWidget, as it needs a releaseWidget when used in MenuMode
80 //(in ComboBoxMode the widget is released automatically when it is
81 // destroyed). When the action is added to the QToolBar, it requests and
82 // releases the widget as needed.
83 toolBar.addAction(&selectAction);
84 QWidget *widget = toolBar.widgetForAction(&selectAction);
85
86 selectAction.setToolTip(QStringLiteral("Test"));
87
88 QVERIFY(widget);
89 QToolButton *toolButton = qobject_cast<QToolButton *>(widget);
90 QVERIFY(toolButton);
91 QCOMPARE(toolButton->toolTip(), QStringLiteral("Test"));
92 }
93
testSetWhatsThisBeforeRequestingComboBoxWidget()94 void KSelectAction_UnitTest::testSetWhatsThisBeforeRequestingComboBoxWidget()
95 {
96 KSelectAction selectAction(QStringLiteral("selectAction"), nullptr);
97 selectAction.setToolBarMode(KSelectAction::ComboBoxMode);
98 selectAction.setWhatsThis(QStringLiteral("Test"));
99
100 QWidget parent;
101 QWidget *widget = selectAction.requestWidget(&parent);
102
103 QVERIFY(widget);
104 QComboBox *comboBox = qobject_cast<QComboBox *>(widget);
105 QVERIFY(comboBox);
106 QCOMPARE(comboBox->whatsThis(), QStringLiteral("Test"));
107 }
108
testSetWhatsThisAfterRequestingComboBoxWidget()109 void KSelectAction_UnitTest::testSetWhatsThisAfterRequestingComboBoxWidget()
110 {
111 KSelectAction selectAction(QStringLiteral("selectAction"), nullptr);
112 selectAction.setToolBarMode(KSelectAction::ComboBoxMode);
113
114 QWidget parent;
115 QWidget *widget = selectAction.requestWidget(&parent);
116
117 selectAction.setWhatsThis(QStringLiteral("Test"));
118
119 QVERIFY(widget);
120 QComboBox *comboBox = qobject_cast<QComboBox *>(widget);
121 QVERIFY(comboBox);
122 QCOMPARE(comboBox->whatsThis(), QStringLiteral("Test"));
123 }
124
testSetWhatsThisBeforeRequestingToolButtonWidget()125 void KSelectAction_UnitTest::testSetWhatsThisBeforeRequestingToolButtonWidget()
126 {
127 KSelectAction selectAction(QStringLiteral("selectAction"), nullptr);
128 selectAction.setToolBarMode(KSelectAction::MenuMode);
129 selectAction.setWhatsThis(QStringLiteral("Test"));
130
131 QToolBar toolBar;
132 // Don't use requestWidget, as it needs a releaseWidget when used in MenuMode
133 //(in ComboBoxMode the widget is released automatically when it is
134 // destroyed). When the action is added to the QToolBar, it requests and
135 // releases the widget as needed.
136 toolBar.addAction(&selectAction);
137 QWidget *widget = toolBar.widgetForAction(&selectAction);
138
139 QVERIFY(widget);
140 QToolButton *toolButton = qobject_cast<QToolButton *>(widget);
141 QVERIFY(toolButton);
142 QCOMPARE(toolButton->whatsThis(), QStringLiteral("Test"));
143 }
144
testSetWhatsThisAfterRequestingToolButtonWidget()145 void KSelectAction_UnitTest::testSetWhatsThisAfterRequestingToolButtonWidget()
146 {
147 KSelectAction selectAction(QStringLiteral("selectAction"), nullptr);
148 selectAction.setToolBarMode(KSelectAction::MenuMode);
149
150 QToolBar toolBar;
151 // Don't use requestWidget, as it needs a releaseWidget when used in MenuMode
152 //(in ComboBoxMode the widget is released automatically when it is
153 // destroyed). When the action is added to the QToolBar, it requests and
154 // releases the widget as needed.
155 toolBar.addAction(&selectAction);
156 QWidget *widget = toolBar.widgetForAction(&selectAction);
157
158 selectAction.setWhatsThis(QStringLiteral("Test"));
159
160 QVERIFY(widget);
161 QToolButton *toolButton = qobject_cast<QToolButton *>(widget);
162 QVERIFY(toolButton);
163 QCOMPARE(toolButton->whatsThis(), QStringLiteral("Test"));
164 }
165
testChildActionStateChangeComboMode()166 void KSelectAction_UnitTest::testChildActionStateChangeComboMode()
167 {
168 KSelectAction selectAction(QStringLiteral("selectAction"), nullptr);
169 selectAction.setToolBarMode(KSelectAction::ComboBoxMode);
170 QWidget parent;
171 QWidget *widget = selectAction.requestWidget(&parent);
172 QComboBox *comboBox = qobject_cast<QComboBox *>(widget);
173 QVERIFY(comboBox);
174 const QString itemText = QStringLiteral("foo");
175 QAction *childAction = selectAction.addAction(itemText);
176 QCOMPARE(comboBox->itemText(0), itemText);
177 childAction->setEnabled(false);
178 // There's no API for item-is-enabled, need to go via the internal model like kselectaction does...
179 QStandardItemModel *model = qobject_cast<QStandardItemModel *>(comboBox->model());
180 QVERIFY(model);
181 QVERIFY(!model->item(0)->isEnabled());
182
183 // Now remove the action
184 selectAction.removeAction(childAction);
185 QCOMPARE(comboBox->count(), 0);
186 delete childAction;
187 }
188
189 // Bug 436808
testCrashComboBoxDestruction()190 void KSelectAction_UnitTest::testCrashComboBoxDestruction()
191 {
192 QWidget parentWidget;
193 QMainWindow mainWindow(&parentWidget);
194
195 // Create a KSelectAction in a QWidget
196 auto *comboSelect = new KSelectAction(QStringLiteral("selectAction"), &mainWindow);
197
198 // Add some actions and create some connections to them
199 for (int i = 0; i < 7; ++i) {
200 QAction *action = comboSelect->addAction(QStringLiteral("Combo Action %1").arg(i));
201 connect(action, &QAction::triggered, &mainWindow, []() {
202 // Empty, just creating a connection to trigger a crash
203 });
204 }
205
206 comboSelect->setToolBarMode(KSelectAction::ComboBoxMode);
207 QToolBar *toolBar = mainWindow.addToolBar(QStringLiteral("Test"));
208
209 // Add the KSelectAction to a toolbar
210 toolBar->addAction(comboSelect);
211 mainWindow.show();
212 mainWindow.activateWindow();
213 // Wait for window to show
214 QVERIFY(QTest::qWaitForWindowActive(&mainWindow));
215
216 // When this method finishes and the QWidget is destroyed, and there
217 // should be no crash in KSelectActionPrivate::comboBoxDeleted()
218 }
219
testRequestWidgetComboBoxModeWidgetParent()220 void KSelectAction_UnitTest::testRequestWidgetComboBoxModeWidgetParent()
221 {
222 KSelectAction selectAction(QStringLiteral("selectAction"), nullptr);
223 selectAction.setToolBarMode(KSelectAction::ComboBoxMode);
224
225 QToolBar toolBar;
226 toolBar.addAction(&selectAction);
227 QWidget *widget = toolBar.widgetForAction(&selectAction);
228
229 QVERIFY(widget);
230 QComboBox *comboBox = qobject_cast<QComboBox *>(widget);
231 QVERIFY(comboBox);
232 QVERIFY(!comboBox->isEnabled());
233 }
234
testRequestWidgetComboBoxModeWidgetParentSeveralActions()235 void KSelectAction_UnitTest::testRequestWidgetComboBoxModeWidgetParentSeveralActions()
236 {
237 KSelectAction selectAction(QStringLiteral("selectAction"), nullptr);
238 selectAction.setToolBarMode(KSelectAction::ComboBoxMode);
239
240 selectAction.addAction(new QAction(QStringLiteral("action1"), &selectAction));
241 selectAction.addAction(new QAction(QStringLiteral("action2"), &selectAction));
242 selectAction.addAction(new QAction(QStringLiteral("action3"), &selectAction));
243
244 QToolBar toolBar;
245 toolBar.addAction(&selectAction);
246 QWidget *widget = toolBar.widgetForAction(&selectAction);
247
248 QVERIFY(widget);
249 QComboBox *comboBox = qobject_cast<QComboBox *>(widget);
250 QVERIFY(comboBox);
251 QVERIFY(comboBox->isEnabled());
252 }
253
testRequestWidgetMenuModeWidgetParent()254 void KSelectAction_UnitTest::testRequestWidgetMenuModeWidgetParent()
255 {
256 KSelectAction selectAction(QStringLiteral("selectAction"), nullptr);
257 selectAction.setToolBarMode(KSelectAction::MenuMode);
258
259 QToolBar toolBar;
260 toolBar.addAction(&selectAction);
261 QWidget *widget = toolBar.widgetForAction(&selectAction);
262
263 QVERIFY(widget);
264 QToolButton *toolButton = qobject_cast<QToolButton *>(widget);
265 QVERIFY(toolButton);
266 QVERIFY(!toolButton->isEnabled());
267 QVERIFY(toolButton->autoRaise());
268 QCOMPARE((int)toolButton->focusPolicy(), (int)Qt::NoFocus);
269 QCOMPARE(toolButton->defaultAction(), (QAction *)&selectAction);
270 QCOMPARE(toolButton->actions().count(), 1);
271 QCOMPARE(toolButton->actions().at(0)->text(), QStringLiteral("selectAction"));
272 }
273
testRequestWidgetMenuModeWidgetParentSeveralActions()274 void KSelectAction_UnitTest::testRequestWidgetMenuModeWidgetParentSeveralActions()
275 {
276 KSelectAction selectAction(QStringLiteral("selectAction"), nullptr);
277 selectAction.setToolBarMode(KSelectAction::MenuMode);
278
279 selectAction.addAction(new QAction(QStringLiteral("action1"), &selectAction));
280 selectAction.addAction(new QAction(QStringLiteral("action2"), &selectAction));
281 selectAction.addAction(new QAction(QStringLiteral("action3"), &selectAction));
282
283 QToolBar toolBar;
284 toolBar.addAction(&selectAction);
285 QWidget *widget = toolBar.widgetForAction(&selectAction);
286
287 QVERIFY(widget);
288 QToolButton *toolButton = qobject_cast<QToolButton *>(widget);
289 QVERIFY(toolButton);
290 QVERIFY(toolButton->isEnabled());
291 QVERIFY(toolButton->autoRaise());
292 QCOMPARE((int)toolButton->focusPolicy(), (int)Qt::NoFocus);
293 QCOMPARE(toolButton->defaultAction(), (QAction *)&selectAction);
294 QCOMPARE(toolButton->actions().count(), 4);
295 QCOMPARE(toolButton->actions().at(0)->text(), QStringLiteral("selectAction"));
296 QCOMPARE(toolButton->actions().at(1)->text(), QStringLiteral("action1"));
297 QCOMPARE(toolButton->actions().at(2)->text(), QStringLiteral("action2"));
298 QCOMPARE(toolButton->actions().at(3)->text(), QStringLiteral("action3"));
299 }
300
testRequestWidgetMenuModeWidgetParentAddActions()301 void KSelectAction_UnitTest::testRequestWidgetMenuModeWidgetParentAddActions()
302 {
303 KSelectAction selectAction(QStringLiteral("selectAction"), nullptr);
304 selectAction.setToolBarMode(KSelectAction::MenuMode);
305
306 QToolBar toolBar;
307 toolBar.addAction(&selectAction);
308 QWidget *widget = toolBar.widgetForAction(&selectAction);
309
310 QVERIFY(widget);
311 QVERIFY(!widget->isEnabled());
312
313 selectAction.addAction(new QAction(QStringLiteral("action1"), &selectAction));
314 selectAction.addAction(new QAction(QStringLiteral("action2"), &selectAction));
315 selectAction.addAction(new QAction(QStringLiteral("action3"), &selectAction));
316
317 QVERIFY(widget->isEnabled());
318 QCOMPARE(widget->actions().count(), 4);
319 QCOMPARE(widget->actions().at(0)->text(), QStringLiteral("selectAction"));
320 QCOMPARE(widget->actions().at(1)->text(), QStringLiteral("action1"));
321 QCOMPARE(widget->actions().at(2)->text(), QStringLiteral("action2"));
322 QCOMPARE(widget->actions().at(3)->text(), QStringLiteral("action3"));
323 }
324
testRequestWidgetMenuModeWidgetParentRemoveActions()325 void KSelectAction_UnitTest::testRequestWidgetMenuModeWidgetParentRemoveActions()
326 {
327 KSelectAction selectAction(QStringLiteral("selectAction"), nullptr);
328 selectAction.setToolBarMode(KSelectAction::MenuMode);
329
330 QToolBar toolBar;
331 toolBar.addAction(&selectAction);
332 QWidget *widget = toolBar.widgetForAction(&selectAction);
333
334 QVERIFY(widget);
335
336 QAction *action1 = new QAction(QStringLiteral("action1"), &selectAction);
337 selectAction.addAction(action1);
338 QAction *action2 = new QAction(QStringLiteral("action2"), &selectAction);
339 selectAction.addAction(action2);
340 QAction *action3 = new QAction(QStringLiteral("action3"), &selectAction);
341 selectAction.addAction(action3);
342
343 delete selectAction.removeAction(action1);
344 delete selectAction.removeAction(action2);
345 delete selectAction.removeAction(action3);
346
347 QVERIFY(!widget->isEnabled());
348 QCOMPARE(widget->actions().count(), 1);
349 QCOMPARE(widget->actions().at(0)->text(), QStringLiteral("selectAction"));
350 }
351