diff options
Diffstat (limited to 'libsowatch')
-rw-r--r-- | libsowatch/configkey.cpp | 8 | ||||
-rw-r--r-- | libsowatch/configkey.h | 52 | ||||
-rw-r--r-- | libsowatch/gconfkey.cpp | 294 | ||||
-rw-r--r-- | libsowatch/gconfkey.h | 54 | ||||
-rw-r--r-- | libsowatch/libsowatch.pro | 44 | ||||
-rw-r--r-- | libsowatch/notificationplugininterface.h | 3 | ||||
-rw-r--r-- | libsowatch/registry.cpp | 259 | ||||
-rw-r--r-- | libsowatch/registry.h | 52 | ||||
-rw-r--r-- | libsowatch/sowatch.h | 4 | ||||
-rw-r--r-- | libsowatch/sowatch_global.h | 6 | ||||
-rw-r--r-- | libsowatch/watchlet.cpp | 2 | ||||
-rw-r--r-- | libsowatch/watchletplugininterface.h | 3 | ||||
-rw-r--r-- | libsowatch/watchplugininterface.h | 7 | ||||
-rw-r--r-- | libsowatch/watchscanner.cpp | 12 | ||||
-rw-r--r-- | libsowatch/watchscanner.h | 32 | ||||
-rw-r--r-- | libsowatch/watchserver.cpp | 35 | ||||
-rw-r--r-- | libsowatch/watchserver.h | 15 |
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; }; } |