1 /* This file is part of the dbusmenu-qt library
2 Copyright 2010 Canonical
3 Author: Aurelien Gateau <aurelien.gateau@canonical.com>
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License (LGPL) as published by the Free Software Foundation;
8 either version 2 of the License, or (at your option) any later
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Library General Public License for more details.
16 You should have received a copy of the GNU Library General Public License
17 along with this library; see the file COPYING.LIB. If not, write to
18 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 Boston, MA 02110-1301, USA.
21 #include "dbusmenuexporterdbus_p.h"
24 #include <QDBusMessage>
30 #include "dbusmenuadaptor.h"
31 #include "dbusmenuexporterprivate_p.h"
32 #include "dbusmenushortcut_p.h"
35 static const char *DBUSMENU_INTERFACE = "com.canonical.dbusmenu";
36 static const char *FDO_PROPERTIES_INTERFACE = "org.freedesktop.DBus.Properties";
38 DBusMenuExporterDBus::DBusMenuExporterDBus(DBusMenuExporter *exporter)
40 , m_exporter(exporter)
43 new DbusmenuAdaptor(this);
46 uint DBusMenuExporterDBus::GetLayout(int parentId, int recursionDepth, const QStringList &propertyNames, DBusMenuLayoutItem &item)
48 QMenu *menu = m_exporter->d->menuForId(parentId);
49 DMRETURN_VALUE_IF_FAIL(menu, 0);
51 // Process pending actions, we need them *now*
52 QMetaObject::invokeMethod(m_exporter, "doUpdateActions");
53 m_exporter->d->fillLayoutItem(&item, menu, parentId, recursionDepth, propertyNames);
55 return m_exporter->d->m_revision;
58 void DBusMenuExporterDBus::Event(int id, const QString &eventType, const QDBusVariant &/*data*/, uint /*timestamp*/)
60 if (eventType == "clicked") {
61 QAction *action = m_exporter->d->m_actionForId.value(id);
65 // dbusmenu-glib seems to ignore the Q_NOREPLY and blocks when calling
66 // Event(), so trigger the action asynchronously
67 QMetaObject::invokeMethod(action, "trigger", Qt::QueuedConnection);
68 } else if (eventType == "hovered") {
69 QMenu *menu = m_exporter->d->menuForId(id);
71 QMetaObject::invokeMethod(menu, "aboutToShow");
76 QDBusVariant DBusMenuExporterDBus::GetProperty(int id, const QString &name)
78 QAction *action = m_exporter->d->m_actionForId.value(id);
79 DMRETURN_VALUE_IF_FAIL(action, QDBusVariant());
80 return QDBusVariant(m_exporter->d->m_actionProperties.value(action).value(name));
83 QVariantMap DBusMenuExporterDBus::getProperties(int id, const QStringList &names) const
87 map.insert("children-display", "submenu");
90 QAction *action = m_exporter->d->m_actionForId.value(id);
91 DMRETURN_VALUE_IF_FAIL(action, QVariantMap());
92 QVariantMap all = m_exporter->d->m_actionProperties.value(action);
93 if (names.isEmpty()) {
97 Q_FOREACH(const QString &name, names) {
98 QVariant value = all.value(name);
99 if (value.isValid()) {
100 map.insert(name, value);
107 DBusMenuItemList DBusMenuExporterDBus::GetGroupProperties(const QList<int> &ids, const QStringList &names)
109 DBusMenuItemList list;
110 Q_FOREACH(int id, ids) {
113 item.properties = getProperties(item.id, names);
120 * An helper class for ::AboutToShow, which sets mChanged to true if a menu
121 * changes after its aboutToShow() signal has been emitted.
123 class ActionEventFilter: public QObject
132 bool eventFilter(QObject *object, QEvent *event)
134 switch (event->type()) {
135 case QEvent::ActionAdded:
136 case QEvent::ActionChanged:
137 case QEvent::ActionRemoved:
139 // We noticed a change, no need to filter anymore
140 object->removeEventFilter(this);
149 bool DBusMenuExporterDBus::AboutToShow(int id)
151 QMenu *menu = m_exporter->d->menuForId(id);
152 DMRETURN_VALUE_IF_FAIL(menu, false);
154 ActionEventFilter filter;
155 menu->installEventFilter(&filter);
156 QMetaObject::invokeMethod(menu, "aboutToShow");
157 return filter.mChanged;
160 void DBusMenuExporterDBus::setStatus(const QString& status)
162 if (m_status == status) {
168 map.insert("Status", QVariant(status));
170 QDBusMessage msg = QDBusMessage::createSignal(m_exporter->d->m_objectPath, FDO_PROPERTIES_INTERFACE, "PropertiesChanged");
171 QVariantList args = QVariantList()
172 << DBUSMENU_INTERFACE
174 << QStringList() // New properties: none
176 msg.setArguments(args);
177 QDBusConnection::sessionBus().send(msg);
180 QString DBusMenuExporterDBus::status() const
186 #include "moc_dbusmenuexporterdbus_p.cpp"