diff --git a/interfaces/notificationsmodel.cpp b/interfaces/notificationsmodel.cpp index 16fbcd3b..2a6a24c2 100644 --- a/interfaces/notificationsmodel.cpp +++ b/interfaces/notificationsmodel.cpp @@ -1,274 +1,271 @@ /** * Copyright 2013 Albert Vaca * * 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 . */ #include "notificationsmodel.h" #include "interfaces_debug.h" #include #include #include #include //#include "modeltest.h" //In older Qt released, qAsConst isnt available #include "core/qtcompat_p.h" NotificationsModel::NotificationsModel(QObject* parent) : QAbstractListModel(parent) , m_dbusInterface(nullptr) { //new ModelTest(this, this); connect(this, &QAbstractItemModel::rowsInserted, this, &NotificationsModel::rowsChanged); connect(this, &QAbstractItemModel::rowsRemoved, this, &NotificationsModel::rowsChanged); connect(this, &QAbstractItemModel::dataChanged, this, &NotificationsModel::anyDismissableChanged); connect(this, &QAbstractItemModel::rowsInserted, this, &NotificationsModel::anyDismissableChanged); QDBusServiceWatcher* watcher = new QDBusServiceWatcher(DaemonDbusInterface::activatedService(), QDBusConnection::sessionBus(), QDBusServiceWatcher::WatchForOwnerChange, this); connect(watcher, &QDBusServiceWatcher::serviceRegistered, this, &NotificationsModel::refreshNotificationList); connect(watcher, &QDBusServiceWatcher::serviceUnregistered, this, &NotificationsModel::clearNotifications); } QHash NotificationsModel::roleNames() const { //Role names for QML QHash names = QAbstractItemModel::roleNames(); names.insert(DbusInterfaceRole, "dbusInterface"); names.insert(AppNameModelRole, "appName"); names.insert(IdModelRole, "notificationId"); names.insert(DismissableModelRole, "dismissable"); names.insert(RepliableModelRole, "repliable"); names.insert(IconPathModelRole, "appIcon"); names.insert(TitleModelRole, "title"); names.insert(TextModelRole, "notitext"); return names; } NotificationsModel::~NotificationsModel() { } QString NotificationsModel::deviceId() const { return m_deviceId; } void NotificationsModel::setDeviceId(const QString& deviceId) { m_deviceId = deviceId; if (m_dbusInterface) { delete m_dbusInterface; } m_dbusInterface = new DeviceNotificationsDbusInterface(deviceId, this); connect(m_dbusInterface, &OrgKdeKdeconnectDeviceNotificationsInterface::notificationPosted, this, &NotificationsModel::notificationAdded); connect(m_dbusInterface, &OrgKdeKdeconnectDeviceNotificationsInterface::notificationRemoved, this, &NotificationsModel::notificationRemoved); connect(m_dbusInterface, &OrgKdeKdeconnectDeviceNotificationsInterface::allNotificationsRemoved, this, &NotificationsModel::clearNotifications); - connect(m_dbusInterface, &OrgKdeKdeconnectDeviceNotificationsInterface::notificationUpdated, - this, &NotificationsModel::notificationUpdated); refreshNotificationList(); Q_EMIT deviceIdChanged(deviceId); } void NotificationsModel::notificationAdded(const QString& id) { beginInsertRows(QModelIndex(), 0, 0); NotificationDbusInterface* dbusInterface = new NotificationDbusInterface(m_deviceId, id, this); + connect(dbusInterface, &NotificationDbusInterface::ready, this, &NotificationsModel::notificationUpdated); m_notificationList.prepend(dbusInterface); endInsertRows(); } void NotificationsModel::notificationRemoved(const QString& id) { 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() { if (!m_dbusInterface) { return; } clearNotifications(); if (!m_dbusInterface->isValid()) { qCWarning(KDECONNECT_INTERFACES) << "dbus interface not valid"; return; } QDBusPendingReply pendingNotificationIds = m_dbusInterface->activeNotifications(); QDBusPendingCallWatcher* watcher = new QDBusPendingCallWatcher(pendingNotificationIds, this); QObject::connect(watcher, &QDBusPendingCallWatcher::finished, this, &NotificationsModel::receivedNotifications); } void NotificationsModel::receivedNotifications(QDBusPendingCallWatcher* watcher) { watcher->deleteLater(); clearNotifications(); QDBusPendingReply pendingNotificationIds = *watcher; if (pendingNotificationIds.isError()) { qCWarning(KDECONNECT_INTERFACES) << pendingNotificationIds.error(); return; } const QStringList notificationIds = pendingNotificationIds.value(); if (notificationIds.isEmpty()) { return; } beginInsertRows(QModelIndex(), 0, notificationIds.size() - 1); for (const QString& notificationId : notificationIds) { NotificationDbusInterface* dbusInterface = new NotificationDbusInterface(m_deviceId, notificationId, this); m_notificationList.append(dbusInterface); } endInsertRows(); } QVariant NotificationsModel::data(const QModelIndex& index, int role) const { if (!index.isValid() || index.row() < 0 || index.row() >= m_notificationList.count() || !m_notificationList[index.row()]->isValid()) { return QVariant(); } if (!m_dbusInterface || !m_dbusInterface->isValid()) { return QVariant(); } NotificationDbusInterface* notification = m_notificationList[index.row()]; //FIXME: This function gets called lots of times, producing lots of dbus calls. Add a cache? switch (role) { case IconModelRole: return QIcon::fromTheme(QStringLiteral("device-notifier")); case IdModelRole: return notification->internalId(); case NameModelRole: return notification->ticker(); case ContentModelRole: return QString(); //To implement in the Android side case AppNameModelRole: return notification->appName(); case DbusInterfaceRole: return qVariantFromValue(notification); case DismissableModelRole: return notification->dismissable(); case RepliableModelRole: return !notification->replyId().isEmpty(); case IconPathModelRole: return notification->iconPath(); case TitleModelRole: return notification->title(); case TextModelRole: return notification->text(); default: return QVariant(); } } NotificationDbusInterface* NotificationsModel::getNotification(const QModelIndex& index) const { if (!index.isValid()) { return nullptr; } int row = index.row(); if (row < 0 || row >= m_notificationList.size()) { return nullptr; } return m_notificationList[row]; } int NotificationsModel::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_notificationList.count(); } bool NotificationsModel::isAnyDimissable() const { for (NotificationDbusInterface* notification : qAsConst(m_notificationList)) { if (notification->dismissable()) { return true; } } return false; } void NotificationsModel::dismissAll() { for (NotificationDbusInterface* notification : qAsConst(m_notificationList)) { if (notification->dismissable()) { notification->dismiss(); } } } void NotificationsModel::clearNotifications() { if (!m_notificationList.isEmpty()) { beginRemoveRows(QModelIndex(), 0, m_notificationList.size() - 1); qDeleteAll(m_notificationList); m_notificationList.clear(); endRemoveRows(); } } -void NotificationsModel::notificationUpdated(const QString& id) +void NotificationsModel::notificationUpdated() { - //TODO only emit the affected indices - Q_UNUSED(id); Q_EMIT dataChanged(index(0,0), index(m_notificationList.size() - 1, 0)); } diff --git a/interfaces/notificationsmodel.h b/interfaces/notificationsmodel.h index a1bf24b6..9da5830c 100644 --- a/interfaces/notificationsmodel.h +++ b/interfaces/notificationsmodel.h @@ -1,90 +1,90 @@ /** * Copyright 2013 Albert Vaca * * 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 . */ #ifndef NOTIFICATIONSMODEL_H #define NOTIFICATIONSMODEL_H #include #include #include #include #include "interfaces/dbusinterfaces.h" class KDECONNECTINTERFACES_EXPORT NotificationsModel : public QAbstractListModel { Q_OBJECT Q_PROPERTY(QString deviceId READ deviceId WRITE setDeviceId NOTIFY deviceIdChanged) Q_PROPERTY(int count READ rowCount NOTIFY rowsChanged) Q_PROPERTY(bool isAnyDimissable READ isAnyDimissable NOTIFY anyDismissableChanged STORED false) public: enum ModelRoles { IconModelRole = Qt::DecorationRole, NameModelRole = Qt::DisplayRole, ContentModelRole = Qt::UserRole, AppNameModelRole = Qt::UserRole + 1, IdModelRole, DismissableModelRole, RepliableModelRole, IconPathModelRole, DbusInterfaceRole, TitleModelRole, TextModelRole }; explicit NotificationsModel(QObject* parent = nullptr); ~NotificationsModel() override; QString deviceId() const; void setDeviceId(const QString& deviceId); QVariant data(const QModelIndex& index, int role) const override; int rowCount(const QModelIndex& parent = QModelIndex()) const override; NotificationDbusInterface* getNotification(const QModelIndex& index) const; Q_INVOKABLE bool isAnyDimissable() const; QHash roleNames() const override; public Q_SLOTS: void dismissAll(); private Q_SLOTS: void notificationAdded(const QString& id); void notificationRemoved(const QString& id); - void notificationUpdated(const QString& id); + void notificationUpdated(); void refreshNotificationList(); void receivedNotifications(QDBusPendingCallWatcher* watcher); void clearNotifications(); Q_SIGNALS: void deviceIdChanged(const QString& value); void anyDismissableChanged(); void rowsChanged(); private: DeviceNotificationsDbusInterface* m_dbusInterface; QList m_notificationList; QString m_deviceId; }; #endif // DEVICESMODEL_H diff --git a/plugins/notifications/notification.cpp b/plugins/notifications/notification.cpp index fcd73cd3..4f498c9c 100644 --- a/plugins/notifications/notification.cpp +++ b/plugins/notifications/notification.cpp @@ -1,191 +1,182 @@ /** * Copyright 2013 Albert Vaca * * 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 . */ #include "notification.h" #include "notification_debug.h" #include #include #include #include #include #include #include #include QMap Notification::s_downloadsInProgress; Notification::Notification(const NetworkPacket& np, QObject* parent) : QObject(parent) { //Make a own directory for each user so noone can see each others icons QString username; #ifdef Q_OS_WIN username = qgetenv("USERNAME"); #else username = qgetenv("USER"); #endif m_imagesDir = QDir::temp().absoluteFilePath(QStringLiteral("kdeconnect_") + username); m_imagesDir.mkpath(m_imagesDir.absolutePath()); QFile(m_imagesDir.absolutePath()).setPermissions(QFileDevice::ReadOwner | QFileDevice::WriteOwner | QFileDevice::ExeOwner); - m_closed = false; m_ready = false; parseNetworkPacket(np); - createKNotification(false, np); + createKNotification(np); } Notification::~Notification() { } void Notification::dismiss() { if (m_dismissable) { Q_EMIT dismissRequested(m_internalId); } } void Notification::show() { m_ready = true; Q_EMIT ready(); if (!m_silent) { - m_closed = false; m_notification->sendEvent(); } } void Notification::update(const NetworkPacket& np) { parseNetworkPacket(np); - createKNotification(!m_closed, np); + createKNotification(np); } -KNotification* Notification::createKNotification(bool update, const NetworkPacket& np) +KNotification* Notification::createKNotification(const NetworkPacket& np) { - if (!update) { + if (!m_notification) { m_notification = new KNotification(QStringLiteral("notification"), KNotification::CloseOnTimeout, this); m_notification->setComponentName(QStringLiteral("kdeconnect")); } QString escapedTitle = m_title.toHtmlEscaped(); QString escapedText = m_text.toHtmlEscaped(); QString escapedTicker = m_ticker.toHtmlEscaped(); m_notification->setTitle(m_appName.toHtmlEscaped()); if (m_title.isEmpty() && m_text.isEmpty()) { m_notification->setText(escapedTicker); } else if (m_appName==m_title) { m_notification->setText(escapedText); } else if (m_title.isEmpty()){ m_notification->setText(escapedText); } else if (m_text.isEmpty()){ m_notification->setText(escapedTitle); } else { m_notification->setText(escapedTitle+": "+escapedText); } m_hasIcon = m_hasIcon && !m_payloadHash.isEmpty(); if (!m_hasIcon) { applyNoIcon(); show(); } else { m_iconPath = m_imagesDir.absoluteFilePath(m_payloadHash); loadIcon(np); } if (!m_requestReplyId.isEmpty()) { m_notification->setActions(QStringList(i18n("Reply"))); connect(m_notification, &KNotification::action1Activated, this, &Notification::reply); } - connect(m_notification, &KNotification::closed, this, &Notification::closed); - return m_notification; } void Notification::loadIcon(const NetworkPacket& np) { m_ready = false; if (QFileInfo::exists(m_iconPath)) { applyIcon(); show(); } else { FileTransferJob* fileTransferJob = s_downloadsInProgress.value(m_iconPath); if (!fileTransferJob) { fileTransferJob = np.createPayloadTransferJob(QUrl::fromLocalFile(m_iconPath)); fileTransferJob->start(); s_downloadsInProgress[m_iconPath] = fileTransferJob; } connect(fileTransferJob, &FileTransferJob::result, this, [this, fileTransferJob]{ s_downloadsInProgress.remove(m_iconPath); if (fileTransferJob->error()) { qCDebug(KDECONNECT_PLUGIN_NOTIFICATION) << "Error in FileTransferJob: " << fileTransferJob->errorString(); applyNoIcon(); } else { applyIcon(); } show(); }); } } void Notification::applyIcon() { QPixmap icon(m_iconPath, "PNG"); m_notification->setPixmap(icon); } void Notification::applyNoIcon() { //HACK The only way to display no icon at all is trying to load a non-existent icon m_notification->setIconName(QStringLiteral("not_a_real_icon")); } void Notification::reply() { Q_EMIT replyRequested(); } -void Notification::closed() -{ - m_closed = true; -} - void Notification::parseNetworkPacket(const NetworkPacket& np) { m_internalId = np.get(QStringLiteral("id")); m_appName = np.get(QStringLiteral("appName")); m_ticker = np.get(QStringLiteral("ticker")); m_title = np.get(QStringLiteral("title")); m_text = np.get(QStringLiteral("text")); m_dismissable = np.get(QStringLiteral("isClearable")); m_hasIcon = np.hasPayload(); m_silent = np.get(QStringLiteral("silent")); m_payloadHash = np.get(QStringLiteral("payloadHash")); m_requestReplyId = np.get(QStringLiteral("requestReplyId"), QString()); } diff --git a/plugins/notifications/notification.h b/plugins/notifications/notification.h index b902334f..44b212dd 100644 --- a/plugins/notifications/notification.h +++ b/plugins/notifications/notification.h @@ -1,102 +1,100 @@ /** * Copyright 2013 Albert Vaca * * 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 . */ #ifndef NOTIFICATION_H #define NOTIFICATION_H #include #include #include #include #include #include class Notification : public QObject { Q_OBJECT Q_CLASSINFO("D-Bus Interface", "org.kde.kdeconnect.device.notifications.notification") Q_PROPERTY(QString internalId READ internalId) Q_PROPERTY(QString appName READ appName) Q_PROPERTY(QString ticker READ ticker) Q_PROPERTY(QString title READ title) Q_PROPERTY(QString text READ text) Q_PROPERTY(QString iconPath READ iconPath) Q_PROPERTY(bool dismissable READ dismissable) Q_PROPERTY(bool hasIcon READ hasIcon) Q_PROPERTY(bool silent READ silent) Q_PROPERTY(QString replyId READ replyId) public: Notification(const NetworkPacket& np, QObject* parent); ~Notification() override; QString internalId() const { return m_internalId; } QString appName() const { return m_appName; } QString ticker() const { return m_ticker; } QString title() const { return m_title; } QString text() const { return m_text; } QString iconPath() const { return m_iconPath; } bool dismissable() const { return m_dismissable; } QString replyId() const { return m_requestReplyId; } bool hasIcon() const { return m_hasIcon; } void show(); bool silent() const { return m_silent; } void update(const NetworkPacket& np); bool isReady() const { return m_ready; } - KNotification* createKNotification(bool update, const NetworkPacket& np); + KNotification* createKNotification(const NetworkPacket& np); public Q_SLOTS: Q_SCRIPTABLE void dismiss(); Q_SCRIPTABLE void reply(); - void closed(); Q_SIGNALS: void dismissRequested(const QString& m_internalId); void replyRequested(); - void ready(); + Q_SCRIPTABLE void ready(); private: QString m_internalId; QString m_appName; QString m_ticker; QString m_title; QString m_text; QString m_iconPath; QString m_requestReplyId; bool m_dismissable; bool m_hasIcon; - KNotification* m_notification; + QPointer m_notification; QDir m_imagesDir; bool m_silent; - bool m_closed; QString m_payloadHash; bool m_ready; void parseNetworkPacket(const NetworkPacket& np); void loadIcon(const NetworkPacket& np); void applyIcon(); void applyNoIcon(); static QMap s_downloadsInProgress; }; #endif diff --git a/plugins/notifications/notificationsdbusinterface.cpp b/plugins/notifications/notificationsdbusinterface.cpp index 68304323..41714979 100644 --- a/plugins/notifications/notificationsdbusinterface.cpp +++ b/plugins/notifications/notificationsdbusinterface.cpp @@ -1,192 +1,183 @@ /** * Copyright 2013 Albert Vaca * * 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 . */ #include "notificationsdbusinterface.h" #include "notification_debug.h" #include "notification.h" #include #include #include #include "notificationsplugin.h" #include "sendreplydialog.h" //In older Qt released, qAsConst isnt available #include "qtcompat_p.h" NotificationsDbusInterface::NotificationsDbusInterface(KdeConnectPlugin* plugin) : QDBusAbstractAdaptor(const_cast(plugin->device())) , m_device(plugin->device()) , m_plugin(plugin) , m_lastId(0) { } NotificationsDbusInterface::~NotificationsDbusInterface() { qCDebug(KDECONNECT_PLUGIN_NOTIFICATION) << "Destroying NotificationsDbusInterface"; } void NotificationsDbusInterface::clearNotifications() { qDeleteAll(m_notifications); m_notifications.clear(); Q_EMIT allNotificationsRemoved(); } QStringList NotificationsDbusInterface::activeNotifications() { return m_notifications.keys(); } void NotificationsDbusInterface::notificationReady() { Notification* noti = static_cast(sender()); disconnect(noti, &Notification::ready, this, &NotificationsDbusInterface::notificationReady); addNotification(noti); } void NotificationsDbusInterface::processPacket(const NetworkPacket& np) { if (np.get(QStringLiteral("isCancel"))) { QString id = np.get(QStringLiteral("id")); // cut off kdeconnect-android's prefix if there: if (id.startsWith(QLatin1String("org.kde.kdeconnect_tp::"))) id = id.mid(id.indexOf(QLatin1String("::")) + 2); removeNotification(id); - } else { - QString id = np.get(QStringLiteral("id")); + return; + } - if (!m_internalIdToPublicId.contains(id)) { - Notification* noti = new Notification(np, this); + QString id = np.get(QStringLiteral("id")); - if (noti->isReady()) { - addNotification(noti); - } else { - connect(noti, &Notification::ready, this, &NotificationsDbusInterface::notificationReady); - } + Notification* noti = nullptr; + + if (!m_internalIdToPublicId.contains(id)) { + noti = new Notification(np, this); + + if (noti->isReady()) { + addNotification(noti); } else { - QString pubId = m_internalIdToPublicId.value(id); - Notification* noti = m_notifications.value(pubId); - if (!noti) - return; - - noti->update(np); - - if (noti->isReady()) { - Q_EMIT notificationUpdated(pubId); - } else { - connect(noti, &Notification::ready, this, [this, pubId]{ - Q_EMIT notificationUpdated(pubId); - }); - } + connect(noti, &Notification::ready, this, &NotificationsDbusInterface::notificationReady); } - + } else { + QString pubId = m_internalIdToPublicId.value(id); + noti = m_notifications.value(pubId); } + noti->update(np); } void NotificationsDbusInterface::addNotification(Notification* noti) { const QString& internalId = noti->internalId(); if (m_internalIdToPublicId.contains(internalId)) { removeNotification(internalId); } //qCDebug(KDECONNECT_PLUGIN_NOTIFICATION) << "addNotification" << internalId; connect(noti, &Notification::dismissRequested, this, &NotificationsDbusInterface::dismissRequested); connect(noti, &Notification::replyRequested, this, [this,noti]{ replyRequested(noti); }); const QString& publicId = newId(); m_notifications[publicId] = noti; m_internalIdToPublicId[internalId] = publicId; QDBusConnection::sessionBus().registerObject(m_device->dbusPath()+"/notifications/"+publicId, noti, QDBusConnection::ExportScriptableContents); Q_EMIT notificationPosted(publicId); } void NotificationsDbusInterface::removeNotification(const QString& internalId) { //qCDebug(KDECONNECT_PLUGIN_NOTIFICATION) << "removeNotification" << internalId; if (!m_internalIdToPublicId.contains(internalId)) { qCDebug(KDECONNECT_PLUGIN_NOTIFICATION) << "Not found noti by internal Id: " << internalId; return; } QString publicId = m_internalIdToPublicId.take(internalId); Notification* noti = m_notifications.take(publicId); if (!noti) { qCDebug(KDECONNECT_PLUGIN_NOTIFICATION) << "Not found noti by public Id: " << publicId; return; } //Deleting the notification will unregister it automatically //QDBusConnection::sessionBus().unregisterObject(mDevice->dbusPath()+"/notifications/"+publicId); noti->deleteLater(); Q_EMIT notificationRemoved(publicId); } void NotificationsDbusInterface::dismissRequested(const QString& internalId) { NetworkPacket np(PACKET_TYPE_NOTIFICATION_REQUEST); np.set(QStringLiteral("cancel"), internalId); m_plugin->sendPacket(np); //Workaround: we erase notifications without waiting a response from the //phone because we won't receive a response if we are out of sync and this //notification no longer exists. Ideally, each time we reach the phone //after some time disconnected we should re-sync all the notifications. removeNotification(internalId); } void NotificationsDbusInterface::replyRequested(Notification* noti) { QString replyId = noti->replyId(); QString appName = noti->appName(); QString originalMessage = noti->ticker(); SendReplyDialog* dialog = new SendReplyDialog(originalMessage, replyId, appName); connect(dialog, &SendReplyDialog::sendReply, this, &NotificationsDbusInterface::sendReply); dialog->show(); dialog->raise(); } void NotificationsDbusInterface::sendReply(const QString& replyId, const QString& message) { NetworkPacket np(PACKET_TYPE_NOTIFICATION_REPLY); np.set(QStringLiteral("requestReplyId"), replyId); np.set(QStringLiteral("message"), message); m_plugin->sendPacket(np); } QString NotificationsDbusInterface::newId() { return QString::number(++m_lastId); }