summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--qml/pages/AddWidget.qml5
-rw-r--r--qml/pages/MainPage.qml2
-rw-r--r--qml/watch/faces/builtinface0.qml11
-rw-r--r--qml/watch/faces/builtinface1.qml11
-rw-r--r--qml/watch/faces/builtinface2.png (renamed from qml/watch/faces/builtinface_what.png)bin906 -> 906 bytes
-rw-r--r--qml/watch/faces/builtinface2.qml11
-rw-r--r--qml/watch/faces/builtinface4.qml2
-rw-r--r--qml/watch/faces/builtinface5.pngbin0 -> 1663 bytes
-rw-r--r--qml/watch/faces/builtinface5.qml11
-rw-r--r--salmeta.pro3
-rw-r--r--src/availablewidgetsmodel.cpp31
-rw-r--r--src/widgetinfomodel.cpp125
-rw-r--r--src/widgetinfomodel.h7
-rw-r--r--translations/salmeta.ts34
14 files changed, 231 insertions, 22 deletions
diff --git a/qml/pages/AddWidget.qml b/qml/pages/AddWidget.qml
index 5c3086e..c854c7c 100644
--- a/qml/pages/AddWidget.qml
+++ b/qml/pages/AddWidget.qml
@@ -19,13 +19,14 @@ Page {
}
delegate : BackgroundItem {
+ id: widgetDelegate
contentHeight: Theme.itemSizeSmall
Label {
anchors.left: parent.left
anchors.margins: Theme.paddingLarge
anchors.verticalCenter: parent.verticalCenter
- text: model.description
+ text: model.description + (!widgetDelegate.enabled ? qsTr(" (does not fit)") : "")
truncationMode: TruncationMode.Elide
color: highlighted ? Theme.highlightColor : Theme.primaryColor
}
@@ -34,6 +35,8 @@ Page {
curWidgets.addWidget(model.url, addToPage, addToPos, model.size);
pageStack.pop();
}
+
+ enabled: !curWidgets.widgetOverlaps(addToPage, addToPos, model.size);
}
}
}
diff --git a/qml/pages/MainPage.qml b/qml/pages/MainPage.qml
index b25ff06..20d602f 100644
--- a/qml/pages/MainPage.qml
+++ b/qml/pages/MainPage.qml
@@ -227,7 +227,7 @@ Page {
Label {
x: Theme.paddingLarge
- text: "TODO"
+ text: "TODO: List of notification types"
}
}
}
diff --git a/qml/watch/faces/builtinface0.qml b/qml/watch/faces/builtinface0.qml
new file mode 100644
index 0000000..a8df091
--- /dev/null
+++ b/qml/watch/faces/builtinface0.qml
@@ -0,0 +1,11 @@
+import QtQuick 2.0
+
+Rectangle {
+ width: 96/2
+ height: 96/2
+
+ Image {
+ anchors.fill: parent
+ source: "builtinface0.png"
+ }
+}
diff --git a/qml/watch/faces/builtinface1.qml b/qml/watch/faces/builtinface1.qml
new file mode 100644
index 0000000..3d4bb57
--- /dev/null
+++ b/qml/watch/faces/builtinface1.qml
@@ -0,0 +1,11 @@
+import QtQuick 2.0
+
+Rectangle {
+ width: 96
+ height: 96/2
+
+ Image {
+ anchors.fill: parent
+ source: "builtinface3.png"
+ }
+}
diff --git a/qml/watch/faces/builtinface_what.png b/qml/watch/faces/builtinface2.png
index 3ade62b..3ade62b 100644
--- a/qml/watch/faces/builtinface_what.png
+++ b/qml/watch/faces/builtinface2.png
Binary files differ
diff --git a/qml/watch/faces/builtinface2.qml b/qml/watch/faces/builtinface2.qml
new file mode 100644
index 0000000..7c4542a
--- /dev/null
+++ b/qml/watch/faces/builtinface2.qml
@@ -0,0 +1,11 @@
+import QtQuick 2.0
+
+Rectangle {
+ width: 96
+ height: 96
+
+ Image {
+ anchors.fill: parent
+ source: "builtinface2.png"
+ }
+}
diff --git a/qml/watch/faces/builtinface4.qml b/qml/watch/faces/builtinface4.qml
index f9eff50..ca542d4 100644
--- a/qml/watch/faces/builtinface4.qml
+++ b/qml/watch/faces/builtinface4.qml
@@ -6,6 +6,6 @@ Rectangle {
Image {
anchors.fill: parent
- source: "builtinface4.png"
+ source: "builtinface3.png"
}
}
diff --git a/qml/watch/faces/builtinface5.png b/qml/watch/faces/builtinface5.png
new file mode 100644
index 0000000..d084bb0
--- /dev/null
+++ b/qml/watch/faces/builtinface5.png
Binary files differ
diff --git a/qml/watch/faces/builtinface5.qml b/qml/watch/faces/builtinface5.qml
new file mode 100644
index 0000000..e64703c
--- /dev/null
+++ b/qml/watch/faces/builtinface5.qml
@@ -0,0 +1,11 @@
+import QtQuick 2.0
+
+Rectangle {
+ width: 96
+ height: 96
+
+ Image {
+ anchors.fill: parent
+ source: "builtinface5.png"
+ }
+}
diff --git a/salmeta.pro b/salmeta.pro
index 550925f..86ccf52 100644
--- a/salmeta.pro
+++ b/salmeta.pro
@@ -45,8 +45,7 @@ OTHER_FILES += qml/salmeta.qml \
qml/pages/MainPage.qml \
qml/watch/WidgetView.qml \
qml/watch/WatchView.qml qml/watch/add_widget.png \
- qml/watch/faces/builtinface3.qml qml/watch/faces/builtinface3.png \
- qml/watch/faces/builtinface4.qml qml/watch/faces/builtinface4.png \
+ qml/watch/faces/*.qml qml/watch/faces/*.png \
qml/watch/icons/*.png \
qml/pages/AddWidget.qml \
qml/watch/notification.png
diff --git a/src/availablewidgetsmodel.cpp b/src/availablewidgetsmodel.cpp
index 37232dc..77304b9 100644
--- a/src/availablewidgetsmodel.cpp
+++ b/src/availablewidgetsmodel.cpp
@@ -53,17 +53,42 @@ void AvailableWidgetsModel::reload()
// Load builtin widgets
WidgetInfo info;
+ info.setUrl(SailfishApp::pathTo("qml/watch/faces/builtinface0.qml"));
+ info.setDescription(tr("Watchface: 1x1 Small"));
+ info.setSize(WidgetInfo::Size1Q);
+ Q_ASSERT(info.builtinClockfaceId() == 0); // Ensure face ID is autodetected from passed URL
+ _widgets.append(info);
+
+
+ info.setUrl(SailfishApp::pathTo("qml/watch/faces/builtinface1.qml"));
+ info.setDescription(tr("Watchface: 2x1 Horizontal"));
+ info.setSize(WidgetInfo::Size2QHorizontal);
+ Q_ASSERT(info.builtinClockfaceId() == 1);
+ _widgets.append(info);
+
+ info.setUrl(SailfishApp::pathTo("qml/watch/faces/builtinface2.qml"));
+ info.setDescription(tr("Watchface: 2x2 MetaWatch logo"));
+ info.setSize(WidgetInfo::Size4Q);
+ Q_ASSERT(info.builtinClockfaceId() == 2);
+ _widgets.append(info);
+
info.setUrl(SailfishApp::pathTo("qml/watch/faces/builtinface3.qml"));
- info.setDescription("Builtin watchface #3");
+ info.setDescription(tr("Watchface: 2x2 Big numbers"));
info.setSize(WidgetInfo::Size4Q);
- Q_ASSERT(info.builtinClockfaceId() == 3); // Autodetected from passed URL
+ Q_ASSERT(info.builtinClockfaceId() == 3);
_widgets.append(info);
info.setUrl(SailfishApp::pathTo("qml/watch/faces/builtinface4.qml"));
- info.setDescription("Builtin watchface #4");
+ info.setDescription(tr("Watchface: 2x2 Fish"));
info.setSize(WidgetInfo::Size4Q);
Q_ASSERT(info.builtinClockfaceId() == 4);
_widgets.append(info);
+ info.setUrl(SailfishApp::pathTo("qml/watch/faces/builtinface5.qml"));
+ info.setDescription(tr("Watchface: 2x2 Hanzi"));
+ info.setSize(WidgetInfo::Size4Q);
+ Q_ASSERT(info.builtinClockfaceId() == 5);
+ _widgets.append(info);
+
endResetModel();
}
diff --git a/src/widgetinfomodel.cpp b/src/widgetinfomodel.cpp
index e2f145f..9bb53e4 100644
--- a/src/widgetinfomodel.cpp
+++ b/src/widgetinfomodel.cpp
@@ -1,4 +1,5 @@
#include <QtCore/QDebug>
+#include <QtCore/QBitArray>
#include <QtCore/QStringList>
#include "widgetinfomodel.h"
@@ -10,6 +11,82 @@ inline QString get_widget_dconf_base(int index)
return QString("widget%1_").arg(index);
}
+WidgetInfo::WidgetPosition canonicalize_widget_pos(WidgetInfo::WidgetPosition pos, WidgetInfo::WidgetSize size)
+{
+ switch (size) {
+ case WidgetInfo::Size1Q:
+ return pos; // Any position is valid
+ case WidgetInfo::Size2QHorizontal:
+ switch (pos) {
+ case WidgetInfo::PosNW:
+ case WidgetInfo::PosNE:
+ return WidgetInfo::PosNW;
+ case WidgetInfo::PosSW:
+ case WidgetInfo::PosSE:
+ return WidgetInfo::PosSW;
+ }
+ break;
+ case WidgetInfo::Size2QVertical:
+ switch (pos) {
+ case WidgetInfo::PosNW:
+ case WidgetInfo::PosSW:
+ return WidgetInfo::PosNW;
+ case WidgetInfo::PosNE:
+ case WidgetInfo::PosSE:
+ return WidgetInfo::PosNE;
+ }
+ break;
+ case WidgetInfo::Size4Q:
+ return WidgetInfo::PosNW; // 4Q widgets use entire screen
+ }
+
+ return pos;
+}
+
+QBitArray used_positions(WidgetInfo::WidgetPosition pos, WidgetInfo::WidgetSize size)
+{
+ QBitArray used(4, false);
+
+ switch (size) {
+ case WidgetInfo::Size1Q:
+ used[pos] = true;
+ break;
+ case WidgetInfo::Size2QHorizontal:
+ switch (pos) {
+ case WidgetInfo::PosNW:
+ case WidgetInfo::PosNE:
+ used[WidgetInfo::PosNW] = true;
+ used[WidgetInfo::PosNE] = true;
+ break;
+ case WidgetInfo::PosSW:
+ case WidgetInfo::PosSE:
+ used[WidgetInfo::PosNW] = true;
+ used[WidgetInfo::PosNE] = true;
+ break;
+ }
+ break;
+ case WidgetInfo::Size2QVertical:
+ switch (pos) {
+ case WidgetInfo::PosNW:
+ case WidgetInfo::PosSW:
+ used[WidgetInfo::PosNW] = true;
+ used[WidgetInfo::PosSW] = true;
+ break;
+ case WidgetInfo::PosNE:
+ case WidgetInfo::PosSE:
+ used[WidgetInfo::PosNE] = true;
+ used[WidgetInfo::PosSE] = true;
+ break;
+ }
+ break;
+ case WidgetInfo::Size4Q:
+ used.fill(true);
+ break;
+ }
+
+ return used;
+}
+
}
WidgetInfoModel::WidgetInfoModel(const QString &settingsPrefix, QObject *parent) :
@@ -69,23 +146,21 @@ QList<WidgetInfo> WidgetInfoModel::toList() const
return _widgets.toList();
}
-void WidgetInfoModel::reload()
+bool WidgetInfoModel::widgetOverlaps(int page, WidgetInfo::WidgetPosition pos, WidgetInfo::WidgetSize size) const
{
- beginResetModel();
- _widgets.resize(16);
+ QBitArray usedPos = used_positions(pos, size);
for (int i = 0; i < _widgets.size(); i++) {
- WidgetInfo &info = _widgets[i];
- const QString base = get_widget_dconf_base(i);
+ if (_widgets[i].url().isEmpty()) continue;
+ if (_widgets[i].page() != page) continue;
- 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());
+ QBitArray intersection = usedPos & used_positions(_widgets[i].position(), _widgets[i].size());
+ if (intersection.count(true) > 0) {
+ return true;
+ }
}
- endResetModel();
+ return false;
}
int WidgetInfoModel::addWidget(const QUrl &url, int page, WidgetInfo::WidgetPosition pos, WidgetInfo::WidgetSize size)
@@ -93,11 +168,18 @@ int WidgetInfoModel::addWidget(const QUrl &url, int page, WidgetInfo::WidgetPosi
int slot = findEmptySlot();
if (slot == -1) {
qWarning() << "No empty slots!"; // This shouldn't happen
- return slot;
+ return -1;
}
+ pos = canonicalize_widget_pos(pos, size);
+
qDebug() << "Adding widget" << url << page << pos << size;
+ if (widgetOverlaps(page, pos, size)) {
+ qWarning() << "Can't add the widget: it overlaps with an existing one!";
+ return -1;
+ }
+
const QString base = get_widget_dconf_base(slot);
_settings->setValue(base + "invert", QVariant::fromValue<bool>(false));
@@ -122,6 +204,25 @@ void WidgetInfoModel::removeWidget(int widgetId)
_settings->setValue(base + "position", 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::findEmptySlot()
{
for (int i = 0; i < _widgets.size(); i++) {
diff --git a/src/widgetinfomodel.h b/src/widgetinfomodel.h
index 4b2a700..bc3cd67 100644
--- a/src/widgetinfomodel.h
+++ b/src/widgetinfomodel.h
@@ -27,12 +27,15 @@ public:
QList<WidgetInfo> toList() const;
+ Q_INVOKABLE bool widgetOverlaps(int page, WidgetInfo::WidgetPosition pos, WidgetInfo::WidgetSize size) const;
+
+ Q_INVOKABLE int addWidget(const QUrl &url, int page, WidgetInfo::WidgetPosition pos, WidgetInfo::WidgetSize size);
+ Q_INVOKABLE void removeWidget(int widgetId);
+
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();
diff --git a/translations/salmeta.ts b/translations/salmeta.ts
index 786af13..605d20c 100644
--- a/translations/salmeta.ts
+++ b/translations/salmeta.ts
@@ -2,6 +2,40 @@
<!DOCTYPE TS>
<TS version="2.0">
<context>
+ <name>AddWidget</name>
+ <message>
+ <source> (does not fit)</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>AvailableWidgetsModel</name>
+ <message>
+ <source>Watchface: 1x1 Small</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Watchface: 2x1 Horizontal</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Watchface: 2x2 MetaWatch logo</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Watchface: 2x2 Big numbers</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Watchface: 2x2 Fish</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Watchface: 2x2 Hanzi</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
<name>MainPage</name>
<message>
<source>Not done yet</source>