summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJavier S. Pedro <dev.git@javispedro.com>2014-09-13 22:40:39 +0200
committerJavier S. Pedro <dev.git@javispedro.com>2014-09-13 22:40:39 +0200
commit85fb48bc51fed06a50b6178727fdf9e96aea4fc4 (patch)
treee5aa942addaf99bb29c73f5e946cf250ca8b80f8
parented40a7f1cbc1da5ae21c58882df241fc0071c2f7 (diff)
downloadsalmeta-85fb48bc51fed06a50b6178727fdf9e96aea4fc4.tar.gz
salmeta-85fb48bc51fed06a50b6178727fdf9e96aea4fc4.zip
UI can now add some widgets around
-rw-r--r--qml/pages/AddWidget.qml36
-rw-r--r--qml/pages/MainPage.qml (renamed from qml/pages/FirstPage.qml)43
-rw-r--r--qml/pages/WatchView.qml45
-rw-r--r--qml/salmeta.qml4
-rw-r--r--qml/watch/WidgetView.qml93
-rw-r--r--qml/watch/add_widget.pngbin0 -> 2475 bytes
-rw-r--r--qml/watch/faces/builtinface4.pngbin0 -> 1025 bytes
-rw-r--r--qml/watch/faces/builtinface4.qml11
-rw-r--r--qml/watch/main.qml8
-rw-r--r--qml/widgetview.qml15
-rw-r--r--salmeta.pro18
-rw-r--r--src/availablewidgetsmodel.cpp65
-rw-r--r--src/availablewidgetsmodel.h35
-rw-r--r--src/controller.cpp5
-rw-r--r--src/controller.h4
-rw-r--r--src/metawatch.cpp2
-rw-r--r--src/metawatch.h2
-rw-r--r--src/salmeta.cpp10
-rw-r--r--src/watchviewitem.cpp15
-rw-r--r--src/watchviewitem.h20
-rw-r--r--src/widgetinfo.cpp80
-rw-r--r--src/widgetinfo.h43
-rw-r--r--src/widgetinfomodel.cpp174
-rw-r--r--src/widgetinfomodel.h46
-rw-r--r--src/widgetview.cpp50
-rw-r--r--src/widgetview.h30
-rw-r--r--translations/salmeta.ts6
27 files changed, 639 insertions, 221 deletions
diff --git a/qml/pages/AddWidget.qml b/qml/pages/AddWidget.qml
new file mode 100644
index 0000000..50bf63d
--- /dev/null
+++ b/qml/pages/AddWidget.qml
@@ -0,0 +1,36 @@
+import QtQuick 2.0
+import Sailfish.Silica 1.0
+import com.javispedro.salmeta 1.0
+
+Page {
+ id: page
+
+ property int addToPage
+ property int addToPos
+
+ SilicaListView {
+ id: allWidgetsListView
+ anchors.fill: parent
+
+ model: allWidgets
+
+ header: PageHeader {
+ title: "Add widget"
+ }
+
+ delegate : BackgroundItem {
+ contentHeight: Theme.itemSizeMedium
+
+ Label {
+ text: url
+ truncationMode: TruncationMode.Elide
+ color: highlighted ? Theme.highlightColor : Theme.primaryColor
+ }
+
+ onClicked: {
+ curWidgets.addWidget(url, addToPage, addToPos, size);
+ pageStack.pop();
+ }
+ }
+ }
+}
diff --git a/qml/pages/FirstPage.qml b/qml/pages/MainPage.qml
index b86029e..5448754 100644
--- a/qml/pages/FirstPage.qml
+++ b/qml/pages/MainPage.qml
@@ -2,14 +2,13 @@ import QtQuick 2.0
import Sailfish.Silica 1.0
import Sailfish.Bluetooth 1.0
import org.nemomobile.configuration 1.0
-import com.javispedro.salmeta 1.0
Page {
id: page
ConfigurationValue {
id: deviceAddress
- key: settingsPrefix + "/address"
+ key: curSettingsPrefix + "/address"
defaultValue: "Select"
}
@@ -46,7 +45,7 @@ Page {
var dialog = pageStack.push("Sailfish.Bluetooth.BluetoothDevicePickerDialog");
dialog.selectedDeviceChanged.connect(function() {
- if (dialog.selectedDevice != "") {
+ if (dialog.selectedDevice !== "") {
deviceAddress.value = dialog.selectedDevice
}
});
@@ -57,10 +56,44 @@ Page {
text: qsTr("Widgets");
}
- WatchView {
- anchors.horizontalCenter: parent.horizontalCenter
+ Item {
width: 96 * 4
height: 96 * 4
+ anchors.horizontalCenter: parent.horizontalCenter
+
+ WatchView {
+ id: watchView
+ anchors.centerIn: parent
+ scale: 4
+ }
+ }
+
+ Row {
+ anchors.horizontalCenter: parent.horizontalCenter
+ spacing: 8
+
+ Repeater {
+ model: 4
+
+ Rectangle {
+ // TODO These should be GlassItem.
+ width: 16
+ height: 16
+ radius: 8
+
+ color: "white"
+ opacity: watchView.curPage == index ? 0.9 : 0.3
+ }
+ }
+ }
+
+ SectionHeader {
+ text: qsTr("Notifications");
+ }
+
+ Label {
+ x: Theme.paddingLarge
+ text: "TODO"
}
}
}
diff --git a/qml/pages/WatchView.qml b/qml/pages/WatchView.qml
new file mode 100644
index 0000000..e738f4e
--- /dev/null
+++ b/qml/pages/WatchView.qml
@@ -0,0 +1,45 @@
+import QtQuick 2.0
+import "../watch"
+
+Flickable {
+ id: watchView
+ width: 96
+ height: 96
+ clip: true
+ flickableDirection: Flickable.HorizontalFlick
+
+ property int curPage: 0
+
+ WidgetView {
+ id: widgetView
+ model: curWidgets
+ editMode: true
+ onEmptyWidgetClicked: {
+ pageStack.push(Qt.resolvedUrl("AddWidget.qml"), {
+ 'addToPage': page,
+ 'addToPos': pos
+ });
+ }
+ }
+
+ contentWidth: widgetView.width
+ contentHeight: widgetView.height
+
+ NumberAnimation {
+ id: pivotAnim
+ targets: watchView
+ property: "contentX"
+ to: curPage * watchView.width
+ duration: 100
+ easing.type: Easing.InOutQuad
+ }
+
+ onMovementStarted: {
+ pivotAnim.stop()
+ }
+
+ onMovementEnded: {
+ curPage = Math.round(watchView.contentX / watchView.width)
+ pivotAnim.start()
+ }
+}
diff --git a/qml/salmeta.qml b/qml/salmeta.qml
index bb031a4..e2f2896 100644
--- a/qml/salmeta.qml
+++ b/qml/salmeta.qml
@@ -34,8 +34,6 @@ import "pages"
ApplicationWindow
{
- initialPage: Component { FirstPage { } }
+ initialPage: Component { MainPage { } }
cover: Qt.resolvedUrl("cover/CoverPage.qml")
}
-
-
diff --git a/qml/watch/WidgetView.qml b/qml/watch/WidgetView.qml
new file mode 100644
index 0000000..9e64fac
--- /dev/null
+++ b/qml/watch/WidgetView.qml
@@ -0,0 +1,93 @@
+import QtQuick 2.0
+import com.javispedro.salmeta 1.0
+
+Rectangle {
+ id: view
+ width: 96*4
+ height: 96
+
+ color: "white";
+
+ property alias model: rep.model
+ property bool editMode: false
+
+ signal emptyWidgetClicked(int page, int pos)
+
+ Grid {
+ id: editGrid
+ anchors.fill: parent
+ columns: 2 * 4
+ rows: 2
+ visible: editMode
+
+ function _calculatePagePosFromIndex(index) {
+ switch (index) {
+ case 0: return [0, 0];
+ case 1: return [0, 1];
+ case 8: return [0, 2];
+ case 9: return [0, 3];
+ case 2: return [1, 0];
+ case 3: return [1, 1];
+ case 10: return [1, 2];
+ case 11: return [1, 3];
+ case 4: return [2, 0];
+ case 5: return [2, 1];
+ case 12: return [2, 2];
+ case 13: return [2, 3];
+ case 6: return [3, 0];
+ case 7: return [3, 1];
+ case 14: return [3, 2];
+ case 15: return [3, 3];
+ }
+ }
+
+ Repeater {
+ model: 16
+ Rectangle {
+ width: 96 / 2
+ height: 96 / 2
+ Image {
+ anchors.centerIn: parent
+ source: "add_widget.png"
+ }
+ MouseArea {
+ anchors.fill: parent
+ onClicked: {
+ var pagePos = editGrid._calculatePagePosFromIndex(index);
+ view.emptyWidgetClicked(pagePos[0], pagePos[1]);
+ }
+ }
+ }
+ }
+ }
+
+ Repeater {
+ id: rep
+
+ Item {
+ id: widgetItem
+
+ x: (model.page * 96) + (model.position === WidgetInfo.PosNE || model.position === WidgetInfo.PosSE ? 96 / 2 : 0)
+ y: (model.position === WidgetInfo.PosSE || model.position === WidgetInfo.PosSW ? 96 / 2 : 0)
+ width: model.size === WidgetInfo.Size2QHorizontal | model.size === WidgetInfo.Size4Q ? 96 : 96 / 2
+ height: model.size === WidgetInfo.Size2QVertical | model.size === WidgetInfo.Size4Q ? 96 : 96 / 2
+
+ visible: widgetLoader.status === Loader.Ready;
+
+ Loader {
+ id: widgetLoader
+ anchors.fill: parent
+ source: url
+ }
+
+ MouseArea {
+ anchors.fill: parent
+ enabled: editMode
+
+ onClicked: {
+ curWidgets.removeWidget(index);
+ }
+ }
+ }
+ }
+}
diff --git a/qml/watch/add_widget.png b/qml/watch/add_widget.png
new file mode 100644
index 0000000..97f5bc4
--- /dev/null
+++ b/qml/watch/add_widget.png
Binary files differ
diff --git a/qml/watch/faces/builtinface4.png b/qml/watch/faces/builtinface4.png
new file mode 100644
index 0000000..eb05c95
--- /dev/null
+++ b/qml/watch/faces/builtinface4.png
Binary files differ
diff --git a/qml/watch/faces/builtinface4.qml b/qml/watch/faces/builtinface4.qml
new file mode 100644
index 0000000..f9eff50
--- /dev/null
+++ b/qml/watch/faces/builtinface4.qml
@@ -0,0 +1,11 @@
+import QtQuick 2.0
+
+Rectangle {
+ width: 96
+ height: 96
+
+ Image {
+ anchors.fill: parent
+ source: "builtinface4.png"
+ }
+}
diff --git a/qml/watch/main.qml b/qml/watch/main.qml
deleted file mode 100644
index 200a8b0..0000000
--- a/qml/watch/main.qml
+++ /dev/null
@@ -1,8 +0,0 @@
-import QtQuick 2.0
-
-Rectangle {
- width: 96
- height: 96
-
- color: "white"
-}
diff --git a/qml/widgetview.qml b/qml/widgetview.qml
deleted file mode 100644
index 077431d..0000000
--- a/qml/widgetview.qml
+++ /dev/null
@@ -1,15 +0,0 @@
-import QtQuick 2.0
-
-Rectangle {
- width: 96*4
- height: 96
-
- color: Qt.rgba(0, 0, 0, 1);
-
- Repeater {
- model: 16
- Loader {
-
- }
- }
-}
diff --git a/salmeta.pro b/salmeta.pro
index 740bb53..acc91c4 100644
--- a/salmeta.pro
+++ b/salmeta.pro
@@ -16,9 +16,9 @@ SOURCES += src/salmeta.cpp \
src/metawatchbletransport.cpp \
src/reconnecttimer.cpp \
src/notificationmonitor.cpp \
- src/widgetview.cpp \
src/widgetinfo.cpp \
- src/watchviewitem.cpp
+ src/widgetinfomodel.cpp \
+ src/availablewidgetsmodel.cpp
HEADERS += \
src/controller.h \
@@ -27,22 +27,24 @@ HEADERS += \
src/metawatchbletransport.h \
src/reconnecttimer.h \
src/notificationmonitor.h \
- src/widgetview.h \
src/widgetinfo.h \
- src/watchviewitem.h
+ src/widgetinfomodel.h \
+ src/availablewidgetsmodel.h
OTHER_FILES += qml/salmeta.qml \
qml/cover/CoverPage.qml \
- qml/pages/FirstPage.qml \
rpm/salmeta.changes.in \
rpm/salmeta.spec \
rpm/salmeta.yaml \
translations/*.ts \
salmeta.desktop \
salmeta.png \
- qml/watch/main.qml \
- qml/widgetview.qml \
- salmeta.service
+ salmeta.service \
+ qml/pages/MainPage.qml \
+ qml/watch/WidgetView.qml \
+ qml/pages/WatchView.qml qml/watch/add_widget.png \
+ qml/watch/faces/builtinface4.qml qml/watch/faces/builtinface4.png \
+ qml/pages/AddWidget.qml
# to disable building translations every time, comment out the
# following CONFIG line
diff --git a/src/availablewidgetsmodel.cpp b/src/availablewidgetsmodel.cpp
new file mode 100644
index 0000000..02ca746
--- /dev/null
+++ b/src/availablewidgetsmodel.cpp
@@ -0,0 +1,65 @@
+#include <sailfishapp.h>
+
+#include "availablewidgetsmodel.h"
+
+AvailableWidgetsModel::AvailableWidgetsModel(QObject *parent) :
+ QAbstractListModel(parent)
+{
+ reload();
+}
+
+QHash<int, QByteArray> AvailableWidgetsModel::roleNames() const
+{
+ QHash<int, QByteArray> roles;
+
+ roles[UrlRole] = "url";
+ roles[SizeRole] = "size";
+
+ return roles;
+}
+
+int AvailableWidgetsModel::rowCount(const QModelIndex &parent) const
+{
+ if (parent.isValid()) return 0;
+ return _widgets.size();
+}
+
+QVariant AvailableWidgetsModel::data(const QModelIndex &index, int role) const
+{
+ if (!index.isValid()) return QVariant();
+ const int row = index.row();
+ if (row < 0 || row >= _widgets.size()) return QVariant();
+
+ switch (role) {
+ case UrlRole:
+ return QVariant::fromValue<QUrl>(_widgets[row].url());
+ case DescriptionRole:
+ return QVariant::fromValue<QString>(_widgets[row].description());
+ case SizeRole:
+ return QVariant::fromValue<int>(_widgets[row].size());
+ default:
+ qWarning() << "Unknown role:" << role;
+ return QVariant();
+ }
+}
+
+void AvailableWidgetsModel::reload()
+{
+ beginResetModel();
+ _widgets.clear();
+
+ // Load builtin widgets
+ WidgetInfo info;
+
+ info.setUrl(SailfishApp::pathTo("qml/watch/faces/builtinface4.qml"));
+ info.setDescription("Watchface #4");
+ info.setSize(WidgetInfo::Size4Q);
+ _widgets.append(info);
+
+ info.setUrl(SailfishApp::pathTo("qml/watch/faces/builtinface4.qml"));
+ info.setDescription("Watchface #4");
+ info.setSize(WidgetInfo::Size4Q);
+ _widgets.append(info);
+
+ endResetModel();
+}
diff --git a/src/availablewidgetsmodel.h b/src/availablewidgetsmodel.h
new file mode 100644
index 0000000..86114d9
--- /dev/null
+++ b/src/availablewidgetsmodel.h
@@ -0,0 +1,35 @@
+#ifndef AVAILABLEWIDGETSMODEL_H
+#define AVAILABLEWIDGETSMODEL_H
+
+#include <QtCore/QAbstractListModel>
+#include <QtCore/QFileSystemWatcher>
+
+#include "widgetinfo.h"
+
+class AvailableWidgetsModel : public QAbstractListModel
+{
+ Q_OBJECT
+public:
+ explicit AvailableWidgetsModel(QObject *parent = 0);
+
+ enum Roles {
+ UrlRole = Qt::UserRole,
+ DescriptionRole,
+ SizeRole
+ };
+
+ QHash<int, QByteArray> roleNames() const;
+ int rowCount(const QModelIndex &parent) const;
+ QVariant data(const QModelIndex &index, int role) const;
+
+signals:
+
+public slots:
+ void reload();
+
+private:
+ QFileSystemWatcher *_watcher;
+ QVector<WidgetInfo> _widgets;
+};
+
+#endif // AVAILABLEWIDGETSMODEL_H
diff --git a/src/controller.cpp b/src/controller.cpp
index 047ad96..9d1961c 100644
--- a/src/controller.cpp
+++ b/src/controller.cpp
@@ -13,7 +13,7 @@ Controller::Controller(const QString &settingsPrefix, QQuickView *view, QObject
_settings(new MDConfGroup(this)),
_metawatch(0),
_reconnect(new ReconnectTimer(this)),
- _view(new WidgetView(settingsPrefix, view, this)),
+ _widgets(new WidgetInfoModel(settingsPrefix, this)),
_batteryCharge(0), _batteryCharging(false)
{
_settings->setPath(settingsPrefix);
@@ -25,6 +25,7 @@ Controller::Controller(const QString &settingsPrefix, QQuickView *view, QObject
connect(_metawatch, &MetaWatch::disconnected, _reconnect, &ReconnectTimer::scheduleNextAttempt);
connect(_metawatch, &MetaWatch::batteryStatus, this, &Controller::handleMetaWatchBatteryStatus);
connect(_reconnect, &ReconnectTimer::tryReconnect, _metawatch, &MetaWatch::connectDevice);
+ connect(_recc)
_reconnect->scheduleNextAttempt();
@@ -69,7 +70,7 @@ void Controller::handleMetaWatchConnected()
_metawatch->setDateTime(QDateTime::currentDateTime());
_metawatch->updateLcdDisplay();
- _metawatch->updateWidgetList(_view->widgets());
+ // TODO _metawatch->updateWidgetList(_view->widgets());
}
void Controller::handleMetaWatchBatteryStatus(bool charging, int charge)
diff --git a/src/controller.h b/src/controller.h
index d7f2349..3570ff4 100644
--- a/src/controller.h
+++ b/src/controller.h
@@ -6,8 +6,8 @@
#include <MDConfGroup>
#include "metawatch.h"
-#include "widgetview.h"
#include "reconnecttimer.h"
+#include "widgetinfomodel.h"
class Controller : public QObject
{
@@ -43,7 +43,7 @@ private:
MetaWatch *_metawatch;
ReconnectTimer *_reconnect;
- WidgetView *_view;
+ WidgetInfoModel *_widgets;
// Watch status
int _batteryCharge;
diff --git a/src/metawatch.cpp b/src/metawatch.cpp
index a27d0ec..b1ea8af 100644
--- a/src/metawatch.cpp
+++ b/src/metawatch.cpp
@@ -63,7 +63,7 @@ void MetaWatch::updateLcdDisplay()
_transport->sendMessage(MessageUpdateLcdDisplay, 0x80, QByteArray());
}
-void MetaWatch::updateWidgetList(const QList<WidgetInfo*> &widgets)
+void MetaWatch::updateWidgetList(const QList<WidgetInfo> &widgets)
{
int num_widgets = 0;
diff --git a/src/metawatch.h b/src/metawatch.h
index dd02bf4..9068c08 100644
--- a/src/metawatch.h
+++ b/src/metawatch.h
@@ -75,7 +75,7 @@ public:
void updateDeviceType();
void updateBatteryStatus();
void updateLcdDisplay(); // TODO: More overloads
- void updateWidgetList(const QList<WidgetInfo*>& widgets);
+ void updateWidgetList(const QList<WidgetInfo>& widgets);
signals:
void connected();
diff --git a/src/salmeta.cpp b/src/salmeta.cpp
index f13cd64..46e4e89 100644
--- a/src/salmeta.cpp
+++ b/src/salmeta.cpp
@@ -2,7 +2,8 @@
#include <sailfishapp.h>
#include "controller.h"
-#include "watchviewitem.h"
+#include "widgetinfomodel.h"
+#include "availablewidgetsmodel.h"
static bool launch_daemon = false;
static QString settings_key_prefix("/apps/salmeta/watch0");
@@ -25,7 +26,8 @@ int main(int argc, char *argv[])
++it;
}
- qmlRegisterType<WatchViewItem>("com.javispedro.salmeta", 1, 0, "WatchView");
+ qmlRegisterUncreatableType<WidgetInfo>("com.javispedro.salmeta", 1, 0, "WidgetInfo",
+ "Use the models, not this");
if (launch_daemon) {
qDebug() << "Starting salmeta (daemon) with settings from" << settings_key_prefix;
@@ -33,7 +35,9 @@ int main(int argc, char *argv[])
new Controller(settings_key_prefix, SailfishApp::createView());
} else {
QQuickView *view = SailfishApp::createView();
- view->rootContext()->setContextProperty("settingsPrefix", settings_key_prefix);
+ view->rootContext()->setContextProperty("curSettingsPrefix", settings_key_prefix);
+ view->rootContext()->setContextProperty("curWidgets", new WidgetInfoModel(settings_key_prefix));
+ view->rootContext()->setContextProperty("allWidgets", new AvailableWidgetsModel);
view->setSource(SailfishApp::pathTo("qml/salmeta.qml"));
view->show();
}
diff --git a/src/watchviewitem.cpp b/src/watchviewitem.cpp
deleted file mode 100644
index dbd4e8a..0000000
--- a/src/watchviewitem.cpp
+++ /dev/null
@@ -1,15 +0,0 @@
-#include <QtCore/QDebug>
-#include <QtGui/QPainter>
-
-#include "watchviewitem.h"
-
-WatchViewItem::WatchViewItem(QQuickItem *parent) :
- QQuickPaintedItem(parent)
-{
- setFillColor(Qt::white);
-}
-
-void WatchViewItem::paint(QPainter *painter)
-{
-
-}
diff --git a/src/watchviewitem.h b/src/watchviewitem.h
deleted file mode 100644
index 5219852..0000000
--- a/src/watchviewitem.h
+++ /dev/null
@@ -1,20 +0,0 @@
-#ifndef WATCHVIEWITEM_H
-#define WATCHVIEWITEM_H
-
-#include <QtQuick/QQuickPaintedItem>
-
-class WatchViewItem : public QQuickPaintedItem
-{
- Q_OBJECT
-public:
- explicit WatchViewItem(QQuickItem *parent = 0);
-
- void paint(QPainter *painter);
-
-signals:
-
-public slots:
-
-};
-
-#endif // WATCHVIEWITEM_H
diff --git a/src/widgetinfo.cpp b/src/widgetinfo.cpp
index 477b61c..d23da8f 100644
--- a/src/widgetinfo.cpp
+++ b/src/widgetinfo.cpp
@@ -1,83 +1,99 @@
#include "widgetinfo.h"
-WidgetInfo::WidgetInfo(QObject *parent)
- : QObject(parent)
+struct WidgetInfoData : public QSharedData
{
+ QUrl url;
+ QString desc;
+ bool invert;
+ short page;
+ WidgetInfo::WidgetSize size;
+ WidgetInfo::WidgetPosition pos;
+};
+WidgetInfo::WidgetInfo()
+ : d(new WidgetInfoData)
+{
+}
+
+WidgetInfo::WidgetInfo(const WidgetInfo &other)
+ : d(other.d)
+{
+}
+
+WidgetInfo::~WidgetInfo()
+{
+}
+
+WidgetInfo& WidgetInfo::operator =(const WidgetInfo &other)
+{
+ if (this != &other) {
+ d = other.d;
+ }
+
+ return *this;
}
bool WidgetInfo::valid() const
{
- return !_url.isEmpty();
+ return !d->url.isEmpty();
}
QUrl WidgetInfo::url() const
{
- return _url;
+ return d->url;
}
void WidgetInfo::setUrl(const QUrl &url)
{
- if (url != _url) {
- const bool cur_valid = valid();
+ d->url = url;
+}
- _url = url;
- emit urlChanged();
+QString WidgetInfo::description() const
+{
+ return d->desc;
+}
- if (cur_valid != valid()) {
- emit validChanged();
- }
- }
+void WidgetInfo::setDescription(const QString &desc)
+{
+ d->desc = desc;
}
bool WidgetInfo::invert() const
{
- return _invert;
+ return d->invert;
}
void WidgetInfo::setInvert(bool invert)
{
- if (invert != _invert) {
- _invert = invert;
- emit invertChanged();
- }
+ d->invert = invert;
}
int WidgetInfo::page() const
{
- return _page;
+ return d->page;
}
void WidgetInfo::setPage(int page)
{
- if (page != _page) {
- _page = page;
- emit pageChanged();
- }
+ d->page = page;
}
WidgetInfo::WidgetSize WidgetInfo::size() const
{
- return _size;
+ return d->size;
}
void WidgetInfo::setSize(const WidgetSize &size)
{
- if (size != _size) {
- _size = size;
- emit sizeChanged();
- }
+ d->size = size;
}
WidgetInfo::WidgetPosition WidgetInfo::position() const
{
- return _pos;
+ return d->pos;
}
void WidgetInfo::setPosition(const WidgetPosition &pos)
{
- if (pos != _pos) {
- _pos = pos;
- emit positionChanged();
- }
+ d->pos = pos;
}
diff --git a/src/widgetinfo.h b/src/widgetinfo.h
index 06a6149..51d617b 100644
--- a/src/widgetinfo.h
+++ b/src/widgetinfo.h
@@ -1,23 +1,23 @@
#ifndef WIDGETINFO_H
#define WIDGETINFO_H
-#include <QtCore/QObject>
+#include <QtCore/QMetaType>
+#include <QtCore/QSharedData>
#include <QtCore/QUrl>
-class WidgetInfo : public QObject
+class WidgetInfoData;
+
+class WidgetInfo
{
- Q_OBJECT
+ Q_GADGET
Q_ENUMS(WidgetSize WidgetPosition)
- Q_PROPERTY(bool valid READ valid NOTIFY validChanged)
- Q_PROPERTY(QUrl url READ url WRITE setUrl NOTIFY urlChanged)
- Q_PROPERTY(bool invert READ invert WRITE setInvert NOTIFY invertChanged)
- Q_PROPERTY(int page READ page WRITE setPage NOTIFY pageChanged)
- Q_PROPERTY(WidgetSize size READ size WRITE setSize NOTIFY sizeChanged)
- Q_PROPERTY(WidgetPosition position READ position WRITE setPosition NOTIFY positionChanged)
-
public:
- explicit WidgetInfo(QObject *parent = 0);
+ WidgetInfo();
+ WidgetInfo(const WidgetInfo &other);
+ ~WidgetInfo();
+
+ WidgetInfo& operator=(const WidgetInfo &other);
enum WidgetSize
{
@@ -40,6 +40,9 @@ public:
QUrl url() const;
void setUrl(const QUrl &url);
+ QString description() const;
+ void setDescription(const QString &desc);
+
bool invert() const;
void setInvert(bool invert);
@@ -52,21 +55,11 @@ public:
WidgetPosition position() const;
void setPosition(const WidgetPosition &pos);
-signals:
- void validChanged();
- void urlChanged();
- void invertChanged();
- void pageChanged();
- void sizeChanged();
- void positionChanged();
-
private:
- QUrl _url;
- bool _invert;
- short _page;
- WidgetSize _size;
- WidgetPosition _pos;
-
+ QSharedDataPointer<WidgetInfoData> d;
};
+Q_DECLARE_METATYPE(WidgetInfo::WidgetSize)
+Q_DECLARE_METATYPE(WidgetInfo::WidgetPosition)
+
#endif // WIDGETINFO_H
diff --git a/src/widgetinfomodel.cpp b/src/widgetinfomodel.cpp
new file mode 100644
index 0000000..6c4d5d2
--- /dev/null
+++ b/src/widgetinfomodel.cpp
@@ -0,0 +1,174 @@
+#include <QtCore/QDebug>
+#include <QtCore/QStringList>
+#include "widgetinfomodel.h"
+
+namespace
+{
+
+inline QString get_widget_dconf_base(int index)
+{
+ return QString("widget%1_").arg(index);
+}
+
+}
+
+WidgetInfoModel::WidgetInfoModel(const QString &settingsPrefix, QObject *parent) :
+ QAbstractListModel(parent),
+ _settings(new MDConfGroup(this))
+{
+ _settings->setPath(settingsPrefix);
+ connect(_settings, &MDConfGroup::valueChanged,
+ this, &WidgetInfoModel::handleSettingChanged);
+ reload();
+}
+
+QHash<int, QByteArray> WidgetInfoModel::roleNames() const
+{
+ QHash<int, QByteArray> roles;
+
+ roles[UrlRole] = "url";
+ roles[InvertRole] = "invert";
+ roles[PageRole] = "page";
+ roles[SizeRole] = "size";
+ roles[PositionRole] = "position";
+
+ return roles;
+}
+
+int WidgetInfoModel::rowCount(const QModelIndex &parent) const
+{
+ if (parent.isValid()) return 0;
+ return _widgets.size();
+}
+
+QVariant WidgetInfoModel::data(const QModelIndex &index, int role) const
+{
+ if (!index.isValid()) return QVariant();
+ const int row = index.row();
+ if (row < 0 || row >= _widgets.size()) return QVariant();
+
+ switch (role) {
+ case UrlRole:
+ return QVariant::fromValue<QUrl>(_widgets[row].url());
+ case InvertRole:
+ return QVariant::fromValue<bool>(_widgets[row].invert());
+ case PageRole:
+ return QVariant::fromValue<int>(_widgets[row].page());
+ case SizeRole:
+ return QVariant::fromValue<int>(_widgets[row].size());
+ case PositionRole:
+ return QVariant::fromValue<int>(_widgets[row].position());
+ default:
+ qWarning() << "Unknown role:" << role;
+ return QVariant();
+ }
+}
+
+void WidgetInfoModel::reload()
+{
+ beginResetModel();
+ _widgets.resize(16);
+
+ for (int i = 0; i < _widgets.size(); i++) {
+ WidgetInfo &info = _widgets[i];
+ const QString base = get_widget_dconf_base(i);
+
+ info.setInvert(_settings->value(base + "invert").toBool());
+ info.setPage(_settings->value(base + "page").toInt());
+ info.setSize(static_cast<WidgetInfo::WidgetSize>(_settings->value(base + "size").toInt()));
+ info.setPosition(static_cast<WidgetInfo::WidgetPosition>(_settings->value(base + "position").toInt()));
+ info.setUrl(_settings->value(base + "url").toUrl());
+ }
+
+ endResetModel();
+}
+
+int WidgetInfoModel::addWidget(const QUrl &url, int page, WidgetInfo::WidgetPosition pos, WidgetInfo::WidgetSize size)
+{
+ int slot = findEmptySlot();
+ if (slot == -1) {
+ qWarning() << "No empty slots!"; // This shouldn't happen
+ return slot;
+ }
+
+ qDebug() << "Adding widget" << url << page << pos << size;
+
+ const QString base = get_widget_dconf_base(slot);
+
+ _settings->setValue(base + "invert", QVariant::fromValue<bool>(false));
+ _settings->setValue(base + "page", QVariant::fromValue<int>(page));
+ _settings->setValue(base + "size", QVariant::fromValue<int>(size));
+ _settings->setValue(base + "position", QVariant::fromValue<int>(pos));
+ _settings->setValue(base + "url", QVariant::fromValue<QUrl>(url));
+
+ // MDConf watcher will update the model.
+
+ return slot;
+}
+
+void WidgetInfoModel::removeWidget(int widgetId)
+{
+ const QString base = get_widget_dconf_base(widgetId);
+
+ _settings->setValue(base + "url", QVariant());
+ _settings->setValue(base + "invert", QVariant());
+ _settings->setValue(base + "page", QVariant());
+ _settings->setValue(base + "size", QVariant());
+ _settings->setValue(base + "position", QVariant());
+}
+
+int WidgetInfoModel::findEmptySlot()
+{
+ for (int i = 0; i < _widgets.size(); i++) {
+ if (_widgets[i].url().isEmpty()) {
+ return i;
+ }
+ }
+
+ return -1;
+}
+
+void WidgetInfoModel::handleSettingChanged(const QString &key)
+{
+ static const QString widgetPrefix("widget");
+ if (key.startsWith(widgetPrefix)) {
+ QStringList parts = key.split('_');
+ if (parts.size() == 2) {
+ bool ok = false;
+ int slot = parts[0].mid(widgetPrefix.length()).toInt(&ok);
+ if (!ok || slot < 0 || slot >= _widgets.size()) {
+ qWarning() << "Invalid widget number:" << key;
+ }
+
+ WidgetInfo &info = _widgets[slot];
+ const QString &role = parts[1];
+ QVector<int> roles;
+
+ if (role == "url") {
+ info.setUrl(_settings->value(key).toUrl());
+ roles << UrlRole;
+ } else if (role == "invert") {
+ info.setInvert(_settings->value(key).toBool());
+ roles << InvertRole;
+ } else if (role == "page") {
+ info.setPage(_settings->value(key).toInt());
+ roles << PageRole;
+ } else if (role == "size") {
+ info.setSize(static_cast<WidgetInfo::WidgetSize>(_settings->value(key).toInt()));
+ roles << SizeRole;
+ } else if (role == "position") {
+ info.setPosition(static_cast<WidgetInfo::WidgetPosition>(_settings->value(key).toInt()));
+ roles << PositionRole;
+ } else {
+ qWarning() << "Unknown widget key changed:" << key;
+ return;
+ }
+
+ const QModelIndex index = createIndex(slot, 0);
+ qDebug() << "Data changed" << slot << roles.at(0);
+ emit dataChanged(index, index, roles);
+ } else {
+ qWarning() << "Unknown widget key changed:" << key;
+ }
+ }
+}
diff --git a/src/widgetinfomodel.h b/src/widgetinfomodel.h
new file mode 100644
index 0000000..6b30a91
--- /dev/null
+++ b/src/widgetinfomodel.h
@@ -0,0 +1,46 @@
+#ifndef WIDGETINFOMODEL_H
+#define WIDGETINFOMODEL_H
+
+#include <QtCore/QAbstractListModel>
+#include <MDConfGroup>
+
+#include "widgetinfo.h"
+
+class WidgetInfoModel : public QAbstractListModel
+{
+ Q_OBJECT
+
+public:
+ explicit WidgetInfoModel(const QString &settingsPrefix, QObject *parent = 0);
+
+ enum Roles {
+ UrlRole = Qt::UserRole,
+ InvertRole,
+ PageRole,
+ SizeRole,
+ PositionRole
+ };
+
+ QHash<int, QByteArray> roleNames() const;
+ int rowCount(const QModelIndex &parent) const;
+ QVariant data(const QModelIndex &index, int role) const;
+
+signals:
+
+public slots:
+ void reload();
+ int addWidget(const QUrl &url, int page, WidgetInfo::WidgetPosition pos, WidgetInfo::WidgetSize size);
+ void removeWidget(int widgetId);
+
+private:
+ int findEmptySlot();
+
+private slots:
+ void handleSettingChanged(const QString &key);
+
+private:
+ MDConfGroup *_settings;
+ QVector<WidgetInfo> _widgets;
+};
+
+#endif // WIDGETINFOMODEL_H
diff --git a/src/widgetview.cpp b/src/widgetview.cpp
deleted file mode 100644
index e5bf21e..0000000
--- a/src/widgetview.cpp
+++ /dev/null
@@ -1,50 +0,0 @@
-#include <QtQml/QQmlContext>
-#include <sailfishapp.h>
-
-#include "widgetview.h"
-
-#define NUM_WIDGETS 16
-
-WidgetView::WidgetView(const QString &settingsPrefix, QQuickView *view, QObject *parent)
- : QObject(parent),
- _settings(new MDConfGroup(this)),
- _view(view)
-{
- _settings->setPath(settingsPrefix);
-
- if (!_view) {
- _view = new QQuickView;
- }
-
- for (int w = 0; w < NUM_WIDGETS; w++) {
- WidgetInfo *info = new WidgetInfo(this);
-
- _widgets.append(info);
- _widgetObjects.append(static_cast<QObject*>(info));
- }
-
- reload();
-
- _view->setResizeMode(QQuickView::SizeViewToRootObject);
- _view->setSource(SailfishApp::pathTo("qml/widgetview.qml"));
- _view->rootContext()->setContextProperty("widgets", QVariant::fromValue(_widgetObjects));
-}
-
-QList<WidgetInfo*> WidgetView::widgets()
-{
- return _widgets;
-}
-
-void WidgetView::reload()
-{
- for (int w = 0; w < _widgets.size(); w++) {
- WidgetInfo *widget = _widgets[w];
- QString base = QString("widget%1/").arg(w);
-
- widget->setInvert(_settings->value(base + "invert").toBool());
- widget->setPage(_settings->value(base + "page").toInt());
- widget->setSize(static_cast<WidgetInfo::WidgetSize>(_settings->value(base + "size").toInt()));
- widget->setPosition(static_cast<WidgetInfo::WidgetPosition>(_settings->value(base + "position").toInt()));
- widget->setUrl(_settings->value(base + "url").toUrl());
- }
-}
diff --git a/src/widgetview.h b/src/widgetview.h
deleted file mode 100644
index 6ce294d..0000000
--- a/src/widgetview.h
+++ /dev/null
@@ -1,30 +0,0 @@
-#ifndef WIDGETVIEW_H
-#define WIDGETVIEW_H
-
-#include <QtCore/QObject>
-#include <QtCore/QVector>
-#include <QtQuick/QQuickView>
-
-#include <MDConfGroup>
-
-#include "widgetinfo.h"
-
-class WidgetView : public QObject
-{
- Q_OBJECT
-public:
- WidgetView(const QString &settingsPrefix, QQuickView *view, QObject *parent = 0);
-
- QList<WidgetInfo*> widgets();
-
-public slots:
- void reload();
-
-private:
- MDConfGroup *_settings;
- QQuickView *_view;
- QList<WidgetInfo*> _widgets;
- QObjectList _widgetObjects;
-};
-
-#endif // WIDGETVIEW_H
diff --git a/translations/salmeta.ts b/translations/salmeta.ts
index 09129a8..79cf7af 100644
--- a/translations/salmeta.ts
+++ b/translations/salmeta.ts
@@ -2,7 +2,7 @@
<!DOCTYPE TS>
<TS version="2.0">
<context>
- <name>FirstPage</name>
+ <name>MainPage</name>
<message>
<source>Not done yet</source>
<translation type="unfinished"></translation>
@@ -15,5 +15,9 @@
<source>Widgets</source>
<translation type="unfinished"></translation>
</message>
+ <message>
+ <source>Notifications</source>
+ <translation type="unfinished"></translation>
+ </message>
</context>
</TS>