Merge branch 'master' into sslrefactor

# Conflicts:
#	core/device.cpp
#	interfaces/devicesmodel.cpp
This commit is contained in:
Albert Vaca 2016-04-14 19:00:42 -07:00
commit 0c95010c3b
45 changed files with 473 additions and 154 deletions

View file

@ -1,11 +1,13 @@
[Desktop Entry]
Name=KDE Connect Application
Name[ar]=تطبيق كدي المتّصل
Name[ast]=Aplicación KDE Connect
Name[ca]=Aplicació KDE Connect
Name[ca@valencia]=Aplicació KDE Connect
Name[cs]=Aplikace KDE Connect
Name[da]=Programmet KDE Connect
Name[de]=KDE-Connect-Anwendung
Name[el]=Εφαρμογή KDE Connect
Name[en_GB]=KDE Connect Application
Name[es]=Aplicación KDE Connect
Name[fi]=KDE Connect -sovellus
@ -27,12 +29,14 @@ Name[uk]=Програма KDE Connect
Name[x-test]=xxKDE Connect Applicationxx
Name[zh_CN]=KDE Connect
GenericName=Device Synchronization
GenericName[ar]=مزامنة الأجهزة
GenericName[ast]=Sincronización de preseos
GenericName[ca]=Sincronització de dispositius
GenericName[ca@valencia]=Sincronització de dispositius
GenericName[cs]=Synchronizace zařízení
GenericName[da]=Enhedssynkronisering
GenericName[de]=Geräteabgleich
GenericName[el]=Συγχρονισμός συσκευών
GenericName[en_GB]=Device Synchronisation
GenericName[es]=Sincronización de dispositivos
GenericName[fi]=Laitteiden synkronointi
@ -55,12 +59,14 @@ GenericName[uk]=Синхронізація із пристроями
GenericName[x-test]=xxDevice Synchronizationxx
GenericName[zh_CN]=
Comment=Make all your devices one
Comment[ar]=اجعل أجهزتك كلّها واحدًا
Comment[ast]=Fai tolos tos preseos ún mesmu
Comment[ca]=Fa que tots els vostres dispositius siguin un
Comment[ca@valencia]=Fa que tots els vostres dispositius siguen un
Comment[cs]=Sjednoťte svá zařízení
Comment[da]=Gør alle dine enheder til en
Comment[de]=Gleichen Sie alle Ihre Geräte ab
Comment[el]=Όλες οι συσκευές σας σε μία
Comment[en_GB]=Make all your devices one
Comment[es]=Convertir todos sus dispositivos en uno
Comment[fi]=Yhdistä kaikki laitteesi toisiinsa

View file

@ -10,6 +10,7 @@ X-KDE-Kded-load-on-demand=false
X-KDE-Kded-phase=1
Name=KDE Connect
Name[ar]=كدي المتّصل
Name[ast]=KDE Connect
Name[bg]=KDE Connect
Name[bs]=Konekcija KDE
@ -18,6 +19,7 @@ Name[ca@valencia]=KDE Connect
Name[cs]=KDE Connect
Name[da]=KDE Connect
Name[de]=KDE-Connect
Name[el]=KDE Connect
Name[en_GB]=KDE Connect
Name[es]=KDE Connect
Name[fi]=KDE Connect
@ -41,6 +43,7 @@ Name[x-test]=xxKDE Connectxx
Name[zh_CN]=KDE Connect
Comment=Connect KDE with your smartphone
Comment[ar]=أوصل كدي بهاتفك الذّكيّ
Comment[ast]=Coneuta KDE col to preséu
Comment[bg]=Свържете КДЕ с вашия смартфон
Comment[bs]=Konektujte se na KDE sa Vašim mobitelom
@ -49,6 +52,7 @@ Comment[ca@valencia]=Connecta el KDE amb el vostre telèfon intel·ligent
Comment[cs]=Propojte KDE s vaším telefonem
Comment[da]=Forbind KDE med din smartphone
Comment[de]=KDE mit Ihren Smartphone verbinden
Comment[el]=Σύνδεση του KDE με το έξυπνο τηλέφωνό σας
Comment[en_GB]=Connect KDE with your smartphone
Comment[es]=Conecte KDE con su teléfono móvil
Comment[fi]=Yhdistä KDE älypuhelimeesi

View file

@ -8,6 +8,7 @@ OnlyShowIn=KDE;GNOME;Unity;XFCE;
NoDisplay=true
Name=KDEConnect daemon
Name[ar]=عفريت KDEConnect
Name[ast]=Degorriu KDEConnect
Name[bg]=Услуга KDE Connect
Name[ca]=Dimoni del KDEConnect
@ -15,6 +16,7 @@ Name[ca@valencia]=Dimoni del KDEConnect
Name[cs]=Démon KDE Connect
Name[da]=KDEConnect-dæmon
Name[de]=KDE-Connect-Dienst
Name[el]=Δαίμονας του KDEConnect
Name[en_GB]=KDEConnect daemon
Name[es]=Demonio de KDE Connect
Name[fi]=KDEConnect-taustapalvelu

View file

@ -1,6 +1,7 @@
[Desktop Entry]
Type=Service
Name=Send file via KDE Connect service
Name[ar]=أرسل ملفًّا عبر خدمة «كدي المتّصل»
Name[ast]=Unviar ficheru pente'l serviciu KDE Connect
Name[bg]=Изпращане на файл през услугата KDE Connect
Name[bs]=Pošalji datoteku putem KDE Connect servisa
@ -9,6 +10,7 @@ Name[ca@valencia]=Envia un fitxer a través del servei KDE Connect
Name[cs]=Poslat soubor přes službu KDE Connect
Name[da]=Send fil via KDE Connect-tjeneste
Name[de]=Datei mit KDE-Connect -Dienst versenden
Name[el]=Αποστολή αρχείου μέσω της υπηρεσίας KDE Connect
Name[en_GB]=Send file via KDE Connect service
Name[es]=Enviar archivo usando el servicio KDE Connect
Name[fi]=Lähetä tiedosto KDE Connect -palvelulla
@ -31,6 +33,8 @@ Name[x-test]=xxSend file via KDE Connect servicexx
Name[zh_CN]= KDE Connect
X-KDE-Library=kdeconnectfiletiemaction
X-KDE-Submenu=Connect
X-KDE-Submenu[ar]=اتّصل,اتصل
X-KDE-Submenu[ast]=Coneutar
X-KDE-Submenu[bg]=Свързване
X-KDE-Submenu[bs]=Uspostavi vezu
X-KDE-Submenu[ca]=Connecta
@ -38,6 +42,7 @@ X-KDE-Submenu[ca@valencia]=Connecta
X-KDE-Submenu[cs]=Připojit
X-KDE-Submenu[da]=Forbind
X-KDE-Submenu[de]=Verbinden
X-KDE-Submenu[el]=Σύνδεση
X-KDE-Submenu[en_GB]=Connect
X-KDE-Submenu[es]=Conectar
X-KDE-Submenu[fi]=Yhdistä

View file

@ -87,6 +87,7 @@ DeviceNotificationsDbusInterface::~DeviceNotificationsDbusInterface()
NotificationDbusInterface::NotificationDbusInterface(const QString& deviceId, const QString& notificationId, QObject* parent)
: OrgKdeKdeconnectDeviceNotificationsNotificationInterface(DaemonDbusInterface::activatedService(), "/modules/kdeconnect/devices/"+deviceId+"/notifications/"+notificationId, QDBusConnection::sessionBus(), parent)
, id(notificationId)
{
}

View file

@ -99,6 +99,10 @@ class KDECONNECTINTERFACES_EXPORT NotificationDbusInterface
public:
NotificationDbusInterface(const QString& deviceId, const QString& notificationId, QObject* parent = nullptr);
virtual ~NotificationDbusInterface();
QString notificationId() { return id; }
private:
const QString id;
};

View file

@ -102,10 +102,7 @@ void DevicesModel::deviceAdded(const QString& id)
DeviceDbusInterface* dev = new DeviceDbusInterface(id, this);
Q_ASSERT(dev->isValid());
bool onlyPaired = (m_displayFilter & StatusFilterFlag::Paired);
bool onlyReachable = (m_displayFilter & StatusFilterFlag::Reachable);
if ((onlyReachable && !dev->isReachable()) || (onlyPaired && !dev->isTrusted())) {
if (! passesFilter(dev)) {
delete dev;
return;
}
@ -127,23 +124,31 @@ void DevicesModel::deviceRemoved(const QString& id)
void DevicesModel::deviceUpdated(const QString& id, bool isVisible)
{
Q_UNUSED(isVisible);
int row = rowForDevice(id);
if (row < 0 && isVisible) {
if (row < 0) {
// FIXME: when m_dbusInterface is not valid refreshDeviceList() does
// nothing and we can miss some devices.
// Someone can reproduce this problem by restarting kdeconnectd while
// kdeconnect's plasmoid is still running.
qCDebug(KDECONNECT_INTERFACES) << "Adding missing device" << id;
// Another reason for this branch is that we removed the device previously
// because of the filter settings.
qCDebug(KDECONNECT_INTERFACES) << "Adding missing or previously removed device" << id;
deviceAdded(id);
row = rowForDevice(id);
}
if (row >= 0) {
} else {
DeviceDbusInterface *dev = getDevice(row);
if (! passesFilter(dev)) {
beginRemoveRows(QModelIndex(), row, row);
delete m_deviceList.takeAt(row);
endRemoveRows();
qCDebug(KDECONNECT_INTERFACES) << "Removed changed device " << id;
} else {
const QModelIndex idx = index(row);
Q_EMIT dataChanged(idx, idx);
}
}
}
int DevicesModel::displayFilter() const
{
@ -264,7 +269,9 @@ QVariant DevicesModel::data(const QModelIndex& index, int role) const
int status = StatusFilterFlag::NoFilter;
if (device->isReachable()) {
status |= StatusFilterFlag::Reachable;
if (device->isTrusted()) status |= StatusFilterFlag::Paired;
}
if (device->isTrusted()) {
status |= StatusFilterFlag::Paired;
}
return status;
}
@ -295,3 +302,11 @@ int DevicesModel::rowCount(const QModelIndex& parent) const
return m_deviceList.size();
}
bool DevicesModel::passesFilter(DeviceDbusInterface* dev) const
{
bool onlyPaired = (m_displayFilter & StatusFilterFlag::Paired);
bool onlyReachable = (m_displayFilter & StatusFilterFlag::Reachable);
return !((onlyReachable && !dev->isReachable()) || (onlyPaired && !dev->isTrusted()));
}

View file

@ -48,10 +48,13 @@ public:
DeviceRole
};
Q_ENUMS(ModelRoles);
// A device is always paired or reachable or both
// You can combine the Paired and Reachable flags
enum StatusFilterFlag {
NoFilter = 0x00,
Paired = 0x01,
Reachable = 0x02
Paired = 0x01, // show device only if it's paired
Reachable = 0x02 // show device only if it's reachable
};
Q_DECLARE_FLAGS(StatusFilterFlags, StatusFilterFlag)
Q_FLAGS(StatusFilterFlags)
@ -84,6 +87,7 @@ private:
int rowForDevice(const QString& id) const;
void clearDevices();
void appendDevice(DeviceDbusInterface* dev);
bool passesFilter(DeviceDbusInterface *dev) const;
DaemonDbusInterface* m_dbusInterface;
QVector<DeviceDbusInterface*> m_deviceList;

View file

@ -87,6 +87,8 @@ void NotificationsModel::setDeviceId(const QString& deviceId)
this, SLOT(notificationAdded(QString)));
connect(m_dbusInterface, SIGNAL(notificationRemoved(QString)),
this, SLOT(notificationRemoved(QString)));
connect(m_dbusInterface, SIGNAL(allNotificationsRemoved()),
this, SLOT(clearNotifications()));
refreshNotificationList();
@ -95,16 +97,24 @@ void NotificationsModel::setDeviceId(const QString& deviceId)
void NotificationsModel::notificationAdded(const QString& id)
{
//TODO: Actually add instead of refresh
Q_UNUSED(id);
refreshNotificationList();
int currentSize = m_notificationList.size();
beginInsertRows(QModelIndex(), currentSize, currentSize);
NotificationDbusInterface* dbusInterface = new NotificationDbusInterface(m_deviceId, id, this);
m_notificationList.append(dbusInterface);
endInsertRows();
}
void NotificationsModel::notificationRemoved(const QString& id)
{
//TODO: Actually remove instead of refresh
Q_UNUSED(id);
refreshNotificationList();
for (int i = 0; i < m_notificationList.size(); ++i) {
if (m_notificationList[i]->notificationId() == id) {
beginRemoveRows(QModelIndex(), i, i);
m_notificationList.removeAt(i);
endRemoveRows();
return;
}
}
qCWarning(KDECONNECT_INTERFACES) << "Attempted to remove unknown notification: " << id;
}
void NotificationsModel::refreshNotificationList()
@ -133,7 +143,6 @@ void NotificationsModel::receivedNotifications(QDBusPendingCallWatcher* watcher)
clearNotifications();
QDBusPendingReply<QStringList> pendingNotificationIds = *watcher;
clearNotifications();
if (pendingNotificationIds.isError()) {
qCWarning(KDECONNECT_INTERFACES) << pendingNotificationIds.error();
return;

View file

@ -69,6 +69,7 @@ private Q_SLOTS:
void notificationRemoved(const QString& id);
void refreshNotificationList();
void receivedNotifications(QDBusPendingCallWatcher* watcher);
void clearNotifications();
Q_SIGNALS:
void deviceIdChanged(const QString& value);
@ -76,8 +77,6 @@ Q_SIGNALS:
void rowsChanged();
private:
void clearNotifications();
DeviceNotificationsDbusInterface* m_dbusInterface;
QList<NotificationDbusInterface*> m_notificationList;
QString m_deviceId;

View file

@ -11,6 +11,7 @@ X-KDE-ParentApp=kcontrol
X-KDE-System-Settings-Parent-Category=hardware
Name=KDE Connect
Name[ar]=كدي المتّصل
Name[ast]=KDE Connect
Name[bg]=KDE Connect
Name[bs]=Konekcija KDE
@ -19,6 +20,7 @@ Name[ca@valencia]=KDE Connect
Name[cs]=KDE Connect
Name[da]=KDE Connect
Name[de]=KDE-Connect
Name[el]=KDE Connect
Name[en_GB]=KDE Connect
Name[es]=KDE Connect
Name[fi]=KDE Connect
@ -42,12 +44,14 @@ Name[x-test]=xxKDE Connectxx
Name[zh_CN]=KDE Connect
Comment=Connect and sync your devices
Comment[ar]=اتّصل وزامن أجهزتك
Comment[ast]=Coneuta y sincroniza los tos preseos
Comment[ca]=Connecta i sincronitza els vostres dispositius
Comment[ca@valencia]=Connecta i sincronitza els vostres dispositius
Comment[cs]=Připojte a synchronizujte svá zařízení
Comment[da]=Forbind og synkronisér dine enheder
Comment[de]=Verbinden und Abgleichen Ihrer Geräte
Comment[el]=Σύνδεση και συγχρονισμός των συσκευών σας
Comment[en_GB]=Connect and sync your devices
Comment[es]=Conectar y sincronizar sus dispositivos
Comment[fi]=Yhdistä ja synkronoi laitteitasi
@ -70,6 +74,7 @@ Comment[x-test]=xxConnect and sync your devicesxx
Comment[zh_CN]=
X-KDE-Keywords=Network,Android,Devices
X-KDE-Keywords[ar]=شبكة,أندرويد,اندرويد,جهاز,أجهزة
X-KDE-Keywords[ast]=Rede,Android,Preseos
X-KDE-Keywords[bg]=Мрежа,Андроид,Устройства
X-KDE-Keywords[bs]=Mreža,Android,Uređaji
@ -78,6 +83,7 @@ X-KDE-Keywords[ca@valencia]=Xarxa,Android,Dispositius
X-KDE-Keywords[cs]=Síť,Android,Zařízení
X-KDE-Keywords[da]=Netværk,Android,Enheder
X-KDE-Keywords[de]=Netzwerk,Android,Geräte
X-KDE-Keywords[el]=Δίκτυο,Android,Συσκευές
X-KDE-Keywords[en_GB]=Network,Android,Devices
X-KDE-Keywords[es]=Red,Android,Dispositivos
X-KDE-Keywords[fi]=Verkko,Android,Laitteet

View file

@ -4,12 +4,14 @@ Icon=kdeconnect
Terminal=false
Exec=kcmshell5 kcm_kdeconnect
Name=KDE Connect Settings
Name[ar]=إعدادات كدي المتّصل
Name[ast]=Axustes KDE Connect
Name[ca]=Arranjament del KDE Connect
Name[ca@valencia]=Arranjament del KDE Connect
Name[cs]=Nastavení KDE Connect
Name[da]=Indstilling af KDE Connect
Name[de]=KDE-Connect-Einstellungen
Name[el]=Ρυθμίσεις KDE Connect
Name[en_GB]=KDE Connect Settings
Name[es]=Ajustes de KDE Connect
Name[fi]=KDE Connectin asetukset
@ -29,12 +31,14 @@ Name[uk]=Параметри KDE Connect
Name[x-test]=xxKDE Connect Settingsxx
Name[zh_CN]=KDE Connect
GenericName=Connect and sync your devices
GenericName[ar]=اتّصل وزامن أجهزتك
GenericName[ast]=Coneuta y sincroniza los tos preseos
GenericName[ca]=Connecta i sincronitza els vostres dispositius
GenericName[ca@valencia]=Connecta i sincronitza els vostres dispositius
GenericName[cs]=Připojte a synchronizujte svá zařízení
GenericName[da]=Forbind og synkronisér dine enheder
GenericName[de]=Verbinden und Abgleichen Ihrer Geräte
GenericName[el]=Σύνδεση και συγχρονισμός των συσκευών σας
GenericName[en_GB]=Connect and sync your devices
GenericName[es]=Conectar y sincronizar sus dispositivos
GenericName[fi]=Yhdistä ja synkronoi laitteitasi

View file

@ -4,6 +4,7 @@
<metadata_license>CC0-1.0</metadata_license>
<project_license>GPL-2.0+</project_license>
<name>KDE Connect</name>
<name xml:lang="ar">كدي المتّصل</name>
<name xml:lang="ast">KDE Connect</name>
<name xml:lang="ca">KDE Connect</name>
<name xml:lang="ca-valencia">KDE Connect</name>
@ -27,6 +28,7 @@
<name xml:lang="x-test">xxKDE Connectxx</name>
<name xml:lang="zh-CN">KDE Connect</name>
<summary>Seamless connection of your devices</summary>
<summary xml:lang="ar">اتّصال سلس بين أجهزتك</summary>
<summary xml:lang="ast">Conexón de los tos preseos ensin esfuerciu</summary>
<summary xml:lang="ca">Connexió transparent amb els vostres dispositius</summary>
<summary xml:lang="ca-valencia">Connexió transparent amb els vostres dispositius</summary>
@ -51,6 +53,7 @@
<summary xml:lang="zh-CN">无缝连接您的设备</summary>
<description>
<p>KDE Connect provides integration between your Android phone and your desktop.</p>
<p xml:lang="ar">يوفّر «كدي المتصّل» التّكامل بين هاتف أندرويد وسطح المكتب.</p>
<p xml:lang="ast">KDE Connect forne integración ente'l to preséu Android y el to escritoriu.</p>
<p xml:lang="ca">El KDE Connect proporciona la integració entre el telèfon Android i el vostre escriptori.</p>
<p xml:lang="ca-valencia">El KDE Connect proporciona la integració entre el telèfon Android i el vostre escriptori.</p>
@ -83,6 +86,7 @@
</screenshot>
</screenshots>
<project_group>KDE Connect</project_group>
<project_group xml:lang="ar">كدي المتّصل</project_group>
<project_group xml:lang="ast">KDE Connect</project_group>
<project_group xml:lang="ca">KDE Connect</project_group>
<project_group xml:lang="ca-valencia">KDE Connect</project_group>

View file

@ -1,11 +1,13 @@
[Desktop Entry]
Name=KDE Connect Monitor
Name[ar]=مرقاب «كدي المتّصل»
Name[ast]=Monitor de KDE Connect
Name[ca]=Controlador del KDE Connect
Name[ca@valencia]=Controlador del KDE Connect
Name[cs]=Monitor KDE Connect
Name[da]=KDE Connect-overvåger
Name[de]=KDE-Connect-Monitor
Name[el]=Εφαρμογή εποπτείας του KDE Connect
Name[en_GB]=KDE Connect Monitor
Name[es]=Monitor de KDE Connect
Name[fi]=KDE Connect -valvonta
@ -25,12 +27,14 @@ Name[uk]=Монітор KDE Connect
Name[x-test]=xxKDE Connect Monitorxx
Name[zh_CN]=KDE Connect
Comment=Display information about your devices
Comment[ar]=اعرض معلومات عن أجهزتك
Comment[ast]=Amuesa información tocante a los tos preseos
Comment[ca]=Mostra la informació dels vostres dispositius
Comment[ca@valencia]=Mostra la informació dels vostres dispositius
Comment[cs]=Zobrazit informace o vašich zařízeních
Comment[da]=Vis information om dine enheder
Comment[de]=Anzeige von Informationen über Ihre Geräte
Comment[el]=Προβολή πληροφοριών σχετικά με τις συσκευές σας
Comment[en_GB]=Display information about your devices
Comment[es]=Mostrar información sobre sus dispositivos
Comment[fi]=Näyttää tietoa laitteistasi

View file

@ -27,9 +27,14 @@ QtObject {
id: root
property string deviceId: ""
property variant device: DeviceDbusInterfaceFactory.create(deviceId)
property bool available: false
property alias deviceId: checker.deviceId
readonly property alias device: checker.device
readonly property alias available: checker.available
readonly property PluginChecker pluginChecker: PluginChecker {
id: checker
pluginName: "battery"
}
property bool charging: false
property int charge: -1
@ -48,7 +53,6 @@ QtObject {
onSuccess: root.charge = result
}
// Note: magically called by qml
onAvailableChanged: {
if (available) {
battery = DeviceBatteryDbusInterfaceFactory.create(deviceId)
@ -62,19 +66,4 @@ QtObject {
battery = null
}
}
function pluginsChanged() {
var result = DBusResponseWaiter.waitForReply(device.hasPlugin("kdeconnect_battery"))
if (result && result != "error") {
available = true
} else {
available = false
}
}
Component.onCompleted: {
device.pluginsChanged.connect(pluginsChanged)
device.pluginsChanged()
}
}

View file

@ -27,9 +27,14 @@ QtObject {
id: root
property string deviceId: ""
property variant device: DeviceDbusInterfaceFactory.create(deviceId)
property bool available: false
property alias deviceId: checker.deviceId
readonly property alias device: checker.device
readonly property alias available: checker.available
readonly property PluginChecker pluginChecker: PluginChecker {
id: checker
pluginName: "findmyphone"
}
property variant findMyPhone: null
@ -39,12 +44,6 @@ QtObject {
}
}
Component.onCompleted: {
device.pluginsChanged.connect(pluginsChanged)
pluginsChanged()
}
// Note: magically called by qml
onAvailableChanged: {
if (available) {
findMyPhone = FindMyPhoneDbusInterfaceFactory.create(deviceId)
@ -52,10 +51,4 @@ QtObject {
findMyPhone = null
}
}
function pluginsChanged() {
var result = DBusResponseWaiter.waitForReply(device.hasPlugin("kdeconnect_findmyphone"))
available = (result && result != "error");
}
}

View file

@ -0,0 +1,45 @@
/**
* Copyright 2014 Samoilenko Yuri <kinnalru@gmail.com>
* Copyright 2016 David Kahles <david.kahles96@gmail.com>
*
* 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/>.
*/
import QtQml 2.2
import org.kde.kdeconnect 1.0
QtObject {
id: root
property string deviceId: ""
property string pluginName: ""
readonly property variant device: DeviceDbusInterfaceFactory.create(deviceId)
property bool available: false
property Connections connection: Connections {
target: device
onPluginsChanged: pluginsChanged()
}
Component.onCompleted: pluginsChanged()
function pluginsChanged() {
var result = DBusResponseWaiter.waitForReply(device.hasPlugin("kdeconnect_" + pluginName))
available = (result && result != "error");
}
}

View file

@ -27,9 +27,14 @@ QtObject {
id: root
property string deviceId: ""
property variant device: DeviceDbusInterfaceFactory.create(deviceId)
property bool available: false
property alias deviceId: checker.deviceId
readonly property alias device: checker.device
readonly property alias available: checker.available
readonly property PluginChecker pluginChecker: PluginChecker {
id: checker
pluginName: "sftp"
}
property variant sftp: null
@ -38,12 +43,6 @@ QtObject {
sftp.startBrowsing();
}
Component.onCompleted: {
device.pluginsChanged.connect(pluginsChanged)
pluginsChanged()
}
// Note: magically called by qml
onAvailableChanged: {
if (available) {
sftp = SftpDbusInterfaceFactory.create(deviceId)
@ -51,10 +50,4 @@ QtObject {
sftp = null
}
}
function pluginsChanged() {
var result = DBusResponseWaiter.waitForReply(device.hasPlugin("kdeconnect_sftp"))
available = (result && result != "error");
}
}

View file

@ -1,5 +1,6 @@
[Desktop Entry]
Name=KDE Connect
Name[ar]=كدي المتّصل
Name[ast]=KDE Connect
Name[bg]=KDE Connect
Name[bs]=Konekcija KDE
@ -8,6 +9,7 @@ Name[ca@valencia]=KDE Connect
Name[cs]=KDE Connect
Name[da]=KDE Connect
Name[de]=KDE-Connect
Name[el]=KDE Connect
Name[en_GB]=KDE Connect
Name[es]=KDE Connect
Name[fi]=KDE Connect
@ -30,14 +32,16 @@ Name[uk]=З’єднання KDE
Name[x-test]=xxKDE Connectxx
Name[zh_CN]=KDE Connect
Comment=Show notifications from your devices using KDE Connect
Comment[ar]=أظهر الإخطارات من أجهزتك باستخدام «كدي المتّصل»
Comment[ast]=Amuesa avisos de los tos preseos usando KDE Connect
Comment[bg]=Показване на уведомления от вашите устройства чрез KDE Connect
Comment[bs]=Prikaži obavlještenja sa uređaja koji koriste KDE konekciju
Comment[ca]=Mostra les notificacions dels vostres dispositius usant el KDE Connect
Comment[ca@valencia]=Mostra les notificacions dels vostres dispositius usant el KDE Connect
Comment[ca]=Mostra les notificacions dels vostres dispositius emprant el KDE Connect
Comment[ca@valencia]=Mostra les notificacions dels vostres dispositius emprant el KDE Connect
Comment[cs]=Zobrazit upozornění z vašich zařízení pomocí KDE Connect
Comment[da]=Vis bekendtgørelser fra dine enheder med KDE Connect
Comment[de]=Zeigt Benachrichtigungen von Ihren Geräten mit KDE-Connect
Comment[el]=Προβολή ειδοποιήσεων από τις συσκευές σας με το KDE Connect
Comment[en_GB]=Show notifications from your devices using KDE Connect
Comment[es]=Mostrar notificaciones de sus dispositivos usando KDE Connect
Comment[fi]=Näytä laitteidesi ilmoitukset KDE Connectilla

View file

@ -37,7 +37,7 @@ BatteryDbusInterface::BatteryDbusInterface(const Device *device)
// destructor.
QMap<QString, BatteryDbusInterface *>::iterator oldInterfaceIter = s_dbusInterfaces.find(device->id());
if (oldInterfaceIter != s_dbusInterfaces.end()) {
qCDebug(KDECONNECT_PLUGIN_BATTERY) << "Deleting stale BattteryDbusInterface for" << device->name();
qCDebug(KDECONNECT_PLUGIN_BATTERY) << "Deleting stale BatteryDbusInterface for" << device->name();
//FIXME: This still crashes sometimes even after the workaround made in 38aa970, commented out by now
//oldInterfaceIter.value()->deleteLater();
s_dbusInterfaces.erase(oldInterfaceIter);

View file

@ -24,7 +24,7 @@
"Description[nn]": "Del utklippstavla mellom einingar",
"Description[pl]": "Współdziel schowek pomiędzy urządzeniami",
"Description[pt]": "Partilhar a área de transferência entre dispositivos",
"Description[pt_BR]": "Compartilhar a área de transferência entre dispositivos",
"Description[pt_BR]": "Compartilha a área de transferência entre dispositivos",
"Description[ru]": "Общий буфер обмена между устройствами",
"Description[sk]": "Zdieľať schránku medzi zariadeniami",
"Description[sv]": "Dela klippbordet mellan apparater",

View file

@ -17,6 +17,7 @@
"Description[ca@valencia]": "Troba el vostra telèfon perdut fent que reproduïsca un so d'alarma ",
"Description[ca]": "Troba el vostra telèfon perdut fent que reprodueixi un so d'alarma ",
"Description[cs]": "Najděte dsvůj telefon tím, že jej necháte přehrát zvuk upomínky",
"Description[de]": "Finden Sie Ihr verlegtes Telefon, indem Sie mit ihm eine Warnton abspielen",
"Description[es]": "Encuentre su teléfono perdido haciéndole reproducir un sonido de alarma",
"Description[fi]": "Löydä hukkaamasi puhelin laittamalla se soittamaan hälytysääntä ",
"Description[gl]": "Reproducir un son de alarma nun teléfono móbil perdido para atopalo.",
@ -43,6 +44,7 @@
"Name[ca@valencia]": "Troba el meu telèfon",
"Name[ca]": "Troba el meu telèfon",
"Name[cs]": "Najít můj telefon",
"Name[de]": "Telefon suchen",
"Name[es]": "Encontrar mi teléfono",
"Name[fi]": "Löydä puhelimeni",
"Name[gl]": "Atopar o móbil",

View file

@ -1,6 +1,7 @@
[Global]
IconName=kdeconnect
Name=KDE Connect
Name[ar]=كدي المتّصل
Name[ast]=KDE Connect
Name[bg]=KDE Connect
Name[bs]=Konekcija KDE
@ -9,6 +10,7 @@ Name[ca@valencia]=KDE Connect
Name[cs]=KDE Connect
Name[da]=KDE Connect
Name[de]=KDE-Connect
Name[el]=KDE Connect
Name[en_GB]=KDE Connect
Name[es]=KDE Connect
Name[fi]=KDE Connect
@ -31,6 +33,7 @@ Name[uk]=З’єднання KDE
Name[x-test]=xxKDE Connectxx
Name[zh_CN]=KDE Connect
Comment=Notifications from your devices
Comment[ar]=الإخطارات من أجهزتك
Comment[ast]=Avisos de los tos preseos
Comment[bg]=Уведомления от устройствата ви
Comment[bs]=Notifikacija sa Vašeg uređaja
@ -39,6 +42,7 @@ Comment[ca@valencia]=Notificacions dels vostres dispositius
Comment[cs]=Oznamování z vašich zařízení
Comment[da]=Bekendtgørelser fra dine enheder
Comment[de]=Benachrichtigungen von Ihren Geräten
Comment[el]=Ειδοποιήσεις από τις συσκευές σας
Comment[en_GB]=Notifications from your devices
Comment[es]=Notificaciones de sus dispositivos
Comment[fi]=Laitteesi ilmoitukset
@ -63,6 +67,7 @@ Comment[zh_CN]=来自你设备的通知
[Event/pairingRequest]
Name=Pairing Request
Name[ar]=طلب اقتران
Name[ast]=Solicitú d'empareyamientu
Name[bg]=Заявка за сдвояване
Name[bs]=Zahtjev za uparivanje
@ -71,6 +76,7 @@ Name[ca@valencia]=Sol·licitud d'aparellament
Name[cs]=Požadavek na párování
Name[da]=Parringsanmodning
Name[de]=Verbindungsanfrage
Name[el]=Αίτημα σύζευξης
Name[en_GB]=Pairing Request
Name[es]=Petición de vinculación
Name[fi]=Paripyyntö
@ -91,39 +97,32 @@ Name[tr]=Eşleşme İsteği
Name[uk]=Запит щодо пов’язування
Name[x-test]=xxPairing Requestxx
Name[zh_CN]=配对请求
Comment=Pairing request received from a devices
Comment[ast]=Solicitú d'empareyamientu d'un preséu
Comment[bg]=Получена е заявка за сдвояване от устройство
Comment[bs]=Primljen zahtjev za uparivanje od uređaja
Comment=Pairing request received from a device
Comment[ar]=استُلم طلب اقتران من جهاز
Comment[ast]=Solicitú d'empareyamientu recibida d'un preséu
Comment[ca]=Les sol·licituds d'aparellament rebudes des d'un dispositiu
Comment[ca@valencia]=Les sol·licituds d'aparellament rebudes des d'un dispositiu
Comment[cs]=Požadavek na párování přijat ze zařízení
Comment[da]=Parringsanmodning modtaget fra en enhed
Comment[de]=Verbindungsanfrage von einem Gerät erhalten
Comment[en_GB]=Pairing request received from a devices
Comment[el]=Λήφθηκε αίτημα σύζευξης από μια συσκευή
Comment[en_GB]=Pairing request received from a device
Comment[es]=Petición de vinculación recibida desde un dispositivo
Comment[fi]=Saatiin paripyyntö laitteelta
Comment[fr]=Demande d'appariement provenant d'un périphérique
Comment[gl]=Recibiuse unha solicitude de emparellamento dun dispositivo.
Comment[hu]=Párosítási kérés érkezett egy eszköztől
Comment[it]=Richiesta di associazione ricevuta da un dispositivo
Comment[ko]=장치에서 연결 요청을 받음
Comment[nl]=Verzoek om een paar te maken ontvangen van een apparaat
Comment[nn]=Mottak parringsførespurnad frå eining
Comment[nl]=Verzoek om een paar te maken ontvangen van apparaten
Comment[pl]=Otrzymano żądanie parowania z urządzenia
Comment[pt]=Pedido de emparelhamento recebido de um dispositivo
Comment[pt_BR]=Solicitação de emparelhamento recebida de um dispositivo
Comment[ru]=От мобильного устройства получен запрос на сопряжение
Comment[sk]=Požiadavka na spárovanie prijatá zo zariadenia
Comment[sv]=Begäran om ihopparning mottagen från en apparat
Comment[tr]=Bir aygıttan eşleşme isteği alındı
Comment[uk]=Від пристрою отримано запит щодо пов’язування
Comment[x-test]=xxPairing request received from a devicesxx
Comment[zh_CN]=收到来自一个设备的配对请求
Comment[x-test]=xxPairing request received from a devicexx
Action=Popup
[Event/callReceived]
Name=Incoming Call
Name[ar]=مكالمة واردة
Name[ast]=Llamada entrante
Name[bg]=Входящо обаждане
Name[ca]=Trucada entrant
@ -131,6 +130,7 @@ Name[ca@valencia]=Trucada entrant
Name[cs]=Příchozí hovor
Name[da]=Indkommende opkald
Name[de]=Eingehender Anruf
Name[el]=Εισερχόμενη κλήση
Name[en_GB]=Incoming Call
Name[es]=Llamada entrante
Name[fi]=Saapuva puhelu
@ -152,6 +152,7 @@ Name[uk]=Вхідний дзвінок
Name[x-test]=xxIncoming Callxx
Name[zh_CN]=收到呼叫
Comment=Someone is calling you
Comment[ar]=ثمّة من يتّصل بك
Comment[ast]=Daquién ta llamándote
Comment[bg]=Някой ви се обажда
Comment[bs]=Neko Vas zove
@ -160,6 +161,7 @@ Comment[ca@valencia]=Algú vos està trucant
Comment[cs]=Někdo vám volá
Comment[da]=Nogen ringer til dig
Comment[de]=Sie werden angerufen
Comment[el]=Κάποιος σας καλεί
Comment[en_GB]=Someone is calling you
Comment[es]=Alguien le está llamando
Comment[fi]=Sinulle soitetaan
@ -185,6 +187,7 @@ Action=Popup
[Event/missedCall]
Name=Missed Call
Name[ar]=مكالمة فائتة
Name[ast]=Llamada perdida
Name[bg]=Пропуснато обаждане
Name[ca]=Trucada perduda
@ -192,6 +195,7 @@ Name[ca@valencia]=Trucada perduda
Name[cs]=Zmeškaný hovor
Name[da]=Ubesvaret opkald
Name[de]=Verpasster Anruf
Name[el]=Αναπάντητη κλήση
Name[en_GB]=Missed Call
Name[es]=Llamada perdida
Name[fi]=Vastaamaton puhelu
@ -213,6 +217,7 @@ Name[uk]=Пропущений дзвінок
Name[x-test]=xxMissed Callxx
Name[zh_CN]=未接来电
Comment=You have a missed call
Comment[ar]=لقد فاتتك مكالمة
Comment[ast]=Tienes una llamada perdida
Comment[bg]=Имате неприето обаждане
Comment[bs]=Imate propušten poziv
@ -221,6 +226,7 @@ Comment[ca@valencia]=Teniu una trucada perduda
Comment[cs]=Máte zmeškaný hovor
Comment[da]=Du har et ubesvaret opkald
Comment[de]=Sie haben einen Anruf verpasst
Comment[el]=Έχετε μια αναπάντητη κλήση
Comment[en_GB]=You have a missed call
Comment[es]=Tiene una llamada perdida
Comment[fi]=Sinulla on vastaamaton puhelu
@ -246,6 +252,7 @@ Action=Popup
[Event/smsReceived]
Name=SMS Received
Name[ar]=استُلمت رسالة
Name[ast]=SMS recibíu
Name[bg]=Получен SMS
Name[ca]=S'ha rebut un SMS
@ -253,6 +260,7 @@ Name[ca@valencia]=S'ha rebut un SMS
Name[cs]=SMS přijata
Name[da]=SMS-modtaget
Name[de]=SMS empfangen
Name[el]=Λήφθηκε SMS
Name[en_GB]=SMS Received
Name[es]=SMS recibido
Name[fi]=Saatiin tekstiviesti
@ -274,6 +282,7 @@ Name[uk]=Отримано SMS
Name[x-test]=xxSMS Receivedxx
Name[zh_CN]=收到短信
Comment=Someone sent you an SMS
Comment[ar]=ثمّة من أرسل رسالة إليك
Comment[ast]=Daquién unvióte un SMS
Comment[bg]=Някой ви изпрати текстово съобщение
Comment[bs]=Neko Vam je poslao SMS poruku
@ -282,6 +291,7 @@ Comment[ca@valencia]=Algú vos ha enviat un SMS
Comment[cs]=Někdo vám poslal SMS
Comment[da]=Nogen sendte dig en SMS
Comment[de]=Jemand hat Ihnen eine SMS gesendet
Comment[el]=Κάποιος σας έστειλε SMS
Comment[en_GB]=Someone sent you an SMS
Comment[es]=Alguien le ha enviado un SMS
Comment[fi]=Sinulle lähetettiin tekstiviesti
@ -307,6 +317,7 @@ Action=Popup
[Event/batteryLow]
Name=Battery Low
Name[ar]=البطّاريّة ضعيفة
Name[ast]=Batería baxa
Name[bg]=Изтощена батерия
Name[ca]=Bateria baixa
@ -314,6 +325,7 @@ Name[ca@valencia]=Bateria baixa
Name[cs]=Baterie je téměř vybitá
Name[da]=Lavt batteri
Name[de]=Akku-Ladestand niedrig
Name[el]=Μπαταρία χαμηλή
Name[en_GB]=Battery Low
Name[es]=Batería baja
Name[fi]=Akku vähissä
@ -335,6 +347,7 @@ Name[uk]=Низький рівень заряду
Name[x-test]=xxBattery Lowxx
Name[zh_CN]=电池电量低
Comment=Your battery is in low state
Comment[ar]=بطّاريّتك في الحالة الضعيفة
Comment[ast]=La to batería ta nun estáu baxu
Comment[bg]=Батерията ви е с нисък заряд
Comment[bs]=Vaša baterija je gotovo prazna
@ -343,6 +356,7 @@ Comment[ca@valencia]=La bateria està baixa
Comment[cs]=Máte slabou baterii
Comment[da]=Dit batteri er på lavt niveau
Comment[de]=Der Ladestand Ihres Akkus ist niedrig
Comment[el]=Η μπαταρία σας είναι σε χαμηλό επίπεδο
Comment[en_GB]=Your battery is in low state
Comment[es]=La batería está en nivel bajo
Comment[fi]=Akkusi virta on vähissä
@ -368,6 +382,7 @@ Action=Popup
[Event/pingReceived]
Name=Ping Received
Name[ar]=استُلمت وكزة
Name[ast]=Ping recibíu
Name[bg]=Пингът е приет
Name[ca]=S'ha rebut un ping
@ -375,6 +390,7 @@ Name[ca@valencia]=S'ha rebut un ping
Name[cs]=Ping přijat
Name[da]=Ping modtaget
Name[de]=Ping empfangen
Name[el]=Λήφθηκε ping
Name[en_GB]=Ping Received
Name[es]=Ping recibido
Name[fi]=Saatiin tiedustelupaketti
@ -396,6 +412,7 @@ Name[uk]=Отримано сигнал підтримки зв’язку
Name[x-test]=xxPing Receivedxx
Name[zh_CN]=收到 Ping
Comment=Ping received
Comment[ar]=استُلمت وكزة
Comment[ast]=Recibióse un ping
Comment[bg]=Пингът е приет
Comment[bs]=Primili ste ping
@ -404,6 +421,7 @@ Comment[ca@valencia]=S'ha rebut un ping
Comment[cs]=Ping přijat
Comment[da]=Ping modtaget
Comment[de]=Ping empfangen
Comment[el]=Λήφθηκε ping
Comment[en_GB]=Ping received
Comment[es]=Ping recibido
Comment[fi]=Saatiin tiedustelupaketti
@ -429,6 +447,7 @@ Action=Popup
[Event/notification]
Name=Generic Notification
Name[ar]=إخطار عموميّ
Name[ast]=Avisu xenéricu
Name[bg]=Общо уведомление
Name[ca]=Notificació genèrica
@ -436,6 +455,7 @@ Name[ca@valencia]=Notificació genèrica
Name[cs]=Obecná hlášení
Name[da]=Generisk bekendtgørelse
Name[de]=Allgemeine Benachrichtigung
Name[el]=Γενική ειδοποίηση
Name[en_GB]=Generic Notification
Name[es]=Notificación genérica
Name[fi]=Yleinen ilmoitus
@ -457,6 +477,7 @@ Name[uk]=Загальне сповіщення
Name[x-test]=xxGeneric Notificationxx
Name[zh_CN]=一般通知
Comment=Notification received
Comment[ar]=استُلم إخطار
Comment[ast]=Avisu recibíu
Comment[bg]=Уведомлението е прието
Comment[bs]=Primjeno obavještenje
@ -465,6 +486,7 @@ Comment[ca@valencia]=Notificació rebuda
Comment[cs]=Bylo přijato upozornění
Comment[da]=Bekendtgørelse modtaget
Comment[de]=Benachrichtigung eingegangen
Comment[el]=Λήφθηκε ειδοποίηση
Comment[en_GB]=Notification received
Comment[es]=Notificación recibida
Comment[fi]=Saatiin ilmoitus
@ -490,6 +512,7 @@ Action=Popup
[Event/transferReceived]
Name=File Transfer
Name[ar]=نقل الملفّات
Name[ast]=Tresferencia de ficheros
Name[bg]=Прехвърляне на файл
Name[ca]=Transferència de fitxers
@ -497,6 +520,7 @@ Name[ca@valencia]=Transferència de fitxers
Name[cs]=Přenos souboru
Name[da]=Filoverførsel
Name[de]=Dateiübertragung
Name[el]=Μεταφορά αρχείου
Name[en_GB]=File Transfer
Name[es]=Transferencia de archivo
Name[fi]=Tiedostonsiirto
@ -518,6 +542,7 @@ Name[uk]=Перенесення файлів
Name[x-test]=xxFile Transferxx
Name[zh_CN]=文件传送
Comment=Incoming file
Comment[ar]=ملفّ قادم
Comment[ast]=Ficheru entrante
Comment[bg]=Входящ файл
Comment[ca]=Fitxer entrant
@ -525,6 +550,7 @@ Comment[ca@valencia]=Fitxer entrant
Comment[cs]=Příchozí soubor
Comment[da]=Indkommende fil
Comment[de]=Eingehende Datei
Comment[el]=Εισερχόμενο αρχείο
Comment[en_GB]=Incoming file
Comment[es]=Archivo entrante
Comment[fi]=Saapuva tiedosto

View file

@ -3,6 +3,7 @@ Type=ServiceType
X-KDE-ServiceType=KdeConnect/Plugin
X-KDE-Derived=KPluginInfo
Name=KDEConnect Plugin
Name[ar]=ملحقة KDEConnect
Name[ast]=Complementu KDEConnect
Name[bg]=Приставка на KDEConnect
Name[bs]=Priključak za KDE konekciju
@ -11,6 +12,7 @@ Name[ca@valencia]=Connector del KDE Connect
Name[cs]=Modul KDEConnect
Name[da]=KDEConnect-plugin
Name[de]=KDEConnect-Modul
Name[el]=Πρόσθετο του KDEConnect
Name[en_GB]=KDEConnect Plugin
Name[es]=Complemento de KDEConnect
Name[fi]=KDE Connect -liitännäinen

View file

@ -36,6 +36,7 @@
"Id": "kdeconnect_lockdevice",
"License": "GPL",
"Name": "LockDevice",
"Name[ast]": "Bloquiar preséu",
"Name[ca@valencia]": "Bloqueja el dispositiu",
"Name[ca]": "Bloqueja el dispositiu",
"Name[cs]": "Uzamknout zařízení",

View file

@ -37,6 +37,7 @@
"Id": "kdeconnect_mpriscontrol",
"License": "GPL",
"Name": "Multimedia control receiver",
"Name[ast]": "Mandu de control multimedia",
"Name[ca@valencia]": "Receptor del comandament multimèdia",
"Name[ca]": "Receptor del comandament multimèdia",
"Name[cs]": "Dálkový ovladač multimédií",

View file

@ -44,27 +44,31 @@ MprisControlPlugin::MprisControlPlugin(QObject* parent, const QVariantList& args
{
m_watcher = new QDBusServiceWatcher(QString(), QDBusConnection::sessionBus(), QDBusServiceWatcher::WatchForOwnerChange, this);
connect(m_watcher, &QDBusServiceWatcher::serviceRegistered, this, &MprisControlPlugin::addService);
connect(m_watcher, &QDBusServiceWatcher::serviceUnregistered, this, &MprisControlPlugin::removeService);
// TODO: QDBusConnectionInterface::serviceOwnerChanged is deprecated, maybe query org.freedesktop.DBus directly?
connect(QDBusConnection::sessionBus().interface(), &QDBusConnectionInterface::serviceOwnerChanged, this, &MprisControlPlugin::serviceOwnerChanged);
//Add existing interfaces
QStringList services = QDBusConnection::sessionBus().interface()->registeredServiceNames().value();
Q_FOREACH (const QString& service, services) {
addService(service);
// The string doesn't matter, it just needs to be empty/non-empty
serviceOwnerChanged(service, QLatin1String(""), QLatin1String("1"));
}
}
void MprisControlPlugin::addService(const QString& service)
// Copied from the mpris2 dataengine in the plasma-workspace repository
void MprisControlPlugin::serviceOwnerChanged(const QString& serviceName, const QString& oldOwner, const QString& newOwner)
{
if (service.startsWith(QLatin1String("org.mpris.MediaPlayer2"))) {
addPlayer(service);
}
if (!serviceName.startsWith(QLatin1String("org.mpris.MediaPlayer2.")))
return;
if (!oldOwner.isEmpty()) {
qCDebug(KDECONNECT_PLUGIN_MPRIS) << "MPRIS service" << serviceName << "just went offline";
removePlayer(serviceName);
}
void MprisControlPlugin::removeService(const QString& service)
{
if (service.startsWith(QLatin1String("org.mpris.MediaPlayer2"))) {
removePlayer(service);
if (!newOwner.isEmpty()) {
qCDebug(KDECONNECT_PLUGIN_MPRIS) << "MPRIS service" << serviceName << "just came online";
addPlayer(serviceName);
}
}

View file

@ -49,9 +49,7 @@ private Q_SLOTS:
void seeked(qlonglong);
private:
void addService(const QString& service);
void removeService(const QString& service);
void serviceOwnerChanged(const QString& serviceName, const QString& oldOwner, const QString& newOwner);
void addPlayer(const QString& ifaceName);
void removePlayer(const QString& ifaceName);
void sendPlayerList();

View file

@ -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
)
#######################################

View file

@ -6,8 +6,13 @@ X-KDE-Library=kdeconnect_notifications_config
X-KDE-ParentComponents=kdeconnect_notifications
Name=Notification synchronization plugin settings
Name[ca]=Ajustament del connector per a la sincronització de les notificacions
Name[ca@valencia]=Ajustament del connector per a la sincronització de les notificacions
Name[ar]=إعدادات ملحقة مزامنة الإخطارات
Name[ast]=Axustes del complementu de sincronización d'avisos
Name[ca]=Ajustament del connector Sincronitza les notificacions
Name[ca@valencia]=Ajustament del connector Sincronitza les notificacions
Name[cs]=Nastavení modulu synchronizace upozornění
Name[de]=Einstellungen für Benachrichtigungsabgleich-Modul
Name[el]=Ρυθμίσεις πρόσθετου συγχρονισμού ειδοποιήσεων
Name[en_GB]=Notification synchronisation plugin settings
Name[es]=Preferencias del complemento de sincronización de notificaciones
Name[fi]=Ilmoitusten synkronointiliitännäisen asetukset

View file

@ -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;

View file

@ -80,6 +80,22 @@
</property>
</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">

View file

@ -51,6 +51,8 @@ NotificationsDbusInterface::~NotificationsDbusInterface()
void NotificationsDbusInterface::clearNotifications()
{
qDeleteAll(mNotifications);
mNotifications.clear();
Q_EMIT allNotificationsRemoved();
}
QStringList NotificationsDbusInterface::activeNotifications()

View file

@ -53,6 +53,7 @@ public Q_SLOTS:
Q_SIGNALS:
Q_SCRIPTABLE void notificationPosted(const QString& publicId);
Q_SCRIPTABLE void notificationRemoved(const QString& publicId);
Q_SCRIPTABLE void allNotificationsRemoved();
private /*methods*/:
void removeNotification(const QString& internalId);

View file

@ -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);

View file

@ -9,7 +9,7 @@
}
],
"Description": "Pause music/videos during a phone call",
"Description[ast]": "Posa música/videos nuna llamada telefónica",
"Description[ast]": "Posa la música/videos nuna llamada telefónica",
"Description[ca@valencia]": "Pausa la música/vídeos durant una trucada telefònica",
"Description[ca]": "Pausa la música/vídeos durant una trucada telefònica",
"Description[cs]": "Pozastavit hudbu/video během telefonátu",

View file

@ -6,6 +6,7 @@ X-KDE-Library=kdeconnect_pausemusic_config
X-KDE-ParentComponents=kdeconnect_pausemusic
Name=Pause Music plugin settings
Name[ar]=إعدادات ملحقة إلباث الموسيقى
Name[ast]=Axustes del complementu de posar música
Name[bg]=Настройки на приставката за поставяне на пауза
Name[bs]=Zaustavi Muziku postavke dodatka
@ -14,6 +15,7 @@ Name[ca@valencia]=Ajustaments del connector Pausa la música
Name[cs]=Nastavení modulu Pozastavení hudby
Name[da]=Indstilling af plugin til at sætte musik på pause
Name[de]=Modul-Einstellungen für das Anhalten der Musikwiedergabe
Name[el]=Ρυθμίσεις προσθέτου παύσης μουσικής
Name[en_GB]=Pause Music plugin settings
Name[es]=Ajustes del complemento PauseMusic
Name[fi]=Keskeytä musiikki -liitännäisen asetukset

View file

@ -36,6 +36,7 @@
"Id": "kdeconnect_remotecontrol",
"License": "GPL",
"Name": "RemoteControl",
"Name[ast]": "Control remotu",
"Name[ca@valencia]": "Control remot",
"Name[ca]": "Control remot",
"Name[cs]": "Dálkové ovládání",

View file

@ -18,6 +18,7 @@
"Description[ca@valencia]": "Executa ordes de la consola de forma remota",
"Description[ca]": "Executa ordres de la consola de forma remota",
"Description[cs]": "Spouštět konzolové příkazy vzdáleně",
"Description[de]": "Entfernte Konsolenbefehle ausführen",
"Description[es]": "Ejecute órdenes de consola remotamente",
"Description[fi]": "Suorita konsolikomentoja etänä",
"Description[gl]": "Executar ordes de consola remotamente.",

View file

@ -6,12 +6,14 @@ X-KDE-Library=kdeconnect_runcommand_config
X-KDE-ParentComponents=kdeconnect_runcommand
Name=Run Command plugin settings
Name[ar]=إعدادات ملحقة تشغيل الأوامر
Name[ast]=Axustes del complementu d'executar comandos
Name[ca]=Ajustaments del connector Executa ordres
Name[ca@valencia]=Ajustaments del connector Executa ordes
Name[cs]=Nastavení modulu Spustit příkaz
Name[da]=Indstilling af kør kommando-plugin
Name[de]=Modul-Einstellungen für Befehlsausführung
Name[el]=Ρυθμίσεις προσθέτου εκτέλεσης εντολής
Name[en_GB]=Run Command plugin settings
Name[es]=Ajustes del complemento de ejecución de órdenes
Name[fi]=Suorita komento -liitännäisen asetukset

View file

@ -24,7 +24,7 @@
"Description[nn]": "Hindra pauseskjermen i å starta når eininga er kopla til",
"Description[pl]": "Powstrzymaj wygaszacz ekrany po podłączeniu urządzenia",
"Description[pt]": "Inibir o protector de ecrã quando o dispositivo estiver ligado",
"Description[pt_BR]": "Inibir o protetor de tela quando o dispositivo estiver conectado",
"Description[pt_BR]": "Inibe o protetor de tela quando o dispositivo estiver conectado",
"Description[ru]": "Предотвращение запуска блокировщика экрана, когда устройство подключено",
"Description[sk]": "Obmedziť šetrič obrazovky keď je pripojené zariadenie",
"Description[sv]": "Stoppa skärmsläckaren när apparaten ansluts",

View file

@ -6,6 +6,7 @@ X-KDE-Library=kdeconnect_share_config
X-KDE-ParentComponents=kdeconnect_share
Name=Share plugin settings
Name[ar]=إعدادات ملحقة المشاركة
Name[ast]=Axustes del complementu de compartir
Name[bg]=Настройки на приставката за споделяне
Name[bs]=Podijeli postavke dodatka
@ -14,6 +15,7 @@ Name[ca@valencia]=Ajustaments del connector Compartició
Name[cs]=Nastavení modulu sdílení
Name[da]=Indstilling af deling-plugin
Name[de]=Modul-Einstellungen für Veröffentlichung
Name[el]=Ρυθμίσεις προσθέτου κοινής χρήσης
Name[en_GB]=Share plugin settings
Name[es]=Ajustes del complemento para compartir
Name[fi]=Jakoliitännäisen asetukset

View file

@ -47,6 +47,7 @@ KNotification* TelephonyPlugin::createNotification(const NetworkPackage& np)
const QString event = np.get<QString>("event");
const QString phoneNumber = np.get<QString>("phoneNumber", i18n("unknown number"));
const QString contactName = np.get<QString>("contactName", phoneNumber);
const QByteArray phoneThumbnail = QByteArray::fromBase64(np.get<QByteArray>("phoneThumbnail", ""));
QString content, type, icon;
KNotification::NotificationFlags flags = KNotification::CloseOnTimeout | KNotification::CloseWhenWidgetActivated;
@ -83,7 +84,13 @@ KNotification* TelephonyPlugin::createNotification(const NetworkPackage& np)
qCDebug(KDECONNECT_PLUGIN_TELEPHONY) << "Creating notification with type:" << type;
KNotification* notification = new KNotification(type, flags, this);
if (!phoneThumbnail.isEmpty()) {
QPixmap photo;
photo.loadFromData(phoneThumbnail, "JPEG");
notification->setPixmap(photo);
} else {
notification->setIconName(icon);
}
notification->setComponentName("kdeconnect");
notification->setTitle(title);
notification->setText(content);

View file

@ -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}
@ -63,4 +63,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)

View file

@ -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);
}
}