#include "notificationmanager.h" #include #include #include #include #include #include //#include "PersonalNotification.h" class NotificationManagerPrivate { Q_DECLARE_PUBLIC(NotificationManager) public: NotificationManagerPrivate(NotificationManager *q) : q_ptr(q), interface(NULL), connected(false) { /*...*/ } NotificationManager *q_ptr; QDBusInterface *interface; bool connected; }; NotificationManager::NotificationManager(Settings *settings, QObject *parent) : QObject(parent), l(metaObject()->className()), d_ptr(new NotificationManagerPrivate(this)), settings(settings) { Q_D(NotificationManager); QDBusConnection::sessionBus().registerObject("/org/freedesktop/Notifications", this, QDBusConnection::ExportAllSlots); d->interface = new QDBusInterface("org.freedesktop.DBus", "/org/freedesktop/DBus", "org.freedesktop.DBus"); d->interface->call("AddMatch", "interface='org.freedesktop.Notifications',member='Notify',type='method_call',eavesdrop='true'"); this->initialize(); } NotificationManager::~NotificationManager() { Q_D(NotificationManager); delete d; } void NotificationManager::initialize(bool notifyError) { Q_D(NotificationManager); bool success = false; if(d->interface->isValid()) { success = true; } if(!(d->connected = success)) { QTimer::singleShot(2000, this, SLOT(initialize())); if(notifyError) emit this->error("Failed to connect to Notifications D-Bus service."); } } QDBusInterface* NotificationManager::interface() const { Q_D(const NotificationManager); return d->interface; } QString NotificationManager::getCleanAppName(QString app_name) { QString desktopFile = QString("/usr/share/applications/%1.desktop").arg(app_name); QFile testFile(desktopFile); if (testFile.exists()) { QSettings settings(desktopFile, QSettings::IniFormat); settings.beginGroup("Desktop Entry"); QString cleanName = settings.value("Name").toString(); settings.endGroup(); if (!cleanName.isEmpty()) { return cleanName; } } return app_name; } QStringHash NotificationManager::getCategoryParams(QString category) { if (!category.isEmpty()) { QString categoryConfigFile = QString("/usr/share/lipstick/notificationcategories/%1.conf").arg(category); QFile testFile(categoryConfigFile); if (testFile.exists()) { QStringHash categories; QSettings settings(categoryConfigFile, QSettings::IniFormat); const QStringList settingKeys = settings.allKeys(); foreach (const QString &settingKey, settingKeys) { categories[settingKey] = settings.value(settingKey).toString(); } return categories; } } return QStringHash(); } uint NotificationManager::Notify(const QString &app_name, uint replaces_id, const QString &app_icon, const QString &summary, const QString &body, const QStringList &actions, const QVariantHash &hints, int expire_timeout) { Q_UNUSED(replaces_id); Q_UNUSED(app_icon); Q_UNUSED(actions); Q_UNUSED(expire_timeout); // new place to check notification owner in Sailfish 1.1.6 QString owner = hints.value("x-nemo-owner", "Unknown").toString(); qCDebug(l) << Q_FUNC_INFO << "Got notification via dbus from" << this->getCleanAppName(app_name) << " Owner: " << owner; qCDebug(l) << hints; // Avoid sending a reply for this method call, since we've received it because we're eavesdropping. // The actual target of the method call will send the proper reply. Q_ASSERT(calledFromDBus()); setDelayedReply(true); QString category = hints.value("category", "").toString(); QStringHash categoryParams = this->getCategoryParams(category); if (category == "x-nemo.email") { if (!settings->property("notificationsEmails").toBool()) { qCDebug(l) << "Ignoring email notification because of setting!"; return 0; } emit this->emailNotify(summary, body, app_name); } else if (category == "x-nemo.call.missed") { if (!settings->property("notificationsMissedCall").toBool()) { qCDebug(l) << "Ignoring MissedCall notification because of setting!"; return 0; } emit this->smsNotify(hints.value("x-nemo-preview-summary", summary).toString(), hints.value("x-nemo-preview-body", body).toString() ); } else if (category == "x-nemo.messaging.sms.preview") { if (!settings->property("notificationsCommhistoryd").toBool()) { qCDebug(l) << "Ignoring commhistoryd notification because of setting!"; return 0; } emit this->smsNotify(hints.value("x-nemo-preview-summary", summary).toString(), hints.value("x-nemo-preview-body", body).toString() ); } else if (app_name.toLower().contains("whatsapp") || app_name.toLower().contains("whatsup")) { if (!settings->property("notificationsWhatsapp").toBool()) { qCDebug(l) << "Ignoring whatsapp notification because of setting!"; return 0; } emit this->whatsappNotify(hints.value("x-nemo-preview-summary", summary).toString(), hints.value("x-nemo-preview-body", body).toString() ); } else if (hints.value("x-nemo-origin-package").toString() == "org.telegram.messenger" || category.startsWith("harbour.sailorgram")) { if (!settings->property("notificationsTelegram").toBool()) { qCDebug(l) << "Ignoring telegram notification because of setting!"; return 0; } emit this->telegramNotify(hints.value("x-nemo-preview-summary", summary).toString(), hints.value("x-nemo-preview-body", body).toString() ); } else if (app_name.toLower().contains("hangouts") || app_name.toLower().contains("hangish")) { if (!settings->property("notificationsHangouts").toBool()) { qCDebug(l) << "Ignoring telegram notification because of setting!"; return 0; } emit this->hangoutNotify(hints.value("x-nemo-preview-summary", summary).toString(), hints.value("x-nemo-preview-body", body).toString() ); } else if (app_name == "twitter-notifications-client" || owner == "twitter-notifications-client") { if (!settings->property("notificationsTwitter").toBool()) { qCDebug(l) << "Ignoring twitter notification because of setting!"; return 0; } emit this->twitterNotify(hints.value("x-nemo-preview-summary", summary).toString(), hints.value("x-nemo-preview-body", body).toString() ); } else { // Ignore transient notifications (notif hints override category hints) // Hack this to accept transient -preview and -summary notifications, as we don't know how to decode the actual notifs yet if (!category.endsWith("preview") && !category.endsWith("summary") && hints.value("transient", categoryParams.value("transient", "false")).toString() == "true") { qCDebug(l) << "Ignoring transient notification from " << owner; return 0; } // Prioritize x-nemo-preview* over dbus direct summary and body QString subject = hints.value("x-nemo-preview-summary", summary).toString(); QString data = hints.value("x-nemo-preview-body", body).toString(); int prio = categoryParams.value("x-nemo-priority", "0").toInt(); qCDebug(l) << "MSG Prio:" << prio; if (!settings->property("notificationsAll").toBool() && prio <= 10) { qCDebug(l) << "Ignoring notification because of setting! (all)"; return 0; } if (!settings->property("notificationsOther").toBool() && prio < 90) { qCDebug(l) << "Ignoring notification because of setting! (other)"; return 0; } if (subject.isEmpty()) { subject = summary; } if (data.isEmpty()) { data = body; } //Prioritize data over subject if (data.isEmpty() && !subject.isEmpty()) { data = subject; subject = ""; } //Never send empty data and subject if (data.isEmpty() && subject.isEmpty()) { qCWarning(l) << Q_FUNC_INFO << "Empty subject and data in dbus app:" << app_name; return 0; } emit this->emailNotify(this->getCleanAppName(app_name), data, subject); } return 0; }