Merge lp:~nick-dedekind/libdbusmenu-qt/qpaexporter into lp:libdbusmenu-qt

Proposed by Nick Dedekind
Status: Work in progress
Proposed branch: lp:~nick-dedekind/libdbusmenu-qt/qpaexporter
Merge into: lp:libdbusmenu-qt
Prerequisite: lp:~nick-dedekind/libdbusmenu-qt/Qt5-tests
Diff against target: 2985 lines (+2413/-149)
31 files modified
CMakeLists.txt (+12/-2)
Doxyfile.in (+1/-1)
debian/changelog (+7/-0)
src/CMakeLists.txt (+35/-28)
src/dbusmenuexporter.cpp (+5/-31)
src/dbusmenuexporterdbus_p.cpp (+4/-36)
src/dbusmenuexporterdbus_p.h (+10/-34)
src/dbusmenuexporterdbusinterface_p.cpp (+67/-0)
src/dbusmenuexporterdbusinterface_p.h (+80/-0)
src/dbusmenuexporterprivate_p.h (+1/-1)
src/dbusmenuimporter.cpp (+2/-2)
src/dbusmenuinterface.cpp (+63/-0)
src/dbusmenuinterface.h (+154/-0)
src/dbusmenuproperty.h (+78/-0)
src/dbusmenushortcut_p.cpp (+2/-0)
src/dbusmenutypes.cpp (+142/-1)
src/dbusmenutypes.h (+20/-5)
src/qpa/exportedplatformmenubar.cpp (+377/-0)
src/qpa/exportedplatformmenubar.h (+136/-0)
src/qpa/exportedplatformmenubar_p.cpp (+129/-0)
src/qpa/exportedplatformmenubar_p.h (+111/-0)
src/qpa/logging_p.h (+38/-0)
src/qpa/qpadbusmenuexporter_p.cpp (+357/-0)
src/qpa/qpadbusmenuexporter_p.h (+94/-0)
src/utils.cpp (+36/-1)
src/utils_p.h (+15/-5)
tests/CMakeLists.txt (+13/-0)
tests/dbusmenuexportertest.cpp (+2/-1)
tests/exportedplatformmenutest.cpp (+366/-0)
tests/exportedplatformmenutest.h (+55/-0)
tests/testutils.h (+1/-1)
To merge this branch: bzr merge lp:~nick-dedekind/libdbusmenu-qt/qpaexporter
Reviewer Review Type Date Requested Status
PS Jenkins bot (community) continuous-integration Needs Fixing
DBus Menu Team Pending
Review via email: mp+253334@code.launchpad.net

This proposal supersedes a proposal from 2015-03-05.

Description of the change

Added exporter support for Qt platform menus.
Exported dbus interface for com.canonical.dbusmenu for use in unity8.

To post a comment you must log in.
276. By Nick Dedekind

reverted dbus xml

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)

Unmerged revisions

276. By Nick Dedekind

reverted dbus xml

275. By Nick Dedekind

fixed addMenu

274. By Nick Dedekind

added exported platformmenu test

273. By Nick Dedekind

merged with test branch

272. By Nick Dedekind

parent of exporter

271. By Nick Dedekind

logging & version bump

270. By Nick Dedekind

added dbusmenuinterface + reworked dbus properties

269. By Nick Dedekind

more qpa exporter

268. By Nick Dedekind

app menu qpa exporter

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'CMakeLists.txt'
2--- CMakeLists.txt 2015-03-18 11:19:06 +0000
3+++ CMakeLists.txt 2015-03-18 11:19:06 +0000
4@@ -34,12 +34,22 @@
5 endif()
6 endif()
7
8+find_package(PkgConfig)
9 # Detect for which Qt version we're building
10 if (USE_QT5)
11+ find_package(Qt5Core REQUIRED)
12 find_package(Qt5Widgets REQUIRED)
13 find_package(Qt5DBus REQUIRED)
14- include_directories(${Qt5Widgets_INCLUDE_DIRS} ${Qt5DBus_INCLUDE_DIRS})
15- find_package(Qt5Core REQUIRED)
16+ find_package(Qt5Gui REQUIRED)
17+ pkg_check_modules(DBUS_CPP dbus-cpp REQUIRED)
18+
19+ include_directories(
20+ ${Qt5Widgets_INCLUDE_DIRS}
21+ ${Qt5DBus_INCLUDE_DIRS}
22+ ${Qt5DBus_PRIVATE_INCLUDE_DIRS}
23+ ${Qt5Gui_PRIVATE_INCLUDE_DIRS}
24+ ${DBUS_CPP_INCLUDE_DIRS}
25+ )
26 set(CMAKE_AUTOMOC ON)
27 set(CMAKE_AUTOMOC_RELAXED_MODE ON)
28 set(CMAKE_POSITION_INDEPENDENT_CODE ON)
29
30=== modified file 'Doxyfile.in'
31--- Doxyfile.in 2011-03-24 15:04:52 +0000
32+++ Doxyfile.in 2015-03-18 11:19:06 +0000
33@@ -232,7 +232,7 @@
34 SEARCH_INCLUDES = YES
35 INCLUDE_PATH =
36 INCLUDE_FILE_PATTERNS =
37-PREDEFINED =
38+PREDEFINED = DOXYGEN_SHOULD_SKIP_THIS
39 EXPAND_AS_DEFINED =
40 SKIP_FUNCTION_MACROS = YES
41 #---------------------------------------------------------------------------
42
43=== modified file 'debian/changelog'
44--- debian/changelog 2014-06-19 09:07:18 +0000
45+++ debian/changelog 2015-03-18 11:19:06 +0000
46@@ -1,3 +1,10 @@
47+libdbusmenu-qt (0.9.4) UNRELEASED; urgency=medium
48+
49+ [ Nick Dedekind ]
50+ * Added exported qpa platform menu & dbusmenu interface
51+
52+ -- Nick Dedekind <nick.dedekind@canonical.com> Thu, 05 Mar 2015 13:39:12 +0000
53+
54 libdbusmenu-qt (0.9.3+14.10.20140619-0ubuntu1) utopic; urgency=low
55
56 [ Aurélien Gâteau ]
57
58=== modified file 'src/CMakeLists.txt'
59--- src/CMakeLists.txt 2015-03-18 11:19:06 +0000
60+++ src/CMakeLists.txt 2015-03-18 11:19:06 +0000
61@@ -1,34 +1,20 @@
62 include(CheckCXXSourceCompiles)
63
64-check_cxx_compiler_flag(-Wall __DBUSMENU_HAVE_W_ALL)
65-if (__DBUSMENU_HAVE_W_ALL)
66- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
67-endif (__DBUSMENU_HAVE_W_ALL)
68-
69 # Check some compiler flags
70-check_cxx_compiler_flag(-fvisibility=hidden __DBUSMENU_HAVE_GCC_VISIBILITY)
71-if (__DBUSMENU_HAVE_GCC_VISIBILITY AND NOT WIN32)
72- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden")
73-endif (__DBUSMENU_HAVE_GCC_VISIBILITY AND NOT WIN32)
74-
75-check_cxx_compiler_flag(-Woverloaded-virtual __DBUSMENU_HAVE_W_OVERLOADED_VIRTUAL)
76-if (__DBUSMENU_HAVE_W_OVERLOADED_VIRTUAL)
77- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Woverloaded-virtual")
78-endif (__DBUSMENU_HAVE_W_OVERLOADED_VIRTUAL)
79-
80 check_cxx_compiler_flag(-Wall __DBUSMENU_HAVE_W_ALL)
81 if (__DBUSMENU_HAVE_W_ALL)
82 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
83 endif (__DBUSMENU_HAVE_W_ALL)
84
85-check_cxx_compiler_flag(-std=c++11 __DBUSMENU_HAVE_CXX11)
86-if (__DBUSMENU_HAVE_CXX11)
87- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
88-endif (__DBUSMENU_HAVE_CXX11)
89+# Find the dbusxml2cpp tool
90+if(DEFINED ENV{DEB_BUILD_MULTIARCH})
91+ set(QDBUSXML2CPP_EXECUTABLE "/usr/lib/$ENV{DEB_BUILD_MULTIARCH}/qt5/bin/qdbusxml2cpp")
92+else()
93+ FIND_PROGRAM(QDBUSXML2CPP_EXECUTABLE qdbusxml2cpp)
94+endif()
95
96 # Check whether QIcon::name() exists. It was added in late Qt 4.7 cycle, and is
97 # not present in betas.
98-
99 if (NOT USE_QT5)
100 set(CMAKE_REQUIRED_INCLUDES "${QT_INCLUDE_DIR}")
101 set(CMAKE_REQUIRED_LIBRARIES "${QT_QTGUI_LIBRARIES};${QT_QTCORE_LIBRARIES}")
102@@ -49,34 +35,55 @@
103 endif()
104 configure_file(dbusmenu_config.h.in ${CMAKE_CURRENT_BINARY_DIR}/dbusmenu_config.h @ONLY)
105
106+include_directories(
107+ ${CMAKE_SOURCE_DIR}/src
108+ ${CMAKE_BINARY_DIR}/src
109+ )
110+
111 set(dbusmenu_qt_SRCS
112 dbusmenu_p.cpp
113 dbusmenuexporter.cpp
114 dbusmenuexporterdbus_p.cpp
115+ dbusmenuexporterdbusinterface_p.cpp
116 dbusmenuimporter.cpp
117- dbusmenutypes_p.cpp
118+ dbusmenuinterface.cpp
119+ dbusmenutypes.cpp
120 dbusmenushortcut_p.cpp
121 utils.cpp
122- )
123-
124-include_directories(
125- ${CMAKE_SOURCE_DIR}/src
126- ${CMAKE_BINARY_DIR}/src
127+ dbusmenuproperty.h
128+ ${CMAKE_BINARY_DIR}/src/dbusmenuinterface_p.cpp
129 )
130
131 if (NOT USE_QT5)
132 qt4_automoc(${dbusmenu_qt_SRCS})
133 qt4_add_dbus_adaptor(dbusmenu_qt_SRCS
134 ${CMAKE_CURRENT_SOURCE_DIR}/com.canonical.dbusmenu.xml
135- ${CMAKE_CURRENT_SOURCE_DIR}/dbusmenuexporterdbus_p.h DBusMenuExporterDBus
136+ ${CMAKE_CURRENT_SOURCE_DIR}/dbusmenuexporterdbusinterface_p.h DBusMenuExporterDBusInterface
137 )
138 else()
139+ set(dbusmenu_qt_SRCS
140+ ${dbusmenu_qt_SRCS}
141+ qpa/exportedplatformmenubar.cpp
142+ qpa/exportedplatformmenubar_p.cpp
143+ qpa/qpadbusmenuexporter_p.cpp
144+ )
145+
146 qt5_add_dbus_adaptor(dbusmenu_qt_SRCS
147 ${CMAKE_CURRENT_SOURCE_DIR}/com.canonical.dbusmenu.xml
148- ${CMAKE_CURRENT_SOURCE_DIR}/dbusmenuexporterdbus_p.h DBusMenuExporterDBus
149+ ${CMAKE_CURRENT_SOURCE_DIR}/dbusmenuexporterdbusinterface_p.h DBusMenuExporterDBusInterface
150 )
151 endif()
152
153+if(${CMAKE_CURRENT_SOURCE_DIR}/com.canonical.dbusmenu.xml IS_NEWER_THAN ${CMAKE_CURRENT_BINARY_DIR}/dbusmenuinterface.h)
154+ execute_process(COMMAND ${QDBUSXML2CPP_EXECUTABLE}
155+ -c DbusMenuInterfacePrivate
156+ -p ${CMAKE_CURRENT_BINARY_DIR}/dbusmenuinterface_p
157+ -i "${CMAKE_SOURCE_DIR}/src/dbusmenutypes.h"
158+ ${CMAKE_CURRENT_SOURCE_DIR}/com.canonical.dbusmenu.xml
159+ com.canonical.dbusmenu
160+ )
161+endif()
162+
163 configure_file(dbusmenu_version.h.in
164 ${CMAKE_CURRENT_BINARY_DIR}/dbusmenu_version.h
165 )
166
167=== modified file 'src/dbusmenuexporter.cpp'
168--- src/dbusmenuexporter.cpp 2012-10-24 14:43:10 +0000
169+++ src/dbusmenuexporter.cpp 2015-03-18 11:19:06 +0000
170@@ -35,7 +35,7 @@
171 #include "dbusmenu_p.h"
172 #include "dbusmenuexporterdbus_p.h"
173 #include "dbusmenuexporterprivate_p.h"
174-#include "dbusmenutypes_p.h"
175+#include "dbusmenutypes.h"
176 #include "dbusmenushortcut_p.h"
177 #include "debug_p.h"
178 #include "utils_p.h"
179@@ -94,7 +94,7 @@
180 QAction *action = button->defaultAction();
181 DMRETURN_VALUE_IF_FAIL(action, map);
182
183- map.insert("label", swapMnemonicChar(action->text(), '&', '_'));
184+ map.insert("label", Utils::swapMnemonicChar(action->text(), '&', '_'));
185 insertIconProperty(&map, action);
186 if (!action->isVisible()) {
187 map.insert("visible", false);
188@@ -115,7 +115,7 @@
189 QVariantMap DBusMenuExporterPrivate::propertiesForStandardAction(QAction *action) const
190 {
191 QVariantMap map;
192- map.insert("label", swapMnemonicChar(action->text(), '&', '_'));
193+ map.insert("label", Utils::swapMnemonicChar(action->text(), '&', '_'));
194 if (!action->isEnabled()) {
195 map.insert("enabled", false);
196 }
197@@ -338,7 +338,7 @@
198 d->m_emittedLayoutUpdatedOnce = false;
199 d->m_itemUpdatedTimer = new QTimer(this);
200 d->m_layoutUpdatedTimer = new QTimer(this);
201- d->m_dbusObject = new DBusMenuExporterDBus(this);
202+ d->m_dbusObject = new DBusMenuExporterDBus(objectPath, this);
203
204 d->addMenu(d->m_rootMenu, 0);
205
206@@ -379,33 +379,7 @@
207 QVariantMap updatedProperties;
208 QStringList removedProperties;
209
210- // Find updated and removed properties
211- QVariantMap::ConstIterator newEnd = newProperties.constEnd();
212-
213- QVariantMap::ConstIterator
214- oldIt = oldProperties.constBegin(),
215- oldEnd = oldProperties.constEnd();
216- for(; oldIt != oldEnd; ++oldIt) {
217- QString key = oldIt.key();
218- QVariantMap::ConstIterator newIt = newProperties.constFind(key);
219- if (newIt != newEnd) {
220- if (newIt.value() != oldIt.value()) {
221- updatedProperties.insert(key, newIt.value());
222- }
223- } else {
224- removedProperties << key;
225- }
226- }
227-
228- // Find new properties (treat them as updated properties)
229- QVariantMap::ConstIterator newIt = newProperties.constBegin();
230- for (; newIt != newEnd; ++newIt) {
231- QString key = newIt.key();
232- oldIt = oldProperties.constFind(key);
233- if (oldIt == oldEnd) {
234- updatedProperties.insert(key, newIt.value());
235- }
236- }
237+ Utils::parsePropertyChanges(oldProperties, newProperties, updatedProperties, removedProperties);
238
239 // Update our data (oldProperties is a reference)
240 oldProperties = newProperties;
241
242=== modified file 'src/dbusmenuexporterdbus_p.cpp'
243--- src/dbusmenuexporterdbus_p.cpp 2011-08-29 14:51:01 +0000
244+++ src/dbusmenuexporterdbus_p.cpp 2015-03-18 11:19:06 +0000
245@@ -21,26 +21,19 @@
246 #include "dbusmenuexporterdbus_p.h"
247
248 // Qt
249-#include <QDBusMessage>
250+#include <QEvent>
251 #include <QMenu>
252 #include <QVariant>
253
254 // Local
255-#include "dbusmenuadaptor.h"
256 #include "dbusmenuexporterprivate_p.h"
257 #include "dbusmenushortcut_p.h"
258 #include "debug_p.h"
259
260-static const char *DBUSMENU_INTERFACE = "com.canonical.dbusmenu";
261-static const char *FDO_PROPERTIES_INTERFACE = "org.freedesktop.DBus.Properties";
262-
263-DBusMenuExporterDBus::DBusMenuExporterDBus(DBusMenuExporter *exporter)
264-: QObject(exporter)
265-, m_exporter(exporter)
266-, m_status("normal")
267+DBusMenuExporterDBus::DBusMenuExporterDBus(const QString& objectPath, DBusMenuExporter *exporter)
268+ : DBusMenuExporterDBusInterface(objectPath, exporter)
269+ , m_exporter(exporter)
270 {
271- DBusMenuTypes_register();
272- new DbusmenuAdaptor(this);
273 }
274
275 uint DBusMenuExporterDBus::GetLayout(int parentId, int recursionDepth, const QStringList &propertyNames, DBusMenuLayoutItem &item)
276@@ -157,30 +150,5 @@
277 return filter.mChanged;
278 }
279
280-void DBusMenuExporterDBus::setStatus(const QString& status)
281-{
282- if (m_status == status) {
283- return;
284- }
285- m_status = status;
286-
287- QVariantMap map;
288- map.insert("Status", QVariant(status));
289-
290- QDBusMessage msg = QDBusMessage::createSignal(m_exporter->d->m_objectPath, FDO_PROPERTIES_INTERFACE, "PropertiesChanged");
291- QVariantList args = QVariantList()
292- << DBUSMENU_INTERFACE
293- << map
294- << QStringList() // New properties: none
295- ;
296- msg.setArguments(args);
297- QDBusConnection::sessionBus().send(msg);
298-}
299-
300-QString DBusMenuExporterDBus::status() const
301-{
302- return m_status;
303-}
304-
305
306 #include "dbusmenuexporterdbus_p.moc"
307
308=== modified file 'src/dbusmenuexporterdbus_p.h'
309--- src/dbusmenuexporterdbus_p.h 2011-08-29 14:51:01 +0000
310+++ src/dbusmenuexporterdbus_p.h 2015-03-18 11:19:06 +0000
311@@ -22,50 +22,26 @@
312 #define DBUSMENUEXPORTERDBUS_P_H
313
314 // Local
315-#include <dbusmenutypes_p.h>
316-
317-// Qt
318-#include <QtCore/QObject>
319-#include <QtCore/QVariant>
320-#include <QtDBus/QDBusAbstractAdaptor>
321-#include <QtDBus/QDBusVariant>
322+#include "dbusmenuexporterdbusinterface_p.h"
323
324 class DBusMenuExporter;
325
326-/**
327- * Internal class implementing the DBus side of DBusMenuExporter
328- * This avoid exposing the implementation of the DBusMenu spec to the outside
329- * world.
330- */
331-class DBusMenuExporterDBus : public QObject
332+class DBusMenuExporterDBus : public DBusMenuExporterDBusInterface
333 {
334 Q_OBJECT
335 Q_CLASSINFO("D-Bus Interface", "com.canonical.dbusmenu")
336- Q_PROPERTY(uint Version READ Version)
337- Q_PROPERTY(QString Status READ status)
338 public:
339- DBusMenuExporterDBus(DBusMenuExporter *m_exporter);
340-
341- uint Version() const { return 2; }
342-
343- QString status() const;
344- void setStatus(const QString &status);
345-
346-public Q_SLOTS:
347- Q_NOREPLY void Event(int id, const QString &eventId, const QDBusVariant &data, uint timestamp);
348- QDBusVariant GetProperty(int id, const QString &property);
349- uint GetLayout(int parentId, int recursionDepth, const QStringList &propertyNames, DBusMenuLayoutItem &item);
350- DBusMenuItemList GetGroupProperties(const QList<int> &ids, const QStringList &propertyNames);
351- bool AboutToShow(int id);
352-
353-Q_SIGNALS:
354- void ItemsPropertiesUpdated(DBusMenuItemList, DBusMenuItemKeysList);
355- void LayoutUpdated(uint revision, int parentId);
356- void ItemActivationRequested(int id, uint timeStamp);
357+ DBusMenuExporterDBus(const QString& objectPath, DBusMenuExporter *m_exporter);
358+
359+public: // overrides
360+ void Event(int id, const QString &eventId, const QDBusVariant &data, uint timestamp) override;
361+ QDBusVariant GetProperty(int id, const QString &property) override;
362+ uint GetLayout(int parentId, int recursionDepth, const QStringList &propertyNames, DBusMenuLayoutItem &item) override;
363+ DBusMenuItemList GetGroupProperties(const QList<int> &ids, const QStringList &propertyNames) override;
364+ bool AboutToShow(int id) override;
365
366 private:
367 DBusMenuExporter *m_exporter;
368- QString m_status;
369
370 friend class DBusMenuExporter;
371 friend class DBusMenuExporterPrivate;
372
373=== added file 'src/dbusmenuexporterdbusinterface_p.cpp'
374--- src/dbusmenuexporterdbusinterface_p.cpp 1970-01-01 00:00:00 +0000
375+++ src/dbusmenuexporterdbusinterface_p.cpp 2015-03-18 11:19:06 +0000
376@@ -0,0 +1,67 @@
377+/* This file is part of the dbusmenu-qt library
378+ Copyright 2015 Canonical
379+ Author: Nick Dedekind <nick.dedekind@canonical.com>
380+
381+ This library is free software; you can redistribute it and/or
382+ modify it under the terms of the GNU Library General Public
383+ License (LGPL) as published by the Free Software Foundation;
384+ either version 2 of the License, or (at your option) any later
385+ version.
386+
387+ This library is distributed in the hope that it will be useful,
388+ but WITHOUT ANY WARRANTY; without even the implied warranty of
389+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
390+ Library General Public License for more details.
391+
392+ You should have received a copy of the GNU Library General Public License
393+ along with this library; see the file COPYING.LIB. If not, write to
394+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
395+ Boston, MA 02110-1301, USA.
396+*/
397+
398+#include "dbusmenuexporterdbusinterface_p.h"
399+#include "dbusmenuadaptor.h"
400+
401+// Qt
402+#include <QDBusMessage>
403+#include <QEvent>
404+
405+static const char *DBUSMENU_INTERFACE = "com.canonical.dbusmenu";
406+static const char *FDO_PROPERTIES_INTERFACE = "org.freedesktop.DBus.Properties";
407+
408+DBusMenuExporterDBusInterface::DBusMenuExporterDBusInterface(const QString& objectPath, QObject *parent)
409+ : QObject(parent)
410+ , m_objectPath(objectPath)
411+ , m_status("normal")
412+{
413+ DBusMenuTypes_register();
414+
415+ new DbusmenuAdaptor(this);
416+ QDBusConnection::sessionBus().registerObject(objectPath, this, QDBusConnection::ExportAllContents);
417+}
418+
419+QString DBusMenuExporterDBusInterface::status() const
420+{
421+ return m_status;
422+}
423+
424+void DBusMenuExporterDBusInterface::setStatus(const QString& status)
425+{
426+ if (m_status == status) {
427+ return;
428+ }
429+ m_status = status;
430+
431+ QVariantMap map;
432+ map.insert("Status", QVariant(status));
433+
434+ QDBusMessage msg = QDBusMessage::createSignal(m_objectPath, FDO_PROPERTIES_INTERFACE, "PropertiesChanged");
435+ QVariantList args = QVariantList()
436+ << DBUSMENU_INTERFACE
437+ << map
438+ << QStringList() // New properties: none
439+ ;
440+ msg.setArguments(args);
441+ QDBusConnection::sessionBus().send(msg);
442+}
443+
444
445=== added file 'src/dbusmenuexporterdbusinterface_p.h'
446--- src/dbusmenuexporterdbusinterface_p.h 1970-01-01 00:00:00 +0000
447+++ src/dbusmenuexporterdbusinterface_p.h 2015-03-18 11:19:06 +0000
448@@ -0,0 +1,80 @@
449+/* This file is part of the dbusmenu-qt library
450+ Copyright 2015 Canonical
451+ Author: Nick Dedekind <nick.dedekind@canonical.com>
452+
453+ This library is free software; you can redistribute it and/or
454+ modify it under the terms of the GNU Library General Public
455+ License (LGPL) as published by the Free Software Foundation;
456+ either version 2 of the License, or (at your option) any later
457+ version.
458+
459+ This library is distributed in the hope that it will be useful,
460+ but WITHOUT ANY WARRANTY; without even the implied warranty of
461+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
462+ Library General Public License for more details.
463+
464+ You should have received a copy of the GNU Library General Public License
465+ along with this library; see the file COPYING.LIB. If not, write to
466+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
467+ Boston, MA 02110-1301, USA.
468+*/
469+#ifndef DBUSMENUEXPORTERDBUSINTERFACE_P_H
470+#define DBUSMENUEXPORTERDBUSINTERFACE_P_H
471+
472+// Local
473+#include <dbusmenutypes.h>
474+
475+// Qt
476+#include <QtCore/QObject>
477+#include <QtCore/QVariant>
478+#include <QtDBus/QDBusAbstractAdaptor>
479+#include <QtDBus/QDBusVariant>
480+
481+/**
482+ * Internal class implementing the DBus side of DBusMenuExporter
483+ * This avoid exposing the implementation of the DBusMenu spec to the outside
484+ * world.
485+ */
486+class DBusMenuExporterDBusInterface : public QObject
487+{
488+ Q_OBJECT
489+ Q_CLASSINFO("D-Bus Interface", "com.canonical.dbusmenu")
490+ Q_PROPERTY(uint Version READ Version)
491+ Q_PROPERTY(QString Status READ status)
492+public:
493+ DBusMenuExporterDBusInterface(const QString& objectPath, QObject* parent = nullptr);
494+ uint Version() const { return 2; }
495+
496+ /**
497+ * The status of the menu. Can be one of "normal" or "notice". This can be
498+ * used to notify the other side the menu should be made more visible.
499+ * For example, appmenu uses it to tell Unity panel to show/hide the menubar
500+ * when the Alt modifier is pressed/released.
501+ */
502+ QString status() const;
503+
504+ /**
505+ * Returns the status of the menu.
506+ * @ref setStatus
507+ */
508+ void setStatus(const QString &status);
509+
510+public Q_SLOTS:
511+ virtual Q_NOREPLY void Event(int id, const QString &eventId, const QDBusVariant &data, uint timestamp) = 0;
512+ virtual QDBusVariant GetProperty(int id, const QString &property) = 0;
513+ virtual uint GetLayout(int parentId, int recursionDepth, const QStringList &propertyNames, DBusMenuLayoutItem &item) = 0;
514+ virtual DBusMenuItemList GetGroupProperties(const QList<int> &ids, const QStringList &propertyNames) = 0;
515+ virtual bool AboutToShow(int id) = 0;
516+
517+Q_SIGNALS:
518+ void ItemsPropertiesUpdated(DBusMenuItemList, DBusMenuItemKeysList);
519+ void LayoutUpdated(uint revision, int parentId);
520+ void ItemActivationRequested(int id, uint timeStamp);
521+
522+private:
523+ QString m_objectPath;
524+ QString m_status;
525+};
526+
527+
528+#endif // DBUSMENUEXPORTERDBUSINTERFACE_P_H
529
530=== modified file 'src/dbusmenuexporterprivate_p.h'
531--- src/dbusmenuexporterprivate_p.h 2012-03-29 14:23:32 +0000
532+++ src/dbusmenuexporterprivate_p.h 2015-03-18 11:19:06 +0000
533@@ -23,7 +23,7 @@
534
535 // Local
536 #include "dbusmenuexporter.h"
537-#include "dbusmenutypes_p.h"
538+#include "dbusmenutypes.h"
539
540 // Qt
541 #include <QtCore/QHash>
542
543=== modified file 'src/dbusmenuimporter.cpp'
544--- src/dbusmenuimporter.cpp 2014-03-05 09:53:39 +0000
545+++ src/dbusmenuimporter.cpp 2015-03-18 11:19:06 +0000
546@@ -36,7 +36,7 @@
547 #include <QWidgetAction>
548
549 // Local
550-#include "dbusmenutypes_p.h"
551+#include "dbusmenutypes.h"
552 #include "dbusmenushortcut_p.h"
553 #include "debug_p.h"
554 #include "utils_p.h"
555@@ -199,7 +199,7 @@
556
557 void updateActionLabel(QAction *action, const QVariant &value)
558 {
559- QString text = swapMnemonicChar(value.toString(), '_', '&');
560+ QString text = Utils::swapMnemonicChar(value.toString(), '_', '&');
561 action->setText(text);
562 }
563
564
565=== added file 'src/dbusmenuinterface.cpp'
566--- src/dbusmenuinterface.cpp 1970-01-01 00:00:00 +0000
567+++ src/dbusmenuinterface.cpp 2015-03-18 11:19:06 +0000
568@@ -0,0 +1,63 @@
569+#include "dbusmenuinterface.h"
570+#include "dbusmenuinterface_p.h"
571+
572+DBusMenuInterface::DBusMenuInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent)
573+ : d(new DbusMenuInterfacePrivate(service, path, connection, this))
574+{
575+ DBusMenuTypes_register();
576+}
577+
578+uint DBusMenuInterface::version() const
579+{
580+ return d->version();
581+}
582+
583+QString DBusMenuInterface::status() const
584+{
585+ return d->status();
586+}
587+
588+bool DBusMenuInterface::isValid() const
589+{
590+ return d->isValid();
591+}
592+
593+QString DBusMenuInterface::service() const
594+{
595+ return d->service();
596+}
597+
598+QString DBusMenuInterface::path() const
599+{
600+ return d->path();
601+}
602+
603+QDBusPendingReply<bool> DBusMenuInterface::AboutToShow(int id)
604+{
605+ return d->AboutToShow(id);
606+}
607+
608+QDBusPendingReply<> DBusMenuInterface::Event(int id, const QString &eventId, const QDBusVariant &data, uint timestamp)
609+{
610+ return d->Event(id, eventId, data, timestamp);
611+}
612+
613+QDBusPendingReply<DBusMenuItemList> DBusMenuInterface::GetGroupProperties(const QList<int> &ids, const QStringList &propertyNames)
614+{
615+ return d->GetGroupProperties(ids, propertyNames);
616+}
617+
618+QDBusPendingReply<QDBusVariant> DBusMenuInterface::GetProperty(int id, const QString &name)
619+{
620+ return d->GetProperty(id, name);
621+}
622+
623+QDBusPendingReply<uint, DBusMenuLayoutItem> DBusMenuInterface::GetLayout(int parentId, int recursionDepth, const QStringList &propertyNames)
624+{
625+ return d->GetLayout(parentId, recursionDepth, propertyNames);
626+}
627+
628+QDBusReply<uint> DBusMenuInterface::GetLayout(int parentId, int recursionDepth, const QStringList &propertyNames, DBusMenuLayoutItem &layout)
629+{
630+ return d->GetLayout(parentId, recursionDepth, propertyNames, layout);
631+}
632
633=== added file 'src/dbusmenuinterface.h'
634--- src/dbusmenuinterface.h 1970-01-01 00:00:00 +0000
635+++ src/dbusmenuinterface.h 2015-03-18 11:19:06 +0000
636@@ -0,0 +1,154 @@
637+/* This file is part of the dbusmenu-qt library
638+ Copyright 2015 Canonical
639+ Author: Nick Dedekind <nick.dedekind@canonical.com>
640+
641+ This library is free software; you can redistribute it and/or
642+ modify it under the terms of the GNU Library General Public
643+ License (LGPL) as published by the Free Software Foundation;
644+ either version 2 of the License, or (at your option) any later
645+ version.
646+
647+ This library is distributed in the hope that it will be useful,
648+ but WITHOUT ANY WARRANTY; without even the implied warranty of
649+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
650+ Library General Public License for more details.
651+
652+ You should have received a copy of the GNU Library General Public License
653+ along with this library; see the file COPYING.LIB. If not, write to
654+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
655+ Boston, MA 02110-1301, USA.
656+*/
657+#ifndef DBUSMENUINTERFACE_H
658+#define DBUSMENUINTERFACE_H
659+
660+// Local
661+#include <dbusmenutypes.h>
662+class DbusMenuInterfacePrivate;
663+
664+// Qt
665+#include <QtCore/QObject>
666+#include <QtDBus/QtDBus>
667+
668+/**
669+ * Internal class implementing the DBus side of DBusMenuExporter
670+ * This avoid exposing the implementation of the DBusMenu spec to the outside
671+ * world.
672+ */
673+class DBUSMENU_EXPORT DBusMenuInterface : public QObject
674+{
675+ Q_OBJECT
676+
677+ /**
678+ * Version of the menu interface.
679+ */
680+ Q_PROPERTY(uint Version READ version)
681+
682+ /**
683+ * Status of the menu.
684+ */
685+ Q_PROPERTY(QString Status READ status)
686+public:
687+ /**
688+ * Creates a DBusMenuInterface on specified service, path & connection
689+ */
690+ DBusMenuInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject* parent = nullptr);
691+
692+ /**
693+ * Returns the version of the menu interface.
694+ */
695+ uint version() const;
696+
697+ /**
698+ * The status of the menu. Can be one of "normal" or "notice". This can be
699+ * used to notify the other side the menu should be made more visible.
700+ * For example, appmenu uses it to tell Unity panel to show/hide the menubar
701+ * when the Alt modifier is pressed/released.
702+ */
703+ QString status() const;
704+
705+ /**
706+ * Returns true if this is a valid reference to a remote object.
707+ * It returns false if there was an error during the creation of the interface
708+ */
709+ bool isValid() const;
710+
711+ /**
712+ * Returns the name of the service this interface is associated with.
713+ */
714+ QString service() const;
715+
716+ /**
717+ * Returns the object path that this interface is associated with.
718+ */
719+ QString path() const;
720+
721+public Q_SLOTS:
722+ /**
723+ * This is called to notify the application that it is about
724+ * to show the menu under the specified item.
725+ */
726+ QDBusPendingReply<bool> AboutToShow(int id);
727+
728+ /**
729+ * This is called by the applet to notify the application an event happened on a
730+ * menu item.
731+ */
732+ QDBusPendingReply<> Event(int id, const QString &eventId, const QDBusVariant &data, uint timestamp);
733+
734+ /**
735+ * Returns the list of items which are children of @p parentId.
736+ */
737+ QDBusPendingReply<DBusMenuItemList> GetGroupProperties(const QList<int> &ids, const QStringList &propertyNames);
738+
739+ /**
740+ * Get a signal property on a single item. This is not useful if you're
741+ * going to implement this interface, it should only be used if you're
742+ * debugging via a commandline tool.
743+ */
744+ QDBusPendingReply<QDBusVariant> GetProperty(int id, const QString &name);
745+
746+ /**
747+ * Provides the layout and propertiers that are attached to the entries
748+ * that are in the layout. It only gives the items that are children
749+ * of the item that is specified in @p parentId. It will return all of the
750+ * properties or specific ones depending of the value in @p propertyNames.
751+ */
752+ QDBusPendingReply<uint, DBusMenuLayoutItem> GetLayout(int parentId, int recursionDepth, const QStringList &propertyNames);
753+
754+ /**
755+ * Provides the layout and propertiers that are attached to the entries
756+ * that are in the layout. It only gives the items that are children
757+ * of the item that is specified in @p parentId. It will return all of the
758+ * properties or specific ones depending of the value @p propertyNames.
759+ */
760+ QDBusReply<uint> GetLayout(int parentId, int recursionDepth, const QStringList &propertyNames, DBusMenuLayoutItem &layout);
761+
762+Q_SIGNALS: // SIGNALS
763+ /**
764+ * The server is requesting that all clients displaying this
765+ * menu open it to the user. This would be for things like
766+ * hotkeys that when the user presses them the menu should
767+ * open and display itself to the user.
768+ */
769+ void ItemActivationRequested(int id, uint timestamp);
770+
771+ /**
772+ * Triggered when there are lots of property updates across many items
773+ * so they all get grouped into a single dbus message. The format is
774+ * the ID of the item with a hashtable of names and values for those
775+ * properties.
776+ */
777+ void ItemsPropertiesUpdated(DBusMenuItemList updatedProps, DBusMenuItemKeysList removedProps);
778+
779+ /**
780+ * Triggered by the application to notify display of a layout update, up to
781+ * revision
782+ */
783+ void LayoutUpdated(uint revision, int parent);
784+
785+private:
786+ DbusMenuInterfacePrivate* d;
787+};
788+
789+
790+#endif // DBUSMENUINTERFACE_H
791
792=== added file 'src/dbusmenuproperty.h'
793--- src/dbusmenuproperty.h 1970-01-01 00:00:00 +0000
794+++ src/dbusmenuproperty.h 2015-03-18 11:19:06 +0000
795@@ -0,0 +1,78 @@
796+#ifndef DBUSMENUPROPERTY_H
797+#define DBUSMENUPROPERTY_H
798+
799+#ifndef DOXYGEN_SHOULD_SKIP_THIS
800+
801+// Qt
802+#include <QtCore/QVariantMap>
803+
804+// Local
805+#include <dbusmenu_export.h>
806+
807+class QKeySequence;
808+class QByteArray;
809+class QString;
810+
811+//// DBusMenuProperty
812+/**
813+ * Structure which contains the names of the common properties
814+ * for a menu item.
815+ */
816+struct DBUSMENU_EXPORT DBusMenuProperty
817+{
818+ static const char* Type;
819+ static const char* Label;
820+ static const char* Enabled;
821+ static const char* Visible;
822+ static const char* IconName;
823+ static const char* IconData;
824+ static const char* Shortcut;
825+ static const char* ToggleType;
826+ static const char* ToggleState;
827+ static const char* ChildrenDisplay;
828+};
829+
830+//// DBusMenuProperties
831+/**
832+ * A map of properties for the dbus with easy accessors for
833+ * the common properties
834+ */
835+struct DBUSMENU_EXPORT DBusMenuProperties: public QVariantMap
836+{
837+ QString type() const;
838+ void setType(const QString&);
839+
840+ QString label() const;
841+ void setLabel(const QString&);
842+
843+ bool enabled() const;
844+ void setEnabled(bool);
845+
846+ bool visible() const;
847+ void setVisible(bool);
848+
849+ QString iconName() const;
850+ void setIconName(const QString&);
851+
852+ QByteArray iconData() const;
853+ void setIconData(const QByteArray&);
854+
855+ QKeySequence shortcut() const;
856+ void setShortcut(const QKeySequence&);
857+
858+ QString toggleType() const;
859+ void setToggleType(const QString&);
860+
861+ int toggleState() const;
862+ void setToggleState(int);
863+
864+ bool childrenDisplay() const;
865+ void setChildrenDisplay(bool);
866+
867+ DBusMenuProperties& operator=(const QVariantMap& rhs);
868+};
869+
870+#endif /* DOXYGEN_SHOULD_SKIP_THIS */
871+
872+
873+#endif // DBUSMENUPROPERTY_H
874
875=== modified file 'src/dbusmenushortcut_p.cpp'
876--- src/dbusmenushortcut_p.cpp 2011-04-12 09:12:18 +0000
877+++ src/dbusmenushortcut_p.cpp 2015-03-18 11:19:06 +0000
878@@ -44,6 +44,8 @@
879 // cf https://bugs.launchpad.net/libdbusmenu-qt/+bug/712565
880 {"+", "plus"},
881 {"-", "minus"},
882+ {"+", "KP_Add"},
883+ {"-", "KP_Subtract"},
884 {0, 0}
885 };
886
887
888=== renamed file 'src/dbusmenutypes_p.cpp' => 'src/dbusmenutypes.cpp'
889--- src/dbusmenutypes_p.cpp 2011-02-23 13:23:56 +0000
890+++ src/dbusmenutypes.cpp 2015-03-18 11:19:06 +0000
891@@ -18,7 +18,7 @@
892 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
893 Boston, MA 02110-1301, USA.
894 */
895-#include "dbusmenutypes_p.h"
896+#include "dbusmenutypes.h"
897
898 // Local
899 #include <dbusmenushortcut_p.h>
900@@ -27,6 +27,18 @@
901 // Qt
902 #include <QDBusArgument>
903 #include <QDBusMetaType>
904+#include <QKeySequence>
905+
906+const char* DBusMenuProperty::Type = "type";
907+const char* DBusMenuProperty::Label = "label";
908+const char* DBusMenuProperty::Enabled = "enabled";
909+const char* DBusMenuProperty::Visible = "visible";
910+const char* DBusMenuProperty::IconName = "icon-name";
911+const char* DBusMenuProperty::IconData = "icon-data";
912+const char* DBusMenuProperty::Shortcut = "shortcut";
913+const char* DBusMenuProperty::ToggleType = "toggle-type";
914+const char* DBusMenuProperty::ToggleState = "toggle-state";
915+const char* DBusMenuProperty::ChildrenDisplay = "children-display";
916
917 //// DBusMenuItem
918 QDBusArgument &operator<<(QDBusArgument &argument, const DBusMenuItem &obj)
919@@ -95,6 +107,16 @@
920 return argument;
921 }
922
923+bool operator==(const DBusMenuLayoutItem& lhs, const DBusMenuLayoutItem& rhs)
924+{
925+ return lhs.id == rhs.id && lhs.properties == rhs.properties && lhs.children == rhs.children;
926+}
927+
928+bool operator!=(const DBusMenuLayoutItem& lhs, const DBusMenuLayoutItem& rhs)
929+{
930+ return !(lhs == rhs);
931+}
932+
933 void DBusMenuTypes_register()
934 {
935 static bool registered = false;
936@@ -110,3 +132,122 @@
937 qDBusRegisterMetaType<DBusMenuShortcut>();
938 registered = true;
939 }
940+
941+QString DBusMenuProperties::type() const
942+{
943+ return value(DBusMenuProperty::Type, "standard").toString();
944+}
945+
946+void DBusMenuProperties::setType(const QString &type)
947+{
948+ insert(DBusMenuProperty::Type, type);
949+}
950+
951+QString DBusMenuProperties::label() const
952+{
953+ return value(DBusMenuProperty::Label, "").toString();
954+}
955+
956+void DBusMenuProperties::setLabel(const QString &label)
957+{
958+ insert(DBusMenuProperty::Label, label);
959+}
960+
961+bool DBusMenuProperties::enabled() const
962+{
963+ return value(DBusMenuProperty::Enabled, true).toBool();
964+}
965+
966+void DBusMenuProperties::setEnabled(bool enabled)
967+{
968+ insert(DBusMenuProperty::Enabled, enabled);
969+}
970+
971+bool DBusMenuProperties::visible() const
972+{
973+ return value(DBusMenuProperty::Visible, true).toBool();
974+}
975+
976+void DBusMenuProperties::setVisible(bool enabled)
977+{
978+ insert(DBusMenuProperty::Visible, enabled);
979+}
980+
981+QString DBusMenuProperties::iconName() const
982+{
983+ return value(DBusMenuProperty::IconName, "").toString();
984+}
985+
986+void DBusMenuProperties::setIconName(const QString &iconName)
987+{
988+ insert(DBusMenuProperty::IconName, iconName);
989+}
990+
991+QByteArray DBusMenuProperties::iconData() const
992+{
993+ return value(DBusMenuProperty::IconData, QVariant()).toByteArray();
994+}
995+
996+void DBusMenuProperties::setIconData(const QByteArray &iconData)
997+{
998+ insert(DBusMenuProperty::IconData, iconData);
999+}
1000+
1001+QKeySequence DBusMenuProperties::shortcut() const
1002+{
1003+ QKeySequence seq;
1004+
1005+ QVariant var = value(DBusMenuProperty::Shortcut, QVariant());
1006+
1007+ if (var.userType() == qMetaTypeId<QDBusArgument>()) {
1008+ QDBusArgument arg = var.value<QDBusArgument>();
1009+
1010+ DBusMenuShortcut shortcut;
1011+ arg >> shortcut;
1012+
1013+ return shortcut.toKeySequence();
1014+ }
1015+ return seq;
1016+}
1017+
1018+void DBusMenuProperties::setShortcut(const QKeySequence &keySequence)
1019+{
1020+ insert(DBusMenuProperty::Shortcut, keySequence);
1021+}
1022+
1023+QString DBusMenuProperties::toggleType() const
1024+{
1025+ return value(DBusMenuProperty::ToggleType, "").toString();
1026+}
1027+
1028+void DBusMenuProperties::setToggleType(const QString &toggleType)
1029+{
1030+ insert(DBusMenuProperty::ToggleType, toggleType);
1031+}
1032+
1033+int DBusMenuProperties::toggleState() const
1034+{
1035+ return value(DBusMenuProperty::ToggleState, -1).toInt();
1036+}
1037+
1038+void DBusMenuProperties::setToggleState(int toggleType)
1039+{
1040+ insert(DBusMenuProperty::ToggleState, toggleType);
1041+}
1042+
1043+bool DBusMenuProperties::childrenDisplay() const
1044+{
1045+ return value(DBusMenuProperty::ChildrenDisplay, false).toBool();
1046+}
1047+
1048+void DBusMenuProperties::setChildrenDisplay(bool childrenDisplay)
1049+{
1050+ insert(DBusMenuProperty::ChildrenDisplay, childrenDisplay);
1051+
1052+}
1053+
1054+DBusMenuProperties &DBusMenuProperties::operator=(const QVariantMap &rhs)
1055+{
1056+ QVariantMap::operator=(rhs);
1057+ return *this;
1058+}
1059
1060=== renamed file 'src/dbusmenutypes_p.h' => 'src/dbusmenutypes.h'
1061--- src/dbusmenutypes_p.h 2011-02-23 13:23:56 +0000
1062+++ src/dbusmenutypes.h 2015-03-18 11:19:06 +0000
1063@@ -18,8 +18,8 @@
1064 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
1065 Boston, MA 02110-1301, USA.
1066 */
1067-#ifndef DBUSMENUTYPES_P_H
1068-#define DBUSMENUTYPES_P_H
1069+#ifndef DBUSMENUTYPES_H
1070+#define DBUSMENUTYPES_H
1071
1072 // Qt
1073 #include <QtCore/QList>
1074@@ -28,6 +28,7 @@
1075
1076 // Local
1077 #include <dbusmenu_export.h>
1078+#include <dbusmenuproperty.h>
1079
1080 class QDBusArgument;
1081
1082@@ -37,8 +38,11 @@
1083 */
1084 struct DBUSMENU_EXPORT DBusMenuItem
1085 {
1086+ /// Id of the menu item
1087 int id;
1088- QVariantMap properties;
1089+
1090+ /// Properties for the menu item
1091+ DBusMenuProperties properties;
1092 };
1093
1094 Q_DECLARE_METATYPE(DBusMenuItem)
1095@@ -57,7 +61,10 @@
1096 */
1097 struct DBUSMENU_EXPORT DBusMenuItemKeys
1098 {
1099+ /// Id of the menu item
1100 int id;
1101+
1102+ /// Properties for the menu item
1103 QStringList properties;
1104 };
1105
1106@@ -75,11 +82,15 @@
1107 * Represents an item with its children. GetLayout() returns a
1108 * DBusMenuLayoutItemList.
1109 */
1110-struct DBusMenuLayoutItem;
1111 struct DBUSMENU_EXPORT DBusMenuLayoutItem
1112 {
1113+ /// Id of the menu item
1114 int id;
1115- QVariantMap properties;
1116+
1117+ /// Id of the menu item
1118+ DBusMenuProperties properties;
1119+
1120+ /// Children of the menu item
1121 QList<DBusMenuLayoutItem> children;
1122 };
1123
1124@@ -88,9 +99,13 @@
1125 DBUSMENU_EXPORT QDBusArgument &operator<<(QDBusArgument &argument, const DBusMenuLayoutItem &);
1126 DBUSMENU_EXPORT const QDBusArgument &operator>>(const QDBusArgument &argument, DBusMenuLayoutItem &);
1127
1128+DBUSMENU_EXPORT bool operator==(const DBusMenuLayoutItem& lhs, const DBusMenuLayoutItem& rhs);
1129+DBUSMENU_EXPORT bool operator!=(const DBusMenuLayoutItem& lhs, const DBusMenuLayoutItem& rhs);
1130+
1131 typedef QList<DBusMenuLayoutItem> DBusMenuLayoutItemList;
1132
1133 Q_DECLARE_METATYPE(DBusMenuLayoutItemList)
1134
1135 void DBusMenuTypes_register();
1136+
1137 #endif /* DBUSMENUTYPES_P_H */
1138
1139=== added directory 'src/qpa'
1140=== added file 'src/qpa/exportedplatformmenubar.cpp'
1141--- src/qpa/exportedplatformmenubar.cpp 1970-01-01 00:00:00 +0000
1142+++ src/qpa/exportedplatformmenubar.cpp 2015-03-18 11:19:06 +0000
1143@@ -0,0 +1,377 @@
1144+/* This file is part of the dbusmenu-qt library
1145+ Copyright 2015 Canonical
1146+ Author: Nick Dedekind <nick.dedekind@canonical.com>
1147+
1148+ This library is free software; you can redistribute it and/or
1149+ modify it under the terms of the GNU Library General Public
1150+ License (LGPL) as published by the Free Software Foundation;
1151+ either version 2 of the License, or (at your option) any later
1152+ version.
1153+
1154+ This library is distributed in the hope that it will be useful,
1155+ but WITHOUT ANY WARRANTY; without even the implied warranty of
1156+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1157+ Library General Public License for more details.
1158+
1159+ You should have received a copy of the GNU Library General Public License
1160+ along with this library; see the file COPYING.LIB. If not, write to
1161+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
1162+ Boston, MA 02110-1301, USA.
1163+*/
1164+
1165+// Local
1166+#include "exportedplatformmenubar.h"
1167+#include "exportedplatformmenubar_p.h"
1168+#include "qpadbusmenuexporter_p.h"
1169+#include "logging_p.h"
1170+
1171+// Qt
1172+#include <QWindow>
1173+#include <QWidget>
1174+
1175+#define MENU_ID(x) (qobject_cast<ExportedPlatformMenu*>(x) ? qobject_cast<ExportedPlatformMenu*>(x)->id() : -1)
1176+#define MENU_ITEM_ID(x) (qobject_cast<ExportedPlatformMenuItem*>(x) ? qobject_cast<ExportedPlatformMenuItem*>(x)->id() : -1)
1177+
1178+ExportedPlatformMenuBar::ExportedPlatformMenuBar(const QString& exportPath)
1179+ : d(new ExportedPlatformMenuBarPrivate)
1180+{
1181+ LOG;
1182+
1183+ d->m_objectPath = exportPath;
1184+ new QPADBusMenuExporter(exportPath, this);
1185+}
1186+
1187+ExportedPlatformMenuBar::~ExportedPlatformMenuBar()
1188+{
1189+ LOG;
1190+}
1191+
1192+QString ExportedPlatformMenuBar::exportedPath() const
1193+{
1194+ return d->m_objectPath;
1195+}
1196+
1197+void
1198+ExportedPlatformMenuBar::insertMenu(QPlatformMenu *menu, QPlatformMenu *before)
1199+{
1200+ LOG << MENU_ID(menu) << " before:" << before;
1201+
1202+ if (!before) {
1203+ d->m_menus.push_back(menu);
1204+ } else {
1205+ for (auto iter = d->m_menus.begin(); iter != d->m_menus.end(); ++iter) {
1206+ if (*iter == before) {
1207+ d->m_menus.insert(iter, menu);
1208+ break;
1209+ }
1210+ }
1211+ }
1212+
1213+ Q_EMIT menuInserted(menu);
1214+}
1215+
1216+void
1217+ExportedPlatformMenuBar::removeMenu(QPlatformMenu *menu)
1218+{
1219+ LOG << menu;
1220+
1221+ for (auto iter = d->m_menus.begin(); iter != d->m_menus.end(); ++iter) {
1222+ if (*iter == menu) {
1223+ iter = d->m_menus.erase(iter);
1224+ }
1225+ }
1226+
1227+ Q_EMIT menuRemoved(menu);
1228+}
1229+
1230+void
1231+ExportedPlatformMenuBar::syncMenu(QPlatformMenu *menu)
1232+{
1233+ LOG_VAR(menu);
1234+ QMetaObject::invokeMethod(menu, "propertyUpdated");
1235+}
1236+
1237+void
1238+ExportedPlatformMenuBar::handleReparent(QWindow *newParentWindow)
1239+{
1240+ LOG_VAR(newParentWindow);
1241+}
1242+
1243+QPlatformMenu *
1244+ExportedPlatformMenuBar::menuForTag(quintptr tag) const
1245+{
1246+ for (auto iter = d->m_menus.begin(); iter != d->m_menus.end(); ++iter) {
1247+ if ((*iter)->tag() == tag) {
1248+ return *iter;
1249+ }
1250+ }
1251+ return nullptr;
1252+}
1253+
1254+QPlatformMenu *
1255+ExportedPlatformMenuBar::menuAt(int position) const
1256+{
1257+ if (position < 0 || position >= d->m_menus.count()) return nullptr;
1258+ return d->m_menus.at(position);
1259+}
1260+
1261+uint ExportedPlatformMenuBar::menuCount()
1262+{
1263+ return d->m_menus.count();
1264+}
1265+
1266+//////////////////////////////////////////////////////////////
1267+
1268+ExportedPlatformMenu::ExportedPlatformMenu()
1269+ : QPlatformMenu()
1270+ , d(new ExportedPlatformMenuPrivate)
1271+{
1272+ LOG << id();
1273+}
1274+
1275+ExportedPlatformMenu::~ExportedPlatformMenu()
1276+{
1277+ LOG << id();
1278+}
1279+
1280+void ExportedPlatformMenu::insertMenuItem(QPlatformMenuItem *menuItem, QPlatformMenuItem *before)
1281+{
1282+ LOG << MENU_ITEM_ID(menuItem) << " before:" << before << " on: " << id();
1283+
1284+ if (!before) {
1285+ d->m_menuItems.push_back(menuItem);
1286+ } else {
1287+ for (auto iter = d->m_menuItems.begin(); iter != d->m_menuItems.end(); ++iter) {
1288+ if (*iter == before) {
1289+ d->m_menuItems.insert(iter, menuItem);
1290+ break;
1291+ }
1292+ }
1293+ }
1294+
1295+ Q_EMIT menuItemInserted(menuItem);
1296+}
1297+
1298+void ExportedPlatformMenu::removeMenuItem(QPlatformMenuItem *menuItem)
1299+{
1300+ LOG_VAR(menuItem) << " on: " << id();
1301+
1302+ QMutableListIterator<QPlatformMenuItem*> iter(d->m_menuItems);
1303+ while (iter.hasNext()) {
1304+ if (iter.next() == menuItem) {
1305+ iter.remove();
1306+ }
1307+ }
1308+
1309+ Q_EMIT menuItemRemoved(menuItem);
1310+}
1311+
1312+void ExportedPlatformMenu::syncMenuItem(QPlatformMenuItem *menuItem)
1313+{
1314+ LOG_VAR(menuItem) << " from: " << id();
1315+ QMetaObject::invokeMethod(menuItem, "propertyUpdated");
1316+}
1317+
1318+void ExportedPlatformMenu::syncSeparatorsCollapsible(bool enable)
1319+{
1320+ LOG_VAR(enable) << " on: " << id();
1321+ Q_EMIT propertyUpdated();
1322+}
1323+
1324+void ExportedPlatformMenu::setTag(quintptr tag)
1325+{
1326+ LOG_VAR(tag) << " on: " << id();
1327+ d->m_tag = tag;
1328+}
1329+
1330+quintptr ExportedPlatformMenu::tag() const
1331+{
1332+ return d->m_tag;
1333+}
1334+
1335+void ExportedPlatformMenu::setText(const QString &text)
1336+{
1337+ LOG_VAR(text) << " on: " << id();
1338+ ExportedPlatformMenuPrivate::set_text(this, text);
1339+ Q_EMIT propertyUpdated();
1340+}
1341+
1342+void ExportedPlatformMenu::setIcon(const QIcon &icon)
1343+{
1344+ LOG_VAR(icon) << " on: " << id();
1345+ ExportedPlatformMenuPrivate::set_icon(this, icon);
1346+ Q_EMIT propertyUpdated();
1347+}
1348+
1349+void ExportedPlatformMenu::setEnabled(bool isEnabled)
1350+{
1351+ LOG_VAR(isEnabled) << " on: " << id();
1352+ ExportedPlatformMenuPrivate::set_enabled(this, isEnabled);
1353+ Q_EMIT propertyUpdated();
1354+}
1355+
1356+void ExportedPlatformMenu::setVisible(bool isVisible)
1357+{
1358+ LOG_VAR(isVisible) << " on: " << id();
1359+ ExportedPlatformMenuPrivate::set_visible(this, isVisible);
1360+ Q_EMIT propertyUpdated();
1361+}
1362+
1363+void ExportedPlatformMenu::setMinimumWidth(int width)
1364+{
1365+ LOG_VAR(width) << " on: " << id();
1366+ Q_EMIT propertyUpdated();
1367+}
1368+
1369+void ExportedPlatformMenu::setFont(const QFont &font)
1370+{
1371+ LOG_VAR(font) << " on: " << id();
1372+ Q_EMIT propertyUpdated();
1373+}
1374+
1375+QPlatformMenuItem *ExportedPlatformMenu::menuItemAt(int position) const
1376+{
1377+ if (position < 0 || position >= d->m_menuItems.count()) return nullptr;
1378+ return d->m_menuItems.at(position);
1379+}
1380+
1381+QPlatformMenuItem *ExportedPlatformMenu::menuItemForTag(quintptr tag) const
1382+{
1383+ for (auto iter = d->m_menuItems.begin(); iter != d->m_menuItems.end(); ++iter) {
1384+ if ((*iter)->tag() == tag) {
1385+ return *iter;
1386+ }
1387+ }
1388+ return nullptr;
1389+}
1390+
1391+uint ExportedPlatformMenu::menuItemCount()
1392+{
1393+ return d->m_menuItems.count();
1394+}
1395+
1396+QPlatformMenuItem *ExportedPlatformMenu::createMenuItem() const
1397+{
1398+ return new ExportedPlatformMenuItem();
1399+}
1400+
1401+int ExportedPlatformMenu::id() const
1402+{
1403+ return d->m_id;
1404+}
1405+
1406+//////////////////////////////////////////////////////////////
1407+
1408+ExportedPlatformMenuItem::ExportedPlatformMenuItem()
1409+ : d(new ExportedPlatformMenuItemPrivate)
1410+{
1411+ LOG << id();
1412+}
1413+
1414+ExportedPlatformMenuItem::~ExportedPlatformMenuItem()
1415+{
1416+ LOG << id();
1417+}
1418+
1419+void ExportedPlatformMenuItem::setTag(quintptr tag)
1420+{
1421+ LOG_VAR(tag) << " on: " << id();
1422+ d->m_tag = tag;
1423+}
1424+
1425+quintptr ExportedPlatformMenuItem::tag() const
1426+{
1427+ return d->m_tag;
1428+}
1429+
1430+void ExportedPlatformMenuItem::setText(const QString &text)
1431+{
1432+ LOG_VAR(text) << " on: " << id();
1433+ ExportedPlatformMenuItemPrivate::set_text(this, text);
1434+ Q_EMIT propertyUpdated();
1435+}
1436+
1437+void ExportedPlatformMenuItem::setIcon(const QIcon &icon)
1438+{
1439+ LOG_VAR(icon) << " on: " << id();
1440+ ExportedPlatformMenuItemPrivate::set_icon(this, icon);
1441+ Q_EMIT propertyUpdated();
1442+}
1443+
1444+void ExportedPlatformMenuItem::setMenu(QPlatformMenu *menu)
1445+{
1446+ LOG << MENU_ID(menu) << " on: " << id();
1447+ d->m_menu = menu;
1448+ Q_EMIT propertyUpdated();
1449+}
1450+
1451+void ExportedPlatformMenuItem::setVisible(bool isVisible)
1452+{
1453+ LOG_VAR(isVisible) << " on: " << id();
1454+ ExportedPlatformMenuItemPrivate::set_visible(this, isVisible);
1455+ Q_EMIT propertyUpdated();
1456+}
1457+
1458+void ExportedPlatformMenuItem::setIsSeparator(bool isSeparator)
1459+{
1460+ LOG_VAR(isSeparator) << " on: " << id();
1461+ ExportedPlatformMenuItemPrivate::set_separator(this, isSeparator);
1462+ Q_EMIT propertyUpdated();
1463+}
1464+
1465+void ExportedPlatformMenuItem::setFont(const QFont &font)
1466+{
1467+ LOG_VAR(font) << " on: " << id();
1468+ Q_EMIT propertyUpdated();
1469+}
1470+
1471+void ExportedPlatformMenuItem::setRole(QPlatformMenuItem::MenuRole role)
1472+{
1473+ LOG_VAR(role) << " on: " << id();
1474+ Q_EMIT propertyUpdated();
1475+}
1476+
1477+void ExportedPlatformMenuItem::setCheckable(bool checkable)
1478+{
1479+ LOG_VAR(checkable) << " on: " << id();
1480+ ExportedPlatformMenuItemPrivate::set_checkable(this, checkable);
1481+ Q_EMIT propertyUpdated();
1482+}
1483+
1484+void ExportedPlatformMenuItem::setChecked(bool isChecked)
1485+{
1486+ LOG_VAR(isChecked) << " on: " << id();
1487+ ExportedPlatformMenuItemPrivate::set_checked(this, isChecked);
1488+ Q_EMIT propertyUpdated();
1489+}
1490+
1491+void ExportedPlatformMenuItem::setShortcut(const QKeySequence &shortcut)
1492+{
1493+ LOG_VAR(shortcut) << " on: " << id();
1494+ ExportedPlatformMenuItemPrivate::set_shortcut(this, shortcut);
1495+ Q_EMIT propertyUpdated();
1496+}
1497+
1498+void ExportedPlatformMenuItem::setEnabled(bool enabled)
1499+{
1500+ LOG_VAR(enabled) << " on: " << id();
1501+ ExportedPlatformMenuItemPrivate::set_enabled(this, enabled);
1502+ Q_EMIT propertyUpdated();
1503+}
1504+
1505+void ExportedPlatformMenuItem::setIconSize(int size)
1506+{
1507+ LOG_VAR(size) << " on: " << id();
1508+ ExportedPlatformMenuItemPrivate::set_iconSize(this, size);
1509+ Q_EMIT propertyUpdated();
1510+}
1511+
1512+int ExportedPlatformMenuItem::id() const
1513+{
1514+ return d->m_id;
1515+}
1516+
1517+QPlatformMenu *ExportedPlatformMenuItem::menu() const
1518+{
1519+ return d->m_menu;
1520+}
1521
1522=== added file 'src/qpa/exportedplatformmenubar.h'
1523--- src/qpa/exportedplatformmenubar.h 1970-01-01 00:00:00 +0000
1524+++ src/qpa/exportedplatformmenubar.h 2015-03-18 11:19:06 +0000
1525@@ -0,0 +1,136 @@
1526+/* This file is part of the dbusmenu-qt library
1527+ Copyright 2015 Canonical
1528+ Author: Nick Dedekind <nick.dedekind@canonical.com>
1529+
1530+ This library is free software; you can redistribute it and/or
1531+ modify it under the terms of the GNU Library General Public
1532+ License (LGPL) as published by the Free Software Foundation;
1533+ either version 2 of the License, or (at your option) any later
1534+ version.
1535+
1536+ This library is distributed in the hope that it will be useful,
1537+ but WITHOUT ANY WARRANTY; without even the implied warranty of
1538+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1539+ Library General Public License for more details.
1540+
1541+ You should have received a copy of the GNU Library General Public License
1542+ along with this library; see the file COPYING.LIB. If not, write to
1543+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
1544+ Boston, MA 02110-1301, USA.
1545+*/
1546+#ifndef EXPORTEDPLATFORMMENUBAR_H
1547+#define EXPORTEDPLATFORMMENUBAR_H
1548+
1549+#include <qpa/qplatformmenu.h>
1550+class ExportedPlatformMenuBarPrivate;
1551+class ExportedPlatformMenuPrivate;
1552+class ExportedPlatformMenuItemPrivate;
1553+class ExportedPlatformMenu;
1554+class ExportedPlatformMenuItem;
1555+
1556+// Local
1557+#include <dbusmenu_export.h>
1558+
1559+class DBUSMENU_EXPORT ExportedPlatformMenuBar : public QPlatformMenuBar
1560+{
1561+ Q_OBJECT
1562+public:
1563+ ExportedPlatformMenuBar(const QString& exportPath);
1564+ ~ExportedPlatformMenuBar();
1565+
1566+ QString exportedPath() const;
1567+
1568+ virtual void insertMenu(QPlatformMenu *menu, QPlatformMenu* before) override;
1569+ virtual void removeMenu(QPlatformMenu *menu) override;
1570+ virtual void syncMenu(QPlatformMenu *menuItem) override;
1571+ virtual void handleReparent(QWindow *newParentWindow) override;
1572+ virtual QPlatformMenu *menuForTag(quintptr tag) const override;
1573+
1574+ QPlatformMenu *menuAt(int position) const;
1575+ uint menuCount();
1576+
1577+Q_SIGNALS:
1578+ void menuInserted(QPlatformMenu *menu);
1579+ void menuRemoved(QPlatformMenu *menu);
1580+
1581+private:
1582+ ExportedPlatformMenuBarPrivate *const d;
1583+ friend class ExportedPlatformMenuBarPrivate;
1584+};
1585+
1586+class DBUSMENU_EXPORT ExportedPlatformMenu : public QPlatformMenu
1587+{
1588+ Q_OBJECT
1589+public:
1590+ ExportedPlatformMenu();
1591+ ~ExportedPlatformMenu();
1592+
1593+ virtual void insertMenuItem(QPlatformMenuItem *menuItem, QPlatformMenuItem *before) override;
1594+ virtual void removeMenuItem(QPlatformMenuItem *menuItem) override;
1595+ virtual void syncMenuItem(QPlatformMenuItem *menuItem) override;
1596+ virtual void syncSeparatorsCollapsible(bool enable) override;
1597+
1598+ virtual void setTag(quintptr tag) override;
1599+ virtual quintptr tag() const override;
1600+
1601+ virtual void setText(const QString &text) override;
1602+ virtual void setIcon(const QIcon &icon) override;
1603+ virtual void setEnabled(bool isEnabled) override;
1604+ virtual void setVisible(bool isVisible) override;
1605+ virtual void setMinimumWidth(int width) override;
1606+ virtual void setFont(const QFont &font) override;
1607+
1608+ virtual QPlatformMenuItem *menuItemAt(int position) const override;
1609+ virtual QPlatformMenuItem *menuItemForTag(quintptr tag) const override;
1610+ uint menuItemCount();
1611+
1612+ virtual QPlatformMenuItem *createMenuItem() const override;
1613+
1614+ int id() const;
1615+
1616+Q_SIGNALS:
1617+ void menuItemInserted(QPlatformMenuItem *menuItem);
1618+ void menuItemRemoved(QPlatformMenuItem *menuItem);
1619+
1620+ void propertyUpdated();
1621+
1622+private:
1623+ ExportedPlatformMenuPrivate *const d;
1624+ friend class ExportedPlatformMenuPrivate;
1625+};
1626+
1627+
1628+class DBUSMENU_EXPORT ExportedPlatformMenuItem : public QPlatformMenuItem
1629+{
1630+ Q_OBJECT
1631+public:
1632+ ExportedPlatformMenuItem();
1633+ ~ExportedPlatformMenuItem();
1634+
1635+ virtual void setTag(quintptr tag) override;
1636+ virtual quintptr tag() const override;
1637+
1638+ virtual void setText(const QString &text) override;
1639+ virtual void setIcon(const QIcon &icon) override;
1640+ virtual void setMenu(QPlatformMenu *menu) override;
1641+ virtual void setVisible(bool isVisible) override;
1642+ virtual void setIsSeparator(bool isSeparator) override;
1643+ virtual void setFont(const QFont &font) override;
1644+ virtual void setRole(MenuRole role) override;
1645+ virtual void setCheckable(bool checkable) override;
1646+ virtual void setChecked(bool isChecked) override;
1647+ virtual void setShortcut(const QKeySequence& shortcut) override;
1648+ virtual void setEnabled(bool enabled) override;
1649+ virtual void setIconSize(int size) override;
1650+
1651+ int id() const;
1652+ QPlatformMenu* menu() const;
1653+
1654+Q_SIGNALS:
1655+ void propertyUpdated();
1656+
1657+private:
1658+ ExportedPlatformMenuItemPrivate *const d;
1659+ friend class ExportedPlatformMenuItemPrivate;
1660+};
1661+#endif // EXPORTEDPLATFORMMENUBAR_H
1662
1663=== added file 'src/qpa/exportedplatformmenubar_p.cpp'
1664--- src/qpa/exportedplatformmenubar_p.cpp 1970-01-01 00:00:00 +0000
1665+++ src/qpa/exportedplatformmenubar_p.cpp 2015-03-18 11:19:06 +0000
1666@@ -0,0 +1,129 @@
1667+/* This file is part of the dbusmenu-qt library
1668+ Copyright 2015 Canonical
1669+ Author: Nick Dedekind <nick.dedekind@canonical.com>
1670+
1671+ This library is free software; you can redistribute it and/or
1672+ modify it under the terms of the GNU Library General Public
1673+ License (LGPL) as published by the Free Software Foundation;
1674+ either version 2 of the License, or (at your option) any later
1675+ version.
1676+
1677+ This library is distributed in the hope that it will be useful,
1678+ but WITHOUT ANY WARRANTY; without even the implied warranty of
1679+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1680+ Library General Public License for more details.
1681+
1682+ You should have received a copy of the GNU Library General Public License
1683+ along with this library; see the file COPYING.LIB. If not, write to
1684+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
1685+ Boston, MA 02110-1301, USA.
1686+*/
1687+
1688+// Local
1689+#include "exportedplatformmenubar_p.h"
1690+#include "dbusmenushortcut_p.h"
1691+#include "debug_p.h"
1692+#include "utils_p.h"
1693+
1694+// Qt
1695+#include <QBuffer>
1696+
1697+int nextMenuId = 1;
1698+
1699+void insertIconProperty(QVariantMap *map, const QIcon& icon)
1700+{
1701+ // provide the icon name for per-theme lookups
1702+ const QString iconName = icon.name();
1703+ if (!iconName.isEmpty()) {
1704+ map->insert(DBusMenuProperty::IconName, iconName);
1705+ }
1706+
1707+ if (!icon.isNull()) {
1708+ QBuffer buffer;
1709+ icon.pixmap(16).save(&buffer, "PNG");
1710+ map->insert(DBusMenuProperty::IconData, buffer.data());
1711+ }
1712+}
1713+
1714+ExportedPlatformMenuBarPrivate::ExportedPlatformMenuBarPrivate()
1715+{
1716+}
1717+
1718+//////////////////////////////////////////////////////
1719+
1720+ExportedPlatformMenuPrivate::ExportedPlatformMenuPrivate()
1721+ : m_tag(0)
1722+ , m_id(nextMenuId++)
1723+{
1724+
1725+}
1726+
1727+QVariantMap ExportedPlatformMenuPrivate::propertiesForMenu(const ExportedPlatformMenu *menu)
1728+{
1729+ QVariantMap map;
1730+ map.insert(DBusMenuProperty::ChildrenDisplay, "submenu");
1731+ map.insert(DBusMenuProperty::Label, Utils::swapMnemonicChar(ExportedPlatformMenuPrivate::get_text(menu), '&', '_'));
1732+ if (!ExportedPlatformMenuPrivate::get_enabled(menu)) {
1733+ map.insert(DBusMenuProperty::Enabled, false);
1734+ }
1735+ if (!ExportedPlatformMenuPrivate::get_visible(menu)) {
1736+ map.insert(DBusMenuProperty::Visible, false);
1737+ }
1738+ insertIconProperty(&map, ExportedPlatformMenuPrivate::get_icon(menu));
1739+ return map;
1740+}
1741+
1742+//////////////////////////////////////////////////////
1743+
1744+ExportedPlatformMenuItemPrivate::ExportedPlatformMenuItemPrivate()
1745+ : m_id(nextMenuId++)
1746+ , m_menu(nullptr)
1747+{
1748+}
1749+
1750+QVariantMap ExportedPlatformMenuItemPrivate::propertiesForMenuItem(const ExportedPlatformMenuItem *menuItem)
1751+{
1752+ DMRETURN_VALUE_IF_FAIL(menuItem, QVariantMap());
1753+
1754+ if (ExportedPlatformMenuItemPrivate::get_separator(menuItem)) {
1755+ return propertiesForSeparatorMenuItem(menuItem);
1756+ } else {
1757+ return propertiesForStandardMenuItem(menuItem);
1758+ }
1759+}
1760+
1761+QVariantMap ExportedPlatformMenuItemPrivate::propertiesForSeparatorMenuItem(const ExportedPlatformMenuItem *menuItem)
1762+{
1763+ QVariantMap map;
1764+ map.insert(DBusMenuProperty::Type, "separator");
1765+ if (!ExportedPlatformMenuItemPrivate::get_visible(menuItem)) {
1766+ map.insert(DBusMenuProperty::Visible, false);
1767+ }
1768+ return map;
1769+}
1770+
1771+QVariantMap ExportedPlatformMenuItemPrivate::propertiesForStandardMenuItem(const ExportedPlatformMenuItem *menuItem)
1772+{
1773+ QVariantMap map;
1774+ map.insert(DBusMenuProperty::Label, Utils::swapMnemonicChar(ExportedPlatformMenuItemPrivate::get_text(menuItem), '&', '_'));
1775+ if (!ExportedPlatformMenuItemPrivate::get_enabled(menuItem)) {
1776+ map.insert(DBusMenuProperty::Enabled, false);
1777+ }
1778+ if (!ExportedPlatformMenuItemPrivate::get_visible(menuItem)) {
1779+ map.insert(DBusMenuProperty::Visible, false);
1780+ }
1781+ if (ExportedPlatformMenuItemPrivate::get_checkable(menuItem)) {
1782+ map.insert(DBusMenuProperty::ToggleType, "checkmark");
1783+ map.insert(DBusMenuProperty::ToggleState, ExportedPlatformMenuItemPrivate::get_checked(menuItem) ? 1 : 0);
1784+ }
1785+ if (menuItem->menu()) {
1786+ map.insert(DBusMenuProperty::ChildrenDisplay, "submenu");
1787+ }
1788+ insertIconProperty(&map, ExportedPlatformMenuItemPrivate::get_icon(menuItem));
1789+ QKeySequence keySequence = get_shortcut(menuItem);
1790+ if (!keySequence.isEmpty()) {
1791+ DBusMenuShortcut shortcut = DBusMenuShortcut::fromKeySequence(keySequence);
1792+ map.insert(DBusMenuProperty::Shortcut, QVariant::fromValue(shortcut));
1793+ }
1794+ return map;
1795+}
1796
1797=== added file 'src/qpa/exportedplatformmenubar_p.h'
1798--- src/qpa/exportedplatformmenubar_p.h 1970-01-01 00:00:00 +0000
1799+++ src/qpa/exportedplatformmenubar_p.h 2015-03-18 11:19:06 +0000
1800@@ -0,0 +1,111 @@
1801+/* This file is part of the dbusmenu-qt library
1802+ Copyright 2015 Canonical
1803+ Author: Nick Dedekind <nick.dedekind@canonical.com>
1804+
1805+ This library is free software; you can redistribute it and/or
1806+ modify it under the terms of the GNU Library General Public
1807+ License (LGPL) as published by the Free Software Foundation;
1808+ either version 2 of the License, or (at your option) any later
1809+ version.
1810+
1811+ This library is distributed in the hope that it will be useful,
1812+ but WITHOUT ANY WARRANTY; without even the implied warranty of
1813+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1814+ Library General Public License for more details.
1815+
1816+ You should have received a copy of the GNU Library General Public License
1817+ along with this library; see the file COPYING.LIB. If not, write to
1818+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
1819+ Boston, MA 02110-1301, USA.
1820+*/
1821+#ifndef EXPORTEDPLATFORMMENUBAR_P_H
1822+#define EXPORTEDPLATFORMMENUBAR_P_H
1823+
1824+// Qt
1825+#include <QtCore/QObject>
1826+#include <QtDBus/QDBusConnection>
1827+#include <qpa/qplatformmenu.h>
1828+
1829+// Local
1830+#include "dbusmenuexporterdbusinterface_p.h"
1831+#include "exportedplatformmenubar.h"
1832+
1833+class QAction;
1834+class QMenu;
1835+
1836+class ExportedPlatformMenuBar;
1837+class ExportedPlatformMenu;
1838+class ExportedPlatformMenuItem;
1839+class QPADBusMenuExporter;
1840+
1841+/**
1842+ * A QPADBusMenuExporter instance can serialize a qua menu over DBus
1843+ */
1844+class ExportedPlatformMenuBarPrivate
1845+{
1846+public:
1847+ ExportedPlatformMenuBarPrivate();
1848+
1849+ QString m_objectPath;
1850+ QList<QPlatformMenu*> m_menus;
1851+};
1852+
1853+class ExportedPlatformMenuPrivate
1854+{
1855+public:
1856+ ExportedPlatformMenuPrivate();
1857+
1858+ static QVariantMap propertiesForMenu(const ExportedPlatformMenu *menu);
1859+
1860+#define STATIC_PROPERTY(name, type, defaultValue) \
1861+ type m_##name = defaultValue; \
1862+ static type get_##name(const ExportedPlatformMenu *menu) { return menu->d->m_##name; } \
1863+ static void set_##name(ExportedPlatformMenu *menu, const type& value) { menu->d->m_##name = value; }
1864+
1865+ STATIC_PROPERTY(text, QString, QString())
1866+ STATIC_PROPERTY(visible, bool, true)
1867+ STATIC_PROPERTY(enabled, bool, true)
1868+ STATIC_PROPERTY(icon, QIcon, QIcon())
1869+#undef STATIC_PROPERTY
1870+
1871+ ExportedPlatformMenu* m_menu;
1872+ QList<QPlatformMenu*> m_menus;
1873+ QList<QPlatformMenuItem*> m_menuItems;
1874+ quintptr m_tag;
1875+ int m_id;
1876+};
1877+
1878+class ExportedPlatformMenuItemPrivate
1879+{
1880+public:
1881+ ExportedPlatformMenuItemPrivate();
1882+
1883+ static QVariantMap propertiesForMenuItem(const ExportedPlatformMenuItem *menuItem);
1884+ static QVariantMap propertiesForSeparatorMenuItem(const ExportedPlatformMenuItem *menuItem);
1885+ static QVariantMap propertiesForStandardMenuItem(const ExportedPlatformMenuItem *menuItem);
1886+
1887+#define STATIC_PROPERTY(name, type, defaultValue) \
1888+ type m_##name = defaultValue; \
1889+ static type get_##name(const ExportedPlatformMenuItem *menuItem) { return menuItem->d->m_##name; } \
1890+ static void set_##name(ExportedPlatformMenuItem *menuItem, const type& value) { menuItem->d->m_##name = value; }
1891+
1892+ STATIC_PROPERTY(separator, bool, false)
1893+ STATIC_PROPERTY(visible, bool, true)
1894+ STATIC_PROPERTY(text, QString, QString())
1895+ STATIC_PROPERTY(enabled, bool, true)
1896+ STATIC_PROPERTY(checkable, bool, false)
1897+ STATIC_PROPERTY(checked, bool, false)
1898+ STATIC_PROPERTY(shortcut, QKeySequence, QKeySequence())
1899+ STATIC_PROPERTY(icon, QIcon, QIcon())
1900+ STATIC_PROPERTY(iconSize, int, 16)
1901+#undef STATIC_PROPERTY
1902+
1903+ ExportedPlatformMenuItem* m_menuItem;
1904+ quintptr m_tag;
1905+ int m_id;
1906+ QPlatformMenu* m_menu;
1907+};
1908+
1909+extern int nextMenuId;
1910+
1911+#endif // EXPORTEDPLATFORMMENUBAR_P_H
1912
1913=== added file 'src/qpa/logging_p.h'
1914--- src/qpa/logging_p.h 1970-01-01 00:00:00 +0000
1915+++ src/qpa/logging_p.h 2015-03-18 11:19:06 +0000
1916@@ -0,0 +1,38 @@
1917+/* This file is part of the dbusmenu-qt library
1918+ Copyright 2015 Canonical
1919+ Author: Nick Dedekind <nick.dedekind@canonical.com>
1920+
1921+ This library is free software; you can redistribute it and/or
1922+ modify it under the terms of the GNU Library General Public
1923+ License (LGPL) as published by the Free Software Foundation;
1924+ either version 2 of the License, or (at your option) any later
1925+ version.
1926+
1927+ This library is distributed in the hope that it will be useful,
1928+ but WITHOUT ANY WARRANTY; without even the implied warranty of
1929+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1930+ Library General Public License for more details.
1931+
1932+ You should have received a copy of the GNU Library General Public License
1933+ along with this library; see the file COPYING.LIB. If not, write to
1934+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
1935+ Boston, MA 02110-1301, USA.
1936+*/
1937+#ifndef LOGGING_H
1938+#define LOGGING_H
1939+
1940+#include <QDebug>
1941+
1942+//#define ENABLE_DEBUG_LOGGING
1943+
1944+#ifdef ENABLE_DEBUG_LOGGING
1945+#define LOG qDebug() << __PRETTY_FUNCTION__
1946+#define LOG_VAR(x) qDebug() << __PRETTY_FUNCTION__<< #x ":" << x
1947+#else
1948+#define LOG QNoDebug()
1949+#define LOG_VAR(x) QNoDebug() << __PRETTY_FUNCTION__<< #x ":" << x
1950+#endif
1951+
1952+#define WARN qWarning() << __PRETTY_FUNCTION__
1953+
1954+#endif // LOGGING_H
1955
1956=== added file 'src/qpa/qpadbusmenuexporter_p.cpp'
1957--- src/qpa/qpadbusmenuexporter_p.cpp 1970-01-01 00:00:00 +0000
1958+++ src/qpa/qpadbusmenuexporter_p.cpp 2015-03-18 11:19:06 +0000
1959@@ -0,0 +1,357 @@
1960+/* This file is part of the dbusmenu-qt library
1961+ Copyright 2015 Canonical
1962+ Author: Nick Dedekind <nick.dedekind@canonical.com>
1963+
1964+ This library is free software; you can redistribute it and/or
1965+ modify it under the terms of the GNU Library General Public
1966+ License (LGPL) as published by the Free Software Foundation;
1967+ either version 2 of the License, or (at your option) any later
1968+ version.
1969+
1970+ This library is distributed in the hope that it will be useful,
1971+ but WITHOUT ANY WARRANTY; without even the implied warranty of
1972+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1973+ Library General Public License for more details.
1974+
1975+ You should have received a copy of the GNU Library General Public License
1976+ along with this library; see the file COPYING.LIB. If not, write to
1977+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
1978+ Boston, MA 02110-1301, USA.
1979+*/
1980+
1981+// Local
1982+#include "qpadbusmenuexporter_p.h"
1983+#include "exportedplatformmenubar.h"
1984+#include "exportedplatformmenubar_p.h"
1985+#include "utils_p.h"
1986+#include "logging_p.h"
1987+
1988+// Qt
1989+#include <QTimer>
1990+
1991+QPADBusMenuExporter::QPADBusMenuExporter(const QString &objectPath, ExportedPlatformMenuBar* menuBar)
1992+ : DBusMenuExporterDBusInterface(objectPath, menuBar)
1993+ , m_menuBar(menuBar)
1994+ , m_revision(1)
1995+ , m_emittedLayoutUpdatedOnce(false)
1996+{
1997+ LOG << "created exporter menu @ " << objectPath;
1998+
1999+ m_propertyTimer = new QTimer(this);
2000+ m_propertyTimer->setInterval(0);
2001+ m_propertyTimer->setSingleShot(true);
2002+ connect(m_propertyTimer, &QTimer::timeout, this, &QPADBusMenuExporter::doMenuPropertyUpdate);
2003+
2004+ m_layoutTimer = new QTimer(this);
2005+ m_layoutTimer->setInterval(0);
2006+ m_layoutTimer->setSingleShot(true);
2007+ connect(m_layoutTimer, &QTimer::timeout, this, &QPADBusMenuExporter::doMenuLayoutUpdate);
2008+
2009+ for (uint i = 0; i < m_menuBar->menuCount(); i++) {
2010+ auto exportedMenu = qobject_cast<ExportedPlatformMenu*>(m_menuBar->menuAt(i));
2011+ addMenu(exportedMenu, 0);
2012+ }
2013+
2014+ connect(menuBar, &ExportedPlatformMenuBar::menuInserted, this, [this](QPlatformMenu* menu) {
2015+ addMenu(qobject_cast<ExportedPlatformMenu*>(menu), 0);
2016+ });
2017+ connect(menuBar, &ExportedPlatformMenuBar::menuRemoved, this, [this](QPlatformMenu* menu) {
2018+ removeMenu(qobject_cast<ExportedPlatformMenu*>(menu), 0);
2019+ });
2020+}
2021+
2022+QPADBusMenuExporter::~QPADBusMenuExporter()
2023+{
2024+}
2025+
2026+void QPADBusMenuExporter::Event(int id, const QString &eventType, const QDBusVariant &data, uint timestamp)
2027+{
2028+ Q_UNUSED(data);
2029+ Q_UNUSED(timestamp);
2030+ LOG << " id:" << id << ", eventType:" << eventType;
2031+
2032+ ExportedPlatformMenuItem* menuItem = m_menuItemForId.value(id, nullptr);
2033+ if (menuItem) {
2034+ if (eventType == "clicked") {
2035+ QMetaObject::invokeMethod(menuItem, "activated");
2036+ } else if (eventType == "hovered") {
2037+ QMetaObject::invokeMethod(menuItem, "hovered");
2038+ }
2039+ }
2040+}
2041+
2042+QDBusVariant QPADBusMenuExporter::GetProperty(int id, const QString &property)
2043+{
2044+ if (!m_propertiesForId.contains(id)) return QDBusVariant();
2045+ return QDBusVariant(m_propertiesForId.value(id).value(property));
2046+}
2047+
2048+void QPADBusMenuExporter::fillLayout(DBusMenuLayoutItem *item, int id, int depth, const QStringList &propertyNames)
2049+{
2050+ item->id = id;
2051+ item->properties = getProperties(id, propertyNames);
2052+
2053+ if (depth != 0) {
2054+ if (id == 0) {
2055+ for (uint i = 0; i < m_menuBar->menuCount(); i++) {
2056+ auto exportedMenu = qobject_cast<ExportedPlatformMenu*>(m_menuBar->menuAt(i));
2057+ if (exportedMenu) {
2058+ DBusMenuLayoutItem child;
2059+ fillLayout(&child, exportedMenu->id(), depth - 1, propertyNames);
2060+ item->children << child;
2061+ }
2062+ }
2063+ } else {
2064+ // menu with children.
2065+ ExportedPlatformMenu* menu = m_menuForId.value(id, nullptr);
2066+ if (menu) {
2067+ for (uint i = 0; i < menu->menuItemCount(); i++) {
2068+ auto exportedMenuItem = qobject_cast<ExportedPlatformMenuItem*>(menu->menuItemAt(i));
2069+
2070+ DBusMenuLayoutItem child;
2071+ fillLayout(&child, exportedMenuItem->id(), depth-1, propertyNames);
2072+ item->children << child;
2073+ }
2074+ } else {
2075+ // child menu items which has an attached menu
2076+ ExportedPlatformMenuItem* menuItem = m_menuItemForId.value(id, nullptr);
2077+ if (menuItem) {
2078+ auto menu = qobject_cast<ExportedPlatformMenu*>(menuItem->menu());
2079+ if (menu) {
2080+ for (uint i = 0; i < menu->menuItemCount(); i++) {
2081+ auto exportedMenuItem = qobject_cast<ExportedPlatformMenuItem*>(menu->menuItemAt(i));
2082+
2083+ DBusMenuLayoutItem child;
2084+ fillLayout(&child, exportedMenuItem->id(), depth-1, propertyNames);
2085+ item->children << child;
2086+ }
2087+ }
2088+ }
2089+ }
2090+ }
2091+ }
2092+}
2093+
2094+uint QPADBusMenuExporter::GetLayout(int parentId, int recursionDepth, const QStringList &propertyNames, DBusMenuLayoutItem &item)
2095+{
2096+ doMenuPropertyUpdate();
2097+
2098+ fillLayout(&item, parentId, recursionDepth, propertyNames);
2099+ return m_revision;
2100+}
2101+
2102+DBusMenuItemList QPADBusMenuExporter::GetGroupProperties(const QList<int> &ids, const QStringList &propertyNames)
2103+{
2104+ DBusMenuItemList list;
2105+ Q_FOREACH(int id, ids) {
2106+ DBusMenuItem item;
2107+ item.id = id;
2108+ item.properties = getProperties(item.id, propertyNames);
2109+ list << item;
2110+ }
2111+ return list;
2112+}
2113+
2114+bool QPADBusMenuExporter::AboutToShow(int id)
2115+{
2116+ return false;
2117+}
2118+
2119+void QPADBusMenuExporter::menuPropertyUpdated(int id)
2120+{
2121+ if (m_propertyUpdates.contains(id)) return;
2122+
2123+ m_propertyUpdates << id;
2124+ if (!m_propertyTimer->isActive()) m_propertyTimer->start();
2125+}
2126+
2127+void QPADBusMenuExporter::menuLayoutUpdated(int id)
2128+{
2129+ if (m_layoutUpdates.contains(id)) return;
2130+
2131+ m_layoutUpdates << id;
2132+ if (!m_layoutTimer->isActive()) m_layoutTimer->start();
2133+}
2134+
2135+inline void logPropertyUpdates(const DBusMenuItemList& updates, const DBusMenuItemKeysList& removals)
2136+{
2137+ Q_FOREACH(const DBusMenuItem& update, updates) {
2138+ qDebug() << "property updates for " << update.id << endl
2139+ << " " << update.properties;
2140+ }
2141+ Q_FOREACH(const DBusMenuItemKeys& remove, removals) {
2142+ qDebug() << "property updates for " << remove.id << endl
2143+ << " " << remove.properties;
2144+ }
2145+}
2146+
2147+void QPADBusMenuExporter::doMenuPropertyUpdate()
2148+{
2149+ if (m_propertyUpdates.isEmpty()) {
2150+ return;
2151+ }
2152+ DBusMenuItemList updatedList;
2153+ DBusMenuItemKeysList removedList;
2154+
2155+ Q_FOREACH(int id, m_propertyUpdates) {
2156+ QVariantMap newProperties;
2157+ ExportedPlatformMenuItem* menuItem = m_menuItemForId.value(id, nullptr);
2158+ // no longer exists?
2159+ if (menuItem) {
2160+ newProperties = ExportedPlatformMenuItemPrivate::propertiesForMenuItem(menuItem);
2161+ } else {
2162+ ExportedPlatformMenu* menu = m_menuForId.value(id, nullptr);
2163+ if (menu) {
2164+ newProperties = ExportedPlatformMenuPrivate::propertiesForMenu(menu);
2165+ }
2166+ }
2167+
2168+ QVariantMap& oldProperties = m_propertiesForId[id];
2169+ QVariantMap updatedProperties;
2170+ QStringList removedProperties;
2171+
2172+ Utils::parsePropertyChanges(oldProperties, newProperties, updatedProperties, removedProperties);
2173+
2174+ // Update our data (oldProperties is a reference)
2175+ oldProperties = newProperties;
2176+
2177+ if (!updatedProperties.isEmpty()) {
2178+ DBusMenuItem item;
2179+ item.id = id;
2180+ item.properties = updatedProperties;
2181+ updatedList << item;
2182+ }
2183+ if (!removedProperties.isEmpty()) {
2184+ DBusMenuItemKeys itemKeys;
2185+ itemKeys.id = id;
2186+ itemKeys.properties = removedProperties;
2187+ removedList << itemKeys;
2188+ }
2189+ }
2190+ m_propertyUpdates.clear();
2191+
2192+ if (!m_emittedLayoutUpdatedOnce) {
2193+ // No need to tell the world about action changes: nobody knows the
2194+ // menu layout so nobody knows about the actions.
2195+ // Note: We still need to reach this method because we want our properties to be
2196+ // updated, even if we don't announce changes.
2197+ return;
2198+ }
2199+ if (!updatedList.isEmpty() || !removedList.isEmpty()) {
2200+#ifdef ENABLE_DEBUG_LOGGING
2201+ logPropertyUpdates(updatedList, removedList);
2202+#endif
2203+
2204+ Q_EMIT ItemsPropertiesUpdated(updatedList, removedList);
2205+ }
2206+}
2207+
2208+void QPADBusMenuExporter::doMenuLayoutUpdate()
2209+{
2210+ // Tell the world about the update
2211+ if (m_emittedLayoutUpdatedOnce) {
2212+ Q_FOREACH(int id, m_layoutUpdates) {
2213+ Q_EMIT LayoutUpdated(++m_revision, id);
2214+ }
2215+ } else {
2216+ // First time we emit LayoutUpdated, no need to emit several layout
2217+ // updates, signals the whole layout (id==0) has been updated
2218+ Q_EMIT LayoutUpdated(++m_revision, 0);
2219+ m_emittedLayoutUpdatedOnce = true;
2220+ }
2221+ m_layoutUpdates.clear();
2222+}
2223+
2224+void QPADBusMenuExporter::addMenu(ExportedPlatformMenu *menu, int parentId)
2225+{
2226+ if (!menu) return;
2227+ if (m_menuForId.contains(menu->id())) return;
2228+
2229+ for (uint i = 0; i < menu->menuItemCount(); i++) {
2230+ auto exportedMenuItem = qobject_cast<ExportedPlatformMenuItem*>(menu->menuItemAt(i));
2231+ addMenuItem(exportedMenuItem, menu->id());
2232+ }
2233+
2234+ m_menuForId[menu->id()] = menu;
2235+ m_propertiesForId[menu->id()] = ExportedPlatformMenuPrivate::propertiesForMenu(menu);
2236+ connect(menu, &ExportedPlatformMenu::propertyUpdated, this, [&, menu]() {
2237+ menuPropertyUpdated(menu->id());
2238+ });
2239+ connect(menu, &ExportedPlatformMenu::menuItemInserted, this, [&, menu](QPlatformMenuItem* menuItem) {
2240+ addMenuItem(qobject_cast<ExportedPlatformMenuItem*>(menuItem), menu->id());
2241+ });
2242+ connect(menu, &ExportedPlatformMenu::menuItemRemoved, this, [&, menu](QPlatformMenuItem* menuItem) {
2243+ removeMenuItem(qobject_cast<ExportedPlatformMenuItem*>(menuItem), menu->id());
2244+ });
2245+
2246+ menuLayoutUpdated(parentId);
2247+}
2248+
2249+void QPADBusMenuExporter::addMenuItem(ExportedPlatformMenuItem *menuItem, int parentId)
2250+{
2251+ if (!menuItem) return;
2252+ if (m_menuItemForId.contains(menuItem->id())) return;
2253+
2254+ m_menuItemForId[menuItem->id()] = menuItem;
2255+ m_propertiesForId[menuItem->id()] = ExportedPlatformMenuItemPrivate::propertiesForMenuItem(menuItem);
2256+
2257+ connect(menuItem, &ExportedPlatformMenuItem::propertyUpdated, this, [&, menuItem]() {
2258+ menuPropertyUpdated(menuItem->id());
2259+ });
2260+
2261+ auto menu = qobject_cast<ExportedPlatformMenu*>(menuItem->menu());
2262+ if (menu) {
2263+ addMenu(menu, parentId);
2264+ }
2265+ menuLayoutUpdated(parentId);
2266+}
2267+
2268+void QPADBusMenuExporter::removeMenu(ExportedPlatformMenu *menu, int parentId)
2269+{
2270+ if (!menu) return;
2271+
2272+ for (uint i = 0; i < menu->menuItemCount(); i++) {
2273+ auto exportedMenuItem = qobject_cast<ExportedPlatformMenuItem*>(menu->menuItemAt(i));
2274+ removeMenuItem(exportedMenuItem, parentId);
2275+ }
2276+ disconnect(menu, 0, this, 0);
2277+}
2278+
2279+void QPADBusMenuExporter::removeMenuItem(ExportedPlatformMenuItem *menuItem, int parentId)
2280+{
2281+ if (!menuItem) return;
2282+
2283+ auto menu = qobject_cast<ExportedPlatformMenu*>(menuItem->menu());
2284+ if (menu) {
2285+ removeMenu(menu, menuItem->id());
2286+ }
2287+
2288+ m_menuItemForId.remove(menuItem->id());
2289+ m_propertiesForId.remove(menuItem->id());
2290+ disconnect(menuItem, 0, this, 0);
2291+
2292+ menuLayoutUpdated(parentId);
2293+}
2294+
2295+QVariantMap QPADBusMenuExporter::getProperties(int id, const QStringList &names) const
2296+{
2297+ if (id == 0) {
2298+ QVariantMap map;
2299+ map.insert(DBusMenuProperty::ChildrenDisplay, "submenu");
2300+ return map;
2301+ }
2302+ QVariantMap all = m_propertiesForId.value(id);
2303+ if (names.isEmpty()) {
2304+ return all;
2305+ } else {
2306+ QVariantMap map;
2307+ Q_FOREACH(const QString &name, names) {
2308+ QVariant value = all.value(name);
2309+ if (value.isValid()) {
2310+ map.insert(name, value);
2311+ }
2312+ }
2313+ return map;
2314+ }
2315+}
2316+
2317
2318=== added file 'src/qpa/qpadbusmenuexporter_p.h'
2319--- src/qpa/qpadbusmenuexporter_p.h 1970-01-01 00:00:00 +0000
2320+++ src/qpa/qpadbusmenuexporter_p.h 2015-03-18 11:19:06 +0000
2321@@ -0,0 +1,94 @@
2322+/* This file is part of the dbusmenu-qt library
2323+ Copyright 2015 Canonical
2324+ Author: Nick Dedekind <nick.dedekind@canonical.com>
2325+
2326+ This library is free software; you can redistribute it and/or
2327+ modify it under the terms of the GNU Library General Public
2328+ License (LGPL) as published by the Free Software Foundation;
2329+ either version 2 of the License, or (at your option) any later
2330+ version.
2331+
2332+ This library is distributed in the hope that it will be useful,
2333+ but WITHOUT ANY WARRANTY; without even the implied warranty of
2334+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
2335+ Library General Public License for more details.
2336+
2337+ You should have received a copy of the GNU Library General Public License
2338+ along with this library; see the file COPYING.LIB. If not, write to
2339+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
2340+ Boston, MA 02110-1301, USA.
2341+*/
2342+#ifndef QPADBUSMENUEXPORTER_H
2343+#define QPADBUSMENUEXPORTER_H
2344+
2345+// Qt
2346+#include <QtCore/QObject>
2347+#include <QtDBus/QDBusConnection>
2348+#include <qpa/qplatformmenu.h>
2349+
2350+// Local
2351+#include "dbusmenuexporterdbusinterface_p.h"
2352+
2353+class QAction;
2354+class QMenu;
2355+
2356+class ExportedPlatformMenuBar;
2357+class ExportedPlatformMenu;
2358+class ExportedPlatformMenuItem;
2359+
2360+/**
2361+ * A QPADBusMenuExporter instance can serialize a qua menu over DBus
2362+ */
2363+class QPADBusMenuExporter : public DBusMenuExporterDBusInterface
2364+{
2365+ Q_OBJECT
2366+ Q_CLASSINFO("D-Bus Interface", "com.canonical.dbusmenu")
2367+public:
2368+ QPADBusMenuExporter(const QString& path, ExportedPlatformMenuBar* menuBar);
2369+ virtual ~QPADBusMenuExporter();
2370+
2371+ // overrides
2372+ void Event(int id, const QString &eventId, const QDBusVariant &data, uint timestamp) override;
2373+ QDBusVariant GetProperty(int id, const QString &property) override;
2374+ uint GetLayout(int parentId, int recursionDepth, const QStringList &propertyNames, DBusMenuLayoutItem &item) override;
2375+ DBusMenuItemList GetGroupProperties(const QList<int> &ids, const QStringList &propertyNames) override;
2376+ bool AboutToShow(int id) override;
2377+
2378+private Q_SLOTS:
2379+ void menuPropertyUpdated(int id);
2380+ void menuLayoutUpdated(int id);
2381+
2382+private Q_SLOTS:
2383+ void doMenuPropertyUpdate();
2384+ void doMenuLayoutUpdate();
2385+
2386+private:
2387+ Q_DISABLE_COPY(QPADBusMenuExporter)
2388+
2389+ void addMenu(ExportedPlatformMenu* menu, int parentId);
2390+ void addMenuItem(ExportedPlatformMenuItem* menu, int parentId);
2391+
2392+ void removeMenu(ExportedPlatformMenu* menu, int parentId);
2393+ void removeMenuItem(ExportedPlatformMenuItem* menuItem, int parentId);
2394+
2395+ void fillLayout(DBusMenuLayoutItem *item, int id, int depth, const QStringList &propertyNames);
2396+ QVariantMap getProperties(int id, const QStringList &names) const;
2397+
2398+ ExportedPlatformMenuBar* m_menuBar;
2399+ QTimer* m_propertyTimer;
2400+ QTimer* m_layoutTimer;
2401+
2402+ QList<int> m_propertyUpdates;
2403+ QList<int> m_layoutUpdates;
2404+ uint m_revision;
2405+ bool m_emittedLayoutUpdatedOnce;
2406+
2407+ QHash<int, ExportedPlatformMenuItem*> m_menuItemForId;
2408+ QHash<int, ExportedPlatformMenu*> m_menuForId;
2409+ QHash<int, QVariantMap> m_propertiesForId;
2410+
2411+ friend class ExportedPlatformMenu;
2412+ friend class ExportedPlatformMenuItem;
2413+};
2414+
2415+#endif /* QPADBUSMENUEXPORTER_H */
2416
2417=== modified file 'src/utils.cpp'
2418--- src/utils.cpp 2010-09-20 08:55:12 +0000
2419+++ src/utils.cpp 2015-03-18 11:19:06 +0000
2420@@ -23,7 +23,7 @@
2421 // Qt
2422 #include <QString>
2423
2424-QString swapMnemonicChar(const QString &in, const char src, const char dst)
2425+QString Utils::swapMnemonicChar(const QString &in, const char src, const char dst)
2426 {
2427 QString out;
2428 bool mnemonicFound = false;
2429@@ -62,3 +62,38 @@
2430
2431 return out;
2432 }
2433+
2434+
2435+void Utils::parsePropertyChanges(const QVariantMap &oldProperties,
2436+ const QVariantMap &newProperties,
2437+ QVariantMap &updatedProperties,
2438+ QStringList &removedProperties)
2439+{
2440+ // Find updated and removed properties
2441+ QVariantMap::ConstIterator newEnd = newProperties.constEnd();
2442+
2443+ QVariantMap::ConstIterator
2444+ oldIt = oldProperties.constBegin(),
2445+ oldEnd = oldProperties.constEnd();
2446+ for(; oldIt != oldEnd; ++oldIt) {
2447+ QString key = oldIt.key();
2448+ QVariantMap::ConstIterator newIt = newProperties.constFind(key);
2449+ if (newIt != newEnd) {
2450+ if (newIt.value() != oldIt.value()) {
2451+ updatedProperties.insert(key, newIt.value());
2452+ }
2453+ } else {
2454+ removedProperties << key;
2455+ }
2456+ }
2457+
2458+ // Find new properties (treat them as updated properties)
2459+ QVariantMap::ConstIterator newIt = newProperties.constBegin();
2460+ for (; newIt != newEnd; ++newIt) {
2461+ QString key = newIt.key();
2462+ oldIt = oldProperties.constFind(key);
2463+ if (oldIt == oldEnd) {
2464+ updatedProperties.insert(key, newIt.value());
2465+ }
2466+ }
2467+}
2468
2469=== modified file 'src/utils_p.h'
2470--- src/utils_p.h 2010-09-20 08:55:12 +0000
2471+++ src/utils_p.h 2015-03-18 11:19:06 +0000
2472@@ -22,10 +22,20 @@
2473 #define UTILS_P_H
2474
2475 class QString;
2476-
2477-/**
2478- * Swap mnemonic char: Qt uses '&', while dbusmenu uses '_'
2479- */
2480-QString swapMnemonicChar(const QString &in, const char src, const char dst);
2481+class QStringList;
2482+#include <QVariant>
2483+
2484+namespace Utils {
2485+
2486+ /**
2487+ * Swap mnemonic char: Qt uses '&', while dbusmenu uses '_'
2488+ */
2489+ QString swapMnemonicChar(const QString &in, const char src, const char dst);
2490+
2491+ void parsePropertyChanges(const QVariantMap& oldProperties,
2492+ const QVariantMap& newProperties,
2493+ QVariantMap& updatedProperties,
2494+ QStringList& removedProperties);
2495+}
2496
2497 #endif /* UTILS_P_H */
2498
2499=== modified file 'tests/CMakeLists.txt'
2500--- tests/CMakeLists.txt 2015-03-18 11:19:06 +0000
2501+++ tests/CMakeLists.txt 2015-03-18 11:19:06 +0000
2502@@ -120,5 +120,18 @@
2503 ${test_LIBRARIES}
2504 )
2505
2506+
2507+# exportedplatformmenutest
2508+if (USE_QT5)
2509+ add_test_executable(exportedplatformmenutest
2510+ exportedplatformmenutest.cpp
2511+ testutils.cpp
2512+ )
2513+
2514+ target_link_libraries(exportedplatformmenutest
2515+ ${test_LIBRARIES}
2516+ )
2517+endif()
2518+
2519 # Keep this at the end
2520 create_check_target()
2521
2522=== modified file 'tests/dbusmenuexportertest.cpp'
2523--- tests/dbusmenuexportertest.cpp 2015-03-18 11:19:06 +0000
2524+++ tests/dbusmenuexportertest.cpp 2015-03-18 11:19:06 +0000
2525@@ -31,7 +31,7 @@
2526
2527 // DBusMenuQt
2528 #include <dbusmenuexporter.h>
2529-#include <dbusmenutypes_p.h>
2530+#include <dbusmenutypes.h>
2531 #include <dbusmenushortcut_p.h>
2532 #include <debug_p.h>
2533
2534@@ -114,6 +114,7 @@
2535 if (enabled) {
2536 QVERIFY(!item.properties.contains("enabled"));
2537 } else {
2538+ QVERIFY(item.properties.contains("enabled"));
2539 QCOMPARE(item.properties.value("enabled").toBool(), false);
2540 }
2541 if (iconName.isEmpty()) {
2542
2543=== added file 'tests/exportedplatformmenutest.cpp'
2544--- tests/exportedplatformmenutest.cpp 1970-01-01 00:00:00 +0000
2545+++ tests/exportedplatformmenutest.cpp 2015-03-18 11:19:06 +0000
2546@@ -0,0 +1,366 @@
2547+/* This file is part of the dbusmenu-qt library
2548+ Copyright 2015 Canonical
2549+ Author: Aurelien Gateau <aurelien.gateau@canonical.com>
2550+
2551+ This library is free software; you can redistribute it and/or
2552+ modify it under the terms of the GNU Library General Public
2553+ License (LGPL) as published by the Free Software Foundation;
2554+ either version 2 of the License, or (at your option) any later
2555+ version.
2556+
2557+ This library is distributed in the hope that it will be useful,
2558+ but WITHOUT ANY WARRANTY; without even the implied warranty of
2559+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
2560+ Library General Public License for more details.
2561+
2562+ You should have received a copy of the GNU Library General Public License
2563+ along with this library; see the file COPYING.LIB. If not, write to
2564+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
2565+ Boston, MA 02110-1301, USA.
2566+*/
2567+// Self
2568+#include "exportedplatformmenutest.h"
2569+
2570+// Qt
2571+#include <QDBusConnection>
2572+#include <QDBusInterface>
2573+#include <QDBusReply>
2574+#include <QtTest>
2575+
2576+// DBusMenuQt
2577+#include <qpa/exportedplatformmenubar.h>
2578+#include <dbusmenutypes.h>
2579+#include <dbusmenushortcut_p.h>
2580+#include <debug_p.h>
2581+
2582+// Local
2583+#include "testutils.h"
2584+
2585+QTEST_MAIN(ExportedPlatformMenuTest)
2586+
2587+static const char *TEST_SERVICE = "org.kde.dbusmenu-qt-test";
2588+static const char *TEST_OBJECT_PATH = "/TestMenuBar";
2589+
2590+Q_DECLARE_METATYPE(QList<int>)
2591+
2592+static DBusMenuLayoutItemList getChildren(QDBusAbstractInterface* iface, int parentId, const QStringList &propertyNames)
2593+{
2594+ QDBusPendingReply<uint, DBusMenuLayoutItem> reply = iface->call("GetLayout", parentId, /*recursionDepth=*/ 1, propertyNames);
2595+ reply.waitForFinished();
2596+ if (!reply.isValid()) {
2597+ qFatal("%s", qPrintable(reply.error().message()));
2598+ return DBusMenuLayoutItemList();
2599+ }
2600+
2601+ DBusMenuLayoutItem rootItem = reply.argumentAt<1>();
2602+ return rootItem.children;
2603+}
2604+
2605+void ExportedPlatformMenuTest::init()
2606+{
2607+ QVERIFY(QDBusConnection::sessionBus().registerService(TEST_SERVICE));
2608+ QCoreApplication::setAttribute(Qt::AA_DontShowIconsInMenus, false);
2609+}
2610+
2611+void ExportedPlatformMenuTest::cleanup()
2612+{
2613+ QVERIFY(QDBusConnection::sessionBus().unregisterService(TEST_SERVICE));
2614+}
2615+
2616+void ExportedPlatformMenuTest::testGetSomeMenuProperties_data()
2617+{
2618+ QTest::addColumn<QString>("label");
2619+ QTest::addColumn<QString>("iconName");
2620+ QTest::addColumn<bool>("enabled");
2621+
2622+ QTest::newRow("label only") << "label" << QString() << true;
2623+ QTest::newRow("disabled, label only") << "label" << QString() << false;
2624+ QTest::newRow("icon name") << "label" << "edit-undo" << true;
2625+}
2626+
2627+void ExportedPlatformMenuTest::testGetSomeMenuProperties()
2628+{
2629+ QFETCH(QString, label);
2630+ QFETCH(QString, iconName);
2631+ QFETCH(bool, enabled);
2632+
2633+ // Create an exporter for a menu with one action, defined by the test data
2634+ ExportedPlatformMenuBar menuBar(TEST_OBJECT_PATH);
2635+ ExportedPlatformMenu menu;
2636+ menu.setText(label);
2637+ if (!iconName.isEmpty()) {
2638+ QIcon icon = QIcon::fromTheme(iconName);
2639+ QVERIFY(!icon.isNull());
2640+ menu.setIcon(icon);
2641+ }
2642+ menu.setEnabled(enabled);
2643+ menuBar.insertMenu(&menu, nullptr);
2644+
2645+ // Check out exporter is on DBus
2646+ QDBusInterface iface(TEST_SERVICE, TEST_OBJECT_PATH);
2647+ QVERIFY2(iface.isValid(), qPrintable(iface.lastError().message()));
2648+
2649+ // Get exported menu info
2650+ QStringList propertyNames = QStringList() << "type" << "enabled" << "label" << "icon-name";
2651+ DBusMenuLayoutItemList list = getChildren(&iface, /*parentId=*/0, propertyNames);
2652+ QVERIFY(!list.isEmpty());
2653+ DBusMenuLayoutItem item = list.first();
2654+
2655+ QVERIFY(item.id != 0);
2656+ QVERIFY(item.children.isEmpty());
2657+ QVERIFY(!item.properties.contains("type"));
2658+ QCOMPARE(item.properties.value("label").toString(), label);
2659+ if (enabled) {
2660+ QVERIFY(!item.properties.contains("enabled"));
2661+ } else {
2662+ QVERIFY(item.properties.contains("enabled"));
2663+ QCOMPARE(item.properties.value("enabled").toBool(), false);
2664+ }
2665+ if (iconName.isEmpty()) {
2666+ QVERIFY(!item.properties.contains("icon-name"));
2667+ } else {
2668+ QCOMPARE(item.properties.value("icon-name").toString(), iconName);
2669+ }
2670+}
2671+
2672+void ExportedPlatformMenuTest::testGetSomeMenuItemProperties_data()
2673+{
2674+ QTest::addColumn<QString>("label");
2675+ QTest::addColumn<QString>("iconName");
2676+ QTest::addColumn<bool>("enabled");
2677+
2678+ QTest::newRow("label only") << "label" << QString() << true;
2679+ QTest::newRow("disabled, label only") << "label" << QString() << false;
2680+ QTest::newRow("icon name") << "label" << "edit-undo" << true;
2681+}
2682+
2683+void ExportedPlatformMenuTest::testGetSomeMenuItemProperties()
2684+{
2685+ QFETCH(QString, label);
2686+ QFETCH(QString, iconName);
2687+ QFETCH(bool, enabled);
2688+
2689+ // Create an exporter for a menu with one action, defined by the test data
2690+ ExportedPlatformMenuBar menuBar(TEST_OBJECT_PATH);
2691+ ExportedPlatformMenu menu;
2692+ menuBar.insertMenu(&menu, nullptr);
2693+
2694+ ExportedPlatformMenuItem menuItem1;
2695+ menuItem1.setText(label);
2696+ if (!iconName.isEmpty()) {
2697+ QIcon icon = QIcon::fromTheme(iconName);
2698+ QVERIFY(!icon.isNull());
2699+ menuItem1.setIcon(icon);
2700+ }
2701+ menuItem1.setEnabled(enabled);
2702+ menu.insertMenuItem(&menuItem1, nullptr);
2703+
2704+ // Check out exporter is on DBus
2705+ QDBusInterface iface(TEST_SERVICE, TEST_OBJECT_PATH);
2706+ QVERIFY2(iface.isValid(), qPrintable(iface.lastError().message()));
2707+
2708+ // Get exported menu info
2709+ QStringList propertyNames = QStringList() << "type" << "enabled" << "label" << "icon-name";
2710+ DBusMenuLayoutItemList list = getChildren(&iface, /*parentId=*/0, propertyNames);
2711+ QVERIFY(!list.isEmpty());
2712+
2713+ // Now get the mennu children (menu items)
2714+ list = getChildren(&iface, list.first().id, QStringList());
2715+ QVERIFY(!list.isEmpty());
2716+ DBusMenuLayoutItem item = list.first();
2717+
2718+ QVERIFY(item.id != 0);
2719+ QVERIFY(item.children.isEmpty());
2720+ QVERIFY(!item.properties.contains("type"));
2721+ QCOMPARE(item.properties.value("label").toString(), label);
2722+ if (enabled) {
2723+ QVERIFY(!item.properties.contains("enabled"));
2724+ } else {
2725+ QVERIFY(item.properties.contains("enabled"));
2726+ QCOMPARE(item.properties.value("enabled").toBool(), false);
2727+ }
2728+ if (iconName.isEmpty()) {
2729+ QVERIFY(!item.properties.contains("icon-name"));
2730+ } else {
2731+ QCOMPARE(item.properties.value("icon-name").toString(), iconName);
2732+ }
2733+}
2734+
2735+void ExportedPlatformMenuTest::testGetAllProperties()
2736+{
2737+ // set of properties which must be returned because their values are not
2738+ // the default values
2739+ const QSet<QString> a1Properties = QSet<QString>()
2740+ << "label"
2741+ ;
2742+
2743+ const QSet<QString> separatorProperties = QSet<QString>()
2744+ << "type";
2745+
2746+ const QSet<QString> a2Properties = QSet<QString>()
2747+ << "label"
2748+ << "enabled"
2749+ << "icon-name"
2750+ << "icon-data" // Icon data is always provided if the icon is valid.
2751+ << "visible";
2752+
2753+ ExportedPlatformMenuBar menuBar(TEST_OBJECT_PATH);
2754+ ExportedPlatformMenu menu;
2755+ menuBar.insertMenu(&menu, nullptr);
2756+
2757+ ExportedPlatformMenuItem menuItem1;
2758+ menuItem1.setText("m1");
2759+ menu.insertMenuItem(&menuItem1, nullptr);
2760+
2761+ ExportedPlatformMenuItem separator;
2762+ separator.setIsSeparator(true);
2763+ menu.insertMenuItem(&separator, nullptr);
2764+
2765+ ExportedPlatformMenuItem menuItem2;
2766+ menuItem2.setText("m2");
2767+ menuItem2.setEnabled(false);
2768+ menuItem2.setVisible(false);
2769+ QIcon icon = QIcon::fromTheme("edit-undo");
2770+ QVERIFY(!icon.isNull());
2771+ menuItem2.setIcon(icon);
2772+ menu.insertMenuItem(&menuItem2, nullptr);
2773+
2774+ // Export them
2775+ QDBusInterface iface(TEST_SERVICE, TEST_OBJECT_PATH);
2776+ QVERIFY2(iface.isValid(), qPrintable(iface.lastError().message()));
2777+
2778+ // Get menu children
2779+ DBusMenuLayoutItemList list = getChildren(&iface, menu.id(), QStringList());
2780+ QCOMPARE(list.count(), 3);
2781+
2782+ // Check we get the right properties
2783+ DBusMenuLayoutItem item = list.takeFirst();
2784+ QCOMPARE(QSet<QString>::fromList(item.properties.keys()), a1Properties);
2785+
2786+ item = list.takeFirst();
2787+ QCOMPARE(QSet<QString>::fromList(item.properties.keys()), separatorProperties);
2788+
2789+ item = list.takeFirst();
2790+ QCOMPARE(QSet<QString>::fromList(item.properties.keys()), a2Properties);
2791+}
2792+
2793+void ExportedPlatformMenuTest::testGetNonExistentProperty()
2794+{
2795+ const char* NON_EXISTENT_KEY = "i-do-not-exist";
2796+
2797+ ExportedPlatformMenuBar menuBar(TEST_OBJECT_PATH);
2798+ ExportedPlatformMenu menu;
2799+ menuBar.insertMenu(&menu, nullptr);
2800+
2801+ QDBusInterface iface(TEST_SERVICE, TEST_OBJECT_PATH);
2802+ DBusMenuLayoutItemList list = getChildren(&iface, 0, QStringList() << NON_EXISTENT_KEY);
2803+ QCOMPARE(list.count(), 1);
2804+
2805+ DBusMenuLayoutItem item = list.takeFirst();
2806+ QVERIFY(!item.properties.contains(NON_EXISTENT_KEY));
2807+}
2808+
2809+void ExportedPlatformMenuTest::testClickedEvent()
2810+{
2811+ ExportedPlatformMenuBar menuBar(TEST_OBJECT_PATH);
2812+ ExportedPlatformMenu menu;
2813+ menuBar.insertMenu(&menu, nullptr);
2814+
2815+ ExportedPlatformMenuItem menuItem1;
2816+ menuItem1.setText("m1");
2817+ menu.insertMenuItem(&menuItem1, nullptr);
2818+
2819+ QSignalSpy spy(&menuItem1, SIGNAL(activated()));
2820+
2821+ QDBusInterface iface(TEST_SERVICE, TEST_OBJECT_PATH);
2822+ DBusMenuLayoutItemList list = getChildren(&iface, menu.id(), QStringList());
2823+ QCOMPARE(list.count(), 1);
2824+ int id = list.first().id;
2825+
2826+ QVariant empty = QVariant::fromValue(QDBusVariant(QString()));
2827+ uint timestamp = QDateTime::currentDateTime().toTime_t();
2828+ iface.call("Event", id, "clicked", empty, timestamp);
2829+ QTest::qWait(100);
2830+
2831+ QCOMPARE(spy.count(), 1);
2832+}
2833+
2834+void ExportedPlatformMenuTest::testSubMenu()
2835+{
2836+ // Root
2837+ // -- submenu
2838+ // ---- childmenu
2839+ // ----- hildmenu
2840+
2841+ // Create our test menu
2842+ ExportedPlatformMenuBar menuBar(TEST_OBJECT_PATH);
2843+ ExportedPlatformMenu menu;
2844+ menuBar.insertMenu(&menu, nullptr);
2845+
2846+ ExportedPlatformMenu subMenu;
2847+ ExportedPlatformMenuItem subMenuItem;
2848+ subMenuItem.setMenu(&subMenu);
2849+ menu.insertMenuItem(&subMenuItem, nullptr);
2850+
2851+ ExportedPlatformMenuItem childMenu1;
2852+ ExportedPlatformMenuItem childMenu2;
2853+ subMenu.insertMenuItem(&childMenu1, nullptr);
2854+ subMenu.insertMenuItem(&childMenu2, nullptr);
2855+
2856+ // Check the structure
2857+ QDBusInterface iface(TEST_SERVICE, TEST_OBJECT_PATH);
2858+ DBusMenuLayoutItemList list = getChildren(&iface, 0, QStringList());
2859+ QCOMPARE(list.count(), 1);
2860+
2861+ list = getChildren(&iface, list.first().id, QStringList());
2862+ QCOMPARE(list.count(), 1);
2863+
2864+ list = getChildren(&iface, list.first().id, QStringList());
2865+ QCOMPARE(list.count(), 2);
2866+}
2867+
2868+void ExportedPlatformMenuTest::testDynamicSubMenu()
2869+{
2870+ // Root
2871+ // -- childmenu
2872+ // -- childmenu
2873+
2874+ // Track LayoutUpdated() signal: we don't want this signal to be emitted
2875+ // too often because it causes refreshes
2876+ QDBusInterface iface(TEST_SERVICE, TEST_OBJECT_PATH);
2877+ ManualSignalSpy layoutUpdatedSpy;
2878+ QDBusConnection::sessionBus().connect(TEST_SERVICE, TEST_OBJECT_PATH, "com.canonical.dbusmenu", "LayoutUpdated", "ui", &layoutUpdatedSpy, SLOT(receiveCall(uint, int)));
2879+
2880+ // Create our test menu
2881+ ExportedPlatformMenuBar menuBar(TEST_OBJECT_PATH);
2882+ ExportedPlatformMenu menu;
2883+ menuBar.insertMenu(&menu, nullptr);
2884+
2885+ // LayoutUpdated should be emitted once because inputMenu is filled
2886+ QTest::qWait(100);
2887+ QCOMPARE(layoutUpdatedSpy.count(), 1);
2888+ QCOMPARE(layoutUpdatedSpy.takeFirst().at(1).toInt(), 0);
2889+
2890+ ExportedPlatformMenu subMenu;
2891+ ExportedPlatformMenuItem subMenuItem1;
2892+ subMenuItem1.setMenu(&subMenu);
2893+ ExportedPlatformMenuItem subMenuItem2;
2894+ subMenuItem2.setMenu(&subMenu);
2895+ menu.insertMenuItem(&subMenuItem1, nullptr);
2896+ menu.insertMenuItem(&subMenuItem2, nullptr);
2897+
2898+ QTest::qWait(100);
2899+ // LayoutUpdated should be emitted once more with the parent menus id
2900+ // because menu item was inserted.
2901+ QCOMPARE(layoutUpdatedSpy.count(), 1);
2902+ QCOMPARE(layoutUpdatedSpy.takeFirst().at(1).toInt(), menu.id());
2903+
2904+ DBusMenuLayoutItemList list = getChildren(&iface, 0, QStringList());
2905+ QCOMPARE(list.count(), 1);
2906+
2907+ list = getChildren(&iface, list.first().id, QStringList());
2908+ QCOMPARE(list.count(), 2);
2909+}
2910+
2911+
2912+#include "exportedplatformmenutest.moc"
2913
2914=== added file 'tests/exportedplatformmenutest.h'
2915--- tests/exportedplatformmenutest.h 1970-01-01 00:00:00 +0000
2916+++ tests/exportedplatformmenutest.h 2015-03-18 11:19:06 +0000
2917@@ -0,0 +1,55 @@
2918+/* This file is part of the dbusmenu-qt library
2919+ Copyright 2015 Canonical
2920+ Author: Aurelien Gateau <aurelien.gateau@canonical.com>
2921+
2922+ This library is free software; you can redistribute it and/or
2923+ modify it under the terms of the GNU Library General Public
2924+ License (LGPL) as published by the Free Software Foundation;
2925+ either version 2 of the License, or (at your option) any later
2926+ version.
2927+
2928+ This library is distributed in the hope that it will be useful,
2929+ but WITHOUT ANY WARRANTY; without even the implied warranty of
2930+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
2931+ Library General Public License for more details.
2932+
2933+ You should have received a copy of the GNU Library General Public License
2934+ along with this library; see the file COPYING.LIB. If not, write to
2935+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
2936+ Boston, MA 02110-1301, USA.
2937+*/
2938+#ifndef EXPORTEDPLATFORMMENUTEST_H
2939+#define EXPORTEDPLATFORMMENUTEST_H
2940+
2941+#define QT_GUI_LIB
2942+#include <QtGui>
2943+
2944+// Qt
2945+#include <QObject>
2946+
2947+// Local
2948+
2949+class ExportedPlatformMenuTest : public QObject
2950+{
2951+Q_OBJECT
2952+private Q_SLOTS:
2953+ // properties
2954+ void testGetSomeMenuProperties();
2955+ void testGetSomeMenuProperties_data();
2956+ void testGetSomeMenuItemProperties();
2957+ void testGetSomeMenuItemProperties_data();
2958+ void testGetAllProperties();
2959+ void testGetNonExistentProperty();
2960+
2961+ // events
2962+ void testClickedEvent();
2963+
2964+ // heirachy
2965+ void testSubMenu();
2966+ void testDynamicSubMenu();
2967+
2968+ void init();
2969+ void cleanup();
2970+};
2971+
2972+#endif /* EXPORTEDPLATFORMMENUTEST_H */
2973
2974=== modified file 'tests/testutils.h'
2975--- tests/testutils.h 2011-08-29 14:51:01 +0000
2976+++ tests/testutils.h 2015-03-18 11:19:06 +0000
2977@@ -23,7 +23,7 @@
2978
2979 // Local
2980 #include <debug_p.h>
2981-#include <dbusmenutypes_p.h>
2982+#include <dbusmenutypes.h>
2983
2984 // Qt
2985 #include <QObject>

Subscribers

People subscribed via source and target branches

to all changes: