on ccb786e help sign in
unity8/plugins/Unity/Launcher/dbusinterface.cpp
208 lines 7.2 kB history raw
1/*
2 * Copyright 2014 Canonical Ltd.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License as published by
6 * the Free Software Foundation; version 3.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authors:
17 * Michael Zanetti <michael.zanetti@canonical.com>
18 */
20#include "dbusinterface.h"
21#include "launchermodel.h"
22#include "launcheritem.h"
24#include <QDBusArgument>
25#include <QDBusConnection>
26#include <QDBusMessage>
27#include <QDebug>
29DBusInterface::DBusInterface(LauncherModel *parent):
30 UnityDBusVirtualObject("/com/canonical/Unity/Launcher", "com.canonical.Unity.Launcher", true, parent),
31 m_launcherModel(parent)
35DBusInterface::~DBusInterface()
39QString DBusInterface::introspect(const QString &path) const
41 /* This case we should just list the nodes */
42 if (path == "/com/canonical/Unity/Launcher/" || path == "/com/canonical/Unity/Launcher") {
43 QString nodes;
45 // Add Refresh to introspect
46 nodes = "<interface name=\"com.canonical.Unity.Launcher\">"
47 "<method name=\"Refresh\"/>"
48 "</interface>";
50 // Add dynamic properties for launcher emblems
51 for (int i = 0; i < m_launcherModel->rowCount(); i++) {
52 nodes.append("<node name=\"");
53 nodes.append(encodeAppId(m_launcherModel->get(i)->appId()));
54 nodes.append("\"/>\n");
55 }
56 return nodes;
57 }
59 /* Should not happen, but let's handle it */
60 if (!path.startsWith("/com/canonical/Unity/Launcher")) {
61 return "";
62 }
64 /* Now we should be looking at a node */
65 QString nodeiface =
66 "<interface name=\"com.canonical.Unity.Launcher.Item\">"
67 "<property name=\"count\" type=\"i\" access=\"readwrite\" />"
68 "<property name=\"countVisible\" type=\"b\" access=\"readwrite\" />"
69 "<property name=\"alerting\" type=\"b\" access=\"readwrite\" />"
70 "</interface>";
71 return nodeiface;
75QString DBusInterface::decodeAppId(const QString& path)
77 QByteArray bytes = path.toUtf8();
78 QByteArray decoded;
80 for (int i = 0; i < bytes.size(); ++i) {
81 char chr = bytes.at(i);
83 if (chr == '_') {
84 QString number;
85 number.append(bytes.at(i+1));
86 number.append(bytes.at(i+2));
88 bool okay;
89 char newchar = number.toUInt(&okay, 16);
90 if (okay)
91 decoded.append(newchar);
93 i += 2;
94 } else {
95 decoded.append(chr);
96 }
97 }
99 return QString::fromUtf8(decoded);
102QString DBusInterface::encodeAppId(const QString& appId)
104 QByteArray bytes = appId.toUtf8();
105 QString encoded;
107 for (int i = 0; i < bytes.size(); ++i) {
108 uchar chr = bytes.at(i);
110 if ((chr >= 'a' && chr <= 'z') ||
111 (chr >= 'A' && chr <= 'Z') ||
112 (chr >= '0' && chr <= '9'&& i != 0)) {
113 encoded.append(chr);
114 } else {
115 QString hexval = QString("_%1").arg(chr, 2, 16, QChar('0'));
116 encoded.append(hexval.toUpper());
117 }
118 }
120 return encoded;
123bool DBusInterface::handleMessage(const QDBusMessage& message, const QDBusConnection& connection)
125 /* Check to make sure we're getting properties on our interface */
126 if (message.type() != QDBusMessage::MessageType::MethodCallMessage) {
127 return false;
128 }
130 // First handle methods of the Launcher interface
131 if (message.interface() == "com.canonical.Unity.Launcher") {
132 if (message.member() == "Refresh") {
133 QDBusMessage reply = message.createReply();
134 Q_EMIT refreshCalled();
135 return connection.send(reply);
136 }
137 }
139 // Now handle dynamic properties (for launcher emblems)
140 if (message.interface() != "org.freedesktop.DBus.Properties") {
141 return false;
142 }
144 if (message.member() != "GetAll" && message.arguments()[0].toString() != "com.canonical.Unity.Launcher.Item") {
145 return false;
146 }
148 /* Break down the path to just the app id */
149 QString pathtemp = message.path();
150 if (!pathtemp.startsWith("/com/canonical/Unity/Launcher/")) {
151 return false;
152 }
153 pathtemp.remove("/com/canonical/Unity/Launcher/");
154 if (pathtemp.indexOf('/') >= 0) {
155 return false;
156 }
158 /* Find ourselves an appid */
159 QString appid = decodeAppId(pathtemp);
160 int index = m_launcherModel->findApplication(appid);
161 LauncherItem *item = static_cast<LauncherItem*>(m_launcherModel->get(index));
163 QVariantList retval;
164 if (message.member() == "Get") {
165 if (!item) {
166 return false;
167 }
168 if (message.arguments()[1].toString() == "count") {
169 retval.append(QVariant::fromValue(QDBusVariant(item->count())));
170 } else if (message.arguments()[1].toString() == "countVisible") {
171 retval.append(QVariant::fromValue(QDBusVariant(item->countVisible())));
172 } else if (message.arguments()[1].toString() == "alerting") {
173 retval.append(QVariant::fromValue(QDBusVariant(item->alerting())));
174 }
175 } else if (message.member() == "Set") {
176 if (message.arguments()[1].toString() == "count") {
177 int newCount = message.arguments()[2].value<QDBusVariant>().variant().toInt();
178 if (!item || newCount != item->count()) {
179 Q_EMIT countChanged(appid, newCount);
180 notifyPropertyChanged("com.canonical.Unity.Launcher.Item", encodeAppId(appid), "count", QVariant(newCount));
181 }
182 } else if (message.arguments()[1].toString() == "countVisible") {
183 bool newVisible = message.arguments()[2].value<QDBusVariant>().variant().toBool();
184 if (!item || newVisible != item->countVisible()) {
185 Q_EMIT countVisibleChanged(appid, newVisible);
186 notifyPropertyChanged("com.canonical.Unity.Launcher.Item", encodeAppId(appid), "countVisible", newVisible);
187 }
188 } else if (message.arguments()[1].toString() == "alerting") {
189 bool newAlerting = message.arguments()[2].value<QDBusVariant>().variant().toBool();
190 if (!item || newAlerting != item->alerting()) {
191 Q_EMIT alertingChanged(appid, newAlerting);
192 notifyPropertyChanged("com.canonical.Unity.Launcher.Item", encodeAppId(appid), "alerting", newAlerting);
193 }
194 }
195 } else if (message.member() == "GetAll") {
196 if (item) {
197 QVariantMap all;
198 all.insert("count", item->count());
199 all.insert("countVisible", item->countVisible());
200 retval.append(all);
201 }
202 } else {
203 return false;
204 }
206 QDBusMessage reply = message.createReply(retval);
207 return connection.send(reply);