on 5dbd13d help sign in
unity8/plugins/Unity/Launcher/dbusinterface.cpp
214 lines 7.0 kB history raw
1#include "dbusinterface.h"
2#include "launchermodel.h"
3#include "launcheritem.h"
5#include <QDBusArgument>
6#include <QDBusConnection>
7#include <QDBusMessage>
8#include <QDebug>
10DBusInterface::DBusInterface(LauncherModel *parent):
11 QDBusVirtualObject(parent),
12 m_launcherModel(parent)
14 /* Set up ourselves on DBus */
15 QDBusConnection con = QDBusConnection::sessionBus();
16 if (!con.registerService("com.canonical.Unity.Launcher2")) {
17 qWarning() << "Unable to register launcher name";
18 }
19 if (!con.registerVirtualObject("/com/canonical/Unity/Launcher2", this, QDBusConnection::VirtualObjectRegisterOption::SubPath)) {
20 qWarning() << "Unable to register launcher object";
21 }
24DBusInterface::~DBusInterface()
26 /* Remove oursevles from DBus */
27 QDBusConnection con = QDBusConnection::sessionBus();
28 con.unregisterService("com.canonical.Unity.Launcher2");
29 con.unregisterObject("/com/canonical/Unity/Launcher2");
32QString DBusInterface::introspect(const QString &path) const
34 qDebug() << "introspecting" << path;
35 /* This case we should just list the nodes */
36 if (path == "/com/canonical/Unity/Launcher2/" || path == "/com/canonical/Unity/Launcher2") {
37 QString nodes;
39 // Add Refresh to introspect
40 nodes = "<interface name=\"com.canonical.Unity.Launcher2\">"
41 "<method name=\"Refresh\"/>"
42 "</interface>";
44 // Add dynamic properties for launcher emblems
45 for (int i = 0; i < m_launcherModel->rowCount(); i++) {
46 nodes.append("<node name=\"");
47 nodes.append(encodeAppId(m_launcherModel->get(i)->appId()));
48 nodes.append("\"/>\n");
49 }
50 return nodes;
51 }
53 /* Should not happen, but let's handle it */
54 if (!path.startsWith("/com/canonical/Unity/Launcher2")) {
55 return "";
56 }
58 /* Now we should be looking at a node */
59 QString nodeiface =
60 "<interface name=\"com.canonical.Unity.Launcher2.Item\">"
61 "<property name=\"count\" type=\"i\" access=\"readwrite\" />"
62 "<property name=\"countVisible\" type=\"b\" access=\"readwrite\" />"
63 "</interface>";
64 return nodeiface;
68QString DBusInterface::decodeAppId(const QString& path)
70 QByteArray bytes = path.toUtf8();
71 QByteArray decoded;
73 for (int i = 0; i < bytes.size(); ++i) {
74 char chr = bytes.at(i);
76 if (chr == '_') {
77 QString number;
78 number.append(bytes.at(i+1));
79 number.append(bytes.at(i+2));
81 bool okay;
82 char newchar = number.toUInt(&okay, 16);
83 if (okay)
84 decoded.append(newchar);
86 i += 2;
87 } else {
88 decoded.append(chr);
89 }
90 }
92 return QString::fromUtf8(decoded);
95QString DBusInterface::encodeAppId(const QString& appId)
97 QByteArray bytes = appId.toUtf8();
98 QString encoded;
100 for (int i = 0; i < bytes.size(); ++i) {
101 uchar chr = bytes.at(i);
103 if ((chr >= 'a' && chr <= 'z') ||
104 (chr >= 'A' && chr <= 'Z') ||
105 (chr >= '0' && chr <= '9'&& i != 0)) {
106 encoded.append(chr);
107 } else {
108 QString hexval = QString("_%1").arg(chr, 2, 16, QChar('0'));
109 encoded.append(hexval.toUpper());
110 }
111 }
113 return encoded;
116bool DBusInterface::handleMessage(const QDBusMessage& message, const QDBusConnection& connection)
118 /* Check to make sure we're getting properties on our interface */
119 if (message.type() != QDBusMessage::MessageType::MethodCallMessage) {
120 return false;
121 }
123 // First handle methods of the Launcher interface
124 if (message.interface() == "com.canonical.Unity.Launcher") {
125 if (message.member() == "Refresh") {
126 QDBusMessage reply = message.createReply();
127 Q_EMIT refreshCalled();
128 return connection.send(reply);
129 }
130 }
132 // Now handle dynamic properties (for launcher emblems)
133 if (message.interface() != "org.freedesktop.DBus.Properties") {
134 return false;
135 }
137 if (message.member() != "GetAll" && message.arguments()[0].toString() != "com.canonical.Unity.Launcher2.Item") {
138 return false;
139 }
141 /* Break down the path to just the app id */
142 QString pathtemp = message.path();
143 if (!pathtemp.startsWith("/com/canonical/Unity/Launcher2/")) {
144 return false;
145 }
146 pathtemp.remove("/com/canonical/Unity/Launcher2/");
147 if (pathtemp.indexOf('/') >= 0) {
148 return false;
149 }
151 /* Find ourselves an appid */
152 QString appid = decodeAppId(pathtemp);
153 int index = m_launcherModel->findApplication(appid);
154 LauncherItem *item = static_cast<LauncherItem*>(m_launcherModel->get(index));
156 QVariantList retval;
157 if (message.member() == "Get") {
158 if (!item) {
159 return false;
160 }
161 if (message.arguments()[1].toString() == "count") {
162 retval.append(QVariant::fromValue(QDBusVariant(item->count())));
163 } else if (message.arguments()[1].toString() == "countVisible") {
164 retval.append(QVariant::fromValue(QDBusVariant(item->countVisible())));
165 }
166 } else if (message.member() == "Set") {
167 if (message.arguments()[1].toString() == "count") {
168 int newCount = message.arguments()[2].value<QDBusVariant>().variant().toInt();
169 if (!item || newCount != item->count()) {
170 Q_EMIT countChanged(appid, newCount);
171 emitPropChangedDbus(appid, "count", QVariant(newCount));
172 }
173 } else if (message.arguments()[1].toString() == "countVisible") {
174 bool newVisible = message.arguments()[2].value<QDBusVariant>().variant().toBool();
175 if (!item || newVisible != item->countVisible()) {
176 Q_EMIT countVisibleChanged(appid, newVisible);
177 emitPropChangedDbus(appid, "countVisible", newVisible);
178 }
179 }
180 } else if (message.member() == "GetAll") {
181 if (item) {
182 QVariantMap all;
183 all.insert("count", item->count());
184 all.insert("countVisible", item->count());
185 retval.append(all);
186 }
187 } else {
188 return false;
189 }
191 QDBusMessage reply = message.createReply(retval);
192 return connection.send(reply);
195void DBusInterface::emitPropChangedDbus(const QString& appId, const QString& property, const QVariant &value)
197 QString path("/com/canonical/Unity/Launcher2/");
198 path.append(encodeAppId(appId));
200 QDBusMessage message = QDBusMessage::createSignal(path, "org.freedesktop.DBus.Properties", "PropertiesChanged");
202 QList<QVariant> arguments;
203 QVariantHash changedprops;
204 changedprops[property] = QVariant::fromValue(QDBusVariant(value));
205 QVariantList deletedprops;
207 arguments.append(changedprops);
208 arguments.append(deletedprops);
210 message.setArguments(arguments);
212 QDBusConnection con = QDBusConnection::sessionBus();
213 con.send(message);