From a1ec50943454ba4674c8c5e5d5dadcdbd414b111 Mon Sep 17 00:00:00 2001
From: "Javier S. Pedro" <maemo@javispedro.com>
Date: Sat, 24 Sep 2011 20:52:17 +0200
Subject: Incoming phone calls working!

---
 libsowatch/notification.cpp       |   8 ++-
 libsowatch/notification.h         |  33 +++++++----
 libsowatch/notificationprovider.h |  11 +---
 libsowatch/watch.h                |  18 ++++--
 libsowatch/watchserver.cpp        | 116 ++++++++++++++++++++++++++++++--------
 libsowatch/watchserver.h          |  24 +++++---
 6 files changed, 151 insertions(+), 59 deletions(-)

(limited to 'libsowatch')

diff --git a/libsowatch/notification.cpp b/libsowatch/notification.cpp
index 55f3e78..b4c97b2 100644
--- a/libsowatch/notification.cpp
+++ b/libsowatch/notification.cpp
@@ -2,12 +2,16 @@
 
 using namespace sowatch;
 
-Notification::Notification(Type type, const QDateTime& dateTime, QString title, QString body)
-	: _type(type), _dateTime(dateTime), _title(title), _body(body)
+Notification::Notification(QObject *parent)
+	: QObject(parent)
 {
 }
 
 Notification::~Notification()
 {
+}
 
+QImage Notification::image() const
+{
+	return QImage();
 }
diff --git a/libsowatch/notification.h b/libsowatch/notification.h
index 7a46ab7..8e58653 100644
--- a/libsowatch/notification.h
+++ b/libsowatch/notification.h
@@ -3,16 +3,21 @@
 
 #include <QtCore/QString>
 #include <QtCore/QDateTime>
+#include <QtGui/QImage>
 #include "sowatch_global.h"
 
 namespace sowatch
 {
 
-class SOWATCH_EXPORT Notification
+class SOWATCH_EXPORT Notification : public QObject
 {
+	Q_OBJECT
+	Q_ENUMS(Type)
+
 public:
 	enum Type {
 		OtherNotification = 0,
+		CallNotification,
 		MissedCallNotification,
 		SmsNotification,
 		MmsNotification,
@@ -22,19 +27,23 @@ public:
 		TypeCount
 	};
 
-	Notification(Type type, const QDateTime& dateTime, QString title, QString body);
-	~Notification();
+	explicit Notification(QObject *parent = 0);
+	virtual ~Notification();
+
+	virtual Type type() const = 0;
+	virtual uint count() const = 0;
+	virtual QDateTime dateTime() const = 0;
+	virtual QString title() const = 0;
+	virtual QString body() const = 0;
+	virtual QImage image() const;
 
-	inline Type type() const { return _type; }
-	inline QDateTime dateTime() const { return _dateTime; }
-	inline QString title() const { return _title; }
-	inline QString body() const { return _body; }
+public slots:
+	virtual void activate() = 0;
+	virtual void clear() = 0;
 
-protected:
-	Type _type;
-	QDateTime _dateTime;
-	QString _title;
-	QString _body;
+signals:
+	void changed();
+	void cleared();
 };
 
 }
diff --git a/libsowatch/notificationprovider.h b/libsowatch/notificationprovider.h
index fe835ef..31182f1 100644
--- a/libsowatch/notificationprovider.h
+++ b/libsowatch/notificationprovider.h
@@ -15,17 +15,8 @@ protected:
 	explicit NotificationProvider(QObject *parent = 0);
 	virtual ~NotificationProvider();
 
-public:
-	virtual int getCount(Notification::Type type) = 0;
-
 signals:
-	void notification(const Notification& n);
-	void unreadCountChanged(Notification::Type type);
-
-	void weatherUpdate();
-
-	void incomingCall(const QString& displayName);
-	void endIncomingCall();
+	void incomingNotification(Notification* notification);
 };
 
 }
diff --git a/libsowatch/watch.h b/libsowatch/watch.h
index 5552a8c..eabfa06 100644
--- a/libsowatch/watch.h
+++ b/libsowatch/watch.h
@@ -21,28 +21,38 @@ public:
 	explicit Watch(QObject* parent = 0);
 	~Watch();
 
+	/** Return a string identiyfying this watch's model. */
 	virtual QString model() const = 0;
+	/** Should return true if the watch is connected. */
 	virtual bool isConnected() const = 0;
 
 	/** Indicates if watch is too busy atm and we should limit frame rate. */
 	virtual bool busy() const = 0;
 
+	/** Changes the current date/time on the watch. */
 	virtual QDateTime dateTime() = 0;
 	virtual void setDateTime(const QDateTime& dateTime) = 0;
 
+	/** Tells the watch to update the unread notifications count, if visible. */
 	virtual void updateNotificationCount(Notification::Type type, int count) = 0;
 
 signals:
+	/** The watch has been found and linked to. */
 	void connected();
+	/** The watch connection has been lost. */
 	void disconnected();
+	/** The watch has returned to the idle screen by either inactivity or notification cleared/timeout. */
+	void idling();
 	void buttonPressed(int button);
 	void buttonReleased(int button);
 
 public slots:
-	virtual void vibrate(bool on) = 0;
-	virtual void showNotification(const Notification& n) = 0;
-	virtual void startRinging(const QString& text) = 0;
-	virtual void stopRinging() = 0;
+	/** Go back to the idle screen. */
+	virtual void displayIdleScreen() = 0;
+	/** A standard notification; it's up to the watch when to stop showing it. */
+	virtual void displayNotification(Notification* n) = 0;
+	/** Enter application mode. */
+	virtual void displayApplication() = 0;
 };
 
 }
diff --git a/libsowatch/watchserver.cpp b/libsowatch/watchserver.cpp
index 942131f..d95d4fb 100644
--- a/libsowatch/watchserver.cpp
+++ b/libsowatch/watchserver.cpp
@@ -13,6 +13,7 @@ WatchServer::WatchServer(Watch* watch, QObject* parent) :
 {
 	connect(_watch, SIGNAL(connected()), SLOT(watchConnected()));
 	connect(_watch, SIGNAL(disconnected()), SLOT(watchDisconnected()));
+	connect(_watch, SIGNAL(idling()), SLOT(watchIdling()));
 }
 
 Watch* WatchServer::watch()
@@ -23,13 +24,8 @@ Watch* WatchServer::watch()
 void WatchServer::addProvider(NotificationProvider *provider)
 {
 	provider->setParent(this);
-
-	connect(provider, SIGNAL(notification(Notification)), SLOT(notificationEmitted(Notification)));
-	connect(provider, SIGNAL(unreadCountChanged(Notification::Type)), SLOT(unreadCountUpdated(Notification::Type)));
-	connect(provider, SIGNAL(incomingCall(QString)), SLOT(incomingCall(QString)));
-	connect(provider, SIGNAL(endIncomingCall()), SLOT(endIncomingCall()));
-
-	_providers.append(provider);
+	connect(provider, SIGNAL(incomingNotification(Notification*)), SLOT(notificationReceived(Notification*)));
+	// And that's it, really.
 }
 
 void WatchServer::runWatchlet(const QString& id)
@@ -39,7 +35,7 @@ void WatchServer::runWatchlet(const QString& id)
 	}
 	_currentWatchlet = _watchlets[id];
 	if (_watch->isConnected()) {
-		_currentWatchlet->activate();
+		reactivateCurrentWatchlet();
 	}
 }
 
@@ -58,10 +54,41 @@ void WatchServer::registerWatchlet(Watchlet *watchlet)
 	_watchlets[watchlet->id()] = watchlet;
 }
 
+void WatchServer::reactivateCurrentWatchlet()
+{
+	Q_ASSERT(_currentWatchlet != 0);
+	_watch->displayApplication();
+	_currentWatchlet->activate();
+}
+
+void WatchServer::nextNotification()
+{
+	if (!_watch->isConnected()) return;
+	if (!_pendingNotifications.empty()) {
+		Notification *n = _pendingNotifications.head();
+		_watch->displayNotification(n);
+	} else if (_currentWatchlet) {
+		reactivateCurrentWatchlet();
+	} else {
+		_watch->displayIdleScreen();
+	}
+}
+
+uint WatchServer::getNotificationCount(Notification::Type type)
+{
+	uint count = 0;
+	foreach (Notification* n, _notifications[type]) {
+		count += n->count();
+	}
+	return count;
+}
+
 void WatchServer::watchConnected()
 {
-	if (_currentWatchlet) {
-		_currentWatchlet->activate();
+	if (!_pendingNotifications.isEmpty()) {
+		nextNotification();
+	} else if (_currentWatchlet) {
+		reactivateCurrentWatchlet();
 	}
 }
 
@@ -70,30 +97,73 @@ void WatchServer::watchDisconnected()
 	if (_currentWatchlet) {
 		_currentWatchlet->deactivate();
 	}
+	_pendingNotifications.clear();
 }
 
-void WatchServer::notificationEmitted(const Notification &notification)
+void WatchServer::watchIdling()
 {
-	// TODO app loses button focus...
-	_watch->showNotification(notification);
+	qDebug() << "Watch idling";
+	if (!_pendingNotifications.empty()) {
+		_pendingNotifications.dequeue();
+		nextNotification();
+	}
 }
 
-void WatchServer::unreadCountUpdated(Notification::Type type)
+void WatchServer::notificationReceived(Notification *notification)
 {
-	uint count = 0;
-	foreach(NotificationProvider* provider, _providers)
-	{
-		count += provider->getCount(type);
+	const Notification::Type type = notification->type();
+	_notifications[type].append(notification);
+
+	connect(notification, SIGNAL(changed()), SLOT(notificationChanged()));
+	connect(notification, SIGNAL(cleared()), SLOT(notificationCleared()));
+
+	qDebug() << "notification received" << notification->title() << notification->count();
+
+	_watch->updateNotificationCount(type, getNotificationCount(type));
+	if (_pendingNotifications.isEmpty()) {
+		_pendingNotifications.enqueue(notification);
+		nextNotification();
+	} else if (type == Notification::CallNotification) {
+		// Oops, priority!!!!
+		_pendingNotifications.prepend(notification);
+		nextNotification();
+	} else {
+		_pendingNotifications.enqueue(notification);
 	}
-	_watch->updateNotificationCount(type, count);
 }
 
-void WatchServer::incomingCall(const QString &displayText)
+void WatchServer::notificationChanged()
 {
-	qDebug() << "Incoming call" << displayText;
+	QObject *obj = sender();
+	if (obj) {
+		Notification* n = static_cast<Notification*>(obj);
+		const Notification::Type type = n->type();
+
+		qDebug() << "notification changed" << n->title() << n->count();
+
+		_watch->updateNotificationCount(type, getNotificationCount(type));
+		if (!_pendingNotifications.isEmpty() && _pendingNotifications.head() == n) {
+			nextNotification();
+		}
+	}
 }
 
-void WatchServer::endIncomingCall()
+void WatchServer::notificationCleared()
 {
-	qDebug() << "End incoming call";
+	QObject *obj = sender();
+	if (obj) {
+		Notification* n = static_cast<Notification*>(obj);
+		const Notification::Type type = n->type();
+		_notifications[type].removeOne(n);
+
+		qDebug() << "notification deleted" << n->title() << n->count();
+
+		_watch->updateNotificationCount(type, getNotificationCount(type));
+		if (!_pendingNotifications.isEmpty() && _pendingNotifications.head() == n) {
+			_pendingNotifications.removeAll(n);
+			nextNotification();
+		} else {
+			_pendingNotifications.removeAll(n);
+		}
+	}
 }
diff --git a/libsowatch/watchserver.h b/libsowatch/watchserver.h
index 27d29aa..1ece104 100644
--- a/libsowatch/watchserver.h
+++ b/libsowatch/watchserver.h
@@ -1,9 +1,9 @@
 #ifndef SOWATCH_WATCHSERVER_H
 #define SOWATCH_WATCHSERVER_H
 
-#include <QtCore/QObject>
+#include <QtCore/QList>
 #include <QtCore/QMap>
-#include <QtCore/QSignalMapper>
+#include <QtCore/QQueue>
 
 #include "sowatch_global.h"
 #include "notification.h"
@@ -32,20 +32,28 @@ public:
 
 protected:
 	Watch* _watch;
-	Watchlet* _currentWatchlet;
 
 	QMap<QString, Watchlet*> _watchlets;
-	QList<NotificationProvider*> _providers;
+
+	/** Stores current notifications, classified by type. */
+	QList<Notification*> _notifications[Notification::TypeCount];
+	QQueue<Notification*> _pendingNotifications;
+
+	Watchlet* _currentWatchlet;
 
 	void registerWatchlet(Watchlet *watchlet);
+	void reactivateCurrentWatchlet();
+
+	void nextNotification();
+	uint getNotificationCount(Notification::Type type);
 
 protected slots:
 	void watchConnected();
 	void watchDisconnected();
-	void notificationEmitted(const Notification& notification);
-	void unreadCountUpdated(Notification::Type type);
-	void incomingCall(const QString& displayText);
-	void endIncomingCall();
+	void watchIdling();
+	void notificationReceived(Notification* notification);
+	void notificationChanged();
+	void notificationCleared();
 
 friend class Watchlet;
 };
-- 
cgit v1.2.3