[SCM] kdeconnect packaging branch, master, updated. debian/0.9g-1-1183-g9d69498
Maximiliano Curia
maxy at moszumanska.debian.org
Fri Oct 14 14:29:32 UTC 2016
Gitweb-URL: http://git.debian.org/?p=pkg-kde/kde-extras/kdeconnect.git;a=commitdiff;h=4b5bde4
The following commit has been merged in the master branch:
commit 4b5bde48589e5e45b57d97c0a28da6d0e918a8e7
Author: Holger Kaelberer <holger.k at elberer.de>
Date: Thu Jan 7 17:37:35 2016 +0100
notifications: synchronize icons if possible and requested
Configurably attach icons as payload to notification packages. By
design and due to restrictions on mobile devices *only* png is sent.
As KIconLoader preferably returns svg icons from iconPath() we fall
back to loading from "hicolor" using KIconTheme directly. Otherwise
*many* icons are dropped because of svg format.
This also improves slightly the test-case to use a tweaked TestDevice
to allow for inspecting sent NetworkPackage-s.
REVIEW: 126666
---
plugins/notifications/CMakeLists.txt | 3 +-
plugins/notifications/notifications_config.cpp | 6 +
plugins/notifications/notifications_config.ui | 16 ++
plugins/notifications/notificationslistener.cpp | 27 +++-
tests/CMakeLists.txt | 4 +-
tests/testnotificationlistener.cpp | 199 +++++++++++++++++++-----
6 files changed, 213 insertions(+), 42 deletions(-)
diff --git a/plugins/notifications/CMakeLists.txt b/plugins/notifications/CMakeLists.txt
index 448be94..d74cca6 100644
--- a/plugins/notifications/CMakeLists.txt
+++ b/plugins/notifications/CMakeLists.txt
@@ -1,4 +1,4 @@
-find_package(KF5 REQUIRED COMPONENTS Notifications KCMUtils I18n)
+find_package(KF5 REQUIRED COMPONENTS Notifications KCMUtils I18n IconThemes)
set(kdeconnect_notifications_SRCS
notification.cpp
@@ -15,6 +15,7 @@ target_link_libraries(kdeconnect_notifications
Qt5::DBus
KF5::Notifications
KF5::I18n
+ KF5::IconThemes
)
#######################################
diff --git a/plugins/notifications/notifications_config.cpp b/plugins/notifications/notifications_config.cpp
index 5086d9f..d9532a7 100644
--- a/plugins/notifications/notifications_config.cpp
+++ b/plugins/notifications/notifications_config.cpp
@@ -51,6 +51,7 @@ NotificationsConfig::NotificationsConfig(QWidget *parent, const QVariantList& ar
connect(m_ui->check_persistent, SIGNAL(toggled(bool)), this, SLOT(changed()));
connect(m_ui->spin_urgency, SIGNAL(editingFinished()), this, SLOT(changed()));
connect(m_ui->check_body, SIGNAL(toggled(bool)), this, SLOT(changed()));
+ connect(m_ui->check_icons, SIGNAL(toggled(bool)), this, SLOT(changed()));
connect(appModel, SIGNAL(applicationsChanged()), this, SLOT(changed()));
@@ -67,6 +68,8 @@ void NotificationsConfig::defaults()
KCModule::defaults();
m_ui->check_persistent->setChecked(false);
m_ui->spin_urgency->setValue(0);
+ m_ui->check_body->setChecked(true);
+ m_ui->check_icons->setChecked(true);
Q_EMIT changed(true);
}
@@ -89,6 +92,8 @@ void NotificationsConfig::load()
m_ui->check_persistent->setChecked(persistent);
bool body = config()->get("generalIncludeBody", true);
m_ui->check_body->setChecked(body);
+ bool icons = config()->get("generalSynchronizeIcons", true);
+ m_ui->check_icons->setChecked(icons);
int urgency = config()->get("generalUrgency", 0);
m_ui->spin_urgency->setValue(urgency);
@@ -100,6 +105,7 @@ void NotificationsConfig::save()
{
config()->set("generalPersistent", m_ui->check_persistent->isChecked());
config()->set("generalIncludeBody", m_ui->check_body->isChecked());
+ config()->set("generalSynchronizeIcons", m_ui->check_icons->isChecked());
config()->set("generalUrgency", m_ui->spin_urgency->value());
QVariantList list;
diff --git a/plugins/notifications/notifications_config.ui b/plugins/notifications/notifications_config.ui
index 3f3d8a4..83b26cc 100644
--- a/plugins/notifications/notifications_config.ui
+++ b/plugins/notifications/notifications_config.ui
@@ -81,6 +81,22 @@
</widget>
</item>
<item>
+ <widget class="QCheckBox" name="check_icons">
+ <property name="font">
+ <font>
+ <weight>50</weight>
+ <bold>false</bold>
+ </font>
+ </property>
+ <property name="toolTip">
+ <string>Synchronize icons of notifying applications if possible?</string>
+ </property>
+ <property name="text">
+ <string>Synchronize icons</string>
+ </property>
+ </widget>
+ </item>
+ <item>
<widget class="QWidget" name="horizontalWidget" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
diff --git a/plugins/notifications/notificationslistener.cpp b/plugins/notifications/notificationslistener.cpp
index 22d50fb..d21f3d7 100644
--- a/plugins/notifications/notificationslistener.cpp
+++ b/plugins/notifications/notificationslistener.cpp
@@ -23,6 +23,9 @@
#include <QtDebug>
#include <QLoggingCategory>
+#include <kiconloader.h>
+#include <kicontheme.h>
+
#include <core/device.h>
#include <core/kdeconnectplugin.h>
@@ -143,7 +146,7 @@ uint NotificationsListener::Notify(const QString &appName, uint replacesId,
app.blacklistExpression.match(ticker).hasMatch())
return 0;
- //qCDebug(KDECONNECT_PLUGIN_NOTIFICATION) << "Sending notification from" << appName << ":" <<ticker;
+ //qCDebug(KDECONNECT_PLUGIN_NOTIFICATION) << "Sending notification from" << appName << ":" <<ticker << "; appIcon=" << appIcon;
NetworkPackage np(PACKAGE_TYPE_NOTIFICATION);
np.set("id", QString::number(replacesId > 0 ? replacesId : ++id));
np.set("appName", appName);
@@ -152,6 +155,28 @@ uint NotificationsListener::Notify(const QString &appName, uint replacesId,
// timeout == 0, for other notifications
// clearability is pointless
+ if (!appIcon.isEmpty() && mPlugin->config()->get("generalSynchronizeIcons", true)) {
+ int size = KIconLoader::SizeEnormous; // use big size to allow for good
+ // quality on High-DPI mobile devices
+ QString iconPath = KIconLoader::global()->iconPath(appIcon, -size, true);
+ if (!iconPath.isEmpty()) {
+ if (!iconPath.endsWith(QLatin1String(".png")) &&
+ KIconLoader::global()->theme()->name() != QLatin1String("hicolor")) {
+ // try falling back to hicolor theme:
+ KIconTheme hicolor(QStringLiteral("hicolor"));
+ if (hicolor.isValid()) {
+ iconPath = hicolor.iconPath(appIcon + ".png", size, KIconLoader::MatchBest);
+ //qCDebug(KDECONNECT_PLUGIN_NOTIFICATION) << "Found non-png icon in default theme trying fallback to hicolor:" << iconPath;
+ }
+ }
+ if (iconPath.endsWith(QLatin1String(".png"))) {
+ //qCDebug(KDECONNECT_PLUGIN_NOTIFICATION) << "Appending icon " << iconPath;
+ QSharedPointer<QIODevice> iconFile(new QFile(iconPath));
+ np.setPayload(iconFile, iconFile->size());
+ }
+ }
+ }
+
mPlugin->sendPackage(np);
return (replacesId > 0 ? replacesId : id);
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 66aeb5f..812b4a3 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -1,5 +1,5 @@
find_package(Qt5 REQUIRED COMPONENTS Test)
-find_package(KF5 REQUIRED COMPONENTS KIO Notifications)
+find_package(KF5 REQUIRED COMPONENTS KIO Notifications IconThemes)
include_directories(
${KDEConnectCore_BINARY_DIR}
@@ -26,4 +26,4 @@ ecm_add_test(testnotificationlistener.cpp
../plugins/notifications/notifyingapplication.cpp
../plugins/notifications/notificationsdbusinterface.cpp
TEST_NAME testnotificationlistener
- LINK_LIBRARIES ${kdeconnect_libraries} Qt5::DBus KF5::Notifications)
+ LINK_LIBRARIES ${kdeconnect_libraries} Qt5::DBus KF5::Notifications KF5::IconThemes)
diff --git a/tests/testnotificationlistener.cpp b/tests/testnotificationlistener.cpp
index e1faa1c..b43a7d3 100644
--- a/tests/testnotificationlistener.cpp
+++ b/tests/testnotificationlistener.cpp
@@ -25,6 +25,8 @@
#include <QTemporaryFile>
#include <QStandardPaths>
+#include <kiconloader.h>
+
#include "core/daemon.h"
#include "core/device.h"
#include "core/kdeconnectplugin.h"
@@ -63,6 +65,52 @@ public:
}
};
+// Tweaked Device for testing:
+class TestDevice: public Device
+{
+ Q_OBJECT
+private:
+ int sentPackages;
+ NetworkPackage *lastPackage;
+
+public:
+ explicit TestDevice(QObject* parent, const QString& id)
+ : Device (parent, id)
+ , sentPackages(0)
+ , lastPackage(nullptr)
+ {}
+
+ virtual ~TestDevice()
+ {
+ delete lastPackage;
+ }
+
+ int getSentPackages() const
+ {
+ return sentPackages;
+ }
+
+ const NetworkPackage* getLastPackage() const
+ {
+ return lastPackage;
+ }
+
+public Q_SLOTS:
+ virtual bool sendPackage(NetworkPackage& np) override
+ {
+ ++sentPackages;
+ // copy package manually to allow for inspection (can't use copy-constructor)
+ delete lastPackage;
+ lastPackage = new NetworkPackage(np.type());
+ Q_ASSERT(lastPackage);
+ for (QVariantMap::ConstIterator iter = np.body().constBegin();
+ iter != np.body().constEnd(); iter++)
+ lastPackage->set(iter.key(), iter.value());
+ lastPackage->setPayload(np.payload(), np.payloadSize());
+ return true;
+ }
+};
+
// Tweaked NotificationsListener for testing:
class TestedNotificationsListener: public NotificationsListener
{
@@ -112,7 +160,10 @@ void TestNotificationListener::testNotify()
//
QString dId("testid");
- Device *d = new Device(nullptr, dId); // not setting any parent or we will double free the dbusInterface
+ TestDevice *d = new TestDevice(nullptr, dId); // not setting any parent or we will double free the dbusInterface
+
+ int proxiedNotifications = 0;
+ QCOMPARE(proxiedNotifications, d->getSentPackages());
plugin = new TestNotificationsPlugin(this,
QVariantList({ QVariant::fromValue<Device*>(d),
"notifications_plugin",
@@ -144,97 +195,169 @@ void TestNotificationListener::testNotify()
uint replacesId = 99;
uint retId;
+ QString appName("some-appName");
+ QString body("some-body");
+ QString icon("some-icon");
+ QString summary("some-summary");
// regular Notify call that is synchronized ...
- retId = listener->Notify("testApp", replacesId, "some-icon", "summary", "body", {}, {{}}, 0);
+ retId = listener->Notify(appName, replacesId, icon, summary, body, {}, {{}}, 0);
// ... should return replacesId,
QCOMPARE(retId, replacesId);
+ // ... have triggered sending a package
+ QCOMPARE(++proxiedNotifications, d->getSentPackages());
+ // ... with our properties,
+ QCOMPARE(d->getLastPackage()->get<uint>("id"), replacesId);
+ QCOMPARE(d->getLastPackage()->get<QString>("appName"), appName);
+ QCOMPARE(d->getLastPackage()->get<QString>("ticker"), summary + ": " + body);
+ QCOMPARE(d->getLastPackage()->get<bool>("isClearable"), true);
+ QCOMPARE(d->getLastPackage()->hasPayload(), false);
+
// ... and create a new application internally that is initialized correctly:
QCOMPARE(listener->getApplications().count(), 1);
- QVERIFY(listener->getApplications().contains("testApp"));
- QVERIFY(listener->getApplications()["testApp"].active);
- QCOMPARE(listener->getApplications()["testApp"].name, QStringLiteral("testApp"));
- QVERIFY(listener->getApplications()["testApp"].blacklistExpression.pattern().isEmpty());
- QCOMPARE(listener->getApplications()["testApp"].name, QStringLiteral("testApp"));
- QCOMPARE(listener->getApplications()["testApp"].icon, QStringLiteral("some-icon"));
+ QVERIFY(listener->getApplications().contains(appName));
+ QVERIFY(listener->getApplications()[appName].active);
+ QCOMPARE(listener->getApplications()[appName].name, appName);
+ QVERIFY(listener->getApplications()[appName].blacklistExpression.pattern().isEmpty());
+ QCOMPARE(listener->getApplications()[appName].name, appName);
+ QCOMPARE(listener->getApplications()[appName].icon, icon);
// another one, with other timeout and urgency values:
- retId = listener->Notify("testApp2", replacesId+1, "some-icon2", "summary2", "body2", {}, {{"urgency", 2}}, 10);
+ QString appName2("some-appName2");
+ QString body2("some-body2");
+ QString icon2("some-icon2");
+ QString summary2("some-summary2");
+
+ retId = listener->Notify(appName2, replacesId+1, icon2, summary2, body2, {}, {{"urgency", 2}}, 10);
QCOMPARE(retId, replacesId+1);
+ QCOMPARE(++proxiedNotifications, d->getSentPackages());
+ QCOMPARE(d->getLastPackage()->get<uint>("id"), replacesId+1);
+ QCOMPARE(d->getLastPackage()->get<QString>("appName"), appName2);
+ QCOMPARE(d->getLastPackage()->get<QString>("ticker"), summary2 + ": " + body2);
+ QCOMPARE(d->getLastPackage()->get<bool>("isClearable"), false); // timeout != 0
+ QCOMPARE(d->getLastPackage()->hasPayload(), false);
QCOMPARE(listener->getApplications().count(), 2);
- QVERIFY(listener->getApplications().contains("testApp2"));
- QVERIFY(listener->getApplications().contains("testApp"));
+ QVERIFY(listener->getApplications().contains(appName2));
+ QVERIFY(listener->getApplications().contains(appName));
// if persistent-only is set, timeouts > 0 are not synced:
plugin->config()->set("generalPersistent", true);
- retId = listener->Notify("testApp", replacesId, "some-icon", "summary", "body", {}, {{}}, 1);
+ retId = listener->Notify(appName, replacesId, icon, summary, body, {}, {{}}, 1);
QCOMPARE(retId, 0U);
- retId = listener->Notify("testApp2", replacesId, "some-icon2", "summary2", "body2", {}, {{}}, 3);
+ QCOMPARE(proxiedNotifications, d->getSentPackages());
+ retId = listener->Notify(appName2, replacesId, icon2, summary2, body2, {}, {{}}, 3);
QCOMPARE(retId, 0U);
+ QCOMPARE(proxiedNotifications, d->getSentPackages());
// but timeout == 0 is
- retId = listener->Notify("testApp", replacesId, "some-icon", "summary", "body", {}, {{}}, 0);
+ retId = listener->Notify(appName, replacesId, icon, summary, body, {}, {{}}, 0);
QCOMPARE(retId, replacesId);
+ QCOMPARE(++proxiedNotifications, d->getSentPackages());
plugin->config()->set("generalPersistent", false);
// if min-urgency is set, lower urgency levels are not synced:
plugin->config()->set("generalUrgency", 1);
- retId = listener->Notify("testApp", replacesId, "some-icon", "summary", "body", {}, {{"urgency", 0}}, 0);
+ retId = listener->Notify(appName, replacesId, icon, summary, body, {}, {{"urgency", 0}}, 0);
QCOMPARE(retId, 0U);
+ QCOMPARE(proxiedNotifications, d->getSentPackages());
// equal urgency is
- retId = listener->Notify("testApp", replacesId, "some-icon", "summary", "body", {}, {{"urgency", 1}}, 0);
+ retId = listener->Notify(appName, replacesId, icon, summary, body, {}, {{"urgency", 1}}, 0);
QCOMPARE(retId, replacesId);
+ QCOMPARE(++proxiedNotifications, d->getSentPackages());
// higher urgency as well
- retId = listener->Notify("testApp", replacesId, "some-icon", "summary", "body", {}, {{"urgency", 2}}, 0);
+ retId = listener->Notify(appName, replacesId, icon, summary, body, {}, {{"urgency", 2}}, 0);
QCOMPARE(retId, replacesId);
+ QCOMPARE(++proxiedNotifications, d->getSentPackages());
plugin->config()->set("generalUrgency", 0);
// notifications for a deactivated application are not synced:
- QVERIFY(listener->getApplications().contains("testApp"));
- listener->getApplications()["testApp"].active = false;
- QVERIFY(!listener->getApplications()["testApp"].active);
- retId = listener->Notify("testApp", replacesId, "some-icon", "summary", "body", {}, {{"urgency", 0}}, 0);
+ QVERIFY(listener->getApplications().contains(appName));
+ listener->getApplications()[appName].active = false;
+ QVERIFY(!listener->getApplications()[appName].active);
+ retId = listener->Notify(appName, replacesId, icon, summary, body, {}, {{"urgency", 0}}, 0);
QCOMPARE(retId, 0U);
+ QCOMPARE(proxiedNotifications, d->getSentPackages());
// others are still:
- retId = listener->Notify("testApp2", replacesId+1, "some-icon2", "summary2", "body2", {}, {{}}, 0);
+ retId = listener->Notify(appName2, replacesId+1, icon2, summary2, body2, {}, {{}}, 0);
QCOMPARE(retId, replacesId+1);
+ QCOMPARE(++proxiedNotifications, d->getSentPackages());
// back to normal:
- listener->getApplications()["testApp"].active = true;
- QVERIFY(listener->getApplications()["testApp"].active);
- retId = listener->Notify("testApp", replacesId, "some-icon", "summary", "body", {}, {{}}, 0);
+ listener->getApplications()[appName].active = true;
+ QVERIFY(listener->getApplications()[appName].active);
+ retId = listener->Notify(appName, replacesId, icon, summary, body, {}, {{}}, 0);
QCOMPARE(retId, replacesId);
+ QCOMPARE(++proxiedNotifications, d->getSentPackages());
// notifications with blacklisted subjects are not synced:
- QVERIFY(listener->getApplications().contains("testApp"));
- listener->getApplications()["testApp"].blacklistExpression.setPattern("black[12]|foo(bar|baz)");
- retId = listener->Notify("testApp", replacesId, "some-icon", "summary black1", "body", {}, {{}}, 0);
+ QVERIFY(listener->getApplications().contains(appName));
+ listener->getApplications()[appName].blacklistExpression.setPattern("black[12]|foo(bar|baz)");
+ retId = listener->Notify(appName, replacesId, icon, "summary black1", body, {}, {{}}, 0);
QCOMPARE(retId, 0U);
- retId = listener->Notify("testApp", replacesId, "some-icon", "summary foobar", "body", {}, {{}}, 0);
+ QCOMPARE(proxiedNotifications, d->getSentPackages());
+ retId = listener->Notify(appName, replacesId, icon, "summary foobar", body, {}, {{}}, 0);
QCOMPARE(retId, 0U);
+ QCOMPARE(proxiedNotifications, d->getSentPackages());
// other subjects are synced:
- retId = listener->Notify("testApp", replacesId, "some-icon", "summary foo", "body", {}, {{}}, 0);
+ retId = listener->Notify(appName, replacesId, icon, "summary foo", body, {}, {{}}, 0);
QCOMPARE(retId, replacesId);
- retId = listener->Notify("testApp", replacesId, "some-icon", "summary black3", "body", {}, {{}}, 0);
+ QCOMPARE(++proxiedNotifications, d->getSentPackages());
+ retId = listener->Notify(appName, replacesId, icon, "summary black3", body, {}, {{}}, 0);
QCOMPARE(retId, replacesId);
+ QCOMPARE(++proxiedNotifications, d->getSentPackages());
// also body is checked by blacklist if requested:
plugin->config()->set("generalIncludeBody", true);
- retId = listener->Notify("testApp", replacesId, "some-icon", "summary", "body black1", {}, {{}}, 0);
+ retId = listener->Notify(appName, replacesId, icon, summary, "body black1", {}, {{}}, 0);
QCOMPARE(retId, 0U);
- retId = listener->Notify("testApp", replacesId, "some-icon", "summary", "body foobaz", {}, {{}}, 0);
+ QCOMPARE(proxiedNotifications, d->getSentPackages());
+ retId = listener->Notify(appName, replacesId, icon, summary, "body foobaz", {}, {{}}, 0);
QCOMPARE(retId, 0U);
+ QCOMPARE(proxiedNotifications, d->getSentPackages());
// body does not matter if inclusion was not requested:
plugin->config()->set("generalIncludeBody", false);
- retId = listener->Notify("testApp", replacesId, "some-icon", "summary", "body black1", {}, {{}}, 0);
+ retId = listener->Notify(appName, replacesId, icon, summary, "body black1", {}, {{}}, 0);
QCOMPARE(retId, replacesId);
- retId = listener->Notify("testApp", replacesId, "some-icon", "summary", "body foobaz", {}, {{}}, 0);
+ QCOMPARE(++proxiedNotifications, d->getSentPackages());
+ // without body, also ticker value is different:
+ QCOMPARE(d->getLastPackage()->get<QString>("ticker"), summary);
+ retId = listener->Notify(appName, replacesId, icon, summary, "body foobaz", {}, {{}}, 0);
QCOMPARE(retId, replacesId);
+ QCOMPARE(++proxiedNotifications, d->getSentPackages());
// back to normal:
- listener->getApplications()["testApp"].blacklistExpression.setPattern("");
+ listener->getApplications()[appName].blacklistExpression.setPattern("");
plugin->config()->set("generalIncludeBody", true);
- retId = listener->Notify("testApp", replacesId, "some-icon", "summary", "body", {}, {{}}, 0);
+ retId = listener->Notify(appName, replacesId, icon, summary, body, {}, {{}}, 0);
QCOMPARE(retId, replacesId);
- retId = listener->Notify("testApp2", replacesId, "some-icon2", "summary2", "body2", {}, {{}}, 0);
+ QCOMPARE(++proxiedNotifications, d->getSentPackages());
+ retId = listener->Notify(appName2, replacesId, icon2, summary2, body2, {}, {{}}, 0);
QCOMPARE(retId, replacesId);
+ QCOMPARE(++proxiedNotifications, d->getSentPackages());
+
+ // icon synchronization:
+ int count = 0;
+ for (const auto& iconName: KIconLoader::global()->queryIcons(-KIconLoader::SizeEnormous, KIconLoader::Application)) {
+ if (!iconName.endsWith(".png"))
+ continue;
+ if (count++ > 3) // max 3 iterations
+ break;
+
+ // existing icons are sync-ed if requested
+ plugin->config()->set("generalSynchronizeIcons", true);
+ QFileInfo fi(iconName);
+ //qDebug() << "XXX" << iconName << fi.baseName() << fi.size();
+ retId = listener->Notify(appName, replacesId, fi.baseName(), summary, body, {}, {{}}, 0);
+ QCOMPARE(retId, replacesId);
+ QCOMPARE(++proxiedNotifications, d->getSentPackages());
+ QVERIFY(d->getLastPackage()->hasPayload());
+ QCOMPARE(d->getLastPackage()->payloadSize(), fi.size());
+
+ // otherwise no payload:
+ plugin->config()->set("generalSynchronizeIcons", false);
+ retId = listener->Notify(appName, replacesId, fi.baseName(), summary, body, {}, {{}}, 0);
+ QCOMPARE(retId, replacesId);
+ QCOMPARE(++proxiedNotifications, d->getSentPackages());
+ QVERIFY(!d->getLastPackage()->hasPayload());
+ QCOMPARE(d->getLastPackage()->payloadSize(), 0);
+ }
}
--
kdeconnect packaging
More information about the pkg-kde-commits
mailing list