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