diff options
| author | Tomasz Sterna <tomek@xiaoka.com> | 2014-07-14 16:49:27 +0200 |
|---|---|---|
| committer | Tomasz Sterna <tomek@xiaoka.com> | 2014-07-14 16:49:27 +0200 |
| commit | c358544734ae26770e91d56a92dcd8e22da71be5 (patch) | |
| tree | 8227bed64b6cbd7088102c762285e64a30418d56 | |
| parent | 9160f139d399bce61c67a4ebc31dfdf1cc5d3e62 (diff) | |
| parent | c911932934f0a7d8bf1c252be4a3e718859b3b09 (diff) | |
Merge branch 'notifications' of github.com:smurfy/pebble into smurfy-notifications
Conflicts:
daemon/daemon.pro
daemon/manager.cpp
daemon/manager.h
| -rw-r--r-- | daemon/daemon.cpp | 3 | ||||
| -rw-r--r-- | daemon/daemon.pro | 2 | ||||
| -rw-r--r-- | daemon/manager.cpp | 58 | ||||
| -rw-r--r-- | daemon/manager.h | 14 | ||||
| -rw-r--r-- | daemon/notificationmanager.cpp | 162 | ||||
| -rw-r--r-- | daemon/notificationmanager.h | 46 | ||||
| -rw-r--r-- | daemon/watchconnector.cpp | 5 |
7 files changed, 244 insertions, 46 deletions
diff --git a/daemon/daemon.cpp b/daemon/daemon.cpp index eba9afa..cd5e781 100644 --- a/daemon/daemon.cpp +++ b/daemon/daemon.cpp @@ -125,8 +125,9 @@ int main(int argc, char *argv[]) watch::WatchConnector watch; DBusConnector dbus; VoiceCallManager voice; + NotificationManager notifications; - Manager manager(&watch, &dbus, &voice); + Manager manager(&watch, &dbus, &voice, ¬ifications); signal(SIGINT, signalhandler); signal(SIGTERM, signalhandler); diff --git a/daemon/daemon.pro b/daemon/daemon.pro index 3db6918..cfcdae1 100644 --- a/daemon/daemon.pro +++ b/daemon/daemon.pro @@ -17,6 +17,7 @@ SOURCES += \ manager.cpp \ voicecallmanager.cpp \ voicecallhandler.cpp \ + notificationmanager.cpp \ watchconnector.cpp \ dbusconnector.cpp \ dbusadaptor.cpp \ @@ -26,6 +27,7 @@ HEADERS += \ manager.h \ voicecallmanager.h \ voicecallhandler.h \ + notificationmanager.h \ watchconnector.h \ dbusconnector.h \ dbusadaptor.h \ diff --git a/daemon/manager.cpp b/daemon/manager.cpp index 496f6d8..ec0d21b 100644 --- a/daemon/manager.cpp +++ b/daemon/manager.cpp @@ -5,8 +5,8 @@ #include <QtContacts/QContact> #include <QtContacts/QContactPhoneNumber> -Manager::Manager(watch::WatchConnector *watch, DBusConnector *dbus, VoiceCallManager *voice) : - QObject(0), watch(watch), dbus(dbus), voice(voice), commands(new WatchCommands(watch, this)), +Manager::Manager(watch::WatchConnector *watch, DBusConnector *dbus, VoiceCallManager *voice, NotificationManager *notifications) : + QObject(0), watch(watch), dbus(dbus), voice(voice), notifications(notifications), commands(new WatchCommands(watch, this)), notification(MNotification::DeviceEvent) { // We don't need to handle presence changes, so report them separately and ignore them @@ -17,14 +17,14 @@ Manager::Manager(watch::WatchConnector *watch, DBusConnector *dbus, VoiceCallMan numberFilter.setDetailType(QContactDetail::TypePhoneNumber, QContactPhoneNumber::FieldNumber); numberFilter.setMatchFlags(QContactFilter::MatchPhoneNumber); - conversations = new GroupManager(this); - connect(conversations, SIGNAL(groupAdded(GroupObject*)), SLOT(onConversationGroupAdded(GroupObject*))); - conversations->getGroups(); + connect(watch, SIGNAL(connectedChanged()), SLOT(onConnectedChanged())); connect(voice, SIGNAL(activeVoiceCallChanged()), SLOT(onActiveVoiceCallChanged())); connect(voice, SIGNAL(error(const QString &)), SLOT(onVoiceError(const QString &))); - connect(watch, SIGNAL(connectedChanged()), SLOT(onConnectedChanged())); + connect(notifications, SIGNAL(error(const QString &)), SLOT(onNotifyError(const QString &))); + connect(notifications, SIGNAL(emailNotify(const QString &,const QString &,const QString &)), SLOT(onEmailNotify(const QString &,const QString &,const QString &))); + connect(notifications, SIGNAL(smsNotify(const QString &,const QString &)), SLOT(onSmsNotify(const QString &,const QString &))); connect(watch, SIGNAL(messageDecoded(uint,uint,QByteArray)), commands, SLOT(processMessage(uint,uint,QByteArray))); connect(commands, SIGNAL(hangup()), SLOT(hangupAll())); @@ -169,45 +169,33 @@ void Manager::onVoiceError(const QString &message) logger()->error() << "Error: " << message; } -void Manager::hangupAll() + +void Manager::onNotifyError(const QString &message) { - foreach (VoiceCallHandler* handler, voice->voiceCalls()) { - handler->hangup(); - } + qWarning() << "Error: " << message; } -void Manager::onConversationGroupAdded(GroupObject *group) +void Manager::onSmsNotify(const QString &sender, const QString &data) { - if (!group) { - logger()->debug() << "Got null conversation group"; - return; - } - - connect(group, SIGNAL(unreadMessagesChanged()), SLOT(onUnreadMessagesChanged())); - if (group->unreadMessages()) processUnreadMessages(group); + logger()->debug() << "SMS:"; + logger()->debug() << sender; + logger()->debug() << data; + watch->sendSMSNotification(sender, data); } - -void Manager::onUnreadMessagesChanged() +void Manager::onEmailNotify(const QString &sender, const QString &data,const QString &subject) { - GroupObject *group = qobject_cast<GroupObject*>(sender()); - if (!group) { - logger()->debug() << "Got unreadMessagesChanged for null group"; - return; - } - processUnreadMessages(group); + logger()->debug() << "Email:"; + logger()->debug() << sender; + logger()->debug() << data; + logger()->debug() << subject; + watch->sendEmailNotification(sender, data, subject); } -void Manager::processUnreadMessages(GroupObject *group) +void Manager::hangupAll() { - if (group->unreadMessages()) { - QString name = group->contactName(); - QString message = group->lastMessageText(); - logger()->debug() << "Msg:" << message; - logger()->debug() << "From:" << name; - watch->sendSMSNotification(name.isEmpty()?"Unknown":name, message); - } else { - logger()->debug() << "Got processUnreadMessages for group with no new messages"; + foreach (VoiceCallHandler* handler, voice->voiceCalls()) { + handler->hangup(); } } diff --git a/daemon/manager.h b/daemon/manager.h index ba482bb..ea24f9e 100644 --- a/daemon/manager.h +++ b/daemon/manager.h @@ -4,6 +4,7 @@ #include "watchconnector.h" #include "dbusconnector.h" #include "voicecallmanager.h" +#include "notificationmanager.h" #include "watchcommands.h" #include <QObject> @@ -11,12 +12,10 @@ #include <QDBusContext> #include <QtContacts/QContactManager> #include <QtContacts/QContactDetailFilter> -#include <CommHistory/GroupModel> #include <MNotification> #include "Logger" using namespace QtContacts; -using namespace CommHistory; class Manager : public QObject, @@ -32,6 +31,7 @@ class Manager : watch::WatchConnector *watch; DBusConnector *dbus; VoiceCallManager *voice; + NotificationManager *notifications; WatchCommands *commands; @@ -39,15 +39,13 @@ class Manager : QContactManager *contacts; QContactDetailFilter numberFilter; - GroupManager *conversations; QString lastSeenMpris; public: - explicit Manager(watch::WatchConnector *watch, DBusConnector *dbus, VoiceCallManager *voice); + explicit Manager(watch::WatchConnector *watch, DBusConnector *dbus, VoiceCallManager *voice, NotificationManager *notifications); Q_INVOKABLE QString findPersonByNumber(QString number); - Q_INVOKABLE void processUnreadMessages(GroupObject *group); Q_INVOKABLE QString mpris(); QVariantMap mprisMetadata; @@ -63,12 +61,12 @@ protected slots: void onActiveVoiceCallChanged(); void onVoiceError(const QString &message); void onActiveVoiceCallStatusChanged(); - void onConversationGroupAdded(GroupObject *group); - void onUnreadMessagesChanged(); + void onNotifyError(const QString &message); + void onSmsNotify(const QString &sender, const QString &data); + void onEmailNotify(const QString &sender, const QString &data,const QString &subject); void onMprisPropertiesChanged(QString,QMap<QString,QVariant>,QStringList); void setMprisMetadata(QDBusArgument metadata); void setMprisMetadata(QVariantMap metadata); - }; class PebbledProxy : public QObject diff --git a/daemon/notificationmanager.cpp b/daemon/notificationmanager.cpp new file mode 100644 index 0000000..917a245 --- /dev/null +++ b/daemon/notificationmanager.cpp @@ -0,0 +1,162 @@ +#include "notificationmanager.h" + +#include <QDebug> +#include <QTimer> +#include <QFile> +#include <QSettings> +#include <QDBusInterface> +#include <QDBusPendingReply> + +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(QObject *parent) + : QObject(parent), d_ptr(new NotificationManagerPrivate(this)) +{ + 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(); +} + +void 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) { + + //Ignore notifcations from myself + if (app_name == "pebbled") { + return; + } + + logger()->debug() << Q_FUNC_INFO << "Got notification via dbus from" << this->getCleanAppName(app_name); + + if (app_name == "messageserver5") { + emit this->emailNotify(hints.value("x-nemo-preview-summary", this->getCleanAppName(app_name)).toString(), + hints.value("x-nemo-preview-body", "default").toString(), + "" + ); + } else if (app_name == "commhistoryd") { + if (summary == "" && body == "") { + emit this->smsNotify(hints.value("x-nemo-preview-summary", "default").toString(), + hints.value("x-nemo-preview-body", "default").toString() + ); + } + } else if (app_name == "harbour-mitakuuluu2-server") { + emit this->smsNotify(hints.value("x-nemo-preview-body", "default").toString(), + hints.value("x-nemo-preview-summary", "default").toString() + ); + } else { + //Prioritize x-nemo-preview* over dbus direct summary and body + QString subject = hints.value("x-nemo-preview-summary", "").toString(); + QString data = hints.value("x-nemo-preview-body", "").toString(); + QString category = hints.value("category", "").toString(); + QStringHash categoryParams = this->getCategoryParams(category); + int prio = categoryParams.value("x-nemo-priority", "0").toInt(); + + logger()->debug() << "MSG Prio:" << prio; + + 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()) { + logger()->warn() << Q_FUNC_INFO << "Empty subject and data in dbus app " << app_name; + return; + } + + emit this->emailNotify(this->getCleanAppName(app_name), data, subject); + } +} diff --git a/daemon/notificationmanager.h b/daemon/notificationmanager.h new file mode 100644 index 0000000..d2640eb --- /dev/null +++ b/daemon/notificationmanager.h @@ -0,0 +1,46 @@ +#ifndef NOTIFICATIONMANAGER_H +#define NOTIFICATIONMANAGER_H + +#include <QObject> +#include "Logger" + +#include <QDBusInterface> +#include <QDBusPendingCallWatcher> + +typedef QHash<QString, QString> QStringHash; + +class NotificationManager : public QObject +{ + Q_OBJECT + LOG4QT_DECLARE_QCLASS_LOGGER + Q_CLASSINFO("D-Bus Interface", "org.freedesktop.Notifications") + + Q_PROPERTY(QDBusInterface* interface READ interface) +public: + explicit NotificationManager(QObject *parent = 0); + ~NotificationManager(); + + QDBusInterface* interface() const; + +Q_SIGNALS: + void error(const QString &message); + void smsNotify(const QString &sender, const QString &data); + void emailNotify(const QString &sender, const QString &data,const QString &subject); + +public Q_SLOTS: + void 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); + +protected Q_SLOTS: + void initialize(bool notifyError = false); + +private: + class NotificationManagerPrivate *d_ptr; + + QString getCleanAppName(QString app_name); + QStringHash getCategoryParams(QString category); + + Q_DISABLE_COPY(NotificationManager) + Q_DECLARE_PRIVATE(NotificationManager) +}; + +#endif // NOTIFICATIONMANAGER_H diff --git a/daemon/watchconnector.cpp b/daemon/watchconnector.cpp index 89d504b..0ce0607 100644 --- a/daemon/watchconnector.cpp +++ b/daemon/watchconnector.cpp @@ -178,9 +178,10 @@ void WatchConnector::buildData(QByteArray &res, QStringList data) { for (QString d : data) { - QByteArray tmp = d.left(0xF0).toUtf8(); - res.append(tmp.length() & 0xFF); + QByteArray tmp = d.left(0xEF).toUtf8(); + res.append((tmp.length() + 1) & 0xFF); res.append(tmp); + res.append('\0'); } } |
