/*
* Copyright 2014 Canonical Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; version 3.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see .
*
* Authors:
* Michael Zanetti
*/
#include "dbusinterface.h"
#include "launchermodel.h"
#include "launcheritem.h"
#include
#include
#include
#include
DBusInterface::DBusInterface(LauncherModel *parent):
UnityDBusVirtualObject(QStringLiteral("/com/canonical/Unity/Launcher"), QStringLiteral("com.canonical.Unity.Launcher"), true, parent),
m_launcherModel(parent)
{
}
QString DBusInterface::introspect(const QString &path) const
{
/* This case we should just list the nodes */
if (path == QLatin1String("/com/canonical/Unity/Launcher/") || path == QLatin1String("/com/canonical/Unity/Launcher")) {
QString nodes;
// Add Refresh to introspect
nodes = QStringLiteral(""
""
"");
// Add dynamic properties for launcher emblems
for (int i = 0; i < m_launcherModel->rowCount(); i++) {
nodes.append("get(i)->appId()));
nodes.append("\"/>\n");
}
return nodes;
}
/* Should not happen, but let's handle it */
if (!path.startsWith(QLatin1String("/com/canonical/Unity/Launcher"))) {
return QLatin1String("");
}
/* Now we should be looking at a node */
QString nodeiface =
QStringLiteral(""
""
""
""
""
"");
return nodeiface;
}
QString DBusInterface::decodeAppId(const QString& path)
{
QByteArray bytes = path.toUtf8();
QByteArray decoded;
for (int i = 0; i < bytes.size(); ++i) {
char chr = bytes.at(i);
if (chr == '_') {
QString number;
number.append(bytes.at(i+1));
number.append(bytes.at(i+2));
bool okay;
char newchar = number.toUInt(&okay, 16);
if (okay)
decoded.append(newchar);
i += 2;
} else {
decoded.append(chr);
}
}
return QString::fromUtf8(decoded);
}
QString DBusInterface::encodeAppId(const QString& appId)
{
QByteArray bytes = appId.toUtf8();
QString encoded;
for (int i = 0; i < bytes.size(); ++i) {
uchar chr = bytes.at(i);
if ((chr >= 'a' && chr <= 'z') ||
(chr >= 'A' && chr <= 'Z') ||
(chr >= '0' && chr <= '9'&& i != 0)) {
encoded.append(chr);
} else {
QString hexval = QStringLiteral("_%1").arg(chr, 2, 16, QChar('0'));
encoded.append(hexval.toUpper());
}
}
return encoded;
}
bool DBusInterface::handleMessage(const QDBusMessage& message, const QDBusConnection& connection)
{
/* Check to make sure we're getting properties on our interface */
if (message.type() != QDBusMessage::MessageType::MethodCallMessage) {
return false;
}
/* Break down the path to just the app id */
bool validpath = true;
QString pathtemp = message.path();
if (!pathtemp.startsWith(QLatin1String("/com/canonical/Unity/Launcher/"))) {
validpath = false;
}
pathtemp.remove(QStringLiteral("/com/canonical/Unity/Launcher/"));
if (pathtemp.indexOf('/') >= 0) {
validpath = false;
}
/* Find ourselves an appid */
QString appid = decodeAppId(pathtemp);
// First handle methods of the Launcher interface
if (message.interface() == QLatin1String("com.canonical.Unity.Launcher")) {
if (message.member() == QLatin1String("Refresh")) {
QDBusMessage reply = message.createReply();
Q_EMIT refreshCalled();
return connection.send(reply);
}
} else if (message.interface() == QLatin1String("com.canonical.Unity.Launcher.Item")) {
// Handle methods of the Launcher-Item interface
if (message.member() == QLatin1String("Alert") && validpath) {
QDBusMessage reply = message.createReply();
Q_EMIT alertCalled(appid);
return connection.send(reply);
}
}
// Now handle dynamic properties (for launcher emblems)
if (message.interface() != QLatin1String("org.freedesktop.DBus.Properties")) {
return false;
}
const QList messageArguments = message.arguments();
if (message.member() == QLatin1String("Get") && (messageArguments.count() != 2 || messageArguments[0].toString() != QLatin1String("com.canonical.Unity.Launcher.Item"))) {
return false;
}
if (message.member() == QLatin1String("Set") && (messageArguments.count() != 3 || messageArguments[0].toString() != QLatin1String("com.canonical.Unity.Launcher.Item"))) {
return false;
}
if (!validpath) {
return false;
}
int index = m_launcherModel->findApplication(appid);
LauncherItem *item = static_cast(m_launcherModel->get(index));
QVariantList retval;
if (message.member() == QLatin1String("Get")) {
QString cachedString = messageArguments[1].toString();
if (!item) {
return false;
}
if (cachedString == QLatin1String("count")) {
retval.append(QVariant::fromValue(QDBusVariant(item->count())));
} else if (cachedString == QLatin1String("countVisible")) {
retval.append(QVariant::fromValue(QDBusVariant(item->countVisible())));
} else if (cachedString == QLatin1String("progress")) {
retval.append(QVariant::fromValue(QDBusVariant(item->progress())));
}
} else if (message.member() == QLatin1String("Set")) {
QString cachedString = messageArguments[1].toString();
if (cachedString == QLatin1String("count")) {
int newCount = messageArguments[2].value().variant().toInt();
if (!item || newCount != item->count()) {
Q_EMIT countChanged(appid, newCount);
notifyPropertyChanged(QStringLiteral("com.canonical.Unity.Launcher.Item"), encodeAppId(appid), QStringLiteral("count"), QVariant(newCount));
}
} else if (cachedString == QLatin1String("countVisible")) {
bool newVisible = messageArguments[2].value().variant().toBool();
if (!item || newVisible != item->countVisible()) {
Q_EMIT countVisibleChanged(appid, newVisible);
notifyPropertyChanged(QStringLiteral("com.canonical.Unity.Launcher.Item"), encodeAppId(appid), QStringLiteral("countVisible"), newVisible);
}
} else if (cachedString == QLatin1String("progress")) {
int newProgress = messageArguments[2].value().variant().toInt();
if (!item || newProgress != item->progress()) {
Q_EMIT progressChanged(appid, newProgress);
notifyPropertyChanged(QStringLiteral("com.canonical.Unity.Launcher.Item"), encodeAppId(appid), QStringLiteral("progress"), QVariant(newProgress));
}
}
} else if (message.member() == QLatin1String("GetAll")) {
if (item) {
QVariantMap all;
all.insert(QStringLiteral("count"), item->count());
all.insert(QStringLiteral("countVisible"), item->countVisible());
all.insert(QStringLiteral("progress"), item->progress());
retval.append(all);
}
} else {
return false;
}
QDBusMessage reply = message.createReply(retval);
return connection.send(reply);
}