diff options
-rw-r--r-- | qml/pages/MainPage.qml | 2 | ||||
-rw-r--r-- | qml/watch/MetaWatch-Large-16pt-Sync.ttf | bin | 0 -> 25420 bytes | |||
-rw-r--r-- | qml/watch/metawatch_16pt_11pxl.ttf | bin | 0 -> 10624 bytes | |||
-rw-r--r-- | qml/watch/metawatch_8pt_5pxl_CAPS.ttf | bin | 0 -> 10964 bytes | |||
-rw-r--r-- | qml/watch/metawatch_8pt_5pxl_Numerals.ttf | bin | 0 -> 2464 bytes | |||
-rw-r--r-- | qml/watch/metawatch_8pt_6pxl_Numerals.ttf | bin | 0 -> 2216 bytes | |||
-rw-r--r-- | qml/watch/metawatch_8pt_7pxl_CAPS.ttf | bin | 0 -> 12016 bytes | |||
-rw-r--r-- | qml/watch/notification.png | bin | 0 -> 460 bytes | |||
-rw-r--r-- | salmeta.pro | 12 | ||||
-rw-r--r-- | src/controller.cpp | 21 | ||||
-rw-r--r-- | src/controller.h | 1 | ||||
-rw-r--r-- | src/metawatch.cpp | 52 | ||||
-rw-r--r-- | src/metawatch.h | 17 | ||||
-rw-r--r-- | src/notification.cpp | 6 | ||||
-rw-r--r-- | src/notification.h | 17 | ||||
-rw-r--r-- | src/notificationmonitor.cpp | 23 | ||||
-rw-r--r-- | src/notificationmonitor.h | 9 | ||||
-rw-r--r-- | src/org.freedesktop.Notifications.xml | 17 | ||||
-rw-r--r-- | src/salmeta.cpp | 8 |
19 files changed, 130 insertions, 55 deletions
diff --git a/qml/pages/MainPage.qml b/qml/pages/MainPage.qml index 6b2893a..b25ff06 100644 --- a/qml/pages/MainPage.qml +++ b/qml/pages/MainPage.qml @@ -56,7 +56,7 @@ Page { onClicked: { var dialog = pageStack.push("Sailfish.Bluetooth.BluetoothDevicePickerDialog"); - dialog.selectedDeviceChanged.connect(function() { + dialog.onAccepted.connect(function() { if (dialog.selectedDevice !== "") { deviceAddress.value = dialog.selectedDevice } diff --git a/qml/watch/MetaWatch-Large-16pt-Sync.ttf b/qml/watch/MetaWatch-Large-16pt-Sync.ttf Binary files differnew file mode 100644 index 0000000..0962a74 --- /dev/null +++ b/qml/watch/MetaWatch-Large-16pt-Sync.ttf diff --git a/qml/watch/metawatch_16pt_11pxl.ttf b/qml/watch/metawatch_16pt_11pxl.ttf Binary files differnew file mode 100644 index 0000000..8baae0c --- /dev/null +++ b/qml/watch/metawatch_16pt_11pxl.ttf diff --git a/qml/watch/metawatch_8pt_5pxl_CAPS.ttf b/qml/watch/metawatch_8pt_5pxl_CAPS.ttf Binary files differnew file mode 100644 index 0000000..7c03800 --- /dev/null +++ b/qml/watch/metawatch_8pt_5pxl_CAPS.ttf diff --git a/qml/watch/metawatch_8pt_5pxl_Numerals.ttf b/qml/watch/metawatch_8pt_5pxl_Numerals.ttf Binary files differnew file mode 100644 index 0000000..9631d8f --- /dev/null +++ b/qml/watch/metawatch_8pt_5pxl_Numerals.ttf diff --git a/qml/watch/metawatch_8pt_6pxl_Numerals.ttf b/qml/watch/metawatch_8pt_6pxl_Numerals.ttf Binary files differnew file mode 100644 index 0000000..ff5b6b1 --- /dev/null +++ b/qml/watch/metawatch_8pt_6pxl_Numerals.ttf diff --git a/qml/watch/metawatch_8pt_7pxl_CAPS.ttf b/qml/watch/metawatch_8pt_7pxl_CAPS.ttf Binary files differnew file mode 100644 index 0000000..408b5b7 --- /dev/null +++ b/qml/watch/metawatch_8pt_7pxl_CAPS.ttf diff --git a/qml/watch/notification.png b/qml/watch/notification.png Binary files differnew file mode 100644 index 0000000..5ce156f --- /dev/null +++ b/qml/watch/notification.png diff --git a/salmeta.pro b/salmeta.pro index ee13291..2a6014a 100644 --- a/salmeta.pro +++ b/salmeta.pro @@ -18,8 +18,7 @@ SOURCES += src/salmeta.cpp \ src/notificationmonitor.cpp \ src/widgetinfo.cpp \ src/widgetinfomodel.cpp \ - src/availablewidgetsmodel.cpp \ - src/notification.cpp + src/availablewidgetsmodel.cpp HEADERS += \ src/controller.h \ @@ -30,8 +29,7 @@ HEADERS += \ src/notificationmonitor.h \ src/widgetinfo.h \ src/widgetinfomodel.h \ - src/availablewidgetsmodel.h \ - src/notification.h + src/availablewidgetsmodel.h OTHER_FILES += qml/salmeta.qml \ qml/cover/CoverPage.qml \ @@ -47,7 +45,11 @@ OTHER_FILES += qml/salmeta.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/pages/AddWidget.qml + qml/pages/AddWidget.qml \ + qml/watch/notification.png + +CONFIG += dbus +DBUS_ADAPTORS += src/org.freedesktop.Notifications.xml # to disable building translations every time, comment out the # following CONFIG line diff --git a/src/controller.cpp b/src/controller.cpp index f4a2b09..bd2b68b 100644 --- a/src/controller.cpp +++ b/src/controller.cpp @@ -1,5 +1,8 @@ #include <QtCore/QDebug> #include <QtCore/QDateTime> +#include <QtGui/QPainter> + +#include <sailfishapp.h> #include "controller.h" @@ -25,6 +28,7 @@ Controller::Controller(const QString &settingsPrefix, QQuickView *view, QObject _curPage = _settings->value(setting_cur_page).toInt(); connect(_settings, &MDConfGroup::valueChanged, this, &Controller::handleSettingChanged); + connect(_monitor, &NotificationMonitor::incomingNotification, this, &Controller::handleIncomingNotification); connect(_widgets, &QAbstractItemModel::dataChanged, this, &Controller::handleWidgetChanged); connectToAddress(_settings->value(setting_address).toString()); @@ -189,6 +193,23 @@ void Controller::handleMetaWatchBatteryStatus(bool charging, int charge) } } +void Controller::handleIncomingNotification(const QString &sender, const QIcon &icon, const QString &summary, const QString &body) +{ + QImage image(96, 96, QImage::Format_MonoLSB); + QPainter p(&image); + + p.drawImage(0, 0, QImage(SailfishApp::pathTo("qml/watch/notification.png").toLocalFile())); + icon.paint(&p, 0, 96 - 24, 24, 24, Qt::AlignLeft | Qt::AlignBottom); + + p.drawText(QRect(2, 26, 92, 55), Qt::AlignLeft | Qt::AlignTop, body); + + image.invertPixels(); + + _metawatch->sendModeImage(MetaWatch::WatchModeNotification, image); + _metawatch->updateLcdDisplayMode(MetaWatch::WatchModeNotification); + _metawatch->setVibrateMode(true, 500, 500, 2); +} + void Controller::handleWidgetChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles) { if (roles.indexOf(WidgetInfoModel::UrlRole) >= 0) { diff --git a/src/controller.h b/src/controller.h index f4d4513..a375247 100644 --- a/src/controller.h +++ b/src/controller.h @@ -46,6 +46,7 @@ private slots: void handleMetaWatchConnected(); void handleMetaWatchModeChange(MetaWatch::WatchMode mode, int page); void handleMetaWatchBatteryStatus(bool charging, int charge); + void handleIncomingNotification(const QString &sender, const QIcon &icon, const QString &summary, const QString &body); void handleWidgetChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles); private: diff --git a/src/metawatch.cpp b/src/metawatch.cpp index b6042af..9b0bae2 100644 --- a/src/metawatch.cpp +++ b/src/metawatch.cpp @@ -1,6 +1,8 @@ #include <QtCore/QDataStream> #include <QtCore/QDateTime> #include <QtCore/QDebug> +#include <QtCore/QThread> +#include <QtGui/QImage> #include "metawatch.h" #include "metawatchbletransport.h" @@ -16,15 +18,16 @@ MetaWatch::MetaWatch(const QString &btAddr, QObject *parent) : connect(_transport, &MetaWatchTransport::messageReceived, this, &MetaWatch::handleTransportMessage); } -QList<QUrl> MetaWatch::availableClocks() +void MetaWatch::setVibrateMode(bool enable, int on_duration, int off_duration, int cycles) { - QList<QUrl> clocks; + QByteArray data; + QDataStream s(&data, QIODevice::WriteOnly); + s.setByteOrder(QDataStream::LittleEndian); - for (int i = 0; i < 6; i++) { - clocks << QUrl("clock://" + QString::number(i)); - } + s << quint8(enable ? 1 : 0); + s << quint16(on_duration) << quint16(off_duration) << quint8(cycles); - return clocks; + _transport->sendMessage(MessageSetVibrateMode, 0, data); } void MetaWatch::setDateTime(const QDateTime &dt) @@ -34,6 +37,7 @@ void MetaWatch::setDateTime(const QDateTime &dt) QByteArray data; QDataStream s(&data, QIODevice::WriteOnly); s.setByteOrder(QDataStream::BigEndian); + s << quint16(date.year()) << quint8(date.month()) << quint8(date.day()); s << quint8(date.dayOfWeek() % 7); s << quint8(time.hour()) << quint8(time.minute()) << quint8(time.second()); @@ -71,6 +75,14 @@ void MetaWatch::updateLcdDisplayPage(int page) QByteArray()); } +void MetaWatch::updateLcdDisplayMode(WatchMode mode) +{ + Q_ASSERT(mode != WatchModeIdle); // TODO + _transport->sendMessage(MessageUpdateLcdDisplay, + (mode & 0x3), + QByteArray()); +} + void MetaWatch::updateWidgetList(const QList<WidgetInfo> &widgets) { int num_widgets = 0; @@ -143,6 +155,22 @@ void MetaWatch::updateWidgetList(const QList<WidgetInfo> &widgets) } } +void MetaWatch::sendModeImage(WatchMode mode, const QImage &image) +{ + Q_ASSERT(image.width() == 96 && image.height() == 96); + Q_ASSERT(image.bytesPerLine() == 12); + QByteArray data(1 + image.bytesPerLine(), '\0');//Qt::Uninitialized); + + for (int i = 0; i < image.height(); i++) { + data[0] = i; + memcpy(data.data() + 1, image.scanLine(i), image.bytesPerLine()); + + _transport->sendMessage(MessageWriteLcdBuffer, + 0x10 | (mode & 0x3), + data); + } +} + void MetaWatch::connectDevice() { _transport->connectDevice(); @@ -153,18 +181,6 @@ void MetaWatch::disconnectDevice() _transport->disconnectDevice(); } -int MetaWatch::clockUrlToClockId(const QUrl &url) -{ - if (url.scheme() != "clock") - return -1; - - QString host = url.host(); - if (!host.startsWith("clock")) - return -1; - - return host.mid(5).toInt(); -} - void MetaWatch::handleTransportMessage(quint8 type, quint8 options, const QByteArray &payload) { switch (type) { diff --git a/src/metawatch.h b/src/metawatch.h index 6b50ead..a83ad0c 100644 --- a/src/metawatch.h +++ b/src/metawatch.h @@ -22,6 +22,8 @@ public: MessageGetDeviceType = 0x01, MessageGetDeviceTypeResponse = 0x02, + MessageSetVibrateMode = 0x23, + MessageSetRealTimeClock = 0x26, MessageWatchPropertyOperation = 0x30, @@ -29,6 +31,8 @@ public: MessageModeChangeIndication = 0x33, + MessageWriteLcdBuffer = 0x40, + MessageUpdateLcdDisplay = 0x43, MessageGetBatteryStatus = 0x56, @@ -50,7 +54,8 @@ public: }; enum WatchMode { - WatchModeIdle = 0 + WatchModeIdle = 0, + WatchModeNotification = 2 }; enum WatchProperty { @@ -72,8 +77,7 @@ public: UiGen2 = 1 }; - static QList<QUrl> availableClocks(); - + void setVibrateMode(bool enable, int on_duration, int off_duration, int cycles); void setDateTime(const QDateTime &dt); void configure(WatchProperties props); @@ -83,8 +87,12 @@ public: void updateLcdDisplay(); /** Goes to idle mode and a specific page */ void updateLcdDisplayPage(int page); + /** Goes to a specific mode. */ + void updateLcdDisplayMode(WatchMode mode); void updateWidgetList(const QList<WidgetInfo>& widgets); + void sendModeImage(WatchMode mode, const QImage &image); + signals: void connected(); void disconnected(); @@ -97,9 +105,6 @@ public slots: void connectDevice(); void disconnectDevice(); -private: - static int clockUrlToClockId(const QUrl &url); - private slots: void handleTransportMessage(quint8 type, quint8 options, const QByteArray &payload); diff --git a/src/notification.cpp b/src/notification.cpp deleted file mode 100644 index 00d66ad..0000000 --- a/src/notification.cpp +++ /dev/null @@ -1,6 +0,0 @@ -#include "notification.h" - -Notification::Notification(QObject *parent) : - QObject(parent) -{ -} diff --git a/src/notification.h b/src/notification.h deleted file mode 100644 index 899a9aa..0000000 --- a/src/notification.h +++ /dev/null @@ -1,17 +0,0 @@ -#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/notificationmonitor.cpp b/src/notificationmonitor.cpp index 50b2e3e..c937b02 100644 --- a/src/notificationmonitor.cpp +++ b/src/notificationmonitor.cpp @@ -1,7 +1,9 @@ #include <QtCore/QDebug> +#include <QtGui/QIcon> #include <QtDBus/QDBusConnection> #include <QtDBus/QDBusConnectionInterface> #include "notificationmonitor.h" +#include "notifications_adaptor.h" static NotificationMonitor *global_monitor = 0; @@ -12,6 +14,8 @@ NotificationMonitor::NotificationMonitor(QObject *parent) : QDBusConnectionInterface *dbus = bus.interface(); dbus->call("AddMatch", "interface='org.freedesktop.Notifications',member='Notify',type='method_call',eavesdrop='true'"); + new NotificationsAdaptor(this); + bus.registerObject("/org/freedesktop/Notifications", this); } NotificationMonitor::~NotificationMonitor() @@ -29,3 +33,22 @@ NotificationMonitor *NotificationMonitor::instance() } return global_monitor; } + +void NotificationMonitor::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) +{ + qDebug() << "Got notification" << app_name << app_icon << summary << body; + QIcon icon; + + if (app_icon.startsWith("/")) { + icon = QIcon(app_icon); + } else if (app_icon.startsWith("file:")) { + QUrl url(app_icon); + icon = QIcon(url.toLocalFile()); + } else { + icon = QIcon::fromTheme(app_icon); + } + + qDebug() << "Icon:" << icon.availableSizes(); + + emit incomingNotification(app_name, icon, summary, body); +} diff --git a/src/notificationmonitor.h b/src/notificationmonitor.h index e8b6501..cfa0e17 100644 --- a/src/notificationmonitor.h +++ b/src/notificationmonitor.h @@ -3,8 +3,6 @@ #include <QtCore/QObject> -#include "notification.h" - class NotificationMonitor : public QObject { Q_OBJECT @@ -14,8 +12,15 @@ public: static NotificationMonitor *instance(); +signals: + void incomingNotification(const QString &sender, const QIcon &icon, const QString &summary, const QString &body); + private: explicit NotificationMonitor(QObject *parent = 0); + +private slots: + friend class NotificationsAdaptor; + void 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); }; #endif // NOTIFICATIONMONITOR_H diff --git a/src/org.freedesktop.Notifications.xml b/src/org.freedesktop.Notifications.xml new file mode 100644 index 0000000..456fd42 --- /dev/null +++ b/src/org.freedesktop.Notifications.xml @@ -0,0 +1,17 @@ +<!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"> + <!-- (Partial) Desktop Notification Specification interface --> + <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"/> + <!-- Not needed for eavesdropping: <arg name="id" type="u" direction="out"/> --> + <annotation name="org.qtproject.QtDBus.QtTypeName.In6" value="QVariantHash"/> + </method> +</node> diff --git a/src/salmeta.cpp b/src/salmeta.cpp index 46e4e89..914f117 100644 --- a/src/salmeta.cpp +++ b/src/salmeta.cpp @@ -1,4 +1,5 @@ #include <QtCore/QDebug> +#include <QtGui/QFontDatabase> #include <sailfishapp.h> #include "controller.h" @@ -29,6 +30,13 @@ int main(int argc, char *argv[]) qmlRegisterUncreatableType<WidgetInfo>("com.javispedro.salmeta", 1, 0, "WidgetInfo", "Use the models, not this"); + QFontDatabase::addApplicationFont(SailfishApp::pathTo("qml/watch/metawatch_8pt_5pxl_CAPS.ttf").toLocalFile()); + QFontDatabase::addApplicationFont(SailfishApp::pathTo("qml/watch/metawatch_8pt_5pxl_Numerals.ttf").toLocalFile()); + QFontDatabase::addApplicationFont(SailfishApp::pathTo("qml/watch/metawatch_8pt_6pxl_Numerals.ttf").toLocalFile()); + QFontDatabase::addApplicationFont(SailfishApp::pathTo("qml/watch/metawatch_8pt_7pxl_CAPS.ttf").toLocalFile()); + QFontDatabase::addApplicationFont(SailfishApp::pathTo("qml/watch/metawatch_16pt_11pxl.ttf").toLocalFile()); + QFontDatabase::addApplicationFont(SailfishApp::pathTo("qml/watch/MetaWatch-Large-16pt-Sync.ttf").toLocalFile()); + if (launch_daemon) { qDebug() << "Starting salmeta (daemon) with settings from" << settings_key_prefix; |