diff --git a/src/notifybysnore.h b/src/notifybysnore.h --- a/src/notifybysnore.h +++ b/src/notifybysnore.h @@ -40,11 +40,13 @@ void notifyDeferred(KNotification* notification); void close(KNotification * notification) override; void update(KNotification *notification, KNotifyConfig *config) override; + private: - QHash> m_notifications; + QHash m_notifications; QString m_program = QStringLiteral("SnoreToast.exe"); QLocalServer m_server; QTemporaryDir m_iconDir; + int m_counter = 0; }; #endif // NOTIFYBYSNORE_H diff --git a/src/notifybysnore.cpp b/src/notifybysnore.cpp --- a/src/notifybysnore.cpp +++ b/src/notifybysnore.cpp @@ -64,10 +64,14 @@ { m_server.listen(QString::number(qHash(qApp->applicationDirPath()))); connect(&m_server, &QLocalServer::newConnection, &m_server, [this]() { + + // receive the callback auto sock = m_server.nextPendingConnection(); sock->waitForReadyRead(); const QByteArray rawData = sock->readAll(); sock->deleteLater(); + + // parse the callback const QString data = QString::fromWCharArray(reinterpret_cast(rawData.constData()), rawData.size() / sizeof(wchar_t)); @@ -79,16 +83,13 @@ } const auto action = map[QStringLiteral("action")].toString(); const auto id = map[QStringLiteral("notificationId")].toInt(); - KNotification *notification; - const auto it = m_notifications.constFind(id); - if (it != m_notifications.constEnd()) { - notification = it.value(); - } - else { + + // retrieve the notification from internal map + KNotification *notification = m_notifications.value(id); + if (notification == nullptr) { qCDebug(LOG_KNOTIFICATIONS) << "Notification not found!"; return; } - // MSVC2019 has issues with QString::toStdWString() // Qstring::toStdWString() doesn't work with MSVC2019 yet. If it gets fixed // in future, feel free to change the implementation below for lesser LOC. @@ -116,8 +117,11 @@ case SnoreToastActions::Actions::ButtonClicked:{ qCDebug(LOG_KNOTIFICATIONS) << " User clicked a button on the toast."; const auto button = map[QStringLiteral("button")].toString(); + qCDebug(LOG_KNOTIFICATIONS) << "button = " << button; QStringList s = m_notifications.value(id)->actions(); int actionNum = s.indexOf(button) + 1; // QStringList starts with index 0 but not actions + qCDebug(LOG_KNOTIFICATIONS) << "id =" << id; + qCDebug(LOG_KNOTIFICATIONS) << "actionNum =" << actionNum; emit actionInvoked(id, actionNum); break;} case SnoreToastActions::Actions::TextEntered: @@ -140,14 +144,12 @@ void NotifyBySnore::notify(KNotification *notification, KNotifyConfig *config) { - Q_UNUSED(config); - // HACK work around that notification->id() is only populated after returning from here - // note that config will be invalid at that point, so we can't pass that along - QMetaObject::invokeMethod(this, [this, notification](){ notifyDeferred(notification); }, Qt::QueuedConnection); -} + if(notification->id() == -1 && notification->eventId() == QStringLiteral("notification")) { + return; + } -void NotifyBySnore::notifyDeferred(KNotification* notification) -{ + Q_UNUSED(config); + const int newId = m_counter++; QProcess *proc = new QProcess(); QStringList arguments; @@ -159,10 +161,10 @@ } arguments << QStringLiteral("-m") << stripRichText(notification->text()); const QString iconPath = m_iconDir.path() + QLatin1Char('/') - + QString::number(notification->id()) + QStringLiteral(".png"); + + QString::number(newId) + QStringLiteral(".png"); if (!notification->pixmap().isNull()) { auto iconPath = QString(m_iconDir.path() + QLatin1Char('/') - + QString::number(notification->id()) + QStringLiteral(".png")); + + QString::number(newId) + QStringLiteral(".png")); notification->pixmap().save(iconPath, "PNG"); arguments << QStringLiteral("-p") << iconPath; } else if (!qApp->windowIcon().isNull()) { @@ -174,41 +176,43 @@ } arguments << QStringLiteral("-appID") << qApp->applicationName() << QStringLiteral("-pid") << QString::number(qApp->applicationPid()) - << QStringLiteral("-id") << QString::number(notification->id()) + << QStringLiteral("-id") << QString::number(newId) << QStringLiteral("-pipename") << m_server.fullServerName(); if (!notification->actions().isEmpty()) { arguments << QStringLiteral("-b") << notification->actions().join(QLatin1Char(';')); } qCDebug(LOG_KNOTIFICATIONS) << arguments; proc->start(m_program, arguments); - m_notifications.insert(notification->id(), notification); + m_notifications.insert(newId, notification); connect(proc, QOverload::of(&QProcess::finished), [=](int exitCode, QProcess::ExitStatus exitStatus){ proc->deleteLater(); if (exitStatus != QProcess::NormalExit) { qCDebug(LOG_KNOTIFICATIONS) << "SnoreToast crashed while trying to show a notification."; close(notification); } QFile::remove(QString(m_iconDir.path() + QLatin1Char('/') - + QString::number(notification->id()) + QStringLiteral(".png"))); + + QString::number(newId) + QStringLiteral(".png"))); }); } void NotifyBySnore::close(KNotification *notification) { - if (m_notifications.constFind(notification->id()) == m_notifications.constEnd()) { + if (m_notifications.key(notification) == -1) { + qCWarning(LOG_KNOTIFICATIONS) << "Notification was already closed."; return; } - qCDebug(LOG_KNOTIFICATIONS) << "SnoreToast closing notification with ID: " << notification->id(); + const int newId = m_notifications.key(notification); + qCDebug(LOG_KNOTIFICATIONS) << "SnoreToast closing notification with ID: " << newId; QStringList arguments; - arguments << QStringLiteral("-close") << QString::number(notification->id()) + arguments << QStringLiteral("-close") << QString::number(newId) << QStringLiteral("-appID") << qApp->applicationName(); QProcess::startDetached(m_program, arguments); if (notification) { finish(notification); } - m_notifications.remove(notification->id()); + m_notifications.remove(newId); } void NotifyBySnore::update(KNotification *notification, KNotifyConfig *config)