diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 56dc2f3..c715954 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,220 +1,222 @@ if (Phonon4Qt5_FOUND) include_directories(${PHONON_INCLUDE_DIR}) endif() if (CANBERRA_FOUND) include_directories(${CANBERRA_INCLUDE_DIRS}) endif() ecm_create_qm_loader(knotifications_QM_LOADER knotifications5_qt) set(knotifications_SRCS knotification.cpp knotificationmanager.cpp kpassivepopup.cpp knotifyconfig.cpp knotificationplugin.cpp notifybypopupgrowl.cpp notifybyexecute.cpp notifybylogfile.cpp notifybytaskbar.cpp ${knotifications_QM_LOADER} ) if (TARGET Qt5::DBus) list(APPEND knotifications_SRCS kstatusnotifieritem.cpp kstatusnotifieritemdbus_p.cpp knotificationrestrictions.cpp imageconverter.cpp #needed to marshal images for sending over dbus by NotifyByPopup notifybypopup.cpp notifybyportal.cpp ) endif() if (ANDROID) add_subdirectory(android) list(APPEND knotifications_SRCS notifybyandroid.cpp knotifications.qrc) endif() if (WIN32) if (MSVC) find_package(LibSnoreToast REQUIRED) set_package_properties(LibSnoreToast PROPERTIES TYPE OPTIONAL PURPOSE "Enable support for the snorenotify framework" DESCRIPTION "a cross-platform notification framework" ) - if (Qt5Network_FOUND) - target_link_libraries(KF5Notifications PUBLIC Qt5::Network) - endif() + find_package(Qt5Core REQUIRED) + find_package(Qt5Network REQUIRED) list(APPEND knotifications_SRCS notifybysnore.cpp) endif () endif () ecm_qt_declare_logging_category(knotifications_SRCS HEADER debug_p.h IDENTIFIER LOG_KNOTIFICATIONS CATEGORY_NAME org.kde.knotifications) if (Canberra_FOUND) set(knotifications_SRCS ${knotifications_SRCS} notifybyaudio_canberra.cpp) elseif (Phonon4Qt5_FOUND) set(knotifications_SRCS ${knotifications_SRCS} notifybyaudio_phonon.cpp) endif() if (Qt5TextToSpeech_FOUND) set(knotifications_SRCS ${knotifications_SRCS} notifybytts.cpp) endif() find_package(dbusmenu-qt5 CONFIG) set_package_properties(dbusmenu-qt5 PROPERTIES DESCRIPTION "DBusMenuQt" URL "https://launchpad.net/libdbusmenu-qt" TYPE OPTIONAL PURPOSE "Support for notification area menus via the DBusMenu protocol") if (dbusmenu-qt5_FOUND) message("dbusmenu-qt5_FOUND") set(HAVE_DBUSMENUQT 1) include_directories(${dbusmenu-qt5_INCLUDE_DIRS}) else() set(HAVE_DBUSMENUQT 0) endif() if (TARGET Qt5::DBus) qt5_add_dbus_adaptor(knotifications_SRCS org.kde.StatusNotifierItem.xml kstatusnotifieritemdbus_p.h KStatusNotifierItemDBus) set(statusnotifierwatcher_xml org.kde.StatusNotifierWatcher.xml) qt5_add_dbus_interface(knotifications_SRCS ${statusnotifierwatcher_xml} statusnotifierwatcher_interface) set(notifications_xml org.freedesktop.Notifications.xml) qt5_add_dbus_interface(knotifications_SRCS ${notifications_xml} notifications_interface) endif() configure_file(config-knotifications.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-knotifications.h ) add_library(KF5Notifications ${knotifications_SRCS}) generate_export_header(KF5Notifications BASE_NAME KNotifications) add_library(KF5::Notifications ALIAS KF5Notifications) target_include_directories(KF5Notifications INTERFACE "$") target_link_libraries(KF5Notifications PUBLIC Qt5::Widgets ) if (TARGET Qt5::DBus) target_link_libraries(KF5Notifications PUBLIC Qt5::DBus) endif() target_link_libraries(KF5Notifications PRIVATE KF5::CoreAddons KF5::ConfigCore KF5::WindowSystem KF5::Codecs ) +if (MSVC) +target_link_libraries(KF5Notifications PUBLIC Qt5::Core Qt5::Network SnoreToast::SnoreToastActions) +endif () if (Phonon4Qt5_FOUND) target_link_libraries(KF5Notifications PRIVATE ${PHONON_LIBRARIES}) endif() if (Canberra_FOUND) target_link_libraries(KF5Notifications PRIVATE Canberra::Canberra) endif() if (Qt5TextToSpeech_FOUND) target_link_libraries(KF5Notifications PRIVATE Qt5::TextToSpeech) endif() if(X11_FOUND) target_link_libraries(KF5Notifications PRIVATE ${X11_X11_LIB} Qt5::X11Extras) endif() if(APPLE) target_link_libraries(KF5Notifications PRIVATE Qt5::MacExtras) endif() if(X11_XTest_FOUND) target_link_libraries(KF5Notifications PRIVATE ${X11_XTest_LIB}) endif() if(HAVE_DBUSMENUQT) target_link_libraries(KF5Notifications PRIVATE dbusmenu-qt5) endif() if (ANDROID) target_link_libraries(KF5Notifications PRIVATE Qt5::AndroidExtras) endif() set_target_properties(KF5Notifications PROPERTIES VERSION ${KNOTIFICATIONS_VERSION_STRING} SOVERSION ${KNOTIFICATIONS_SOVERSION} EXPORT_NAME Notifications ) ecm_generate_headers(KNotifications_HEADERS HEADER_NAMES KNotification KPassivePopup KStatusNotifierItem KNotificationRestrictions KNotificationPlugin KNotifyConfig REQUIRED_HEADERS KNotifications_HEADERS ) install(TARGETS KF5Notifications EXPORT KF5NotificationsTargets ${KF5_INSTALL_TARGETS_DEFAULT_ARGS}) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/knotifications_export.h ${KNotifications_HEADERS} DESTINATION ${KDE_INSTALL_INCLUDEDIR_KF5}/KNotifications COMPONENT Devel ) if(BUILD_QCH) ecm_add_qch( KF5Notifications_QCH NAME KNotifications BASE_NAME KF5Notifications VERSION ${KF5_VERSION} ORG_DOMAIN org.kde SOURCES # using only public headers, to cover only public API ${KNotifications_HEADERS} MD_MAINPAGE "${CMAKE_SOURCE_DIR}/README.md" IMAGE_DIRS "${CMAKE_SOURCE_DIR}/docs/pics" LINK_QCHS Qt5Widgets_QCH BLANK_MACROS KNOTIFICATIONS_EXPORT KNOTIFICATIONS_DEPRECATED KNOTIFICATIONS_DEPRECATED_EXPORT TAGFILE_INSTALL_DESTINATION ${KDE_INSTALL_QTQCHDIR} QCH_INSTALL_DESTINATION ${KDE_INSTALL_QTQCHDIR} COMPONENT Devel ) endif() if (TARGET Qt5::DBus) install(FILES org.kde.StatusNotifierItem.xml DESTINATION ${KDE_INSTALL_DBUSINTERFACEDIR} RENAME kf5_org.kde.StatusNotifierItem.xml) install(FILES org.kde.StatusNotifierWatcher.xml DESTINATION ${KDE_INSTALL_DBUSINTERFACEDIR} RENAME kf5_org.kde.StatusNotifierWatcher.xml) endif() install(FILES knotificationplugin.desktop DESTINATION ${KDE_INSTALL_KSERVICETYPES5DIR}) include(ECMGeneratePriFile) ecm_generate_pri_file(BASE_NAME KNotifications LIB_NAME KF5Notifications DEPS "widgets" FILENAME_VAR PRI_FILENAME INCLUDE_INSTALL_DIR ${KDE_INSTALL_INCLUDEDIR_KF5}/KNotifications) install(FILES ${PRI_FILENAME} DESTINATION ${ECM_MKSPECS_INSTALL_DIR}) if (ANDROID) install(FILES KF5Notifications-android-dependencies.xml DESTINATION ${KDE_INSTALL_LIBDIR}) endif() diff --git a/src/notifybysnore.cpp b/src/notifybysnore.cpp index ceaab31..a2a9969 100644 --- a/src/notifybysnore.cpp +++ b/src/notifybysnore.cpp @@ -1,154 +1,179 @@ /* Copyright (C) 2019 Piyush Aggarwal This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. 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 Library 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 "notifybysnore.h" #include "knotification.h" #include "knotifyconfig.h" #include "debug_p.h" #include #include #include #include #include #include #include #include #include -// Q_LOGGING_CATEGORY(SNORETOAST, "SNORETOAST") -// #include -// #include -#include -#include -#include - -#include +#include +#include -#include "snoretoastactions.h" +#include static NotifyBySnore *s_instance = nullptr; // RUN THIS BEFORE TRYING OR THE NOTIFS WON'T SHOW! // .\SnoreToast.exe -install "KDE Connect" "C:\CraftRoot\bin\kdeconnectd.exe" "org.kde.connect" //gotta get more inspirations from notifybyportal // installing the Shortcut NotifyBySnore::NotifyBySnore(QObject* parent) : KNotificationPlugin(parent) { s_instance = this; program = QStringLiteral("SnoreToast.exe"); // Sleep(uint(4000)); } NotifyBySnore::~NotifyBySnore() { s_instance = nullptr; } void NotifyBySnore::notify(KNotification *notification, KNotifyConfig *config) { if (m_notifications.find(notification->id()) != m_notifications.end() || notification->id() == -1) { qDebug() << "AHAA ! Duplicate for ID: " << notification->id() << " caught!"; return; } proc = new QProcess(); QTemporaryFile iconFile; QStringList arguments; // we read from the pixmap sent through KDE Connect // and save it to a file temporarily, then delete the icon once the notif is rendered if (!notification->pixmap().isNull()) { if (iconFile.open()) { notification->pixmap().save(&iconFile, "PNG"); } } + // ACTION! +int id = notification->id(); + QObject::connect(server, &QLocalServer::newConnection, server, [this,id]() { + + + auto sock = server->nextPendingConnection(); + sock->waitForReadyRead(); + const QByteArray rawData = sock->readAll(); + const QString data = + QString::fromWCharArray(reinterpret_cast(rawData.constData()), + rawData.size() / sizeof(wchar_t)); + QMap map; + for (const auto &str : data.split(QStringLiteral(";"))) { + const auto index = str.indexOf(QStringLiteral("=")); + map[str.mid(0, index)] = str.mid(index + 1); + } + const auto action = map[QStringLiteral("action")]; + const auto snoreAction = SnoreToastActions::getAction(action.toStdWString()); + + // std::wcout << "Action: " << qPrintable(action) << " " << static_cast(snoreAction) + // << std::endl; + + qDebug() << "THE ID IS : " << id << "AND THE ACTION IS : " << action; + NotifyBySnore::notificationActionInvoked(id, static_cast(snoreAction)); +}); + server->listen(QStringLiteral("foo")); + + arguments << QStringLiteral("-t") << notification->title(); arguments << QStringLiteral("-m") << notification->text()+QString::number(notification->id()); - arguments << QStringLiteral("-p") << iconFile.fileName() ; + arguments << QStringLiteral("-p") << iconFile.fileName(); + arguments << QStringLiteral("-pipename") << server->fullServerName(); arguments << QStringLiteral("-appID") << QStringLiteral("org.kde.connect"); arguments << QStringLiteral("-id") << QString::number(notification->id()); // arguments << QStringLiteral("-b") << QStringLiteral("Close;Button2"); arguments << QStringLiteral("-w"); m_notifications.insert(notification->id(), notification); proc->start(program, arguments); + Sleep(5000); // !HACK! for the notifications to pick up the image icon if(proc->waitForStarted(5000)) { qDebug() << "SnoreToast called for Notif-show by ID: "<< notification->id(); - arguments.clear(); } else { qDebug() << "SnoreToast did not start in time for Notif-Show"; } + proc->waitForFinished(); + } /* Then we also have a config Not sure what's that, but we surely get this from notifs in KDEConnect. Here in this plugin we gotta define our own notificationFinished notificationActionInvoked aaaand we should be done :) */ // LIMITATION : notifs won't get closed auto-ly if you open Action Center, read them, and then close it back. void NotifyBySnore::close(KNotification* notification) { const auto it = m_notifications.find(notification->id()); if (it == m_notifications.end()) { return; } qDebug() << "SnoreToast called for closing notif by ID: "<< notification->id(); proc = new QProcess(); QStringList arguments; arguments << QStringLiteral("-close") << QString::number(notification->id()); proc->start(program, arguments); arguments.clear(); m_notifications.erase(it); if (it.value()) { finish(it.value()); } } void NotifyBySnore::update(KNotification *notification, KNotifyConfig *config) { close(notification); notify(notification, config); } void NotifyBySnore::notificationActionInvoked(int id, int action) { qCDebug(LOG_KNOTIFICATIONS) << id << action; emit actionInvoked(id, action); } diff --git a/src/notifybysnore.h b/src/notifybysnore.h index 15bca95..2d6f15b 100644 --- a/src/notifybysnore.h +++ b/src/notifybysnore.h @@ -1,48 +1,50 @@ /* Copyright (C) 2019 Piyush Aggarwal This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. 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 Library 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 NOTIFYBYSNORE_H #define NOTIFYBYSNORE_H #include "knotificationplugin.h" #include +#include +#include #include #include /** Windows notification backend - inspired by Android notification backend. */ class NotifyBySnore : public KNotificationPlugin { Q_OBJECT public: explicit NotifyBySnore(QObject *parent = nullptr); ~NotifyBySnore() override; QString optionName() override { return QStringLiteral("Popup"); } void notify(KNotification *notification, KNotifyConfig *config) override; void close(KNotification * notification) override; void update(KNotification *notification, KNotifyConfig *config) override; void notificationActionInvoked(int id, int action); - // void installShortcut(QString& appName, QString& appLocation, QString& appID); private: QHash> m_notifications; QString program; QProcess *proc; + QLocalServer *server = new QLocalServer(); }; #endif // NOTIFYBYSNORE_H