summaryrefslogtreecommitdiff
path: root/libsowatch
diff options
context:
space:
mode:
Diffstat (limited to 'libsowatch')
-rw-r--r--libsowatch/configkey.cpp8
-rw-r--r--libsowatch/configkey.h52
-rw-r--r--libsowatch/gconfkey.cpp294
-rw-r--r--libsowatch/gconfkey.h54
-rw-r--r--libsowatch/libsowatch.pro44
-rw-r--r--libsowatch/notificationplugininterface.h3
-rw-r--r--libsowatch/registry.cpp259
-rw-r--r--libsowatch/registry.h52
-rw-r--r--libsowatch/sowatch.h4
-rw-r--r--libsowatch/sowatch_global.h6
-rw-r--r--libsowatch/watchlet.cpp2
-rw-r--r--libsowatch/watchletplugininterface.h3
-rw-r--r--libsowatch/watchplugininterface.h7
-rw-r--r--libsowatch/watchscanner.cpp12
-rw-r--r--libsowatch/watchscanner.h32
-rw-r--r--libsowatch/watchserver.cpp35
-rw-r--r--libsowatch/watchserver.h15
17 files changed, 759 insertions, 123 deletions
diff --git a/libsowatch/configkey.cpp b/libsowatch/configkey.cpp
new file mode 100644
index 0000000..176b411
--- /dev/null
+++ b/libsowatch/configkey.cpp
@@ -0,0 +1,8 @@
+#include "configkey.h"
+
+using namespace sowatch;
+
+ConfigKey::ConfigKey(QObject *parent)
+{
+ Q_UNUSED(parent);
+}
diff --git a/libsowatch/configkey.h b/libsowatch/configkey.h
new file mode 100644
index 0000000..ef7665e
--- /dev/null
+++ b/libsowatch/configkey.h
@@ -0,0 +1,52 @@
+#ifndef SOWATCH_CONFIGKEY_H
+#define SOWATCH_CONFIGKEY_H
+
+#include <QtCore/QObject>
+#include <QtCore/QVariant>
+#include <QtCore/QStringList>
+#include "sowatch_global.h"
+
+namespace sowatch
+{
+
+class SOWATCH_EXPORT ConfigKey : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QString key READ key CONSTANT)
+ Q_PROPERTY(QVariant value READ value WRITE set RESET unset NOTIFY changed USER true)
+ Q_PROPERTY(QStringList dirs READ dirs)
+ Q_PROPERTY(QStringList keys READ keys)
+
+public:
+ ConfigKey(QObject *parent = 0);
+
+ virtual QString key() const = 0;
+
+ virtual QVariant value() const = 0;
+ virtual void set(const QVariant& value) = 0;
+ virtual void unset() = 0;
+ virtual bool isSet() const = 0;
+ virtual bool isDir() const = 0;
+
+ virtual QVariant value(const QString& subkey) const = 0;
+ virtual QVariant value(const QString& subkey, const QVariant& def) const = 0;
+ virtual void set(const QString& subkey, const QVariant& value) = 0;
+ virtual void unset(const QString& subkey) = 0;
+ virtual bool isSet(const QString& subkey) const = 0;
+ virtual bool isDir(const QString& subkey) const = 0;
+
+ virtual QStringList dirs() const = 0;
+ virtual QStringList keys() const = 0;
+
+ virtual void recursiveUnset() = 0;
+
+ virtual ConfigKey* getSubkey(const QString& subkey, QObject *parent = 0) const = 0;
+
+signals:
+ void changed();
+ void subkeyChanged(const QString& subkey);
+};
+
+}
+
+#endif // SOWATCH_CONFIGKEY_H
diff --git a/libsowatch/gconfkey.cpp b/libsowatch/gconfkey.cpp
new file mode 100644
index 0000000..b47deb5
--- /dev/null
+++ b/libsowatch/gconfkey.cpp
@@ -0,0 +1,294 @@
+#include <QtCore/QDebug>
+
+#include <gconf/gconf-client.h>
+#include <gconf/gconf-value.h>
+
+#include "gconfkey.h"
+
+using namespace sowatch;
+
+static GConfClient* g_client = NULL;
+
+static GConfClient* get_client() {
+ if (!g_client) {
+ g_client = gconf_client_get_default();
+ }
+ return g_client;
+}
+
+static QVariant convert_value(GConfValue *gval)
+{
+ switch (gval->type) {
+ case GCONF_VALUE_STRING:
+ return QVariant(QString::fromUtf8(gconf_value_get_string(gval)));
+ case GCONF_VALUE_INT:
+ return QVariant(gconf_value_get_int(gval));
+ case GCONF_VALUE_FLOAT:
+ return QVariant(gconf_value_get_float(gval));
+ case GCONF_VALUE_BOOL:
+ return QVariant(gconf_value_get_bool(gval) ? true : false);
+ case GCONF_VALUE_LIST:
+ if (gconf_value_get_list_type(gval) == GCONF_VALUE_STRING) {
+ QStringList r;
+ for (GSList *l = gconf_value_get_list(gval); l; l = l->next) {
+ GConfValue* lgval = (GConfValue *) l->data;
+ r.append(QString::fromUtf8(gconf_value_get_string(lgval)));
+ }
+ return QVariant::fromValue(r);
+ } else {
+ QVariantList r;
+ for (GSList *l = gconf_value_get_list(gval); l; l = l->next) {
+ GConfValue* lgval = (GConfValue *) l->data;
+ r.append(convert_value(lgval));
+ }
+ return QVariant::fromValue(r);
+ }
+ default:
+ return QVariant();
+ }
+}
+
+static GConfValue * convert_value(const QVariant& v)
+{
+ GConfValue *gval;
+ switch (v.type()) {
+ case QVariant::String:
+ gval = gconf_value_new(GCONF_VALUE_STRING);
+ gconf_value_set_string(gval, v.toString().toUtf8().constData());
+ break;
+ case QVariant::Int:
+ gval = gconf_value_new(GCONF_VALUE_INT);
+ gconf_value_set_int(gval, v.toInt());
+ break;
+ case QVariant::Double:
+ gval = gconf_value_new(GCONF_VALUE_FLOAT);
+ gconf_value_set_float(gval, v.toDouble());
+ break;
+ case QVariant::Bool:
+ gval = gconf_value_new(GCONF_VALUE_BOOL);
+ gconf_value_set_bool(gval, v.toBool());
+ break;
+ case QVariant::StringList: {
+ QStringList sl = v.toStringList();
+ GSList *glist = NULL;
+ gval = gconf_value_new(GCONF_VALUE_LIST);
+ gconf_value_set_list_type(gval, GCONF_VALUE_STRING);
+ foreach (const QString& s, sl) {
+ GConfValue *lgval = gconf_value_new(GCONF_VALUE_STRING);
+ gconf_value_set_string(lgval, s.toUtf8().constData());
+ glist = g_slist_prepend(glist, lgval);
+ }
+ gconf_value_set_list_nocopy(gval, g_slist_reverse(glist));
+ }
+ break;
+ // TODO: QVariantList, anything else.
+ default:
+ gval = NULL;
+ break;
+ }
+
+ return gval;
+}
+
+static QByteArray convert_key(const QString &key)
+{
+ return key.toAscii();
+}
+
+static QString convert_key(const gchar *key)
+{
+ return QString::fromAscii(key);
+}
+
+static void notify_func(GConfClient* client, guint cnxn_id, GConfEntry *entry, gpointer user_data)
+{
+ Q_UNUSED(client);
+ Q_UNUSED(cnxn_id);
+ GConfKey* key = static_cast<GConfKey*>(user_data);
+ key->notifyChanged(convert_key(entry->key));
+}
+
+static QString get_basename(const QString& path)
+{
+ int pos = path.lastIndexOf('/');
+ if (pos >= 0) {
+ return path.mid(pos+1);
+ } else {
+ return path;
+ }
+}
+
+GConfKey::GConfKey(const QString& key, QObject *parent) :
+ ConfigKey(parent), _key(key), _notify(0)
+{
+ if (_key.endsWith("/")) {
+ _key.chop(1);
+ }
+}
+
+GConfKey::~GConfKey()
+{
+ if (_notify) {
+ GConfClient* client = get_client();
+ gconf_client_remove_dir(client, getNativeKey(), NULL);
+ gconf_client_notify_remove(client, _notify);
+ }
+}
+
+QString GConfKey::key() const
+{
+ return _key;
+}
+
+QVariant GConfKey::value() const
+{
+ return value(QString());
+}
+
+void GConfKey::set(const QVariant &value)
+{
+ set(QString(), value);
+}
+
+void GConfKey::unset()
+{
+ unset(QString());
+}
+
+bool GConfKey::isSet() const
+{
+ return isSet(QString());
+}
+
+bool GConfKey::isDir() const
+{
+ return isDir(QString());
+}
+
+QVariant GConfKey::value(const QString &subkey) const
+{
+ const QString path = fullpath(subkey);
+ GConfValue *gval = gconf_client_get(get_client(), convert_key(path), NULL);
+ if (!gval) {
+ return QVariant();
+ }
+ QVariant v = convert_value(gval);
+ gconf_value_free(gval);
+ return v;
+}
+
+QVariant GConfKey::value(const QString &subkey, const QVariant &def) const
+{
+ const QString path = fullpath(subkey);
+ GConfValue *gval = gconf_client_get_without_default(get_client(), convert_key(path), NULL);
+ if (!gval) {
+ return def;
+ }
+ QVariant v = convert_value(gval);
+ gconf_value_free(gval);
+ return v;
+}
+
+void GConfKey::set(const QString &subkey, const QVariant &value)
+{
+ const QString path = fullpath(subkey);
+ GConfValue *gval = convert_value(value);
+ gconf_client_set(get_client(), convert_key(path), gval, NULL);
+ gconf_value_free(gval);
+}
+
+void GConfKey::unset(const QString &subkey)
+{
+ const QString path = fullpath(subkey);
+ gconf_client_unset(get_client(), convert_key(path), NULL);
+}
+
+bool GConfKey::isSet(const QString &subkey) const
+{
+ const QString path = fullpath(subkey);
+ GConfValue *gval = gconf_client_get_without_default(get_client(), convert_key(path), NULL);
+ if (gval) {
+ gconf_value_free(gval);
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool GConfKey::isDir(const QString &subkey) const
+{
+ const QString path = fullpath(subkey);
+ return gconf_client_dir_exists(get_client(), convert_key(path), NULL);
+}
+
+QStringList GConfKey::dirs() const
+{
+ QStringList r;
+ GSList *l = gconf_client_all_dirs(get_client(), getNativeKey(), NULL);
+ for (GSList *i = l; i; i = i->next) {
+ QString path = QString::fromAscii(static_cast<char*>(i->data));
+ r.append(get_basename(path));
+ g_free(i->data);
+ }
+ g_slist_free(l);
+ return r;
+}
+
+QStringList GConfKey::keys() const
+{
+ QStringList r;
+ GSList *l = gconf_client_all_entries(get_client(), getNativeKey(), NULL);
+ for (GSList *i = l; i; i = i->next) {
+ GConfEntry *e = static_cast<GConfEntry*>(i->data);
+ QString path = QString::fromAscii(e->key);
+ r.append(get_basename(path));
+ gconf_entry_free(e);
+ }
+ g_slist_free(l);
+ return r;
+}
+
+void GConfKey::recursiveUnset()
+{
+ gconf_client_recursive_unset(get_client(), getNativeKey(),
+ static_cast<GConfUnsetFlags>(0), NULL);
+}
+
+ConfigKey* GConfKey::getSubkey(const QString &subkey, QObject *parent) const
+{
+ return new GConfKey(fullpath(subkey), parent);
+}
+
+void GConfKey::notifyChanged(const QString& key)
+{
+ if (key == _key) {
+ emit changed();
+ } else if (key.startsWith(_key + '/')) {
+ emit subkeyChanged(key.mid(_key.size() + 1));
+ }
+}
+
+void GConfKey::connectNotify(const char *signal)
+{
+ Q_UNUSED(signal);
+ if (!_notify) {
+ GConfClient* client = get_client();
+ gconf_client_add_dir(client, getNativeKey(), GCONF_CLIENT_PRELOAD_NONE, NULL);
+ _notify = gconf_client_notify_add(client, getNativeKey(), notify_func,
+ this, NULL, NULL);
+ }
+}
+
+QString GConfKey::fullpath(const QString &child) const
+{
+ if (child.isEmpty()) {
+ return _key;
+ } else {
+ return _key + '/' + child;
+ }
+}
+
+QByteArray GConfKey::getNativeKey() const
+{
+ return convert_key(_key);
+}
diff --git a/libsowatch/gconfkey.h b/libsowatch/gconfkey.h
new file mode 100644
index 0000000..c9074ea
--- /dev/null
+++ b/libsowatch/gconfkey.h
@@ -0,0 +1,54 @@
+#ifndef SOWATCH_GCONFKEY_H
+#define SOWATCH_GCONFKEY_H
+
+#include "configkey.h"
+
+namespace sowatch
+{
+
+class SOWATCH_EXPORT GConfKey : public ConfigKey
+{
+ Q_OBJECT
+
+public:
+ GConfKey(const QString& key, QObject *parent = 0);
+ ~GConfKey();
+
+ QString key() const;
+
+ QVariant value() const;
+ void set(const QVariant& value);
+ void unset();
+ bool isSet() const;
+ bool isDir() const;
+
+ QVariant value(const QString& subkey) const;
+ QVariant value(const QString& subkey, const QVariant& def) const;
+ void set(const QString& subkey, const QVariant& value);
+ void unset(const QString& subkey);
+ bool isSet(const QString& subkey) const;
+ bool isDir(const QString& subkey) const;
+
+ QStringList dirs() const;
+ QStringList keys() const;
+
+ void recursiveUnset();
+
+ ConfigKey* getSubkey(const QString& subkey, QObject *parent = 0) const;
+
+ void notifyChanged(const QString& key);
+
+protected:
+ void connectNotify(const char *signal);
+
+private:
+ QString _key;
+ uint _notify;
+
+ QString fullpath(const QString& subkey = QString()) const;
+ QByteArray getNativeKey() const;
+};
+
+}
+
+#endif // SOWATCH_CONFIGKEY_H
diff --git a/libsowatch/libsowatch.pro b/libsowatch/libsowatch.pro
index 6f657c8..7a5b8eb 100644
--- a/libsowatch/libsowatch.pro
+++ b/libsowatch/libsowatch.pro
@@ -4,11 +4,14 @@
#
#-------------------------------------------------
-QT += gui declarative
+QT += gui declarative
-TARGET = sowatch
-TEMPLATE = lib
-VERSION = 1.0.0
+CONFIG += link_pkgconfig
+PKGCONFIG += gconf-2.0
+
+TARGET = sowatch
+TEMPLATE = lib
+VERSION = 1.0.0
DEFINES += SOWATCH_LIBRARY
@@ -27,7 +30,10 @@ SOURCES += \
notificationplugininterface.cpp \
notificationprovider.cpp \
watchletplugininterface.cpp \
- registry.cpp
+ registry.cpp \
+ watchscanner.cpp \
+ configkey.cpp \
+ gconfkey.cpp
HEADERS += \
watchsimulator.h \
@@ -46,26 +52,18 @@ HEADERS += \
notificationplugininterface.h \
notificationprovider.h \
watchletplugininterface.h \
- registry.h
+ registry.h \
+ watchscanner.h \
+ configkey.h \
+ gconfkey.h
install_headers.files = $$HEADERS
-symbian {
- MMP_RULES += EXPORTUNFROZEN
- TARGET.UID3 = 0xE6B95AFF
- TARGET.CAPABILITY =
- TARGET.EPOCALLOWDLLDATA = 1
- addFiles.sources = libsowatch.dll
- addFiles.path = !:/sys/bin
- DEPLOYMENT += addFiles
+install_headers.path = /usr/include/sowatch
+!isEmpty(MEEGO_VERSION_MAJOR)|maemo5 {
+ target.path = /opt/sowatch/lib
+} else {
+ target.path = /usr/lib
}
-unix:!symbian {
- install_headers.path = /usr/include/sowatch
- !isEmpty(MEEGO_VERSION_MAJOR)|maemo5 {
- target.path = /opt/sowatch/lib
- } else {
- target.path = /usr/lib
- }
- INSTALLS += install_headers target
-}
+INSTALLS += install_headers target
diff --git a/libsowatch/notificationplugininterface.h b/libsowatch/notificationplugininterface.h
index b6c16f7..d753afc 100644
--- a/libsowatch/notificationplugininterface.h
+++ b/libsowatch/notificationplugininterface.h
@@ -9,6 +9,7 @@
namespace sowatch
{
+class ConfigKey;
class Notification;
class NotificationProvider;
@@ -18,7 +19,7 @@ public:
virtual ~NotificationPluginInterface();
virtual QStringList providers() = 0;
- virtual NotificationProvider* getProvider(const QString& driver, QSettings& settings, QObject *parent = 0) = 0;
+ virtual NotificationProvider* getProvider(const QString& driver, ConfigKey *settings, QObject *parent = 0) = 0;
};
}
diff --git a/libsowatch/registry.cpp b/libsowatch/registry.cpp
index 7ade260..5cbc464 100644
--- a/libsowatch/registry.cpp
+++ b/libsowatch/registry.cpp
@@ -21,99 +21,228 @@ Registry* Registry::registry()
return singleRegistry;
}
+Registry::~Registry()
+{
+}
+
Registry::Registry()
+ : _watcher(new QFileSystemWatcher(this))
{
+ _watcher->addPath(SOWATCH_DRIVERS_DIR);
+ _watcher->addPath(SOWATCH_NOTIFICATIONS_DIR);
+ _watcher->addPath(SOWATCH_WATCHLETS_DIR);
+
loadDrivers();
loadNotificationProviders();
loadWatchlets();
+
+ connect(_watcher, SIGNAL(directoryChanged(QString)),
+ this, SLOT(handlePluginDirectoryChanged(QString)));
+ connect(_watcher, SIGNAL(fileChanged(QString)),
+ this, SLOT(handlePluginFileChanged(QString)));
}
void Registry::loadDrivers()
{
QDir dir(SOWATCH_DRIVERS_DIR);
- foreach (QString file, dir.entryList(QDir::Files)) {
-#if defined(Q_OS_UNIX)
- // Temporary workaround for QtC deploy plugin issues
- if (!file.endsWith(".so")) continue;
-#endif
- QPluginLoader loader(dir.absoluteFilePath(file));
- QObject *pluginObj = loader.instance();
- if (pluginObj) {
- WatchPluginInterface *plugin = qobject_cast<WatchPluginInterface*>(pluginObj);
- if (plugin) {
- QStringList drivers = plugin->drivers();
- foreach (const QString& driver, drivers) {
- _drivers[driver] = plugin;
- }
- } else {
- qWarning() << "Invalid plugin" << file;
- loader.unload();
- }
- } else {
- qWarning() << "Invalid plugin" << file << loader.errorString();
- loader.unload();
- }
+ foreach (QString entry, dir.entryList(QDir::Files)) {
+ QString file = dir.absoluteFilePath(entry);
+ loadDriver(file);
}
- qDebug() << "loaded drivers" << _drivers.keys();
+ qDebug() << "loaded drivers" << _driverIds.keys();
}
void Registry::loadNotificationProviders()
{
QDir dir(SOWATCH_NOTIFICATIONS_DIR);
- foreach (QString file, dir.entryList(QDir::Files)) {
-#if defined(Q_OS_UNIX)
- // Temporary workaround for QtC deploy plugin issues
- if (!file.endsWith(".so")) continue;
-#endif
- QPluginLoader loader(dir.absoluteFilePath(file));
- QObject *pluginObj = loader.instance();
- if (pluginObj) {
- NotificationPluginInterface *plugin = qobject_cast<NotificationPluginInterface*>(pluginObj);
- if (plugin) {
- QStringList providers = plugin->providers();
- foreach (const QString& provider, providers) {
- _providers[provider] = plugin;
- }
- } else {
- qWarning() << "Invalid plugin" << file;
- loader.unload();
+ foreach (QString entry, dir.entryList(QDir::Files)) {
+ QString file = dir.absoluteFilePath(entry);
+ loadNotificationProvider(file);
+ }
+
+ qDebug() << "loaded notification providers" << _providerIds.keys();
+}
+
+void Registry::loadWatchlets()
+{
+ QDir dir(SOWATCH_WATCHLETS_DIR);
+ foreach (QString entry, dir.entryList(QDir::Files)) {
+ QString file = dir.absoluteFilePath(entry);
+ loadWatchlet(file);
+ }
+
+ qDebug() << "loaded watchlets" << _watchletIds.keys();
+}
+
+void Registry::loadDriver(const QString &file)
+{
+ QPluginLoader* loader = new QPluginLoader(file, this);
+ QObject *pluginObj = loader->instance();
+ if (pluginObj) {
+ WatchPluginInterface *plugin = qobject_cast<WatchPluginInterface*>(pluginObj);
+ if (plugin) {
+ _driverFiles[file] = loader;
+ _drivers += plugin;
+ QStringList drivers = plugin->drivers();
+ foreach (const QString& driver, drivers) {
+ _driverIds[driver] = plugin;
}
+ _watcher->addPath(file);
} else {
- qWarning() << "Invalid plugin" << file << loader.errorString();
- loader.unload();
+ qWarning() << "Invalid plugin" << file;
+ loader->unload();
+ delete loader;
}
+ } else {
+ qWarning() << "Invalid plugin" << file << loader->errorString();
+ loader->unload();
+ delete loader;
}
+}
- qDebug() << "loaded notification providers" << _providers.keys();
+void Registry::loadNotificationProvider(const QString &file)
+{
+ QPluginLoader* loader = new QPluginLoader(file, this);
+ QObject *pluginObj = loader->instance();
+ if (pluginObj) {
+ NotificationPluginInterface *plugin = qobject_cast<NotificationPluginInterface*>(pluginObj);
+ if (plugin) {
+ _providerFiles[file] = loader;
+ _providers += plugin;
+ QStringList providers = plugin->providers();
+ foreach (const QString& provider, providers) {
+ _providerIds[provider] = plugin;
+ }
+ _watcher->addPath(file);
+ } else {
+ qWarning() << "Invalid plugin" << file;
+ loader->unload();
+ delete loader;
+ }
+ } else {
+ qWarning() << "Invalid plugin" << file << loader->errorString();
+ loader->unload();
+ delete loader;
+ }
}
-void Registry::loadWatchlets()
+void Registry::loadWatchlet(const QString &file)
{
- QDir dir(SOWATCH_WATCHLETS_DIR);
- foreach (QString file, dir.entryList(QDir::Files)) {
-#if defined(Q_OS_UNIX)
- // Temporary workaround for QtC deploy plugin issues
- if (!file.endsWith(".so")) continue;
-#endif
- QPluginLoader loader(dir.absoluteFilePath(file));
- QObject *pluginObj = loader.instance();
- if (pluginObj) {
- WatchletPluginInterface *plugin = qobject_cast<WatchletPluginInterface*>(pluginObj);
- if (plugin) {
- QStringList watchlets = plugin->watchlets();
- foreach (const QString& watchlet, watchlets) {
- _watchlets[watchlet] = plugin;
- }
- } else {
- qWarning() << "Invalid plugin" << file;
- loader.unload();
+ QPluginLoader* loader = new QPluginLoader(file, this);
+ QObject *pluginObj = loader->instance();
+ if (pluginObj) {
+ WatchletPluginInterface *plugin = qobject_cast<WatchletPluginInterface*>(pluginObj);
+ if (plugin) {
+ _watchletFiles[file] = loader;
+ _watchlets += plugin;
+ QStringList watchlets = plugin->watchlets();
+ foreach (const QString& watchlet, watchlets) {
+ _watchletIds[watchlet] = plugin;
}
+ _watcher->addPath(file);
} else {
- qWarning() << "Invalid plugin" << file << loader.errorString();
- loader.unload();
+ qWarning() << "Invalid plugin" << file;
+ loader->unload();
+ delete loader;
}
+ } else {
+ qWarning() << "Invalid plugin" << file << loader->errorString();
+ loader->unload();
+ delete loader;
}
+}
+
+void Registry::unloadDriver(QPluginLoader *loader)
+{
+ QString file = loader->fileName();
+
+ WatchPluginInterface *plugin = qobject_cast<WatchPluginInterface*>(loader->instance());
+ QStringList drivers = plugin->drivers();
- qDebug() << "loaded watchlets" << _watchlets.keys();
+ foreach (const QString& driver, drivers) {
+ _driverIds.remove(driver);
+ }
+
+ _drivers.removeAll(plugin);
+ _driverFiles.remove(file);
+ _watcher->removePath(file);
+
+ // loader->unload();
+ // TODO : Signal loss of a plugin so that servers can remove it before
+ // we unload it.
+}
+
+void Registry::unloadNotificationProvider(QPluginLoader *loader)
+{
+ QString file = loader->fileName();
+ NotificationPluginInterface *plugin = qobject_cast<NotificationPluginInterface*>(loader->instance());
+ QStringList providers = plugin->providers();
+
+ foreach (const QString& provider, providers) {
+ _providerIds.remove(provider);
+ }
+
+ _providers.removeAll(plugin);
+ _providerFiles.remove(file);
+ _watcher->removePath(file);
+}
+
+void Registry::unloadWatchlet(QPluginLoader *loader)
+{
+ QString file = loader->fileName();
+ WatchletPluginInterface *plugin = qobject_cast<WatchletPluginInterface*>(loader->instance());
+ QStringList watchlets = plugin->watchlets();
+
+ foreach (const QString& watchlet, watchlets) {
+ _watchletIds.remove(watchlet);
+ }
+
+ _watchlets.removeAll(plugin);
+ _watchletFiles.remove(file);
+ _watcher->removePath(file);
+}
+
+void Registry::handlePluginDirectoryChanged(const QString &path)
+{
+ // If the directory changed, rescan it to load new discover new plugins.
+ if (path == SOWATCH_DRIVERS_DIR) {
+ QDir dir(path);
+ foreach (QString entry, dir.entryList(QDir::Files)) {
+ QString file = dir.absoluteFilePath(entry);
+ if (!_driverFiles.contains(file)) {
+ loadDriver(file);
+ }
+ }
+ } else if (path == SOWATCH_NOTIFICATIONS_DIR) {
+ QDir dir(path);
+ foreach (QString entry, dir.entryList(QDir::Files)) {
+ QString file = dir.absoluteFilePath(entry);
+ if (!_providerFiles.contains(file)) {
+ loadNotificationProvider(file);
+ }
+ }
+ } else if (path == SOWATCH_WATCHLETS_DIR) {
+ QDir dir(path);
+ foreach (QString entry, dir.entryList(QDir::Files)) {
+ QString file = dir.absoluteFilePath(entry);
+ if (!_watchletFiles.contains(file)) {
+ loadWatchlet(file);
+ }
+ }
+ }
+}
+
+void Registry::handlePluginFileChanged(const QString &file)
+{
+ QFile f(file);
+ if (_driverFiles.contains(file)) {
+ unloadDriver(_driverFiles[file]);
+ }
+ if (_providerFiles.contains(file)) {
+ unloadNotificationProvider(_providerFiles[file]);
+ }
+ if (_watchletFiles.contains(file)) {
+ unloadWatchlet(_watchletFiles[file]);
+ }
}
diff --git a/libsowatch/registry.h b/libsowatch/registry.h
index ca7252a..74e9388 100644
--- a/libsowatch/registry.h
+++ b/libsowatch/registry.h
@@ -1,8 +1,10 @@
#ifndef SOWATCH_REGISTRY_H
#define SOWATCH_REGISTRY_H
+#include <QtCore/QPluginLoader>
#include <QtCore/QString>
#include <QtCore/QMap>
+#include <QtCore/QFileSystemWatcher>
#include "sowatch_global.h"
namespace sowatch
@@ -12,21 +14,35 @@ class WatchPluginInterface;
class NotificationPluginInterface;
class WatchletPluginInterface;
-class SOWATCH_EXPORT Registry
+class SOWATCH_EXPORT Registry : public QObject
{
+ Q_OBJECT
+
public:
static Registry* registry();
+ inline QList<WatchPluginInterface*> getWatchPlugins() {
+ return _drivers;
+ }
+
+ inline QList<NotificationPluginInterface*> getNotificationPlugins() {
+ return _providers;
+ }
+
+ inline QList<WatchletPluginInterface*> getWatchletPlugins() {
+ return _watchlets;
+ }
+
inline WatchPluginInterface* getWatchPlugin(const QString& id) {
- return _drivers.value(id, 0);
+ return _driverIds.value(id, 0);
}
inline NotificationPluginInterface* getNotificationPlugin(const QString& id) {
- return _providers.value(id, 0);
+ return _providerIds.value(id, 0);
}
inline WatchletPluginInterface* getWatchletPlugin(const QString& id) {
- return _watchlets.value(id, 0);
+ return _watchletIds.value(id, 0);
}
protected:
@@ -36,13 +52,35 @@ protected:
private:
static Registry* singleRegistry;
- QMap<QString, WatchPluginInterface*> _drivers;
- QMap<QString, NotificationPluginInterface*> _providers;
- QMap<QString, WatchletPluginInterface*> _watchlets;
+ QFileSystemWatcher* _watcher;
+
+ QList<WatchPluginInterface*> _drivers;
+ QList<NotificationPluginInterface*> _providers;
+ QList<WatchletPluginInterface*> _watchlets;
+
+ QMap<QString, QPluginLoader*> _driverFiles;
+ QMap<QString, QPluginLoader*> _providerFiles;
+ QMap<QString, QPluginLoader*> _watchletFiles;
+
+ QMap<QString, WatchPluginInterface*> _driverIds;
+ QMap<QString, NotificationPluginInterface*> _providerIds;
+ QMap<QString, WatchletPluginInterface*> _watchletIds;
void loadDrivers();
void loadNotificationProviders();
void loadWatchlets();
+
+ void loadDriver(const QString& file);
+ void loadNotificationProvider(const QString& file);
+ void loadWatchlet(const QString& file);
+
+ void unloadDriver(QPluginLoader* loader);
+ void unloadNotificationProvider(QPluginLoader* loader);
+ void unloadWatchlet(QPluginLoader* loader);
+
+private slots:
+ void handlePluginDirectoryChanged(const QString& path);
+ void handlePluginFileChanged(const QString& file);
};
}
diff --git a/libsowatch/sowatch.h b/libsowatch/sowatch.h
index b0aa999..efc5ee8 100644
--- a/libsowatch/sowatch.h
+++ b/libsowatch/sowatch.h
@@ -3,9 +3,13 @@
#include "sowatch_global.h"
+#include "configkey.h"
+#include "gconfkey.h"
+
#include "watch.h"
#include "watchserver.h"
#include "watchsimulator.h"
+#include "watchscanner.h"
#include "watchplugininterface.h"
#include "notification.h"
diff --git a/libsowatch/sowatch_global.h b/libsowatch/sowatch_global.h
index 510a38a..9c6cf73 100644
--- a/libsowatch/sowatch_global.h
+++ b/libsowatch/sowatch_global.h
@@ -10,7 +10,11 @@
# define SOWATCH_EXPORT Q_DECL_IMPORT
#endif
-#if defined(MEEGO_VERSION_MAJOR) || defined(Q_WS_MAEMO_5)
+#if defined(QT_SIMULATOR) || !defined(QT_NO_DEBUG)
+# define SOWATCH_PLUGINS_DIR ".."
+# define SOWATCH_RESOURCES_DIR ".."
+# define SOWATCH_QML_DIR ".."
+#elif defined(MEEGO_VERSION_MAJOR) || defined(Q_WS_MAEMO_5)
# define SOWATCH_PLUGINS_DIR "/opt/sowatch/lib"
# define SOWATCH_RESOURCES_DIR "/opt/sowatch/share"
# define SOWATCH_QML_DIR "/opt/sowatch/qml"
diff --git a/libsowatch/watchlet.cpp b/libsowatch/watchlet.cpp
index 15e0b6c..9b3567e 100644
--- a/libsowatch/watchlet.cpp
+++ b/libsowatch/watchlet.cpp
@@ -6,7 +6,7 @@ using namespace sowatch;
Watchlet::Watchlet(WatchServer *server, const QString& id) :
QObject(server), _id(id), _active(false), _server(server)
{
- _server->registerWatchlet(this);
+
}
Watchlet::~Watchlet()
diff --git a/libsowatch/watchletplugininterface.h b/libsowatch/watchletplugininterface.h
index 4f525f2..ef03d81 100644
--- a/libsowatch/watchletplugininterface.h
+++ b/libsowatch/watchletplugininterface.h
@@ -9,6 +9,7 @@
namespace sowatch
{
+class ConfigKey;
class Watchlet;
class WatchServer;
@@ -18,7 +19,7 @@ public:
virtual ~WatchletPluginInterface();
virtual QStringList watchlets() = 0;
- virtual Watchlet* getWatchlet(const QString& id, QSettings& settings, WatchServer *server) = 0;
+ virtual Watchlet* getWatchlet(const QString& id, ConfigKey *settings, WatchServer *server) = 0;
};
}
diff --git a/libsowatch/watchplugininterface.h b/libsowatch/watchplugininterface.h
index c027c47..804f7f5 100644
--- a/libsowatch/watchplugininterface.h
+++ b/libsowatch/watchplugininterface.h
@@ -2,7 +2,7 @@
#define SOWATCH_WATCHPLUGININTERFACE_H
#include <QtPlugin>
-#include <QtCore/QSettings>
+#include <QtCore/QVariantMap>
#include <QtCore/QStringList>
#include "sowatch_global.h"
@@ -10,6 +10,8 @@ namespace sowatch
{
class Watch;
+class WatchScanner;
+class ConfigKey;
class SOWATCH_EXPORT WatchPluginInterface
{
@@ -17,7 +19,8 @@ public:
virtual ~WatchPluginInterface();
virtual QStringList drivers() = 0;
- virtual Watch* getWatch(const QString& driver, QSettings& settings, QObject *parent = 0) = 0;
+ virtual WatchScanner* getScanner(QObject *parent = 0) = 0;
+ virtual Watch* getWatch(const QString& driver, ConfigKey* settings, QObject *parent = 0) = 0;
};
}
diff --git a/libsowatch/watchscanner.cpp b/libsowatch/watchscanner.cpp
new file mode 100644
index 0000000..f744a25
--- /dev/null
+++ b/libsowatch/watchscanner.cpp
@@ -0,0 +1,12 @@
+#include "watchscanner.h"
+
+using namespace sowatch;
+
+WatchScanner::WatchScanner(QObject *parent) :
+ QObject(parent)
+{
+}
+
+WatchScanner::~WatchScanner()
+{
+}
diff --git a/libsowatch/watchscanner.h b/libsowatch/watchscanner.h
new file mode 100644
index 0000000..c74761e
--- /dev/null
+++ b/libsowatch/watchscanner.h
@@ -0,0 +1,32 @@
+#ifndef SOWATCH_WATCHSCANNER_H
+#define SOWATCH_WATCHSCANNER_H
+
+#include <QtCore/QObject>
+#include <QtCore/QVariant>
+
+namespace sowatch
+{
+
+
+class WatchScanner : public QObject
+{
+ Q_OBJECT
+
+protected:
+ explicit WatchScanner(QObject *parent = 0);
+
+public:
+ virtual ~WatchScanner();
+
+signals:
+ void started();
+ void finished();
+ void watchFound(const QVariantMap& info);
+
+public slots:
+ virtual void start() = 0;
+};
+
+}
+
+#endif // SOWATCH_WATCHSCANNER_H
diff --git a/libsowatch/watchserver.cpp b/libsowatch/watchserver.cpp
index da7d282..540eeea 100644
--- a/libsowatch/watchserver.cpp
+++ b/libsowatch/watchserver.cpp
@@ -56,6 +56,17 @@ void WatchServer::addProvider(NotificationProvider *provider)
connect(provider, SIGNAL(incomingNotification(Notification*)), SLOT(postNotification(Notification*)));
}
+void WatchServer::addWatchlet(Watchlet *watchlet)
+{
+ // A watchlet is best not reparented; just look that the parent is correct
+ Q_ASSERT(watchlet->_server == this);
+ _watchlets.append(watchlet);
+ QString id = watchlet->id();
+ if (!_watchletIds.contains(id)) {
+ _watchletIds[id] = watchlet;
+ }
+}
+
QList<Notification*> WatchServer::liveNotifications()
{
QList<Notification*> notifications;
@@ -67,17 +78,24 @@ QList<Notification*> WatchServer::liveNotifications()
return notifications;
}
-void WatchServer::runWatchlet(const QString& id)
+void WatchServer::runWatchlet(Watchlet *watchlet)
{
+ Q_ASSERT(watchlet->_server == this);
if (_currentWatchlet && _currentWatchletActive) {
deactivateCurrentWatchlet();
}
- _currentWatchlet = _watchlets[id];
+ _currentWatchlet = watchlet;
if (_watch->isConnected()) {
reactivateCurrentWatchlet();
}
}
+void WatchServer::runWatchlet(const QString& id)
+{
+ Q_ASSERT(_watchletIds.contains(id));
+ runWatchlet(_watchletIds[id]);
+}
+
void WatchServer::closeWatchlet()
{
if (_currentWatchlet) {
@@ -91,15 +109,6 @@ void WatchServer::closeWatchlet()
}
}
-void WatchServer::registerWatchlet(Watchlet *watchlet)
-{
- Q_ASSERT(watchlet->_server == this);
- QString id = watchlet->id();
- _watchlets[id] = watchlet;
- _watchletIds.append(id);
-}
-
-
void WatchServer::deactivateCurrentWatchlet()
{
Q_ASSERT(_currentWatchlet != 0);
@@ -123,11 +132,11 @@ void WatchServer::nextWatchlet()
{
qDebug() << "current watchlet index" << _currentWatchletIndex;
_currentWatchletIndex++;
- if (_currentWatchletIndex >= _watchletIds.size() || _currentWatchletIndex < 0) {
+ if (_currentWatchletIndex >= _watchlets.size() || _currentWatchletIndex < 0) {
_currentWatchletIndex = -1;
closeWatchlet();
} else {
- QString watchlet = _watchletIds.at(_currentWatchletIndex);
+ Watchlet* watchlet = _watchlets.at(_currentWatchletIndex);
runWatchlet(watchlet);
}
}
diff --git a/libsowatch/watchserver.h b/libsowatch/watchserver.h
index d73b56b..3995bc6 100644
--- a/libsowatch/watchserver.h
+++ b/libsowatch/watchserver.h
@@ -32,6 +32,7 @@ public:
QString nextWatchletButton() const;
void setNextWatchletButton(const QString& value);
+ void addWatchlet(Watchlet* watchlet);
void addProvider(NotificationProvider* provider);
/** Get a list of all current live notifications. */
@@ -41,6 +42,7 @@ public slots:
void postNotification(Notification *notification);
void nextNotification();
+ void runWatchlet(Watchlet* watchlet);
void runWatchlet(const QString& id);
void closeWatchlet();
void nextWatchlet();
@@ -55,10 +57,10 @@ private:
/** The amount of seconds that have to pass for a notification to be considered "outdated" and not shown. */
int _oldNotificationThreshold;
- /** A list of watchlets in order, for use by nextWatchlet() */
- QStringList _watchletIds;
- /** Actual Watchlet child objects by id. */
- QMap<QString, Watchlet*> _watchlets;
+ /** A list of watchlets, in order. */
+ QList<Watchlet*> _watchlets;
+ /** Stores all the watchlets with a given watchled id. */
+ QMap<QString, Watchlet*> _watchletIds;
/** Stores current live notifications, classified by type. */
QList<Notification*> _notifications[Notification::TypeCount];
@@ -79,9 +81,6 @@ private:
/** Used for periodic watch time syncing. */
QTimer* _syncTimeTimer;
- /** Called by Watchlet constructor to register itself as a child. */
- void registerWatchlet(Watchlet *watchlet);
-
/** Counts all notifications from a given type. */
uint getNotificationCount(Notification::Type type);
@@ -97,8 +96,6 @@ private slots:
void notificationChanged();
void notificationDismissed();
-
-friend class Watchlet;
};
}