diff --git a/plugins/notifications/notification.h b/plugins/notifications/notification.h --- a/plugins/notifications/notification.h +++ b/plugins/notifications/notification.h @@ -60,17 +60,18 @@ void show(); bool silent() const { return m_silent; } void update(const NetworkPackage& np); + bool isReady() const { return m_ready; } KNotification* createKNotification(bool update, const NetworkPackage& np); public Q_SLOTS: Q_SCRIPTABLE void dismiss(); - Q_SCRIPTABLE void applyIconAndShow(); Q_SCRIPTABLE void reply(); void closed(); Q_SIGNALS: void dismissRequested(const QString& m_internalId); void replyRequested(); + void ready(); private: QString m_internalId; @@ -87,8 +88,12 @@ bool m_silent; bool m_closed; QString m_payloadHash; + bool m_ready; void parseNetworkPackage(const NetworkPackage& np); + void loadIcon(const NetworkPackage& np); + void applyIcon(); + void applyNoIcon(); }; #endif diff --git a/plugins/notifications/notification.cpp b/plugins/notifications/notification.cpp --- a/plugins/notifications/notification.cpp +++ b/plugins/notifications/notification.cpp @@ -19,6 +19,7 @@ */ #include "notification.h" +#include "notification_debug.h" #include #include @@ -36,6 +37,7 @@ m_imagesDir = QDir::temp().absoluteFilePath(QStringLiteral("kdeconnect")); m_imagesDir.mkpath(m_imagesDir.absolutePath()); m_closed = false; + m_ready = false; parseNetworkPackage(np); createKNotification(false, np); @@ -55,21 +57,14 @@ void Notification::show() { + m_ready = true; + Q_EMIT ready(); if (!m_silent) { m_closed = false; m_notification->sendEvent(); } } -void Notification::applyIconAndShow() -{ - if (!m_silent) { - QPixmap icon(m_iconPath, "PNG"); - m_notification->setPixmap(icon); - show(); - } -} - void Notification::update(const NetworkPackage& np) { parseNetworkPackage(np); @@ -101,26 +96,25 @@ m_notification->setText(escapedTitle+": "+escapedText); } + m_hasIcon = m_hasIcon && !m_payloadHash.isEmpty(); + if (!m_hasIcon) { - //HACK The only way to display no icon at all is trying to load a non-existant icon - m_notification->setIconName(QString("not_a_real_icon")); + applyNoIcon(); show(); } else { - QString filename = m_payloadHash; - if (filename.isEmpty()) { - m_hasIcon = false; + m_iconPath = m_imagesDir.absoluteFilePath(m_payloadHash); + + if (!QFile::exists(m_iconPath)) { + loadIcon(np); } else { - m_iconPath = m_imagesDir.absoluteFilePath(filename); - QUrl destinationUrl(m_iconPath); - FileTransferJob* job = np.createPayloadTransferJob(destinationUrl); - job->start(); - connect(job, &FileTransferJob::result, this, &Notification::applyIconAndShow); + applyIcon(); + show(); } } - if(!m_requestReplyId.isEmpty()) { - m_notification->setActions( QStringList(i18n("Reply")) ); + if (!m_requestReplyId.isEmpty()) { + m_notification->setActions(QStringList(i18n("Reply"))); connect(m_notification, &KNotification::action1Activated, this, &Notification::reply); } @@ -129,6 +123,36 @@ return m_notification; } +void Notification::loadIcon(const NetworkPackage& np) +{ + m_ready = false; + FileTransferJob* job = np.createPayloadTransferJob(QUrl::fromLocalFile(m_iconPath)); + job->start(); + + connect(job, &FileTransferJob::result, this, [this, job]{ + + if (job->error()) { + qCDebug(KDECONNECT_PLUGIN_NOTIFICATION) << "Error in FileTransferJob: " << job->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-existant icon + m_notification->setIconName(QString("not_a_real_icon")); +} + void Notification::reply() { Q_EMIT replyRequested(); diff --git a/plugins/notifications/notificationsdbusinterface.h b/plugins/notifications/notificationsdbusinterface.h --- a/plugins/notifications/notificationsdbusinterface.h +++ b/plugins/notifications/notificationsdbusinterface.h @@ -39,6 +39,10 @@ Q_CLASSINFO("D-Bus Interface", "org.kde.kdeconnect.device.notifications") public: + enum RemoveType{ + KeepNotification, DestroyNotification + }; + explicit NotificationsDbusInterface(KdeConnectPlugin* plugin); ~NotificationsDbusInterface() override; @@ -58,7 +62,7 @@ Q_SCRIPTABLE void allNotificationsRemoved(); private /*methods*/: - void removeNotification(const QString& internalId); + void removeNotification(const QString& internalId, RemoveType removetype=DestroyNotification); QString newId(); //Generates successive identifitiers to use as public ids private /*attributes*/: diff --git a/plugins/notifications/notificationsdbusinterface.cpp b/plugins/notifications/notificationsdbusinterface.cpp --- a/plugins/notifications/notificationsdbusinterface.cpp +++ b/plugins/notifications/notificationsdbusinterface.cpp @@ -80,12 +80,22 @@ } else { QString id = np.get(QStringLiteral("id")); + Notification* noti; + if (!m_internalIdToPublicId.contains(id)) { - Notification* noti = new Notification(np, this); - addNotification(noti); + noti = new Notification(np, this); } else { QString pubId = m_internalIdToPublicId[id]; - m_notifications[pubId]->update(np); + noti = m_notifications[pubId]; + noti->update(np); + } + + if (noti->isReady()) { + addNotification(noti); + } else { + connect(noti, &Notification::ready, this, [this, noti]{ + addNotification(noti); + }); } } } @@ -95,7 +105,7 @@ const QString& internalId = noti->internalId(); if (m_internalIdToPublicId.contains(internalId)) { - removeNotification(internalId); + removeNotification(internalId, KeepNotification); } //qCDebug(KDECONNECT_PLUGIN_NOTIFICATION) << "addNotification" << internalId; @@ -115,12 +125,12 @@ Q_EMIT notificationPosted(publicId); } -void NotificationsDbusInterface::removeNotification(const QString& internalId) +void NotificationsDbusInterface::removeNotification(const QString& internalId, RemoveType removetype) { //qCDebug(KDECONNECT_PLUGIN_NOTIFICATION) << "removeNotification" << internalId; if (!m_internalIdToPublicId.contains(internalId)) { - qCDebug(KDECONNECT_PLUGIN_NOTIFICATION) << "Not found noti by internal Id: " << internalId; + //qCDebug(KDECONNECT_PLUGIN_NOTIFICATION) << "Not found noti by internal Id: " << internalId; return; } @@ -128,13 +138,16 @@ Notification* noti = m_notifications.take(publicId); if (!noti) { - qCDebug(KDECONNECT_PLUGIN_NOTIFICATION) << "Not found noti by public Id: " << publicId; + //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(); + if (removetype == KeepNotification){ + QDBusConnection::sessionBus().unregisterObject(m_device->dbusPath()+"/notifications/"+publicId); + } else if (removetype == DestroyNotification){ + noti->deleteLater(); + } Q_EMIT notificationRemoved(publicId); }