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 importer.updateMenu();
157 while (spy.isEmpty()) {
161 QCOMPARE(outputMenu->actions().count(), 2);
163 QAction* a1Output = outputMenu->actions().first();
165 // a1Output should have an empty menu
166 QMenu* a1OutputMenu = a1Output->menu();
167 QVERIFY(a1OutputMenu);
168 QCOMPARE(a1OutputMenu->actions().count(), 0);
170 // Show a1OutputMenu, a3 should get added
171 QMetaObject::invokeMethod(a1OutputMenu, "aboutToShow");
174 QCOMPARE(a1OutputMenu->actions().count(), 1);
176 // menuUpdated() should only have been emitted once
177 QCOMPARE(spy.count(), 1);
180 void DBusMenuImporterTest::testActionActivationRequested()
184 QAction *inputA1 = inputMenu.addAction("a1");
185 QAction *inputA2 = inputMenu.addAction("a2");
186 DBusMenuExporter exporter(TEST_OBJECT_PATH, &inputMenu);
189 DBusMenuImporter importer(TEST_SERVICE, TEST_OBJECT_PATH);
190 QSignalSpy spy(&importer, SIGNAL(actionActivationRequested(QAction*)));
193 QMenu *outputMenu = importer.menu();
195 // Get matching output actions
196 QCOMPARE(outputMenu->actions().count(), 2);
197 QAction *outputA1 = outputMenu->actions().at(0);
198 QAction *outputA2 = outputMenu->actions().at(1);
200 // Request activation
201 exporter.activateAction(inputA1);
202 exporter.activateAction(inputA2);
204 // Check we received the signal in the right order
206 QCOMPARE(spy.count(), 2);
207 QCOMPARE(spy.takeFirst().at(0).value<QAction*>(), outputA1);
208 QCOMPARE(spy.takeFirst().at(0).value<QAction*>(), outputA2);
211 void DBusMenuImporterTest::testActionsAreDeletedWhenImporterIs()
215 inputMenu.addAction("a1");
216 QMenu *inputSubMenu = inputMenu.addMenu("subMenu");
217 inputSubMenu->addAction("a2");
218 DBusMenuExporter exporter(TEST_OBJECT_PATH, &inputMenu);
221 DBusMenuImporter *importer = new DBusMenuImporter(TEST_SERVICE, TEST_OBJECT_PATH);
224 // Put all items of the menu in a list of QPointers
225 QList< QPointer<QObject> > children;
227 QMenu *outputMenu = importer->menu();
228 QCOMPARE(outputMenu->actions().count(), 2);
229 QMenu *outputSubMenu = outputMenu->actions().at(1)->menu();
230 QVERIFY(outputSubMenu);
231 // Fake aboutToShow so that outputSubMenu is populated
232 QMetaObject::invokeMethod(outputSubMenu, "aboutToShow");
233 QCOMPARE(outputSubMenu->actions().count(), 1);
235 children << outputMenu->actions().at(0);
236 children << outputMenu->actions().at(1);
237 children << outputSubMenu;
238 children << outputSubMenu->actions().at(0);
241 waitForDeferredDeletes();
243 // There should be only invalid pointers in children
244 Q_FOREACH(QPointer<QObject> child, children) {
246 QVERIFY(child.isNull());
250 void DBusMenuImporterTest::testIconData()
253 QImage img(16, 16, QImage::Format_ARGB32);
255 QPainter painter(&img);
256 painter.setCompositionMode(QPainter::CompositionMode_Source);
257 QRect rect = img.rect();
258 painter.fillRect(rect, Qt::transparent);
259 rect.adjust(2, 2, -2, -2);
260 painter.fillRect(rect, Qt::red);
261 rect.adjust(2, 2, -2, -2);
262 painter.fillRect(rect, Qt::green);
264 QIcon inputIcon(QPixmap::fromImage(img));
268 QAction *a1 = inputMenu.addAction("a1");
269 a1->setIcon(inputIcon);
270 DBusMenuExporter exporter(TEST_OBJECT_PATH, &inputMenu);
273 DBusMenuImporter *importer = new DBusMenuImporter(TEST_SERVICE, TEST_OBJECT_PATH);
276 // Check icon of action
277 QMenu *outputMenu = importer->menu();
278 QCOMPARE(outputMenu->actions().count(), 1);
280 QIcon outputIcon = outputMenu->actions().first()->icon();
281 QVERIFY(!outputIcon.isNull());
283 QImage result = outputIcon.pixmap(16).toImage();
284 QByteArray origBytes, resultBytes;
286 result.save(resultBytes);
287 QCOMPARE(origBytes,resultBytes);
290 void DBusMenuImporterTest::testInvisibleItem()
293 QAction *action = inputMenu.addAction("Test");
294 DBusMenuExporter exporter(TEST_OBJECT_PATH, &inputMenu);
296 DBusMenuImporter importer(TEST_SERVICE, TEST_OBJECT_PATH);
299 QMenu *outputMenu = importer.menu();
300 QCOMPARE(outputMenu->actions().count(), 1);
301 QAction *outputAction = outputMenu->actions().first();
303 QVERIFY(outputAction->isVisible());
306 action->setVisible(false);
308 QVERIFY(!outputAction->isVisible());
311 action->setVisible(true);
313 QVERIFY(outputAction->isVisible());
316 void DBusMenuImporterTest::testDisabledItem()
319 QAction *action = inputMenu.addAction("Test");
320 DBusMenuExporter exporter(TEST_OBJECT_PATH, &inputMenu);
322 DBusMenuImporter importer(TEST_SERVICE, TEST_OBJECT_PATH);
325 QMenu *outputMenu = importer.menu();
326 QCOMPARE(outputMenu->actions().count(), 1);
327 QAction *outputAction = outputMenu->actions().first();
328 QVERIFY(outputAction->isEnabled());
330 // Disable the action
331 DMDEBUG << "Disabling";
332 action->setEnabled(false);
334 QVERIFY(!outputAction->isEnabled());
337 action->setEnabled(true);
339 QVERIFY(outputAction->isEnabled());
342 #include "moc_dbusmenuimportertest.cpp"