1 #define DBUS_SERVICE "org.freedesktop.Notifications"
2 #define DBUS_PATH    "/org/freedesktop/Notifications"
3 #define DBUS_OBJECT  "org.freedesktop.Notifications"
4 #define DBUS_CLOSED  "NotificationClosed"
5 #define DBUS_ACTION  "ActionInvoked"
6 #define DBUS_NOTIFY  "Notify"
7 #define DBUS_NCLOSE  "CloseNotification"
8 
9 #include "asemanlinuxnativenotification.h"
10 
11 #include <QDBusConnection>
12 #include <QDBusMessage>
13 #include <QDBusArgument>
14 #include <QCoreApplication>
15 #include <QDebug>
16 
17 class AsemanLinuxNativeNotificationPrivate
18 {
19 public:
20     QDBusConnection *connection;
21 
22     QSet<uint> notifies;
23 };
24 
AsemanLinuxNativeNotification(QObject * parent)25 AsemanLinuxNativeNotification::AsemanLinuxNativeNotification(QObject *parent) :
26     QObject(parent)
27 {
28     p = new AsemanLinuxNativeNotificationPrivate;
29 
30     p->connection = new QDBusConnection( QDBusConnection::sessionBus() );
31     p->connection->connect( DBUS_SERVICE , DBUS_PATH , DBUS_OBJECT , DBUS_CLOSED , this , SLOT(notificationClosed(QDBusMessage)) );
32     p->connection->connect( DBUS_SERVICE , DBUS_PATH , DBUS_OBJECT , DBUS_ACTION , this , SLOT(actionInvoked(QDBusMessage))      );
33 }
34 
sendNotify(const QString & title,const QString & body,const QString & icon,uint replace_id,int timeOut,const QStringList & actions)35 uint AsemanLinuxNativeNotification::sendNotify(const QString &title, const QString &body, const QString &icon, uint replace_id, int timeOut, const QStringList &actions)
36 {
37     QVariantList args;
38     args << QCoreApplication::applicationName();
39     args << replace_id;
40     args << icon;
41     args << title;
42     args << body;
43     args << QVariant::fromValue<QStringList>(actions) ;
44     args << QVariant::fromValue<QVariantMap>(QVariantMap());
45     args << timeOut;
46 
47     QDBusMessage omsg = QDBusMessage::createMethodCall( DBUS_SERVICE , DBUS_PATH , DBUS_OBJECT , DBUS_NOTIFY );
48     omsg.setArguments( args );
49 
50     const QDBusMessage & imsg = p->connection->call( omsg , QDBus::BlockWithGui );
51     const QVariantList & res = imsg.arguments();
52     if( res.isEmpty() )
53         return 0;
54 
55     uint id_res = res.first().toUInt();
56     p->notifies.insert( id_res );
57     return id_res;
58 }
59 
closeNotification(uint id)60 void AsemanLinuxNativeNotification::closeNotification(uint id)
61 {
62     if( !p->notifies.contains(id) )
63         return;
64 
65     QVariantList args;
66     args << id;
67 
68     QDBusMessage omsg = QDBusMessage::createMethodCall( DBUS_SERVICE , DBUS_PATH , DBUS_OBJECT , DBUS_NCLOSE );
69     omsg.setArguments( args );
70 
71     p->connection->call( omsg , QDBus::NoBlock );
72 }
73 
notificationClosed(const QDBusMessage & dmsg)74 void AsemanLinuxNativeNotification::notificationClosed(const QDBusMessage &dmsg)
75 {
76     if( dmsg.type() != QDBusMessage::SignalMessage )
77         return ;
78 
79     const QVariantList & args = dmsg.arguments();
80     if( args.isEmpty() )
81         return ;
82 
83     uint id = args.at(0).toUInt();
84     if( !p->notifies.contains(id) )
85         return;
86 
87     if( args.count() == 1 )
88     {
89         emit notifyClosed(id);
90         p->notifies.remove(id);
91         return;
92     }
93 
94     int type = args.at(1).toInt();
95     switch (type) {
96     case 1:
97         emit notifyTimedOut( id );
98         break;
99 
100     case 2:
101     default:
102         emit notifyClosed( id );
103         p->notifies.remove(id);
104         break;
105     }
106 }
107 
actionInvoked(const QDBusMessage & dmsg)108 void AsemanLinuxNativeNotification::actionInvoked(const QDBusMessage &dmsg)
109 {
110     if( dmsg.type() != QDBusMessage::SignalMessage )
111         return ;
112 
113     const QVariantList & args = dmsg.arguments();
114     if( args.count() != 2 )
115         return ;
116 
117     uint id = args.at(0).toUInt();
118     if( !p->notifies.contains(id) )
119         return;
120 
121     QString action = args.at(1).toString();
122     emit notifyAction(id, action);
123 }
124 
~AsemanLinuxNativeNotification()125 AsemanLinuxNativeNotification::~AsemanLinuxNativeNotification()
126 {
127     delete p;
128 }
129 
130