1 /* This file is part of the dbusmenu-qt library
2 Copyright 2010 Canonical
3 Author: Aurelien Gateau <aurelien.gateau@canonical.com>
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License (LGPL) as published by the Free Software Foundation;
8 either version 2 of the License, or (at your option) any later
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Library General Public License for more details.
16 You should have received a copy of the GNU Library General Public License
17 along with this library; see the file COPYING.LIB. If not, write to
18 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 Boston, MA 02110-1301, USA.
22 #include "dbusmenuimportertest.h"
27 #include <QDBusConnection>
28 #include <QDBusInterface>
35 #include <dbusmenuexporter.h>
36 #include <dbusmenuimporter.h>
40 #include "testutils.h"
42 QTEST_MAIN(DBusMenuImporterTest)
44 static const char *TEST_SERVICE = "com.canonical.dbusmenu-qt-test";
45 static const char *TEST_OBJECT_PATH = "/TestMenuBar";
47 Q_DECLARE_METATYPE(QAction*)
49 void DBusMenuImporterTest::initTestCase()
51 qRegisterMetaType<QAction*>("QAction*");
52 QVERIFY(QDBusConnection::sessionBus().registerService(TEST_SERVICE));
55 void DBusMenuImporterTest::cleanup()
57 waitForDeferredDeletes();
60 void DBusMenuImporterTest::testStandardItem()
63 QAction *action = inputMenu.addAction("Test");
64 DBusMenuExporter exporter(TEST_OBJECT_PATH, &inputMenu);
66 DBusMenuImporter importer(TEST_SERVICE, TEST_OBJECT_PATH);
69 QMenu *outputMenu = importer.menu();
70 QCOMPARE(outputMenu->actions().count(), 1);
71 QAction *outputAction = outputMenu->actions().first();
72 QCOMPARE(outputAction->text(), QString("Test"));
75 void DBusMenuImporterTest::testAddingNewItem()
78 QAction *action = inputMenu.addAction("Test");
79 DBusMenuExporter exporter(TEST_OBJECT_PATH, &inputMenu);
81 DBusMenuImporter importer(TEST_SERVICE, TEST_OBJECT_PATH);
83 QMenu *outputMenu = importer.menu();
84 QCOMPARE(outputMenu->actions().count(), inputMenu.actions().count());
86 inputMenu.addAction("Test2");
88 QCOMPARE(outputMenu->actions().count(), inputMenu.actions().count());
91 void DBusMenuImporterTest::testShortcut()
94 QAction *action = inputMenu.addAction("Test");
95 action->setShortcut(Qt::CTRL | Qt::Key_S);
96 DBusMenuExporter exporter(TEST_OBJECT_PATH, &inputMenu);
98 DBusMenuImporter importer(TEST_SERVICE, TEST_OBJECT_PATH);
100 QMenu *outputMenu = importer.menu();
102 QAction *outputAction = outputMenu->actions().at(0);
103 QCOMPARE(outputAction->shortcut(), action->shortcut());
106 void DBusMenuImporterTest::testDeletingImporterWhileWaitingForAboutToShow()
108 // Start test program and wait for it to be ready
109 QProcess slowMenuProcess;
110 slowMenuProcess.start("./slowmenu");
113 // Create importer and wait for the menu
114 DBusMenuImporter *importer = new DBusMenuImporter(TEST_SERVICE, TEST_OBJECT_PATH);
117 QMenu *outputMenu = importer->menu();
118 QTimer::singleShot(100, importer, SLOT(deleteLater()));
119 outputMenu->popup(QPoint(0, 0));
121 // If it crashes, it will crash while waiting there
124 // Done, stop our test program
125 slowMenuProcess.close();
126 slowMenuProcess.waitForFinished();
129 void DBusMenuImporterTest::testDynamicMenu()
132 QAction* a1 = new QAction("a1", &rootMenu);
133 QAction* a2 = new QAction("a2", &rootMenu);
134 MenuFiller rootMenuFiller(&rootMenu);
135 rootMenuFiller.addAction(a1);
136 rootMenuFiller.addAction(a2);
139 MenuFiller subMenuFiller(&subMenu);
140 subMenuFiller.addAction(new QAction("a3", &subMenu));
142 a1->setMenu(&subMenu);
144 DBusMenuExporter exporter(TEST_OBJECT_PATH, &rootMenu);
147 DBusMenuImporter importer(TEST_SERVICE, TEST_OBJECT_PATH);
149 QMenu *outputMenu = importer.menu();
151 // There should be no children for now
152 QCOMPARE(outputMenu->actions().count(), 0);
154 // Update menu, a1 and a2 should get added
155 QSignalSpy spy(&importer, SIGNAL(menuUpdated()));
156 QSignalSpy spyOld(&importer, SIGNAL(menuReadyToBeShown()));
157 importer.updateMenu();
158 while (spy.isEmpty()) {
162 QCOMPARE(outputMenu->actions().count(), 2);
164 QAction* a1Output = outputMenu->actions().first();
166 // a1Output should have an empty menu
167 QMenu* a1OutputMenu = a1Output->menu();
168 QVERIFY(a1OutputMenu);
169 QCOMPARE(a1OutputMenu->actions().count(), 0);
171 // Show a1OutputMenu, a3 should get added
172 QMetaObject::invokeMethod(a1OutputMenu, "aboutToShow");
175 QCOMPARE(a1OutputMenu->actions().count(), 1);
177 // menuUpdated() and menuReadyToBeShown() should only have been emitted
179 QCOMPARE(spy.count(), 1);
180 QCOMPARE(spyOld.count(), 1);
183 void DBusMenuImporterTest::testActionActivationRequested()
187 QAction *inputA1 = inputMenu.addAction("a1");
188 QAction *inputA2 = inputMenu.addAction("a2");
189 DBusMenuExporter exporter(TEST_OBJECT_PATH, &inputMenu);
192 DBusMenuImporter importer(TEST_SERVICE, TEST_OBJECT_PATH);
193 QSignalSpy spy(&importer, SIGNAL(actionActivationRequested(QAction*)));
196 QMenu *outputMenu = importer.menu();
198 // Get matching output actions
199 QCOMPARE(outputMenu->actions().count(), 2);
200 QAction *outputA1 = outputMenu->actions().at(0);
201 QAction *outputA2 = outputMenu->actions().at(1);
203 // Request activation
204 exporter.activateAction(inputA1);
205 exporter.activateAction(inputA2);
207 // Check we received the signal in the right order
209 QCOMPARE(spy.count(), 2);
210 QCOMPARE(spy.takeFirst().at(0).value<QAction*>(), outputA1);
211 QCOMPARE(spy.takeFirst().at(0).value<QAction*>(), outputA2);
214 void DBusMenuImporterTest::testActionsAreDeletedWhenImporterIs()
218 inputMenu.addAction("a1");
219 QMenu *inputSubMenu = inputMenu.addMenu("subMenu");
220 inputSubMenu->addAction("a2");
221 DBusMenuExporter exporter(TEST_OBJECT_PATH, &inputMenu);
224 DBusMenuImporter *importer = new DBusMenuImporter(TEST_SERVICE, TEST_OBJECT_PATH);
227 // Put all items of the menu in a list of QPointers
228 QList< QPointer<QObject> > children;
230 QMenu *outputMenu = importer->menu();
231 QCOMPARE(outputMenu->actions().count(), 2);
232 QMenu *outputSubMenu = outputMenu->actions().at(1)->menu();
233 QVERIFY(outputSubMenu);
234 // Fake aboutToShow so that outputSubMenu is populated
235 QMetaObject::invokeMethod(outputSubMenu, "aboutToShow");
236 QCOMPARE(outputSubMenu->actions().count(), 1);
238 children << outputMenu->actions().at(0);
239 children << outputMenu->actions().at(1);
240 children << outputSubMenu;
241 children << outputSubMenu->actions().at(0);
244 waitForDeferredDeletes();
246 // There should be only invalid pointers in children
247 Q_FOREACH(QPointer<QObject> child, children) {
249 QVERIFY(child.isNull());
253 void DBusMenuImporterTest::testIconData()
256 QImage img(16, 16, QImage::Format_ARGB32);
258 QPainter painter(&img);
259 painter.setCompositionMode(QPainter::CompositionMode_Source);
260 QRect rect = img.rect();
261 painter.fillRect(rect, Qt::transparent);
262 rect.adjust(2, 2, -2, -2);
263 painter.fillRect(rect, Qt::red);
264 rect.adjust(2, 2, -2, -2);
265 painter.fillRect(rect, Qt::green);
267 QIcon inputIcon(QPixmap::fromImage(img));
271 QAction *a1 = inputMenu.addAction("a1");
272 a1->setIcon(inputIcon);
273 DBusMenuExporter exporter(TEST_OBJECT_PATH, &inputMenu);
276 DBusMenuImporter *importer = new DBusMenuImporter(TEST_SERVICE, TEST_OBJECT_PATH);
279 // Check icon of action
280 QMenu *outputMenu = importer->menu();
281 QCOMPARE(outputMenu->actions().count(), 1);
283 QIcon outputIcon = outputMenu->actions().first()->icon();
284 QVERIFY(!outputIcon.isNull());
286 QImage result = outputIcon.pixmap(16).toImage();
287 QByteArray origBytes, resultBytes;
289 result.save(resultBytes);
290 QCOMPARE(origBytes,resultBytes);
293 void DBusMenuImporterTest::testInvisibleItem()
296 QAction *action = inputMenu.addAction("Test");
297 DBusMenuExporter exporter(TEST_OBJECT_PATH, &inputMenu);
299 DBusMenuImporter importer(TEST_SERVICE, TEST_OBJECT_PATH);
302 QMenu *outputMenu = importer.menu();
303 QCOMPARE(outputMenu->actions().count(), 1);
304 QAction *outputAction = outputMenu->actions().first();
306 QVERIFY(outputAction->isVisible());
309 action->setVisible(false);
311 QVERIFY(!outputAction->isVisible());
314 action->setVisible(true);
316 QVERIFY(outputAction->isVisible());
319 void DBusMenuImporterTest::testDisabledItem()
322 QAction *action = inputMenu.addAction("Test");
323 DBusMenuExporter exporter(TEST_OBJECT_PATH, &inputMenu);
325 DBusMenuImporter importer(TEST_SERVICE, TEST_OBJECT_PATH);
328 QMenu *outputMenu = importer.menu();
329 QCOMPARE(outputMenu->actions().count(), 1);
330 QAction *outputAction = outputMenu->actions().first();
331 QVERIFY(outputAction->isEnabled());
333 // Disable the action
334 DMDEBUG << "Disabling";
335 action->setEnabled(false);
337 QVERIFY(!outputAction->isEnabled());
340 action->setEnabled(true);
342 QVERIFY(outputAction->isEnabled());
345 #include "moc_dbusmenuimportertest.cpp"