Merge lp:~mitya57/appmenu-qt5/menus-and-systemtrayicons into lp:appmenu-qt5

Proposed by Dmitry Shachnev
Status: Merged
Approved by: Łukasz Zemczak
Approved revision: 28
Merged at revision: 29
Proposed branch: lp:~mitya57/appmenu-qt5/menus-and-systemtrayicons
Merge into: lp:appmenu-qt5
Diff against target: 1241 lines (+1139/-5)
13 files modified
src/appmenuplatformmenu.cpp (+129/-0)
src/appmenuplatformmenu.h (+59/-0)
src/appmenuplatformmenubar.cpp (+11/-2)
src/appmenuplatformmenuitem.cpp (+124/-0)
src/appmenuplatformmenuitem.h (+54/-0)
src/appmenuplatformsystemtrayicon.cpp (+235/-0)
src/appmenuplatformsystemtrayicon.h (+101/-0)
src/dbusstructures.cpp (+64/-0)
src/dbusstructures.h (+58/-0)
src/iconcache.cpp (+140/-0)
src/iconcache.h (+54/-0)
src/org.kde.StatusNotifierItem.xml (+96/-0)
src/src.pro (+14/-3)
To merge this branch: bzr merge lp:~mitya57/appmenu-qt5/menus-and-systemtrayicons
Reviewer Review Type Date Requested Status
Łukasz Zemczak Approve
Indicator Applet Developers Pending
Review via email: mp+244545@code.launchpad.net

Commit message

Add implementations of QPlatformMenuItem, QPlatformMenu and QPlatformSystemTrayIcon.

Description of the change

This adds new AppMenuPlatformMenuItem, AppMenuPlatformMenu, AppMenuPlatformSystemTrayIcon classes and helper classes/methods. A result of all this is that QSystemTrayIcon is useful again on Ubuntu.

Please read the QLTBA (questions likely to be asked) in the commit message.

How to test it: you need either Qt 5.4 from ppa:canonical-qt5-edgers/qt5-beta2 or patched Qt 5.3 from ppa:mitya57/test2 (the patch will be in the next official upload). Running systray example from qtbase5-examples should be a good way to test it.

To post a comment you must log in.
27. By Dmitry Shachnev

Add AppMenuPlatformMenuItem and AppMenuPlatformMenu classes

Having these classes will allow us to implement missing functionality
for AppMenuPlatformMenuBar class, and also add a new class for system
tray icons (AppMenuPlatformSystemTrayIcon).

28. By Dmitry Shachnev

Add AppMenuPlatformSystemTrayIcon implementation

Q: What’s this for?
A: Currently Qt 5 desktop applications which try to display a system
   tray icon will fail to do so in Unity desktop, because we abandoned
   the old XEmbed-based tray. This branch will make it work again, and
   in a nicer way. As a side-effect, notifications will now work too.

Q: We already have sni-qt, why is this needed?
A: sni-qt was only working with Qt 4, it does not work with Qt 5.
   Actually, a big part of code in this commit is copied from sni-qt.

Q: Why not just port sni-qt to Qt 5, why this code should be here?
A: In Qt 5, features such as platform tray icon should be implemented
   using Qt Platform Abstraction (QPA), which was not the case in Qt 4.
   More important, things like platform menu bar and platform tray icon
   should be in the same plugin, called “platform theme”. There should be
   only one platform theme for a platform, in Ubuntu it is appmenu-qt5.

Q: So is it just a copy of sni-qt code?
A: Most of it is based on sni-qt code, but it was changed a lot to work
   with Qt 5 and QPA interface. I also cleaned it up a bit and deleted
   some stuff that I think is not relevant.

Q: Does it add any additional dependencies to appmenu-qt5?
A: No. The only third-party library it needs is libdbusmenu-qt5, which
   is already used by appmenu-qt5.

Q: How does it work?
A: There are two things we should export — the “status notifier item”
   (which contains icon, tooltip, etc) and the menu. While the status
   notifier item will work with any server-side implementation, the menu
   will only work with ours (indicator-application). When
   indicator-application sees that an item has a menu, it will convert
   it into an indicator, and any indicator renderer (such as Unity, or
   indicator-applet) will show it.

Q: Which desktop environments will it work with?
A: It is designed to work with anything that supports indicators, like
   Unity or GNOME Flashback.

Q: Why the interface has KDE in name?
A: The StatusNotifierItem was originally developed by KDE project. While
   it is very possible that this standard will be adopted by FreeDesktop,
   indicator-application currently only supports the KDE name.

Q: Can KDE reuse this implementation?
A: They already have their own implementation, in Framework Integration.
   I could not reuse their code because they have not signed the
   Canonical contributor license agreement.

Revision history for this message
Dmitry Shachnev (mitya57) wrote :

This is ready for review now.

Note that this is disabled for KDE, as it is not going to work properly there. I think we should drop the KDE support altogether, as KDE now has its own platform theme and these two will conflict.

Revision history for this message
Łukasz Zemczak (sil2100) wrote :

Looks really good so far. I would like to do a few additional tests tomorrow morning still. Come to think of it, maybe soon we might need to think of changing the name from appmenu-qt5 to something more 'ubuntu-generic'.

Revision history for this message
Dmitry Shachnev (mitya57) wrote :

Yes, I want to get bug 1378935 fixed (when I have time for it), and after that it will become a full-featured platform theme. Maybe ubuntu-qt5-platform-theme will be a good name for it.

Revision history for this message
Dmitry Shachnev (mitya57) wrote :

I have just been pointed to https://codereview.qt-project.org/102386, which makes this whole branch unneeded. However it has not been merged yes, and if it is merged, in may or may not land in Qt 5.5. So let's keep my implementation until we have that new Qt (5.5 or 5.6) in Ubuntu.

Revision history for this message
Łukasz Zemczak (sil2100) wrote :

Ok, the code looks good. I didn't know too much of the old sni-qt code, but it seems everything we need is now included here as well. And let's not worry about future plans for Qt5, we can deprecate this when the need arises. For this cycle we're targeting 5.4 and I'm not sure if we'd jump to an even higher revision before release still.

review: Approve
Revision history for this message
Dmitry Shachnev (mitya57) wrote :

Hi Łukasz, are you going to land my branches, or should I take care of that? (Or do you have other pending changes?)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added file 'src/appmenuplatformmenu.cpp'
2--- src/appmenuplatformmenu.cpp 1970-01-01 00:00:00 +0000
3+++ src/appmenuplatformmenu.cpp 2014-12-13 15:39:31 +0000
4@@ -0,0 +1,129 @@
5+/*
6+ * Copyright 2014 Dmitry Shachnev <mitya57@ubuntu.com>
7+ *
8+ * This program is free software: you can redistribute it and/or modify
9+ * it under the terms of the GNU Lesser General Public License as published by
10+ * the Free Software Foundation, version 3 of the License.
11+ *
12+ * This program is distributed in the hope that it will be useful,
13+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+ * GNU Lesser General Public License for more details.
16+ *
17+ * You should have received a copy of the GNU Lesser General Public License
18+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
19+ */
20+
21+#include "appmenuplatformmenuitem.h"
22+#include "appmenuplatformmenu.h"
23+
24+AppMenuPlatformMenu::AppMenuPlatformMenu():
25+ m_menu(new QMenu()),
26+ m_tag(0)
27+{
28+ connect(m_menu, &QMenu::aboutToShow, this, &QPlatformMenu::aboutToShow);
29+ connect(m_menu, &QMenu::aboutToHide, this, &QPlatformMenu::aboutToHide);
30+}
31+
32+AppMenuPlatformMenu::~AppMenuPlatformMenu()
33+{
34+ delete m_menu;
35+}
36+
37+void AppMenuPlatformMenu::insertMenuItem(QPlatformMenuItem *menuItem, QPlatformMenuItem *before)
38+{
39+ AppMenuPlatformMenuItem *myMenuItem = qobject_cast<AppMenuPlatformMenuItem *>(menuItem);
40+ AppMenuPlatformMenuItem *myBefore = qobject_cast<AppMenuPlatformMenuItem *>(before);
41+
42+ QAction *beforeAction = myBefore ? myBefore->m_action : Q_NULLPTR;
43+ m_menu->insertAction(beforeAction, myMenuItem->m_action);
44+
45+ if (!myBefore) {
46+ m_menuitems.append(myMenuItem);
47+ return;
48+ }
49+
50+ for (int i = 0; i < m_menuitems.size(); ++i) {
51+ if (m_menuitems.at(i)->m_action == beforeAction) {
52+ m_menuitems.insert(i, myMenuItem);
53+ return;
54+ }
55+ }
56+}
57+
58+void AppMenuPlatformMenu::removeMenuItem(QPlatformMenuItem *menuItem)
59+{
60+ AppMenuPlatformMenuItem *myMenuItem = qobject_cast<AppMenuPlatformMenuItem *>(menuItem);
61+ m_menuitems.removeOne(myMenuItem);
62+ m_menu->removeAction(myMenuItem->m_action);
63+}
64+
65+void AppMenuPlatformMenu::syncMenuItem(QPlatformMenuItem *menuItem)
66+{
67+ Q_UNUSED(menuItem);
68+}
69+
70+void AppMenuPlatformMenu::syncSeparatorsCollapsible(bool enable)
71+{
72+ m_menu->setSeparatorsCollapsible(enable);
73+}
74+
75+void AppMenuPlatformMenu::setTag(quintptr tag)
76+{
77+ m_tag = tag;
78+}
79+
80+quintptr AppMenuPlatformMenu::tag() const
81+{
82+ return m_tag;
83+}
84+
85+void AppMenuPlatformMenu::setText(const QString &text)
86+{
87+ m_menu->setTitle(text);
88+}
89+
90+void AppMenuPlatformMenu::setIcon(const QIcon &icon)
91+{
92+ m_menu->setIcon(icon);
93+}
94+
95+void AppMenuPlatformMenu::setEnabled(bool enabled)
96+{
97+ m_menu->setEnabled(enabled);
98+}
99+
100+void AppMenuPlatformMenu::setVisible(bool visible)
101+{
102+ m_menu->setVisible(visible);
103+}
104+
105+void AppMenuPlatformMenu::setMinimumWidth(int width)
106+{
107+ m_menu->setMinimumWidth(width);
108+}
109+
110+void AppMenuPlatformMenu::setFont(const QFont &font)
111+{
112+ m_menu->setFont(font);
113+}
114+
115+QPlatformMenuItem *AppMenuPlatformMenu::menuItemAt(int position) const
116+{
117+ return m_menuitems.at(position);
118+}
119+
120+QPlatformMenuItem *AppMenuPlatformMenu::menuItemForTag(quintptr tag) const
121+{
122+ foreach (AppMenuPlatformMenuItem *item, m_menuitems) {
123+ if (item->m_tag == tag) {
124+ return item;
125+ }
126+ }
127+ return Q_NULLPTR;
128+}
129+
130+QPlatformMenuItem *AppMenuPlatformMenu::createMenuItem() const
131+{
132+ return new AppMenuPlatformMenuItem();
133+}
134
135=== added file 'src/appmenuplatformmenu.h'
136--- src/appmenuplatformmenu.h 1970-01-01 00:00:00 +0000
137+++ src/appmenuplatformmenu.h 2014-12-13 15:39:31 +0000
138@@ -0,0 +1,59 @@
139+/*
140+ * Copyright 2014 Dmitry Shachnev <mitya57@ubuntu.com>
141+ *
142+ * This program is free software: you can redistribute it and/or modify
143+ * it under the terms of the GNU Lesser General Public License as published by
144+ * the Free Software Foundation, version 3 of the License.
145+ *
146+ * This program is distributed in the hope that it will be useful,
147+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
148+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
149+ * GNU Lesser General Public License for more details.
150+ *
151+ * You should have received a copy of the GNU Lesser General Public License
152+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
153+ */
154+
155+#ifndef APPMENUPLATFORMMENU_H
156+#define APPMENUPLATFORMMENU_H
157+
158+#include <QtCore/qlist.h>
159+#include <QtWidgets/qmenu.h>
160+#include <qpa/qplatformmenu.h>
161+#include "appmenuplatformmenuitem.h"
162+
163+class AppMenuPlatformMenu : public QPlatformMenu
164+{
165+ Q_OBJECT
166+ friend class AppMenuPlatformMenuItem;
167+ friend class AppMenuPlatformSystemTrayIcon;
168+
169+public:
170+ AppMenuPlatformMenu();
171+ virtual ~AppMenuPlatformMenu();
172+
173+ virtual void insertMenuItem(QPlatformMenuItem *menuItem, QPlatformMenuItem *before);
174+ virtual void removeMenuItem(QPlatformMenuItem *menuItem);
175+ virtual void syncMenuItem(QPlatformMenuItem *menuItem);
176+ virtual void syncSeparatorsCollapsible(bool enable);
177+ virtual void setTag(quintptr tag);
178+ virtual quintptr tag() const;
179+ virtual void setText(const QString &text);
180+ virtual void setIcon(const QIcon &icon);
181+ virtual void setEnabled(bool enabled);
182+ virtual void setVisible(bool visible);
183+ virtual void setMinimumWidth(int width);
184+ virtual void setFont(const QFont &font);
185+ virtual QPlatformMenuItem *menuItemAt(int position) const;
186+ virtual QPlatformMenuItem *menuItemForTag(quintptr tag) const;
187+ virtual QPlatformMenuItem *createMenuItem() const;
188+
189+private:
190+ Q_DISABLE_COPY(AppMenuPlatformMenu)
191+
192+ QMenu *m_menu;
193+ QList<AppMenuPlatformMenuItem *> m_menuitems;
194+ quintptr m_tag;
195+};
196+
197+#endif /* APPMENUPLATFORMMENU_H */
198
199=== modified file 'src/appmenuplatformmenubar.cpp'
200--- src/appmenuplatformmenubar.cpp 2014-11-24 15:17:32 +0000
201+++ src/appmenuplatformmenubar.cpp 2014-12-13 15:39:31 +0000
202@@ -17,6 +17,8 @@
203 */
204
205 #include "appmenuplatformmenubar.h"
206+#include "appmenuplatformmenuitem.h"
207+#include "appmenuplatformsystemtrayicon.h"
208 #include "registrar_interface.h"
209
210 // Ugly, but sadly we need to use private headers for desktop-theme related classes
211@@ -243,9 +245,14 @@
212 {
213 public:
214 GnomeAppMenuPlatformTheme();
215- virtual QPlatformMenuItem* createPlatformMenuItem() const { return 0; }
216+ virtual QPlatformMenuItem* createPlatformMenuItem() const {
217+ return new AppMenuPlatformMenuItem();
218+ }
219 virtual QPlatformMenu* createPlatformMenu() const { return 0; }
220 virtual QPlatformMenuBar* createPlatformMenuBar() const;
221+ virtual QPlatformSystemTrayIcon* createPlatformSystemTrayIcon() const {
222+ return new AppMenuPlatformSystemTrayIcon();
223+ }
224
225 virtual QVariant themeHint(QPlatformTheme::ThemeHint hint) const;
226 };
227@@ -304,7 +311,9 @@
228 {
229 }
230 #endif
231- virtual QPlatformMenuItem* createPlatformMenuItem() const { return 0; }
232+ virtual QPlatformMenuItem* createPlatformMenuItem() const {
233+ return new AppMenuPlatformMenuItem();
234+ }
235 virtual QPlatformMenu* createPlatformMenu() const { return 0; }
236 virtual QPlatformMenuBar* createPlatformMenuBar() const;
237 };
238
239=== added file 'src/appmenuplatformmenuitem.cpp'
240--- src/appmenuplatformmenuitem.cpp 1970-01-01 00:00:00 +0000
241+++ src/appmenuplatformmenuitem.cpp 2014-12-13 15:39:31 +0000
242@@ -0,0 +1,124 @@
243+/*
244+ * Copyright 2014 Dmitry Shachnev <mitya57@ubuntu.com>
245+ *
246+ * This program is free software: you can redistribute it and/or modify
247+ * it under the terms of the GNU Lesser General Public License as published by
248+ * the Free Software Foundation, version 3 of the License.
249+ *
250+ * This program is distributed in the hope that it will be useful,
251+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
252+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
253+ * GNU Lesser General Public License for more details.
254+ *
255+ * You should have received a copy of the GNU Lesser General Public License
256+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
257+ */
258+
259+#include "appmenuplatformmenuitem.h"
260+#include "appmenuplatformmenu.h"
261+
262+AppMenuPlatformMenuItem::AppMenuPlatformMenuItem():
263+ m_action(new QAction(this)),
264+ m_tag(0)
265+{
266+ connect(m_action, &QAction::triggered, this, &QPlatformMenuItem::activated);
267+ connect(m_action, &QAction::hovered, this, &QPlatformMenuItem::hovered);
268+}
269+
270+AppMenuPlatformMenuItem::~AppMenuPlatformMenuItem()
271+{
272+ delete m_action;
273+}
274+
275+void AppMenuPlatformMenuItem::setTag(quintptr tag)
276+{
277+ m_tag = tag;
278+}
279+
280+quintptr AppMenuPlatformMenuItem::tag() const
281+{
282+ return m_tag;
283+}
284+
285+void AppMenuPlatformMenuItem::setText(const QString &text)
286+{
287+ m_action->setText(text);
288+}
289+
290+void AppMenuPlatformMenuItem::setIcon(const QIcon &icon)
291+{
292+ m_action->setIcon(icon);
293+}
294+
295+void AppMenuPlatformMenuItem::setMenu(QPlatformMenu *menu)
296+{
297+ if (menu) {
298+ AppMenuPlatformMenu *myMenu = qobject_cast<AppMenuPlatformMenu *>(menu);
299+ m_action->setMenu(myMenu->m_menu);
300+ }
301+}
302+
303+void AppMenuPlatformMenuItem::setVisible(bool isVisible)
304+{
305+ m_action->setVisible(isVisible);
306+}
307+
308+void AppMenuPlatformMenuItem::setIsSeparator(bool isSeparator)
309+{
310+ m_action->setSeparator(isSeparator);
311+}
312+
313+void AppMenuPlatformMenuItem::setFont(const QFont &font)
314+{
315+ m_action->setFont(font);
316+}
317+
318+void AppMenuPlatformMenuItem::setRole(MenuRole role)
319+{
320+ QAction::MenuRole newRole;
321+ switch (role) {
322+ case TextHeuristicRole:
323+ newRole = QAction::TextHeuristicRole;
324+ break;
325+ case ApplicationSpecificRole:
326+ newRole = QAction::ApplicationSpecificRole;
327+ break;
328+ case AboutRole:
329+ newRole = QAction::AboutRole;
330+ break;
331+ case PreferencesRole:
332+ newRole = QAction::PreferencesRole;
333+ break;
334+ case QuitRole:
335+ newRole = QAction::QuitRole;
336+ break;
337+ default:
338+ newRole = QAction::NoRole;
339+ }
340+ m_action->setMenuRole(newRole);
341+}
342+
343+void AppMenuPlatformMenuItem::setCheckable(bool checkable)
344+{
345+ m_action->setCheckable(checkable);
346+}
347+
348+void AppMenuPlatformMenuItem::setChecked(bool isChecked)
349+{
350+ m_action->setChecked(isChecked);
351+}
352+
353+void AppMenuPlatformMenuItem::setShortcut(const QKeySequence& shortcut)
354+{
355+ m_action->setShortcut(shortcut);
356+}
357+
358+void AppMenuPlatformMenuItem::setEnabled(bool enabled)
359+{
360+ m_action->setEnabled(enabled);
361+}
362+
363+void AppMenuPlatformMenuItem::setIconSize(int size)
364+{
365+ Q_UNUSED(size);
366+}
367
368=== added file 'src/appmenuplatformmenuitem.h'
369--- src/appmenuplatformmenuitem.h 1970-01-01 00:00:00 +0000
370+++ src/appmenuplatformmenuitem.h 2014-12-13 15:39:31 +0000
371@@ -0,0 +1,54 @@
372+/*
373+ * Copyright 2014 Dmitry Shachnev <mitya57@ubuntu.com>
374+ *
375+ * This program is free software: you can redistribute it and/or modify
376+ * it under the terms of the GNU Lesser General Public License as published by
377+ * the Free Software Foundation, version 3 of the License.
378+ *
379+ * This program is distributed in the hope that it will be useful,
380+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
381+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
382+ * GNU Lesser General Public License for more details.
383+ *
384+ * You should have received a copy of the GNU Lesser General Public License
385+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
386+ */
387+
388+#ifndef APPMENUPLATFORMMENUITEM_H
389+#define APPMENUPLATFORMMENUITEM_H
390+
391+#include <QtWidgets/qaction.h>
392+#include <qpa/qplatformmenu.h>
393+
394+class AppMenuPlatformMenuItem : public QPlatformMenuItem
395+{
396+ Q_OBJECT
397+ friend class AppMenuPlatformMenu;
398+
399+public:
400+ AppMenuPlatformMenuItem();
401+ virtual ~AppMenuPlatformMenuItem();
402+
403+ virtual void setTag(quintptr tag);
404+ virtual quintptr tag() const;
405+ virtual void setText(const QString &text);
406+ virtual void setIcon(const QIcon &icon);
407+ virtual void setMenu(QPlatformMenu *menu);
408+ virtual void setVisible(bool isVisible);
409+ virtual void setIsSeparator(bool isSeparator);
410+ virtual void setFont(const QFont &font);
411+ virtual void setRole(MenuRole role);
412+ virtual void setCheckable(bool checkable);
413+ virtual void setChecked(bool isChecked);
414+ virtual void setShortcut(const QKeySequence& shortcut);
415+ virtual void setEnabled(bool enabled);
416+ virtual void setIconSize(int size);
417+
418+private:
419+ Q_DISABLE_COPY(AppMenuPlatformMenuItem)
420+
421+ QAction *m_action;
422+ quintptr m_tag;
423+};
424+
425+#endif /* APPMENUPLATFORMMENUITEM_H */
426
427=== added file 'src/appmenuplatformsystemtrayicon.cpp'
428--- src/appmenuplatformsystemtrayicon.cpp 1970-01-01 00:00:00 +0000
429+++ src/appmenuplatformsystemtrayicon.cpp 2014-12-13 15:39:31 +0000
430@@ -0,0 +1,235 @@
431+/*
432+ * Copyright 2011 Canonical Ltd.
433+ * Copyright 2014 Dmitry Shachnev <mitya57@ubuntu.com>
434+ *
435+ * This program is free software: you can redistribute it and/or modify
436+ * it under the terms of the GNU Lesser General Public License as published by
437+ * the Free Software Foundation, version 3 of the License.
438+ *
439+ * This program is distributed in the hope that it will be useful,
440+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
441+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
442+ * GNU Lesser General Public License for more details.
443+ *
444+ * You should have received a copy of the GNU Lesser General Public License
445+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
446+ *
447+ * Based on sni-qt code by Aurelien Gateau <aurelien.gateau@canonical.com>.
448+ */
449+
450+#include <QtCore/qcoreapplication.h>
451+#include <QtDBus/qdbusconnection.h>
452+#include <QtDBus/qdbusconnectioninterface.h>
453+#include <QtDBus/qdbusinterface.h>
454+#include "appmenuplatformmenu.h"
455+#include "appmenuplatformsystemtrayicon.h"
456+#include "iconcache.h"
457+
458+static const char *SNW_INTERFACE = "org.kde.StatusNotifierWatcher";
459+static const char *SNW_SERVICE = "org.kde.StatusNotifierWatcher";
460+static const char *SNW_PATH = "/StatusNotifierWatcher";
461+
462+static const char *NOTIFICATION_INTERFACE = "org.freedesktop.Notifications";
463+static const char *NOTIFICATION_SERVICE = "org.freedesktop.Notifications";
464+static const char *NOTIFICATION_PATH = "/org/freedesktop/Notifications";
465+
466+static IconCache iconCache;
467+
468+AppMenuPlatformSystemTrayIcon::AppMenuPlatformSystemTrayIcon():
469+ m_sniAdaptor(new StatusNotifierItemAdaptor(this)),
470+ m_dbusMenuExporter(Q_NULLPTR)
471+{
472+ static int id = 1;
473+ m_objectPath = QString("/org/kde/statusnotifieritem/%1").arg(id++);
474+
475+ registerMetaTypes();
476+ QDBusConnection bus = QDBusConnection::sessionBus();
477+ bus.registerObject(m_objectPath, this, QDBusConnection::ExportAdaptors);
478+ QDBusInterface snw(SNW_SERVICE, SNW_PATH, SNW_INTERFACE);
479+ snw.asyncCall("RegisterStatusNotifierItem", m_objectPath);
480+}
481+
482+AppMenuPlatformSystemTrayIcon::~AppMenuPlatformSystemTrayIcon()
483+{
484+ delete m_sniAdaptor;
485+}
486+
487+// QPlatformSystemTrayIcon implementation
488+
489+void AppMenuPlatformSystemTrayIcon::init()
490+{
491+ m_status = QStringLiteral("Active");
492+ emit NewStatus(m_status);
493+}
494+
495+void AppMenuPlatformSystemTrayIcon::cleanup()
496+{
497+ m_status = QStringLiteral("Passive");
498+ emit NewStatus(m_status);
499+}
500+
501+void AppMenuPlatformSystemTrayIcon::updateIcon(const QIcon &icon)
502+{
503+ m_icon = icon;
504+ emit NewIcon();
505+ emit NewToolTip(); // ToolTip contains the icon
506+}
507+
508+void AppMenuPlatformSystemTrayIcon::updateToolTip(const QString &tooltip)
509+{
510+ m_tooltip = tooltip;
511+ emit NewToolTip();
512+}
513+
514+void AppMenuPlatformSystemTrayIcon::updateMenu(QPlatformMenu *menu)
515+{
516+ QMenu *qMenu = qobject_cast<AppMenuPlatformMenu *>(menu)->m_menu;
517+ QString menuObjectPath = m_objectPath + QStringLiteral("/menu");
518+ m_dbusMenuExporter = new DBusMenuExporter(menuObjectPath, qMenu);
519+}
520+
521+QRect AppMenuPlatformSystemTrayIcon::geometry() const
522+{
523+ return QRect();
524+}
525+
526+void AppMenuPlatformSystemTrayIcon::showMessage(const QString &title, const QString &msg,
527+ const QIcon &icon, MessageIcon iconType, int msecs)
528+{
529+ QString iconString = icon.name();
530+ if (iconString.isEmpty()) {
531+ switch (iconType) {
532+ case NoIcon:
533+ break;
534+ case Information:
535+ iconString = "dialog-information";
536+ break;
537+ case Warning:
538+ iconString = "dialog-warning";
539+ break;
540+ case Critical:
541+ iconString = "dialog-error";
542+ break;
543+ }
544+ }
545+
546+ QDBusInterface iface(NOTIFICATION_SERVICE, NOTIFICATION_PATH, NOTIFICATION_INTERFACE);
547+ iface.asyncCall("Notify",
548+ id(),
549+ quint32(0), // replaces_id
550+ iconString,
551+ title,
552+ msg,
553+ QStringList(), // actions
554+ QVariantMap(), // hints
555+ msecs); // timeout
556+}
557+
558+bool AppMenuPlatformSystemTrayIcon::isSystemTrayAvailable() const
559+{
560+ const QDBusConnectionInterface *interface = QDBusConnection::sessionBus().interface();
561+ if (!interface->isServiceRegistered(SNW_SERVICE).value()) {
562+ return false;
563+ }
564+ QDBusInterface snw(SNW_SERVICE, SNW_PATH, SNW_INTERFACE);
565+ QVariant value = snw.property("IsStatusNotifierHostRegistered");
566+ if (!value.canConvert<bool>()) {
567+ return false;
568+ }
569+ return value.toBool();
570+}
571+
572+bool AppMenuPlatformSystemTrayIcon::supportsMessages() const
573+{
574+ const QDBusConnectionInterface *interface = QDBusConnection::sessionBus().interface();
575+ return interface->isServiceRegistered(NOTIFICATION_SERVICE).value();
576+}
577+
578+QPlatformMenu *AppMenuPlatformSystemTrayIcon::createMenu() const
579+{
580+ return new AppMenuPlatformMenu();
581+}
582+
583+// Properties
584+
585+QString AppMenuPlatformSystemTrayIcon::category() const
586+{
587+ return QStringLiteral("ApplicationStatus");
588+}
589+
590+QString AppMenuPlatformSystemTrayIcon::id() const
591+{
592+ return QCoreApplication::applicationFilePath().section('/', -1);
593+}
594+
595+QString AppMenuPlatformSystemTrayIcon::title() const
596+{
597+ QString title = QCoreApplication::applicationName();
598+ return title.isEmpty() ? id() : title;
599+}
600+
601+QString AppMenuPlatformSystemTrayIcon::status() const
602+{
603+ return m_status;
604+}
605+
606+QString AppMenuPlatformSystemTrayIcon::iconThemePath() const
607+{
608+ return iconCache.themePath();
609+}
610+
611+QString AppMenuPlatformSystemTrayIcon::iconName() const
612+{
613+ if (m_icon.isNull()) {
614+ return QString();
615+ }
616+ QString name = m_icon.name();
617+ if (!name.isEmpty()) {
618+ return name;
619+ }
620+
621+ return iconCache.nameForIcon(m_icon);
622+}
623+
624+DBusToolTip AppMenuPlatformSystemTrayIcon::toolTip() const
625+{
626+ DBusToolTip tip;
627+ tip.iconName = iconName();
628+ tip.title = m_tooltip;
629+ return tip;
630+}
631+
632+QDBusObjectPath AppMenuPlatformSystemTrayIcon::menu() const
633+{
634+ return m_dbusMenuExporter
635+ ? QDBusObjectPath(m_objectPath + QStringLiteral("/menu"))
636+ : QDBusObjectPath("/invalid");
637+}
638+
639+// StatusNotifierItem implementation
640+
641+void AppMenuPlatformSystemTrayIcon::ContextMenu(int x, int y)
642+{
643+ Q_UNUSED(x);
644+ Q_UNUSED(y);
645+}
646+
647+void AppMenuPlatformSystemTrayIcon::Activate(int x, int y)
648+{
649+ Q_UNUSED(x);
650+ Q_UNUSED(y);
651+ emit activated(Trigger);
652+}
653+
654+void AppMenuPlatformSystemTrayIcon::SecondaryActivate(int x, int y)
655+{
656+ Q_UNUSED(x);
657+ Q_UNUSED(y);
658+ emit activated(MiddleClick);
659+}
660+
661+void AppMenuPlatformSystemTrayIcon::Scroll(int delta, const QString& orientation)
662+{
663+ Q_UNUSED(delta);
664+ Q_UNUSED(orientation);
665+}
666
667=== added file 'src/appmenuplatformsystemtrayicon.h'
668--- src/appmenuplatformsystemtrayicon.h 1970-01-01 00:00:00 +0000
669+++ src/appmenuplatformsystemtrayicon.h 2014-12-13 15:39:31 +0000
670@@ -0,0 +1,101 @@
671+/*
672+ * Copyright 2014 Dmitry Shachnev <mitya57@ubuntu.com>
673+ *
674+ * This program is free software: you can redistribute it and/or modify
675+ * it under the terms of the GNU Lesser General Public License as published by
676+ * the Free Software Foundation, version 3 of the License.
677+ *
678+ * This program is distributed in the hope that it will be useful,
679+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
680+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
681+ * GNU Lesser General Public License for more details.
682+ *
683+ * You should have received a copy of the GNU Lesser General Public License
684+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
685+ */
686+
687+#ifndef APPMENUPLATFORMSYSTEMTRAYICON_H
688+#define APPMENUPLATFORMSYSTEMTRAYICON_H
689+
690+#include <QtCore/qrect.h>
691+#include <QtCore/qstring.h>
692+#include <QtGui/qicon.h>
693+#include <qpa/qplatformsystemtrayicon.h>
694+#include <dbusmenuexporter.h>
695+#include "statusnotifieritem_adaptor.h"
696+
697+class AppMenuPlatformSystemTrayIcon : public QPlatformSystemTrayIcon
698+{
699+ Q_OBJECT
700+ Q_PROPERTY(QString Category READ category)
701+ Q_PROPERTY(QString Id READ id)
702+ Q_PROPERTY(QString Title READ title)
703+ Q_PROPERTY(QString Status READ status)
704+ Q_PROPERTY(quint32 WindowId READ windowId)
705+ Q_PROPERTY(QString IconThemePath READ iconThemePath)
706+ Q_PROPERTY(QString IconName READ iconName)
707+ Q_PROPERTY(DBusImageList IconPixmap READ iconPixmap)
708+ Q_PROPERTY(QString OverlayIconName READ overlayIconName)
709+ Q_PROPERTY(DBusImageList OverlayIconPixmap READ overlayIconPixmap)
710+ Q_PROPERTY(QString AttentionIconName READ attentionIconName)
711+ Q_PROPERTY(DBusImageList AttentionIconPixmap READ attentionIconPixmap)
712+ Q_PROPERTY(QString AttentionMovieName READ attentionMovieName)
713+ Q_PROPERTY(DBusToolTip ToolTip READ toolTip)
714+ Q_PROPERTY(QDBusObjectPath Menu READ menu)
715+
716+public:
717+ AppMenuPlatformSystemTrayIcon();
718+ virtual ~AppMenuPlatformSystemTrayIcon();
719+
720+ // QPlatformSystemTrayIcon
721+ virtual void init();
722+ virtual void cleanup();
723+ virtual void updateIcon(const QIcon &icon);
724+ virtual void updateToolTip(const QString &tooltip);
725+ virtual void updateMenu(QPlatformMenu *menu);
726+ virtual QRect geometry() const;
727+ virtual void showMessage(const QString &title, const QString &msg,
728+ const QIcon &icon, MessageIcon iconType, int msecs);
729+ virtual bool isSystemTrayAvailable() const;
730+ virtual bool supportsMessages() const;
731+ virtual QPlatformMenu *createMenu() const;
732+
733+ // Properties
734+ QString category() const;
735+ QString id() const;
736+ QString title() const;
737+ QString status() const;
738+ quint32 windowId() const { return 0; }
739+ QString iconThemePath() const;
740+ QString iconName() const;
741+ DBusImageList iconPixmap() const { return DBusImageList(); }
742+ QString overlayIconName() const { return QString(); }
743+ DBusImageList overlayIconPixmap() const { return DBusImageList(); }
744+ QString attentionIconName() const { return QString(); }
745+ DBusImageList attentionIconPixmap() const { return DBusImageList(); }
746+ QString attentionMovieName() const { return QString(); }
747+ DBusToolTip toolTip() const;
748+ QDBusObjectPath menu() const;
749+
750+ // StatusNotifierItem
751+ void ContextMenu(int x, int y);
752+ void Activate(int x, int y);
753+ void SecondaryActivate(int x, int y);
754+ void Scroll(int delta, const QString& orientation);
755+
756+Q_SIGNALS:
757+ void NewStatus(const QString &status);
758+ void NewIcon();
759+ void NewToolTip();
760+
761+private:
762+ QString m_objectPath;
763+ QString m_status;
764+ QIcon m_icon;
765+ QString m_tooltip;
766+
767+ StatusNotifierItemAdaptor *m_sniAdaptor;
768+ DBusMenuExporter *m_dbusMenuExporter;
769+};
770+
771+#endif /* APPMENUPLATFORMSYSTEMTRAYICON_H */
772
773=== added file 'src/dbusstructures.cpp'
774--- src/dbusstructures.cpp 1970-01-01 00:00:00 +0000
775+++ src/dbusstructures.cpp 2014-12-13 15:39:31 +0000
776@@ -0,0 +1,64 @@
777+/*
778+ * Copyright 2011 Canonical Ltd.
779+ * Copyright 2014 Dmitry Shachnev <mitya57@ubuntu.com>
780+ *
781+ * This program is free software: you can redistribute it and/or modify
782+ * it under the terms of the GNU Lesser General Public License as published by
783+ * the Free Software Foundation, version 3 of the License.
784+ *
785+ * This program is distributed in the hope that it will be useful,
786+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
787+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
788+ * GNU Lesser General Public License for more details.
789+ *
790+ * You should have received a copy of the GNU Lesser General Public License
791+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
792+ *
793+ * Based on sni-qt code by Aurelien Gateau <aurelien.gateau@canonical.com>.
794+ */
795+
796+#include <QtDBus/qdbusmetatype.h>
797+#include "dbusstructures.h"
798+
799+QDBusArgument &operator<<(QDBusArgument &argument, const DBusImage &image)
800+{
801+ argument.beginStructure();
802+ argument << image.width << image.height << image.pixels;
803+ argument.endStructure();
804+ return argument;
805+}
806+
807+const QDBusArgument &operator>>(const QDBusArgument &argument, DBusImage &image)
808+{
809+ argument.beginStructure();
810+ argument >> image.width >> image.height >> image.pixels;
811+ argument.endStructure();
812+ return argument;
813+}
814+
815+QDBusArgument &operator<<(QDBusArgument &argument, const DBusToolTip &tip)
816+{
817+ argument.beginStructure();
818+ argument << tip.iconName << tip.iconPixmap << tip.title << tip.description;
819+ argument.endStructure();
820+ return argument;
821+}
822+
823+const QDBusArgument &operator>>(const QDBusArgument &argument, DBusToolTip &tip)
824+{
825+ argument.beginStructure();
826+ argument >> tip.iconName >> tip.iconPixmap >> tip.title >> tip.description;
827+ argument.endStructure();
828+ return argument;
829+}
830+
831+void registerMetaTypes()
832+{
833+ static bool registered = false;
834+ if (registered) {
835+ return;
836+ }
837+ qDBusRegisterMetaType<DBusImage>();
838+ qDBusRegisterMetaType<DBusImageList>();
839+ qDBusRegisterMetaType<DBusToolTip>();
840+}
841
842=== added file 'src/dbusstructures.h'
843--- src/dbusstructures.h 1970-01-01 00:00:00 +0000
844+++ src/dbusstructures.h 2014-12-13 15:39:31 +0000
845@@ -0,0 +1,58 @@
846+/*
847+ * Copyright 2011 Canonical Ltd.
848+ * Copyright 2014 Dmitry Shachnev <mitya57@ubuntu.com>
849+ *
850+ * This program is free software: you can redistribute it and/or modify
851+ * it under the terms of the GNU Lesser General Public License as published by
852+ * the Free Software Foundation, version 3 of the License.
853+ *
854+ * This program is distributed in the hope that it will be useful,
855+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
856+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
857+ * GNU Lesser General Public License for more details.
858+ *
859+ * You should have received a copy of the GNU Lesser General Public License
860+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
861+ *
862+ * Based on sni-qt code by Aurelien Gateau <aurelien.gateau@canonical.com>.
863+ */
864+
865+#ifndef DBUSSTRUCTURES_H
866+#define DBUSSTRUCTURES_H
867+
868+#include <QtCore/qbytearray.h>
869+#include <QtCore/qstring.h>
870+#include <QtCore/qlist.h>
871+#include <QtGui/qicon.h>
872+#include <QtGui/qpixmap.h>
873+#include <QtDBus/qdbusargument.h>
874+
875+struct DBusImage
876+{
877+ int width;
878+ int height;
879+ QByteArray pixels;
880+};
881+Q_DECLARE_METATYPE(DBusImage)
882+
883+typedef QList<DBusImage> DBusImageList;
884+Q_DECLARE_METATYPE(DBusImageList)
885+
886+struct DBusToolTip
887+{
888+ QString iconName;
889+ DBusImageList iconPixmap;
890+ QString title;
891+ QString description;
892+};
893+Q_DECLARE_METATYPE(DBusToolTip)
894+
895+QDBusArgument &operator<<(QDBusArgument&, const DBusImage&);
896+const QDBusArgument &operator>>(const QDBusArgument&, DBusImage&);
897+
898+QDBusArgument &operator<<(QDBusArgument&, const DBusToolTip&);
899+const QDBusArgument &operator>>(const QDBusArgument&, DBusToolTip&);
900+
901+void registerMetaTypes();
902+
903+#endif /* DBUSSTRUCTURES_H */
904
905=== added file 'src/iconcache.cpp'
906--- src/iconcache.cpp 1970-01-01 00:00:00 +0000
907+++ src/iconcache.cpp 2014-12-13 15:39:31 +0000
908@@ -0,0 +1,140 @@
909+/*
910+ * Copyright 2011 Canonical Ltd.
911+ * Copyright 2014 Dmitry Shachnev <mitya57@ubuntu.com>
912+ *
913+ * This program is free software: you can redistribute it and/or modify
914+ * it under the terms of the GNU Lesser General Public License as published by
915+ * the Free Software Foundation, version 3 of the License.
916+ *
917+ * This program is distributed in the hope that it will be useful,
918+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
919+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
920+ * GNU Lesser General Public License for more details.
921+ *
922+ * You should have received a copy of the GNU Lesser General Public License
923+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
924+ *
925+ * Based on sni-qt code by Aurelien Gateau <aurelien.gateau@canonical.com>.
926+ */
927+
928+#include <sys/types.h>
929+#include <utime.h>
930+#include <QtCore/qcoreapplication.h>
931+#include <QtCore/qdatetime.h>
932+#include <QtCore/qdebug.h>
933+#include <QtCore/qdir.h>
934+#include "iconcache.h"
935+
936+const int IconCache::MaxIconCount = 20;
937+
938+IconCache::IconCache(QObject *parent):
939+ QObject(parent),
940+ m_temporaryDir(Q_NULLPTR),
941+ m_initialized(false)
942+{
943+}
944+
945+IconCache::~IconCache()
946+{
947+ if (m_temporaryDir) {
948+ delete m_temporaryDir;
949+ }
950+}
951+
952+QString IconCache::themePath()
953+{
954+ if (!m_initialized) {
955+ QString path = QDir::tempPath() + QStringLiteral("/iconcache-XXXXXX");
956+ m_temporaryDir = new QTemporaryDir(path);
957+ m_initialized = true;
958+ }
959+ return m_temporaryDir->path();
960+}
961+
962+QString IconCache::nameForIcon(const QIcon &icon)
963+{
964+ if (icon.isNull()) {
965+ return QString();
966+ }
967+
968+ qint64 key = icon.cacheKey();
969+ QList<qint64>::iterator it = qFind(m_cacheKeys.begin(), m_cacheKeys.end(), key);
970+ if (it == m_cacheKeys.end()) {
971+ cacheIcon(key, icon);
972+ trimCache();
973+ } else {
974+ // Place key at the end of list as it is the most recently accessed
975+ m_cacheKeys.erase(it);
976+ m_cacheKeys.append(key);
977+ }
978+
979+ return QString::number(key);
980+}
981+
982+void IconCache::trimCache()
983+{
984+ QDir dir(themePath() + "/hicolor");
985+ dir.setFilter(QDir::Dirs);
986+
987+ while (m_cacheKeys.count() > MaxIconCount) {
988+ qint64 cacheKey = m_cacheKeys.takeFirst();
989+
990+ Q_FOREACH(const QString &sizeDir, dir.entryList()) {
991+ QString iconSubPath = QString("%1/apps/%2.png").arg(sizeDir).arg(cacheKey);
992+ if (dir.exists(iconSubPath)) {
993+ dir.remove(iconSubPath);
994+ }
995+ }
996+ }
997+}
998+
999+void touch(const QString &_name, const QDateTime &time)
1000+{
1001+ QByteArray name = QFile::encodeName(_name);
1002+ struct utimbuf buf;
1003+ buf.actime = time.toTime_t();
1004+ buf.modtime = buf.actime;
1005+ int ret = utime(name.data(), &buf);
1006+ if (ret) {
1007+ qCritical("Failed to touch %s: %s", name.data(), strerror(errno));
1008+ }
1009+}
1010+
1011+void IconCache::cacheIcon(qint64 key, const QIcon &icon)
1012+{
1013+ QList<QSize> sizes; //= icon.availableSizes();
1014+ if (sizes.isEmpty()) {
1015+ // sizes can be empty if icon is an SVG. In this case generate images for a few sizes
1016+ sizes << QSize(16, 16) << QSize(22, 22) << QSize(32, 32) << QSize(48, 48);
1017+ }
1018+
1019+ QDir dir(themePath());
1020+ Q_FOREACH(const QSize &size, sizes) {
1021+ QPixmap pix = icon.pixmap(size);
1022+ QString dirName = QString("hicolor/%1x%1/apps").arg(size.width());
1023+ if (!dir.exists(dirName)) {
1024+ if (!dir.mkpath(dirName)) {
1025+ qWarning("Could not create '%s' dir in '%s'",
1026+ qPrintable(themePath()), qPrintable(dirName));
1027+ continue;
1028+ }
1029+ }
1030+ QString pixPath = QString("%1/%2/%3.png")
1031+ .arg(themePath()).arg(dirName).arg(key);
1032+ if (!pix.save(pixPath, "png")) {
1033+ qWarning("Could not save icon as '%s'", qPrintable(pixPath));
1034+ }
1035+ }
1036+
1037+ m_cacheKeys << key;
1038+
1039+ // Touch the theme path: GTK icon loading system checks the mtime of the
1040+ // dir to decide whether it should look for new icons in the theme dir.
1041+ //
1042+ // Note: We do not use QDateTime::currentDateTime() as the new time because
1043+ // if the icon is updated in less than one second, GTK won't notice it.
1044+ // See https://bugs.launchpad.net/sni-qt/+bug/812884
1045+ QFileInfo info(themePath());
1046+ QDateTime mtime = info.lastModified();
1047+ touch(themePath(), mtime.addSecs(1));
1048+}
1049
1050=== added file 'src/iconcache.h'
1051--- src/iconcache.h 1970-01-01 00:00:00 +0000
1052+++ src/iconcache.h 2014-12-13 15:39:31 +0000
1053@@ -0,0 +1,54 @@
1054+/*
1055+ * Copyright 2011 Canonical Ltd.
1056+ * Copyright 2014 Dmitry Shachnev <mitya57@ubuntu.com>
1057+ *
1058+ * This program is free software: you can redistribute it and/or modify
1059+ * it under the terms of the GNU Lesser General Public License as published by
1060+ * the Free Software Foundation, version 3 of the License.
1061+ *
1062+ * This program is distributed in the hope that it will be useful,
1063+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1064+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1065+ * GNU Lesser General Public License for more details.
1066+ *
1067+ * You should have received a copy of the GNU Lesser General Public License
1068+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1069+ *
1070+ * Based on sni-qt code by Aurelien Gateau <aurelien.gateau@canonical.com>.
1071+ */
1072+
1073+#ifndef ICONCACHE_H
1074+#define ICONCACHE_H
1075+
1076+#include <QtCore/qlist.h>
1077+#include <QtCore/qobject.h>
1078+#include <QtCore/qstring.h>
1079+#include <QtCore/qtemporarydir.h>
1080+#include <QtGui/qicon.h>
1081+
1082+/**
1083+ * This class will save pixmaps from icons in a temporary dir on the disk,
1084+ * making it possible to pass filenames for icons without names.
1085+ */
1086+class IconCache : public QObject
1087+{
1088+ Q_OBJECT
1089+public:
1090+ IconCache(QObject* parent=0);
1091+ ~IconCache();
1092+
1093+ static const int MaxIconCount;
1094+
1095+ QString themePath();
1096+ QString nameForIcon(const QIcon &icon);
1097+
1098+private:
1099+ QTemporaryDir *m_temporaryDir;
1100+ mutable QList<qint64> m_cacheKeys;
1101+ bool m_initialized;
1102+
1103+ void cacheIcon(qint64 key, const QIcon &);
1104+ void trimCache();
1105+};
1106+
1107+#endif /* ICONCACHE_H */
1108
1109=== added file 'src/org.kde.StatusNotifierItem.xml'
1110--- src/org.kde.StatusNotifierItem.xml 1970-01-01 00:00:00 +0000
1111+++ src/org.kde.StatusNotifierItem.xml 2014-12-13 15:39:31 +0000
1112@@ -0,0 +1,96 @@
1113+<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
1114+<node>
1115+ <interface name="org.kde.StatusNotifierItem">
1116+
1117+ <property name="Category" type="s" access="read"/>
1118+ <property name="Id" type="s" access="read"/>
1119+ <property name="Title" type="s" access="read"/>
1120+ <property name="Status" type="s" access="read"/>
1121+ <property name="WindowId" type="i" access="read"/>
1122+
1123+ <!-- An additional path to add to the theme search path to find the icons specified above. -->
1124+ <property name="IconThemePath" type="s" access="read"/>
1125+ <property name="Menu" type="o" access="read"/>
1126+ <property name="ItemIsMenu" type="b" access="read"/>
1127+
1128+
1129+ <!-- main icon -->
1130+ <!-- names are preferred over pixmaps -->
1131+ <property name="IconName" type="s" access="read"/>
1132+
1133+ <!--struct containing width, height and image data-->
1134+ <property name="IconPixmap" type="(iiay)" access="read">
1135+ <annotation name="org.qtproject.QtDBus.QtTypeName" value="DBusImageList"/>
1136+ </property>
1137+
1138+ <property name="OverlayIconName" type="s" access="read"/>
1139+
1140+ <property name="OverlayIconPixmap" type="(iiay)" access="read">
1141+ <annotation name="org.qtproject.QtDBus.QtTypeName" value="DBusImageList"/>
1142+ </property>
1143+
1144+
1145+ <!-- Requesting attention icon -->
1146+ <property name="AttentionIconName" type="s" access="read"/>
1147+
1148+ <!--same definition as image-->
1149+ <property name="AttentionIconPixmap" type="(iiay)" access="read">
1150+ <annotation name="org.qtproject.QtDBus.QtTypeName" value="DBusImageList"/>
1151+ </property>
1152+
1153+ <property name="AttentionMovieName" type="s" access="read"/>
1154+
1155+
1156+
1157+ <!-- tooltip data -->
1158+
1159+ <!--(iiay) is an image-->
1160+ <property name="ToolTip" type="(s(iiay)ss)" access="read">
1161+ <annotation name="org.qtproject.QtDBus.QtTypeName" value="DBusToolTip"/>
1162+ </property>
1163+
1164+
1165+ <!-- interaction: the systemtray wants the application to do something -->
1166+ <method name="ContextMenu">
1167+ <!-- we're passing the coordinates of the icon, so the app knows where to put the popup window -->
1168+ <arg name="x" type="i" direction="in"/>
1169+ <arg name="y" type="i" direction="in"/>
1170+ </method>
1171+
1172+ <method name="Activate">
1173+ <arg name="x" type="i" direction="in"/>
1174+ <arg name="y" type="i" direction="in"/>
1175+ </method>
1176+
1177+ <method name="SecondaryActivate">
1178+ <arg name="x" type="i" direction="in"/>
1179+ <arg name="y" type="i" direction="in"/>
1180+ </method>
1181+
1182+ <method name="Scroll">
1183+ <arg name="delta" type="i" direction="in"/>
1184+ <arg name="orientation" type="s" direction="in"/>
1185+ </method>
1186+
1187+ <!-- Signals: the client wants to change something in the status-->
1188+ <signal name="NewTitle">
1189+ </signal>
1190+
1191+ <signal name="NewIcon">
1192+ </signal>
1193+
1194+ <signal name="NewAttentionIcon">
1195+ </signal>
1196+
1197+ <signal name="NewOverlayIcon">
1198+ </signal>
1199+
1200+ <signal name="NewToolTip">
1201+ </signal>
1202+
1203+ <signal name="NewStatus">
1204+ <arg name="status" type="s"/>
1205+ </signal>
1206+
1207+ </interface>
1208+</node>
1209
1210=== modified file 'src/src.pro'
1211--- src/src.pro 2014-04-14 15:04:02 +0000
1212+++ src/src.pro 2014-12-13 15:39:31 +0000
1213@@ -6,14 +6,25 @@
1214
1215 QT += core-private gui-private platformsupport-private dbus widgets
1216 DBUS_INTERFACES += com.canonical.AppMenu.Registrar.xml
1217+DBUS_ADAPTORS += org.kde.StatusNotifierItem.xml
1218+QDBUSXML2CPP_ADAPTOR_HEADER_FLAGS += -i dbusstructures.h
1219
1220 CONFIG += X11 link_pkgconfig debug
1221 PKGCONFIG += dbusmenu-qt5 gtk+-2.0
1222 DESTDIR = ./
1223
1224 HEADERS += \
1225- appmenuplatformmenubar.h
1226+ appmenuplatformmenuitem.h \
1227+ appmenuplatformmenu.h \
1228+ appmenuplatformmenubar.h \
1229+ appmenuplatformsystemtrayicon.h \
1230+ dbusstructures.h \
1231+ iconcache.h
1232
1233 SOURCES += \
1234- appmenuplatformmenubar.cpp
1235-
1236+ appmenuplatformmenuitem.cpp \
1237+ appmenuplatformmenu.cpp \
1238+ appmenuplatformmenubar.cpp \
1239+ appmenuplatformsystemtrayicon.cpp \
1240+ dbusstructures.cpp \
1241+ iconcache.cpp

Subscribers

People subscribed via source and target branches