summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
Diffstat (limited to 'app')
-rw-r--r--app/app.pro17
-rw-r--r--app/pebble.cpp12
-rw-r--r--app/pebbleappiconprovider.cpp28
-rw-r--r--app/pebbleappiconprovider.h18
-rw-r--r--app/pebbledinterface.cpp269
-rw-r--r--app/pebbledinterface.h69
-rw-r--r--app/qml/pages/AboutPage.qml2
-rw-r--r--app/qml/pages/AppConfigDialog.qml87
-rw-r--r--app/qml/pages/InstallAppDialog.qml75
-rw-r--r--app/qml/pages/WatchPage.qml157
-rw-r--r--app/qml/pages/WebItemSelDialog.qml45
-rw-r--r--app/qml/pebble.qml4
-rw-r--r--app/translations/pebble-es.ts254
-rw-r--r--app/translations/pebble.ts253
14 files changed, 1195 insertions, 95 deletions
diff --git a/app/app.pro b/app/app.pro
index cb4c33b..97c6232 100644
--- a/app/app.pro
+++ b/app/app.pro
@@ -3,23 +3,34 @@ TARGET = pebble
CONFIG += sailfishapp
QT += dbus
-QMAKE_CXXFLAGS += -std=c++0x
+CONFIG += c++11
DEFINES += APP_VERSION=\\\"$$VERSION\\\"
SOURCES += \
pebble.cpp \
- pebbledinterface.cpp
+ pebbledinterface.cpp \
+ pebbleappiconprovider.cpp
HEADERS += \
- pebbledinterface.h
+ pebbledinterface.h \
+ pebbleappiconprovider.h
+
+DBUS_INTERFACES += ../org.pebbled.Watch.xml
OTHER_FILES += \
qml/cover/CoverPage.qml \
qml/pages/ManagerPage.qml \
qml/pages/WatchPage.qml \
qml/pages/AboutPage.qml \
+ qml/pages/InstallAppDialog.qml \
+ qml/pages/AppConfigDialog.qml \
+ qml/pages/WebItemSelDialog.qml \
qml/pebble.qml \
qml/images/* \
+ translations/*.ts \
pebble.desktop \
pebble.png
+
+CONFIG += sailfishapp_i18n
+TRANSLATIONS += translations/pebble-es.ts
diff --git a/app/pebble.cpp b/app/pebble.cpp
index 44f1aeb..41da080 100644
--- a/app/pebble.cpp
+++ b/app/pebble.cpp
@@ -33,16 +33,22 @@
#include <sailfishapp.h>
#include "pebbledinterface.h"
+#include "pebbleappiconprovider.h"
int main(int argc, char *argv[])
{
- // Register Pebble daemon interface object on QML side
- qmlRegisterType<PebbledInterface>("org.pebbled", 0, 1, "PebbledInterface");
-
QScopedPointer<QGuiApplication> app(SailfishApp::application(argc, argv));
+ qmlRegisterUncreatableType<PebbledInterface>("org.pebbled", 0, 1, "PebbledInterface",
+ "Please use pebbled context property");
+
QScopedPointer<QQuickView> view(SailfishApp::createView());
+ QScopedPointer<PebbledInterface> pebbled(new PebbledInterface);
+ QScopedPointer<PebbleAppIconProvider> appicons(new PebbleAppIconProvider(pebbled.data()));
+
view->rootContext()->setContextProperty("APP_VERSION", APP_VERSION);
+ view->rootContext()->setContextProperty("pebbled", pebbled.data());
+ view->engine()->addImageProvider("pebble-app-icon", appicons.data());
view->setSource(SailfishApp::pathTo("qml/pebble.qml"));
view->show();
diff --git a/app/pebbleappiconprovider.cpp b/app/pebbleappiconprovider.cpp
new file mode 100644
index 0000000..0e694ff
--- /dev/null
+++ b/app/pebbleappiconprovider.cpp
@@ -0,0 +1,28 @@
+#include <QDebug>
+#include <QUrl>
+#include "pebbleappiconprovider.h"
+
+PebbleAppIconProvider::PebbleAppIconProvider(PebbledInterface *interface)
+ : QQuickImageProvider(QQmlImageProviderBase::Image), pebbled(interface)
+{
+}
+
+QImage PebbleAppIconProvider::requestImage(const QString &id, QSize *size, const QSize &requestedSize)
+{
+ QUuid uuid(QUrl::fromPercentEncoding(id.toLatin1()));
+ QImage img = pebbled->menuIconForApp(uuid);
+
+ if (requestedSize.width() > 0 && requestedSize.height() > 0) {
+ img = img.scaled(requestedSize, Qt::KeepAspectRatio);
+ } else if (requestedSize.width() > 0) {
+ img = img.scaledToWidth(requestedSize.width());
+ } else if (requestedSize.height() > 0) {
+ img = img.scaledToHeight(requestedSize.height());
+ }
+
+ if (size) {
+ *size = img.size();
+ }
+
+ return img;
+}
diff --git a/app/pebbleappiconprovider.h b/app/pebbleappiconprovider.h
new file mode 100644
index 0000000..c76641a
--- /dev/null
+++ b/app/pebbleappiconprovider.h
@@ -0,0 +1,18 @@
+#ifndef PEBBLEAPPICONPROVIDER_H
+#define PEBBLEAPPICONPROVIDER_H
+
+#include <QQuickImageProvider>
+#include "pebbledinterface.h"
+
+class PebbleAppIconProvider : public QQuickImageProvider
+{
+public:
+ explicit PebbleAppIconProvider(PebbledInterface *interface);
+
+ QImage requestImage(const QString &id, QSize *size, const QSize &requestedSize);
+
+private:
+ PebbledInterface *pebbled;
+};
+
+#endif // PEBBLEAPPICONPROVIDER_H
diff --git a/app/pebbledinterface.cpp b/app/pebbledinterface.cpp
index 05ca614..c978dd0 100644
--- a/app/pebbledinterface.cpp
+++ b/app/pebbledinterface.cpp
@@ -1,33 +1,42 @@
#include "pebbledinterface.h"
+#include "watch_interface.h"
-QString PebbledInterface::PEBBLED_SYSTEMD_UNIT("pebbled.service");
-QString PebbledInterface::PEBBLED_DBUS_SERVICE("org.pebbled");
-QString PebbledInterface::PEBBLED_DBUS_PATH("/");
-QString PebbledInterface::PEBBLED_DBUS_IFACE("org.pebbled");
-
-#define PebbledDbusInterface QDBusInterface(PEBBLED_DBUS_SERVICE, PEBBLED_DBUS_PATH, PEBBLED_DBUS_IFACE)
-
+static const QString PEBBLED_SYSTEMD_UNIT("pebbled.service");
+static const QString PEBBLED_DBUS_SERVICE("org.pebbled");
+static const QString PEBBLED_DBUS_PATH("/org/pebbled/Watch");
+static const QString PEBBLED_DBUS_IFACE("org.pebbled.Watch");
PebbledInterface::PebbledInterface(QObject *parent) :
- QObject(parent), systemd(0)
+ QObject(parent),
+ systemd(new QDBusInterface("org.freedesktop.systemd1",
+ "/org/freedesktop/systemd1",
+ "org.freedesktop.systemd1.Manager",
+ QDBusConnection::sessionBus(), this)),
+ watch(new OrgPebbledWatchInterface(PEBBLED_DBUS_SERVICE,
+ PEBBLED_DBUS_PATH,
+ QDBusConnection::sessionBus(), this))
{
- QDBusConnection::sessionBus().connect(
- PEBBLED_DBUS_SERVICE, PEBBLED_DBUS_PATH, PEBBLED_DBUS_IFACE,
- "connectedChanged", this, SIGNAL(connectedChanged()));
+ connect(watch, &OrgPebbledWatchInterface::NameChanged,
+ this, &PebbledInterface::nameChanged);
+ connect(watch, &OrgPebbledWatchInterface::AddressChanged,
+ this, &PebbledInterface::addressChanged);
+ connect(watch, &OrgPebbledWatchInterface::ConnectedChanged,
+ this, &PebbledInterface::connectedChanged);
+ connect(watch, &OrgPebbledWatchInterface::AppUuidChanged,
+ this, &PebbledInterface::appUuidChanged);
+ connect(watch, &OrgPebbledWatchInterface::AppSlotsChanged,
+ this, &PebbledInterface::refreshAppSlots);
+ connect(watch, &OrgPebbledWatchInterface::AllAppsChanged,
+ this, &PebbledInterface::refreshAllApps);
- QDBusConnection::sessionBus().connect(
- PEBBLED_DBUS_SERVICE, PEBBLED_DBUS_PATH, PEBBLED_DBUS_IFACE,
- "pebbleChanged", this, SLOT(onPebbleChanged()));
+ connect(watch, &OrgPebbledWatchInterface::ConnectedChanged,
+ this, &PebbledInterface::onWatchConnectedChanged);
// simulate connected change on active changed
// as the daemon might not had a chance to send 'connectedChanged'
// when going down
- connect(this, SIGNAL(activeChanged()), SIGNAL(connectedChanged()));
-
- systemd = new QDBusInterface("org.freedesktop.systemd1",
- "/org/freedesktop/systemd1",
- "org.freedesktop.systemd1.Manager",
- QDBusConnection::sessionBus(), this);
+ connect(this, &PebbledInterface::activeChanged,
+ this, &PebbledInterface::connectedChanged);
systemd->call("Subscribe");
@@ -44,6 +53,11 @@ PebbledInterface::PebbledInterface(QObject *parent) :
} else {
qWarning() << unit.error().message();
}
+
+ if (watch->isValid()) {
+ refreshAllApps();
+ refreshAppSlots();
+ }
}
void PebbledInterface::getUnitProperties()
@@ -55,9 +69,9 @@ void PebbledInterface::getUnitProperties()
QDBusReply<QVariantMap> reply = QDBusConnection::sessionBus().call(request);
if (reply.isValid()) {
QVariantMap newProperties = reply.value();
- bool emitEnabledChanged = (properties["UnitFileState"] != newProperties["UnitFileState"]);
- bool emitActiveChanged = (properties["ActiveState"] != newProperties["ActiveState"]);
- properties = newProperties;
+ bool emitEnabledChanged = (unitProperties["UnitFileState"] != newProperties["UnitFileState"]);
+ bool emitActiveChanged = (unitProperties["ActiveState"] != newProperties["ActiveState"]);
+ unitProperties = newProperties;
if (emitEnabledChanged) emit enabledChanged();
if (emitActiveChanged) emit activeChanged();
} else {
@@ -67,24 +81,16 @@ void PebbledInterface::getUnitProperties()
void PebbledInterface::onPropertiesChanged(QString interface, QMap<QString,QVariant> changed, QStringList invalidated)
{
- qDebug() << __FUNCTION__ << interface << changed << invalidated;
+ qDebug() << Q_FUNC_INFO << interface << changed << invalidated;
if (interface != "org.freedesktop.systemd1.Unit") return;
- if (invalidated.contains("UnitFileState") or invalidated.contains("ActiveState"))
+ if (invalidated.contains("UnitFileState") || invalidated.contains("ActiveState"))
getUnitProperties();
}
-void PebbledInterface::onPebbleChanged()
-{
- qDebug() << __FUNCTION__;
- emit nameChanged();
- emit addressChanged();
- emit pebbleChanged();
-}
-
bool PebbledInterface::enabled() const
{
- qDebug() << __FUNCTION__;
- return properties["UnitFileState"].toString() == "enabled";
+ qDebug() << Q_FUNC_INFO;
+ return unitProperties["UnitFileState"].toString() == "enabled";
}
void PebbledInterface::setEnabled(bool enabled)
@@ -103,8 +109,8 @@ void PebbledInterface::setEnabled(bool enabled)
bool PebbledInterface::active() const
{
- qDebug() << __FUNCTION__;
- return properties["ActiveState"].toString() == "active";
+ qDebug() << Q_FUNC_INFO;
+ return unitProperties["ActiveState"].toString() == "active";
}
void PebbledInterface::setActive(bool active)
@@ -118,48 +124,199 @@ void PebbledInterface::setActive(bool active)
bool PebbledInterface::connected() const
{
- qDebug() << __FUNCTION__;
- return PebbledDbusInterface.property(__FUNCTION__).toBool();
+ qDebug() << Q_FUNC_INFO;
+ return watch->connected();
}
-QVariantMap PebbledInterface::pebble() const
+QString PebbledInterface::name() const
{
- qDebug() << __FUNCTION__;
- return PebbledDbusInterface.property(__FUNCTION__).toMap();
+ qDebug() << Q_FUNC_INFO;
+ return watch->name();
}
-QString PebbledInterface::name() const
+QString PebbledInterface::address() const
{
- qDebug() << __FUNCTION__;
- return PebbledDbusInterface.property(__FUNCTION__).toString();
+ qDebug() << Q_FUNC_INFO;
+ return watch->address();
}
-QString PebbledInterface::address() const
+QString PebbledInterface::appUuid() const
{
- qDebug() << __FUNCTION__;
- return PebbledDbusInterface.property(__FUNCTION__).toString();
+ qDebug() << Q_FUNC_INFO;
+ return watch->appUuid();
}
void PebbledInterface::ping()
{
- qDebug() << __FUNCTION__;
- PebbledDbusInterface.call("ping", 66);
+ qDebug() << Q_FUNC_INFO;
+ watch->Ping(66);
}
void PebbledInterface::time()
{
- qDebug() << __FUNCTION__;
- PebbledDbusInterface.call("time");
+ qDebug() << Q_FUNC_INFO;
+ watch->SyncTime();
}
void PebbledInterface::disconnect()
{
- qDebug() << __FUNCTION__;
- PebbledDbusInterface.call("disconnect");
+ qDebug() << Q_FUNC_INFO;
+ watch->Disconnect();
}
void PebbledInterface::reconnect()
{
- qDebug() << __FUNCTION__;
- PebbledDbusInterface.call("reconnect");
+ qDebug() << Q_FUNC_INFO;
+ watch->Reconnect();
+}
+
+QUrl PebbledInterface::configureApp(const QString &uuid)
+{
+ qDebug() << Q_FUNC_INFO << uuid;
+ QDBusPendingReply<QString> reply = watch->StartAppConfiguration(uuid);
+ reply.waitForFinished();
+ if (reply.isError()) {
+ qWarning() << "Received error:" << reply.error().message();
+ return QUrl();
+ } else {
+ return QUrl(reply.value());
+ }
+}
+
+bool PebbledInterface::isAppInstalled(const QString &uuid) const
+{
+ QUuid u(uuid);
+
+ foreach (const QString &s, _appSlots) {
+ if (QUuid(s) == u) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+QImage PebbledInterface::menuIconForApp(const QUuid &uuid) const
+{
+ return _appMenuIcons.value(uuid);
+}
+
+void PebbledInterface::setAppConfiguration(const QString &uuid, const QString &data)
+{
+ qDebug() << Q_FUNC_INFO << uuid << data;
+ watch->SendAppConfigurationData(uuid, data);
+}
+
+void PebbledInterface::launchApp(const QString &uuid)
+{
+ qDebug() << Q_FUNC_INFO << uuid;
+ QDBusPendingReply<> reply = watch->LaunchApp(uuid);
+ reply.waitForFinished();
+
+ // TODO Terrible hack; need to give time for the watch to open the app
+ // A better solution would be to wait until AppUuidChanged is generated.
+ QUuid u(uuid);
+ if (u.isNull()) return;
+ int sleep_count = 0;
+ while (QUuid(watch->appUuid()) != u && sleep_count < 5) {
+ qDebug() << "Waiting for" << u.toString() << "to launch";
+ QThread::sleep(1);
+ sleep_count++;
+ }
+}
+
+void PebbledInterface::uploadApp(const QString &uuid, int slot)
+{
+ qDebug() << Q_FUNC_INFO << uuid << slot;
+ QDBusPendingReply<> reply = watch->UploadApp(uuid, slot);
+ reply.waitForFinished();
+}
+
+void PebbledInterface::unloadApp(int slot)
+{
+ qDebug() << Q_FUNC_INFO << slot;
+ QDBusPendingReply<> reply = watch->UnloadApp(slot);
+ reply.waitForFinished();
+}
+
+QStringList PebbledInterface::appSlots() const
+{
+ return _appSlots;
+}
+
+QVariantList PebbledInterface::allApps() const
+{
+ return _apps;
+}
+
+QVariantMap PebbledInterface::appInfoByUuid(const QString &uuid) const
+{
+ int index = _appsByUuid.value(QUuid(uuid), -1);
+ if (index >= 0) {
+ return _apps[index].toMap();
+ } else {
+ return QVariantMap();
+ }
+}
+
+void PebbledInterface::onWatchConnectedChanged()
+{
+ qDebug() << Q_FUNC_INFO;
+ if (watch->connected()) {
+ refreshAllApps();
+ refreshAppSlots();
+ }
+}
+
+void PebbledInterface::refreshAppSlots()
+{
+ qDebug() << "refreshing app slots list";
+ _appSlots = watch->appSlots();
+ emit appSlotsChanged();
+}
+
+void PebbledInterface::refreshAllApps()
+{
+ _apps.clear();
+ _appsByUuid.clear();
+ _appMenuIcons.clear();
+
+ qDebug() << "refreshing all apps list";
+
+ const QVariantList l = watch->allApps();
+ foreach (const QVariant &v, l) {
+ QVariantMap orig = qdbus_cast<QVariantMap>(v.value<QDBusArgument>());
+ QUuid uuid = orig.value("uuid").toUuid();
+ if (uuid.isNull()) {
+ qWarning() << "Invalid app uuid received" << orig;
+ continue;
+ }
+
+ QVariantMap m;
+ m.insert("uuid", uuid.toString());
+ m.insert("shortName", orig.value("short-name"));
+ m.insert("longName", orig.value("long-name"));
+
+ QByteArray pngIcon = orig.value("menu-icon").toByteArray();
+ if (!pngIcon.isEmpty()) {
+ _appMenuIcons.insert(uuid, QImage::fromData(pngIcon, "PNG"));
+ }
+
+ _apps.append(QVariant::fromValue(m));
+ }
+
+ std::sort(_apps.begin(), _apps.end(), [](const QVariant &v1, const QVariant &v2) {
+ const QVariantMap &a = v1.toMap();
+ const QVariantMap &b = v2.toMap();
+ return a.value("shortName").toString() < b.value("shortName").toString();
+ });
+
+ for (int i = 0; i < _apps.size(); ++i) {
+ QUuid uuid = _apps[i].toMap().value("uuid").toUuid();
+ _appsByUuid.insert(uuid, i);
+ }
+
+ qDebug() << _appsByUuid.size() << "different app uuids known";
+
+ emit allAppsChanged();
}
diff --git a/app/pebbledinterface.h b/app/pebbledinterface.h
index 0a6f15d..51efa12 100644
--- a/app/pebbledinterface.h
+++ b/app/pebbledinterface.h
@@ -2,48 +2,57 @@
#define PEBBLEDINTERFACE_H
#include <QObject>
-#include <QtDBus/QtDBus>
-#include <QDBusArgument>
+#include <QUrl>
+#include <QHash>
+#include <QUuid>
+#include <QImage>
+#include <QDBusInterface>
+
+class OrgPebbledWatchInterface;
class PebbledInterface : public QObject
{
Q_OBJECT
+ Q_PROPERTY(bool enabled READ enabled WRITE setEnabled NOTIFY enabledChanged)
+ Q_PROPERTY(bool active READ active WRITE setActive NOTIFY activeChanged)
+ Q_PROPERTY(bool connected READ connected NOTIFY connectedChanged)
+ Q_PROPERTY(QString name READ name NOTIFY nameChanged)
+ Q_PROPERTY(QString address READ address NOTIFY addressChanged)
+ Q_PROPERTY(QString appUuid READ appUuid NOTIFY appUuidChanged)
- static QString PEBBLED_SYSTEMD_UNIT;
- static QString PEBBLED_DBUS_SERVICE;
- static QString PEBBLED_DBUS_PATH;
- static QString PEBBLED_DBUS_IFACE;
+ Q_PROPERTY(QStringList appSlots READ appSlots NOTIFY appSlotsChanged)
+ Q_PROPERTY(QVariantList allApps READ allApps NOTIFY allAppsChanged)
- Q_PROPERTY(bool enabled READ enabled WRITE setEnabled NOTIFY enabledChanged)
- bool enabled() const;
+public:
+ explicit PebbledInterface(QObject *parent = 0);
- Q_PROPERTY(bool active READ active WRITE setActive NOTIFY activeChanged)
+ bool enabled() const;
bool active() const;
-
- Q_PROPERTY(bool connected READ connected NOTIFY connectedChanged)
bool connected() const;
+ QString name() const;
+ QString address() const;
+ QString appUuid() const;
- Q_PROPERTY(QVariantMap pebble READ pebble NOTIFY pebbleChanged)
- QVariantMap pebble() const;
+ QStringList appSlots() const;
+ QVariantList allApps() const;
- Q_PROPERTY(QString name READ name NOTIFY nameChanged)
- QString name() const;
+ Q_INVOKABLE QVariantMap appInfoByUuid(const QString& uuid) const;
- Q_PROPERTY(QString address READ address NOTIFY addressChanged)
- QString address() const;
+ Q_INVOKABLE QUrl configureApp(const QString &uuid);
+ Q_INVOKABLE bool isAppInstalled(const QString &uuid) const;
-public:
- explicit PebbledInterface(QObject *parent = 0);
+ QImage menuIconForApp(const QUuid &uuid) const;
signals:
void enabledChanged();
void activeChanged();
-
void connectedChanged();
- void pebbleChanged();
void nameChanged();
void addressChanged();
+ void appUuidChanged();
+ void appSlotsChanged();
+ void allAppsChanged();
public slots:
void setEnabled(bool);
@@ -53,16 +62,30 @@ public slots:
void disconnect();
void reconnect();
+ void setAppConfiguration(const QString &uuid, const QString &data);
+
+ void launchApp(const QString &uuid);
+ void uploadApp(const QString &uuid, int slot);
+ void unloadApp(int slot);
+
private slots:
+ void onWatchConnectedChanged();
void getUnitProperties();
void onPropertiesChanged(QString interface, QMap<QString, QVariant> changed, QStringList invalidated);
- void onPebbleChanged();
+ void refreshAppSlots();
+ void refreshAllApps();
private:
QDBusInterface *systemd;
+ OrgPebbledWatchInterface *watch;
QDBusObjectPath unitPath;
+ QVariantMap unitProperties;
- QVariantMap properties;
+ // Cached properties
+ QStringList _appSlots;
+ QVariantList _apps;
+ QHash<QUuid, int> _appsByUuid;
+ QHash<QUuid, QImage> _appMenuIcons;
};
#endif // PEBBLEDINTERFACE_H
diff --git a/app/qml/pages/AboutPage.qml b/app/qml/pages/AboutPage.qml
index 3ab92a0..12f4d53 100644
--- a/app/qml/pages/AboutPage.qml
+++ b/app/qml/pages/AboutPage.qml
@@ -40,7 +40,7 @@ Page {
anchors {
left: parent.left
right: parent.right
- margins: Theme.paddingSmall
+ margins: Theme.paddingMedium
}
font.pixelSize: Theme.fontSizeTiny
horizontalAlignment: Text.AlignJustify
diff --git a/app/qml/pages/AppConfigDialog.qml b/app/qml/pages/AppConfigDialog.qml
new file mode 100644
index 0000000..1562985
--- /dev/null
+++ b/app/qml/pages/AppConfigDialog.qml
@@ -0,0 +1,87 @@
+import QtQuick 2.0
+import QtQml 2.1
+import QtWebKit 3.0
+import Sailfish.Silica 1.0
+
+Dialog {
+ id: appConfigPage
+
+ property alias url: webview.url
+ property string uuid
+ property string name
+
+ SilicaWebView {
+ id: webview
+ visible: url != ""
+ anchors.fill: parent
+
+ header: DialogHeader {
+ title: "Configuring " + name
+ }
+
+ VerticalScrollDecorator { flickable: webview }
+
+ overridePageStackNavigation: true
+
+ onNavigationRequested: {
+ console.log("appconfig navigation requested to " + request.url);
+ var url = request.url.toString();
+ if (/^pebblejs:\/\/close/.exec(url)) {
+ var data = decodeURIComponent(url.substring(17));
+ console.log("appconfig requesting close; data: " + data);
+ pebbled.setAppConfiguration(uuid, data);
+ appConfigPage.canAccept = true;
+ appConfigPage.accept();
+ request.action = WebView.IgnoreRequest;
+ } else {
+ request.action = WebView.AcceptRequest;
+ }
+ }
+
+ experimental.itemSelector: Component {
+ Item {
+ Component.onCompleted: {
+ var dialog = pageStack.push(Qt.resolvedUrl("WebItemSelDialog.qml"), {
+ model: model.items
+ });
+ dialog.onRejected.connect(function() {
+ model.reject();
+ });
+ dialog.onAccepted.connect(function() {
+ model.accept(dialog.selectedIndex);
+ });
+ }
+ }
+ }
+ }
+
+ ProgressBar {
+ anchors {
+ left: parent.left
+ right: parent.right
+ bottom: parent.bottom
+ }
+
+ visible: webview.visible && webview.loading
+ minimumValue: 0
+ maximumValue: 100
+ indeterminate: webview.loadProgress === 0
+ value: webview.loadProgress
+ }
+
+ Text {
+ anchors.centerIn: parent
+ visible: url == ""
+ text: qsTr("No configuration settings available")
+ width: parent.width - 2*Theme.paddingLarge
+ horizontalAlignment: Text.AlignHCenter
+ wrapMode: Text.Wrap
+ font {
+ pixelSize: Theme.fontSizeLarge
+ family: Theme.fontFamilyHeading
+ }
+ color: Theme.highlightColor
+ }
+
+ canAccept: false
+}
diff --git a/app/qml/pages/InstallAppDialog.qml b/app/qml/pages/InstallAppDialog.qml
new file mode 100644
index 0000000..fa96c28
--- /dev/null
+++ b/app/qml/pages/InstallAppDialog.qml
@@ -0,0 +1,75 @@
+import QtQuick 2.0
+import QtQml 2.1
+import Sailfish.Silica 1.0
+
+Dialog {
+ id: installAppPage
+
+ property string selectedUuid;
+
+ SilicaListView {
+ id: appList
+ anchors.fill: parent
+
+ header: DialogHeader {
+ title: qsTr("Install app")
+ defaultAcceptText: qsTr("Install")
+ }
+
+ VerticalScrollDecorator { flickable: flickable }
+
+ currentIndex: -1
+
+ delegate: ListItem {
+ id: appDelegate
+ contentHeight: Theme.itemSizeSmall
+
+ property string uuid: modelData.uuid
+ property bool alreadyInstalled: pebbled.isAppInstalled(uuid)
+
+ Item {
+ id: appIcon
+ width: Theme.itemSizeSmall
+ height: Theme.itemSizeSmall
+
+ anchors {
+ top: parent.top
+ left: parent.left
+ leftMargin: Theme.paddingLarge
+ }
+
+ Image {
+ id: appImage
+ anchors.centerIn: parent
+ source: "image://pebble-app-icon/" + uuid;
+ scale: 2
+ }
+ }
+
+ Label {
+ id: appName
+ anchors {
+ left: appIcon.right
+ leftMargin: Theme.paddingMedium
+ right: parent.right
+ rightMargin: Theme.paddingLarge
+ verticalCenter: parent.verticalCenter
+ }
+ text: modelData.longName
+ color: appDelegate.highlighted ? Theme.highlightColor : Theme.primaryColor
+ }
+
+ onClicked: {
+ appList.currentIndex = index
+ if (!alreadyInstalled) {
+ selectedUuid = uuid
+ accept();
+ }
+ }
+ }
+
+ model: pebbled.allApps
+ }
+
+ canAccept: appList.currentIndex >= 0 && !appList.currentItem.alreadyInstalled
+}
diff --git a/app/qml/pages/WatchPage.qml b/app/qml/pages/WatchPage.qml
index 90e5ec9..43c2b99 100644
--- a/app/qml/pages/WatchPage.qml
+++ b/app/qml/pages/WatchPage.qml
@@ -34,7 +34,7 @@ import QtQml 2.1
import Sailfish.Silica 1.0
Page {
- id: page
+ id: watchPage
SilicaFlickable {
id: flickable
@@ -45,9 +45,8 @@ Page {
Column {
id: column
+ width: watchPage.width
- width: page.width
- spacing: Theme.paddingLarge
PageHeader {
title: pebbled.name
}
@@ -61,7 +60,7 @@ Page {
Button {
- text: "Ping"
+ text: qsTr("Ping")
width: parent.width / 2
onClicked: {
pebbled.ping(66)
@@ -69,7 +68,7 @@ Page {
}
Button {
- text: "Sync Time"
+ text: qsTr("Sync Time")
width: parent.width / 2
onClicked: {
pebbled.time()
@@ -77,6 +76,154 @@ Page {
}
}
+ Item {
+ width: parent.width
+ height: Theme.paddingLarge
+ }
+
+ Label {
+ text: qsTr("Installed applications")
+ font.family: Theme.fontFamilyHeading
+ color: Theme.highlightColor
+ anchors.right: parent.right
+ anchors.rightMargin: Theme.paddingMedium
+ }
+
+ Repeater {
+ id: slotsRepeater
+ model: pebbled.appSlots
+
+ ListItem {
+ id: slotDelegate
+ menu: slotMenu
+ contentHeight: Theme.itemSizeSmall
+
+ property bool isEmptySlot: modelData === ""
+ property var appInfo: pebbled.appInfoByUuid(modelData)
+ property bool isKnownApp: appInfo.hasOwnProperty("uuid")
+ property bool busy: false
+
+ function configure() {
+ var uuid = modelData;
+ pebbled.launchApp(uuid);
+ console.log("going to call configure on app with uuid " + uuid);
+ var url = pebbled.configureApp(uuid);
+ console.log("received url: " + url);
+ pageStack.push(Qt.resolvedUrl("AppConfigDialog.qml"), {
+ url: url,
+ uuid: uuid,
+ name: appInfo.longName
+ });
+ }
+
+ function remove() {
+ remorseAction(qsTr("Uninstalling"), function() {
+ busy = true;
+ pebbled.unloadApp(index);
+ });
+ }
+
+ function install() {
+ var dialog = pageStack.push(Qt.resolvedUrl("InstallAppDialog.qml"));
+ dialog.accepted.connect(function() {
+ var uuid = dialog.selectedUuid;
+
+ if (pebbled.isAppInstalled(uuid)) {
+ console.warn("uuid already installed");
+ return;
+ }
+
+ var slot = index;
+ console.log("installing " + uuid + " into " + slot);
+ busy = true;
+ pebbled.uploadApp(uuid, slot);
+ });
+
+ }
+
+ Item {
+ id: slotIcon
+ width: Theme.itemSizeSmall
+ height: Theme.itemSizeSmall
+
+ anchors {
+ top: parent.top
+ left: parent.left
+ leftMargin: Theme.paddingLarge
+ }
+
+ Image {
+ id: slotImage
+ anchors.centerIn: parent
+ source: isKnownApp ? "image://pebble-app-icon/" + modelData : ""
+ scale: 2
+ visible: !isEmptySlot && isKnownApp && !slotBusy.running
+ }
+
+ Rectangle {
+ width: 30
+ height: 30
+ anchors.centerIn: parent
+ scale: 2
+ border {
+ width: 2
+ color: slotDelegate.highlighted ? Theme.highlightColor : Theme.primaryColor
+ }
+ color: "transparent"
+ visible: isEmptySlot && !slotBusy.running
+ }
+
+ BusyIndicator {
+ id: slotBusy
+ anchors.centerIn: parent
+ running: slotDelegate.busy
+ }
+ }
+
+ Label {
+ id: slotName
+ anchors {
+ left: slotIcon.right
+ leftMargin: Theme.paddingMedium
+ right: parent.right
+ rightMargin: Theme.paddingLarge
+ verticalCenter: parent.verticalCenter
+ }
+ text: isEmptySlot ? qsTr("(empty slot)") : (isKnownApp ? appInfo.longName : qsTr("(slot in use by unknown app)"))
+ color: slotDelegate.highlighted ? Theme.highlightColor : Theme.primaryColor
+ onTextChanged: slotDelegate.busy = false;
+ }
+
+ Component {
+ id: slotMenu
+ ContextMenu {
+ MenuItem {
+ text: qsTr("Install app...")
+ visible: isEmptySlot
+ onClicked: install();
+ }
+ MenuItem {
+ text: qsTr("Configure...")
+ visible: !isEmptySlot && isKnownApp
+ onClicked: configure();
+ }
+ MenuItem {
+ text: qsTr("Uninstall")
+ visible: !isEmptySlot
+ onClicked: remove();
+ }
+ }
+ }
+
+ onClicked: {
+ if (isEmptySlot) {
+ install();
+ } else {
+ showMenu();
+ }
+ }
+ }
+ }
}
}
}
diff --git a/app/qml/pages/WebItemSelDialog.qml b/app/qml/pages/WebItemSelDialog.qml
new file mode 100644
index 0000000..f8c49f2
--- /dev/null
+++ b/app/qml/pages/WebItemSelDialog.qml
@@ -0,0 +1,45 @@
+import QtQuick 2.0
+import QtQml 2.1
+import Sailfish.Silica 1.0
+
+Dialog {
+ id: itemSelDialog
+ property alias model: listView.model
+ property int selectedIndex: -1
+
+ SilicaListView {
+ id: listView
+ anchors.fill: parent
+
+ VerticalScrollDecorator { flickable: webview }
+
+ header: PageHeader {
+ }
+
+ delegate: ListItem {
+ id: itemDelegate
+ contentHeight: Theme.itemSizeSmall
+
+ Label {
+ anchors {
+ left: parent.left
+ leftMargin: Theme.paddingMedium
+ right: parent.right
+ rightMargin: Theme.paddingMedium
+ verticalCenter: parent.verticalCenter
+ }
+ text: model.text
+ color: model.enabled ?
+ (itemDelegate.highlighted ? Theme.highlightColor : Theme.primaryColor)
+ : Theme.secondaryColor
+ truncationMode: TruncationMode.Fade
+ }
+
+ enabled: model.enabled
+ onClicked: {
+ selectedIndex = model.index;
+ accept();
+ }
+ }
+ }
+}
diff --git a/app/qml/pebble.qml b/app/qml/pebble.qml
index da3bfb5..2e26ebe 100644
--- a/app/qml/pebble.qml
+++ b/app/qml/pebble.qml
@@ -38,8 +38,4 @@ ApplicationWindow
{
initialPage: Component { ManagerPage { } }
cover: Qt.resolvedUrl("cover/CoverPage.qml")
-
- PebbledInterface {
- id: pebbled
- }
}
diff --git a/app/translations/pebble-es.ts b/app/translations/pebble-es.ts
new file mode 100644
index 0000000..0316ecb
--- /dev/null
+++ b/app/translations/pebble-es.ts
@@ -0,0 +1,254 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.1" language="es_ES">
+<context>
+ <name>AboutPage</name>
+ <message>
+ <location filename="../qml/pages/AboutPage.qml" line="24"/>
+ <source>Version </source>
+ <translation>Versión </translation>
+ </message>
+ <message>
+ <location filename="../qml/pages/AboutPage.qml" line="47"/>
+ <source>THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS &quot;AS IS&quot; AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../qml/pages/AboutPage.qml" line="71"/>
+ <source>Bugs?</source>
+ <translation>¿Errores?</translation>
+ </message>
+</context>
+<context>
+ <name>AppConfigDialog</name>
+ <message>
+ <location filename="../qml/pages/AppConfigDialog.qml" line="75"/>
+ <source>No configuration settings available</source>
+ <translation>No hay opciones disponibles para configurar</translation>
+ </message>
+</context>
+<context>
+ <name>CoverPage</name>
+ <message>
+ <location filename="../qml/cover/CoverPage.qml" line="56"/>
+ <source>connected</source>
+ <translation>conectado</translation>
+ </message>
+ <message>
+ <location filename="../qml/cover/CoverPage.qml" line="56"/>
+ <source>disconnected</source>
+ <translation>desconectado</translation>
+ </message>
+</context>
+<context>
+ <name>InstallAppDialog</name>
+ <message>
+ <location filename="../qml/pages/InstallAppDialog.qml" line="15"/>
+ <source>Install app</source>
+ <translation>Instalar app</translation>
+ </message>
+ <message>
+ <location filename="../qml/pages/InstallAppDialog.qml" line="16"/>
+ <source>Install</source>
+ <translation>Instalar</translation>
+ </message>
+</context>
+<context>
+ <name>ManagerPage</name>
+ <message>
+ <location filename="../qml/pages/ManagerPage.qml" line="65"/>
+ <source>About</source>
+ <translation>Acerca de</translation>
+ </message>
+ <message>
+ <location filename="../qml/pages/ManagerPage.qml" line="76"/>
+ <source>Pebble Manager</source>
+ <translation></translation>
+ </message>
+ <message>
+ <location filename="../qml/pages/ManagerPage.qml" line="83"/>
+ <source>Waiting for watch...
+If it can&apos;t be found please check it&apos;s available and paired in Bluetooth settings.</source>
+ <translation>Buscando el reloj
+Si esto tarda mucho, comprueba que el reloj esté emparejado correctamente.</translation>
+ </message>
+ <message>
+ <location filename="../qml/pages/ManagerPage.qml" line="104"/>
+ <source>Service</source>
+ <translation>Servicio</translation>
+ </message>
+ <message>
+ <location filename="../qml/pages/ManagerPage.qml" line="111"/>
+ <source>Enabled</source>
+ <translation>Habilitado</translation>
+ </message>
+ <message>
+ <location filename="../qml/pages/ManagerPage.qml" line="112"/>
+ <source>Automatic startup</source>
+ <translation>Inicio automático</translation>
+ </message>
+ <message>
+ <location filename="../qml/pages/ManagerPage.qml" line="112"/>
+ <source>Manual startup</source>
+ <translation>Inicio manual</translation>
+ </message>
+ <message>
+ <location filename="../qml/pages/ManagerPage.qml" line="118"/>
+ <source>Active</source>
+ <translation>Activo</translation>
+ </message>
+ <message>
+ <location filename="../qml/pages/ManagerPage.qml" line="119"/>
+ <source>Running</source>
+ <translation>Ejecutándose</translation>
+ </message>
+ <message>
+ <location filename="../qml/pages/ManagerPage.qml" line="119"/>
+ <source>Dead</source>
+ <translation>Detenido</translation>
+ </message>
+ <message>
+ <location filename="../qml/pages/ManagerPage.qml" line="125"/>
+ <source>Connection</source>
+ <translation>Conexión</translation>
+ </message>
+ <message>
+ <location filename="../qml/pages/ManagerPage.qml" line="126"/>
+ <source>Connected</source>
+ <translation>Conectado</translation>
+ </message>
+ <message>
+ <location filename="../qml/pages/ManagerPage.qml" line="126"/>
+ <source>Disconnected</source>
+ <translation>Desconectado</translation>
+ </message>
+ <message>
+ <location filename="../qml/pages/ManagerPage.qml" line="139"/>
+ <source>Settings</source>
+ <translation>Configuración</translation>
+ </message>
+ <message>
+ <location filename="../qml/pages/ManagerPage.qml" line="146"/>
+ <source>Forward phone calls</source>
+ <translation>Transferir llamadas</translation>
+ </message>
+ <message>
+ <location filename="../qml/pages/ManagerPage.qml" line="154"/>
+ <source>Silent when connected</source>
+ <translation>Modo silencio automático</translation>
+ </message>
+ <message>
+ <location filename="../qml/pages/ManagerPage.qml" line="155"/>
+ <source>Sets phone profile to &quot;silent&quot; when Pebble is connected</source>
+ <translation>Activa el modo silencio cuando se conecte un Pebble</translation>
+ </message>
+ <message>
+ <location filename="../qml/pages/ManagerPage.qml" line="163"/>
+ <source>Transliterate messages</source>
+ <translation>Transliterar mensajes</translation>
+ </message>
+ <message>
+ <location filename="../qml/pages/ManagerPage.qml" line="164"/>
+ <source>Messages are transliterated to ASCII before sending to Pebble</source>
+ <translation>Codifica los mensajes entrates a ASCII antes de enviarlos a Pebble</translation>
+ </message>
+ <message>
+ <location filename="../qml/pages/ManagerPage.qml" line="173"/>
+ <source>Notifications</source>
+ <translation>Notificaciones</translation>
+ </message>
+ <message>
+ <location filename="../qml/pages/ManagerPage.qml" line="181"/>
+ <source>Messaging</source>
+ <translation>Mensajería</translation>
+ </message>
+ <message>
+ <location filename="../qml/pages/ManagerPage.qml" line="182"/>
+ <source>SMS and IM</source>
+ <translation>SMS y chat</translation>
+ </message>
+ <message>
+ <location filename="../qml/pages/ManagerPage.qml" line="191"/>
+ <source>Missed call</source>
+ <translation>Llamadas perdidas</translation>
+ </message>
+ <message>
+ <location filename="../qml/pages/ManagerPage.qml" line="200"/>
+ <source>Emails</source>
+ <translation>Correos electrónicos</translation>
+ </message>
+ <message>
+ <location filename="../qml/pages/ManagerPage.qml" line="209"/>
+ <source>Mitakuuluu</source>
+ <translation></translation>
+ </message>
+ <message>
+ <location filename="../qml/pages/ManagerPage.qml" line="218"/>
+ <source>Twitter</source>
+ <translation>Twitter</translation>
+ </message>
+ <message>
+ <location filename="../qml/pages/ManagerPage.qml" line="228"/>
+ <source>Facebook</source>
+ <translation>Facebook</translation>
+ </message>
+ <message>
+ <location filename="../qml/pages/ManagerPage.qml" line="237"/>
+ <source>Other notifications</source>
+ <translation>Resto de notificaciones</translation>
+ </message>
+ <message>
+ <location filename="../qml/pages/ManagerPage.qml" line="246"/>
+ <source>All notifications</source>
+ <translation>Todas las notificaciones</translation>
+ </message>
+</context>
+<context>
+ <name>WatchPage</name>
+ <message>
+ <location filename="../qml/pages/WatchPage.qml" line="63"/>
+ <source>Ping</source>
+ <translation>Ping</translation>
+ </message>
+ <message>
+ <location filename="../qml/pages/WatchPage.qml" line="71"/>
+ <source>Sync Time</source>
+ <translation>Ajustar hora</translation>
+ </message>
+ <message>
+ <location filename="../qml/pages/WatchPage.qml" line="85"/>
+ <source>Installed applications</source>
+ <translation>Aplicaciones instaladas</translation>
+ </message>
+ <message>
+ <location filename="../qml/pages/WatchPage.qml" line="120"/>
+ <source>Uninstalling</source>
+ <translation>Desinstalando</translation>
+ </message>
+ <message>
+ <location filename="../qml/pages/WatchPage.qml" line="192"/>
+ <source>(empty slot)</source>
+ <translation>(hueco libre)</translation>
+ </message>
+ <message>
+ <location filename="../qml/pages/WatchPage.qml" line="192"/>
+ <source>(slot in use by unknown app)</source>
+ <translation>(hueco en uso)</translation>
+ </message>
+ <message>
+ <location filename="../qml/pages/WatchPage.qml" line="201"/>
+ <source>Install app...</source>
+ <translation>Instalar app...</translation>
+ </message>
+ <message>
+ <location filename="../qml/pages/WatchPage.qml" line="206"/>
+ <source>Configure...</source>
+ <translation>Configurar...</translation>
+ </message>
+ <message>
+ <location filename="../qml/pages/WatchPage.qml" line="211"/>
+ <source>Uninstall</source>
+ <translation>Desinstalar</translation>
+ </message>
+</context>
+</TS>
diff --git a/app/translations/pebble.ts b/app/translations/pebble.ts
new file mode 100644
index 0000000..7a78d9d
--- /dev/null
+++ b/app/translations/pebble.ts
@@ -0,0 +1,253 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.1">
+<context>
+ <name>AboutPage</name>
+ <message>
+ <location filename="../qml/pages/AboutPage.qml" line="24"/>
+ <source>Version </source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../qml/pages/AboutPage.qml" line="47"/>
+ <source>THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS &quot;AS IS&quot; AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../qml/pages/AboutPage.qml" line="71"/>
+ <source>Bugs?</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>AppConfigDialog</name>
+ <message>
+ <location filename="../qml/pages/AppConfigDialog.qml" line="75"/>
+ <source>No configuration settings available</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>CoverPage</name>
+ <message>
+ <location filename="../qml/cover/CoverPage.qml" line="56"/>
+ <source>connected</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../qml/cover/CoverPage.qml" line="56"/>
+ <source>disconnected</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>InstallAppDialog</name>
+ <message>
+ <location filename="../qml/pages/InstallAppDialog.qml" line="15"/>
+ <source>Install app</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../qml/pages/InstallAppDialog.qml" line="16"/>
+ <source>Install</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>ManagerPage</name>
+ <message>
+ <location filename="../qml/pages/ManagerPage.qml" line="65"/>
+ <source>About</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../qml/pages/ManagerPage.qml" line="76"/>
+ <source>Pebble Manager</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../qml/pages/ManagerPage.qml" line="83"/>
+ <source>Waiting for watch...
+If it can&apos;t be found please check it&apos;s available and paired in Bluetooth settings.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../qml/pages/ManagerPage.qml" line="104"/>
+ <source>Service</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../qml/pages/ManagerPage.qml" line="111"/>
+ <source>Enabled</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../qml/pages/ManagerPage.qml" line="112"/>
+ <source>Automatic startup</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../qml/pages/ManagerPage.qml" line="112"/>
+ <source>Manual startup</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../qml/pages/ManagerPage.qml" line="118"/>
+ <source>Active</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../qml/pages/ManagerPage.qml" line="119"/>
+ <source>Running</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../qml/pages/ManagerPage.qml" line="119"/>
+ <source>Dead</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../qml/pages/ManagerPage.qml" line="125"/>
+ <source>Connection</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../qml/pages/ManagerPage.qml" line="126"/>
+ <source>Connected</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../qml/pages/ManagerPage.qml" line="126"/>
+ <source>Disconnected</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../qml/pages/ManagerPage.qml" line="139"/>
+ <source>Settings</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../qml/pages/ManagerPage.qml" line="146"/>
+ <source>Forward phone calls</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../qml/pages/ManagerPage.qml" line="154"/>
+ <source>Silent when connected</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../qml/pages/ManagerPage.qml" line="155"/>
+ <source>Sets phone profile to &quot;silent&quot; when Pebble is connected</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../qml/pages/ManagerPage.qml" line="163"/>
+ <source>Transliterate messages</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../qml/pages/ManagerPage.qml" line="164"/>
+ <source>Messages are transliterated to ASCII before sending to Pebble</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../qml/pages/ManagerPage.qml" line="173"/>
+ <source>Notifications</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../qml/pages/ManagerPage.qml" line="181"/>
+ <source>Messaging</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../qml/pages/ManagerPage.qml" line="182"/>
+ <source>SMS and IM</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../qml/pages/ManagerPage.qml" line="191"/>
+ <source>Missed call</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../qml/pages/ManagerPage.qml" line="200"/>
+ <source>Emails</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../qml/pages/ManagerPage.qml" line="209"/>
+ <source>Mitakuuluu</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../qml/pages/ManagerPage.qml" line="218"/>
+ <source>Twitter</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../qml/pages/ManagerPage.qml" line="228"/>
+ <source>Facebook</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../qml/pages/ManagerPage.qml" line="237"/>
+ <source>Other notifications</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../qml/pages/ManagerPage.qml" line="246"/>
+ <source>All notifications</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>WatchPage</name>
+ <message>
+ <location filename="../qml/pages/WatchPage.qml" line="63"/>
+ <source>Ping</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../qml/pages/WatchPage.qml" line="71"/>
+ <source>Sync Time</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../qml/pages/WatchPage.qml" line="85"/>
+ <source>Installed applications</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../qml/pages/WatchPage.qml" line="120"/>
+ <source>Uninstalling</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../qml/pages/WatchPage.qml" line="192"/>
+ <source>(empty slot)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../qml/pages/WatchPage.qml" line="192"/>
+ <source>(slot in use by unknown app)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../qml/pages/WatchPage.qml" line="201"/>
+ <source>Install app...</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../qml/pages/WatchPage.qml" line="206"/>
+ <source>Configure...</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../qml/pages/WatchPage.qml" line="211"/>
+ <source>Uninstall</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+</TS>