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;  };  } | 
