[SCM] kdeconnect packaging branch, master, updated. debian/0.9g-1-1183-g9d69498

Maximiliano Curia maxy at moszumanska.debian.org
Fri Oct 14 14:29:25 UTC 2016


Gitweb-URL: http://git.debian.org/?p=pkg-kde/kde-extras/kdeconnect.git;a=commitdiff;h=f072a0c

The following commit has been merged in the master branch:
commit f072a0c615115ecce0c0ab9ec8a83ae7ab0b7622
Author: Holger Kaelberer <holger.k at elberer.de>
Date:   Sat Dec 5 23:11:57 2015 +0100

    notifications: allow to configure how to sync desktop notifications
    
    Added kcm ui with global and app-specific config options.
    
    Global options affect all notifications:
    
    - Persistent only? --> Sync only notifications with timeout == 0?
    - Include body? --> Add body string to summary when syncing?
    - Minimum urgency
    
    Per-application options affect notifications sent by a specific
    application:
    
    - Sync it at all?
    - If yes, allow to define a "blacklist" pattern (QRegularExpression)
      to define which notifications should *not* be synced.
    
    Applications are maintained in the per-device config and added when
    seen the first time by the notification listener. From that moment on
    they can be configured in the kcm ui.
---
 core/kdeconnectpluginconfig.cpp                    |  30 +++
 core/kdeconnectpluginconfig.h                      |   8 +
 plugins/notifications/CMakeLists.txt               |  25 ++-
 .../kdeconnect_notifications_config.desktop        |  10 +
 plugins/notifications/notifications_config.cpp     | 113 ++++++++++
 .../notifications_config.h}                        |  22 +-
 plugins/notifications/notifications_config.ui      | 210 ++++++++++++++++++
 plugins/notifications/notificationslistener.cpp    |  69 +++++-
 plugins/notifications/notificationslistener.h      |   6 +
 ...icationslistener.h => notifyingapplication.cpp} |  46 ++--
 .../{notification.cpp => notifyingapplication.h}   |  40 ++--
 .../notifications/notifyingapplicationmodel.cpp    | 235 +++++++++++++++++++++
 plugins/notifications/notifyingapplicationmodel.h  |  56 +++++
 13 files changed, 814 insertions(+), 56 deletions(-)

diff --git a/core/kdeconnectpluginconfig.cpp b/core/kdeconnectpluginconfig.cpp
index 980235c..7c11e3c 100644
--- a/core/kdeconnectpluginconfig.cpp
+++ b/core/kdeconnectpluginconfig.cpp
@@ -62,6 +62,24 @@ QVariant KdeConnectPluginConfig::get(const QString& key, const QVariant& default
     return d->mConfig->value(key, defaultValue);
 }
 
+QVariantList KdeConnectPluginConfig::getList(const QString& key,
+                                             const QVariantList& defaultValue)
+{
+    QVariantList list;
+    d->mConfig->sync();  // note: need sync() to get recent changes signalled from other process
+    int size = d->mConfig->beginReadArray(key);
+    if (size < 1) {
+        d->mConfig->endArray();
+        return defaultValue;
+    }
+    for (int i = 0; i < size; ++i) {
+        d->mConfig->setArrayIndex(i);
+        list << d->mConfig->value("value");
+    }
+    d->mConfig->endArray();
+    return list;
+}
+
 void KdeConnectPluginConfig::set(const QString& key, const QVariant& value)
 {
     d->mConfig->setValue(key, value);
@@ -69,6 +87,18 @@ void KdeConnectPluginConfig::set(const QString& key, const QVariant& value)
     QDBusConnection::sessionBus().send(d->signal);
 }
 
+void KdeConnectPluginConfig::setList(const QString& key, const QVariantList& list)
+{
+    d->mConfig->beginWriteArray(key);
+    for (int i = 0; i < list.size(); ++i) {
+        d->mConfig->setArrayIndex(i);
+        d->mConfig->setValue("value", list.at(i));
+    }
+    d->mConfig->endArray();
+    d->mConfig->sync();
+    QDBusConnection::sessionBus().send(d->signal);
+}
+
 void KdeConnectPluginConfig::slotConfigChanged()
 {
     Q_EMIT configChanged();
diff --git a/core/kdeconnectpluginconfig.h b/core/kdeconnectpluginconfig.h
index 09bf68e..a3fcf18 100644
--- a/core/kdeconnectpluginconfig.h
+++ b/core/kdeconnectpluginconfig.h
@@ -51,6 +51,12 @@ public:
     void set(const QString& key, const QVariant& value);
 
     /**
+     * Store a list of values in this config object under the array name
+     * specified in key.
+     */
+    void setList(const QString& key, const QVariantList& list);
+
+    /**
      * Read a key-value pair from this config object
      */
     QVariant get(const QString& key, const QVariant& defaultValue);
@@ -62,6 +68,8 @@ public:
         return get(key, QVariant(defaultValue)).template value<T>(); //Important note: Awesome template syntax is awesome
     }
 
+    QVariantList getList(const QString& key, const QVariantList& defaultValue = {});
+
 private Q_SLOTS:
     void slotConfigChanged();
 
diff --git a/plugins/notifications/CMakeLists.txt b/plugins/notifications/CMakeLists.txt
index fbb459e..448be94 100644
--- a/plugins/notifications/CMakeLists.txt
+++ b/plugins/notifications/CMakeLists.txt
@@ -1,10 +1,11 @@
-find_package(KF5 REQUIRED COMPONENTS Notifications)
+find_package(KF5 REQUIRED COMPONENTS Notifications KCMUtils I18n)
 
 set(kdeconnect_notifications_SRCS
     notification.cpp
     notificationsplugin.cpp
     notificationsdbusinterface.cpp
     notificationslistener.cpp
+    notifyingapplication.cpp
 )
 
 kdeconnect_add_plugin(kdeconnect_notifications JSON kdeconnect_notifications.json SOURCES ${kdeconnect_notifications_SRCS})
@@ -13,4 +14,26 @@ target_link_libraries(kdeconnect_notifications
     kdeconnectcore
     Qt5::DBus
     KF5::Notifications
+    KF5::I18n
 )
+
+#######################################
+# Config
+
+set( kdeconnect_notifications_config_SRCS
+     notifications_config.cpp
+     notifyingapplication.cpp
+     notifyingapplicationmodel.cpp
+)
+ki18n_wrap_ui( kdeconnect_notifications_config_SRCS notifications_config.ui )
+
+add_library(kdeconnect_notifications_config MODULE ${kdeconnect_notifications_config_SRCS} )
+target_link_libraries( kdeconnect_notifications_config
+    kdeconnectcore
+    kdeconnectpluginkcm
+    KF5::I18n
+    KF5::KCMUtils
+)
+
+install( TARGETS kdeconnect_notifications_config DESTINATION ${PLUGIN_INSTALL_DIR} )
+install( FILES kdeconnect_notifications_config.desktop DESTINATION ${SERVICES_INSTALL_DIR} )
diff --git a/plugins/notifications/kdeconnect_notifications_config.desktop b/plugins/notifications/kdeconnect_notifications_config.desktop
new file mode 100644
index 0000000..6535bc7
--- /dev/null
+++ b/plugins/notifications/kdeconnect_notifications_config.desktop
@@ -0,0 +1,10 @@
+[Desktop Entry]
+Type=Service
+X-KDE-ServiceTypes=KCModule
+
+X-KDE-Library=kdeconnect_notifications_config
+X-KDE-ParentComponents=kdeconnect_notifications
+
+Name=Notification synchronization plugin settings
+
+Categories=Qt;KDE;X-KDE-settings-kdeconnect;
diff --git a/plugins/notifications/notifications_config.cpp b/plugins/notifications/notifications_config.cpp
new file mode 100644
index 0000000..5086d9f
--- /dev/null
+++ b/plugins/notifications/notifications_config.cpp
@@ -0,0 +1,113 @@
+/**
+ * Copyright 2015 Holger Kaelberer <holger.k at elberer.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License or (at your option) version 3 or any later version
+ * accepted by the membership of KDE e.V. (or its successor approved
+ * by the membership of KDE e.V.), which shall act as a proxy
+ * defined in Section 14 of version 3 of the license.
+ *
+ * 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "notifications_config.h"
+#include "ui_notifications_config.h"
+#include "notifyingapplicationmodel.h"
+
+#include <KCModule>
+#include <KPluginFactory>
+
+K_PLUGIN_FACTORY(NotificationsConfigFactory, registerPlugin<NotificationsConfig>();)
+
+NotificationsConfig::NotificationsConfig(QWidget *parent, const QVariantList& args)
+    : KdeConnectPluginKcm(parent, args, "kdeconnect_notifications_config")
+    , m_ui(new Ui::NotificationsConfigUi())
+    , appModel(new NotifyingApplicationModel)
+{
+    qRegisterMetaTypeStreamOperators<NotifyingApplication>("NotifyingApplication");
+
+    m_ui->setupUi(this);
+    m_ui->appList->setIconSize(QSize(32,32));
+
+    m_ui->appList->setModel(appModel);
+
+    m_ui->appList->horizontalHeader()->setSectionResizeMode(0, QHeaderView::QHeaderView::Fixed);
+    m_ui->appList->horizontalHeader()->setSectionResizeMode(1, QHeaderView::QHeaderView::Stretch);
+    m_ui->appList->horizontalHeader()->setSectionResizeMode(2, QHeaderView::QHeaderView::Stretch);
+    for (int i = 0; i < 3; i++)
+        m_ui->appList->resizeColumnToContents(i);
+
+    connect(m_ui->appList->horizontalHeader(), SIGNAL(sortIndicatorChanged(int,Qt::SortOrder)),
+            m_ui->appList, SLOT(sortByColumn(int)));
+
+    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(appModel, SIGNAL(applicationsChanged()), this, SLOT(changed()));
+
+    connect(config(), SIGNAL(configChanged()), this, SLOT(loadApplications()));
+}
+
+NotificationsConfig::~NotificationsConfig()
+{
+    delete m_ui;
+}
+
+void NotificationsConfig::defaults()
+{
+    KCModule::defaults();
+    m_ui->check_persistent->setChecked(false);
+    m_ui->spin_urgency->setValue(0);
+    Q_EMIT changed(true);
+}
+
+void NotificationsConfig::loadApplications()
+{
+    appModel->clearApplications();
+    QVariantList list = config()->getList("applications");
+    for (const auto& a: list) {
+        NotifyingApplication app = a.value<NotifyingApplication>();
+        if (!appModel->containsApp(app.name)) {
+            appModel->appendApp(app);
+        }
+    }
+}
+
+void NotificationsConfig::load()
+{
+    KCModule::load();
+    bool persistent = config()->get("generalPersistent", false);
+    m_ui->check_persistent->setChecked(persistent);
+    bool body = config()->get("generalIncludeBody", true);
+    m_ui->check_body->setChecked(body);
+    int urgency = config()->get("generalUrgency", 0);
+    m_ui->spin_urgency->setValue(urgency);
+
+    loadApplications();
+    Q_EMIT changed(false);
+}
+
+void NotificationsConfig::save()
+{
+    config()->set("generalPersistent", m_ui->check_persistent->isChecked());
+    config()->set("generalIncludeBody", m_ui->check_body->isChecked());
+    config()->set("generalUrgency", m_ui->spin_urgency->value());
+
+    QVariantList list;
+    for (const auto& a: appModel->apps())
+        list << QVariant::fromValue<NotifyingApplication>(a);
+    config()->setList("applications", list);
+    KCModule::save();
+    Q_EMIT changed(false);
+}
+
+#include "notifications_config.moc"
diff --git a/plugins/pausemusic/pausemusic_config.h b/plugins/notifications/notifications_config.h
similarity index 71%
copy from plugins/pausemusic/pausemusic_config.h
copy to plugins/notifications/notifications_config.h
index 002e39e..fedbfc6 100644
--- a/plugins/pausemusic/pausemusic_config.h
+++ b/plugins/notifications/notifications_config.h
@@ -1,5 +1,5 @@
 /**
- * Copyright 2013 Albert Vaca <albertvaka at gmail.com>
+ * Copyright 2015 Holger Kaelberer <holger.k at elberer.de>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as
@@ -18,30 +18,36 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#ifndef PAUSEMUSIC_CONFIG_H
-#define PAUSEMUSIC_CONFIG_H
+#ifndef NOTIFICATIONS_CONFIG_H
+#define NOTIFICATIONS_CONFIG_H
 
 #include "kcmplugin/kdeconnectpluginkcm.h"
 
 namespace Ui {
-    class PauseMusicConfigUi;
+    class NotificationsConfigUi;
 }
 
-class PauseMusicConfig
+class NotifyingApplicationModel;
+
+class NotificationsConfig
     : public KdeConnectPluginKcm
 {
     Q_OBJECT
 public:
-    PauseMusicConfig(QWidget *parent, const QVariantList&);
-    virtual ~PauseMusicConfig();
+    NotificationsConfig(QWidget *parent, const QVariantList&);
+    virtual ~NotificationsConfig();
 
 public Q_SLOTS:
     virtual void save() override;
     virtual void load() override;
     virtual void defaults() override;
 
+private Q_SLOTS:
+    void loadApplications();
+
 private:
-    Ui::PauseMusicConfigUi* m_ui;
+    Ui::NotificationsConfigUi* m_ui;
+    NotifyingApplicationModel* appModel;
 
 };
 
diff --git a/plugins/notifications/notifications_config.ui b/plugins/notifications/notifications_config.ui
new file mode 100644
index 0000000..3f3d8a4
--- /dev/null
+++ b/plugins/notifications/notifications_config.ui
@@ -0,0 +1,210 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>NotificationsConfigUi</class>
+ <widget class="QWidget" name="NotificationsConfigUi">
+  <property name="windowModality">
+   <enum>Qt::WindowModal</enum>
+  </property>
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>350</width>
+    <height>326</height>
+   </rect>
+  </property>
+  <property name="sizePolicy">
+   <sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
+    <horstretch>0</horstretch>
+    <verstretch>0</verstretch>
+   </sizepolicy>
+  </property>
+  <property name="minimumSize">
+   <size>
+    <width>350</width>
+    <height>0</height>
+   </size>
+  </property>
+  <property name="windowTitle">
+   <string>Pause music plugin</string>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout">
+   <item>
+    <widget class="QGroupBox" name="groupBox_2">
+     <property name="sizePolicy">
+      <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+       <horstretch>0</horstretch>
+       <verstretch>0</verstretch>
+      </sizepolicy>
+     </property>
+     <property name="font">
+      <font>
+       <pointsize>11</pointsize>
+       <weight>75</weight>
+       <bold>true</bold>
+      </font>
+     </property>
+     <property name="title">
+      <string>General</string>
+     </property>
+     <layout class="QVBoxLayout" name="verticalLayout_2">
+      <item>
+       <widget class="QCheckBox" name="check_persistent">
+        <property name="font">
+         <font>
+          <weight>50</weight>
+          <bold>false</bold>
+         </font>
+        </property>
+        <property name="toolTip">
+         <string>Synchronize only notifications with a timeout value of 0?</string>
+        </property>
+        <property name="text">
+         <string>Persistent notifications only</string>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <widget class="QCheckBox" name="check_body">
+        <property name="font">
+         <font>
+          <weight>50</weight>
+          <bold>false</bold>
+         </font>
+        </property>
+        <property name="toolTip">
+         <string>Append the notification body to the summary when synchronizing notifications?</string>
+        </property>
+        <property name="text">
+         <string>Include body</string>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <widget class="QWidget" name="horizontalWidget" native="true">
+        <property name="sizePolicy">
+         <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+          <horstretch>0</horstretch>
+          <verstretch>0</verstretch>
+         </sizepolicy>
+        </property>
+        <layout class="QHBoxLayout" name="horizontalLayout">
+         <item>
+          <widget class="QSpinBox" name="spin_urgency">
+           <property name="maximumSize">
+            <size>
+             <width>40</width>
+             <height>32</height>
+            </size>
+           </property>
+           <property name="font">
+            <font>
+             <weight>50</weight>
+             <bold>false</bold>
+            </font>
+           </property>
+           <property name="toolTip">
+            <string><html><head/><body><p>Minimum urgency level of the notifications</p></body></html></string>
+           </property>
+           <property name="maximum">
+            <number>2</number>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class="QLabel" name="label">
+           <property name="font">
+            <font>
+             <weight>50</weight>
+             <bold>false</bold>
+            </font>
+           </property>
+           <property name="toolTip">
+            <string>Synchronize only notifications with the given urgency level.</string>
+           </property>
+           <property name="text">
+            <string>Minimum urgency level</string>
+           </property>
+          </widget>
+         </item>
+        </layout>
+       </widget>
+      </item>
+     </layout>
+    </widget>
+   </item>
+   <item>
+    <widget class="QGroupBox" name="groupBox">
+     <property name="sizePolicy">
+      <sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
+       <horstretch>0</horstretch>
+       <verstretch>0</verstretch>
+      </sizepolicy>
+     </property>
+     <property name="font">
+      <font>
+       <weight>75</weight>
+       <bold>true</bold>
+      </font>
+     </property>
+     <property name="toolTip">
+      <string/>
+     </property>
+     <property name="title">
+      <string>Applications</string>
+     </property>
+     <layout class="QHBoxLayout" name="horizontalLayout_2">
+      <item>
+       <widget class="QTableView" name="appList">
+        <property name="sizePolicy">
+         <sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
+          <horstretch>0</horstretch>
+          <verstretch>0</verstretch>
+         </sizepolicy>
+        </property>
+        <property name="font">
+         <font>
+          <weight>50</weight>
+          <bold>false</bold>
+         </font>
+        </property>
+        <property name="alternatingRowColors">
+         <bool>true</bool>
+        </property>
+        <property name="showGrid">
+         <bool>false</bool>
+        </property>
+        <property name="gridStyle">
+         <enum>Qt::NoPen</enum>
+        </property>
+        <property name="sortingEnabled">
+         <bool>true</bool>
+        </property>
+        <attribute name="horizontalHeaderVisible">
+         <bool>true</bool>
+        </attribute>
+        <attribute name="horizontalHeaderDefaultSectionSize">
+         <number>150</number>
+        </attribute>
+        <attribute name="horizontalHeaderMinimumSectionSize">
+         <number>20</number>
+        </attribute>
+        <attribute name="horizontalHeaderShowSortIndicator" stdset="0">
+         <bool>true</bool>
+        </attribute>
+        <attribute name="horizontalHeaderStretchLastSection">
+         <bool>true</bool>
+        </attribute>
+        <attribute name="verticalHeaderVisible">
+         <bool>false</bool>
+        </attribute>
+       </widget>
+      </item>
+     </layout>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/plugins/notifications/notificationslistener.cpp b/plugins/notifications/notificationslistener.cpp
index 88ad98b..7e643af 100644
--- a/plugins/notifications/notificationslistener.cpp
+++ b/plugins/notifications/notificationslistener.cpp
@@ -30,6 +30,7 @@
 #include "notificationsplugin.h"
 #include "notification_debug.h"
 #include "notificationsdbusinterface.h"
+#include "notifyingapplication.h"
 
 NotificationsListener::NotificationsListener(KdeConnectPlugin* aPlugin,
                                              NotificationsDbusInterface* aDbusInterface)
@@ -37,6 +38,8 @@ NotificationsListener::NotificationsListener(KdeConnectPlugin* aPlugin,
       mPlugin(aPlugin),
       dbusInterface(aDbusInterface)
 {
+    qRegisterMetaTypeStreamOperators<NotifyingApplication>("NotifyingApplication");
+
     bool ret = QDBusConnection::sessionBus()
                 .registerObject("/org/freedesktop/Notifications",
                                 this,
@@ -55,6 +58,10 @@ NotificationsListener::NotificationsListener(KdeConnectPlugin* aPlugin,
                          "org.freedesktop.DBus");
     iface.call("AddMatch",
                "interface='org.freedesktop.Notifications',member='Notify',type='method_call',eavesdrop='true'");
+
+    loadApplications();
+
+    connect(mPlugin->config(), SIGNAL(configChanged()), this, SLOT(loadApplications()));
 }
 
 NotificationsListener::~NotificationsListener()
@@ -67,6 +74,18 @@ NotificationsListener::~NotificationsListener()
     QDBusConnection::sessionBus().unregisterObject("/org/freedesktop/Notifications");
 }
 
+void NotificationsListener::loadApplications()
+{
+    applications.clear();
+    QVariantList list = mPlugin->config()->getList("applications");
+    for (const auto& a: list) {
+        NotifyingApplication app = a.value<NotifyingApplication>();
+        if (!applications.contains(app.name))
+            applications.insert(app.name, app);
+    }
+    //qCDebug(KDECONNECT_PLUGIN_NOTIFICATION) << "Loaded" << applications.size() << " applications";
+}
+
 uint NotificationsListener::Notify(const QString &appName, uint replacesId,
                                    const QString &appIcon,
                                    const QString &summary, const QString &body,
@@ -74,20 +93,60 @@ uint NotificationsListener::Notify(const QString &appName, uint replacesId,
                                    const QVariantMap &hints, int timeout)
 {
     static int id = 0;
-    qCDebug(KDECONNECT_PLUGIN_NOTIFICATION) << "Got notification appName=" << appName << "replacesId=" << replacesId << "appIcon=" << appIcon << "summary=" << summary << "body=" << body << "actions=" << actions << "hints=" << hints << "timeout=" << timeout;
-    Q_UNUSED(hints);
     Q_UNUSED(actions);
-    Q_UNUSED(appIcon);
-    Q_UNUSED(body);
+
+    //qCDebug(KDECONNECT_PLUGIN_NOTIFICATION) << "Got notification appName=" << appName << "replacesId=" << replacesId << "appIcon=" << appIcon << "summary=" << summary << "body=" << body << "actions=" << actions << "hints=" << hints << "timeout=" << timeout;
 
     // skip our own notifications
     if (appName == QLatin1String("KDE Connect"))
         return 0;
 
+    NotifyingApplication app;
+    if (!applications.contains(appName)) {
+        // new application -> add to config
+        app.name = appName;
+        app.icon = appIcon;
+        app.active = true;
+        app.blacklistExpression = QRegularExpression();
+        applications.insert(app.name, app);
+        // update config:
+        QVariantList list;
+        for (const auto& a: applications.values())
+            list << QVariant::fromValue<NotifyingApplication>(a);
+        mPlugin->config()->setList("applications", list);
+        //qCDebug(KDECONNECT_PLUGIN_NOTIFICATION) << "Added new application to config:" << app;
+    } else
+        app = applications.value(appName);
+
+    if (!app.active)
+        return 0;
+
+    if (timeout > 0 && mPlugin->config()->get("generalPersistent", false))
+        return 0;
+
+    int urgency = -1;
+    bool ok;
+    if (hints.contains("urgency"))
+        urgency = hints["urgency"].toInt(&ok);
+    if (!ok)
+        urgency = -1;
+    if (urgency > -1 && urgency < mPlugin->config()->get<int>("generalUrgency", 0))
+        return 0;
+
+    QString ticker = summary;
+    if (!body.isEmpty() && mPlugin->config()->get("generalIncludeBody", true))
+        ticker += QLatin1String(": ") + body;
+
+    if (app.blacklistExpression.isValid() &&
+            !app.blacklistExpression.pattern().isEmpty() &&
+            app.blacklistExpression.match(ticker).hasMatch())
+        return 0;
+
+    //qCDebug(KDECONNECT_PLUGIN_NOTIFICATION) << "Sending notification from" << appName << ":" <<ticker;
     NetworkPackage np(PACKAGE_TYPE_NOTIFICATION);
     np.set("id", QString::number(replacesId > 0 ? replacesId : ++id));
     np.set("appName", appName);
-    np.set("ticker", summary);
+    np.set("ticker", ticker);
     np.set("isClearable", timeout == 0);  // KNotifications are persistent if
                                           // timeout == 0, for other notifications
                                           // clearability is pointless
diff --git a/plugins/notifications/notificationslistener.h b/plugins/notifications/notificationslistener.h
index 7887b59..bb37ead 100644
--- a/plugins/notifications/notificationslistener.h
+++ b/plugins/notifications/notificationslistener.h
@@ -24,6 +24,7 @@
 class KdeConnectPlugin;
 class NotificationsDbusInterface;
 class Notification;
+class NotifyingApplication;
 
 class NotificationsListener : public QDBusAbstractAdaptor
 {
@@ -38,9 +39,14 @@ public:
 private:
     KdeConnectPlugin* mPlugin;
     NotificationsDbusInterface* dbusInterface;
+    QHash<QString, NotifyingApplication> applications;
 
 public Q_SLOTS:
     Q_SCRIPTABLE uint Notify(const QString&, uint, const QString&,
                              const QString&, const QString&,
                              const QStringList&, const QVariantMap&, int);
+
+private Q_SLOTS:
+    void loadApplications();
+
 };
diff --git a/plugins/notifications/notificationslistener.h b/plugins/notifications/notifyingapplication.cpp
similarity index 53%
copy from plugins/notifications/notificationslistener.h
copy to plugins/notifications/notifyingapplication.cpp
index 7887b59..dc1c3c1 100644
--- a/plugins/notifications/notificationslistener.h
+++ b/plugins/notifications/notifyingapplication.cpp
@@ -18,29 +18,33 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#include <QtDBus/QDBusAbstractAdaptor>
-#include <core/device.h>
+#include "notifyingapplication.h"
 
-class KdeConnectPlugin;
-class NotificationsDbusInterface;
-class Notification;
+#include <QDebug>
+#include <QDataStream>
 
-class NotificationsListener : public QDBusAbstractAdaptor
+QDataStream &operator<<(QDataStream &out, const NotifyingApplication &app)
 {
-    Q_OBJECT
-    Q_CLASSINFO("D-Bus Interface", "org.freedesktop.Notifications")
+    out << app.name << app.icon << app.active << app.blacklistExpression.pattern();
+    return out;
+}
 
-public:
-    explicit NotificationsListener(KdeConnectPlugin* aPlugin,
-                                   NotificationsDbusInterface* aDbusInterface);
-    virtual ~NotificationsListener();
-
-private:
-    KdeConnectPlugin* mPlugin;
-    NotificationsDbusInterface* dbusInterface;
+QDataStream &operator>>(QDataStream &in, NotifyingApplication &app)
+{
+    QString pattern;
+    in >> app.name;
+    in >> app.icon;
+    in >> app.active;
+    in >> pattern;
+    app.blacklistExpression.setPattern(pattern);
+    return in;
+}
 
-public Q_SLOTS:
-    Q_SCRIPTABLE uint Notify(const QString&, uint, const QString&,
-                             const QString&, const QString&,
-                             const QStringList&, const QVariantMap&, int);
-};
+QDebug operator<<(QDebug dbg, const NotifyingApplication& a) {
+    dbg.nospace() << "{ name=" << a.name
+                  << ", icon=" << a.icon
+                  << ", active=" << a.active
+                  << ", blacklistExpression =" << a.blacklistExpression
+                  << " }";
+    return dbg.space();
+}
diff --git a/plugins/notifications/notification.cpp b/plugins/notifications/notifyingapplication.h
similarity index 56%
copy from plugins/notifications/notification.cpp
copy to plugins/notifications/notifyingapplication.h
index 3e42f2a..97421aa 100644
--- a/plugins/notifications/notification.cpp
+++ b/plugins/notifications/notifyingapplication.h
@@ -1,5 +1,5 @@
 /**
- * Copyright 2013 Albert Vaca <albertvaka at gmail.com>
+ * Copyright 2015 Holger Kaelberer <holger.k at elberer.de>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as
@@ -18,29 +18,27 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "notification.h"
+#ifndef NOTIFYINGAPPLICATION_H
+#define NOTIFYINGAPPLICATION_H
 
-#include <QDBusConnection>
+#include <QRegularExpression>
+#include <QList>
 
-Notification::Notification(const NetworkPackage& np, const QString& iconPath, QObject* parent)
-    : QObject(parent)
-{
-    mInternalId = np.get<QString>("id");
-    mAppName = np.get<QString>("appName");
-    mTicker = np.get<QString>("ticker");
-    mDismissable = np.get<bool>("isClearable");
-    mIconPath = iconPath;
-}
+struct NotifyingApplication {
+    QString name;
+    QString icon;
+    bool active;
+    QRegularExpression blacklistExpression;
 
-Notification::~Notification()
-{
+    bool operator==(const NotifyingApplication& other) const {
+        return (name == other.name);
+    }
+};
 
-}
+Q_DECLARE_METATYPE(NotifyingApplication);
 
-void Notification::dismiss()
-{
-    if (mDismissable) {
-        Q_EMIT dismissRequested(mInternalId);
-    }
-}
+QDataStream &operator<<(QDataStream &out, const NotifyingApplication &app);
+QDataStream &operator>>(QDataStream &in, NotifyingApplication &app);
+QDebug operator<<(QDebug dbg, const NotifyingApplication &a);
 
+#endif //NOTIFYINGAPPLICATION_H
diff --git a/plugins/notifications/notifyingapplicationmodel.cpp b/plugins/notifications/notifyingapplicationmodel.cpp
new file mode 100644
index 0000000..eadd46a
--- /dev/null
+++ b/plugins/notifications/notifyingapplicationmodel.cpp
@@ -0,0 +1,235 @@
+/**
+ * Copyright 2015 Holger Kaelberer <holger.k at elberer.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License or (at your option) version 3 or any later version
+ * accepted by the membership of KDE e.V. (or its successor approved
+ * by the membership of KDE e.V.), which shall act as a proxy
+ * defined in Section 14 of version 3 of the license.
+ *
+ * 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <QString>
+#include <QIcon>
+#include <QDebug>
+#include <KLocalizedString>
+#include <algorithm>
+
+#include "notifyingapplicationmodel.h"
+//#include "modeltest.h"
+
+NotifyingApplicationModel::NotifyingApplicationModel(QObject *parent)
+    : QAbstractTableModel(parent)
+{
+}
+
+NotifyingApplicationModel::~NotifyingApplicationModel()
+{
+}
+
+QVector<NotifyingApplication> NotifyingApplicationModel::apps()
+{
+    return m_apps;
+}
+
+void NotifyingApplicationModel::appendApp(const NotifyingApplication& app)
+{
+    if (app.name.isEmpty() || apps().contains(app))
+        return;
+    beginInsertRows(QModelIndex(), m_apps.size(), m_apps.size());
+    m_apps.append(app);
+    endInsertRows();
+}
+
+bool NotifyingApplicationModel::containsApp(const QString& name) const
+{
+    for (const auto& a: m_apps)
+        if (a.name == name)
+            return true;
+    return false;
+}
+
+Qt::ItemFlags NotifyingApplicationModel::flags(const QModelIndex& index) const
+{
+    Qt::ItemFlags flags = Qt::ItemIsEnabled;
+    if (index.isValid() && index.row() >= 0 && index.row() < m_apps.size() &&
+            index.column() < 3)
+    {
+        if (index.column() == 0)
+             flags |= Qt::ItemIsEditable | Qt::ItemIsUserCheckable;
+        else if (index.column() == 2) {
+            if (m_apps[index.row()].active)
+                flags |= Qt::ItemIsEditable;
+            else
+                flags ^= Qt::ItemIsEnabled;
+        }
+        else if (index.column() == 1) {
+            if (!m_apps[index.row()].active)
+                flags ^= Qt::ItemIsEnabled;
+        }
+    }
+    return flags;
+}
+
+void NotifyingApplicationModel::clearApplications()
+{
+    if (!m_apps.isEmpty()) {
+        beginRemoveRows(QModelIndex(), 0, m_apps.size() - 1);
+        m_apps.clear();
+        endRemoveRows();
+    }
+}
+
+QVariant NotifyingApplicationModel::data(const QModelIndex& index, int role) const
+{
+    Q_UNUSED(role);
+    if (!index.isValid()
+        || index.row() < 0
+        || index.row() >= m_apps.size()
+        || index.column() > 3)
+    {
+        return QVariant();
+    }
+
+    switch (role) {
+        case Qt::TextAlignmentRole: {
+            if (index.column() == 0)
+                return int(Qt::AlignCenter | Qt::AlignVCenter );
+            else
+                return int(Qt::AlignLeft | Qt::AlignVCenter );
+            break;
+        }
+        case Qt::DisplayRole: {
+            if (index.column() == 1)
+                return m_apps[index.row()].name;
+            else if (index.column() == 0)
+                return QVariant();//m_apps[index.row()].active;
+            else if (index.column() == 2)
+                return m_apps[index.row()].blacklistExpression.pattern();
+            else
+                return QVariant();
+            break;
+        }
+        case Qt::DecorationRole: {
+            if (index.column() == 1)
+                return QIcon::fromTheme(m_apps[index.row()].icon, QIcon::fromTheme("application-x-executable"));
+            else
+                return QVariant();
+            break;
+        }
+        case Qt::EditRole: {
+            if (index.column() == 0)
+                return m_apps[index.row()].active ? Qt::Checked : Qt::Unchecked;
+            else if (index.column() == 2)
+                return m_apps[index.row()].blacklistExpression.pattern();
+            else
+                return QVariant();
+            break;
+        }
+        case Qt::CheckStateRole: {
+            if (index.column() == 0)
+                return m_apps[index.row()].active ? Qt::Checked : Qt::Unchecked;
+            else
+                return QVariant();
+            break;
+        }
+    }
+    return QVariant();
+}
+
+bool NotifyingApplicationModel::setData(const QModelIndex &index, const QVariant &value, int role)
+{
+    if (!index.isValid() ||
+            (index.column() != 0 && index.column() != 2) ||
+            index.row() < 0 || index.row() >= m_apps.size())
+        return false;
+
+    bool res = false;
+    QModelIndex bottomRight = createIndex(index.row(), index.column());
+    switch (role) {
+        case Qt::CheckStateRole: {
+            if (index.column() == 0) {
+                m_apps[index.row()].active = ((Qt::CheckState)value.toInt() == Qt::Checked);
+                bottomRight = createIndex(index.row(), index.column() + 1);
+                res = true;
+            }
+            break;
+        }
+        case Qt::EditRole: {
+            if (index.column() == 2) {
+                m_apps[index.row()].blacklistExpression.setPattern(value.toString());
+                res = true;
+            }
+        }
+    }
+    if (res) {
+        Q_EMIT dataChanged(index, bottomRight);
+        Q_EMIT applicationsChanged();  // -> notify config that we need to save
+    }
+    return res;
+}
+
+void NotifyingApplicationModel::sort(int column, Qt::SortOrder order)
+{
+    if (column != 1)
+        return;
+
+    if (order == Qt::AscendingOrder)
+        std::sort(m_apps.begin(), m_apps.end(),
+                  [](const NotifyingApplication& a, const NotifyingApplication& b) {
+                     return (a.name.compare(b.name,  Qt::CaseInsensitive) < 1);
+                  });
+    else
+        std::sort(m_apps.begin(), m_apps.end(),
+                  [](const NotifyingApplication& a, const NotifyingApplication& b) {
+                     return (b.name.compare(a.name,  Qt::CaseInsensitive) < 1);
+                  });
+    Q_EMIT dataChanged(createIndex(0, 0), createIndex(m_apps.size(), 2));
+}
+
+QVariant NotifyingApplicationModel::headerData(int section, Qt::Orientation /*orientation*/,
+                                          int role) const
+{
+    switch (role) {
+        case Qt::DisplayRole: {
+            if (section == 1)
+                return i18n("Name");
+            else if (section == 0)
+                return QVariant(); //i18n("Sync");
+            else
+                return i18n("Blacklisted");
+        }
+        case Qt::ToolTipRole: {
+            if (section == 1)
+                return i18n("Name of a notifying application.");
+            else if (section == 0)
+                return i18n("Synchronize notifications of an application?");
+            else
+                return i18n("Regular expression defining which notifications should not be sent.
This pattern is applied to the summary and, if selected above, the body of notifications.");
+        }
+    }
+    return QVariant();
+}
+
+int NotifyingApplicationModel::columnCount(const QModelIndex&) const
+{
+    return 3;
+}
+
+int NotifyingApplicationModel::rowCount(const QModelIndex& parent) const
+{
+    if(parent.isValid()) {
+        //Return size 0 if we are a child because this is not a tree
+        return 0;
+    }
+    return m_apps.size();
+}
diff --git a/plugins/notifications/notifyingapplicationmodel.h b/plugins/notifications/notifyingapplicationmodel.h
new file mode 100644
index 0000000..efeda19
--- /dev/null
+++ b/plugins/notifications/notifyingapplicationmodel.h
@@ -0,0 +1,56 @@
+/**
+ * Copyright 2015 Holger Kaelberer <holger.k at elberer.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License or (at your option) version 3 or any later version
+ * accepted by the membership of KDE e.V. (or its successor approved
+ * by the membership of KDE e.V.), which shall act as a proxy
+ * defined in Section 14 of version 3 of the license.
+ *
+ * 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef NOTIFYINGAPPLICATIONMODEL_H
+#define NOTIFYINGAPPLICATIONMODEL_H
+
+#include <QAbstractTableModel>
+
+#include "notifyingapplication.h"
+
+class NotifyingApplicationModel: public QAbstractTableModel
+{
+    Q_OBJECT
+
+public:
+    explicit NotifyingApplicationModel(QObject *parent = nullptr);
+    virtual ~NotifyingApplicationModel();
+
+    virtual QVariant data(const QModelIndex& index, int role) const override;
+    virtual bool setData(const QModelIndex &index, const QVariant &value, int role) override;
+    virtual int rowCount(const QModelIndex& parent = QModelIndex()) const override;
+    virtual int columnCount(const QModelIndex& parent = QModelIndex()) const override;
+    virtual Qt::ItemFlags flags(const QModelIndex & index) const override;
+    virtual QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
+    virtual void sort(int column, Qt::SortOrder order = Qt::AscendingOrder) override;
+
+    QVector<NotifyingApplication> apps();
+    void clearApplications();
+    void appendApp(const NotifyingApplication& app);
+    bool containsApp(const QString& name) const;
+
+Q_SIGNALS:
+    void applicationsChanged();
+
+private:
+    QVector<NotifyingApplication> m_apps;
+};
+
+#endif // NOTIFYINGAPPLICATIONMODEL_H

-- 
kdeconnect packaging



More information about the pkg-kde-commits mailing list