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

Proposed by Nick Dedekind
Status: Superseded
Proposed branch: lp:~nick-dedekind/libdbusmenu-qt/qpaexporter
Merge into: lp:libdbusmenu-qt
Diff against target: 3256 lines (+2519/-190)
33 files modified
CMakeLists.txt (+29/-4)
Doxyfile.in (+1/-1)
debian/changelog (+7/-0)
src/CMakeLists.txt (+42/-25)
src/com.canonical.dbusmenu.xml (+15/-15)
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 (+78/-27)
tests/dbusmenuexportertest.cpp (+3/-1)
tests/exportedplatformmenutest.cpp (+366/-0)
tests/exportedplatformmenutest.h (+55/-0)
tests/slowmenu.cpp (+1/-0)
tests/testutils.h (+1/-1)
To merge this branch: bzr merge lp:~nick-dedekind/libdbusmenu-qt/qpaexporter
Reviewer Review Type Date Requested Status
DBus Menu Team Pending
Review via email: mp+251888@code.launchpad.net

This proposal has been superseded by a proposal from 2015-03-18.

Commit message

Added support for qt platform and unity8

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.
271. By Nick Dedekind

logging & version bump

272. By Nick Dedekind

parent of exporter

273. By Nick Dedekind

merged with test branch

274. By Nick Dedekind

added exported platformmenu test

275. By Nick Dedekind

fixed addMenu

276. By Nick Dedekind

reverted dbus xml

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

Subscribers

People subscribed via source and target branches

to all changes: