From 7ee859f6a5e6a334a172015fce744baeff539050 Mon Sep 17 00:00:00 2001
From: Javier <dev.git@javispedro.com>
Date: Sun, 26 Apr 2015 00:15:06 +0200
Subject: drop c++11 requirement, use private classes

---
 libwatchfish.pro        |   2 +-
 notification.cpp        | 104 +++++++++++++-
 notification.h          |  64 ++++++---
 notificationmonitor.cpp | 371 ++++++++++++++++++++++++++----------------------
 notificationmonitor.h   |  20 +--
 5 files changed, 356 insertions(+), 205 deletions(-)

diff --git a/libwatchfish.pro b/libwatchfish.pro
index 7967685..63026d5 100644
--- a/libwatchfish.pro
+++ b/libwatchfish.pro
@@ -3,7 +3,7 @@ TARGET = watchfish
 TEMPLATE = lib
 CONFIG += staticlib
 
-CONFIG += c++11 link_pkgconfig
+CONFIG += link_pkgconfig
 PKGCONFIG += dbus-1
 INCLUDEPATH += /usr/include/dbus-1.0
 
diff --git a/notification.cpp b/notification.cpp
index 09f61fb..24617b9 100644
--- a/notification.cpp
+++ b/notification.cpp
@@ -1,7 +1,107 @@
 #include "notification.h"
 
-using namespace watchfish;
+namespace watchfish
+{
+
+struct NotificationPrivate
+{
+	uint id;
+	QString sender;
+	QString summary;
+	QString body;
+	QDateTime timestamp;
+	QString icon;
+};
+
+Notification::Notification(uint id, QObject *parent) : QObject(parent), d_ptr(new NotificationPrivate)
+{
+	Q_D(Notification);
+	d->id = id;
+}
+
+Notification::~Notification()
+{
+}
+
+uint Notification::id() const
+{
+	Q_D(const Notification);
+	return d->id;
+}
+
+QString Notification::sender() const
+{
+	Q_D(const Notification);
+	return d->sender;
+}
+
+void Notification::setSender(const QString &sender)
+{
+	Q_D(Notification);
+	if (sender != d->sender) {
+		d->sender = sender;
+		emit senderChanged();
+	}
+}
+
+QString Notification::summary() const
+{
+	Q_D(const Notification);
+	return d->summary;
+}
 
-Notification::Notification(QObject *parent) : QObject(parent)
+void Notification::setSummary(const QString &summary)
 {
+	Q_D(Notification);
+	if (summary != d->summary) {
+		d->summary = summary;
+		emit summaryChanged();
+	}
+}
+
+QString Notification::body() const
+{
+	Q_D(const Notification);
+	return d->body;
+}
+
+void Notification::setBody(const QString &body)
+{
+	Q_D(Notification);
+	if (body != d->body) {
+		d->body = body;
+		emit bodyChanged();
+	}
+}
+
+QDateTime Notification::timestamp() const
+{
+	Q_D(const Notification);
+	return d->timestamp;
+}
+
+void Notification::setTimestamp(const QDateTime &dt)
+{
+	Q_D(Notification);
+	if (dt != d->timestamp) {
+		d->timestamp = dt;
+		emit timestampChanged();
+	}
+}
+
+QString Notification::icon() const
+{
+	Q_D(const Notification);
+	return d->icon;
+}
+
+void Notification::setIcon(const QString &icon)
+{
+	Q_D(Notification);
+	if (icon != d->icon) {
+		d->icon = icon;
+		emit iconChanged();
+	}
+}
+
 }
diff --git a/notification.h b/notification.h
index 46b6754..c6a9966 100644
--- a/notification.h
+++ b/notification.h
@@ -7,43 +7,63 @@
 namespace watchfish
 {
 
+class NotificationPrivate;
+
 class Notification : public QObject
 {
 	Q_OBJECT
-	Q_PROPERTY(uint id READ id CONSTANT)
-	Q_PROPERTY(QString sender READ sender)
-	Q_PROPERTY(QString summary READ summary NOTIFY summaryChanged)
-	Q_PROPERTY(QString body READ body NOTIFY bodyChanged)
-	Q_PROPERTY(QDateTime timestamp READ timestamp NOTIFY timestampChanged)
-	Q_PROPERTY(QString icon READ icon NOTIFY iconChanged)
+	Q_DECLARE_PRIVATE(Notification)
 
-	explicit Notification(QObject *parent = 0);
+	/** Notification ID */
+	Q_PROPERTY(uint id READ id CONSTANT)
+	/** Name of sender program */
+	Q_PROPERTY(QString sender READ sender WRITE setSender NOTIFY senderChanged)
+	Q_PROPERTY(QString summary READ summary WRITE setSummary NOTIFY summaryChanged)
+	Q_PROPERTY(QString body READ body WRITE setBody NOTIFY bodyChanged)
+	Q_PROPERTY(QDateTime timestamp READ timestamp WRITE setTimestamp NOTIFY timestampChanged)
+	/** Icon file path */
+	Q_PROPERTY(QString icon READ icon WRITE setIcon NOTIFY iconChanged)
+	Q_ENUMS(CloseReason)
 
 public:
-	inline uint id() const { return _id; }
-	inline QString sender() const { return _sender; }
-	inline QString summary() const { return _summary; }
-	inline QString body() const { return _body; }
-	inline QDateTime timestamp() const { return _timestamp; }
-	inline QString icon() const { return _icon; }
+	explicit Notification(uint id, QObject *parent = 0);
+	~Notification();
+
+	enum CloseReason {
+		Expired = 1,
+		DismissedByUser = 2,
+		DismissedByProgram = 3,
+		ClosedOther = 4
+	};
+
+	uint id() const;
+
+	QString sender() const;
+	void setSender(const QString &sender);
+
+	QString summary() const;
+	void setSummary(const QString &summary);
+
+	QString body() const;
+	void setBody(const QString &body);
+
+	QDateTime timestamp() const;
+	void setTimestamp(const QDateTime &dt);
+
+	QString icon() const;
+	void setIcon(const QString &icon);
 
 signals:
+	void senderChanged();
 	void summaryChanged();
 	void bodyChanged();
 	void timestampChanged();
 	void iconChanged();
 
-	void closed(int reason);
+	void closed(CloseReason reason);
 
 private:
-	friend class NotificationMonitor;
-
-	uint _id;
-	QString _sender;
-	QString _summary;
-	QString _body;
-	QDateTime _timestamp;
-	QString _icon;
+	NotificationPrivate * const d_ptr;
 };
 
 }
diff --git a/notificationmonitor.cpp b/notificationmonitor.cpp
index 339f43c..25948ee 100644
--- a/notificationmonitor.cpp
+++ b/notificationmonitor.cpp
@@ -1,71 +1,161 @@
-#include <QtCore/QDebug>
+#include <QtCore/QMessageLogger>
 #include <QtCore/QSocketNotifier>
 #include <dbus/dbus.h>
 
 #include "notification.h"
 #include "notificationmonitor.h"
 
-using namespace watchfish;
+namespace watchfish
+{
+
+Q_LOGGING_CATEGORY(notificationMonitorCat, "watchfish-NotificationMonitor")
 
-namespace
+class NotificationMonitorPrivate
 {
+	NotificationMonitor * const q_ptr;
+	Q_DECLARE_PUBLIC(NotificationMonitor)
+
+	/** The current set of monitored notifications, indexed by id. */
+	QMap<quint32, Notification*> _notifs;
+	/** Low level dbus connection used for sniffing. */
+	DBusConnection *_conn;
+	/** Serials of DBUS method calls of which we are expecting a reply. */
+	QHash<quint32, QVariantHash> _pending_confirmation;
+
+	NotificationMonitorPrivate(NotificationMonitor *q);
+	~NotificationMonitorPrivate();
+
+	void processIncomingNotification(quint32 id, const QVariantHash &content);
+	void processCloseNotification(quint32 id, quint32 reason);
+
+	void sendMessageWithString(const char *service, const char *path, const char *iface, const char *method, const char *arg);
+	void addMatchRule(const char *rule);
+	void removeMatchRule(const char *rule);
 
-NotificationMonitor *global_monitor = 0;
+	QVariantHash parseNotifyCall(DBusMessage *msg) const;
 
-DBusConnection *bus_connection;
+	static dbus_bool_t busWatchAdd(DBusWatch *watch, void *data);
+	static void busWatchRemove(DBusWatch *watch, void *data);
+	static void busWatchToggle(DBusWatch *watch, void *data);
 
-QHash<quint32, QVariantHash> pending_confirmation;
+	static DBusHandlerResult busMessageFilter(DBusConnection *conn, DBusMessage *msg, void *user_data);
 
-dbus_bool_t bus_watch_add(DBusWatch *watch, void *data)
+	void handleBusSocketActivated();
+};
+
+NotificationMonitorPrivate::NotificationMonitorPrivate(NotificationMonitor *q)
+	: q_ptr(q)
 {
-	NotificationMonitor *monitor = static_cast<NotificationMonitor*>(data);
-	int socket = dbus_watch_get_socket(watch);
-	int flags = dbus_watch_get_flags(watch);
-	QSocketNotifier::Type type;
-	switch (flags) {
-	case DBUS_WATCH_READABLE:
-		type = QSocketNotifier::Read;
-		break;
-	case DBUS_WATCH_WRITABLE:
-		type = QSocketNotifier::Write;
-		break;
-	default:
-		qWarning() << "Can't add this type of watch" << flags;
-		return FALSE;
+	DBusError error = DBUS_ERROR_INIT;
+	_conn = dbus_bus_get_private(DBUS_BUS_SESSION, &error);
+	if (!_conn) {
+		qCWarning(notificationMonitorCat) << "Could not connect to the session bus";
+		return;
 	}
 
-	QSocketNotifier *notifier = new QSocketNotifier(socket, type, monitor);
-	dbus_watch_set_data(watch, notifier, NULL);
+	dbus_connection_set_exit_on_disconnect(_conn, FALSE);
 
-	notifier->setEnabled(dbus_watch_get_enabled(watch));
+	dbus_connection_set_watch_functions(_conn, busWatchAdd, busWatchRemove,
+										busWatchToggle, this, NULL);
 
-	notifier->connect(notifier, &QSocketNotifier::activated,
-			[watch]() {
-		dbus_watch_handle(watch, dbus_watch_get_flags(watch));
+	addMatchRule("type='method_call',interface='org.freedesktop.Notifications',member='Notify',eavesdrop='true'");
+	addMatchRule("type='method_return',sender='org.freedesktop.Notifications',eavesdrop='true'");
+	addMatchRule("type='signal',sender='org.freedesktop.Notifications',path='/org/freedesktop/Notifications',interface='org.freedesktop.Notifications',member='NotificationClosed'");
 
-		while (dbus_connection_get_dispatch_status(bus_connection) == DBUS_DISPATCH_DATA_REMAINS) {
-			dbus_connection_dispatch(bus_connection);
-		}
-	});
+	dbus_bool_t result = dbus_connection_add_filter(_conn, busMessageFilter,
+													this, NULL);
+	if (!result) {
+		qCWarning(notificationMonitorCat) << "Could not add filter";
+	}
 
-	return TRUE;
+	qCDebug(notificationMonitorCat) << "Starting notification monitor";
 }
 
-void bus_watch_remove(DBusWatch *watch, void *data)
+NotificationMonitorPrivate::~NotificationMonitorPrivate()
 {
-	QSocketNotifier *notifier = static_cast<QSocketNotifier*>(dbus_watch_get_data(watch));
-	Q_UNUSED(data);
-	delete notifier;
+	QMap<quint32, Notification*>::iterator it = _notifs.begin();
+	while (it != _notifs.end()) {
+		delete it.value();
+	}
+
+	removeMatchRule("type='method_call',interface='org.freedesktop.Notifications',member='Notify',eavesdrop='true'");
+	removeMatchRule("type='method_return',sender='org.freedesktop.Notifications',eavesdrop='true'");
+	removeMatchRule("type='signal',sender='org.freedesktop.Notifications',path='/org/freedesktop/Notifications',interface='org.freedesktop.Notifications',member='NotificationClosed'");
+
+	dbus_connection_remove_filter(_conn, busMessageFilter, this);
+
+	dbus_connection_close(_conn);
+	dbus_connection_unref(_conn);
 }
 
-void bus_watch_toggle(DBusWatch *watch, void *data)
+void NotificationMonitorPrivate::processIncomingNotification(quint32 id, const QVariantHash &content)
 {
-	QSocketNotifier *notifier = static_cast<QSocketNotifier*>(dbus_watch_get_data(watch));
-	Q_UNUSED(data);
-	notifier->setEnabled(dbus_watch_get_enabled(watch));
+	Q_Q(NotificationMonitor);
+	qCDebug(notificationMonitorCat) << "Incoming notification" << id << content;
+
+	Notification *n = _notifs.value(id, 0);
+
+	bool is_new_notification = !n;
+	if (is_new_notification) {
+		n = new Notification(id, q);
+	}
+
+	n->setSender(content["sender"].toString());
+	n->setSummary(content["summary"].toString());
+	n->setBody(content["body"].toString());
+	n->setIcon(content["icon"].toString());
+
+	QDateTime timestamp = content["timestamp"].toDateTime();
+	if (timestamp.isValid()) {
+		n->setTimestamp(timestamp);
+	} else if (is_new_notification) {
+		n->setTimestamp(QDateTime::currentDateTime());
+	}
+
+	if (is_new_notification) {
+		_notifs.insert(id, n);
+		emit q->notification(n);
+	}
 }
 
-QVariantHash parse_notify_call(DBusMessage *msg)
+void NotificationMonitorPrivate::processCloseNotification(quint32 id, quint32 reason)
+{
+	qCDebug(notificationMonitorCat) << "Close notification" << id << reason;
+	Notification *n = _notifs.value(id, 0);
+	if (n) {
+		_notifs.remove(id);
+		emit n->closed(static_cast<Notification::CloseReason>(reason));
+		n->deleteLater();
+	} else {
+		qCDebug(notificationMonitorCat) << " but it is not found";
+	}
+}
+
+void NotificationMonitorPrivate::sendMessageWithString(const char *service, const char *path, const char *iface, const char *method, const char *arg)
+{
+	DBusMessage *msg = dbus_message_new_method_call(service, path, iface, method);
+	Q_ASSERT(msg);
+	dbus_message_set_no_reply(msg, TRUE);
+	dbus_message_append_args(msg,
+							 DBUS_TYPE_STRING, &arg,
+							 DBUS_TYPE_INVALID);
+	dbus_connection_send(_conn, msg, NULL);
+	dbus_message_unref(msg);
+}
+
+void NotificationMonitorPrivate::addMatchRule(const char *rule)
+{
+	sendMessageWithString("org.freedesktop.DBus", "/",
+						  "org.freedesktop.DBus", "AddMatch", rule);
+}
+
+void NotificationMonitorPrivate::removeMatchRule(const char *rule)
+{
+	sendMessageWithString("org.freedesktop.DBus", "/",
+						  "org.freedesktop.DBus", "RemoveMatch", rule);
+}
+
+QVariantHash NotificationMonitorPrivate::parseNotifyCall(DBusMessage *msg) const
 {
 	QVariantHash r;
 	DBusMessageIter iter, sub;
@@ -74,7 +164,7 @@ QVariantHash parse_notify_call(DBusMessage *msg)
 	qint32 expire_timeout;
 
 	if (strcmp(dbus_message_get_signature(msg), "susssasa{sv}i") != 0) {
-		qWarning() << "Invalid signature";
+		qCWarning(notificationMonitorCat) << "Invalid signature";
 		return r;
 	}
 
@@ -143,27 +233,73 @@ QVariantHash parse_notify_call(DBusMessage *msg)
 	return r;
 }
 
-DBusHandlerResult message_filter(DBusConnection *conn, DBusMessage *msg, void *user_data)
+dbus_bool_t NotificationMonitorPrivate::busWatchAdd(DBusWatch *watch, void *data)
+{
+	NotificationMonitorPrivate *self = static_cast<NotificationMonitorPrivate*>(data);
+	NotificationMonitor *monitor = self->q_func();
+	int socket = dbus_watch_get_socket(watch);
+	int flags = dbus_watch_get_flags(watch);
+
+	QSocketNotifier::Type type;
+	switch (flags) {
+	case DBUS_WATCH_READABLE:
+		type = QSocketNotifier::Read;
+		break;
+	case DBUS_WATCH_WRITABLE:
+		type = QSocketNotifier::Write;
+		break;
+	default:
+		qCWarning(notificationMonitorCat) << "Can't add this type of watch" << flags;
+		return FALSE;
+	}
+
+	QSocketNotifier *notifier = new QSocketNotifier(socket, type, monitor);
+	dbus_watch_set_data(watch, notifier, NULL);
+
+	notifier->setEnabled(dbus_watch_get_enabled(watch));
+	notifier->setProperty("dbus-watch", QVariant::fromValue<void*>(watch));
+
+	notifier->connect(notifier, SIGNAL(activated(int)),
+					  monitor, SLOT(handleBusSocketActivated()));
+
+	return TRUE;
+}
+
+void NotificationMonitorPrivate::busWatchRemove(DBusWatch *watch, void *data)
 {
-	NotificationMonitor *monitor = static_cast<NotificationMonitor*>(user_data);
+	QSocketNotifier *notifier = static_cast<QSocketNotifier*>(dbus_watch_get_data(watch));
+	Q_UNUSED(data);
+	delete notifier;
+}
+
+void NotificationMonitorPrivate::busWatchToggle(DBusWatch *watch, void *data)
+{
+	QSocketNotifier *notifier = static_cast<QSocketNotifier*>(dbus_watch_get_data(watch));
+	Q_UNUSED(data);
+	notifier->setEnabled(dbus_watch_get_enabled(watch));
+}
+
+DBusHandlerResult NotificationMonitorPrivate::busMessageFilter(DBusConnection *conn, DBusMessage *msg, void *user_data)
+{
+	NotificationMonitorPrivate *self = static_cast<NotificationMonitorPrivate*>(user_data);
 	DBusError error = DBUS_ERROR_INIT;
 	Q_UNUSED(conn);
 	switch (dbus_message_get_type(msg)) {
 	case DBUS_MESSAGE_TYPE_METHOD_CALL:
 		if (dbus_message_is_method_call(msg, "org.freedesktop.Notifications", "Notify")) {
 			quint32 serial = dbus_message_get_serial(msg);
-			QVariantHash content = parse_notify_call(msg);
-			pending_confirmation.insert(serial, content);
+			QVariantHash content = self->parseNotifyCall(msg);
+			self->_pending_confirmation.insert(serial, content);
 		}
 		break;
 	case DBUS_MESSAGE_TYPE_METHOD_RETURN:
-		if (pending_confirmation.contains(dbus_message_get_reply_serial(msg))) {
+		if (self->_pending_confirmation.contains(dbus_message_get_reply_serial(msg))) {
 			quint32 id;
 			if (dbus_message_get_args(msg, &error, DBUS_TYPE_UINT32, &id, DBUS_TYPE_INVALID)) {
-				QVariantHash content = pending_confirmation.take(dbus_message_get_reply_serial(msg));
-				monitor->processIncomingNotification(id, content);
+				QVariantHash content = self->_pending_confirmation.take(dbus_message_get_reply_serial(msg));
+				self->processIncomingNotification(id, content);
 			} else {
-				qWarning() << "Could not parse notification method return";
+				qCWarning(notificationMonitorCat) << "Could not parse notification method return";
 			}
 		}
 		break;
@@ -174,149 +310,42 @@ DBusHandlerResult message_filter(DBusConnection *conn, DBusMessage *msg, void *u
 									  DBUS_TYPE_UINT32, &id,
 									  DBUS_TYPE_UINT32, &reason,
 									  DBUS_TYPE_INVALID)) {
-				monitor->processCloseNotification(id, reason);
+				self->processCloseNotification(id, reason);
 			} else {
-				qWarning() << "Failed to parse notification signal arguments";
+				qCWarning(notificationMonitorCat) << "Failed to parse notification signal arguments";
 			}
 
 		}
 		break;
 	}
-	return DBUS_HANDLER_RESULT_HANDLED;
-}
 
-void send_message_with_string(const char *service, const char *path, const char *iface, const char *method, const char *arg)
-{
-	DBusMessage *msg = dbus_message_new_method_call(service, path, iface, method);
-	Q_ASSERT(msg);
-	dbus_message_set_no_reply(msg, TRUE);
-	dbus_message_append_args(msg,
-							 DBUS_TYPE_STRING, &arg,
-							 DBUS_TYPE_INVALID);
-	dbus_connection_send(bus_connection, msg, NULL);
-	dbus_message_unref(msg);
+	return DBUS_HANDLER_RESULT_HANDLED;
 }
 
-void add_match_rule(const char *rule)
+void NotificationMonitorPrivate::handleBusSocketActivated()
 {
-	send_message_with_string("org.freedesktop.DBus", "/",
-							 "org.freedesktop.DBus", "AddMatch", rule);
-}
+	Q_Q(NotificationMonitor);
+	QSocketNotifier *notifier = static_cast<QSocketNotifier*>(q->sender());
+	DBusWatch *watch = static_cast<DBusWatch*>(notifier->property("dbus-watch").value<void*>());
 
-void remove_match_rule(const char *rule)
-{
-	send_message_with_string("org.freedesktop.DBus", "/",
-							 "org.freedesktop.DBus", "RemoveMatch", rule);
-}
+	dbus_watch_handle(watch, dbus_watch_get_flags(watch));
 
+	while (dbus_connection_get_dispatch_status(_conn) == DBUS_DISPATCH_DATA_REMAINS) {
+		dbus_connection_dispatch(_conn);
+	}
 }
 
 NotificationMonitor::NotificationMonitor(QObject *parent) :
-	QObject(parent)
+	QObject(parent), d_ptr(new NotificationMonitorPrivate(this))
 {
-	Q_ASSERT(!bus_connection);
-	DBusError error = DBUS_ERROR_INIT;
-	bus_connection = dbus_bus_get_private(DBUS_BUS_SESSION, &error);
-	if (!bus_connection) {
-		qWarning() << "Could not connect to the session bus";
-		return;
-	}
 
-	dbus_connection_set_exit_on_disconnect(bus_connection, FALSE);
-
-	dbus_connection_set_watch_functions(bus_connection, bus_watch_add,
-										bus_watch_remove, bus_watch_toggle,
-										this, NULL);
-
-	add_match_rule("type='method_call',interface='org.freedesktop.Notifications',member='Notify',eavesdrop='true'");
-	add_match_rule("type='method_return',sender='org.freedesktop.Notifications',eavesdrop='true'");
-	add_match_rule("type='signal',sender='org.freedesktop.Notifications',path='/org/freedesktop/Notifications',interface='org.freedesktop.Notifications',member='NotificationClosed'");
-
-	dbus_bool_t result = dbus_connection_add_filter(bus_connection, message_filter,
-													this, NULL);
-	if (!result) {
-		qWarning() << "Could not add filter";
-	}
-
-	qDebug() << "Starting notification monitor";
 }
 
 NotificationMonitor::~NotificationMonitor()
 {
-	Q_ASSERT(bus_connection);
-
-	remove_match_rule("type='method_call',interface='org.freedesktop.Notifications',member='Notify',eavesdrop='true'");
-	remove_match_rule("type='method_return',sender='org.freedesktop.Notifications',eavesdrop='true'");
-	remove_match_rule("type='signal',sender='org.freedesktop.Notifications',path='/org/freedesktop/Notifications',interface='org.freedesktop.Notifications',member='NotificationClosed'");
-
-	dbus_connection_remove_filter(bus_connection, message_filter, this);
-
-	dbus_connection_close(bus_connection);
-	dbus_connection_unref(bus_connection);
-	bus_connection = NULL;
+	delete d_ptr;
 }
 
-NotificationMonitor *NotificationMonitor::instance()
-{
-	if (!global_monitor) {
-		global_monitor = new NotificationMonitor;
-	}
-	return global_monitor;
 }
 
-void NotificationMonitor::processIncomingNotification(quint32 id, const QVariantHash &content)
-{
-	qDebug() << "Incoming notification" << id << content;
-	Notification *n = _notifs.value(id, 0);
-	if (n) {
-		QString s = content["summary"].toString();
-		if (n->_summary != s) {
-			n->_summary = s;
-			emit n->summaryChanged();
-		}
-		s = content["body"].toString();
-		if (n->_body != s) {
-			n->_body = s;
-			emit n->bodyChanged();
-		}
-		s = content["icon"].toString();
-		if (n->_icon != s) {
-			n->_icon = s;
-			emit n->iconChanged();
-		}
-		QDateTime dt = content["timestamp"].toDateTime();
-		if (dt.isValid() && n->_timestamp != dt) {
-			n->_timestamp = dt;
-			emit n->timestampChanged();
-		}
-	} else {
-		n = new Notification(this);
-		n->_id = id;
-		n->_sender = content["sender"].toString();
-		n->_summary = content["summary"].toString();
-		n->_body = content["body"].toString();
-		n->_timestamp = content["timestamp"].toDateTime();
-		n->_icon = content["icon"].toString();
-
-		if (!n->_timestamp.isValid()) {
-			n->_timestamp = QDateTime::currentDateTime();
-		}
-
-		_notifs.insert(id, n);
-
-		emit notification(n);
-	}
-}
-
-void NotificationMonitor::processCloseNotification(quint32 id, quint32 reason)
-{
-	qDebug() << "Close notification" << id << reason;
-	Notification *n = _notifs.value(id, 0);
-	if (n) {
-		_notifs.remove(id);
-		emit n->closed(reason);
-		n->deleteLater();
-	} else {
-		qDebug() << " but it is not found";
-	}
-}
+#include "moc_notificationmonitor.cpp"
diff --git a/notificationmonitor.h b/notificationmonitor.h
index 8563053..1cb7cca 100644
--- a/notificationmonitor.h
+++ b/notificationmonitor.h
@@ -1,32 +1,34 @@
 #ifndef NOTIFICATIONMONITOR_H
 #define NOTIFICATIONMONITOR_H
 
-#include <QtCore/QObject>
+#include <QtCore/QLoggingCategory>
 #include <QtCore/QMap>
+#include <QtCore/QObject>
+
+#include "notification.h"
 
 namespace watchfish
 {
 
-class Notification;
+Q_DECLARE_LOGGING_CATEGORY(notificationMonitorCat)
+
+class NotificationMonitorPrivate;
 
 class NotificationMonitor : public QObject
 {
 	Q_OBJECT
+	Q_DECLARE_PRIVATE(NotificationMonitor)
 
 public:
+	explicit NotificationMonitor(QObject *parent = 0);
 	~NotificationMonitor();
 
-	static NotificationMonitor *instance();
-
-	void processIncomingNotification(quint32 id, const QVariantHash &content);
-	void processCloseNotification(quint32 id, quint32 reason);
-
 signals:
 	void notification(Notification *n);
 
 private:
-	explicit NotificationMonitor(QObject *parent = 0);
-	QMap<quint32, Notification*> _notifs;
+	Q_PRIVATE_SLOT(d_func(), void handleBusSocketActivated())
+	NotificationMonitorPrivate * const d_ptr;
 };
 
 }
-- 
cgit v1.2.3