summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJavier S. Pedro <maemo@javispedro.com>2012-08-10 00:45:24 +0200
committerJavier S. Pedro <maemo@javispedro.com>2012-08-10 00:45:24 +0200
commitd194a6112299cfe045c34e5cdb6adbbb81418d09 (patch)
tree4973f946b6701c8aea8bed73e5c4c6c978ce8e66
parentb1ccb04d7dd2fb20def829be084474ed329d4988 (diff)
downloadsowatch-d194a6112299cfe045c34e5cdb6adbbb81418d09.tar.gz
sowatch-d194a6112299cfe045c34e5cdb6adbbb81418d09.zip
new watchhandler for watchlet/prov lifecycle mgmt
-rw-r--r--libsowatch/notificationprovider.h2
-rw-r--r--libsowatch/watchserver.cpp43
-rw-r--r--libsowatch/watchserver.h10
-rw-r--r--metawatch/metawatch.cpp10
-rw-r--r--metawatch/metawatchscanner.cpp2
-rw-r--r--sowatchd/daemon.cpp105
-rw-r--r--sowatchd/daemon.h4
-rw-r--r--sowatchd/sowatchd.pro6
-rw-r--r--sowatchd/watchhandler.cpp132
-rw-r--r--sowatchd/watchhandler.h41
-rw-r--r--sowatchui/sowatchui.pro4
-rw-r--r--sowatchui/watchesmodel.cpp7
12 files changed, 258 insertions, 108 deletions
diff --git a/libsowatch/notificationprovider.h b/libsowatch/notificationprovider.h
index d5449f8..b18b3d6 100644
--- a/libsowatch/notificationprovider.h
+++ b/libsowatch/notificationprovider.h
@@ -12,7 +12,7 @@ class SOWATCH_EXPORT NotificationProvider : public QObject
{
Q_OBJECT
-protected:
+public:
explicit NotificationProvider(QObject *parent = 0);
virtual ~NotificationProvider();
diff --git a/libsowatch/watchserver.cpp b/libsowatch/watchserver.cpp
index d5db9da..2cadc98 100644
--- a/libsowatch/watchserver.cpp
+++ b/libsowatch/watchserver.cpp
@@ -50,21 +50,46 @@ void WatchServer::setNextWatchletButton(const QString& value)
}
}
-void WatchServer::addProvider(NotificationProvider *provider)
+void WatchServer::addWatchlet(Watchlet *watchlet)
{
- provider->setParent(this);
- connect(provider, SIGNAL(incomingNotification(Notification*)), SLOT(postNotification(Notification*)));
+ insertWatchlet(_watchlets.size(), watchlet);
}
-void WatchServer::addWatchlet(Watchlet *watchlet)
+void WatchServer::insertWatchlet(int position, Watchlet *watchlet)
+{
+ const QString id = watchlet->id();
+ Q_ASSERT(watchlet->_server == this);
+ Q_ASSERT(!_watchletIds.contains(id));
+
+ _watchlets.insert(position, watchlet);
+ _watchletIds[id] = watchlet;
+}
+
+void WatchServer::removeWatchlet(const Watchlet *watchlet)
{
- // A watchlet is best not reparented; just look that the parent is correct
+ const QString id = watchlet->id();
+
Q_ASSERT(watchlet->_server == this);
- _watchlets.append(watchlet);
- QString id = watchlet->id();
- if (!_watchletIds.contains(id)) {
- _watchletIds[id] = watchlet;
+ Q_ASSERT(_watchletIds.contains(id));
+
+ if (_currentWatchlet == watchlet) {
+ closeWatchlet();
}
+
+ _watchlets.removeAll(const_cast<Watchlet*>(watchlet));
+ _watchletIds.remove(id);
+}
+
+void WatchServer::addProvider(NotificationProvider *provider)
+{
+ connect(provider, SIGNAL(incomingNotification(Notification*)),
+ this, SLOT(postNotification(Notification*)));
+}
+
+void WatchServer::removeProvider(const NotificationProvider *provider)
+{
+ disconnect(provider, SIGNAL(incomingNotification(Notification*)),
+ this, SLOT(postNotification(Notification*)));
}
QList<Notification*> WatchServer::liveNotifications()
diff --git a/libsowatch/watchserver.h b/libsowatch/watchserver.h
index 54d3dc1..c1e6ef0 100644
--- a/libsowatch/watchserver.h
+++ b/libsowatch/watchserver.h
@@ -25,15 +25,19 @@ class SOWATCH_EXPORT WatchServer : public QObject
Q_PROPERTY(QString nextWatchletButton READ nextWatchletButton WRITE setNextWatchletButton)
public:
- explicit WatchServer(Watch* watch, QObject* parent = 0);
+ explicit WatchServer(Watch *watch, QObject *parent = 0);
Watch* watch();
QString nextWatchletButton() const;
void setNextWatchletButton(const QString& value);
- void addWatchlet(Watchlet* watchlet);
- void addProvider(NotificationProvider* provider);
+ void addWatchlet(Watchlet *watchlet);
+ void insertWatchlet(int position, Watchlet *watchlet);
+ void removeWatchlet(const Watchlet *watchlet);
+
+ void addProvider(NotificationProvider *provider);
+ void removeProvider(const NotificationProvider *provider);
/** Get a list of all current live notifications. */
QList<Notification*> liveNotifications();
diff --git a/metawatch/metawatch.cpp b/metawatch/metawatch.cpp
index fe080e4..6f8edca 100644
--- a/metawatch/metawatch.cpp
+++ b/metawatch/metawatch.cpp
@@ -120,7 +120,13 @@ MetaWatch::MetaWatch(ConfigKey* settings, QObject* parent) :
MetaWatch::~MetaWatch()
{
- delete _paintEngine;
+ if (_socket) {
+ _socket->close();
+ delete _socket;
+ }
+ if (_paintEngine) {
+ delete _paintEngine;
+ }
}
QPaintEngine* MetaWatch::paintEngine() const
@@ -724,7 +730,7 @@ void MetaWatch::socketDisconnected()
timeToNextRetry = connectRetryTimes[_connectRetries];
_connectRetries++;
}
- qDebug() << "Backing off for " << timeToNextRetry << "seconds for next retry";
+ qDebug() << "Backing off for" << timeToNextRetry << "seconds for next retry";
_connectAlignedTimer->start(timeToNextRetry / 2, timeToNextRetry * 2);
if (_connectAlignedTimer->lastError() != QSystemAlignedTimer::NoError) {
// I would like to know why QtM couldn't _emulate_ here using a QTimer by itself.
diff --git a/metawatch/metawatchscanner.cpp b/metawatch/metawatchscanner.cpp
index 99ccc93..a34f71b 100644
--- a/metawatch/metawatchscanner.cpp
+++ b/metawatch/metawatchscanner.cpp
@@ -37,9 +37,11 @@ void MetaWatchScanner::handleDiscoveredService(const QBluetoothServiceInfo &info
qDebug() << "metawatch bluetooth scan found:" << deviceName;
if (deviceName.contains("Digital", Qt::CaseInsensitive)) {
foundInfo["driver"] = QString("metawatch-digital");
+ foundInfo["next-watchlet-button"] = QString("A");
emit watchFound(foundInfo);
} else if (deviceName.contains("Analog", Qt::CaseInsensitive)) {
foundInfo["driver"] = QString("metawatch-analog");
+ foundInfo["next-watchlet-button"] = QString("A");
emit watchFound(foundInfo);
} else {
qWarning() << "Unknown MetaWatch device found:" << deviceName;
diff --git a/sowatchd/daemon.cpp b/sowatchd/daemon.cpp
index c668f59..bcf3686 100644
--- a/sowatchd/daemon.cpp
+++ b/sowatchd/daemon.cpp
@@ -21,14 +21,8 @@ Daemon::Daemon(QObject *parent) :
QString Daemon::getWatchStatus(const QString &name)
{
- if (_servers.contains(name)) {
- WatchServer* server = _servers[name];
- Watch* watch = server->watch();
- if (watch->isConnected()) {
- return QLatin1String("connected");
- } else {
- return QLatin1String("enabled");
- }
+ if (_watches.contains(name)) {
+ return _watches[name]->status();
} else {
return QLatin1String("disabled");
}
@@ -42,87 +36,29 @@ void Daemon::terminate()
void Daemon::startWatch(const QString &name)
{
qDebug() << "Starting watch" << name;
- QScopedPointer<ConfigKey> watchSettings(_config->getSubkey(name));
-
- const QString driver = watchSettings->value("driver").toString().toLower();
- if (driver.isEmpty()) {
- qWarning() << "Watch" << name << "has no driver setting";
- return;
- }
-
- WatchPluginInterface *watchPlugin = _registry->getWatchPlugin(driver);
- if (!watchPlugin) {
- qWarning() << "Invalid driver" << driver;
- return;
- }
-
- // Create the watch object from the plugin
- Watch *watch = watchPlugin->getWatch(driver, watchSettings.data(), this);
- if (!watch) {
- qWarning() << "Driver" << driver << "failed to initiate watch";
- }
-
- // Create the server
- WatchServer* server = new WatchServer(watch, this);
- _servers[name] = server;
-
+ QScopedPointer<ConfigKey> watchConfig(_config->getSubkey(name));
+ WatchHandler *handler = new WatchHandler(watchConfig.data(), this);
+ _status_mapper->setMapping(handler, name);
+ _watches[name] = handler;
handleWatchStatusChange(name);
-
- // Connect watch status signals
- _status_mapper->setMapping(watch, name);
- connect(watch, SIGNAL(connected()),
+ connect(handler, SIGNAL(statusChanged()),
_status_mapper, SLOT(map()));
- connect(watch, SIGNAL(disconnected()),
- _status_mapper, SLOT(map()));
-
- // Configure the server
- server->setNextWatchletButton(watchSettings->value("next-watchlet-button").toString());
-
- // Initialize providers
- QStringList list;
- list = watchSettings->value("active-notifications").toStringList();
- foreach (const QString& s, list) {
- QScopedPointer<ConfigKey> settings(watchSettings->getSubkey(s));
- QString id = settings->value("id").toString().toLower();
- NotificationPluginInterface *plugin = _registry->getNotificationPlugin(id);
- if (plugin) {
- NotificationProvider *provider = plugin->getProvider(id, settings.data(), server);
- server->addProvider(provider);
- } else {
- qWarning() << "Unknown notification provider" << id;
- }
- }
-
- // Initialize watchlets
- list = watchSettings->value("active-watchlets").toStringList();
- foreach (const QString& s, list) {
- QScopedPointer<ConfigKey> settings(watchSettings->getSubkey(s));
- QString id = settings->value("id").toString().toLower();
- WatchletPluginInterface *plugin = _registry->getWatchletPlugin(id);
- if (plugin) {
- Watchlet *watchlet = plugin->getWatchlet(id, settings.data(), server);
- server->addWatchlet(watchlet);
- } else {
- qWarning() << "Unknown watchlet" << id;
- }
- }
}
void Daemon::stopWatch(const QString &name)
{
qDebug() << "Stopping watch" << name;
- WatchServer* server = _servers[name];
- Watch* watch = server->watch();
- server->deleteLater();
- watch->deleteLater();
- _servers.remove(name);
+ WatchHandler *handler = _watches[name];
+ _watches.remove(name);
+ _status_mapper->removeMappings(handler);
+ delete handler;
handleWatchStatusChange(name);
}
void Daemon::startEnabledWatches()
{
QStringList watches = _watches_list->value().toStringList();
- QSet<QString> startedWatches = _servers.keys().toSet();
+ QSet<QString> startedWatches = _watches.keys().toSet();
QSet<QString> removed = startedWatches - watches.toSet();
// Those watches have been entirely removed from the list, not disabled first
@@ -132,7 +68,7 @@ void Daemon::startEnabledWatches()
foreach (const QString& s, watches) {
bool enabled_in_config = _config->value(s + "/enable").toBool();
- bool currently_started = _servers.contains(s);
+ bool currently_started = _watches.contains(s);
if (enabled_in_config && !currently_started) {
startWatch(s);
@@ -145,12 +81,11 @@ void Daemon::startEnabledWatches()
void Daemon::handleSettingsChanged(const QString &subkey)
{
qDebug() << "Daemon settings changed" << subkey;
- static QRegExp enabled_key_pattern("^([^/])/enable$");
+ static QRegExp enabled_key_pattern("([^/]+)/enable");
if (enabled_key_pattern.exactMatch(subkey)) {
- QStringList watches = _watches_list->value().toStringList();
QString watchName = enabled_key_pattern.cap(1);
bool enabled_in_config = _config->value(subkey).toBool();
- bool currently_started = _servers.contains(watchName);
+ bool currently_started = _watches.contains(watchName);
if (enabled_in_config && !currently_started) {
startWatch(watchName);
@@ -164,14 +99,8 @@ void Daemon::handleSettingsChanged(const QString &subkey)
void Daemon::handleWatchStatusChange(const QString &name)
{
- if (_servers.contains(name)) {
- WatchServer* server = _servers[name];
- Watch* watch = server->watch();
- if (watch->isConnected()) {
- emit WatchStatusChanged(name, QLatin1String("connected"));
- } else {
- emit WatchStatusChanged(name, QLatin1String("enabled"));
- }
+ if (_watches.contains(name)) {
+ emit WatchStatusChanged(name, _watches[name]->status());
} else if (_watches_list->value().toStringList().contains(name)) {
emit WatchStatusChanged(name, QLatin1String("disabled"));
} else {
diff --git a/sowatchd/daemon.h b/sowatchd/daemon.h
index d35b56b..e3f748b 100644
--- a/sowatchd/daemon.h
+++ b/sowatchd/daemon.h
@@ -7,6 +7,8 @@
#include <sowatch.h>
+#include "watchhandler.h"
+
namespace sowatch
{
@@ -28,7 +30,7 @@ private:
Registry* _registry;
ConfigKey* _config;
ConfigKey* _watches_list;
- QMap<QString, WatchServer*> _servers;
+ QMap<QString, WatchHandler*> _watches;
QSignalMapper *_status_mapper;
void startWatch(const QString& name);
diff --git a/sowatchd/sowatchd.pro b/sowatchd/sowatchd.pro
index 4b1b668..9299f05 100644
--- a/sowatchd/sowatchd.pro
+++ b/sowatchd/sowatchd.pro
@@ -5,8 +5,10 @@ TEMPLATE = app
QT += core gui dbus
CONFIG -= app_bundle
-SOURCES += main.cpp daemon.cpp daemonadaptor.cpp
-HEADERS += global.h daemon.h daemonadaptor.h
+SOURCES += main.cpp daemon.cpp daemonadaptor.cpp \
+ watchhandler.cpp
+HEADERS += global.h daemon.h daemonadaptor.h \
+ watchhandler.h
LIBS += -L$$OUT_PWD/../libsowatch/ -lsowatch
INCLUDEPATH += $$PWD/../libsowatch
diff --git a/sowatchd/watchhandler.cpp b/sowatchd/watchhandler.cpp
new file mode 100644
index 0000000..e396c17
--- /dev/null
+++ b/sowatchd/watchhandler.cpp
@@ -0,0 +1,132 @@
+#include "watchhandler.h"
+
+using namespace sowatch;
+
+WatchHandler::WatchHandler(ConfigKey *config, QObject *parent)
+ : QObject(parent),
+ _config(config->getSubkey("", this))
+{
+ Registry *registry = Registry::registry();
+
+ qDebug() << "Starting watch handler on" << _config->key();
+
+ connect(_config, SIGNAL(subkeyChanged(QString)),
+ SLOT(handleConfigSubkeyChanged(QString)));
+
+ const QString driver = _config->value("driver").toString();
+ if (driver.isEmpty()) {
+ qWarning() << "Watch" << _config->value("name") << "has no driver setting";
+ return;
+ }
+
+ WatchPluginInterface *watchPlugin = registry->getWatchPlugin(driver);
+ if (!watchPlugin) {
+ qWarning() << "Invalid driver" << driver;
+ return;
+ }
+
+ // Create the watch object from the plugin
+ _watch = watchPlugin->getWatch(driver, _config, this);
+ if (!_watch) {
+ qWarning() << "Driver" << driver << "failed to initiate watch";
+ return;
+ }
+
+ // Setup watch status connections
+ connect(_watch, SIGNAL(connected()),
+ SIGNAL(statusChanged()));
+ connect(_watch, SIGNAL(connected()),
+ SIGNAL(statusChanged()));
+
+ // Now create the UI server
+ _server = new WatchServer(_watch, this);
+
+ // Configure the server
+ _server->setNextWatchletButton(_config->value("next-watchlet-button").toString());
+
+ updateProviders();
+ updateWatchlets();
+}
+
+QString WatchHandler::status() const
+{
+ if (_watch->isConnected()) {
+ return "connected";
+ } else if (_config->value("enable").toBool()) {
+ return "enabled";
+ } else {
+ return "disabled";
+ }
+}
+
+void WatchHandler::updateWatchlets()
+{
+ Registry *registry = Registry::registry();
+ QStringList newWatchlets = _config->value("watchlets").toStringList();
+ QStringList curWatchlets = _watchlet_order;
+
+ // TODO: Something better than removing all and readding
+ foreach (const QString& s, curWatchlets) {
+ Watchlet* watchlet = _watchlets[s];
+ _server->removeWatchlet(watchlet);
+ delete watchlet;
+ }
+
+ _watchlet_order.clear();
+ _watchlets.clear();
+
+ foreach (const QString& s, newWatchlets) {
+ WatchletPluginInterface *plugin = registry->getWatchletPlugin(s);
+ if (!plugin) {
+ qWarning() << "Unknown watchlet" << s;
+ continue;
+ }
+ ConfigKey *subconfig = _config->getSubkey(s);
+ Watchlet* watchlet = plugin->getWatchlet(s, subconfig, _server);
+ _watchlet_order << s;
+ _watchlets[s] = watchlet;
+ _server->addWatchlet(watchlet);
+ delete subconfig;
+ }
+
+ qDebug() << "Watchlets reloaded";
+}
+
+void WatchHandler::updateProviders()
+{
+ Registry *registry = Registry::registry();
+ QSet<QString> curProviders = _providers.keys().toSet();
+ QSet<QString> newProviders = _config->value("providers").toStringList().toSet();
+ QSet<QString> removed = curProviders - newProviders;
+ QSet<QString> added = newProviders - curProviders;
+
+ foreach (const QString& s, removed) {
+ NotificationProvider *provider = _providers[s];
+ _server->removeProvider(provider);
+ delete provider;
+ }
+
+ foreach (const QString& s, added) {
+ NotificationPluginInterface *plugin = registry->getNotificationPlugin(s);
+ if (!plugin) {
+ qWarning() << "Unknown notification provider" << s;
+ continue;
+ }
+ ConfigKey *subconfig = _config->getSubkey(s);
+ NotificationProvider *provider = plugin->getProvider(s, subconfig, _server);
+ _server->addProvider(provider);
+ _providers[s] = provider;
+ delete subconfig;
+ }
+}
+
+void WatchHandler::handleConfigSubkeyChanged(const QString &subkey)
+{
+ if (subkey == "watchlets") {
+ updateWatchlets();
+ } else if (subkey == "providers") {
+ updateProviders();
+ } else if (subkey == "next-watchlet-button") {
+ _server->setNextWatchletButton(_config->value("next-watchlet-button").toString());
+ }
+}
diff --git a/sowatchd/watchhandler.h b/sowatchd/watchhandler.h
new file mode 100644
index 0000000..3fa7c6b
--- /dev/null
+++ b/sowatchd/watchhandler.h
@@ -0,0 +1,41 @@
+#ifndef WATCHHANDLER_H
+#define WATCHHANDLER_H
+
+#include <QtCore/QObject>
+#include <QtCore/QList>
+
+#include <sowatch.h>
+
+namespace sowatch
+{
+
+class WatchHandler : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QString status READ status NOTIFY statusChanged)
+
+public:
+ explicit WatchHandler(ConfigKey *config, QObject *parent = 0);
+
+ QString status() const;
+
+signals:
+ void statusChanged();
+
+private slots:
+ void updateWatchlets();
+ void updateProviders();
+ void handleConfigSubkeyChanged(const QString& key);
+
+private:
+ ConfigKey *_config;
+ Watch *_watch;
+ WatchServer *_server;
+ QList<QString> _watchlet_order;
+ QMap<QString, Watchlet*> _watchlets;
+ QMap<QString, NotificationProvider*> _providers;
+};
+
+}
+
+#endif // WATCHHANDLER_H
diff --git a/sowatchui/sowatchui.pro b/sowatchui/sowatchui.pro
index 9caa163..c0589fc 100644
--- a/sowatchui/sowatchui.pro
+++ b/sowatchui/sowatchui.pro
@@ -10,9 +10,9 @@ DEPLOYMENTFOLDERS = qml_folder
# Install icon files also to resources directory
res_files.files += sowatch64.png sowatch80.png
!isEmpty(MEEGO_VERSION_MAJOR)|maemo5 {
- res_files.path = /opt/sowatch/share/metawatch
+ res_files.path = /opt/sowatch/share
} else {
- res_files.path = /usr/share/sowatch/metawatch
+ res_files.path = /usr/share/sowatch
}
INSTALLS += res_files
diff --git a/sowatchui/watchesmodel.cpp b/sowatchui/watchesmodel.cpp
index 0930715..302e484 100644
--- a/sowatchui/watchesmodel.cpp
+++ b/sowatchui/watchesmodel.cpp
@@ -12,6 +12,7 @@ WatchesModel::WatchesModel(QObject *parent) :
{
QHash<int, QByteArray> roles = roleNames();
roles[Qt::DisplayRole] = QByteArray("title");
+ roles[Qt::DecorationRole] = QByteArray("iconSource");
roles[Qt::StatusTipRole] = QByteArray("subtitle");
roles[EnabledRole] = QByteArray("enabled");
roles[ConfigKeyRole] = QByteArray("configKey");
@@ -44,6 +45,12 @@ QVariant WatchesModel::data(const QModelIndex &index, int role) const
switch (role) {
case Qt::DisplayRole:
return config->value("name");
+ case Qt::DecorationRole:
+#if defined(QT_DEBUG)
+ return QVariant(QDir::current().absoluteFilePath(SOWATCH_RESOURCES_DIR "/sowatch64.png"));
+#else
+ return QVariant(SOWATCH_RESOURCES_DIR "/sowatch64.png");
+#endif
case Qt::StatusTipRole:
if (config->value("enable").toBool()) {
QString status = _status[id];