summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJavier S. Pedro <dev.git@javispedro.com>2014-09-14 14:11:26 +0200
committerJavier S. Pedro <dev.git@javispedro.com>2014-09-14 14:11:26 +0200
commitb9b1829dbc50534190c8b81f91ee477af6971834 (patch)
tree360f09061f43a247a5afdc2c83df2b9a03d86a4a
parent85fb48bc51fed06a50b6178727fdf9e96aea4fc4 (diff)
downloadsalmeta-b9b1829dbc50534190c8b81f91ee477af6971834.tar.gz
salmeta-b9b1829dbc50534190c8b81f91ee477af6971834.zip
addign watch properties, starting notification work
-rw-r--r--qml/pages/AddWidget.qml5
-rw-r--r--qml/pages/MainPage.qml137
-rw-r--r--qml/pages/WatchView.qml5
-rw-r--r--qml/watch/faces/builtinface3.pngbin0 -> 892 bytes
-rw-r--r--qml/watch/faces/builtinface3.qml11
-rw-r--r--rpm/salmeta.spec3
-rw-r--r--rpm/salmeta.yaml3
-rw-r--r--salmeta.pro9
-rw-r--r--src/availablewidgetsmodel.cpp9
-rw-r--r--src/controller.cpp152
-rw-r--r--src/controller.h27
-rw-r--r--src/metawatch.cpp56
-rw-r--r--src/metawatch.h19
-rw-r--r--src/notification.cpp6
-rw-r--r--src/notification.h17
-rw-r--r--src/notificationadaptor.cpp27
-rw-r--r--src/notificationadaptor.h65
-rw-r--r--src/notificationmonitor.cpp55
-rw-r--r--src/notificationmonitor.h21
-rw-r--r--src/org.freedesktop.Notifications.xml46
-rw-r--r--src/widgetinfo.cpp18
-rw-r--r--src/widgetinfo.h2
-rw-r--r--src/widgetinfomodel.cpp6
-rw-r--r--src/widgetinfomodel.h2
-rw-r--r--translations/salmeta.ts16
25 files changed, 654 insertions, 63 deletions
diff --git a/qml/pages/AddWidget.qml b/qml/pages/AddWidget.qml
index 50bf63d..d79ede9 100644
--- a/qml/pages/AddWidget.qml
+++ b/qml/pages/AddWidget.qml
@@ -22,13 +22,14 @@ Page {
contentHeight: Theme.itemSizeMedium
Label {
- text: url
+ x: Theme.paddingLarge
+ text: model.description
truncationMode: TruncationMode.Elide
color: highlighted ? Theme.highlightColor : Theme.primaryColor
}
onClicked: {
- curWidgets.addWidget(url, addToPage, addToPos, size);
+ curWidgets.addWidget(model.url, addToPage, addToPos, model.size);
pageStack.pop();
}
}
diff --git a/qml/pages/MainPage.qml b/qml/pages/MainPage.qml
index 5448754..9014a48 100644
--- a/qml/pages/MainPage.qml
+++ b/qml/pages/MainPage.qml
@@ -12,6 +12,18 @@ Page {
defaultValue: "Select"
}
+ ConfigurationValue {
+ id: curPageSetting
+ key: curSettingsPrefix + "/cur-page"
+ defaultValue: 0
+
+ onValueChanged: {
+ if (watchView.curPage !== value) {
+ watchView.switchToPage(value);
+ }
+ }
+ }
+
SilicaFlickable {
anchors.fill: parent
@@ -26,7 +38,7 @@ Page {
Column {
id: column
width: page.width
- spacing: Theme.paddingLarge
+ spacing: Theme.paddingMedium
PageHeader {
title: "Salmeta"
@@ -37,7 +49,6 @@ Page {
}
ValueButton {
- x: Theme.paddingLarge
label: "Device"
value: deviceAddress.value
@@ -52,6 +63,122 @@ Page {
}
}
+ ComboBox {
+ id: timeFormat
+ label: qsTr("Time format");
+
+ function load() {
+ if (showSecondsSetting.value) {
+ currentIndex = timeFormatSetting.value ? 3 : 2;
+ } else {
+ currentIndex = timeFormatSetting.value ? 1 : 0;
+ }
+ }
+
+ ConfigurationValue {
+ id: timeFormatSetting
+ key: curSettingsPrefix + "/24h-mode"
+ defaultValue: 0
+ }
+
+ ConfigurationValue {
+ id: showSecondsSetting
+ key: curSettingsPrefix + "/show-seconds"
+ defaultValue: 0
+ }
+
+ Component.onCompleted: {
+ load();
+ }
+
+ menu: ContextMenu {
+ MenuItem {
+ text: Qt.formatTime(new Date(), "hh:mm ap")
+ }
+ MenuItem {
+ text: Qt.formatTime(new Date(), "hh:mm")
+ }
+ MenuItem {
+ text: Qt.formatTime(new Date(), "hh:mm:ss ap")
+ }
+ MenuItem {
+ text: Qt.formatTime(new Date(), "hh:mm:ss")
+ }
+ }
+
+ onCurrentIndexChanged: {
+ timeFormatSetting.value = currentIndex === 1 || currentIndex === 3;
+ showSecondsSetting.value = currentIndex === 2 || currentIndex === 3;
+ }
+ }
+
+ ComboBox {
+ id: dateFormat
+ label: qsTr("Date format");
+
+ ConfigurationValue {
+ id: dateFormatSetting
+ key: curSettingsPrefix + "/ddmm-mode"
+ defaultValue: 0
+ }
+
+ menu: ContextMenu {
+ MenuItem {
+ text: Qt.formatDate(new Date(), "M/d")
+ }
+ MenuItem {
+ text: Qt.formatDate(new Date(), "d/M")
+ }
+ }
+
+ onCurrentIndexChanged: {
+ dateFormatSetting.value = currentIndex;
+ }
+
+ Component.onCompleted: {
+ currentIndex = dateFormatSetting.value ? 1 : 0;
+ }
+ }
+
+ TextSwitch {
+ id: separators
+ text: qsTr("Show separator lines");
+
+ ConfigurationValue {
+ id: separatorsSetting
+ key: curSettingsPrefix + "/show-separation-lines"
+ defaultValue: false
+ }
+
+ onCheckedChanged: {
+ separatorsSetting.value = checked;
+ }
+
+ Component.onCompleted: {
+ checked = separatorsSetting.value;
+ }
+ }
+
+ TextSwitch {
+ id: autobacklight
+ text: qsTr("Auto-backlight");
+
+ ConfigurationValue {
+ id: autobacklightSetting
+ key: curSettingsPrefix + "/auto-backlight"
+ defaultValue: false
+ }
+
+ onCheckedChanged: {
+ autobacklightSetting.value = checked;
+ }
+
+ Component.onCompleted: {
+ checked = autobacklightSetting.value;
+ }
+ }
+
+
SectionHeader {
text: qsTr("Widgets");
}
@@ -65,6 +192,12 @@ Page {
id: watchView
anchors.centerIn: parent
scale: 4
+
+ onCurPageChanged: {
+ if (curPageSetting.value !== curPage) {
+ curPageSetting.value = curPage;
+ }
+ }
}
}
diff --git a/qml/pages/WatchView.qml b/qml/pages/WatchView.qml
index e738f4e..a5d755e 100644
--- a/qml/pages/WatchView.qml
+++ b/qml/pages/WatchView.qml
@@ -42,4 +42,9 @@ Flickable {
curPage = Math.round(watchView.contentX / watchView.width)
pivotAnim.start()
}
+
+ function switchToPage(page) {
+ curPage = page;
+ pivotAnim.start();
+ }
}
diff --git a/qml/watch/faces/builtinface3.png b/qml/watch/faces/builtinface3.png
new file mode 100644
index 0000000..9154c9d
--- /dev/null
+++ b/qml/watch/faces/builtinface3.png
Binary files differ
diff --git a/qml/watch/faces/builtinface3.qml b/qml/watch/faces/builtinface3.qml
new file mode 100644
index 0000000..ca542d4
--- /dev/null
+++ b/qml/watch/faces/builtinface3.qml
@@ -0,0 +1,11 @@
+import QtQuick 2.0
+
+Rectangle {
+ width: 96
+ height: 96
+
+ Image {
+ anchors.fill: parent
+ source: "builtinface3.png"
+ }
+}
diff --git a/rpm/salmeta.spec b/rpm/salmeta.spec
index de24543..d1f3b26 100644
--- a/rpm/salmeta.spec
+++ b/rpm/salmeta.spec
@@ -33,6 +33,7 @@ BuildRequires: pkgconfig(Qt5DBus)
BuildRequires: pkgconfig(Qt5Bluetooth)
BuildRequires: pkgconfig(mlite5)
BuildRequires: pkgconfig(libiphb)
+BuildRequires: libgato-devel
BuildRequires: desktop-file-utils
%description
@@ -73,7 +74,7 @@ desktop-file-install --delete-original \
# >> post
if [ "$1" -ge 1 ]; then
systemctl-user daemon-reload || :
-systemctl-user restart salmeta.service || :
+#systemctl-user restart salmeta.service || :
fi
# << post
diff --git a/rpm/salmeta.yaml b/rpm/salmeta.yaml
index d664d45..17ec9bd 100644
--- a/rpm/salmeta.yaml
+++ b/rpm/salmeta.yaml
@@ -22,6 +22,9 @@ PkgConfigBR:
- mlite5
- libiphb
+PkgBR:
+ - libgato-devel
+
Requires:
- sailfishsilica-qt5 >= 0.10.9
- sailfish-components-bluetooth-qt5
diff --git a/salmeta.pro b/salmeta.pro
index acc91c4..4a75956 100644
--- a/salmeta.pro
+++ b/salmeta.pro
@@ -18,7 +18,9 @@ SOURCES += src/salmeta.cpp \
src/notificationmonitor.cpp \
src/widgetinfo.cpp \
src/widgetinfomodel.cpp \
- src/availablewidgetsmodel.cpp
+ src/availablewidgetsmodel.cpp \
+ src/notificationadaptor.cpp \
+ src/notification.cpp
HEADERS += \
src/controller.h \
@@ -29,7 +31,9 @@ HEADERS += \
src/notificationmonitor.h \
src/widgetinfo.h \
src/widgetinfomodel.h \
- src/availablewidgetsmodel.h
+ src/availablewidgetsmodel.h \
+ src/notificationadaptor.h \
+ src/notification.h
OTHER_FILES += qml/salmeta.qml \
qml/cover/CoverPage.qml \
@@ -43,6 +47,7 @@ OTHER_FILES += qml/salmeta.qml \
qml/pages/MainPage.qml \
qml/watch/WidgetView.qml \
qml/pages/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/pages/AddWidget.qml
diff --git a/src/availablewidgetsmodel.cpp b/src/availablewidgetsmodel.cpp
index 02ca746..b95e79a 100644
--- a/src/availablewidgetsmodel.cpp
+++ b/src/availablewidgetsmodel.cpp
@@ -13,6 +13,7 @@ QHash<int, QByteArray> AvailableWidgetsModel::roleNames() const
QHash<int, QByteArray> roles;
roles[UrlRole] = "url";
+ roles[DescriptionRole] = "description";
roles[SizeRole] = "size";
return roles;
@@ -51,14 +52,16 @@ void AvailableWidgetsModel::reload()
// Load builtin widgets
WidgetInfo info;
- info.setUrl(SailfishApp::pathTo("qml/watch/faces/builtinface4.qml"));
- info.setDescription("Watchface #4");
+ info.setUrl(SailfishApp::pathTo("qml/watch/faces/builtinface3.qml"));
+ info.setDescription("Builtin watchface #3");
info.setSize(WidgetInfo::Size4Q);
+ Q_ASSERT(info.builtinClockfaceId() == 3); // Autodetected from passed URL
_widgets.append(info);
info.setUrl(SailfishApp::pathTo("qml/watch/faces/builtinface4.qml"));
- info.setDescription("Watchface #4");
+ info.setDescription("Builtin watchface #4");
info.setSize(WidgetInfo::Size4Q);
+ Q_ASSERT(info.builtinClockfaceId() == 4);
_widgets.append(info);
endResetModel();
diff --git a/src/controller.cpp b/src/controller.cpp
index 9d1961c..a5ff22d 100644
--- a/src/controller.cpp
+++ b/src/controller.cpp
@@ -4,9 +4,12 @@
#include "controller.h"
static const QLatin1String setting_address("address");
-static const QLatin1String setting_num_pages("num-pages");
-static const QLatin1String setting_page("page%1");
-static const QLatin1String setting_page_widget("widget%1");
+static const QLatin1String setting_cur_page("cur-page");
+static const QLatin1String setting_24h_mode("24h-mode");
+static const QLatin1String setting_ddmm_mode("ddmm-mode");
+static const QLatin1String setting_seconds("show-seconds");
+static const QLatin1String setting_separation_lines("show-separation-lines");
+static const QLatin1String setting_auto_backlight("auto-backlight");
Controller::Controller(const QString &settingsPrefix, QQuickView *view, QObject *parent) :
QObject(parent),
@@ -14,22 +17,39 @@ Controller::Controller(const QString &settingsPrefix, QQuickView *view, QObject
_metawatch(0),
_reconnect(new ReconnectTimer(this)),
_widgets(new WidgetInfoModel(settingsPrefix, this)),
+ _curMode(MetaWatch::WatchModeIdle), _curPage(0),
_batteryCharge(0), _batteryCharging(false)
{
_settings->setPath(settingsPrefix);
- _metawatch = new MetaWatch(_settings->value(setting_address).toString(), this);
+ _curPage = _settings->value(setting_cur_page).toInt();
connect(_settings, &MDConfGroup::valueChanged, this, &Controller::handleSettingChanged);
- connect(_metawatch, &MetaWatch::connected, _reconnect, &ReconnectTimer::stop);
- connect(_metawatch, &MetaWatch::connected, this, &Controller::handleMetaWatchConnected);
- connect(_metawatch, &MetaWatch::disconnected, _reconnect, &ReconnectTimer::scheduleNextAttempt);
- connect(_metawatch, &MetaWatch::batteryStatus, this, &Controller::handleMetaWatchBatteryStatus);
- connect(_reconnect, &ReconnectTimer::tryReconnect, _metawatch, &MetaWatch::connectDevice);
- connect(_recc)
+ connect(_widgets, &QAbstractItemModel::dataChanged, this, &Controller::handleWidgetChanged);
- _reconnect->scheduleNextAttempt();
+ connectToAddress(_settings->value(setting_address).toString());
+}
+
+Controller::~Controller()
+{
+}
+
+MetaWatch::WatchMode Controller::mode() const
+{
+ return _curMode;
+}
+
+int Controller::page() const
+{
+ return _curPage;
+}
- reloadPages();
+void Controller::setPage(int page)
+{
+ if (page != _curPage) {
+ _curPage = page;
+ _metawatch->updateLcdDisplayPage(_curPage);
+ emit pageChanged();
+ }
}
int Controller::batteryCharge() const
@@ -42,22 +62,79 @@ bool Controller::batteryCharging() const
return _batteryCharging;
}
-void Controller::reloadPages()
+void Controller::connectToAddress(const QString &address)
{
+ if (_metawatch) {
+ if (address == _address) {
+ // Connecting to the same address and there's already a watch object created
+ return;
+ }
+
+ _reconnect->stop();
+ disconnect(_metawatch, 0, this, 0);
+ disconnect(_metawatch, 0, _reconnect, 0);
+ delete _metawatch;
+ _metawatch = 0;
+ }
+
+ _address = address;
+
+ if (_address.isEmpty()) {
+ qDebug() << "Empty address, doing nothing except wasting memory";
+ return;
+ }
+
+ _metawatch = new MetaWatch(_address, this);
+ connect(_metawatch, &MetaWatch::connected, _reconnect, &ReconnectTimer::stop);
+ connect(_metawatch, &MetaWatch::connected, this, &Controller::handleMetaWatchConnected);
+ connect(_metawatch, &MetaWatch::disconnected, _reconnect, &ReconnectTimer::scheduleNextAttempt);
+ connect(_metawatch, &MetaWatch::modeChange, this, &Controller::handleMetaWatchModeChange);
+ connect(_metawatch, &MetaWatch::batteryStatus, this, &Controller::handleMetaWatchBatteryStatus);
+ connect(_reconnect, &ReconnectTimer::tryReconnect, _metawatch, &MetaWatch::connectDevice);
+ _reconnect->scheduleNextAttempt();
}
-void Controller::switchToPage(int page)
+void Controller::updateProperties()
{
+ MetaWatch::WatchProperties props;
+
+ if (_settings->value(setting_24h_mode).toBool()) {
+ props |= MetaWatch::WatchPropertyHourFormat24h;
+ }
+
+ if (_settings->value(setting_ddmm_mode).toBool()) {
+ props |= MetaWatch::WatchPropertyDateFormatDDMM;
+ }
+
+ if (_settings->value(setting_seconds).toBool()) {
+ props |= MetaWatch::WatchPropertyShowSeconds;
+ }
+
+ if (_settings->value(setting_separation_lines).toBool()) {
+ props |= MetaWatch::WatchPropertyShowSeparationLines;
+ }
+
+ if (_settings->value(setting_auto_backlight).toBool()) {
+ props |= MetaWatch::WatchPropertyAutoBacklight;
+ }
+ _metawatch->configure(props);
}
void Controller::handleSettingChanged(const QString &key)
{
qDebug() << "Setting" << key << "changed";
- if (key == setting_num_pages) {
- _settings->value(setting_num_pages, 0);
- switchToPage(0);
+ if (key == setting_address) {
+ connectToAddress(_settings->value(setting_address).toString());
+ } else if (key == setting_cur_page) {
+ int page = _settings->value(setting_cur_page).toInt();
+ if (_curPage != page) {
+ setPage(page);
+ }
+ } else if (key == setting_24h_mode || key == setting_ddmm_mode || key == setting_seconds
+ || key == setting_separation_lines || key == setting_auto_backlight) {
+ updateProperties();
}
}
@@ -68,9 +145,33 @@ void Controller::handleMetaWatchConnected()
_metawatch->updateDeviceType();
_metawatch->updateBatteryStatus();
_metawatch->setDateTime(QDateTime::currentDateTime());
- _metawatch->updateLcdDisplay();
+ _metawatch->updateWidgetList(_widgets->toList());
+ _metawatch->updateLcdDisplayPage(_curPage);
+
+ _curMode = MetaWatch::WatchModeIdle;
+
+ updateProperties();
+}
- // TODO _metawatch->updateWidgetList(_view->widgets());
+void Controller::handleMetaWatchModeChange(MetaWatch::WatchMode mode, int page)
+{
+ switch (mode) {
+ case MetaWatch::WatchModeIdle:
+ if (_curMode != mode) {
+ _curMode = mode;
+ emit modeChanged();
+ }
+ if (page != _curPage) {
+ _curPage = page;
+ _settings->setValue(setting_cur_page, QVariant::fromValue(_curPage));
+ emit pageChanged();
+ }
+
+ break;
+ default:
+ qWarning() << "Unhandled metawatch mode:" << mode;
+ break;
+ }
}
void Controller::handleMetaWatchBatteryStatus(bool charging, int charge)
@@ -84,3 +185,16 @@ void Controller::handleMetaWatchBatteryStatus(bool charging, int charge)
emit batteryChargeChanged();
}
}
+
+void Controller::handleWidgetChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles)
+{
+ if (roles.indexOf(WidgetInfoModel::UrlRole) >= 0) {
+ // Can't send partial updates to watch, so entire list must be
+ // resubmitted everytime something important changes
+ _metawatch->updateWidgetList(_widgets->toList());
+
+ if (_widgets->data(topLeft, WidgetInfoModel::PageRole).toInt() == _curPage) {
+ _metawatch->updateLcdDisplayPage(_curPage);
+ }
+ }
+}
diff --git a/src/controller.h b/src/controller.h
index 3570ff4..604da2e 100644
--- a/src/controller.h
+++ b/src/controller.h
@@ -1,8 +1,8 @@
#ifndef DAEMON_H
#define DAEMON_H
-#include <QObject>
-#include <QQuickView>
+#include <QtCore/QObject>
+#include <QtQuick/QQuickView>
#include <MDConfGroup>
#include "metawatch.h"
@@ -13,30 +13,39 @@ class Controller : public QObject
{
Q_OBJECT
+ Q_PROPERTY(MetaWatch::WatchMode mode READ mode NOTIFY modeChanged)
+ Q_PROPERTY(int page READ page WRITE setPage NOTIFY pageChanged)
Q_PROPERTY(int batteryCharge READ batteryCharge NOTIFY batteryChargeChanged)
Q_PROPERTY(bool batteryCharging READ batteryCharging NOTIFY batteryChargingChanged)
public:
Controller(const QString &settingsPrefix, QQuickView *view = 0, QObject *parent = 0);
+ ~Controller();
+
+ MetaWatch::WatchMode mode() const;
+
+ int page() const;
+ void setPage(int page);
int batteryCharge() const;
bool batteryCharging() const;
signals:
+ void modeChanged();
+ void pageChanged();
void batteryChargeChanged();
void batteryChargingChanged();
-public slots:
- void reloadPages();
- void switchToPage(int page);
-
private:
- static int parseClockUrl(const QUrl &url);
+ void connectToAddress(const QString &address);
+ void updateProperties();
private slots:
void handleSettingChanged(const QString &key);
void handleMetaWatchConnected();
+ void handleMetaWatchModeChange(MetaWatch::WatchMode mode, int page);
void handleMetaWatchBatteryStatus(bool charging, int charge);
+ void handleWidgetChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles);
private:
MDConfGroup *_settings;
@@ -45,7 +54,11 @@ private:
WidgetInfoModel *_widgets;
+ QString _address;
+
// Watch status
+ MetaWatch::WatchMode _curMode;
+ int _curPage;
int _batteryCharge;
bool _batteryCharging;
};
diff --git a/src/metawatch.cpp b/src/metawatch.cpp
index b1ea8af..b6042af 100644
--- a/src/metawatch.cpp
+++ b/src/metawatch.cpp
@@ -59,8 +59,16 @@ void MetaWatch::updateBatteryStatus()
void MetaWatch::updateLcdDisplay()
{
- // Switches to UiGen2 mode and to page 0.
- _transport->sendMessage(MessageUpdateLcdDisplay, 0x80, QByteArray());
+ _transport->sendMessage(MessageUpdateLcdDisplay,
+ 1 << 7,
+ QByteArray());
+}
+
+void MetaWatch::updateLcdDisplayPage(int page)
+{
+ _transport->sendMessage(MessageUpdateLcdDisplay,
+ 1 << 7 | 1 << 5 | ((page << 2) & 0xC),
+ QByteArray());
}
void MetaWatch::updateWidgetList(const QList<WidgetInfo> &widgets)
@@ -69,8 +77,8 @@ void MetaWatch::updateWidgetList(const QList<WidgetInfo> &widgets)
// Count valid widgets
for (int w = 0; w < widgets.size(); w++) {
- const WidgetInfo *info = widgets[w];
- if (info->valid()) num_widgets++;
+ const WidgetInfo &info = widgets[w];
+ if (info.valid()) num_widgets++;
}
const int max_widgets_in_one_msg = 7;
@@ -82,6 +90,8 @@ void MetaWatch::updateWidgetList(const QList<WidgetInfo> &widgets)
msg.reserve(max_widgets_in_one_msg * 2);
+ qDebug() << "Sending widget list:" << num_widgets << "widgets," << num_messages << "messages";
+
if (num_widgets == 0) {
msg.append(static_cast<char>(0xFF));
msg.append(static_cast<char>(0x00));
@@ -92,27 +102,24 @@ void MetaWatch::updateWidgetList(const QList<WidgetInfo> &widgets)
return;
}
- qDebug() << "Msgs" << num_messages << num_message;
-
- for (int w = 0; w < num_widgets; w++) {
- WidgetInfo *info = widgets[w];
- if (!info->valid()) continue; // Skip disabled/empty widget
+ for (int i = 0; i < widgets.size(); i++) {
+ const WidgetInfo &info = widgets[i];
+ if (!info.valid()) continue; // Skip disabled/empty widget
- quint8 id = w;
- quint8 options = ((info->page() << 4) & 0x30)
- | ((info->size() << 2) & 0xC) | ((info->position() << 2) & 0x3);
+ quint8 id = i;
+ quint8 options = ((info.page() << 4) & 0x30)
+ | ((info.size() << 2) & 0xC) | ((info.position() << 2) & 0x3);
- if (info->url().scheme() == "clock") {
- id |= (clockUrlToClockId(info->url()) << 4) & 0xF0;
+ int clockFace = info.builtinClockfaceId();
+ if (clockFace >= 0) {
+ id |= (clockFace << 4) & 0xF0;
options |= 0x80;
}
- if (info->invert()) {
+ if (info.invert()) {
options |= 0x40;
}
- qDebug() << QString::number(id, 16) << QString::number(options, 16);
-
msg.append(id);
msg.append(options);
@@ -166,6 +173,21 @@ void MetaWatch::handleTransportMessage(quint8 type, quint8 options, const QByteA
break;
case MessageModeChangeIndication:
qDebug() << "Got mode change indication";
+ if (payload.size() < 1) {
+ qWarning() << "Invalid mode change indicator size";
+ }
+ switch (payload.at(0)) {
+ case 1:
+ emit modeChange(WatchMode(options & 0xF), (options >> 4) & 0xF);
+ break;
+ default:
+ qWarning() << "Unknown mode change indicator: " << payload.toHex();
+ break;
+ }
+
+ break;
+ case MessageWatchPropertyOperationResponse:
+ qDebug() << "Got watch property operation response";
break;
case MessageReadBatteryStatusResponse:
if (payload.size() < 6) {
diff --git a/src/metawatch.h b/src/metawatch.h
index 9068c08..6b50ead 100644
--- a/src/metawatch.h
+++ b/src/metawatch.h
@@ -12,7 +12,7 @@ QT_USE_NAMESPACE_BLUETOOTH
class MetaWatch : public QObject
{
Q_OBJECT
- Q_ENUMS(MessageTypes WatchProperty UiStyle)
+ Q_ENUMS(MessageTypes DeviceType WatchMode WatchProperty UiStyle)
Q_FLAGS(WatchProperties)
public:
@@ -25,6 +25,7 @@ public:
MessageSetRealTimeClock = 0x26,
MessageWatchPropertyOperation = 0x30,
+ MessageWatchPropertyOperationResponse = 0x31,
MessageModeChangeIndication = 0x33,
@@ -48,6 +49,10 @@ public:
DeviceMetaWatchDigitalGen2 = 5
};
+ enum WatchMode {
+ WatchModeIdle = 0
+ };
+
enum WatchProperty {
WatchPropertyHourFormat12h = 0,
WatchPropertyHourFormat24h = 1,
@@ -55,10 +60,10 @@ public:
WatchPropertyDateFormatDDMM = 1 << 1,
WatchPropertyShowSeconds = 1 << 2,
WatchPropertyShowSeparationLines = 1 << 3,
- WatchPropertyAutobacklight = 1 << 4,
+ WatchPropertyAutoBacklight = 1 << 4,
- WatchPropertyOperationRead = 0 << 7,
- WatchPropertyOperationWrite = 1 << 7
+ WatchPropertyOperationRead = 1 << 7,
+ WatchPropertyOperationWrite = 0 << 7
};
Q_DECLARE_FLAGS(WatchProperties, WatchProperty)
@@ -74,7 +79,10 @@ public:
void updateDeviceType();
void updateBatteryStatus();
- void updateLcdDisplay(); // TODO: More overloads
+ /** Switches to v2 UI, goes to idle mode */
+ void updateLcdDisplay();
+ /** Goes to idle mode and a specific page */
+ void updateLcdDisplayPage(int page);
void updateWidgetList(const QList<WidgetInfo>& widgets);
signals:
@@ -82,6 +90,7 @@ signals:
void disconnected();
void deviceType(DeviceType type);
+ void modeChange(WatchMode mode, int page);
void batteryStatus(bool charging, int charge);
public slots:
diff --git a/src/notification.cpp b/src/notification.cpp
new file mode 100644
index 0000000..00d66ad
--- /dev/null
+++ b/src/notification.cpp
@@ -0,0 +1,6 @@
+#include "notification.h"
+
+Notification::Notification(QObject *parent) :
+ QObject(parent)
+{
+}
diff --git a/src/notification.h b/src/notification.h
new file mode 100644
index 0000000..899a9aa
--- /dev/null
+++ b/src/notification.h
@@ -0,0 +1,17 @@
+#ifndef NOTIFICATION_H
+#define NOTIFICATION_H
+
+#include <QObject>
+
+class Notification : public QObject
+{
+public:
+ explicit Notification(QObject *parent = 0);
+
+signals:
+
+public slots:
+
+};
+
+#endif // NOTIFICATION_H
diff --git a/src/notificationadaptor.cpp b/src/notificationadaptor.cpp
new file mode 100644
index 0000000..4279831
--- /dev/null
+++ b/src/notificationadaptor.cpp
@@ -0,0 +1,27 @@
+/*
+ * This file was generated by qdbusxml2cpp version 0.7
+ * Command line was: qdbusxml2cpp -c NotificationAdaptor -a notificationadaptor.cpp org.freedesktop.Notifications.xml
+ *
+ * qdbusxml2cpp is Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+ *
+ * This is an auto-generated file.
+ * This file may have been hand-edited. Look for HAND-EDIT comments
+ * before re-generating it.
+ */
+
+#include "notificationadaptor.h"
+
+/*
+ * Implementation of adaptor class NotificationAdaptor
+ */
+
+NotificationAdaptor::NotificationAdaptor(QObject *parent)
+ : QDBusAbstractAdaptor(parent)
+{
+}
+
+uint NotificationAdaptor::Notify(const QString &app_name, uint replaces_id, const QString &app_icon, const QString &summary, const QString &body, const QStringList &actions, const QVariantHash &hints, int expire_timeout)
+{
+ // handle method call org.freedesktop.Notifications.Notify
+ static_cast<NotificationMonitor*>(parent())->handleNotification(app_name, replaces_id, app_icon, summary, body, actions, hints, expire_timeout);
+}
diff --git a/src/notificationadaptor.h b/src/notificationadaptor.h
new file mode 100644
index 0000000..0fba973
--- /dev/null
+++ b/src/notificationadaptor.h
@@ -0,0 +1,65 @@
+/*
+ * This file was generated by qdbusxml2cpp version 0.7
+ * Command line was: qdbusxml2cpp -c NotificationAdaptor -a notificationadaptor.cpp org.freedesktop.Notifications.xml
+ *
+ * qdbusxml2cpp is Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+ *
+ * This is an auto-generated file.
+ * This file may have been hand-edited. Look for HAND-EDIT comments
+ * before re-generating it.
+ */
+
+#ifndef NOTIFICATIONADAPTOR
+#define NOTIFICATIONADAPTOR
+
+#include <QtCore/QObject>
+#include <QtCore/QMetaObject>
+#include <QtCore/QVariant>
+#include <QtDBus/QDBusAbstractAdaptor>
+#include <QtCore/QList>
+#include <QtCore/QMap>
+#include <QtCore/QString>
+#include <QtCore/QStringList>
+#include <QtCore/QVariant>
+
+#include "notificationmonitor.h"
+
+/*
+ * Adaptor class for interface org.freedesktop.Notifications
+ */
+class NotificationAdaptor: public QDBusAbstractAdaptor
+{
+ Q_OBJECT
+ Q_CLASSINFO("D-Bus Interface", "org.freedesktop.Notifications")
+ Q_CLASSINFO("D-Bus Introspection", ""
+" <interface name=\"org.freedesktop.Notifications\">\n"
+" <method name=\"Notify\">\n"
+" <arg direction=\"in\" type=\"s\" name=\"app_name\"/>\n"
+" <arg direction=\"in\" type=\"u\" name=\"replaces_id\"/>\n"
+" <arg direction=\"in\" type=\"s\" name=\"app_icon\"/>\n"
+" <arg direction=\"in\" type=\"s\" name=\"summary\"/>\n"
+" <arg direction=\"in\" type=\"s\" name=\"body\"/>\n"
+" <arg direction=\"in\" type=\"as\" name=\"actions\"/>\n"
+" <arg direction=\"in\" type=\"a{sv}\" name=\"hints\"/>\n"
+" <arg direction=\"in\" type=\"i\" name=\"expire_timeout\"/>\n"
+" <arg direction=\"out\" type=\"u\" name=\"id\"/>\n"
+" <annotation value=\"QVariantHash\" name=\"org.qtproject.QtDBus.QtTypeName.In6\"/>\n"
+" </method>\n"
+" <method name=\"CloseNotification\">\n"
+" <arg direction=\"in\" type=\"u\" name=\"id\"/>\n"
+" </method>\n"
+" </interface>\n"
+ <method name="CloseNotification">
+ <arg name="id" type="u" direction="in"/>
+ </method>
+ "")
+public:
+ explicit NotificationAdaptor(QObject *parent);
+
+public: // PROPERTIES
+public Q_SLOTS: // METHODS
+ uint Notify(const QString &app_name, uint replaces_id, const QString &app_icon, const QString &summary, const QString &body, const QStringList &actions, const QVariantHash &hints, int expire_timeout);
+ void NotificationClosed(uint id, uint reason);
+};
+
+#endif
diff --git a/src/notificationmonitor.cpp b/src/notificationmonitor.cpp
index ca6f713..cdf4d50 100644
--- a/src/notificationmonitor.cpp
+++ b/src/notificationmonitor.cpp
@@ -1,6 +1,59 @@
+#include <QtCore/QDebug>
+#include <QtDBus/QDBusConnection>
+#include <QtDBus/QDBusConnectionInterface>
+
#include "notificationmonitor.h"
+#include "notificationadaptor.h"
+
+static NotificationMonitor *global_monitor = 0;
+
+namespace
+{
+
+void handleEavesdropCallFinished(QDBusPendingCallWatcher *watcher)
+{
+ QDBusPendingReply reply = *watcher;
+ if (reply.isError()) {
+ QDBusError error = reply.error();
+ qWarning() << "Failure to eavesdrop for notifications:" << error.message();
+ } else {
+ qDebug() << "Now eavesdropping notifications";
+ }
+}
+
+}
NotificationMonitor::NotificationMonitor(QObject *parent) :
- QObject(parent)
+ QObject(parent)
+{
+}
+
+NotificationMonitor::~NotificationMonitor()
+{
+}
+
+NotificationMonitor *NotificationMonitor::instance()
{
+ if (!global_monitor) {
+ QDBusConnection bus = QDBusConnection::sessionBus();
+
+ // First register the global monitor object that will listen for notifications...
+ global_monitor = new NotificationMonitor;
+ new NotificationAdaptor(global_monitor);
+ bus.registerObject("/org/freedesktop/Notifications", global_monitor);
+
+ // Now register for eavesdropping
+ QDBusConnectionInterface *dbus = bus.interface();
+ QDBusPendingCall call = dbus->asyncCall("AddMatch",
+ "interface='org.freedesktop.Notifications',member='Notify',type='method_call',eavesdrop='true'");
+
+ QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(call);
+ connect(watcher, &QDBusPendingCallWatcher::finished, &handleEavesdropCallFinished);
+ }
+ return global_monitor;
+}
+
+void NotificationMonitor::handleNotification(const QString &app_name, uint replaces_id, const QString &app_icon, const QString &summary, const QString &body, const QStringList &actions, const QVariantHash &hints, int expire_timeout)
+{
+
}
diff --git a/src/notificationmonitor.h b/src/notificationmonitor.h
index c7b6cb2..de9a0e7 100644
--- a/src/notificationmonitor.h
+++ b/src/notificationmonitor.h
@@ -1,18 +1,33 @@
#ifndef NOTIFICATIONMONITOR_H
#define NOTIFICATIONMONITOR_H
-#include <QObject>
+#include <QtCore/QObject>
+#include <QtCore/QHash>
+
+#include "notification.h"
class NotificationMonitor : public QObject
{
Q_OBJECT
+
public:
- explicit NotificationMonitor(QObject *parent = 0);
+ ~NotificationMonitor();
+
+ static NotificationMonitor *instance();
signals:
+ void newNotification(Notification *notification);
+
+private:
+ explicit NotificationMonitor(QObject *parent = 0);
-public slots:
+private slots:
+ void handleNotification(const QString &app_name, uint replaces_id, const QString &app_icon, const QString &summary, const QString &body, const QStringList &actions, const QVariantHash &hints, int expire_timeout);
+ void handleClosedNotification(uint id);
+ friend class NotificationAdaptor;
+private:
+ QHash<int,
};
#endif // NOTIFICATIONMONITOR_H
diff --git a/src/org.freedesktop.Notifications.xml b/src/org.freedesktop.Notifications.xml
new file mode 100644
index 0000000..89947c9
--- /dev/null
+++ b/src/org.freedesktop.Notifications.xml
@@ -0,0 +1,46 @@
+<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
+<node>
+ <interface name="org.freedesktop.Notifications">
+ <!-- Desktop Notification Specification interface -->
+ <method name="GetCapabilities">
+ <arg name="capabilities" type="as" direction="out"/>
+ </method>
+ <method name="Notify">
+ <arg name="app_name" type="s" direction="in"/>
+ <arg name="replaces_id" type="u" direction="in"/>
+ <arg name="app_icon" type="s" direction="in"/>
+ <arg name="summary" type="s" direction="in"/>
+ <arg name="body" type="s" direction="in"/>
+ <arg name="actions" type="as" direction="in"/>
+ <arg name="hints" type="a{sv}" direction="in"/>
+ <arg name="expire_timeout" type="i" direction="in"/>
+ <arg name="id" type="u" direction="out"/>
+ <annotation name="org.qtproject.QtDBus.QtTypeName.In6" value="QVariantHash"/>
+ </method>
+ <method name="CloseNotification">
+ <arg name="id" type="u" direction="in"/>
+ </method>
+ <method name="GetServerInformation">
+ <arg type="s" direction="out"/>
+ <arg name="name" type="s" direction="out"/>
+ <arg name="vendor" type="s" direction="out"/>
+ <arg name="version" type="s" direction="out"/>
+ </method>
+ <signal name="NotificationClosed">
+ <arg name="id" type="u"/>
+ <arg name="reason" type="u"/>
+ </signal>
+ <signal name="ActionInvoked">
+ <arg name="id" type="u"/>
+ <arg name="action_key" type="s"/>
+ </signal>
+
+ <!-- Nemo extensions -->
+ <method name="GetNotifications">
+ <arg name="app_name" type="s" direction="in"/>
+ <arg name="notifications" type="a(sussasa{sv}i)" direction="out"/>
+ <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="QList &lt; Notification &gt; "/>
+ </method>
+ </interface>
+</node>
+
diff --git a/src/widgetinfo.cpp b/src/widgetinfo.cpp
index d23da8f..f7b766c 100644
--- a/src/widgetinfo.cpp
+++ b/src/widgetinfo.cpp
@@ -1,3 +1,5 @@
+#include <QtCore/QRegularExpression>
+
#include "widgetinfo.h"
struct WidgetInfoData : public QSharedData
@@ -48,6 +50,22 @@ void WidgetInfo::setUrl(const QUrl &url)
d->url = url;
}
+int WidgetInfo::builtinClockfaceId() const
+{
+ QString file = d->url.toLocalFile();
+ if (file.isEmpty()) return -1;
+
+
+ // I'm definitely evil:
+ static const QRegularExpression re("qml/watch/faces/builtinface([0-9]+).qml$");
+ QRegularExpressionMatch match = re.match(file);
+ if (match.hasMatch()) {
+ return match.captured(1).toInt();
+ } else {
+ return -1;
+ }
+}
+
QString WidgetInfo::description() const
{
return d->desc;
diff --git a/src/widgetinfo.h b/src/widgetinfo.h
index 51d617b..b5f46fe 100644
--- a/src/widgetinfo.h
+++ b/src/widgetinfo.h
@@ -37,6 +37,8 @@ public:
bool valid() const;
+ int builtinClockfaceId() const;
+
QUrl url() const;
void setUrl(const QUrl &url);
diff --git a/src/widgetinfomodel.cpp b/src/widgetinfomodel.cpp
index 6c4d5d2..e2f145f 100644
--- a/src/widgetinfomodel.cpp
+++ b/src/widgetinfomodel.cpp
@@ -64,6 +64,11 @@ QVariant WidgetInfoModel::data(const QModelIndex &index, int role) const
}
}
+QList<WidgetInfo> WidgetInfoModel::toList() const
+{
+ return _widgets.toList();
+}
+
void WidgetInfoModel::reload()
{
beginResetModel();
@@ -165,7 +170,6 @@ void WidgetInfoModel::handleSettingChanged(const QString &key)
}
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
index 6b30a91..4b2a700 100644
--- a/src/widgetinfomodel.h
+++ b/src/widgetinfomodel.h
@@ -25,6 +25,8 @@ public:
int rowCount(const QModelIndex &parent) const;
QVariant data(const QModelIndex &index, int role) const;
+ QList<WidgetInfo> toList() const;
+
signals:
public slots:
diff --git a/translations/salmeta.ts b/translations/salmeta.ts
index 79cf7af..786af13 100644
--- a/translations/salmeta.ts
+++ b/translations/salmeta.ts
@@ -19,5 +19,21 @@
<source>Notifications</source>
<translation type="unfinished"></translation>
</message>
+ <message>
+ <source>Time format</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Date format</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Show separator lines</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Auto-backlight</source>
+ <translation type="unfinished"></translation>
+ </message>
</context>
</TS>