From 39fa663cd08bd2b7d46ed170d49ac794c531c42e Mon Sep 17 00:00:00 2001 From: "Javier S. Pedro" Date: Fri, 10 Aug 2012 16:06:14 +0200 Subject: watchlet edit UI --- sowatchui/main.cpp | 2 + sowatchui/providersmodel.cc | 105 ----------------------- sowatchui/providersmodel.cpp | 128 ++++++++++++++++++++++++++++ sowatchui/providersmodel.h | 1 + sowatchui/qml/AddWatchletSheet.qml | 48 +++++++++++ sowatchui/qml/WatchPage.qml | 62 ++++++++++++-- sowatchui/sowatchui.pro | 6 +- sowatchui/watchesmodel.cpp | 40 ++++++--- sowatchui/watchesmodel.h | 2 +- sowatchui/watchletsmodel.cpp | 166 +++++++++++++++++++++++++++++++++++++ sowatchui/watchletsmodel.h | 52 ++++++++++++ 11 files changed, 487 insertions(+), 125 deletions(-) delete mode 100644 sowatchui/providersmodel.cc create mode 100644 sowatchui/providersmodel.cpp create mode 100644 sowatchui/qml/AddWatchletSheet.qml create mode 100644 sowatchui/watchletsmodel.cpp create mode 100644 sowatchui/watchletsmodel.h (limited to 'sowatchui') diff --git a/sowatchui/main.cpp b/sowatchui/main.cpp index 5e116ac..80a0f6b 100644 --- a/sowatchui/main.cpp +++ b/sowatchui/main.cpp @@ -7,6 +7,7 @@ #include "watchesmodel.h" #include "watchscannermodel.h" #include "providersmodel.h" +#include "watchletsmodel.h" static sowatch::Registry *registry; static WatchesModel *watches; @@ -26,6 +27,7 @@ Q_DECL_EXPORT int main(int argc, char *argv[]) qmlRegisterType(); qmlRegisterType("com.javispedro.sowatch", 1, 0, "GConfKey"); qmlRegisterType("com.javispedro.sowatch", 1, 0, "ProvidersModel"); + qmlRegisterType("com.javispedro.sowatch", 1, 0, "WatchletsModel"); viewer->rootContext()->setContextProperty("watches", watches); viewer->rootContext()->setContextProperty("watchScanner", watchScanner); diff --git a/sowatchui/providersmodel.cc b/sowatchui/providersmodel.cc deleted file mode 100644 index 68ce21b..0000000 --- a/sowatchui/providersmodel.cc +++ /dev/null @@ -1,105 +0,0 @@ -#include - -#include "providersmodel.h" - -using namespace sowatch; - -ProvidersModel::ProvidersModel(QObject *parent) : - QAbstractListModel(parent), - _config(0) -{ - QHash roles = roleNames(); - roles[Qt::DisplayRole] = QByteArray("title"); - roles[NameRole] = QByteArray("name"); - roles[EnabledRole] = QByteArray("enabled"); - setRoleNames(roles); -} - -QString ProvidersModel::configKey() const -{ - if (_config) { - return _config->key(); - } else { - return QString(); - } -} - -void ProvidersModel::setConfigKey(const QString &configKey) -{ - QString oldConfigKey = this->configKey(); - if (_config) { - delete _config; - _config = 0; - } - if (!configKey.isEmpty()) { - _config = new GConfKey(configKey, this); - connect(_config, SIGNAL(changed()), SLOT(reload())); - } - if (this->configKey() != oldConfigKey) { - reload(); - emit configKeyChanged(); - } -} - -int ProvidersModel::rowCount(const QModelIndex &parent) const -{ - return _all_list.count(); -} - -QVariant ProvidersModel::data(const QModelIndex &index, int role) const -{ - switch (role) { - case Qt::DisplayRole: - return QVariant::fromValue(_info_list[index.row()].name); - case NameRole: - return QVariant::fromValue(_all_list[index.row()]); - case EnabledRole: - return QVariant::fromValue(_enabled.contains(_all_list[index.row()])); - } - return QVariant(); -} - -bool ProvidersModel::setData(const QModelIndex &index, const QVariant &value, int role) -{ - switch (role) { - case EnabledRole: - setProviderEnabled(_all_list[index.row()], value.toBool()); - return true; - } - return false; -} - -void ProvidersModel::setProviderEnabled(const QString &id, bool enabled) -{ - if (enabled) { - _enabled.insert(id); - } else { - _enabled.remove(id); - } - _config->set(QVariant::fromValue(QStringList(_enabled.toList()))); -} - -void ProvidersModel::reload() -{ - Registry *registry = Registry::registry(); - beginResetModel(); - _all_list.clear(); - _info_list.clear(); - _enabled.clear(); - - _all_list = registry->allNotificationProviders(); - _info_list.reserve(_all_list.size()); - foreach (const QString& s, _all_list) { - NotificationPluginInterface *plugin = registry->getNotificationPlugin(s); - if (plugin) { - _info_list.append(plugin->describeProvider(s)); - } else { - NotificationPluginInterface::NotificationProviderInfo info; - info.name = s; - _info_list.append(info); - } - } - - _enabled = _config->value().toStringList().toSet(); - endResetModel(); -} diff --git a/sowatchui/providersmodel.cpp b/sowatchui/providersmodel.cpp new file mode 100644 index 0000000..8e93e5c --- /dev/null +++ b/sowatchui/providersmodel.cpp @@ -0,0 +1,128 @@ +#include + +#include "providersmodel.h" + +using namespace sowatch; + +static const QString providersSubKey("/providers"); + +ProvidersModel::ProvidersModel(QObject *parent) : + QAbstractListModel(parent), + _config(0) +{ + QHash roles = roleNames(); + roles[Qt::DisplayRole] = QByteArray("title"); + roles[NameRole] = QByteArray("name"); + roles[EnabledRole] = QByteArray("enabled"); + setRoleNames(roles); +} + +QString ProvidersModel::configKey() const +{ + if (_config) { + QString key = _config->key(); + return key.left(key.length() - providersSubKey.length()); + } else { + return QString(); + } +} + +void ProvidersModel::setConfigKey(const QString &configKey) +{ + QString oldConfigKey = this->configKey(); + if (_config) { + delete _config; + _config = 0; + } + if (!configKey.isEmpty()) { + _config = new GConfKey(configKey + providersSubKey, this); + connect(_config, SIGNAL(changed()), SLOT(handleConfigChanged())); + } + if (this->configKey() != oldConfigKey) { + reload(); + emit configKeyChanged(); + } +} + +int ProvidersModel::rowCount(const QModelIndex &parent) const +{ + Q_UNUSED(parent); + return _all_list.count(); +} + +QVariant ProvidersModel::data(const QModelIndex &index, int role) const +{ + switch (role) { + case Qt::DisplayRole: + return QVariant::fromValue(_info_list[index.row()].name); + case NameRole: + return QVariant::fromValue(_all_list[index.row()]); + case EnabledRole: + return QVariant::fromValue(_enabled.contains(_all_list[index.row()])); + } + return QVariant(); +} + +bool ProvidersModel::setData(const QModelIndex &index, const QVariant &value, int role) +{ + switch (role) { + case EnabledRole: + setProviderEnabled(_all_list[index.row()], value.toBool()); + return true; + } + return false; +} + +void ProvidersModel::setProviderEnabled(const QString &id, bool enabled) +{ + if (enabled) { + _enabled.insert(id); + } else { + _enabled.remove(id); + } + + qDebug() << "Storing providers" << _enabled; + + _config->set(QVariant::fromValue(QStringList(_enabled.toList()))); +} + +void ProvidersModel::reload() +{ + Registry *registry = Registry::registry(); + beginResetModel(); + _all_list.clear(); + _info_list.clear(); + _enabled.clear(); + + qDebug() << "Reloading providers"; + + _all_list = registry->allNotificationProviders(); + _info_list.reserve(_all_list.size()); + _all_list.sort(); + foreach (const QString& s, _all_list) { + NotificationPluginInterface *plugin = registry->getNotificationPlugin(s); + if (plugin) { + _info_list.append(plugin->describeProvider(s)); + } else { + NotificationPluginInterface::NotificationProviderInfo info; + info.name = s; + _info_list.append(info); + } + } + + _enabled = _config->value().toStringList().toSet(); + endResetModel(); +} + +void ProvidersModel::handleConfigChanged() +{ + QSet prevEnabled = _enabled; + _enabled = _config->value().toStringList().toSet(); + + for (int i = 0; i < _all_list.count(); i++) { + const QString& id = _all_list[i]; + if (_enabled.contains(id) != prevEnabled.contains(id)) { + emit dataChanged(createIndex(i, 0), createIndex(i, 0)); + } + } +} diff --git a/sowatchui/providersmodel.h b/sowatchui/providersmodel.h index 9cf6ec6..bcde2d5 100644 --- a/sowatchui/providersmodel.h +++ b/sowatchui/providersmodel.h @@ -33,6 +33,7 @@ signals: private slots: void reload(); + void handleConfigChanged(); private: sowatch::ConfigKey *_config; diff --git a/sowatchui/qml/AddWatchletSheet.qml b/sowatchui/qml/AddWatchletSheet.qml new file mode 100644 index 0000000..e052350 --- /dev/null +++ b/sowatchui/qml/AddWatchletSheet.qml @@ -0,0 +1,48 @@ +import QtQuick 1.1 +import com.nokia.meego 1.1 +import com.nokia.extras 1.1 +import com.javispedro.sowatch 1.0 + +Sheet { + id: sheet + anchors.margins: UiConstants.DefaultMargin + + property string configKey; + + rejectButtonText: qsTr("Cancel") + + content: ListView { + id: listView + anchors.fill: parent + anchors.margins: UiConstants.DefaultMargin + + flickableDirection: Flickable.VerticalFlick + + model: WatchletsModel { + id: watchletsModel + configKey: sheet.configKey + displayUnadded: true + } + + header: Column { + width: parent.width + + GroupHeader { + width: parent.width + text: qsTr("Available watchlets") + } + } + + delegate: ListDelegate { + onClicked: { + watchletsModel.addWatchlet(model.name); + close(); + accepted(); + } + } + + ScrollDecorator { + flickableItem: listView + } + } +} diff --git a/sowatchui/qml/WatchPage.qml b/sowatchui/qml/WatchPage.qml index 21c4543..4799085 100644 --- a/sowatchui/qml/WatchPage.qml +++ b/sowatchui/qml/WatchPage.qml @@ -14,10 +14,55 @@ Page { tools: ToolBarLayout { ToolIcon { + id: backToolIcon platformIconId: "toolbar-back" anchors.left: parent.left onClicked: pageStack.pop() } + ToolIcon { + id: menuToolIcon + platformIconId: "toolbar-view-menu" + anchors.right: parent.right + onClicked: (watchMenu.status === DialogStatus.Closed) ? watchMenu.open() : watchMenu.close(); + } + } + + Menu { + id: watchMenu + MenuLayout { + MenuItem { + text: qsTr("Remove watch") + onClicked: { + watchMenu.close(); + watches.removeWatch(watchPage.configKey); + pageStack.pop(); + } + } + } + } + + Menu { + id: watchletMenu + property string watchlet; + MenuLayout { + MenuItem { + text: qsTr("Move up") + onClicked: watchletsModel.moveWatchletUp(watchletMenu.watchlet) + } + MenuItem { + text: qsTr("Move down") + onClicked: watchletsModel.moveWatchletDown(watchletMenu.watchlet) + } + MenuItem { + text: qsTr("Remove watchlet") + onClicked: watchletsModel.removeWatchlet(watchletMenu.watchlet) + } + } + } + + AddWatchletSheet { + id: addWatchletSheet + configKey: watchPage.configKey } GConfKey { @@ -84,7 +129,7 @@ Page { height: UiConstants.ListItemHeightDefault * count model: ProvidersModel { id: providersModel - configKey: watchPage.configKey + "/providers" + configKey: watchPage.configKey } delegate: ListDelegate { CheckBox { @@ -107,19 +152,24 @@ Page { interactive: false width: parent.width height: UiConstants.ListItemHeightDefault * count - model: ListModel { - ListElement { - title: "Test" - } + model: WatchletsModel { + id: watchletsModel + configKey: watchPage.configKey + displayUnadded: false } - delegate: ListDelegate { + delegate: ListDelegate { + onClicked: { + watchletMenu.watchlet = model.name; + watchletMenu.open(); + } } } Button { anchors.horizontalCenter: parent.horizontalCenter text: qsTr("Add new watchlet") + onClicked: addWatchletSheet.open() } } } diff --git a/sowatchui/sowatchui.pro b/sowatchui/sowatchui.pro index fa965d3..4098228 100644 --- a/sowatchui/sowatchui.pro +++ b/sowatchui/sowatchui.pro @@ -38,12 +38,14 @@ DEPENDPATH += $$PWD/../libsowatch SOURCES += main.cpp \ watchesmodel.cpp daemonproxy.cpp \ watchscannermodel.cpp \ - providersmodel.cc + providersmodel.cpp \ + watchletsmodel.cpp HEADERS += \ watchesmodel.h daemonproxy.h \ watchscannermodel.h \ - providersmodel.h + providersmodel.h \ + watchletsmodel.h OTHER_FILES += qml/main.qml \ qml/MainPage.qml \ diff --git a/sowatchui/watchesmodel.cpp b/sowatchui/watchesmodel.cpp index 302e484..f8afcd4 100644 --- a/sowatchui/watchesmodel.cpp +++ b/sowatchui/watchesmodel.cpp @@ -81,14 +81,6 @@ QVariant WatchesModel::data(const QModelIndex &index, int role) const return QVariant(); } -bool WatchesModel::removeRows(int row, int count, const QModelIndex &parent) -{ - Q_UNUSED(row); - Q_UNUSED(count); - Q_UNUSED(parent); - return false; // TODO -} - void WatchesModel::addFoundWatch(const QVariantMap &info) { QStringList existing = _config->dirs(); @@ -109,9 +101,8 @@ void WatchesModel::addFoundWatch(const QVariantMap &info) // Set some defaults Registry *registry = Registry::registry(); - foreach (const QString& providerId, registry->allNotificationProviders()) { - qDebug() << "Would add" << providerId; - } + newkey->set("providers", registry->allNotificationProviders()); + newkey->set("watchlets", registry->allWatchlets()); // Now add to the watches list QStringList active = _watches_list->value().toStringList(); @@ -120,6 +111,33 @@ void WatchesModel::addFoundWatch(const QVariantMap &info) // Now enable newkey->set("enable", true); + + delete newkey; +} + +void WatchesModel::removeWatch(const QString &id) +{ + QString name; + + int i = id.lastIndexOf('/'); + if (i != -1) { + // Hack: QML UI might pass /apps/sowatch/id instead of id alone + name = id.mid(i + 1); + } else { + name = id; + } + + ConfigKey *subkey = _config->getSubkey(name); + + qDebug() << "Deleting watch" << name; + + // Remove from watches list + QStringList active = _watches_list->value().toStringList(); + active.removeAll(name); + _watches_list->set(active); + + subkey->recursiveUnset(); + delete subkey; } void WatchesModel::reload() diff --git a/sowatchui/watchesmodel.h b/sowatchui/watchesmodel.h index 6e9b65e..46114e5 100644 --- a/sowatchui/watchesmodel.h +++ b/sowatchui/watchesmodel.h @@ -22,10 +22,10 @@ public: int rowCount(const QModelIndex &parent) const; QVariant data(const QModelIndex &index, int role) const; - bool removeRows(int row, int count, const QModelIndex &parent); public slots: void addFoundWatch(const QVariantMap& info); + void removeWatch(const QString& id); private slots: void reload(); diff --git a/sowatchui/watchletsmodel.cpp b/sowatchui/watchletsmodel.cpp new file mode 100644 index 0000000..d9c8f86 --- /dev/null +++ b/sowatchui/watchletsmodel.cpp @@ -0,0 +1,166 @@ +#include "watchletsmodel.h" + +using namespace sowatch; + +static const QString watchletsSubKey("/watchlets"); + +WatchletsModel::WatchletsModel(QObject *parent) : + QAbstractListModel(parent), + _config(0), + _unadded(false) +{ + QHash roles = roleNames(); + roles[Qt::DisplayRole] = QByteArray("title"); + roles[Qt::DecorationRole] = QByteArray("iconSource"); + roles[NameRole] = QByteArray("name"); + setRoleNames(roles); +} + +QString WatchletsModel::configKey() const +{ + if (_config) { + QString key = _config->key(); + return key.left(key.length() - watchletsSubKey.length()); + } else { + return QString(); + } +} + +void WatchletsModel::setConfigKey(const QString &configKey) +{ + qDebug() << "Set confgKey" << configKey; + QString oldConfigKey = this->configKey(); + if (_config) { + delete _config; + _config = 0; + } + if (!configKey.isEmpty()) { + _config = new GConfKey(configKey + watchletsSubKey, this); + connect(_config, SIGNAL(changed()), SLOT(handleConfigChanged())); + } + if (this->configKey() != oldConfigKey) { + reload(); + emit configKeyChanged(); + } +} + +bool WatchletsModel::displayUnadded() const +{ + return _unadded; +} + +void WatchletsModel::setDisplayUnadded(bool displayUnadded) +{ + qDebug() << "Set dunadded" << displayUnadded; + _unadded = displayUnadded; + if (_config) reload(); + emit displayUnaddedChanged(); +} + +int WatchletsModel::rowCount(const QModelIndex &parent) const +{ + Q_UNUSED(parent); + return _list.count(); +} + +QVariant WatchletsModel::data(const QModelIndex &index, int role) const +{ + const QString id = _list[index.row()]; + switch (role) { + case Qt::DisplayRole: + return QVariant::fromValue(_info[id].name); + case Qt::DecorationRole: + return QVariant::fromValue(_info[id].icon); + case NameRole: + return QVariant::fromValue(id); + } + return QVariant(); +} + +void WatchletsModel::addWatchlet(const QString &name) +{ + if (!_config) return; + QStringList enabled = _config->value().toStringList(); + if (_enabled.contains(name)) return; + enabled << name; + _config->set(enabled); +} + +void WatchletsModel::removeWatchlet(const QString &name) +{ + if (!_config) return; + QStringList enabled = _config->value().toStringList(); + enabled.removeAll(name); + _config->set(enabled); +} + +void WatchletsModel::moveWatchletUp(const QString &name) +{ + if (!_config) return; + QStringList enabled = _config->value().toStringList(); + int index = enabled.indexOf(name); + qDebug() << "move up" << enabled << index << enabled[index]; + if (index > 0 && index < enabled.size()) { + enabled.swap(index - 1, index); + } + _config->set(enabled); +} + +void WatchletsModel::moveWatchletDown(const QString &name) +{ + if (!_config) return; + QStringList enabled = _config->value().toStringList(); + int index = enabled.indexOf(name); + qDebug() << "move down" << enabled << index << enabled[index]; + if (index >= 0 && index < enabled.size() - 1) { + enabled.swap(index, index + 1); + } + _config->set(enabled); +} + +void WatchletsModel::reload() +{ + Registry *registry = Registry::registry(); + Q_ASSERT(_config); + beginResetModel(); + _list.clear(); + _info.clear(); + _enabled.clear(); + + qDebug() << "Reloading watchlets"; + + QStringList all = registry->allWatchlets(); + foreach (const QString& s, all) { + WatchletPluginInterface *plugin = registry->getWatchletPlugin(s); + if (plugin) { + _info[s] = plugin->describeWatchlet(s); + } else { + WatchletPluginInterface::WatchletInfo info; + info.name = s; + _info[s] = info; + } + } + + QStringList enabled = _config->value().toStringList(); + _enabled = enabled.toSet(); + + if (_unadded) { + qDebug() << "Listing unadded watchlets from" << all; + foreach (const QString& s, all) { + if (!_enabled.contains(s)) { + _list.append(s); + } + } + _list.sort(); + } else { + qDebug() << "Listing added watchlets from" << enabled; + _list = enabled; + } + endResetModel(); +} + +void WatchletsModel::handleConfigChanged() +{ + // TODO + reload(); +} diff --git a/sowatchui/watchletsmodel.h b/sowatchui/watchletsmodel.h new file mode 100644 index 0000000..e0c2c62 --- /dev/null +++ b/sowatchui/watchletsmodel.h @@ -0,0 +1,52 @@ +#ifndef WATCHLETSMODEL_H +#define WATCHLETSMODEL_H + +#include + +#include + +class WatchletsModel : public QAbstractListModel +{ + Q_OBJECT + Q_PROPERTY(QString configKey READ configKey WRITE setConfigKey NOTIFY configKeyChanged) + Q_PROPERTY(bool displayUnadded READ displayUnadded WRITE setDisplayUnadded NOTIFY displayUnaddedChanged) + +public: + explicit WatchletsModel(QObject *parent = 0); + + enum DataRoles { + NameRole = Qt::UserRole + }; + + QString configKey() const; + void setConfigKey(const QString& configKey); + + bool displayUnadded() const; + void setDisplayUnadded(bool displayUnadded); + + int rowCount(const QModelIndex &parent) const; + QVariant data(const QModelIndex &index, int role) const; + +public slots: + void addWatchlet(const QString& name); + void removeWatchlet(const QString& name); + void moveWatchletUp(const QString& name); + void moveWatchletDown(const QString& name); + +signals: + void configKeyChanged(); + void displayUnaddedChanged(); + +private slots: + void reload(); + void handleConfigChanged(); + +private: + sowatch::ConfigKey *_config; + bool _unadded; + QStringList _list; + QMap _info; + QSet _enabled; +}; + +#endif // WATCHLETSMODEL_H -- cgit v1.2.3