diff options
80 files changed, 5440 insertions, 2169 deletions
@@ -6,17 +6,28 @@ msgid "" msgstr "" "Project-Id-Version: rockwork\n" +<<<<<<< HEAD +"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n" +"POT-Creation-Date: 2016-02-08 03:04+0100\n" +"PO-Revision-Date: 2016-01-12 09:52+0000\n" +======= "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2016-02-14 23:39+0100\n" "PO-Revision-Date: 2016-02-15 06:05+0000\n" +>>>>>>> refs/heads/rockwork "Last-Translator: Michael Zanetti <michael.zanetti@canonical.com>\n" "Language-Team: German <de@li.org>\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" +<<<<<<< HEAD +"X-Launchpad-Export-Date: 2016-02-08 05:41+0000\n" +"X-Generator: Launchpad (build 17908)\n" +======= "X-Launchpad-Export-Date: 2016-02-16 05:44+0000\n" "X-Generator: Launchpad (build 17925)\n" "Language: de\n" +>>>>>>> refs/heads/rockwork #: /home/micha/Develop/upebble/rockwork/AppSettingsPage.qml:13 msgid "App Settings" @@ -58,7 +69,7 @@ msgstr "Neue App hinzufügen" msgid "Add new watchface" msgstr "Neues Ziffernblatt hinzufügen" -#: /home/micha/Develop/upebble/rockwork/AppStorePage.qml:125 +#: /home/micha/Develop/upebble/rockwork/AppStorePage.qml:119 msgid "See all" msgstr "Alle anzeigen" @@ -76,25 +87,38 @@ msgstr "Bildschirmfotos" msgid "Report problem" msgstr "Fehler berichten" +<<<<<<< HEAD +======= #: /home/micha/Develop/upebble/rockwork/DeveloperToolsPage.qml:42 msgid "Install app or watchface from file" msgstr "App oder Watchface aus datei installieren" +>>>>>>> refs/heads/rockwork #: /home/micha/Develop/upebble/rockwork/DeveloperToolsPage.qml:109 msgid "Preparing logs package..." msgstr "Bereite Logs vor..." #: /home/micha/Develop/upebble/rockwork/DeveloperToolsPage.qml:120 +<<<<<<< HEAD +#: /home/micha/Develop/upebble/rockwork/DeveloperToolsPage.qml:132 +msgid "rockworkd.log" +msgstr "" +======= msgid "pebble.log" msgstr "pebble.log" +>>>>>>> refs/heads/rockwork #: /home/micha/Develop/upebble/rockwork/DeveloperToolsPage.qml:127 msgid "Send rockworkd.log" +<<<<<<< HEAD +msgstr "" +======= msgstr "rockworkd.log senden" #: /home/micha/Develop/upebble/rockwork/DeveloperToolsPage.qml:132 msgid "rockworkd.log" msgstr "rockworkd.log" +>>>>>>> refs/heads/rockwork #: /home/micha/Develop/upebble/rockwork/DeveloperToolsPage.qml:137 msgid "Send watch logs" @@ -112,8 +136,13 @@ msgid "Firmware upgrade" msgstr "Software updaten" #: /home/micha/Develop/upebble/rockwork/FirmwareUpgradePage.qml:16 +<<<<<<< HEAD +msgid "A new firmware upgrade is available for your Pebble smarwatch." +msgstr "" +======= msgid "A new firmware upgrade is available for your Pebble smartwatch." msgstr "Eine neue Software für Ihre Pebble Uhr steht zur Verfügung." +>>>>>>> refs/heads/rockwork #: /home/micha/Develop/upebble/rockwork/FirmwareUpgradePage.qml:23 #, qt-format @@ -183,10 +212,13 @@ msgstr "Ich möchte mehr schlafen" msgid "OK" msgstr "OK" +<<<<<<< HEAD +======= #: /home/micha/Develop/upebble/rockwork/ImportPackagePage.qml:7 msgid "Import watchapp or watchface" msgstr "Watchapp oder Watchface importieren" +>>>>>>> refs/heads/rockwork #: /home/micha/Develop/upebble/rockwork/InfoPage.qml:31 #, qt-format msgid "Version %1" @@ -242,8 +274,13 @@ msgid "Loading..." msgstr "" #: /home/micha/Develop/upebble/rockwork/MainMenuPage.qml:15 +<<<<<<< HEAD +msgid "Info" +msgstr "" +======= msgid "About" msgstr "Über" +>>>>>>> refs/heads/rockwork #: /home/micha/Develop/upebble/rockwork/MainMenuPage.qml:22 msgid "Developer tools" diff --git a/po/en_GB.po b/po/en_GB.po index 0d69af1..2a022a8 100644 --- a/po/en_GB.po +++ b/po/en_GB.po @@ -6,17 +6,29 @@ msgid "" msgstr "" "Project-Id-Version: rockwork\n" +<<<<<<< HEAD +"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n" +"POT-Creation-Date: 2016-02-08 03:04+0100\n" +"PO-Revision-Date: 2016-01-26 18:00+0000\n" +"Last-Translator: Emanuele Antonio Faraone <emanueleant03@gmail.com>\n" +======= "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2016-02-14 23:39+0100\n" "PO-Revision-Date: 2016-02-15 08:54+0000\n" "Last-Translator: Adrian Chiang <Unknown>\n" +>>>>>>> refs/heads/rockwork "Language-Team: English (United Kingdom) <en_GB@li.org>\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" +<<<<<<< HEAD +"X-Launchpad-Export-Date: 2016-02-08 05:41+0000\n" +"X-Generator: Launchpad (build 17908)\n" +======= "X-Launchpad-Export-Date: 2016-02-16 05:44+0000\n" "X-Generator: Launchpad (build 17925)\n" "Language: \n" +>>>>>>> refs/heads/rockwork #: /home/micha/Develop/upebble/rockwork/AppSettingsPage.qml:13 msgid "App Settings" @@ -58,7 +70,7 @@ msgstr "Add new watchapp" msgid "Add new watchface" msgstr "Add new watchface" -#: /home/micha/Develop/upebble/rockwork/AppStorePage.qml:125 +#: /home/micha/Develop/upebble/rockwork/AppStorePage.qml:119 msgid "See all" msgstr "See all" @@ -76,25 +88,38 @@ msgstr "Screenshots" msgid "Report problem" msgstr "Report problem" +<<<<<<< HEAD +======= #: /home/micha/Develop/upebble/rockwork/DeveloperToolsPage.qml:42 msgid "Install app or watchface from file" msgstr "Install app or watchface from file" +>>>>>>> refs/heads/rockwork #: /home/micha/Develop/upebble/rockwork/DeveloperToolsPage.qml:109 msgid "Preparing logs package..." msgstr "Preparing logs package..." #: /home/micha/Develop/upebble/rockwork/DeveloperToolsPage.qml:120 +<<<<<<< HEAD +#: /home/micha/Develop/upebble/rockwork/DeveloperToolsPage.qml:132 +msgid "rockworkd.log" +msgstr "" +======= msgid "pebble.log" msgstr "pebble.log" +>>>>>>> refs/heads/rockwork #: /home/micha/Develop/upebble/rockwork/DeveloperToolsPage.qml:127 msgid "Send rockworkd.log" +<<<<<<< HEAD +msgstr "" +======= msgstr "Send rockworkd.log" #: /home/micha/Develop/upebble/rockwork/DeveloperToolsPage.qml:132 msgid "rockworkd.log" msgstr "rockworkd.log" +>>>>>>> refs/heads/rockwork #: /home/micha/Develop/upebble/rockwork/DeveloperToolsPage.qml:137 msgid "Send watch logs" @@ -112,8 +137,13 @@ msgid "Firmware upgrade" msgstr "Firmware upgrade" #: /home/micha/Develop/upebble/rockwork/FirmwareUpgradePage.qml:16 +<<<<<<< HEAD +msgid "A new firmware upgrade is available for your Pebble smarwatch." +msgstr "" +======= msgid "A new firmware upgrade is available for your Pebble smartwatch." msgstr "A new firmware upgrade is available for your Pebble smartwatch." +>>>>>>> refs/heads/rockwork #: /home/micha/Develop/upebble/rockwork/FirmwareUpgradePage.qml:23 #, qt-format @@ -182,10 +212,13 @@ msgstr "I want to sleep more" msgid "OK" msgstr "OK" +<<<<<<< HEAD +======= #: /home/micha/Develop/upebble/rockwork/ImportPackagePage.qml:7 msgid "Import watchapp or watchface" msgstr "Import watchapp or watchface" +>>>>>>> refs/heads/rockwork #: /home/micha/Develop/upebble/rockwork/InfoPage.qml:31 #, qt-format msgid "Version %1" @@ -241,8 +274,13 @@ msgid "Loading..." msgstr "Loading..." #: /home/micha/Develop/upebble/rockwork/MainMenuPage.qml:15 +<<<<<<< HEAD +msgid "Info" +msgstr "" +======= msgid "About" msgstr "About" +>>>>>>> refs/heads/rockwork #: /home/micha/Develop/upebble/rockwork/MainMenuPage.qml:22 msgid "Developer tools" @@ -6,17 +6,27 @@ msgid "" msgstr "" "Project-Id-Version: rockwork\n" +<<<<<<< HEAD +"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n" +"POT-Creation-Date: 2016-02-08 03:04+0100\n" +======= "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2016-02-14 23:39+0100\n" +>>>>>>> refs/heads/rockwork "PO-Revision-Date: 2016-02-03 22:34+0000\n" "Last-Translator: Aitzol Berasategi <aitzol76@gmail.com>\n" "Language-Team: Basque <eu@li.org>\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" +<<<<<<< HEAD +"X-Launchpad-Export-Date: 2016-02-08 05:41+0000\n" +"X-Generator: Launchpad (build 17908)\n" +======= "X-Launchpad-Export-Date: 2016-02-15 05:44+0000\n" "X-Generator: Launchpad (build 17925)\n" "Language: eu\n" +>>>>>>> refs/heads/rockwork #: /home/micha/Develop/upebble/rockwork/AppSettingsPage.qml:13 msgid "App Settings" @@ -58,7 +68,7 @@ msgstr "Watchapp berria gehitu" msgid "Add new watchface" msgstr "Watchface berria gehitu" -#: /home/micha/Develop/upebble/rockwork/AppStorePage.qml:125 +#: /home/micha/Develop/upebble/rockwork/AppStorePage.qml:119 msgid "See all" msgstr "Guztiak ikusi" @@ -76,26 +86,19 @@ msgstr "Pantaila-argazkiak" msgid "Report problem" msgstr "" -#: /home/micha/Develop/upebble/rockwork/DeveloperToolsPage.qml:42 -msgid "Install app or watchface from file" -msgstr "" - #: /home/micha/Develop/upebble/rockwork/DeveloperToolsPage.qml:109 msgid "Preparing logs package..." msgstr "" #: /home/micha/Develop/upebble/rockwork/DeveloperToolsPage.qml:120 -msgid "pebble.log" +#: /home/micha/Develop/upebble/rockwork/DeveloperToolsPage.qml:132 +msgid "rockworkd.log" msgstr "" #: /home/micha/Develop/upebble/rockwork/DeveloperToolsPage.qml:127 msgid "Send rockworkd.log" msgstr "" -#: /home/micha/Develop/upebble/rockwork/DeveloperToolsPage.qml:132 -msgid "rockworkd.log" -msgstr "" - #: /home/micha/Develop/upebble/rockwork/DeveloperToolsPage.qml:137 msgid "Send watch logs" msgstr "" @@ -112,7 +115,11 @@ msgid "Firmware upgrade" msgstr "Firmware eguneraketa" #: /home/micha/Develop/upebble/rockwork/FirmwareUpgradePage.qml:16 +<<<<<<< HEAD +msgid "A new firmware upgrade is available for your Pebble smarwatch." +======= msgid "A new firmware upgrade is available for your Pebble smartwatch." +>>>>>>> refs/heads/rockwork msgstr "" #: /home/micha/Develop/upebble/rockwork/FirmwareUpgradePage.qml:23 @@ -182,10 +189,6 @@ msgstr "" msgid "OK" msgstr "" -#: /home/micha/Develop/upebble/rockwork/ImportPackagePage.qml:7 -msgid "Import watchapp or watchface" -msgstr "" - #: /home/micha/Develop/upebble/rockwork/InfoPage.qml:31 #, qt-format msgid "Version %1" @@ -239,7 +242,7 @@ msgid "Loading..." msgstr "" #: /home/micha/Develop/upebble/rockwork/MainMenuPage.qml:15 -msgid "About" +msgid "Info" msgstr "" #: /home/micha/Develop/upebble/rockwork/MainMenuPage.qml:22 @@ -6,17 +6,28 @@ msgid "" msgstr "" "Project-Id-Version: upebble\n" +<<<<<<< HEAD +"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n" +"POT-Creation-Date: 2016-02-08 03:04+0100\n" +"PO-Revision-Date: 2016-02-07 15:41+0000\n" +======= "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2016-02-14 23:39+0100\n" "PO-Revision-Date: 2016-02-15 06:05+0000\n" +>>>>>>> refs/heads/rockwork "Last-Translator: Anne <anneonyme017@gmail.com>\n" "Language-Team: French <fr@li.org>\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" +<<<<<<< HEAD +"X-Launchpad-Export-Date: 2016-02-08 05:41+0000\n" +"X-Generator: Launchpad (build 17908)\n" +======= "X-Launchpad-Export-Date: 2016-02-16 05:44+0000\n" "X-Generator: Launchpad (build 17925)\n" "Language: fr\n" +>>>>>>> refs/heads/rockwork #: /home/micha/Develop/upebble/rockwork/AppSettingsPage.qml:13 msgid "App Settings" @@ -56,15 +67,15 @@ msgstr "Ajouter une nouvelle application pour montre" #: /home/micha/Develop/upebble/rockwork/AppStorePage.qml:8 msgid "Add new watchface" -msgstr "Ajouter une nouveau cadran" +msgstr "Ajouter un nouveau thème de montre" -#: /home/micha/Develop/upebble/rockwork/AppStorePage.qml:125 +#: /home/micha/Develop/upebble/rockwork/AppStorePage.qml:119 msgid "See all" msgstr "Tout voir" #: /home/micha/Develop/upebble/rockwork/DeveloperToolsPage.qml:9 msgid "Developer Tools" -msgstr "Outils pour développeurs" +msgstr "" #: /home/micha/Develop/upebble/rockwork/DeveloperToolsPage.qml:28 #: /home/micha/Develop/upebble/rockwork/ScreenshotsPage.qml:11 @@ -74,27 +85,33 @@ msgstr "Captures d'écran" #: /home/micha/Develop/upebble/rockwork/DeveloperToolsPage.qml:35 #: /home/micha/Develop/upebble/rockwork/DeveloperToolsPage.qml:102 msgid "Report problem" +<<<<<<< HEAD +msgstr "" +======= msgstr "Signaler un problème" #: /home/micha/Develop/upebble/rockwork/DeveloperToolsPage.qml:42 msgid "Install app or watchface from file" msgstr "Installer une application ou un cadran à partir d'un fichier" +>>>>>>> refs/heads/rockwork #: /home/micha/Develop/upebble/rockwork/DeveloperToolsPage.qml:109 msgid "Preparing logs package..." msgstr "Préparation de l'ensemble des rapports…" #: /home/micha/Develop/upebble/rockwork/DeveloperToolsPage.qml:120 +<<<<<<< HEAD +#: /home/micha/Develop/upebble/rockwork/DeveloperToolsPage.qml:132 +msgid "rockworkd.log" +msgstr "" +======= msgid "pebble.log" msgstr "pebble.log" +>>>>>>> refs/heads/rockwork #: /home/micha/Develop/upebble/rockwork/DeveloperToolsPage.qml:127 msgid "Send rockworkd.log" -msgstr "Envoi de rockworkd.log" - -#: /home/micha/Develop/upebble/rockwork/DeveloperToolsPage.qml:132 -msgid "rockworkd.log" -msgstr "rockworkd.log" +msgstr "" #: /home/micha/Develop/upebble/rockwork/DeveloperToolsPage.qml:137 msgid "Send watch logs" @@ -112,7 +129,11 @@ msgid "Firmware upgrade" msgstr "Mise à niveau du micrologiciel" #: /home/micha/Develop/upebble/rockwork/FirmwareUpgradePage.qml:16 +<<<<<<< HEAD +msgid "A new firmware upgrade is available for your Pebble smarwatch." +======= msgid "A new firmware upgrade is available for your Pebble smartwatch." +>>>>>>> refs/heads/rockwork msgstr "" "Une nouvelle mise à niveau du micrologiciel est disponible pour votre montre " "connectée Pebble." @@ -147,27 +168,31 @@ msgstr "" #: /home/micha/Develop/upebble/rockwork/HealthSettingsDialog.qml:9 msgid "Health settings" -msgstr "Paramètre de Bien-Être" +msgstr "" #: /home/micha/Develop/upebble/rockwork/HealthSettingsDialog.qml:17 msgid "Health app enabled" +<<<<<<< HEAD +msgstr "" +======= msgstr "L'application Bien-Être est activée" +>>>>>>> refs/heads/rockwork #: /home/micha/Develop/upebble/rockwork/HealthSettingsDialog.qml:28 msgid "Female" -msgstr "Femme" +msgstr "" #: /home/micha/Develop/upebble/rockwork/HealthSettingsDialog.qml:28 msgid "Male" -msgstr "Homme" +msgstr "" #: /home/micha/Develop/upebble/rockwork/HealthSettingsDialog.qml:34 msgid "Age" -msgstr "Âge" +msgstr "" #: /home/micha/Develop/upebble/rockwork/HealthSettingsDialog.qml:47 msgid "Height (cm)" -msgstr "Taille (cm):" +msgstr "" #: /home/micha/Develop/upebble/rockwork/HealthSettingsDialog.qml:60 msgid "Weight" @@ -183,20 +208,31 @@ msgstr "Je veux dormir plus" #: /home/micha/Develop/upebble/rockwork/HealthSettingsDialog.qml:95 msgid "OK" +<<<<<<< HEAD +msgstr "" +======= msgstr "Valider" #: /home/micha/Develop/upebble/rockwork/ImportPackagePage.qml:7 msgid "Import watchapp or watchface" msgstr "Importer une application ou un cadran" +>>>>>>> refs/heads/rockwork #: /home/micha/Develop/upebble/rockwork/InfoPage.qml:31 #, qt-format msgid "Version %1" -msgstr "Version %1" +msgstr "" #: /home/micha/Develop/upebble/rockwork/InfoPage.qml:40 +<<<<<<< HEAD +msgid "Contributors" +msgstr "" + +#: /home/micha/Develop/upebble/rockwork/InfoPage.qml:52 +======= +>>>>>>> refs/heads/rockwork msgid "Legal" -msgstr "Informations légales" +msgstr "" #: /home/micha/Develop/upebble/rockwork/InfoPage.qml:62 msgid "" @@ -212,7 +248,7 @@ msgstr "Pebble est une marque déposée par Pebble Technology Corp." #: /home/micha/Develop/upebble/rockwork/InstalledAppsPage.qml:9 msgid "Apps & Watchfaces" -msgstr "Applications & Cadrans" +msgstr "Applications & thèmes de montre" #: /home/micha/Develop/upebble/rockwork/InstalledAppsPage.qml:9 msgid "Apps" @@ -220,7 +256,7 @@ msgstr "Applications" #: /home/micha/Develop/upebble/rockwork/InstalledAppsPage.qml:9 msgid "Watchfaces" -msgstr "Cadrans" +msgstr "Thèmes de montre" #: /home/micha/Develop/upebble/rockwork/InstalledAppsPage.qml:167 msgid "Launch" @@ -244,12 +280,17 @@ msgid "Loading..." msgstr "" #: /home/micha/Develop/upebble/rockwork/MainMenuPage.qml:15 +<<<<<<< HEAD +msgid "Info" +msgstr "" +======= msgid "About" msgstr "À propos" +>>>>>>> refs/heads/rockwork #: /home/micha/Develop/upebble/rockwork/MainMenuPage.qml:22 msgid "Developer tools" -msgstr "Outils de développement" +msgstr "" #: /home/micha/Develop/upebble/rockwork/MainMenuPage.qml:52 msgid "Manage notifications" @@ -261,12 +302,12 @@ msgstr "Gérer les applications" #: /home/micha/Develop/upebble/rockwork/MainMenuPage.qml:67 msgid "Manage Watchfaces" -msgstr "Gérer les cadrans" +msgstr "Gérer les thèmes de montre" #: /home/micha/Develop/upebble/rockwork/MainMenuPage.qml:75 #: /home/micha/Develop/upebble/rockwork/SettingsPage.qml:8 msgid "Settings" -msgstr "Paramètres" +msgstr "" #: /home/micha/Develop/upebble/rockwork/MainMenuPage.qml:190 #: /home/micha/Develop/upebble/rockwork/PebblesPage.qml:36 @@ -351,20 +392,24 @@ msgstr "Enregistrer" #: /home/micha/Develop/upebble/rockwork/SettingsPage.qml:19 msgid "Distance Units" -msgstr "Unités de Distance" +msgstr "" #: /home/micha/Develop/upebble/rockwork/SettingsPage.qml:35 msgid "Metric" -msgstr "Métrique" +msgstr "" #: /home/micha/Develop/upebble/rockwork/SettingsPage.qml:48 msgid "Imperial" -msgstr "Impérial" +msgstr "" #: /home/micha/Develop/upebble/rockwork/SettingsPage.qml:55 msgid "Calendar" -msgstr "Agenda" +msgstr "" #: /home/micha/Develop/upebble/rockwork/SettingsPage.qml:62 msgid "Sync calendar to timeline" +<<<<<<< HEAD +msgstr "" +======= msgstr "Synchroniser l'agenda sur la Timeline." +>>>>>>> refs/heads/rockwork @@ -6,17 +6,27 @@ msgid "" msgstr "" "Project-Id-Version: rockwork\n" +<<<<<<< HEAD +"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n" +"POT-Creation-Date: 2016-02-08 03:04+0100\n" +======= "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2016-02-14 23:39+0100\n" +>>>>>>> refs/heads/rockwork "PO-Revision-Date: 2016-02-02 09:30+0000\n" "Last-Translator: Richard Somlói <ricsipontaz@gmail.com>\n" "Language-Team: Hungarian <hu@li.org>\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" +<<<<<<< HEAD +"X-Launchpad-Export-Date: 2016-02-08 05:41+0000\n" +"X-Generator: Launchpad (build 17908)\n" +======= "X-Launchpad-Export-Date: 2016-02-15 05:44+0000\n" "X-Generator: Launchpad (build 17925)\n" "Language: hu\n" +>>>>>>> refs/heads/rockwork #: /home/micha/Develop/upebble/rockwork/AppSettingsPage.qml:13 msgid "App Settings" @@ -58,7 +68,7 @@ msgstr "Új alkalmazás hozzáadása" msgid "Add new watchface" msgstr "Új számlap hozzáadása" -#: /home/micha/Develop/upebble/rockwork/AppStorePage.qml:125 +#: /home/micha/Develop/upebble/rockwork/AppStorePage.qml:119 msgid "See all" msgstr "Összes" @@ -76,26 +86,19 @@ msgstr "Képernyőképek" msgid "Report problem" msgstr "" -#: /home/micha/Develop/upebble/rockwork/DeveloperToolsPage.qml:42 -msgid "Install app or watchface from file" -msgstr "" - #: /home/micha/Develop/upebble/rockwork/DeveloperToolsPage.qml:109 msgid "Preparing logs package..." msgstr "" #: /home/micha/Develop/upebble/rockwork/DeveloperToolsPage.qml:120 -msgid "pebble.log" +#: /home/micha/Develop/upebble/rockwork/DeveloperToolsPage.qml:132 +msgid "rockworkd.log" msgstr "" #: /home/micha/Develop/upebble/rockwork/DeveloperToolsPage.qml:127 msgid "Send rockworkd.log" msgstr "" -#: /home/micha/Develop/upebble/rockwork/DeveloperToolsPage.qml:132 -msgid "rockworkd.log" -msgstr "" - #: /home/micha/Develop/upebble/rockwork/DeveloperToolsPage.qml:137 msgid "Send watch logs" msgstr "" @@ -112,8 +115,13 @@ msgid "Firmware upgrade" msgstr "Firmware frissítés" #: /home/micha/Develop/upebble/rockwork/FirmwareUpgradePage.qml:16 +<<<<<<< HEAD +msgid "A new firmware upgrade is available for your Pebble smarwatch." +msgstr "Egy új firmware frissítés érhető el a Pebble okosórájához" +======= msgid "A new firmware upgrade is available for your Pebble smartwatch." msgstr "" +>>>>>>> refs/heads/rockwork #: /home/micha/Develop/upebble/rockwork/FirmwareUpgradePage.qml:23 #, qt-format @@ -182,10 +190,6 @@ msgstr "" msgid "OK" msgstr "" -#: /home/micha/Develop/upebble/rockwork/ImportPackagePage.qml:7 -msgid "Import watchapp or watchface" -msgstr "" - #: /home/micha/Develop/upebble/rockwork/InfoPage.qml:31 #, qt-format msgid "Version %1" @@ -239,7 +243,7 @@ msgid "Loading..." msgstr "" #: /home/micha/Develop/upebble/rockwork/MainMenuPage.qml:15 -msgid "About" +msgid "Info" msgstr "" #: /home/micha/Develop/upebble/rockwork/MainMenuPage.qml:22 @@ -6,17 +6,29 @@ msgid "" msgstr "" "Project-Id-Version: upebble\n" +<<<<<<< HEAD +"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n" +"POT-Creation-Date: 2016-02-08 03:04+0100\n" +"PO-Revision-Date: 2016-02-02 06:06+0000\n" +"Last-Translator: Emanuele Antonio Faraone <emanueleant03@gmail.com>\n" +======= "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2016-02-14 23:39+0100\n" "PO-Revision-Date: 2016-02-15 12:21+0000\n" "Last-Translator: Marco Trevisan (Treviño) <mail@3v1n0.net>\n" +>>>>>>> refs/heads/rockwork "Language-Team: Italian <it@li.org>\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" +<<<<<<< HEAD +"X-Launchpad-Export-Date: 2016-02-08 05:41+0000\n" +"X-Generator: Launchpad (build 17908)\n" +======= "X-Launchpad-Export-Date: 2016-02-16 05:44+0000\n" "X-Generator: Launchpad (build 17925)\n" "Language: it\n" +>>>>>>> refs/heads/rockwork #: /home/micha/Develop/upebble/rockwork/AppSettingsPage.qml:13 msgid "App Settings" @@ -58,13 +70,17 @@ msgstr "Aggiungi Watchapp" msgid "Add new watchface" msgstr "Aggiungi Watchface" -#: /home/micha/Develop/upebble/rockwork/AppStorePage.qml:125 +#: /home/micha/Develop/upebble/rockwork/AppStorePage.qml:119 msgid "See all" msgstr "Mostra tutto" #: /home/micha/Develop/upebble/rockwork/DeveloperToolsPage.qml:9 msgid "Developer Tools" +<<<<<<< HEAD +msgstr "" +======= msgstr "Strumenti per sviluppatori" +>>>>>>> refs/heads/rockwork #: /home/micha/Develop/upebble/rockwork/DeveloperToolsPage.qml:28 #: /home/micha/Develop/upebble/rockwork/ScreenshotsPage.qml:11 @@ -74,31 +90,45 @@ msgstr "Screenshot" #: /home/micha/Develop/upebble/rockwork/DeveloperToolsPage.qml:35 #: /home/micha/Develop/upebble/rockwork/DeveloperToolsPage.qml:102 msgid "Report problem" +<<<<<<< HEAD +msgstr "" +======= msgstr "Riporta un problema" #: /home/micha/Develop/upebble/rockwork/DeveloperToolsPage.qml:42 msgid "Install app or watchface from file" msgstr "Installa app o watchface da file" +>>>>>>> refs/heads/rockwork #: /home/micha/Develop/upebble/rockwork/DeveloperToolsPage.qml:109 msgid "Preparing logs package..." +<<<<<<< HEAD +msgstr "" +======= msgstr "Preparazione del pacchetto di log..." +>>>>>>> refs/heads/rockwork #: /home/micha/Develop/upebble/rockwork/DeveloperToolsPage.qml:120 +<<<<<<< HEAD +#: /home/micha/Develop/upebble/rockwork/DeveloperToolsPage.qml:132 +msgid "rockworkd.log" +msgstr "" +======= msgid "pebble.log" msgstr "pebble.log" +>>>>>>> refs/heads/rockwork #: /home/micha/Develop/upebble/rockwork/DeveloperToolsPage.qml:127 msgid "Send rockworkd.log" -msgstr "Invia rockworkd.log" - -#: /home/micha/Develop/upebble/rockwork/DeveloperToolsPage.qml:132 -msgid "rockworkd.log" -msgstr "rockworkd.log" +msgstr "" #: /home/micha/Develop/upebble/rockwork/DeveloperToolsPage.qml:137 msgid "Send watch logs" +<<<<<<< HEAD +msgstr "" +======= msgstr "Invia log dell'orologio" +>>>>>>> refs/heads/rockwork #: /home/micha/Develop/upebble/rockwork/DeveloperToolsPage.qml:146 #: /home/micha/Develop/upebble/rockwork/HealthSettingsDialog.qml:110 @@ -112,9 +142,14 @@ msgid "Firmware upgrade" msgstr "Aggiornamento Firmware" #: /home/micha/Develop/upebble/rockwork/FirmwareUpgradePage.qml:16 +<<<<<<< HEAD +msgid "A new firmware upgrade is available for your Pebble smarwatch." +msgstr "Un nuovo aggiornamento del firmware è disponibile per il tuo Pebble." +======= msgid "A new firmware upgrade is available for your Pebble smartwatch." msgstr "" "Un nuovo aggiornamento firmware è disponibile per il tuo Smartwatch Pebble" +>>>>>>> refs/heads/rockwork #: /home/micha/Develop/upebble/rockwork/FirmwareUpgradePage.qml:23 #, qt-format @@ -145,68 +180,98 @@ msgstr "" #: /home/micha/Develop/upebble/rockwork/HealthSettingsDialog.qml:9 msgid "Health settings" +<<<<<<< HEAD +msgstr "" +======= msgstr "Impostazioni Health" +>>>>>>> refs/heads/rockwork #: /home/micha/Develop/upebble/rockwork/HealthSettingsDialog.qml:17 msgid "Health app enabled" +<<<<<<< HEAD +msgstr "" +======= msgstr "App Health attiva" +>>>>>>> refs/heads/rockwork #: /home/micha/Develop/upebble/rockwork/HealthSettingsDialog.qml:28 msgid "Female" -msgstr "Femmina" +msgstr "" #: /home/micha/Develop/upebble/rockwork/HealthSettingsDialog.qml:28 msgid "Male" -msgstr "Maschio" +msgstr "" #: /home/micha/Develop/upebble/rockwork/HealthSettingsDialog.qml:34 msgid "Age" -msgstr "Età" +msgstr "" #: /home/micha/Develop/upebble/rockwork/HealthSettingsDialog.qml:47 msgid "Height (cm)" -msgstr "Altezza (cm)" +msgstr "" #: /home/micha/Develop/upebble/rockwork/HealthSettingsDialog.qml:60 msgid "Weight" -msgstr "Peso" +msgstr "" #: /home/micha/Develop/upebble/rockwork/HealthSettingsDialog.qml:73 msgid "I want to be more active" +<<<<<<< HEAD +msgstr "" +======= msgstr "Vorrei essere più attivo" +>>>>>>> refs/heads/rockwork #: /home/micha/Develop/upebble/rockwork/HealthSettingsDialog.qml:84 msgid "I want to sleep more" -msgstr "Vorrei dormire di più" +msgstr "" #: /home/micha/Develop/upebble/rockwork/HealthSettingsDialog.qml:95 msgid "OK" +<<<<<<< HEAD +msgstr "" +======= msgstr "OK" #: /home/micha/Develop/upebble/rockwork/ImportPackagePage.qml:7 msgid "Import watchapp or watchface" msgstr "Importa una app o una watchface" +>>>>>>> refs/heads/rockwork #: /home/micha/Develop/upebble/rockwork/InfoPage.qml:31 #, qt-format msgid "Version %1" -msgstr "Versione %1" +msgstr "" #: /home/micha/Develop/upebble/rockwork/InfoPage.qml:40 +<<<<<<< HEAD +msgid "Contributors" +msgstr "" + +#: /home/micha/Develop/upebble/rockwork/InfoPage.qml:52 +======= +>>>>>>> refs/heads/rockwork msgid "Legal" -msgstr "Note legali" +msgstr "" #: /home/micha/Develop/upebble/rockwork/InfoPage.qml:62 msgid "" "This application is neither affiliated with nor endorsed by Pebble " "Technology Corp." msgstr "" +<<<<<<< HEAD +======= "Questa applicazione non è né affiliata né supportata da Pebble Techology " "Corp." +>>>>>>> refs/heads/rockwork #: /home/micha/Develop/upebble/rockwork/InfoPage.qml:67 msgid "Pebble is a trademark of Pebble Technology Corp." +<<<<<<< HEAD +msgstr "" +======= msgstr "Pebble è un marchio registrato di Pebble Technology Corp." +>>>>>>> refs/heads/rockwork #: /home/micha/Develop/upebble/rockwork/InstalledAppsPage.qml:9 msgid "Apps & Watchfaces" @@ -242,12 +307,17 @@ msgid "Loading..." msgstr "Caricamento..." #: /home/micha/Develop/upebble/rockwork/MainMenuPage.qml:15 +<<<<<<< HEAD +msgid "Info" +msgstr "" +======= msgid "About" msgstr "Informazioni su..." +>>>>>>> refs/heads/rockwork #: /home/micha/Develop/upebble/rockwork/MainMenuPage.qml:22 msgid "Developer tools" -msgstr "Strumenti per sviluppatori" +msgstr "" #: /home/micha/Develop/upebble/rockwork/MainMenuPage.qml:52 msgid "Manage notifications" @@ -264,7 +334,7 @@ msgstr "Gestisci le Watchfaces" #: /home/micha/Develop/upebble/rockwork/MainMenuPage.qml:75 #: /home/micha/Develop/upebble/rockwork/SettingsPage.qml:8 msgid "Settings" -msgstr "Impostazioni" +msgstr "" #: /home/micha/Develop/upebble/rockwork/MainMenuPage.qml:190 #: /home/micha/Develop/upebble/rockwork/PebblesPage.qml:36 @@ -293,7 +363,12 @@ msgstr "Apri Impostazioni" #: /home/micha/Develop/upebble/rockwork/MainMenuPage.qml:221 msgid "" "Your Pebble smartwatch is in factory mode and needs to be initialized." +<<<<<<< HEAD +msgstr "" +"Il tuo Pebble è in modalitá di fabbrica e sta per essere inizializzato" +======= msgstr "Il tuo Pebble è in modalità di fabbrica e deve essere inizializzato." +>>>>>>> refs/heads/rockwork #: /home/micha/Develop/upebble/rockwork/MainMenuPage.qml:230 msgid "Initialize Pebble" @@ -347,20 +422,28 @@ msgstr "Salva" #: /home/micha/Develop/upebble/rockwork/SettingsPage.qml:19 msgid "Distance Units" +<<<<<<< HEAD +msgstr "" +======= msgstr "Unità di misura distanza" +>>>>>>> refs/heads/rockwork #: /home/micha/Develop/upebble/rockwork/SettingsPage.qml:35 msgid "Metric" -msgstr "Metrica" +msgstr "" #: /home/micha/Develop/upebble/rockwork/SettingsPage.qml:48 msgid "Imperial" -msgstr "Imperiale" +msgstr "" #: /home/micha/Develop/upebble/rockwork/SettingsPage.qml:55 msgid "Calendar" -msgstr "Calendario" +msgstr "" #: /home/micha/Develop/upebble/rockwork/SettingsPage.qml:62 msgid "Sync calendar to timeline" +<<<<<<< HEAD +msgstr "" +======= msgstr "Sincronizza calendario con la timeline" +>>>>>>> refs/heads/rockwork @@ -6,17 +6,28 @@ msgid "" msgstr "" "Project-Id-Version: upebble\n" +<<<<<<< HEAD +"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n" +"POT-Creation-Date: 2016-02-08 03:04+0100\n" +"PO-Revision-Date: 2016-02-05 15:12+0000\n" +======= "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2016-02-14 23:39+0100\n" "PO-Revision-Date: 2016-02-16 15:41+0000\n" +>>>>>>> refs/heads/rockwork "Last-Translator: Vitor Loureiro <Unknown>\n" "Language-Team: Portuguese <pt@li.org>\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" +<<<<<<< HEAD +"X-Launchpad-Export-Date: 2016-02-08 05:41+0000\n" +"X-Generator: Launchpad (build 17908)\n" +======= "X-Launchpad-Export-Date: 2016-02-17 05:49+0000\n" "X-Generator: Launchpad (build 17925)\n" "Language: pt\n" +>>>>>>> refs/heads/rockwork #: /home/micha/Develop/upebble/rockwork/AppSettingsPage.qml:13 msgid "App Settings" @@ -58,13 +69,13 @@ msgstr "Adicionar nova watchapp" msgid "Add new watchface" msgstr "Adicionar nova watchface" -#: /home/micha/Develop/upebble/rockwork/AppStorePage.qml:125 +#: /home/micha/Develop/upebble/rockwork/AppStorePage.qml:119 msgid "See all" msgstr "Ver todos" #: /home/micha/Develop/upebble/rockwork/DeveloperToolsPage.qml:9 msgid "Developer Tools" -msgstr "Ferramentas de Desenvolvimento" +msgstr "" #: /home/micha/Develop/upebble/rockwork/DeveloperToolsPage.qml:28 #: /home/micha/Develop/upebble/rockwork/ScreenshotsPage.qml:11 @@ -74,31 +85,37 @@ msgstr "Capturas de ecrã" #: /home/micha/Develop/upebble/rockwork/DeveloperToolsPage.qml:35 #: /home/micha/Develop/upebble/rockwork/DeveloperToolsPage.qml:102 msgid "Report problem" +<<<<<<< HEAD +msgstr "" +======= msgstr "Reportar problema" #: /home/micha/Develop/upebble/rockwork/DeveloperToolsPage.qml:42 msgid "Install app or watchface from file" msgstr "Instalar app ou watchface de arquivo" +>>>>>>> refs/heads/rockwork #: /home/micha/Develop/upebble/rockwork/DeveloperToolsPage.qml:109 msgid "Preparing logs package..." msgstr "A preparar pacote de logs..." #: /home/micha/Develop/upebble/rockwork/DeveloperToolsPage.qml:120 +<<<<<<< HEAD +#: /home/micha/Develop/upebble/rockwork/DeveloperToolsPage.qml:132 +msgid "rockworkd.log" +msgstr "" +======= msgid "pebble.log" msgstr "pebble.log" +>>>>>>> refs/heads/rockwork #: /home/micha/Develop/upebble/rockwork/DeveloperToolsPage.qml:127 msgid "Send rockworkd.log" -msgstr "Enviar rockworkd.log" - -#: /home/micha/Develop/upebble/rockwork/DeveloperToolsPage.qml:132 -msgid "rockworkd.log" -msgstr "rockworkd.log" +msgstr "" #: /home/micha/Develop/upebble/rockwork/DeveloperToolsPage.qml:137 msgid "Send watch logs" -msgstr "Enviar logs do relógio" +msgstr "" #: /home/micha/Develop/upebble/rockwork/DeveloperToolsPage.qml:146 #: /home/micha/Develop/upebble/rockwork/HealthSettingsDialog.qml:110 @@ -112,7 +129,11 @@ msgid "Firmware upgrade" msgstr "Atualização do firmware" #: /home/micha/Develop/upebble/rockwork/FirmwareUpgradePage.qml:16 +<<<<<<< HEAD +msgid "A new firmware upgrade is available for your Pebble smarwatch." +======= msgid "A new firmware upgrade is available for your Pebble smartwatch." +>>>>>>> refs/heads/rockwork msgstr "" "Um novo upgrade de firmware está disponível para o seu Pebble smartwatch." @@ -153,48 +174,59 @@ msgstr "Aplicação Health ativada" #: /home/micha/Develop/upebble/rockwork/HealthSettingsDialog.qml:28 msgid "Female" -msgstr "Feminino" +msgstr "" #: /home/micha/Develop/upebble/rockwork/HealthSettingsDialog.qml:28 msgid "Male" -msgstr "Masculino" +msgstr "" #: /home/micha/Develop/upebble/rockwork/HealthSettingsDialog.qml:34 msgid "Age" -msgstr "Idade" +msgstr "" #: /home/micha/Develop/upebble/rockwork/HealthSettingsDialog.qml:47 msgid "Height (cm)" -msgstr "Altura (cm)" +msgstr "" #: /home/micha/Develop/upebble/rockwork/HealthSettingsDialog.qml:60 msgid "Weight" -msgstr "Peso" +msgstr "" #: /home/micha/Develop/upebble/rockwork/HealthSettingsDialog.qml:73 msgid "I want to be more active" -msgstr "Eu quero ser mais ativo" +msgstr "" #: /home/micha/Develop/upebble/rockwork/HealthSettingsDialog.qml:84 msgid "I want to sleep more" -msgstr "Eu quero dormir mais" +msgstr "" #: /home/micha/Develop/upebble/rockwork/HealthSettingsDialog.qml:95 msgid "OK" +<<<<<<< HEAD +msgstr "" +======= msgstr "OK" #: /home/micha/Develop/upebble/rockwork/ImportPackagePage.qml:7 msgid "Import watchapp or watchface" msgstr "Importar watchapp ou watchface" +>>>>>>> refs/heads/rockwork #: /home/micha/Develop/upebble/rockwork/InfoPage.qml:31 #, qt-format msgid "Version %1" -msgstr "Versão %1" +msgstr "" #: /home/micha/Develop/upebble/rockwork/InfoPage.qml:40 +<<<<<<< HEAD +msgid "Contributors" +msgstr "" + +#: /home/micha/Develop/upebble/rockwork/InfoPage.qml:52 +======= +>>>>>>> refs/heads/rockwork msgid "Legal" -msgstr "Legal" +msgstr "" #: /home/micha/Develop/upebble/rockwork/InfoPage.qml:62 msgid "" @@ -205,7 +237,7 @@ msgstr "" #: /home/micha/Develop/upebble/rockwork/InfoPage.qml:67 msgid "Pebble is a trademark of Pebble Technology Corp." -msgstr "Pebble é uma marca comercial da Pebble Technology Corp." +msgstr "" #: /home/micha/Develop/upebble/rockwork/InstalledAppsPage.qml:9 msgid "Apps & Watchfaces" @@ -241,12 +273,17 @@ msgid "Loading..." msgstr "A carregar..." #: /home/micha/Develop/upebble/rockwork/MainMenuPage.qml:15 +<<<<<<< HEAD +msgid "Info" +msgstr "" +======= msgid "About" msgstr "Acerca" +>>>>>>> refs/heads/rockwork #: /home/micha/Develop/upebble/rockwork/MainMenuPage.qml:22 msgid "Developer tools" -msgstr "Ferramentas do programador" +msgstr "" #: /home/micha/Develop/upebble/rockwork/MainMenuPage.qml:52 msgid "Manage notifications" @@ -263,7 +300,7 @@ msgstr "Gerir watchfaces" #: /home/micha/Develop/upebble/rockwork/MainMenuPage.qml:75 #: /home/micha/Develop/upebble/rockwork/SettingsPage.qml:8 msgid "Settings" -msgstr "Configurações" +msgstr "" #: /home/micha/Develop/upebble/rockwork/MainMenuPage.qml:190 #: /home/micha/Develop/upebble/rockwork/PebblesPage.qml:36 @@ -346,15 +383,15 @@ msgstr "Guardar" #: /home/micha/Develop/upebble/rockwork/SettingsPage.qml:19 msgid "Distance Units" -msgstr "Unidades de distância" +msgstr "" #: /home/micha/Develop/upebble/rockwork/SettingsPage.qml:35 msgid "Metric" -msgstr "Métrica" +msgstr "" #: /home/micha/Develop/upebble/rockwork/SettingsPage.qml:48 msgid "Imperial" -msgstr "Imperial" +msgstr "" #: /home/micha/Develop/upebble/rockwork/SettingsPage.qml:55 msgid "Calendar" diff --git a/po/rockwork.mzanetti.pot b/po/rockwork.mzanetti.pot index 6017fa8..a783b9a 100644 --- a/po/rockwork.mzanetti.pot +++ b/po/rockwork.mzanetti.pot @@ -8,7 +8,11 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" +<<<<<<< HEAD +"POT-Creation-Date: 2016-02-08 03:04+0100\n" +======= "POT-Creation-Date: 2016-02-14 23:39+0100\n" +>>>>>>> refs/heads/rockwork "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" @@ -57,7 +61,7 @@ msgstr "" msgid "Add new watchface" msgstr "" -#: /home/micha/Develop/upebble/rockwork/AppStorePage.qml:125 +#: /home/micha/Develop/upebble/rockwork/AppStorePage.qml:119 msgid "See all" msgstr "" @@ -75,26 +79,19 @@ msgstr "" msgid "Report problem" msgstr "" -#: /home/micha/Develop/upebble/rockwork/DeveloperToolsPage.qml:42 -msgid "Install app or watchface from file" -msgstr "" - #: /home/micha/Develop/upebble/rockwork/DeveloperToolsPage.qml:109 msgid "Preparing logs package..." msgstr "" #: /home/micha/Develop/upebble/rockwork/DeveloperToolsPage.qml:120 -msgid "pebble.log" +#: /home/micha/Develop/upebble/rockwork/DeveloperToolsPage.qml:132 +msgid "rockworkd.log" msgstr "" #: /home/micha/Develop/upebble/rockwork/DeveloperToolsPage.qml:127 msgid "Send rockworkd.log" msgstr "" -#: /home/micha/Develop/upebble/rockwork/DeveloperToolsPage.qml:132 -msgid "rockworkd.log" -msgstr "" - #: /home/micha/Develop/upebble/rockwork/DeveloperToolsPage.qml:137 msgid "Send watch logs" msgstr "" @@ -111,7 +108,7 @@ msgid "Firmware upgrade" msgstr "" #: /home/micha/Develop/upebble/rockwork/FirmwareUpgradePage.qml:16 -msgid "A new firmware upgrade is available for your Pebble smartwatch." +msgid "A new firmware upgrade is available for your Pebble smarwatch." msgstr "" #: /home/micha/Develop/upebble/rockwork/FirmwareUpgradePage.qml:23 @@ -179,10 +176,6 @@ msgstr "" msgid "OK" msgstr "" -#: /home/micha/Develop/upebble/rockwork/ImportPackagePage.qml:7 -msgid "Import watchapp or watchface" -msgstr "" - #: /home/micha/Develop/upebble/rockwork/InfoPage.qml:31 #, qt-format msgid "Version %1" @@ -236,7 +229,7 @@ msgid "Loading..." msgstr "" #: /home/micha/Develop/upebble/rockwork/MainMenuPage.qml:15 -msgid "About" +msgid "Info" msgstr "" #: /home/micha/Develop/upebble/rockwork/MainMenuPage.qml:22 @@ -6,17 +6,27 @@ msgid "" msgstr "" "Project-Id-Version: rockwork\n" +<<<<<<< HEAD +"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n" +"POT-Creation-Date: 2016-02-08 03:04+0100\n" +======= "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2016-02-14 23:39+0100\n" +>>>>>>> refs/heads/rockwork "PO-Revision-Date: 2016-01-23 13:33+0000\n" "Last-Translator: Eugene Marshal <Unknown>\n" "Language-Team: Russian <ru@li.org>\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" +<<<<<<< HEAD +"X-Launchpad-Export-Date: 2016-02-08 05:41+0000\n" +"X-Generator: Launchpad (build 17908)\n" +======= "X-Launchpad-Export-Date: 2016-02-15 05:44+0000\n" "X-Generator: Launchpad (build 17925)\n" "Language: ru\n" +>>>>>>> refs/heads/rockwork #: /home/micha/Develop/upebble/rockwork/AppSettingsPage.qml:13 msgid "App Settings" @@ -58,7 +68,7 @@ msgstr "Добавить приложение" msgid "Add new watchface" msgstr "Добавить циферблат" -#: /home/micha/Develop/upebble/rockwork/AppStorePage.qml:125 +#: /home/micha/Develop/upebble/rockwork/AppStorePage.qml:119 msgid "See all" msgstr "См. все" @@ -76,26 +86,19 @@ msgstr "Снимки экрана" msgid "Report problem" msgstr "" -#: /home/micha/Develop/upebble/rockwork/DeveloperToolsPage.qml:42 -msgid "Install app or watchface from file" -msgstr "" - #: /home/micha/Develop/upebble/rockwork/DeveloperToolsPage.qml:109 msgid "Preparing logs package..." msgstr "" #: /home/micha/Develop/upebble/rockwork/DeveloperToolsPage.qml:120 -msgid "pebble.log" +#: /home/micha/Develop/upebble/rockwork/DeveloperToolsPage.qml:132 +msgid "rockworkd.log" msgstr "" #: /home/micha/Develop/upebble/rockwork/DeveloperToolsPage.qml:127 msgid "Send rockworkd.log" msgstr "" -#: /home/micha/Develop/upebble/rockwork/DeveloperToolsPage.qml:132 -msgid "rockworkd.log" -msgstr "" - #: /home/micha/Develop/upebble/rockwork/DeveloperToolsPage.qml:137 msgid "Send watch logs" msgstr "" @@ -112,7 +115,7 @@ msgid "Firmware upgrade" msgstr "" #: /home/micha/Develop/upebble/rockwork/FirmwareUpgradePage.qml:16 -msgid "A new firmware upgrade is available for your Pebble smartwatch." +msgid "A new firmware upgrade is available for your Pebble smarwatch." msgstr "" #: /home/micha/Develop/upebble/rockwork/FirmwareUpgradePage.qml:23 @@ -180,10 +183,6 @@ msgstr "" msgid "OK" msgstr "" -#: /home/micha/Develop/upebble/rockwork/ImportPackagePage.qml:7 -msgid "Import watchapp or watchface" -msgstr "" - #: /home/micha/Develop/upebble/rockwork/InfoPage.qml:31 #, qt-format msgid "Version %1" @@ -237,7 +236,7 @@ msgid "Loading..." msgstr "" #: /home/micha/Develop/upebble/rockwork/MainMenuPage.qml:15 -msgid "About" +msgid "Info" msgstr "" #: /home/micha/Develop/upebble/rockwork/MainMenuPage.qml:22 diff --git a/po/template.pot b/po/template.pot index 6017fa8..a783b9a 100644 --- a/po/template.pot +++ b/po/template.pot @@ -8,7 +8,11 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" +<<<<<<< HEAD +"POT-Creation-Date: 2016-02-08 03:04+0100\n" +======= "POT-Creation-Date: 2016-02-14 23:39+0100\n" +>>>>>>> refs/heads/rockwork "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" @@ -57,7 +61,7 @@ msgstr "" msgid "Add new watchface" msgstr "" -#: /home/micha/Develop/upebble/rockwork/AppStorePage.qml:125 +#: /home/micha/Develop/upebble/rockwork/AppStorePage.qml:119 msgid "See all" msgstr "" @@ -75,26 +79,19 @@ msgstr "" msgid "Report problem" msgstr "" -#: /home/micha/Develop/upebble/rockwork/DeveloperToolsPage.qml:42 -msgid "Install app or watchface from file" -msgstr "" - #: /home/micha/Develop/upebble/rockwork/DeveloperToolsPage.qml:109 msgid "Preparing logs package..." msgstr "" #: /home/micha/Develop/upebble/rockwork/DeveloperToolsPage.qml:120 -msgid "pebble.log" +#: /home/micha/Develop/upebble/rockwork/DeveloperToolsPage.qml:132 +msgid "rockworkd.log" msgstr "" #: /home/micha/Develop/upebble/rockwork/DeveloperToolsPage.qml:127 msgid "Send rockworkd.log" msgstr "" -#: /home/micha/Develop/upebble/rockwork/DeveloperToolsPage.qml:132 -msgid "rockworkd.log" -msgstr "" - #: /home/micha/Develop/upebble/rockwork/DeveloperToolsPage.qml:137 msgid "Send watch logs" msgstr "" @@ -111,7 +108,7 @@ msgid "Firmware upgrade" msgstr "" #: /home/micha/Develop/upebble/rockwork/FirmwareUpgradePage.qml:16 -msgid "A new firmware upgrade is available for your Pebble smartwatch." +msgid "A new firmware upgrade is available for your Pebble smarwatch." msgstr "" #: /home/micha/Develop/upebble/rockwork/FirmwareUpgradePage.qml:23 @@ -179,10 +176,6 @@ msgstr "" msgid "OK" msgstr "" -#: /home/micha/Develop/upebble/rockwork/ImportPackagePage.qml:7 -msgid "Import watchapp or watchface" -msgstr "" - #: /home/micha/Develop/upebble/rockwork/InfoPage.qml:31 #, qt-format msgid "Version %1" @@ -236,7 +229,7 @@ msgid "Loading..." msgstr "" #: /home/micha/Develop/upebble/rockwork/MainMenuPage.qml:15 -msgid "About" +msgid "Info" msgstr "" #: /home/micha/Develop/upebble/rockwork/MainMenuPage.qml:22 diff --git a/rockpool.pro b/rockpool.pro new file mode 100644 index 0000000..d38aaf6 --- /dev/null +++ b/rockpool.pro @@ -0,0 +1,14 @@ +TEMPLATE = subdirs +SUBDIRS = rockwork rockworkd +OTHER_FILES += \ + README.md \ + rpm/rockpool.spec \ + rpm/rockpool.yaml \ + rpm/rockpool.changes + +# TODO: +# Merge in latest changes from rockwork release +# Migrate VoiceCallManager over to replace callchannelobserver +# Dismiss notifications +# Integrate calendar +# Alarms? diff --git a/rockpool.pro.user b/rockpool.pro.user new file mode 100644 index 0000000..a24f009 --- /dev/null +++ b/rockpool.pro.user @@ -0,0 +1,407 @@ +<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE QtCreatorProject>
+<!-- Written by QtCreator 3.5.0, 2016-02-17T01:14:22. -->
+<qtcreator>
+ <data>
+ <variable>EnvironmentId</variable>
+ <value type="QByteArray">{bfe4fced-130c-4a1d-b5dd-4ef663a59e13}</value>
+ </data>
+ <data>
+ <variable>ProjectExplorer.Project.ActiveTarget</variable>
+ <value type="int">0</value>
+ </data>
+ <data>
+ <variable>ProjectExplorer.Project.EditorSettings</variable>
+ <valuemap type="QVariantMap">
+ <value type="bool" key="EditorConfiguration.AutoIndent">true</value>
+ <value type="bool" key="EditorConfiguration.AutoSpacesForTabs">false</value>
+ <value type="bool" key="EditorConfiguration.CamelCaseNavigation">true</value>
+ <valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.0">
+ <value type="QString" key="language">Cpp</value>
+ <valuemap type="QVariantMap" key="value">
+ <value type="QByteArray" key="CurrentPreferences">CppGlobal</value>
+ </valuemap>
+ </valuemap>
+ <valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.1">
+ <value type="QString" key="language">QmlJS</value>
+ <valuemap type="QVariantMap" key="value">
+ <value type="QByteArray" key="CurrentPreferences">QmlJSGlobal</value>
+ </valuemap>
+ </valuemap>
+ <value type="int" key="EditorConfiguration.CodeStyle.Count">2</value>
+ <value type="QByteArray" key="EditorConfiguration.Codec">UTF-8</value>
+ <value type="bool" key="EditorConfiguration.ConstrainTooltips">false</value>
+ <value type="int" key="EditorConfiguration.IndentSize">4</value>
+ <value type="bool" key="EditorConfiguration.KeyboardTooltips">false</value>
+ <value type="int" key="EditorConfiguration.MarginColumn">80</value>
+ <value type="bool" key="EditorConfiguration.MouseHiding">true</value>
+ <value type="bool" key="EditorConfiguration.MouseNavigation">true</value>
+ <value type="int" key="EditorConfiguration.PaddingMode">1</value>
+ <value type="bool" key="EditorConfiguration.ScrollWheelZooming">true</value>
+ <value type="bool" key="EditorConfiguration.ShowMargin">false</value>
+ <value type="int" key="EditorConfiguration.SmartBackspaceBehavior">0</value>
+ <value type="bool" key="EditorConfiguration.SpacesForTabs">true</value>
+ <value type="int" key="EditorConfiguration.TabKeyBehavior">0</value>
+ <value type="int" key="EditorConfiguration.TabSize">8</value>
+ <value type="bool" key="EditorConfiguration.UseGlobal">true</value>
+ <value type="int" key="EditorConfiguration.Utf8BomBehavior">1</value>
+ <value type="bool" key="EditorConfiguration.addFinalNewLine">true</value>
+ <value type="bool" key="EditorConfiguration.cleanIndentation">true</value>
+ <value type="bool" key="EditorConfiguration.cleanWhitespace">true</value>
+ <value type="bool" key="EditorConfiguration.inEntireDocument">false</value>
+ </valuemap>
+ </data>
+ <data>
+ <variable>ProjectExplorer.Project.PluginSettings</variable>
+ <valuemap type="QVariantMap"/>
+ </data>
+ <data>
+ <variable>ProjectExplorer.Project.Target.0</variable>
+ <valuemap type="QVariantMap">
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">MerSDK-SailfishOS-armv7hl</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">MerSDK-SailfishOS-armv7hl</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">{a1087e50-1b78-48e9-a186-a57cbfa9e4dd}</value>
+ <value type="int" key="ProjectExplorer.Target.ActiveBuildConfiguration">1</value>
+ <value type="int" key="ProjectExplorer.Target.ActiveDeployConfiguration">2</value>
+ <value type="int" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value>
+ <valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.0">
+ <value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">D:/Git/build-rockpool-MerSDK_SailfishOS_armv7hl-Debug</value>
+ <valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
+ <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
+ <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Start SDK</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Mer.MerSdkStartStep</value>
+ </valuemap>
+ <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
+ <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">qmake</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
+ <value type="bool" key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibrary">true</value>
+ <value type="bool" key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibraryAuto">false</value>
+ <value type="QString" key="QtProjectManager.QMakeBuildStep.QMakeArguments"></value>
+ <value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
+ <value type="bool" key="QtProjectManager.QMakeBuildStep.SeparateDebugInfo">false</value>
+ <value type="bool" key="QtProjectManager.QMakeBuildStep.UseQtQuickCompiler">false</value>
+ </valuemap>
+ <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.2">
+ <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
+ <valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments">
+ <value type="QString">-w</value>
+ <value type="QString">-r</value>
+ </valuelist>
+ <value type="bool" key="Qt4ProjectManager.MakeStep.Clean">false</value>
+ <value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments"></value>
+ <value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
+ </valuemap>
+ <value type="int" key="ProjectExplorer.BuildStepList.StepsCount">3</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
+ </valuemap>
+ <valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
+ <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
+ <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Start SDK</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Mer.MerSdkStartStep</value>
+ </valuemap>
+ <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
+ <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
+ <valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments">
+ <value type="QString">-w</value>
+ <value type="QString">-r</value>
+ </valuelist>
+ <value type="bool" key="Qt4ProjectManager.MakeStep.Clean">true</value>
+ <value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
+ <value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
+ </valuemap>
+ <value type="int" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
+ </valuemap>
+ <value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
+ <value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
+ <valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Debug</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
+ <value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">2</value>
+ <value type="bool" key="Qt4ProjectManager.Qt4BuildConfiguration.UseShadowBuild">true</value>
+ </valuemap>
+ <valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.1">
+ <value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">D:/Git/build-rockpool-MerSDK_SailfishOS_armv7hl-Release</value>
+ <valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
+ <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
+ <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Start SDK</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Mer.MerSdkStartStep</value>
+ </valuemap>
+ <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
+ <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">qmake</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
+ <value type="bool" key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibrary">false</value>
+ <value type="bool" key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibraryAuto">true</value>
+ <value type="QString" key="QtProjectManager.QMakeBuildStep.QMakeArguments"></value>
+ <value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
+ <value type="bool" key="QtProjectManager.QMakeBuildStep.SeparateDebugInfo">false</value>
+ <value type="bool" key="QtProjectManager.QMakeBuildStep.UseQtQuickCompiler">false</value>
+ </valuemap>
+ <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.2">
+ <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
+ <valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments">
+ <value type="QString">-w</value>
+ <value type="QString">-r</value>
+ </valuelist>
+ <value type="bool" key="Qt4ProjectManager.MakeStep.Clean">false</value>
+ <value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments"></value>
+ <value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
+ </valuemap>
+ <value type="int" key="ProjectExplorer.BuildStepList.StepsCount">3</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
+ </valuemap>
+ <valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
+ <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
+ <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Start SDK</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Mer.MerSdkStartStep</value>
+ </valuemap>
+ <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
+ <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
+ <valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments">
+ <value type="QString">-w</value>
+ <value type="QString">-r</value>
+ </valuelist>
+ <value type="bool" key="Qt4ProjectManager.MakeStep.Clean">true</value>
+ <value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
+ <value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
+ </valuemap>
+ <value type="int" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
+ </valuemap>
+ <value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
+ <value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
+ <valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Release</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
+ <value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">0</value>
+ <value type="bool" key="Qt4ProjectManager.Qt4BuildConfiguration.UseShadowBuild">true</value>
+ </valuemap>
+ <value type="int" key="ProjectExplorer.Target.BuildConfigurationCount">2</value>
+ <valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.0">
+ <valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
+ <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
+ <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">RPM</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QmakeProjectManager.MerRpmBuildStep</value>
+ </valuemap>
+ <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
+ <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">RPM Validation</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QmakeProjectManager.MerRpmValidationStep</value>
+ </valuemap>
+ <value type="int" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deploy</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
+ </valuemap>
+ <value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deploy By Building An RPM Package</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QmakeProjectManager.MerMb2RpmBuildConfiguration</value>
+ </valuemap>
+ <valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.1">
+ <valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
+ <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
+ <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Prepare Target</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QmakeProjectManager.MerPrepareTargetStep</value>
+ </valuemap>
+ <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
+ <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Rsync</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QmakeProjectManager.MerRsyncDeployStep</value>
+ </valuemap>
+ <value type="int" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deploy</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
+ </valuemap>
+ <value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deploy By Copying Binaries</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QmakeProjectManager.MerRSyncDeployConfiguration</value>
+ </valuemap>
+ <valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.2">
+ <valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
+ <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
+ <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Prepare Target</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QmakeProjectManager.MerPrepareTargetStep</value>
+ </valuemap>
+ <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
+ <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">RPM</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QmakeProjectManager.MerRpmDeployStep</value>
+ </valuemap>
+ <value type="int" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deploy</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
+ </valuemap>
+ <value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deploy As RPM Package</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QmakeProjectManager.MerRpmDeployConfiguration</value>
+ </valuemap>
+ <value type="int" key="ProjectExplorer.Target.DeployConfigurationCount">3</value>
+ <valuemap type="QVariantMap" key="ProjectExplorer.Target.PluginSettings"/>
+ <valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.0">
+ <valuelist type="QVariantList" key="Analyzer.Valgrind.AddedSuppressionFiles"/>
+ <value type="bool" key="Analyzer.Valgrind.Callgrind.CollectBusEvents">false</value>
+ <value type="bool" key="Analyzer.Valgrind.Callgrind.CollectSystime">false</value>
+ <value type="bool" key="Analyzer.Valgrind.Callgrind.EnableBranchSim">false</value>
+ <value type="bool" key="Analyzer.Valgrind.Callgrind.EnableCacheSim">false</value>
+ <value type="bool" key="Analyzer.Valgrind.Callgrind.EnableEventToolTips">true</value>
+ <value type="double" key="Analyzer.Valgrind.Callgrind.MinimumCostRatio">0.01</value>
+ <value type="double" key="Analyzer.Valgrind.Callgrind.VisualisationMinimumCostRatio">10</value>
+ <value type="bool" key="Analyzer.Valgrind.FilterExternalIssues">true</value>
+ <value type="int" key="Analyzer.Valgrind.LeakCheckOnFinish">1</value>
+ <value type="int" key="Analyzer.Valgrind.NumCallers">25</value>
+ <valuelist type="QVariantList" key="Analyzer.Valgrind.RemovedSuppressionFiles"/>
+ <value type="int" key="Analyzer.Valgrind.SelfModifyingCodeDetection">1</value>
+ <value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
+ <value type="bool" key="Analyzer.Valgrind.ShowReachable">false</value>
+ <value type="bool" key="Analyzer.Valgrind.TrackOrigins">true</value>
+ <value type="QString" key="Analyzer.Valgrind.ValgrindExecutable">valgrind</value>
+ <valuelist type="QVariantList" key="Analyzer.Valgrind.VisibleErrorKinds">
+ <value type="int">0</value>
+ <value type="int">1</value>
+ <value type="int">2</value>
+ <value type="int">3</value>
+ <value type="int">4</value>
+ <value type="int">5</value>
+ <value type="int">6</value>
+ <value type="int">7</value>
+ <value type="int">8</value>
+ <value type="int">9</value>
+ <value type="int">10</value>
+ <value type="int">11</value>
+ <value type="int">12</value>
+ <value type="int">13</value>
+ <value type="int">14</value>
+ </valuelist>
+ <value type="int" key="PE.EnvironmentAspect.Base">1</value>
+ <valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">rockpool (on Remote Device)</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QmakeProjectManager.MerRunConfiguration:rockpool</value>
+ <valuelist type="QVariantList" key="Qt4ProjectManager.MaemoRunConfiguration.Arguments"/>
+ <value type="QString" key="Qt4ProjectManager.MaemoRunConfiguration.TargetName">rockpool</value>
+ <value type="QString" key="RemoteLinux.RunConfig.AlternateRemoteExecutable"></value>
+ <value type="bool" key="RemoteLinux.RunConfig.UseAlternateRemoteExecutable">false</value>
+ <value type="QString" key="RemoteLinux.RunConfig.WorkingDirectory"></value>
+ <value type="uint" key="RunConfiguration.QmlDebugServerPort">3768</value>
+ <value type="bool" key="RunConfiguration.UseCppDebugger">false</value>
+ <value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
+ <value type="bool" key="RunConfiguration.UseMultiProcess">false</value>
+ <value type="bool" key="RunConfiguration.UseQmlDebugger">false</value>
+ <value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
+ </valuemap>
+ <valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.1">
+ <valuelist type="QVariantList" key="Analyzer.Valgrind.AddedSuppressionFiles"/>
+ <value type="bool" key="Analyzer.Valgrind.Callgrind.CollectBusEvents">false</value>
+ <value type="bool" key="Analyzer.Valgrind.Callgrind.CollectSystime">false</value>
+ <value type="bool" key="Analyzer.Valgrind.Callgrind.EnableBranchSim">false</value>
+ <value type="bool" key="Analyzer.Valgrind.Callgrind.EnableCacheSim">false</value>
+ <value type="bool" key="Analyzer.Valgrind.Callgrind.EnableEventToolTips">true</value>
+ <value type="double" key="Analyzer.Valgrind.Callgrind.MinimumCostRatio">0.01</value>
+ <value type="double" key="Analyzer.Valgrind.Callgrind.VisualisationMinimumCostRatio">10</value>
+ <value type="bool" key="Analyzer.Valgrind.FilterExternalIssues">true</value>
+ <value type="int" key="Analyzer.Valgrind.LeakCheckOnFinish">1</value>
+ <value type="int" key="Analyzer.Valgrind.NumCallers">25</value>
+ <valuelist type="QVariantList" key="Analyzer.Valgrind.RemovedSuppressionFiles"/>
+ <value type="int" key="Analyzer.Valgrind.SelfModifyingCodeDetection">1</value>
+ <value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
+ <value type="bool" key="Analyzer.Valgrind.ShowReachable">false</value>
+ <value type="bool" key="Analyzer.Valgrind.TrackOrigins">true</value>
+ <value type="QString" key="Analyzer.Valgrind.ValgrindExecutable">valgrind</value>
+ <valuelist type="QVariantList" key="Analyzer.Valgrind.VisibleErrorKinds">
+ <value type="int">0</value>
+ <value type="int">1</value>
+ <value type="int">2</value>
+ <value type="int">3</value>
+ <value type="int">4</value>
+ <value type="int">5</value>
+ <value type="int">6</value>
+ <value type="int">7</value>
+ <value type="int">8</value>
+ <value type="int">9</value>
+ <value type="int">10</value>
+ <value type="int">11</value>
+ <value type="int">12</value>
+ <value type="int">13</value>
+ <value type="int">14</value>
+ </valuelist>
+ <value type="int" key="PE.EnvironmentAspect.Base">1</value>
+ <valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">rockpoold (on Remote Device)</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QmakeProjectManager.MerRunConfiguration:rockpoold</value>
+ <valuelist type="QVariantList" key="Qt4ProjectManager.MaemoRunConfiguration.Arguments"/>
+ <value type="QString" key="Qt4ProjectManager.MaemoRunConfiguration.TargetName">rockpoold</value>
+ <value type="QString" key="RemoteLinux.RunConfig.AlternateRemoteExecutable"></value>
+ <value type="bool" key="RemoteLinux.RunConfig.UseAlternateRemoteExecutable">false</value>
+ <value type="QString" key="RemoteLinux.RunConfig.WorkingDirectory"></value>
+ <value type="uint" key="RunConfiguration.QmlDebugServerPort">3768</value>
+ <value type="bool" key="RunConfiguration.UseCppDebugger">false</value>
+ <value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
+ <value type="bool" key="RunConfiguration.UseMultiProcess">true</value>
+ <value type="bool" key="RunConfiguration.UseQmlDebugger">false</value>
+ <value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
+ </valuemap>
+ <value type="int" key="ProjectExplorer.Target.RunConfigurationCount">2</value>
+ </valuemap>
+ </data>
+ <data>
+ <variable>ProjectExplorer.Project.TargetCount</variable>
+ <value type="int">1</value>
+ </data>
+ <data>
+ <variable>ProjectExplorer.Project.Updater.FileVersion</variable>
+ <value type="int">18</value>
+ </data>
+ <data>
+ <variable>Version</variable>
+ <value type="int">18</value>
+ </data>
+</qtcreator>
diff --git a/rockwork.pro.user b/rockwork.pro.user new file mode 100644 index 0000000..b336876 --- /dev/null +++ b/rockwork.pro.user @@ -0,0 +1,407 @@ +<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE QtCreatorProject>
+<!-- Written by QtCreator 3.5.0, 2016-02-10T00:15:52. -->
+<qtcreator>
+ <data>
+ <variable>EnvironmentId</variable>
+ <value type="QByteArray">{bfe4fced-130c-4a1d-b5dd-4ef663a59e13}</value>
+ </data>
+ <data>
+ <variable>ProjectExplorer.Project.ActiveTarget</variable>
+ <value type="int">0</value>
+ </data>
+ <data>
+ <variable>ProjectExplorer.Project.EditorSettings</variable>
+ <valuemap type="QVariantMap">
+ <value type="bool" key="EditorConfiguration.AutoIndent">true</value>
+ <value type="bool" key="EditorConfiguration.AutoSpacesForTabs">false</value>
+ <value type="bool" key="EditorConfiguration.CamelCaseNavigation">true</value>
+ <valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.0">
+ <value type="QString" key="language">Cpp</value>
+ <valuemap type="QVariantMap" key="value">
+ <value type="QByteArray" key="CurrentPreferences">CppGlobal</value>
+ </valuemap>
+ </valuemap>
+ <valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.1">
+ <value type="QString" key="language">QmlJS</value>
+ <valuemap type="QVariantMap" key="value">
+ <value type="QByteArray" key="CurrentPreferences">QmlJSGlobal</value>
+ </valuemap>
+ </valuemap>
+ <value type="int" key="EditorConfiguration.CodeStyle.Count">2</value>
+ <value type="QByteArray" key="EditorConfiguration.Codec">UTF-8</value>
+ <value type="bool" key="EditorConfiguration.ConstrainTooltips">false</value>
+ <value type="int" key="EditorConfiguration.IndentSize">4</value>
+ <value type="bool" key="EditorConfiguration.KeyboardTooltips">false</value>
+ <value type="int" key="EditorConfiguration.MarginColumn">80</value>
+ <value type="bool" key="EditorConfiguration.MouseHiding">true</value>
+ <value type="bool" key="EditorConfiguration.MouseNavigation">true</value>
+ <value type="int" key="EditorConfiguration.PaddingMode">1</value>
+ <value type="bool" key="EditorConfiguration.ScrollWheelZooming">true</value>
+ <value type="bool" key="EditorConfiguration.ShowMargin">false</value>
+ <value type="int" key="EditorConfiguration.SmartBackspaceBehavior">0</value>
+ <value type="bool" key="EditorConfiguration.SpacesForTabs">true</value>
+ <value type="int" key="EditorConfiguration.TabKeyBehavior">0</value>
+ <value type="int" key="EditorConfiguration.TabSize">8</value>
+ <value type="bool" key="EditorConfiguration.UseGlobal">true</value>
+ <value type="int" key="EditorConfiguration.Utf8BomBehavior">1</value>
+ <value type="bool" key="EditorConfiguration.addFinalNewLine">true</value>
+ <value type="bool" key="EditorConfiguration.cleanIndentation">true</value>
+ <value type="bool" key="EditorConfiguration.cleanWhitespace">true</value>
+ <value type="bool" key="EditorConfiguration.inEntireDocument">false</value>
+ </valuemap>
+ </data>
+ <data>
+ <variable>ProjectExplorer.Project.PluginSettings</variable>
+ <valuemap type="QVariantMap"/>
+ </data>
+ <data>
+ <variable>ProjectExplorer.Project.Target.0</variable>
+ <valuemap type="QVariantMap">
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">MerSDK-SailfishOS-armv7hl</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">MerSDK-SailfishOS-armv7hl</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">{a1087e50-1b78-48e9-a186-a57cbfa9e4dd}</value>
+ <value type="int" key="ProjectExplorer.Target.ActiveBuildConfiguration">0</value>
+ <value type="int" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>
+ <value type="int" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value>
+ <valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.0">
+ <value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">D:/Git/build-rockwork-MerSDK_SailfishOS_armv7hl-Debug</value>
+ <valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
+ <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
+ <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Start SDK</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Mer.MerSdkStartStep</value>
+ </valuemap>
+ <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
+ <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">qmake</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
+ <value type="bool" key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibrary">true</value>
+ <value type="bool" key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibraryAuto">false</value>
+ <value type="QString" key="QtProjectManager.QMakeBuildStep.QMakeArguments"></value>
+ <value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
+ <value type="bool" key="QtProjectManager.QMakeBuildStep.SeparateDebugInfo">false</value>
+ <value type="bool" key="QtProjectManager.QMakeBuildStep.UseQtQuickCompiler">false</value>
+ </valuemap>
+ <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.2">
+ <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
+ <valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments">
+ <value type="QString">-w</value>
+ <value type="QString">-r</value>
+ </valuelist>
+ <value type="bool" key="Qt4ProjectManager.MakeStep.Clean">false</value>
+ <value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments"></value>
+ <value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
+ </valuemap>
+ <value type="int" key="ProjectExplorer.BuildStepList.StepsCount">3</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
+ </valuemap>
+ <valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
+ <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
+ <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Start SDK</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Mer.MerSdkStartStep</value>
+ </valuemap>
+ <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
+ <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
+ <valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments">
+ <value type="QString">-w</value>
+ <value type="QString">-r</value>
+ </valuelist>
+ <value type="bool" key="Qt4ProjectManager.MakeStep.Clean">true</value>
+ <value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
+ <value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
+ </valuemap>
+ <value type="int" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
+ </valuemap>
+ <value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
+ <value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
+ <valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Debug</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
+ <value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">2</value>
+ <value type="bool" key="Qt4ProjectManager.Qt4BuildConfiguration.UseShadowBuild">true</value>
+ </valuemap>
+ <valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.1">
+ <value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">D:/Git/build-rockwork-MerSDK_SailfishOS_armv7hl-Release</value>
+ <valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
+ <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
+ <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Start SDK</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Mer.MerSdkStartStep</value>
+ </valuemap>
+ <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
+ <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">qmake</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
+ <value type="bool" key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibrary">false</value>
+ <value type="bool" key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibraryAuto">true</value>
+ <value type="QString" key="QtProjectManager.QMakeBuildStep.QMakeArguments"></value>
+ <value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
+ <value type="bool" key="QtProjectManager.QMakeBuildStep.SeparateDebugInfo">false</value>
+ <value type="bool" key="QtProjectManager.QMakeBuildStep.UseQtQuickCompiler">false</value>
+ </valuemap>
+ <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.2">
+ <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
+ <valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments">
+ <value type="QString">-w</value>
+ <value type="QString">-r</value>
+ </valuelist>
+ <value type="bool" key="Qt4ProjectManager.MakeStep.Clean">false</value>
+ <value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments"></value>
+ <value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
+ </valuemap>
+ <value type="int" key="ProjectExplorer.BuildStepList.StepsCount">3</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
+ </valuemap>
+ <valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
+ <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
+ <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Start SDK</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Mer.MerSdkStartStep</value>
+ </valuemap>
+ <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
+ <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
+ <valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments">
+ <value type="QString">-w</value>
+ <value type="QString">-r</value>
+ </valuelist>
+ <value type="bool" key="Qt4ProjectManager.MakeStep.Clean">true</value>
+ <value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
+ <value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
+ </valuemap>
+ <value type="int" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
+ </valuemap>
+ <value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
+ <value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
+ <valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Release</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
+ <value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">0</value>
+ <value type="bool" key="Qt4ProjectManager.Qt4BuildConfiguration.UseShadowBuild">true</value>
+ </valuemap>
+ <value type="int" key="ProjectExplorer.Target.BuildConfigurationCount">2</value>
+ <valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.0">
+ <valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
+ <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
+ <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">RPM</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QmakeProjectManager.MerRpmBuildStep</value>
+ </valuemap>
+ <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
+ <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">RPM Validation</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QmakeProjectManager.MerRpmValidationStep</value>
+ </valuemap>
+ <value type="int" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deploy</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
+ </valuemap>
+ <value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deploy By Building An RPM Package</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QmakeProjectManager.MerMb2RpmBuildConfiguration</value>
+ </valuemap>
+ <valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.1">
+ <valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
+ <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
+ <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Prepare Target</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QmakeProjectManager.MerPrepareTargetStep</value>
+ </valuemap>
+ <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
+ <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Rsync</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QmakeProjectManager.MerRsyncDeployStep</value>
+ </valuemap>
+ <value type="int" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deploy</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
+ </valuemap>
+ <value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deploy By Copying Binaries</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QmakeProjectManager.MerRSyncDeployConfiguration</value>
+ </valuemap>
+ <valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.2">
+ <valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
+ <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
+ <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Prepare Target</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QmakeProjectManager.MerPrepareTargetStep</value>
+ </valuemap>
+ <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
+ <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">RPM</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QmakeProjectManager.MerRpmDeployStep</value>
+ </valuemap>
+ <value type="int" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deploy</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
+ </valuemap>
+ <value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deploy As RPM Package</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QmakeProjectManager.MerRpmDeployConfiguration</value>
+ </valuemap>
+ <value type="int" key="ProjectExplorer.Target.DeployConfigurationCount">3</value>
+ <valuemap type="QVariantMap" key="ProjectExplorer.Target.PluginSettings"/>
+ <valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.0">
+ <valuelist type="QVariantList" key="Analyzer.Valgrind.AddedSuppressionFiles"/>
+ <value type="bool" key="Analyzer.Valgrind.Callgrind.CollectBusEvents">false</value>
+ <value type="bool" key="Analyzer.Valgrind.Callgrind.CollectSystime">false</value>
+ <value type="bool" key="Analyzer.Valgrind.Callgrind.EnableBranchSim">false</value>
+ <value type="bool" key="Analyzer.Valgrind.Callgrind.EnableCacheSim">false</value>
+ <value type="bool" key="Analyzer.Valgrind.Callgrind.EnableEventToolTips">true</value>
+ <value type="double" key="Analyzer.Valgrind.Callgrind.MinimumCostRatio">0.01</value>
+ <value type="double" key="Analyzer.Valgrind.Callgrind.VisualisationMinimumCostRatio">10</value>
+ <value type="bool" key="Analyzer.Valgrind.FilterExternalIssues">true</value>
+ <value type="int" key="Analyzer.Valgrind.LeakCheckOnFinish">1</value>
+ <value type="int" key="Analyzer.Valgrind.NumCallers">25</value>
+ <valuelist type="QVariantList" key="Analyzer.Valgrind.RemovedSuppressionFiles"/>
+ <value type="int" key="Analyzer.Valgrind.SelfModifyingCodeDetection">1</value>
+ <value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
+ <value type="bool" key="Analyzer.Valgrind.ShowReachable">false</value>
+ <value type="bool" key="Analyzer.Valgrind.TrackOrigins">true</value>
+ <value type="QString" key="Analyzer.Valgrind.ValgrindExecutable">valgrind</value>
+ <valuelist type="QVariantList" key="Analyzer.Valgrind.VisibleErrorKinds">
+ <value type="int">0</value>
+ <value type="int">1</value>
+ <value type="int">2</value>
+ <value type="int">3</value>
+ <value type="int">4</value>
+ <value type="int">5</value>
+ <value type="int">6</value>
+ <value type="int">7</value>
+ <value type="int">8</value>
+ <value type="int">9</value>
+ <value type="int">10</value>
+ <value type="int">11</value>
+ <value type="int">12</value>
+ <value type="int">13</value>
+ <value type="int">14</value>
+ </valuelist>
+ <value type="int" key="PE.EnvironmentAspect.Base">1</value>
+ <valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">rockworkd (on Remote Device)</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QmakeProjectManager.MerRunConfiguration:rockworkd</value>
+ <valuelist type="QVariantList" key="Qt4ProjectManager.MaemoRunConfiguration.Arguments"/>
+ <value type="QString" key="Qt4ProjectManager.MaemoRunConfiguration.TargetName">rockworkd</value>
+ <value type="QString" key="RemoteLinux.RunConfig.AlternateRemoteExecutable"></value>
+ <value type="bool" key="RemoteLinux.RunConfig.UseAlternateRemoteExecutable">false</value>
+ <value type="QString" key="RemoteLinux.RunConfig.WorkingDirectory"></value>
+ <value type="uint" key="RunConfiguration.QmlDebugServerPort">3768</value>
+ <value type="bool" key="RunConfiguration.UseCppDebugger">false</value>
+ <value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
+ <value type="bool" key="RunConfiguration.UseMultiProcess">false</value>
+ <value type="bool" key="RunConfiguration.UseQmlDebugger">false</value>
+ <value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
+ </valuemap>
+ <valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.1">
+ <valuelist type="QVariantList" key="Analyzer.Valgrind.AddedSuppressionFiles"/>
+ <value type="bool" key="Analyzer.Valgrind.Callgrind.CollectBusEvents">false</value>
+ <value type="bool" key="Analyzer.Valgrind.Callgrind.CollectSystime">false</value>
+ <value type="bool" key="Analyzer.Valgrind.Callgrind.EnableBranchSim">false</value>
+ <value type="bool" key="Analyzer.Valgrind.Callgrind.EnableCacheSim">false</value>
+ <value type="bool" key="Analyzer.Valgrind.Callgrind.EnableEventToolTips">true</value>
+ <value type="double" key="Analyzer.Valgrind.Callgrind.MinimumCostRatio">0.01</value>
+ <value type="double" key="Analyzer.Valgrind.Callgrind.VisualisationMinimumCostRatio">10</value>
+ <value type="bool" key="Analyzer.Valgrind.FilterExternalIssues">true</value>
+ <value type="int" key="Analyzer.Valgrind.LeakCheckOnFinish">1</value>
+ <value type="int" key="Analyzer.Valgrind.NumCallers">25</value>
+ <valuelist type="QVariantList" key="Analyzer.Valgrind.RemovedSuppressionFiles"/>
+ <value type="int" key="Analyzer.Valgrind.SelfModifyingCodeDetection">1</value>
+ <value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
+ <value type="bool" key="Analyzer.Valgrind.ShowReachable">false</value>
+ <value type="bool" key="Analyzer.Valgrind.TrackOrigins">true</value>
+ <value type="QString" key="Analyzer.Valgrind.ValgrindExecutable">valgrind</value>
+ <valuelist type="QVariantList" key="Analyzer.Valgrind.VisibleErrorKinds">
+ <value type="int">0</value>
+ <value type="int">1</value>
+ <value type="int">2</value>
+ <value type="int">3</value>
+ <value type="int">4</value>
+ <value type="int">5</value>
+ <value type="int">6</value>
+ <value type="int">7</value>
+ <value type="int">8</value>
+ <value type="int">9</value>
+ <value type="int">10</value>
+ <value type="int">11</value>
+ <value type="int">12</value>
+ <value type="int">13</value>
+ <value type="int">14</value>
+ </valuelist>
+ <value type="int" key="PE.EnvironmentAspect.Base">-1</value>
+ <valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">rockwork (on Remote Device)</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QmakeProjectManager.MerRunConfiguration:rockwork</value>
+ <valuelist type="QVariantList" key="Qt4ProjectManager.MaemoRunConfiguration.Arguments"/>
+ <value type="QString" key="Qt4ProjectManager.MaemoRunConfiguration.TargetName">rockwork</value>
+ <value type="QString" key="RemoteLinux.RunConfig.AlternateRemoteExecutable"></value>
+ <value type="bool" key="RemoteLinux.RunConfig.UseAlternateRemoteExecutable">false</value>
+ <value type="QString" key="RemoteLinux.RunConfig.WorkingDirectory"></value>
+ <value type="uint" key="RunConfiguration.QmlDebugServerPort">3768</value>
+ <value type="bool" key="RunConfiguration.UseCppDebugger">false</value>
+ <value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
+ <value type="bool" key="RunConfiguration.UseMultiProcess">false</value>
+ <value type="bool" key="RunConfiguration.UseQmlDebugger">false</value>
+ <value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
+ </valuemap>
+ <value type="int" key="ProjectExplorer.Target.RunConfigurationCount">2</value>
+ </valuemap>
+ </data>
+ <data>
+ <variable>ProjectExplorer.Project.TargetCount</variable>
+ <value type="int">1</value>
+ </data>
+ <data>
+ <variable>ProjectExplorer.Project.Updater.FileVersion</variable>
+ <value type="int">18</value>
+ </data>
+ <data>
+ <variable>Version</variable>
+ <value type="int">18</value>
+ </data>
+</qtcreator>
diff --git a/rockwork/AppStorePage.qml b/rockwork/AppStorePage.qml deleted file mode 100644 index bb8712b..0000000 --- a/rockwork/AppStorePage.qml +++ /dev/null @@ -1,266 +0,0 @@ -import QtQuick 2.4 -import Ubuntu.Components 1.3 -import QtQuick.Layouts 1.1 -import RockWork 1.0 - -Page { - id: root - title: showWatchApps ? i18n.tr("Add new watchapp") : i18n.tr("Add new watchface") - - property var pebble: null - property bool showWatchApps: false - property bool showWatchFaces: false - - property string link: "" - - function fetchHome() { - if (showWatchApps) { - client.fetchHome(AppStoreClient.TypeWatchapp) - } else { - client.fetchHome(AppStoreClient.TypeWatchface) - } - } - - head { - actions: [ - Action { - iconName: "search" - onTriggered: { - if (searchField.shown) { - searchField.shown = false; - root.fetchHome(); - } else { - searchField.shown = true; - } - } - } - ] - } - - Component.onCompleted: { - if (root.link) { - client.fetchLink(link) - } else { - root.fetchHome() - } - } - - AppStoreClient { - id: client - hardwarePlatform: pebble.hardwarePlatform - } - - Item { - id: searchField - anchors { left: parent.left; right: parent.right; top: parent.top } - anchors.topMargin: shown ? 0 : -height - Behavior on anchors.topMargin { UbuntuNumberAnimation {} } - opacity: shown ? 1 : 0 - Behavior on opacity { UbuntuNumberAnimation {} } - height: units.gu(6) - - property bool shown: false - onShownChanged: { - if (shown) { - searchTextField.focus = true; - } - } - - TextField { - id: searchTextField - anchors.centerIn: parent - width: parent.width - units.gu(2) - onDisplayTextChanged: { - searchTimer.restart() - } - - Timer { - id: searchTimer - interval: 300 - onTriggered: { - client.search(searchTextField.displayText, root.showWatchApps ? AppStoreClient.TypeWatchapp : AppStoreClient.TypeWatchface); - } - } - } - } - - Item { - anchors { left: parent.left; top: searchField.bottom; right: parent.right; bottom: parent.bottom } - ListView { - anchors.fill: parent - model: ApplicationsFilterModel { - id: appsFilterModel - model: client.model - } - clip: true - section.property: "groupId" - section.labelPositioning: ViewSection.CurrentLabelAtStart | - ViewSection.InlineLabels - section.delegate: ListItem { - height: section ? label.implicitHeight + units.gu(3) : 0 - - Rectangle { - anchors.fill: parent - color: "white" - } - - RowLayout { - anchors.fill: parent - anchors.margins: units.gu(1) - Label { - id: label - text: client.model.groupName(section) - fontSize: "large" -// font.weight: Font.DemiBold - elide: Text.ElideRight - Layout.fillWidth: true - } - AbstractButton { - Layout.fillHeight: true - implicitWidth: seeAllLabel.implicitWidth + height - Row { - anchors.verticalCenter: parent.verticalCenter - Label { - id: seeAllLabel - text: i18n.tr("See all") - } - Icon { - implicitHeight: parent.height - implicitWidth: height - name: "go-next" - } - } - onClicked: { - pageStack.push(Qt.resolvedUrl("AppStorePage.qml"), {pebble: root.pebble, link: client.model.groupLink(section), title: client.model.groupName(section)}); - } - } - } - } - - footer: Item { - height: client.model.links.length > 0 ? units.gu(6) : 0 - width: parent.width - - RowLayout { - anchors { - fill: parent - margins: units.gu(1) - } - spacing: units.gu(1) - - Repeater { - model: client.model.links - Button { - text: client.model.linkName(client.model.links[index]) - onClicked: client.fetchLink(client.model.links[index]); - color: UbuntuColors.orange - Layout.fillWidth: true - } - } - } - } - - delegate: ListItem { - height: delegateColumn.height + units.gu(2) - - RowLayout { - id: delegateRow - anchors.fill: parent - anchors.margins: units.gu(1) - spacing: units.gu(1) - - AnimatedImage { - Layout.fillHeight: true - Layout.preferredWidth: height - source: model.icon - asynchronous: true -// sourceSize.width: width -// sourceSize.height: height - } - - ColumnLayout { - id: delegateColumn - Layout.fillWidth: true; - Layout.fillHeight: true; - Label { - Layout.fillWidth: true - text: model.name - font.weight: Font.DemiBold - elide: Text.ElideRight - } - Label { - Layout.fillWidth: true - text: model.category - } - RowLayout { - Icon { - name: "like" - Layout.preferredHeight: parent.height - Layout.preferredWidth: height - implicitHeight: parent.height - } - Label { - Layout.fillWidth: true - text: model.hearts - } - Icon { - id: tickIcon - name: "tick" - implicitHeight: parent.height - Layout.preferredWidth: height - visible: root.pebble.installedApps.contains(model.storeId) || root.pebble.installedWatchfaces.contains(model.storeId) - Connections { - target: root.pebble.installedApps - onChanged: { - tickIcon.visible = root.pebble.installedApps.contains(model.storeId) || root.pebble.installedWatchfaces.contains(model.storeId) - } - } - - Connections { - target: root.pebble.installedWatchfaces - onChanged: { - tickIcon.visible = root.pebble.installedApps.contains(model.storeId) || root.pebble.installedWatchfaces.contains(model.storeId) - } - } - - } - } - } - - } - - onClicked: { - client.fetchAppDetails(model.storeId); - pageStack.push(Qt.resolvedUrl("AppStoreDetailsPage.qml"), {app: appsFilterModel.get(index), pebble: root.pebble}) - } - } - } - -// RowLayout { -// id: buttonRow -// anchors { left: parent.left; bottom: parent.bottom; right: parent.right; margins: units.gu(1) } -// spacing: units.gu(1) -// Button { -// text: i18n.tr("Previous") -// Layout.fillWidth: true -// enabled: client.offset > 0 -// onClicked: { -// client.previous() -// } -// } -// Button { -// text: i18n.tr("Next") -// Layout.fillWidth: true -// onClicked: { -// client.next() -// } -// } -// } - } - - ActivityIndicator { - anchors.centerIn: parent - running: client.busy - } -} - diff --git a/rockwork/InstalledAppDelegate.qml b/rockwork/InstalledAppDelegate.qml deleted file mode 100644 index 89f6ba8..0000000 --- a/rockwork/InstalledAppDelegate.qml +++ /dev/null @@ -1,88 +0,0 @@ -import QtQuick 2.4 -import QtQuick.Layouts 1.1 -import Ubuntu.Components 1.3 -import RockWork 1.0 - -ListItem { - id: root - - property string uuid: "" - property string name: "" - property string iconSource: "" - property string vendor: "" - property bool hasSettings: false - property alias hasGrip: grip.visible - property bool isSystemApp: false - - signal deleteApp(); - signal configureApp(); - - leadingActions: ListItemActions { - actions: [ - Action { - visible: !root.isSystemApp - iconName: "delete" - onTriggered: { - root.deleteApp(); - } - } - ] - } - - trailingActions: ListItemActions { - actions: [ - Action { - visible: root.hasSettings - iconName: "settings" - onTriggered: { - print("settings triggered") - root.configureApp(); - } - } - ] - } - - RowLayout { - anchors { - fill: parent - margins: units.gu(1) - } - spacing: units.gu(1) - - SystemAppIcon { - Layout.fillHeight: true - Layout.preferredWidth: height - isSystemApp: root.isSystemApp - uuid: root.uuid - iconSource: root.iconSource - } - - ColumnLayout { - Layout.fillWidth: true - Label { - text: root.name - Layout.fillWidth: true - } - - Label { - text: root.vendor - Layout.fillWidth: true - fontSize: "small" - } - } - - Item { - id: grip - Layout.fillHeight: true - Layout.preferredWidth: height - opacity: (root.contentMoving || root.swiped || root.dragging) ? 0 : 1 - Behavior on opacity { UbuntuNumberAnimation {} } - Icon { - width: units.gu(3) - height: width - anchors.centerIn: parent - name: "grip-large" - } - } - } -} diff --git a/rockwork/InstalledAppsPage.qml b/rockwork/InstalledAppsPage.qml deleted file mode 100644 index a18cd3f..0000000 --- a/rockwork/InstalledAppsPage.qml +++ /dev/null @@ -1,201 +0,0 @@ -import QtQuick 2.4 -import QtQuick.Layouts 1.1 -import Ubuntu.Components 1.3 -import Ubuntu.Components.Popups 1.3 -import RockWork 1.0 - -Page { - id: root - title: showWatchApps ? (showWatchFaces ? i18n.tr("Apps & Watchfaces") : i18n.tr("Apps")) : i18n.tr("Watchfaces") - - property var pebble: null - property bool showWatchApps: false - property bool showWatchFaces: false - - head { - actions: [ - Action { - iconName: "add" - onTriggered: pageStack.push(Qt.resolvedUrl("AppStorePage.qml"), {pebble: root.pebble, showWatchApps: root.showWatchApps, showWatchFaces: root.showWatchFaces}) - } - ] - } - - function configureApp(uuid) { - // The health app is special :/ - if (uuid == "{36d8c6ed-4c83-4fa1-a9e2-8f12dc941f8c}") { - var popup = PopupUtils.open(Qt.resolvedUrl("HealthSettingsDialog.qml"), root, {healthParams: pebble.healthParams}); - popup.accepted.connect(function() { - pebble.healthParams = popup.healthParams - }) - } else { - pebble.requestConfigurationURL(uuid); - } - } - - Item { - anchors.fill: parent - ListView { - id: listView - anchors.fill: parent - model: root.showWatchApps ? root.pebble.installedApps : root.pebble.installedWatchfaces - clip: true - property real realContentY: contentY + originY - - delegate: InstalledAppDelegate { - id: delegate - uuid: model.uuid - name: model.name - iconSource: model.icon - vendor: model.vendor - visible: dndArea.draggedIndex !== index - hasGrip: index > 0 - isSystemApp: model.isSystemApp - hasSettings: model.hasSettings - - onDeleteApp: { - pebble.removeApp(model.uuid) - } - onConfigureApp: { - root.configureApp(model.uuid) - } - onClicked: { - PopupUtils.open(dialogComponent, root, {app: listView.model.get(index)}) - } - } - } - MouseArea { - id: dndArea - anchors { - top: parent.top - bottom: parent.bottom - right: parent.right - } - drag.axis: Drag.YAxis - propagateComposedEvents: true - width: units.gu(5) - - property int startY: 0 - property int draggedIndex: -1 - - - onPressAndHold: { - startY = mouseY; - draggedIndex = Math.floor((listView.realContentY + mouseY) / fakeDragItem.height) - if (draggedIndex == 0) { - print("cannot drag settings app"); - return; - } - - var draggedItem = listView.model.get(draggedIndex); - fakeDragItem.uuid = draggedItem.uuid; - fakeDragItem.name = draggedItem.name; - fakeDragItem.vendor = draggedItem.vendor; - fakeDragItem.iconSource = draggedItem.icon; - fakeDragItem.isSystemApp = draggedItem.isSystemApp; - fakeDragItem.y = (fakeDragItem.height * draggedIndex) - listView.realContentY - drag.target = fakeDragItem; - } - - onMouseYChanged: { - var newIndex = Math.floor((listView.realContentY + mouseY) / fakeDragItem.height) - - if (newIndex > draggedIndex) { - newIndex = draggedIndex + 1; - } else if (newIndex < draggedIndex) { - newIndex = draggedIndex - 1; - } else { - return; - } - - if (newIndex >= 1 && newIndex < listView.count) { - listView.model.move(draggedIndex, newIndex); - draggedIndex = newIndex; - } - } - - onReleased: { - if (draggedIndex > -1) { - listView.model.commitMove(); - draggedIndex = -1; - drag.target = null; - } - } - } - } - - - - InstalledAppDelegate { - id: fakeDragItem - visible: dndArea.draggedIndex != -1 - - } - - Component { - id: dialogComponent - Dialog { - id: dialog - property var app: null - - RowLayout { - SystemAppIcon { - height: titleCol.height - width: height - isSystemApp: app.isSystemApp - uuid: app.uuid - iconSource: app.icon - } - - ColumnLayout { - id: titleCol - Layout.fillWidth: true - - Label { - Layout.fillWidth: true - text: app.name - fontSize: "large" - } - Label { - Layout.fillWidth: true - text: app.vendor - } - } - } - - Button { - text: i18n.tr("Launch") - color: UbuntuColors.green - onClicked: { - pebble.launchApp(app.uuid); - PopupUtils.close(dialog); - } - } - - Button { - text: i18n.tr("Configure") - color: UbuntuColors.blue - visible: app.hasSettings - onClicked: { - root.configureApp(app.uuid); - PopupUtils.close(dialog); - } - } - - Button { - text: i18n.tr("Delete") - color: UbuntuColors.red - visible: !app.isSystemApp - onClicked: { - pebble.removeApp(app.uuid); - PopupUtils.close(dialog); - } - } - - Button { - text: i18n.tr("Close") - onClicked: PopupUtils.close(dialog) - } - } - } -} diff --git a/rockwork/MainMenuPage.qml b/rockwork/MainMenuPage.qml deleted file mode 100644 index 32c7b96..0000000 --- a/rockwork/MainMenuPage.qml +++ /dev/null @@ -1,317 +0,0 @@ -import QtQuick 2.4 -import QtQuick.Layouts 1.1 -import Ubuntu.Components 1.3 - -Page { - id: root - title: pebble.name - - property var pebble: null - - head { - actions: [ - Action { - iconName: "info" - text: i18n.tr("About") - onTriggered: { - pageStack.push(Qt.resolvedUrl("InfoPage.qml")) - } - }, - Action { - iconName: "ubuntu-sdk-symbolic" - text: i18n.tr("Developer tools") - onTriggered: { - pageStack.push(Qt.resolvedUrl("DeveloperToolsPage.qml"), {pebble: root.pebble}) - } - } - ] - } - - //Creating the menu list this way to allow the text field to be translatable (http://askubuntu.com/a/476331) - ListModel { - id: mainMenuModel - dynamicRoles: true - } - - Component.onCompleted: { - populateMainMenu(); - } - - Connections { - target: root.pebble - onFirmwareUpgradeAvailableChanged: { - populateMainMenu(); - } - } - - function populateMainMenu() { - mainMenuModel.clear(); - - mainMenuModel.append({ - icon: "stock_notification", - text: i18n.tr("Manage notifications"), - page: "NotificationsPage.qml", - color: "blue" - }); - - mainMenuModel.append({ - icon: "stock_application", - text: i18n.tr("Manage Apps"), - page: "InstalledAppsPage.qml", - showWatchApps: true, - color: UbuntuColors.green - }); - - mainMenuModel.append({ - icon: "clock-app-symbolic", - text: i18n.tr("Manage Watchfaces"), - page: "InstalledAppsPage.qml", - showWatchFaces: true, - color: "black" - }); - - mainMenuModel.append({ - icon: "settings", - text: i18n.tr("Settings"), - page: "SettingsPage.qml", - showWatchFaces: true, - color: "gold" - }); - - if (root.pebble.firmwareUpgradeAvailable) { - mainMenuModel.append({ - icon: "preferences-system-updates-symbolic", - text: i18n.tr("Firmware upgrade"), - page: "FirmwareUpgradePage.qml", - color: "red" - }); - } - - } - - PebbleModels { - id: modelModel - } - - GridLayout { - anchors.fill: parent - columns: parent.width > parent.height ? 2 : 1 - - Item { - Layout.fillWidth: true - Layout.fillHeight: true - Layout.maximumHeight: units.gu(30) - - RowLayout { - anchors.fill: parent - anchors.margins: units.gu(1) - spacing: units.gu(1) - - Item { - Layout.alignment: Qt.AlignHCenter - Layout.fillHeight: true - Layout.fillWidth: true - Layout.minimumWidth: watchImage.width - Image { - id: watchImage - width: implicitWidth * height / implicitHeight - height: parent.height - anchors.horizontalCenter: parent.horizontalCenter - - source: modelModel.get(root.pebble.model).image - fillMode: Image.PreserveAspectFit - - Item { - id: watchFace - height: parent.height * (modelModel.get(root.pebble.model - 1).shape === "rectangle" ? .5 : .515) - width: height * (modelModel.get(root.pebble.model - 1).shape === "rectangle" ? .85 : 1) - anchors.centerIn: parent - anchors.horizontalCenterOffset: units.dp(1) - anchors.verticalCenterOffset: units.dp(modelModel.get(root.pebble.model - 1).shape === "rectangle" ? 0 : 1) - - Image { - id: image - anchors.fill: parent - source: "file://" + root.pebble.screenshots.latestScreenshot - visible: false - } - - Component.onCompleted: { - if (!root.pebble.screenshots.latestScreenshot) { - root.pebble.requestScreenshot(); - } - } - - Rectangle { - id: textItem - anchors.fill: parent - layer.enabled: true - radius: modelModel.get(root.pebble.model - 1).shape === "rectangle" ? units.gu(.5) : height / 2 - // This item should be used as the 'mask' - layer.samplerName: "maskSource" - layer.effect: ShaderEffect { - property var colorSource: image; - fragmentShader: " - uniform lowp sampler2D colorSource; - uniform lowp sampler2D maskSource; - uniform lowp float qt_Opacity; - varying highp vec2 qt_TexCoord0; - void main() { - gl_FragColor = - texture2D(colorSource, qt_TexCoord0) - * texture2D(maskSource, qt_TexCoord0).a - * qt_Opacity; - } - " - } - } - } - } - } - ColumnLayout { - Layout.fillWidth: true - Layout.fillHeight: true - spacing: units.gu(2) - Rectangle { - height: units.gu(10) - width: height - radius: height / 2 - color: root.pebble.connected ? UbuntuColors.green : UbuntuColors.red - - Icon { - anchors.fill: parent - anchors.margins: units.gu(2) - color: "white" - name: root.pebble.connected ? "tick" : "dialog-error-symbolic" - } - } - - Label { - text: root.pebble.connected ? i18n.tr("Connected") : i18n.tr("Disconnected") - Layout.fillWidth: true - } - } - } - } - - - Column { - Layout.fillWidth: true - Layout.preferredHeight: childrenRect.height - spacing: menuRepeater.count > 0 ? 0 : units.gu(2) - Label { - text: i18n.tr("Your Pebble smartwatch is disconnected. Please make sure it is powered on, within range and it is paired properly in the Bluetooth System Settings.") - width: parent.width - units.gu(4) - anchors.horizontalCenter: parent.horizontalCenter - wrapMode: Text.WordWrap - visible: !root.pebble.connected - fontSize: "large" - horizontalAlignment: Text.AlignHCenter - } - - Button { - text: i18n.tr("Open System Settings") - visible: !root.pebble.connected - onClicked: Qt.openUrlExternally("settings://system/bluetooth") - color: UbuntuColors.orange - anchors.horizontalCenter: parent.horizontalCenter - } - - Label { - text: i18n.tr("Your Pebble smartwatch is in factory mode and needs to be initialized.") - width: parent.width - units.gu(4) - anchors.horizontalCenter: parent.horizontalCenter - wrapMode: Text.WordWrap - visible: root.pebble.connected && root.pebble.recovery && !root.pebble.upgradingFirmware - fontSize: "large" - horizontalAlignment: Text.AlignHCenter - } - Button { - text: i18n.tr("Initialize Pebble") - onClicked: root.pebble.performFirmwareUpgrade(); - visible: root.pebble.connected && root.pebble.recovery && !root.pebble.upgradingFirmware - color: UbuntuColors.orange - anchors.horizontalCenter: parent.horizontalCenter - } - - Rectangle { - id: upgradeIcon - height: units.gu(10) - width: height - radius: width / 2 - color: UbuntuColors.orange - anchors.horizontalCenter: parent.horizontalCenter - Icon { - anchors.fill: parent - anchors.margins: units.gu(1) - name: "preferences-system-updates-symbolic" - color: "white" - } - - RotationAnimation on rotation { - duration: 2000 - loops: Animation.Infinite - from: 0 - to: 360 - running: upgradeIcon.visible - } - visible: root.pebble.connected && root.pebble.upgradingFirmware - } - - Label { - text: i18n.tr("Upgrading...") - fontSize: "large" - anchors.horizontalCenter: parent.horizontalCenter - visible: root.pebble.connected && root.pebble.upgradingFirmware - } - - Repeater { - id: menuRepeater - model: root.pebble.connected && !root.pebble.recovery && !root.pebble.upgradingFirmware ? mainMenuModel : null - delegate: ListItem { - - RowLayout { - anchors.fill: parent - anchors.margins: units.gu(1) - - UbuntuShape { - Layout.fillHeight: true - Layout.preferredWidth: height - backgroundColor: model.color - Icon { - anchors.fill: parent - anchors.margins: units.gu(.5) - name: model.icon - color: "white" - } - } - - - Label { - text: model.text - Layout.fillWidth: true - } - } - - onClicked: { - var options = {}; - options["pebble"] = root.pebble - var modelItem = mainMenuModel.get(index) - options["showWatchApps"] = modelItem.showWatchApps - options["showWatchFaces"] = modelItem.showWatchFaces - pageStack.push(Qt.resolvedUrl(model.page), options) - } - } - } - } - } - - Connections { - target: pebble - onOpenURL: { - if (url) { - pageStack.push(Qt.resolvedUrl("AppSettingsPage.qml"), {uuid: uuid, url: url, pebble: pebble}) - } - } - } -} diff --git a/rockwork/PebbleModels.qml b/rockwork/PebbleModels.qml deleted file mode 100644 index 103064a..0000000 --- a/rockwork/PebbleModels.qml +++ /dev/null @@ -1,28 +0,0 @@ -import QtQuick 2.4 - -ListModel { - id: modelModel - ListElement { image: 'artwork/tintin-black.png'; shape: "rectangle" } // Fallback for Unknown - ListElement { image: 'artwork/tintin-black.png'; shape: "rectangle" } - ListElement { image: 'artwork/tintin-white.png'; shape: "rectangle" } - ListElement { image: 'artwork/tintin-red.png'; shape: "rectangle" } - ListElement { image: 'artwork/tintin-orange.png'; shape: "rectangle" } - ListElement { image: 'artwork/tintin-grey.png'; shape: "rectangle" } - ListElement { image: 'artwork/bianca-silver.png'; shape: "rectangle" } - ListElement { image: 'artwork/bianca-black.png'; shape: "rectangle" } - ListElement { image: 'artwork/tintin-blue.png'; shape: "rectangle" } - ListElement { image: 'artwork/tintin-green.png'; shape: "rectangle" } - ListElement { image: 'artwork/tintin-pink.png'; shape: "rectangle" } - ListElement { image: 'artwork/snowy-white.png'; shape: "rectangle" } - ListElement { image: 'artwork/snowy-black.png'; shape: "rectangle" } - ListElement { image: 'artwork/snowy-red.png'; shape: "rectangle" } - ListElement { image: 'artwork/bobby-silver.png'; shape: "rectangle" } - ListElement { image: 'artwork/bobby-black.png'; shape: "rectangle" } - ListElement { image: 'artwork/bobby-gold.png'; shape: "rectangle" } - ListElement { image: 'artwork/spalding-14mm-silver.png'; shape: "round" } - ListElement { image: 'artwork/spalding-14mm-black.png'; shape: "round" } - ListElement { image: 'artwork/spalding-20mm-silver.png'; shape: "round" } - ListElement { image: 'artwork/spalding-20mm-black.png'; shape: "round" } - ListElement { image: 'artwork/spalding-14mm-rose-gold.png'; shape: "round" } -} - diff --git a/rockwork/artwork/back-cover.png b/rockwork/artwork/back-cover.png Binary files differnew file mode 100644 index 0000000..2d5ab14 --- /dev/null +++ b/rockwork/artwork/back-cover.png diff --git a/rockwork/artwork/rockwork.svg b/rockwork/artwork/rockwork.svg deleted file mode 100644 index e4e92c0..0000000 --- a/rockwork/artwork/rockwork.svg +++ /dev/null @@ -1,275 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?> -<!-- Created with Inkscape (http://www.inkscape.org/) --> - -<svg - xmlns:dc="http://purl.org/dc/elements/1.1/" - xmlns:cc="http://creativecommons.org/ns#" - xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" - xmlns:svg="http://www.w3.org/2000/svg" - xmlns="http://www.w3.org/2000/svg" - xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" - xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" - width="72.248886mm" - height="72.248886mm" - viewBox="0 0 255.99999 255.99999" - id="svg2" - version="1.1" - inkscape:version="0.91 r13725" - sodipodi:docname="upebble.svg"> - <defs - id="defs4"> - <filter - inkscape:collect="always" - style="color-interpolation-filters:sRGB" - id="filter4248" - x="-0.025328101" - width="1.0506562" - y="-0.013960773" - height="1.0279215"> - <feGaussianBlur - inkscape:collect="always" - stdDeviation="2.3907822" - id="feGaussianBlur4250" /> - </filter> - </defs> - <sodipodi:namedview - id="base" - pagecolor="#ffffff" - bordercolor="#666666" - borderopacity="1.0" - inkscape:pageopacity="0.0" - inkscape:pageshadow="2" - inkscape:zoom="3.959798" - inkscape:cx="89.121544" - inkscape:cy="77.044911" - inkscape:document-units="px" - inkscape:current-layer="layer1" - showgrid="true" - fit-margin-top="0" - fit-margin-left="0" - fit-margin-right="0" - fit-margin-bottom="0" - inkscape:window-width="2880" - inkscape:window-height="1752" - inkscape:window-x="0" - inkscape:window-y="48" - inkscape:window-maximized="1"> - <inkscape:grid - type="xygrid" - id="grid4136" - originx="-40.000001" - originy="-539" - snapvisiblegridlinesonly="true" - enabled="false" /> - </sodipodi:namedview> - <metadata - id="metadata7"> - <rdf:RDF> - <cc:Work - rdf:about=""> - <dc:format>image/svg+xml</dc:format> - <dc:type - rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> - <dc:title></dc:title> - </cc:Work> - </rdf:RDF> - </metadata> - <g - inkscape:label="Layer 1" - inkscape:groupmode="layer" - id="layer1" - transform="translate(-40,-257.36221)"> - <rect - style="opacity:1;fill:#78d3fc;fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" - id="rect4200" - width="256" - height="256" - x="40" - y="257.36221" /> - <path - style="opacity:1;fill:#000000;fill-opacity:0.0479798;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" - d="m 40,257.36221 256,0 -256,256 z" - id="rect4252" - inkscape:connector-curvature="0" - sodipodi:nodetypes="cccc" /> - <g - id="g4300"> - <g - style="fill:#000000;fill-opacity:1;opacity:0.291;filter:url(#filter4248)" - id="g4202" - transform="matrix(0.60632857,0,0,0.60632857,-37.462675,74.399202)"> - <path - sodipodi:nodetypes="czccc" - inkscape:connector-curvature="0" - id="path4204" - d="m 437.97969,445.08937 c 0,0 11.49464,-4.59544 12.27285,0.25253 0.77821,4.84797 2.06459,45.23266 2.06459,45.23266 -8.36034,0.32794 -13.15013,-0.0886 -13.15013,-0.0886 z" - style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> - <path - sodipodi:nodetypes="ccccc" - inkscape:connector-curvature="0" - id="path4206" - d="m 439.49492,491.6046 12.68287,0.70015 0.54937,42.27954 -13.73731,0.25254 z" - style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> - <rect - style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" - id="rect4208" - width="120" - height="95" - x="280" - y="623.36218" /> - <rect - y="307.36221" - x="280" - height="95" - width="120" - id="rect4210" - style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> - <path - sodipodi:nodetypes="zcczz" - inkscape:connector-curvature="0" - id="path4212" - d="M 228.0862,442.4309 C 228.58744,435.98794 240,437.36221 240,437.36221 l 0,42.02031 c 0,0 -14.31567,-1.22669 -13.80125,-2.84014 0.51442,-1.61345 1.3862,-27.66851 1.88745,-34.11148 z" - style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> - <path - style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" - d="M 420,643.715 337.60905,658.36221 255,643.715 l 0,-20 165,0 z" - id="path4214" - inkscape:connector-curvature="0" - sodipodi:nodetypes="cccccc" /> - <path - sodipodi:nodetypes="cccccc" - inkscape:connector-curvature="0" - id="path4216" - d="M 255,382.36221 337.39095,367.715 420,382.36221 l 0,20 -165,0 z" - style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> - <path - sodipodi:nodetypes="cczcc" - inkscape:connector-curvature="0" - id="path4218" - d="m 438.52906,535.82255 c 0,0 5.15979,0.84007 13.83236,0.44761 0.13423,13.76866 -1.20901,37.74804 -1.85634,42.35471 -0.64733,4.60667 -11.01016,-0.50508 -11.01016,-0.50508 z" - style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> - <path - sodipodi:nodetypes="zzzzzzzzz" - inkscape:connector-curvature="0" - id="path4220" - d="m 244.85206,406.56127 c 16.07143,-13.92858 66.12644,-13.34299 97.65304,-13.30725 31.5266,0.0357 73.56632,-0.53467 90.70918,15.17961 17.14286,15.71428 12.91706,70.98675 13.01566,106.0726 0.0986,35.08586 5.19864,81.42741 -13.01565,99.64169 C 415,632.3622 371.12033,628.47664 339.15317,628.18658 307.186,627.89652 263.91063,632.7014 245.3392,615.91569 226.76777,599.12997 231.43107,540.45867 231.61582,505.9352 c 0.18475,-34.52347 -2.83519,-85.44536 13.23624,-99.37393 z" - style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> - <rect - ry="20" - rx="20" - y="422.36221" - x="260" - height="174.99998" - width="155" - id="rect4222" - style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> - <rect - y="442.36221" - x="280" - height="135" - width="120" - id="rect4224" - style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> - <path - sodipodi:nodetypes="cccccccc" - inkscape:connector-curvature="0" - id="path4226" - d="m 375,442.36221 25,0 0,135 -25,0 0,-109.75206 -7.32361,-5.3033 7.32361,-4.9245 z" - style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> - </g> - <path - sodipodi:nodetypes="czccc" - inkscape:connector-curvature="0" - id="rect4177" - d="m 228.09692,344.2696 c 0,0 6.96953,-2.78634 7.44138,0.15312 0.47185,2.93946 1.25182,27.42585 1.25182,27.42585 -5.06911,0.19884 -7.9733,-0.0537 -7.9733,-0.0537 z" - style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> - <path - sodipodi:nodetypes="ccccc" - inkscape:connector-curvature="0" - id="rect4179" - d="m 229.01565,372.47312 7.68999,0.42452 0.3331,25.63529 -8.32933,0.15312 z" - style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> - <rect - style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" - id="rect4167" - width="72.75943" - height="57.601215" - x="132.30933" - y="452.36151" /> - <rect - y="260.76169" - x="132.30933" - height="57.601215" - width="72.75943" - id="rect4165" - style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> - <path - sodipodi:nodetypes="zcczz" - inkscape:connector-curvature="0" - id="rect4169" - d="m 100.8325,342.6577 c 0.30392,-3.90655 7.22368,-3.07329 7.22368,-3.07329 l 0,25.47811 c 0,0 -8.679998,-0.74378 -8.36809,-1.72206 0.311907,-0.97828 0.84049,-16.77621 1.14441,-20.68276 z" - style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> - <path - style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" - d="m 217.19532,464.702 -49.95598,8.88102 -50.08823,-8.88102 0,-12.12657 100.04421,0 z" - id="path4175" - inkscape:connector-curvature="0" - sodipodi:nodetypes="cccccc" /> - <path - sodipodi:nodetypes="cccccc" - inkscape:connector-curvature="0" - id="rect4172" - d="m 117.15111,306.23633 49.95599,-8.88102 50.08822,8.88102 0,12.12658 -100.04421,0 z" - style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> - <path - sodipodi:nodetypes="cczcc" - inkscape:connector-curvature="0" - id="rect4181" - d="m 228.43002,399.28372 c 0,0 3.12853,0.50936 8.38696,0.2714 0.0814,8.34833 -0.73306,22.88772 -1.12555,25.68087 -0.3925,2.79316 -6.67578,-0.30624 -6.67578,-0.30624 z" - style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> - <path - sodipodi:nodetypes="zzzzzzzzz" - inkscape:connector-curvature="0" - id="rect4149" - d="m 110.99812,320.90892 c 9.74457,-8.4453 40.09435,-8.09024 59.20983,-8.06857 19.11548,0.0217 44.60536,-0.32419 54.99957,9.20383 10.39421,9.52802 7.83198,43.0413 7.89177,64.31485 0.0598,21.27356 3.15208,49.37176 -7.89176,60.4156 -11.04385,11.04384 -37.64935,8.68791 -57.03195,8.51204 -19.38261,-0.17587 -45.6217,2.73747 -56.88209,-7.44019 -11.26039,-10.17766 -8.4329,-45.75175 -8.32088,-66.68431 0.11202,-20.93257 -1.71905,-51.80796 8.02551,-60.25325 z" - style="opacity:1;fill:#cbcbcb;fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> - <path - style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" - d="m 133.22587,330.48948 69.72779,0 c 6.71812,0 11.83367,5.41484 12.12657,12.12657 1.19073,27.28478 1.19022,54.56956 0,81.85435 -0.29278,6.71174 -5.40845,12.12657 -12.12657,12.12657 l -69.72779,0 c -6.71812,0 -11.82926,-5.41504 -12.12657,-12.12657 -1.18246,-26.69356 -1.65764,-53.74075 0,-81.85435 0.39543,-6.70647 5.40845,-12.12657 12.12657,-12.12657 z" - id="rect4152" - inkscape:connector-curvature="0" - sodipodi:nodetypes="sssssssss" /> - <rect - y="342.61606" - x="131.62029" - height="81.854355" - width="72.75943" - id="rect4154" - style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> - <path - sodipodi:nodetypes="cccccccc" - inkscape:connector-curvature="0" - id="rect4156" - d="m 189.2215,342.61605 15.15821,0 0,81.85436 -15.15821,0 0,-66.54581 -4.44052,-3.21555 4.44052,-2.98586 z" - style="opacity:1;fill:#78d3fc;fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> - </g> - <path - style="fill:#000000" - d="m 143.63128,393.17695 c -0.82884,-0.82884 0.32908,-1.46136 2.67524,-1.46136 3.02637,0 3.07586,-0.7116 0.31911,-4.58902 l -2.10477,-2.96041 2.0287,-2.94922 c 1.15063,-1.67272 2.20678,-4.13671 2.44014,-5.69282 0.40696,-2.71383 0.44252,-2.74828 3.27625,-3.17322 1.57564,-0.23629 4.03472,-1.23453 5.46462,-2.21832 1.42988,-0.98379 2.85437,-1.78871 3.16551,-1.78871 0.31114,0 1.68177,0.80847 3.04585,1.7966 1.40341,1.01663 3.70432,1.98019 5.29992,2.21946 2.92933,0.43928 2.99923,0.52347 3.81465,4.59457 0.23714,1.18397 1.22649,3.16119 2.19857,4.39382 0.97208,1.23265 1.76741,2.42825 1.76741,2.6569 0,0.22864 -0.83031,1.62253 -1.84514,3.09753 -2.44659,3.556 -2.38325,4.49115 0.32038,4.72947 1.19102,0.10499 2.22891,0.46766 2.30641,0.80594 0.15778,0.68864 -33.49245,1.21919 -34.17285,0.53879 z m 27.8729,-2.84521 c 0.009,-0.76112 0.83738,-2.4679 1.83992,-3.79283 l 1.82279,-2.40898 -1.58789,-2.08183 c -0.87334,-1.14501 -1.90888,-3.37431 -2.30119,-4.954 -0.68475,-2.75721 -0.82407,-2.89364 -3.48101,-3.40876 -1.52223,-0.29514 -3.68339,-1.22898 -4.80255,-2.0752 l -2.03486,-1.53859 -2.27046,1.53481 c -2.19134,1.48132 -2.85113,1.74296 -6.34208,2.51493 -1.32103,0.29212 -1.68348,0.80695 -2.01126,2.85674 -0.2199,1.37522 -1.11243,3.57721 -1.98338,4.8933 l -1.58355,2.39291 1.54803,2.0343 c 0.85141,1.11887 1.73796,2.79542 1.97011,3.72567 l 0.42209,1.69138 10.38909,0 c 10.35877,0 10.38914,-0.004 10.4062,-1.38385 z m -16.16204,-1.17442 c -3.00082,-0.83158 -3.29439,-2.70542 -0.30753,-1.96294 1.0994,0.27329 2.9676,0.49689 4.15156,0.49689 1.18396,0 3.05216,-0.2236 4.15155,-0.49689 1.34833,-0.33517 1.9989,-0.27586 1.9989,0.18225 0,1.61808 -6.44052,2.76557 -9.99448,1.78069 z m -1.87921,-5.21512 c -0.23497,-0.23497 -0.42721,-1.51123 -0.42721,-2.83614 0,-2.76084 1.40937,-2.98541 1.73071,-0.27578 0.21201,1.78766 -0.62633,3.78908 -1.3035,3.11192 z m 10.02856,-2.68238 c 0,-1.7768 0.25627,-2.46018 0.92256,-2.46018 0.6663,0 0.92257,0.68338 0.92257,2.46018 0,1.7768 -0.25627,2.46018 -0.92257,2.46018 -0.66629,0 -0.92256,-0.68338 -0.92256,-2.46018 z m -22.75668,2.7677 c 0,-0.69366 0.43166,-0.94682 1.38386,-0.81158 0.76111,0.10809 1.38385,0.47331 1.38385,0.81158 0,0.33828 -0.62274,0.70349 -1.38385,0.81159 -0.9522,0.13523 -1.38386,-0.11793 -1.38386,-0.81159 z m 37.8226,0.30318 c -0.46699,-0.7556 1.22568,-1.49279 2.13592,-0.93022 0.35999,0.22248 0.4953,0.66216 0.30068,0.97707 -0.46943,0.75955 -1.95589,0.73096 -2.4366,-0.0469 z m -32.49939,-13.42132 c -1.23387,-1.36341 -1.29125,-1.95046 -0.19065,-1.95046 1.05106,0 3.00139,2.11681 2.45435,2.66385 -0.65422,0.65422 -1.17438,0.49029 -2.2637,-0.71339 z m 27.38286,0.11435 c 0.23773,-1.20797 2.11252,-2.50883 2.72827,-1.89307 0.48678,0.48678 -1.47947,2.90348 -2.36232,2.90348 -0.31065,0 -0.47533,-0.45468 -0.36595,-1.01041 z m -13.38512,-4.7488 c -0.52662,-1.37234 -0.0519,-3.6431 0.82178,-3.93083 0.51752,-0.17043 0.76881,0.45533 0.76881,1.91443 0,2.29458 -0.99824,3.56005 -1.59059,2.0164 z" - id="path4285" - inkscape:connector-curvature="0" - sodipodi:nodetypes="ssscsssssssssssssssscsssscsssscsscsssssssssssssssssssssscssccssssssssssss" /> - <text - xml:space="preserve" - style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" - x="136.46957" - y="405.82156" - id="text4342" - sodipodi:linespacing="125%"><tspan - sodipodi:role="line" - id="tspan4344" - x="136.46957" - y="405.82156" - style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:10px;font-family:Ubuntu;-inkscape-font-specification:Ubuntu">Tomorrow</tspan></text> - </g> -</svg> diff --git a/rockwork/main.cpp b/rockwork/main.cpp index 70fd0d7..57a8772 100644 --- a/rockwork/main.cpp +++ b/rockwork/main.cpp @@ -12,26 +12,28 @@ #include "applicationsfiltermodel.h" #include "appstoreclient.h" #include "screenshotmodel.h" +#include <sailfishapp.h> int main(int argc, char *argv[]) { - QGuiApplication app(argc, argv); + QScopedPointer<QGuiApplication> app(SailfishApp::application(argc, argv)); + app->setApplicationName("pebble"); + app->setOrganizationName(""); - qmlRegisterUncreatableType<Pebble>("RockWork", 1, 0, "Pebble", "Get them from the model"); - qmlRegisterUncreatableType<ApplicationsModel>("RockWork", 1, 0, "ApplicationsModel", "Get them from a Pebble object"); - qmlRegisterUncreatableType<AppItem>("RockWork", 1, 0, "AppItem", "Get them from an ApplicationsModel"); - qmlRegisterType<ApplicationsFilterModel>("RockWork", 1, 0, "ApplicationsFilterModel"); - qmlRegisterType<Pebbles>("RockWork", 1, 0, "Pebbles"); - qmlRegisterUncreatableType<NotificationSourceModel>("RockWork", 1, 0, "NotificationSourceModel", "Get it from a Pebble object"); - qmlRegisterType<ServiceControl>("RockWork", 1, 0, "ServiceController"); - qmlRegisterType<AppStoreClient>("RockWork", 1, 0, "AppStoreClient"); - qmlRegisterType<ScreenshotModel>("RockWork", 1, 0, "ScreenshotModel"); + qmlRegisterUncreatableType<Pebble>("RockPool", 1, 0, "Pebble", "Get them from the model"); + qmlRegisterUncreatableType<ApplicationsModel>("RockPool", 1, 0, "ApplicationsModel", "Get them from a Pebble object"); + qmlRegisterUncreatableType<AppItem>("RockPool", 1, 0, "AppItem", "Get them from an ApplicationsModel"); + qmlRegisterType<ApplicationsFilterModel>("RockPool", 1, 0, "ApplicationsFilterModel"); + qmlRegisterType<Pebbles>("RockPool", 1, 0, "Pebbles"); + qmlRegisterUncreatableType<NotificationSourceModel>("RockPool", 1, 0, "NotificationSourceModel", "Get it from a Pebble object"); + qmlRegisterType<ServiceControl>("RockPool", 1, 0, "ServiceController"); + qmlRegisterType<AppStoreClient>("RockPool", 1, 0, "AppStoreClient"); + qmlRegisterType<ScreenshotModel>("RockPool", 1, 0, "ScreenshotModel"); - QQuickView view; - view.engine()->rootContext()->setContextProperty("version", QStringLiteral(VERSION)); - view.engine()->rootContext()->setContextProperty("homePath", QStandardPaths::standardLocations(QStandardPaths::HomeLocation).first()); - view.setSource(QUrl(QStringLiteral("qrc:///Main.qml"))); - view.setResizeMode(QQuickView::SizeRootObjectToView); - view.show(); - return app.exec(); + QScopedPointer<QQuickView> view(SailfishApp::createView()); + view->rootContext()->setContextProperty("version", QStringLiteral(VERSION)); + view->setSource(SailfishApp::pathTo("qml/Main.qml")); + view->show(); + + return app->exec(); } diff --git a/rockwork/AppSettingsPage.qml b/rockwork/qml/AppSettingsPage.qml index d8d865b..da7d577 100644 --- a/rockwork/AppSettingsPage.qml +++ b/rockwork/qml/AppSettingsPage.qml @@ -1,7 +1,5 @@ -import QtQuick 2.4 -import Ubuntu.Web 0.2 -import Ubuntu.Components 1.3 -import com.canonical.Oxide 1.0 as Oxide +import QtQuick 2.0 +import Sailfish.Silica 1.0 Page { id: settings diff --git a/rockwork/AppStoreDetailsPage.qml b/rockwork/qml/AppStoreDetailsPage.qml index 696e3c6..dbb8d5f 100644 --- a/rockwork/AppStoreDetailsPage.qml +++ b/rockwork/qml/AppStoreDetailsPage.qml @@ -1,7 +1,5 @@ -import QtQuick 2.4 -import QtQuick.Layouts 1.1 -import Ubuntu.Components 1.3 -import Ubuntu.Components.ListItems 1.3 +import QtQuick 2.0 +import Sailfish.Silica 1.0 import QtGraphicalEffects 1.0 Page { diff --git a/rockwork/qml/AppStorePage.qml b/rockwork/qml/AppStorePage.qml new file mode 100644 index 0000000..7e006da --- /dev/null +++ b/rockwork/qml/AppStorePage.qml @@ -0,0 +1,268 @@ +import QtQuick 2.0 +import QtQml 2.1 +import Sailfish.Silica 1.0 +import RockPool 1.0 + +Page { + id: root + + property var pebble: null + property bool showWatchApps: false + property bool showWatchFaces: false + + property string link: "" + + function fetchHome() { + if (showWatchApps) { + client.fetchHome(AppStoreClient.TypeWatchapp) + } else { + client.fetchHome(AppStoreClient.TypeWatchface) + } + } + SilicaFlickable { + id: flickable + anchors.top: parent.top + width: parent.width + PageHeader { + title: showWatchApps ? qsTr("Add new watchapp") : qsTr("Add new watchface") + } + PullDownMenu { + MenuItem { + text: qsTr("Show search") + onClicked: { + if (searchField.shown) { + searchField.shown = false; + root.fetchHome(); + } else { + searchField.shown = true; + } + } + } + } + + Component.onCompleted: { + if (root.link) { + client.fetchLink(link) + } else { + root.fetchHome() + } + } + + AppStoreClient { + id: client + hardwarePlatform: pebble.hardwarePlatform + } + + Item { + id: searchField + anchors { left: parent.left; right: parent.right; top: parent.top } + anchors.topMargin: shown ? 0 : -height + Behavior on anchors.topMargin { NumberAnimation {} } + opacity: shown ? 1 : 0 + Behavior on opacity { NumberAnimation {} } + height: units.gu(6) + + property bool shown: false + onShownChanged: { + if (shown) { + searchTextField.focus = true; + } + } + + SearchField { + id: searchTextField + anchors.centerIn: parent + width: parent.width - units.gu(2) + onDisplayTextChanged: { + searchTimer.restart() + } + + Timer { + id: searchTimer + interval: 300 + onTriggered: { + client.search(searchTextField.displayText, root.showWatchApps ? AppStoreClient.TypeWatchapp : AppStoreClient.TypeWatchface); + } + } + } + } + + Item { + anchors { left: parent.left; top: searchField.bottom; right: parent.right; bottom: parent.bottom } + ListView { + anchors.fill: parent + model: ApplicationsFilterModel { + id: appsFilterModel + model: client.model + } + clip: true + section.property: "groupId" + section.labelPositioning: ViewSection.CurrentLabelAtStart | + ViewSection.InlineLabels + section.delegate: ListItem { + height: section ? label.implicitHeight + units.gu(3) : 0 + + Rectangle { + anchors.fill: parent + color: "white" + } + + Row { + anchors.fill: parent + anchors.margins: units.gu(1) + Label { + id: label + text: client.model.groupName(section) + font.pixelSize: Theme.fontSizeLarge + // font.weight: Font.DemiBold + elide: Text.ElideRight + width: parent.width + } + Button { + implicitWidth: seeAllLabel.implicitWidth + height + Row { + anchors.verticalCenter: parent.verticalCenter + Label { + id: seeAllLabel + text: qsTr("See all") + } + IconButton { + implicitHeight: parent.height + implicitWidth: height + icon.source: "image://theme/icon-m-forward" + } + } + onClicked: { + pageStack.push(Qt.resolvedUrl("AppStorePage.qml"), {pebble: root.pebble, link: client.model.groupLink(section), title: client.model.groupName(section)}); + } + } + } + } + + footer: Item { + height: client.model.links.length > 0 ? units.gu(6) : 0 + width: parent.width + + Row { + anchors { + fill: parent + margins: units.gu(1) + } + spacing: units.gu(1) + + Repeater { + model: client.model.links + Button { + text: client.model.linkName(client.model.links[index]) + onClicked: client.fetchLink(client.model.links[index]); + color: UbuntuColors.orange + width: parent.width + } + } + } + } + + delegate: ListItem { + height: delegateColumn.height + units.gu(2) + + Row { + id: delegateRow + anchors.fill: parent + anchors.margins: units.gu(1) + spacing: units.gu(1) + + AnimatedImage { + source: model.icon + asynchronous: true + // sourceSize.width: width + // sourceSize.height: height + } + + Column { + id: delegateColumn + width: parent.width + //Layout.fillHeight: true; + Label { + width: parent.width + text: model.name + font.weight: Font.DemiBold + elide: Text.ElideRight + } + Label { + width: parent.width + text: model.category + } + Row { + IconButton { + icon.source: "image://theme/icon-m-back" + id: like + //Layout.preferredHeight: parent.height + //Layout.preferredWidth: height + implicitHeight: parent.height + } + Label { + width: parent.width + text: model.hearts + } + IconButton { + id: tickIcon + icon.source: "image://theme/icon-m-acknowledge" + implicitHeight: parent.height + //Layout.preferredWidth: height + visible: root.pebble.installedApps.contains(model.storeId) || root.pebble.installedWatchfaces.contains(model.storeId) + Connections { + target: root.pebble.installedApps + onTargetChanged: { + tickIcon.visible = root.pebble.installedApps.contains(model.storeId) || root.pebble.installedWatchfaces.contains(model.storeId) + } + } + + Connections { + target: root.pebble.installedWatchfaces + onTargetChanged: { + tickIcon.visible = root.pebble.installedApps.contains(model.storeId) || root.pebble.installedWatchfaces.contains(model.storeId) + } + } + + } + } + } + + } + + onClicked: { + client.fetchAppDetails(model.storeId); + pageStack.push(Qt.resolvedUrl("AppStoreDetailsPage.qml"), {app: appsFilterModel.get(index), pebble: root.pebble}) + } + } + } + + // RowLayout { + // id: buttonRow + // anchors { left: parent.left; bottom: parent.bottom; right: parent.right; margins: units.gu(1) } + // spacing: units.gu(1) + // Button { + // text: qsTr("Previous") + // Layout.fillWidth: true + // enabled: client.offset > 0 + // onClicked: { + // client.previous() + // } + // } + // Button { + // text: qsTr("Next") + // Layout.fillWidth: true + // onClicked: { + // client.next() + // } + // } + // } + } + + BusyIndicator { + anchors.centerIn: parent + running: client.busy + } + } +} + diff --git a/rockwork/ContentPeerPickerPage.qml b/rockwork/qml/ContentPeerPickerPage.qml index 7ee9702..9f9917f 100644 --- a/rockwork/ContentPeerPickerPage.qml +++ b/rockwork/qml/ContentPeerPickerPage.qml @@ -1,7 +1,6 @@ -import QtQuick 2.4 -import Ubuntu.Components 1.3 -import Ubuntu.Content 1.3 -import RockWork 1.0 +import QtQuick 2.0 +import Sailfish.Silica 1.0 +import RockPool 1.0 Page { id: pickerPage diff --git a/rockwork/qml/CoverPage.qml b/rockwork/qml/CoverPage.qml new file mode 100644 index 0000000..962e876 --- /dev/null +++ b/rockwork/qml/CoverPage.qml @@ -0,0 +1,44 @@ +import QtQuick 2.0 +import Sailfish.Silica 1.0 + +CoverBackground { + property var pebble: null + Image { + fillMode: Image.PreserveAspectCrop + anchors.fill: parent + source: "back-cover.png" + } + + Label { + id: label + anchors.horizontalCenter: parent.horizontalCenter + anchors.bottom: state.top + anchors.bottomMargin: Theme.paddingSmall + font.pointSize: Theme.fontSizeExtraLarge + text: pebble.name ? pebble.name : "Pebble" + } + Label { + id: state + anchors.horizontalCenter: parent.horizontalCenter + anchors.bottom: parent.verticalCenter + font.pointSize: Theme.fontSizeExtraSmall + color: Theme.highlightColor + text: pebble.connected ? qsTr("connected") : qsTr("disconnected") + } + + CoverActionList { + id: coverAction + enabled: pebble.connected + + CoverAction { + iconSource: pebble.connected ? "image://theme/icon-cover-transfers" : "image://theme/icon-cover-sync" + onTriggered: { + if (pebble.connected) { + pebble.requestScreenshot(); + } else { + pebble.reconnect(); + } + } + } + } +} diff --git a/rockwork/DeveloperToolsPage.qml b/rockwork/qml/DeveloperToolsPage.qml index 2f77254..dec03d1 100644 --- a/rockwork/DeveloperToolsPage.qml +++ b/rockwork/qml/DeveloperToolsPage.qml @@ -1,8 +1,6 @@ -import QtQuick 2.4 -import QtQuick.Layouts 1.1 -import Ubuntu.Components 1.3 -import Ubuntu.Components.Popups 1.3 -import Ubuntu.Content 1.3 +import QtQuick 2.0 +import Sailfish.Silica 1.0 +import RockPool 1.0 Page { id: root diff --git a/rockwork/FirmwareUpgradePage.qml b/rockwork/qml/FirmwareUpgradePage.qml index 3281a12..0b0a6d5 100644 --- a/rockwork/FirmwareUpgradePage.qml +++ b/rockwork/qml/FirmwareUpgradePage.qml @@ -1,5 +1,5 @@ -import QtQuick 2.4 -import Ubuntu.Components 1.3 +import QtQuick 2.0 +import Sailfish.Silica 1.0 Page { id: root diff --git a/rockwork/HealthSettingsDialog.qml b/rockwork/qml/HealthSettingsDialog.qml index 94e5d22..66a0215 100644 --- a/rockwork/HealthSettingsDialog.qml +++ b/rockwork/qml/HealthSettingsDialog.qml @@ -1,8 +1,6 @@ -import QtQuick 2.4 -import QtQuick.Layouts 1.1 -import Ubuntu.Components 1.3 -import Ubuntu.Components.Popups 1.3 -import Ubuntu.Components.ListItems 1.3 +import QtQuick 2.0 +import Sailfish.Silica 1.0 +import RockPool 1.0 Dialog { id: root diff --git a/rockwork/ImportPackagePage.qml b/rockwork/qml/ImportPackagePage.qml index 4f86f78..5de3df0 100644 --- a/rockwork/ImportPackagePage.qml +++ b/rockwork/qml/ImportPackagePage.qml @@ -1,6 +1,6 @@ -import QtQuick 2.4 -import Ubuntu.Components 1.3 -import Ubuntu.Content 1.3 +import QtQuick 2.0 +import Sailfish.Silica 1.0 +import RockPool 1.0 Page { id: root diff --git a/rockwork/qml/InfoPage.qml b/rockwork/qml/InfoPage.qml new file mode 100644 index 0000000..b23aed1 --- /dev/null +++ b/rockwork/qml/InfoPage.qml @@ -0,0 +1,84 @@ +import QtQuick 2.0 +import Sailfish.Silica 1.0 + +Page { + title: "About RockWork" + + Flickable { + anchors.fill: parent + contentHeight: contentColumn.height + units.gu(4) + + ColumnLayout { + id: contentColumn + anchors { left: parent.left; top: parent.top; right: parent.right; margins: units.gu(2) } + spacing: units.gu(2) + + RowLayout { + Layout.fillWidth: true + spacing: units.gu(2) + UbuntuShape { + source: Image { + anchors.fill: parent + source: "artwork/rockwork.svg" + } + height: units.gu(6) + width: height + } + + Label { + text: i18n.tr("Version %1").arg(version) + Layout.fillWidth: true + fontSize: "large" + } + } + + ThinDivider {} + + Label { + text: i18n.tr("Contributors") + Layout.fillWidth: true + font.bold: true + } + Label { + text: "Michael Zanetti<br>Brian Douglas<br>Katharine Berry" + Layout.fillWidth: true + } + + ThinDivider {} + + Label { + text: i18n.tr("Legal") + Layout.fillWidth: true + font.bold: true + } + + Label { + text: "This program is free software: you can redistribute it and/or modify" + + "it under the terms of the GNU General Public License as published by" + + "the Free Software Foundation, version 3 of the License.<br>" + + + "This program is distributed in the hope that it will be useful," + + "but WITHOUT ANY WARRANTY; without even the implied warranty of" + + "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the" + + "GNU General Public License for more details.<br>" + + + "You should have received a copy of the GNU General Public License" + + "along with this program. If not, see <http://www.gnu.org/licenses/>." + Layout.fillWidth: true + wrapMode: Text.WordWrap + } + + Label { + text: i18n.tr("This application is neither affiliated with nor endorsed by Pebble Technology Corp.") + Layout.fillWidth: true + wrapMode: Text.WordWrap + } + Label { + text: i18n.tr("Pebble is a trademark of Pebble Technology Corp.") + Layout.fillWidth: true + wrapMode: Text.WordWrap + } + } + } +} + diff --git a/rockwork/qml/InstalledAppDelegate.qml b/rockwork/qml/InstalledAppDelegate.qml new file mode 100644 index 0000000..e910a40 --- /dev/null +++ b/rockwork/qml/InstalledAppDelegate.qml @@ -0,0 +1,78 @@ +import QtQuick 2.0 +import Sailfish.Silica 1.0 +import RockPool 1.0 + +ListItem { + id: root + + property string uuid: "" + property string name: "" + property string iconSource: "" + property string vendor: "" + property bool hasSettings: false + property alias hasGrip: grip.visible + property bool isSystemApp: false + + signal deleteApp(); + signal configureApp(); + + menu: ContextMenu { + MenuItem { + visible: !root.isSystemApp + text: "Delete" + onClicked: { + root.deleteApp(); + } + } + MenuItem { + visible: root.hasSettings + text: "Settings" + onClicked: { + print("Settings triggered") + root.configureApp(); + } + } + } + + Row { + anchors { + fill: parent + //margins: units.gu(1) + } + //spacing: units.gu(1) + + SystemAppIcon { + isSystemApp: root.isSystemApp + uuid: root.uuid + iconSource: root.iconSource + } + + Column { + width: parent.width + Label { + text: root.name + width: parent.width + } + + Label { + text: root.vendor + width: parent.width + font.pixelSize: Theme.fontSizeSmall + } + } + + Item { + id: grip +// Layout.fillHeight: true +// Layout.preferredWidth: height + opacity: (root.contentMoving || root.swiped || root.dragging) ? 0 : 1 + Behavior on opacity { NumberAnimation {} } + IconButton { + //width: units.gu(3) + height: width + anchors.centerIn: parent + icon.source: "image://theme/icon-m-gesture" + } + } + } +} diff --git a/rockwork/qml/InstalledAppsPage.qml b/rockwork/qml/InstalledAppsPage.qml new file mode 100644 index 0000000..f7c8113 --- /dev/null +++ b/rockwork/qml/InstalledAppsPage.qml @@ -0,0 +1,205 @@ +import QtQuick 2.0 +import Sailfish.Silica 1.0 +import RockPool 1.0 + +Page { + id: root + + property var pebble: null + property bool showWatchApps: false + property bool showWatchFaces: false + + SilicaFlickable { + id: flickable + anchors.top: parent.top + width: parent.width + PullDownMenu { + MenuItem { + text: qsTr("Add") + onClicked: pageStack.push(Qt.resolvedUrl("AppStorePage.qml"), {pebble: root.pebble, showWatchApps: root.showWatchApps, showWatchFaces: root.showWatchFaces}) + } + } + + PageHeader { + title: showWatchApps ? (showWatchFaces ? qsTr("Apps & Watchfaces") : qsTr("Apps")) : qsTr("Watchfaces") + } + + function configureApp(uuid) { + // The health app is special :/ + if (uuid == "{36d8c6ed-4c83-4fa1-a9e2-8f12dc941f8c}") { + var popup = PopupUtils.open(Qt.resolvedUrl("HealthSettingsDialog.qml"), root, {healthParams: pebble.healthParams}); + popup.accepted.connect(function() { + pebble.healthParams = popup.healthParams + }) + } else { + pebble.requestConfigurationURL(uuid); + } + } + + Item { + anchors.fill: parent + ListView { + id: listView + anchors.fill: parent + model: root.showWatchApps ? root.pebble.installedApps : root.pebble.installedWatchfaces + clip: true + property real realContentY: contentY + originY + + delegate: InstalledAppDelegate { + id: delegate + uuid: model.uuid + name: model.name + iconSource: model.icon + vendor: model.vendor + visible: dndArea.draggedIndex !== index + hasGrip: index > 0 + isSystemApp: model.isSystemApp + hasSettings: model.hasSettings + + onDeleteApp: { + pebble.removeApp(model.uuid) + } + onConfigureApp: { + root.configureApp(model.uuid) + } + onClicked: { + PopupUtils.open(dialogComponent, root, {app: listView.model.get(index)}) + } + } + } + MouseArea { + id: dndArea + anchors { + top: parent.top + bottom: parent.bottom + right: parent.right + } + drag.axis: Drag.YAxis + propagateComposedEvents: true + //width: units.gu(5) + + property int startY: 0 + property int draggedIndex: -1 + + + onPressAndHold: { + startY = mouseY; + draggedIndex = Math.floor((listView.realContentY + mouseY) / fakeDragItem.height) + if (draggedIndex == 0) { + print("cannot drag settings app"); + return; + } + + var draggedItem = listView.model.get(draggedIndex); + fakeDragItem.uuid = draggedItem.uuid; + fakeDragItem.name = draggedItem.name; + fakeDragItem.vendor = draggedItem.vendor; + fakeDragItem.iconSource = draggedItem.icon; + fakeDragItem.isSystemApp = draggedItem.isSystemApp; + fakeDragItem.y = (fakeDragItem.height * draggedIndex) - listView.realContentY + drag.target = fakeDragItem; + } + + onMouseYChanged: { + var newIndex = Math.floor((listView.realContentY + mouseY) / fakeDragItem.height) + + if (newIndex > draggedIndex) { + newIndex = draggedIndex + 1; + } else if (newIndex < draggedIndex) { + newIndex = draggedIndex - 1; + } else { + return; + } + + if (newIndex >= 1 && newIndex < listView.count) { + listView.model.move(draggedIndex, newIndex); + draggedIndex = newIndex; + } + } + + onReleased: { + if (draggedIndex > -1) { + listView.model.commitMove(); + draggedIndex = -1; + drag.target = null; + } + } + } + } + + + + InstalledAppDelegate { + id: fakeDragItem + visible: dndArea.draggedIndex != -1 + + } + + Component { + id: dialogComponent + Dialog { + id: dialog + property var app: null + + Row { + SystemAppIcon { + height: titleCol.height + width: height + isSystemApp: app.isSystemApp + uuid: app.uuid + iconSource: app.icon + } + + Column { + id: titleCol + width: parent.width; + + Label { + width: parent.width; + text: app.name + font.pixelSize: Theme.fontSizeLarge + } + Label { + width: parent.width; + text: app.vendor + } + } + } + + Button { + text: qsTr("Launch") + color: UbuntuColors.green + onClicked: { + pebble.launchApp(app.uuid); + PopupUtils.close(dialog); + } + } + + Button { + text: qsTr("Configure") + color: UbuntuColors.blue + visible: app.hasSettings + onClicked: { + root.configureApp(app.uuid); + PopupUtils.close(dialog); + } + } + + Button { + text: qsTr("Delete") + color: UbuntuColors.red + visible: !app.isSystemApp + onClicked: { + pebble.removeApp(app.uuid); + PopupUtils.close(dialog); + } + } + + Button { + text: qsTr("Close") + onClicked: PopupUtils.close(dialog) + } + } + } + } +} diff --git a/rockwork/qml/Main.qml b/rockwork/qml/Main.qml new file mode 100644 index 0000000..aae852b --- /dev/null +++ b/rockwork/qml/Main.qml @@ -0,0 +1,45 @@ +import QtQuick 2.0 +import Sailfish.Silica 1.0 +import RockPool 1.0 + +/*! + \brief MainView with a Label and Button elements. +*/ + +ApplicationWindow { + id: app + + ServiceController { + id: serviceController + Component.onCompleted: { + if (!serviceController.serviceRunning) { + print("Service not running. Starting now.") + serviceController.startService(); + } + if (pebbles.version !== version) { + print("Service file version (", version, ") is not equal running service version (", pebbles.version, "). Restarting service.") + serviceController.restartService(); + } + } + } + + Pebbles { + id: pebbles + onCountChanged: loadStack() + } + + function loadStack() { + pageStack.clear() + if (pebbles.count == 1) { + pageStack.push(Qt.resolvedUrl("MainMenuPage.qml"), {pebble: pebbles.get(0)}) + app.cover.replace(Qt.resolvedUrl("CoverPage.qml"), {pebble: pebbles.get(0)}) + } else { + pageStack.push(Qt.resolvedUrl("PebblesPage.qml")) + } + } + + PageStack { + id: pageStack + Component.onCompleted: loadStack(); + } +} diff --git a/rockwork/qml/MainMenuPage.qml b/rockwork/qml/MainMenuPage.qml new file mode 100644 index 0000000..6713d70 --- /dev/null +++ b/rockwork/qml/MainMenuPage.qml @@ -0,0 +1,292 @@ +import QtQuick 2.0 +import Sailfish.Silica 1.0 + +Page { + id: root + + property var pebble: null + + SilicaFlickable { + id: flickable + anchors.fill: parent + contentHeight: column.height + + VerticalScrollDecorator { flickable: flickable } + + PullDownMenu { + MenuItem { + text: qsTr("About") + onClicked: { + pageStack.push(Qt.resolvedUrl("InfoPage.qml")) + } + } + MenuItem { + text: qsTr("Developer tools") + onClicked: { + pageStack.push(Qt.resolvedUrl("DeveloperToolsPage.qml"), {pebble: root.pebble}) + } + } + } + Column { + id: column + width: root.width + spacing: Theme.paddingLarge + PageHeader { + title: qsTr("RockPool") + } + + ListView { + model: mainMenuModel + } + + //Creating the menu list this way to allow the text field to be translatable (http://askubuntu.com/a/476331) + ListModel { + id: mainMenuModel + dynamicRoles: true + } + + Component.onCompleted: { + populateMainMenu(); + } + + Connections { + target: root.pebble + onFirmwareUpgradeAvailableChanged: { + populateMainMenu(); + } + } + + function populateMainMenu() { + mainMenuModel.clear(); + + mainMenuModel.append({ + icon: "stock_notification", + text: qsTr("Manage notifications"), + page: "NotificationsPage.qml", + color: "blue" + }); + + mainMenuModel.append({ + icon: "stock_application", + text: qsTr("Manage Apps"), + page: "InstalledAppsPage.qml", + showWatchApps: true, + color: "green" + }); + + mainMenuModel.append({ + icon: "clock-app-symbolic", + text: qsTr("Manage Watchfaces"), + page: "InstalledAppsPage.qml", + showWatchFaces: true, + color: "black" + }); + + mainMenuModel.append({ + icon: "settings", + text: qsTr("Settings"), + page: "SettingsPage.qml", + showWatchFaces: true, + color: "gold" + }); + + if (root.pebble.firmwareUpgradeAvailable) { + mainMenuModel.append({ + icon: "preferences-system-updates-symbolic", + text: qsTr("Firmware upgrade"), + page: "FirmwareUpgradePage.qml", + color: "red" + }); + } + } + + PebbleModels { + id: modelModel + } + + Column { + anchors.fill: parent + Item { + //Layout.alignment: Qt.AlignHCenter + width: root.width + Image { + id: watchImage + width: implicitWidth * height / implicitHeight + height: parent.height + anchors.horizontalCenter: parent.horizontalCenter + + source: Qt.resolvedUrl("qrc:///"+modelModel.get(root.pebble.model).image) + fillMode: Image.PreserveAspectFit + } + Item { + id: watchFace + height: parent.height * (modelModel.get(root.pebble.model - 1).shape === "rectangle" ? .5 : .515) + width: height * (modelModel.get(root.pebble.model - 1).shape === "rectangle" ? .85 : 1) + anchors.centerIn: parent + anchors.horizontalCenterOffset: units.dp(1) + anchors.verticalCenterOffset: units.dp(modelModel.get(root.pebble.model - 1).shape === "rectangle" ? 0 : 1) + + Image { + id: image + anchors.fill: parent + source: "file://" + root.pebble.screenshots.latestScreenshot + visible: false + } + + Component.onCompleted: { + if (!root.pebble.screenshots.latestScreenshot) { + root.pebble.requestScreenshot(); + } + } + + Rectangle { + id: textItem + anchors.fill: parent + layer.enabled: true + radius: modelModel.get(root.pebble.model - 1).shape === "rectangle" ? units.gu(.5) : height / 2 + // This item should be used as the 'mask' + layer.samplerName: "maskSource" + layer.effect: ShaderEffect { + property var colorSource: image; + fragmentShader: " + uniform lowp sampler2D colorSource; + uniform lowp sampler2D maskSource; + uniform lowp float qt_Opacity; + varying highp vec2 qt_TexCoord0; + void main() { + gl_FragColor = + texture2D(colorSource, qt_TexCoord0) + * texture2D(maskSource, qt_TexCoord0).a + * qt_Opacity; + } + " + } + } + } + } + Column { + width: root.width + spacing: units.gu(2) + Rectangle { + height: units.gu(10) + width: height + radius: height / 2 + color: root.pebble.connected ? "green" : "red" + + IconButton { + anchors.fill: parent + anchors.margins: units.gu(2) + icon.source: root.pebble.connected ? "image://theme/icon-m-acknowledge" : "image://theme/icon-m-reset" + } + } + + Label { + text: root.pebble.connected ? qsTr("Connected") : qsTr("Disconnected") + width: root.width + } + } + } + + + Column { + width: root.width + //Layout.preferredHeight: childrenRect.height + spacing: menuRepeater.count > 0 ? 0 : units.gu(2) + Label { + text: qsTr("Your Pebble smartwatch is disconnected. Please make sure it is powered on, within range and it is paired properly in the Bluetooth System Settings.") + width: parent.width - units.gu(4) + anchors.horizontalCenter: parent.horizontalCenter + wrapMode: Text.WordWrap + visible: !root.pebble.connected + font.pixelSize: Theme.fontSizeLarge + horizontalAlignment: Text.AlignHCenter + } + + Label { + text: qsTr("Your Pebble smartwatch is in factory mode and needs to be initialized.") + width: parent.width - units.gu(4) + anchors.horizontalCenter: parent.horizontalCenter + wrapMode: Text.WordWrap + visible: root.pebble.connected && root.pebble.recovery && !root.pebble.upgradingFirmware + font.pixelSize: Theme.fontSizeLarge + horizontalAlignment: Text.AlignHCenter + } + Button { + text: qsTr("Initialize Pebble") + onClicked: root.pebble.performFirmwareUpgrade(); + visible: root.pebble.connected && root.pebble.recovery && !root.pebble.upgradingFirmware + color: "orange" + anchors.horizontalCenter: parent.horizontalCenter + } + + Rectangle { + id: upgradeIcon + height: units.gu(10) + width: height + radius: width / 2 + color: Theme.highlightColor + anchors.horizontalCenter: parent.horizontalCenter + BusyIndicator { + anchors.horizontalCenter: parent.horizontalCenter + running: upgradeInProgress + size: BusyIndicatorSize.Large + } + visible: root.pebble.connected && root.pebble.upgradingFirmware + } + + Label { + text: qsTr("Upgrading...") + font.pixelSize: Theme.fontSizeLarge + anchors.horizontalCenter: parent.horizontalCenter + visible: root.pebble.connected && root.pebble.upgradingFirmware + } + + Repeater { + id: menuRepeater + model: root.pebble.connected && !root.pebble.recovery && !root.pebble.upgradingFirmware ? mainMenuModel : null + delegate: ListItem { + + Row { + anchors.fill: parent + anchors.margins: units.gu(1) + + Rectangle { + //Layout.fillHeight: true + //Layout.preferredWidth: height + //backgroundColor: model.color + Image { + anchors.fill: parent + anchors.margins: units.gu(.5) + source: model.icon + } + } + + + Label { + text: model.text + width: page.width + } + } + + onClicked: { + var options = {}; + options["pebble"] = root.pebble + var modelItem = mainMenuModel.get(index) + options["showWatchApps"] = modelItem.showWatchApps + options["showWatchFaces"] = modelItem.showWatchFaces + pageStack.push(Qt.resolvedUrl(model.page), options) + } + } + } + } + } + } + Connections { + target: pebble + onOpenURL: { + if (url) { + pageStack.push(Qt.resolvedUrl("AppSettingsPage.qml"), {uuid: uuid, url: url, pebble: pebble}) + } + } + } +} diff --git a/rockwork/qml/NotificationsPage.qml b/rockwork/qml/NotificationsPage.qml new file mode 100644 index 0000000..3942ecf --- /dev/null +++ b/rockwork/qml/NotificationsPage.qml @@ -0,0 +1,99 @@ +import QtQuick 2.0 +import Sailfish.Silica 1.0 +import RockPool 1.0 + +Page { + id: root + + property var pebble: null + + SilicaFlickable { + id: flickable + anchors.fill: parent + contentHeight: column.height + PageHeader { + title: qsTr("Notifications") + } + Column { + + anchors.fill: parent + anchors.topMargin: units.gu(1) + + + + Item { + width: parent.width + implicitHeight: infoLabel.height + + Label { + id: infoLabel + anchors { + left: parent.left + right: parent.right + margins: units.gu(2) + } + + wrapMode: Text.WordWrap + text: i18n.tr("Entries here will be added as notifications appear on the phone. Selected notifications will be shown on your Pebble smartwatch.") + } + } + + + ListView { + width: parent.width + //Layout.fillHeight: true + clip: true + model: root.pebble.notifications + + delegate: ListItem { + Item { + Rectangle { + //SlotsLayout.position: SlotsLayout.Leading; + height: units.gu(5) + width: height + color: { + // Add some hacks for known icons + switch (model.icon) { + case "calendar": + return "orange"; + case "settings": + return "grey"; + case "dialog-question-symbolic": + return "red"; + case "alarm-clock": + return "purple"; + case "gpm-battery-050": + return "green"; + } + return "black" + } + // source: Image { + // height: parent.height + // width: parent.width + // source: model.icon.indexOf("/") === 0 ? "file://" + model.icon : "" + // } + Label { + text: model.name + } + + IconButton { + anchors.fill: parent + anchors.margins: units.gu(.5) + icon.source: model.icon.indexOf("/") !== 0 ? model.icon : "" + //color: "white" + } + } + + Switch { + checked: model.enabled + // SlotsLayout.position: SlotsLayout.Trailing; + onClicked: { + root.pebble.setNotificationFilter(model.name, checked) + } + } + } + } + } + } + } +} diff --git a/rockwork/qml/PebbleModels.qml b/rockwork/qml/PebbleModels.qml new file mode 100644 index 0000000..d2248c1 --- /dev/null +++ b/rockwork/qml/PebbleModels.qml @@ -0,0 +1,28 @@ +import QtQuick 2.0 + +ListModel { + id: modelModel + ListElement { image: 'tintin-black.png'; shape: "rectangle" } // Fallback for Unknown + ListElement { image: 'tintin-black.png'; shape: "rectangle" } + ListElement { image: 'tintin-white.png'; shape: "rectangle" } + ListElement { image: 'tintin-red.png'; shape: "rectangle" } + ListElement { image: 'tintin-orange.png'; shape: "rectangle" } + ListElement { image: 'tintin-grey.png'; shape: "rectangle" } + ListElement { image: 'bianca-silver.png'; shape: "rectangle" } + ListElement { image: 'bianca-black.png'; shape: "rectangle" } + ListElement { image: 'tintin-blue.png'; shape: "rectangle" } + ListElement { image: 'tintin-green.png'; shape: "rectangle" } + ListElement { image: 'tintin-pink.png'; shape: "rectangle" } + ListElement { image: 'snowy-white.png'; shape: "rectangle" } + ListElement { image: 'snowy-black.png'; shape: "rectangle" } + ListElement { image: 'snowy-red.png'; shape: "rectangle" } + ListElement { image: 'bobby-silver.png'; shape: "rectangle" } + ListElement { image: 'bobby-black.png'; shape: "rectangle" } + ListElement { image: 'bobby-gold.png'; shape: "rectangle" } + ListElement { image: 'spalding-14mm-silver.png'; shape: "round" } + ListElement { image: 'spalding-14mm-black.png'; shape: "round" } + ListElement { image: 'spalding-20mm-silver.png'; shape: "round" } + ListElement { image: 'spalding-20mm-black.png'; shape: "round" } + ListElement { image: 'spalding-14mm-rose-gold.png'; shape: "round" } +} + diff --git a/rockwork/PebblesPage.qml b/rockwork/qml/PebblesPage.qml index a973b0a..13aca60 100644 --- a/rockwork/PebblesPage.qml +++ b/rockwork/qml/PebblesPage.qml @@ -1,6 +1,6 @@ -import QtQuick 2.4 -import QtQuick.Layouts 1.1 -import Ubuntu.Components 1.3 +import QtQuick 2.0 +import Sailfish.Silica 1.0 +import RockPool 1.0 Page { title: i18n.tr("Manage Pebble Watches") diff --git a/rockwork/ScreenshotsPage.qml b/rockwork/qml/ScreenshotsPage.qml index fdbeb9a..28ca866 100644 --- a/rockwork/ScreenshotsPage.qml +++ b/rockwork/qml/ScreenshotsPage.qml @@ -1,9 +1,6 @@ -import QtQuick 2.4 -import QtQuick.Layouts 1.1 -import Ubuntu.Components 1.3 -import Ubuntu.Components.Popups 1.3 -import Ubuntu.Content 1.3 -import RockWork 1.0 +import QtQuick 2.0 +import Sailfish.Silica 1.0 +import RockPool 1.0 Page { id: root diff --git a/rockwork/SettingsPage.qml b/rockwork/qml/SettingsPage.qml index 153aaf4..8116f7a 100644 --- a/rockwork/SettingsPage.qml +++ b/rockwork/qml/SettingsPage.qml @@ -1,7 +1,6 @@ -import QtQuick 2.4 -import QtQuick.Layouts 1.1 -import Ubuntu.Components 1.3 -import Ubuntu.Components.ListItems 1.3 +import QtQuick 2.0 +import Sailfish.Silica 1.0 +import RockPool 1.0 Page { id: root diff --git a/rockwork/SystemAppIcon.qml b/rockwork/qml/SystemAppIcon.qml index 88e37bc..3823cf2 100644 --- a/rockwork/SystemAppIcon.qml +++ b/rockwork/qml/SystemAppIcon.qml @@ -1,5 +1,6 @@ -import QtQuick 2.4 -import Ubuntu.Components 1.3 +import QtQuick 2.0 +import Sailfish.Silica 1.0 +import RockPool 1.0 Item { id: root @@ -8,10 +9,10 @@ Item { property string uuid: "" property string iconSource: "" - UbuntuShape { + Rectangle { anchors.fill: parent visible: root.isSystemApp - backgroundColor: { + color: { switch (root.uuid) { case "{07e0d9cb-8957-4bf7-9d42-35bf47caadfe}": return "gray"; @@ -32,28 +33,27 @@ Item { return ""; } } - Icon { + IconButton { anchors.fill: parent implicitHeight: height - anchors.margins: units.gu(1) + //anchors.margins: units.gu(1) visible: root.isSystemApp - color: "white" - name: { + icon.source: { switch (root.uuid) { case "{07e0d9cb-8957-4bf7-9d42-35bf47caadfe}": - return "settings"; + return "image://theme/icon-m-developer-mode"; case "{18e443ce-38fd-47c8-84d5-6d0c775fbe55}": - return "clock-app-symbolic"; + return "image://theme/icon-m-clock"; case "{36d8c6ed-4c83-4fa1-a9e2-8f12dc941f8c}": - return "like"; + return "image://theme/icon-m-like"; case "{1f03293d-47af-4f28-b960-f2b02a6dd757}": - return "stock_music"; + return "image://theme/icon-m-music"; case "{b2cae818-10f8-46df-ad2b-98ad2254a3c1}": - return "stock_notification"; + return "image://theme/icon-m-notifications"; case "{67a32d95-ef69-46d4-a0b9-854cc62f97f9}": - return "stock_alarm-clock"; + return "image://theme/icon-m-alarm"; case "{8f3c8686-31a1-4f5f-91f5-01600c9bdc59}": - return "clock-app-symbolic"; + return "image://theme/icon-m-clock"; } return ""; } diff --git a/rockwork/rockpool.desktop b/rockwork/rockpool.desktop new file mode 100644 index 0000000..989d24d --- /dev/null +++ b/rockwork/rockpool.desktop @@ -0,0 +1,7 @@ +[Desktop Entry] +Name=RockPool +Exec=rockpool +Icon=rockpool +Type=Application +X-Nemo-Application-Type=silica-qt5 + diff --git a/rockwork/rockpool.png b/rockwork/rockpool.png Binary files differnew file mode 100644 index 0000000..571ac11 --- /dev/null +++ b/rockwork/rockpool.png diff --git a/rockwork/rockwork.apparmor b/rockwork/rockwork.apparmor deleted file mode 100644 index 9756323..0000000 --- a/rockwork/rockwork.apparmor +++ /dev/null @@ -1,7 +0,0 @@ -{ - "policy_groups": [ - "networking" - ], - "policy_version": 1.3, - "template": "unconfined" -} diff --git a/rockwork/rockwork.desktop b/rockwork/rockwork.desktop deleted file mode 100644 index 0a75199..0000000 --- a/rockwork/rockwork.desktop +++ /dev/null @@ -1,8 +0,0 @@ -[Desktop Entry] -Name=RockWork -Exec=rockwork -Icon=rockwork/rockwork.svg -Terminal=false -Type=Application -X-Ubuntu-Touch=true - diff --git a/rockwork/rockwork.pro b/rockwork/rockwork.pro index 43b1dea..a695e42 100644 --- a/rockwork/rockwork.pro +++ b/rockwork/rockwork.pro @@ -1,72 +1,54 @@ -TEMPLATE = app -TARGET = rockwork - -include(../version.pri) -load(ubuntu-click) - -QT += qml quick dbus - -CONFIG += c++11 - -HEADERS += \ - notificationsourcemodel.h \ - servicecontrol.h \ - pebble.h \ - pebbles.h \ - applicationsmodel.h \ - applicationsfiltermodel.h \ - appstoreclient.h \ - screenshotmodel.h - -SOURCES += main.cpp \ - notificationsourcemodel.cpp \ - servicecontrol.cpp \ - pebble.cpp \ - pebbles.cpp \ - applicationsmodel.cpp \ - applicationsfiltermodel.cpp \ - appstoreclient.cpp \ - screenshotmodel.cpp - -RESOURCES += rockwork.qrc - -QML_FILES += $$files(*.qml,true) \ - $$files(*.js,true) - -CONF_FILES += rockwork.apparmor \ - rockwork.svg \ - rockwork.desktop \ - rockwork.url-dispatcher - -AP_TEST_FILES += tests/autopilot/run \ - $$files(tests/*.py,true) - -#show all the files in QtCreator -OTHER_FILES += $${CONF_FILES} \ - $${QML_FILES} \ - $${AP_TEST_FILES} \ - - -#specify where the config files are installed to -config_files.path = /rockwork -config_files.files += $${CONF_FILES} -INSTALLS+=config_files - -#install the desktop file, a translated version is -#automatically created in the build directory -desktop_file.path = /rockwork -desktop_file.files = $$OUT_PWD/rockwork.desktop -desktop_file.CONFIG += no_check_exist -INSTALLS+=desktop_file - -# Default rules for deployment. -target.path = $${UBUNTU_CLICK_BINARY_PATH} -INSTALLS+=target - -DISTFILES += \ - NotificationsPage.qml \ - PebblesPage.qml \ - AppStorePage.qml \ - AppStoreDetailsPage.qml \ - PebbleModels.qml \ - InfoPage.qml +TARGET = rockpool
+
+include(../version.pri)
+
+QT += qml quick dbus webkit quick-private webkit-private
+
+CONFIG += c++11
+CONFIG += sailfishapp
+
+HEADERS += \
+ notificationsourcemodel.h \
+ servicecontrol.h \
+ pebble.h \
+ pebbles.h \
+ applicationsmodel.h \
+ applicationsfiltermodel.h \
+ appstoreclient.h \
+ screenshotmodel.h
+
+SOURCES += main.cpp \
+ notificationsourcemodel.cpp \
+ servicecontrol.cpp \
+ pebble.cpp \
+ pebbles.cpp \
+ applicationsmodel.cpp \
+ applicationsfiltermodel.cpp \
+ appstoreclient.cpp \
+ screenshotmodel.cpp
+
+RESOURCES += rockwork.qrc
+
+QML_FILES += $$files(qml/*.qml,true)
+
+CONF_FILES += rockpool.png \
+ rockpool.desktop
+
+#show all the files in QtCreator
+OTHER_FILES += $${QML_FILES} \
+ $${CONF_FILES}
+
+#specify where the qml files are installed to
+qml.path = /usr/share/rockpool/qml
+qml.files += $${QML_FILES}
+INSTALLS+=qml
+
+#and the app icon
+icon.path = /usr/share/icons/hicolor/86x86/apps/
+icon.files = rockpool.png
+INSTALLS+=icon
+
+# Default rules for deployment.
+INSTALLS+=target icon
+target.path = /usr/bin
+
diff --git a/rockwork/rockwork.qrc b/rockwork/rockwork.qrc index 1d565a1..3cb6f76 100644 --- a/rockwork/rockwork.qrc +++ b/rockwork/rockwork.qrc @@ -1,18 +1,6 @@ <RCC> <qresource prefix="/"> - <file>Main.qml</file> - <file>NotificationsPage.qml</file> - <file>PebblesPage.qml</file> - <file>InstalledAppsPage.qml</file> - <file>MainMenuPage.qml</file> - <file>AppSettingsPage.qml</file> - <file>AppStorePage.qml</file> - <file>AppStoreDetailsPage.qml</file> - <file>InstalledAppDelegate.qml</file> - <file>SystemAppIcon.qml</file> - <file>ScreenshotsPage.qml</file> - <file>snowywhite.svg</file> - <file>snowywhite.png</file> + <file>artwork/back-cover.png</file> <file>artwork/bianca-black.png</file> <file>artwork/bianca-silver.png</file> <file>artwork/black-20mm-hole.png</file> @@ -35,14 +23,5 @@ <file>artwork/tintin-pink.png</file> <file>artwork/tintin-red.png</file> <file>artwork/tintin-white.png</file> - <file>PebbleModels.qml</file> - <file>FirmwareUpgradePage.qml</file> - <file>InfoPage.qml</file> - <file>artwork/rockwork.svg</file> - <file>DeveloperToolsPage.qml</file> - <file>ContentPeerPickerPage.qml</file> - <file>HealthSettingsDialog.qml</file> - <file>SettingsPage.qml</file> - <file>ImportPackagePage.qml</file> </qresource> </RCC> diff --git a/rockwork/rockwork.svg b/rockwork/rockwork.svg deleted file mode 100644 index e4e92c0..0000000 --- a/rockwork/rockwork.svg +++ /dev/null @@ -1,275 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?> -<!-- Created with Inkscape (http://www.inkscape.org/) --> - -<svg - xmlns:dc="http://purl.org/dc/elements/1.1/" - xmlns:cc="http://creativecommons.org/ns#" - xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" - xmlns:svg="http://www.w3.org/2000/svg" - xmlns="http://www.w3.org/2000/svg" - xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" - xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" - width="72.248886mm" - height="72.248886mm" - viewBox="0 0 255.99999 255.99999" - id="svg2" - version="1.1" - inkscape:version="0.91 r13725" - sodipodi:docname="upebble.svg"> - <defs - id="defs4"> - <filter - inkscape:collect="always" - style="color-interpolation-filters:sRGB" - id="filter4248" - x="-0.025328101" - width="1.0506562" - y="-0.013960773" - height="1.0279215"> - <feGaussianBlur - inkscape:collect="always" - stdDeviation="2.3907822" - id="feGaussianBlur4250" /> - </filter> - </defs> - <sodipodi:namedview - id="base" - pagecolor="#ffffff" - bordercolor="#666666" - borderopacity="1.0" - inkscape:pageopacity="0.0" - inkscape:pageshadow="2" - inkscape:zoom="3.959798" - inkscape:cx="89.121544" - inkscape:cy="77.044911" - inkscape:document-units="px" - inkscape:current-layer="layer1" - showgrid="true" - fit-margin-top="0" - fit-margin-left="0" - fit-margin-right="0" - fit-margin-bottom="0" - inkscape:window-width="2880" - inkscape:window-height="1752" - inkscape:window-x="0" - inkscape:window-y="48" - inkscape:window-maximized="1"> - <inkscape:grid - type="xygrid" - id="grid4136" - originx="-40.000001" - originy="-539" - snapvisiblegridlinesonly="true" - enabled="false" /> - </sodipodi:namedview> - <metadata - id="metadata7"> - <rdf:RDF> - <cc:Work - rdf:about=""> - <dc:format>image/svg+xml</dc:format> - <dc:type - rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> - <dc:title></dc:title> - </cc:Work> - </rdf:RDF> - </metadata> - <g - inkscape:label="Layer 1" - inkscape:groupmode="layer" - id="layer1" - transform="translate(-40,-257.36221)"> - <rect - style="opacity:1;fill:#78d3fc;fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" - id="rect4200" - width="256" - height="256" - x="40" - y="257.36221" /> - <path - style="opacity:1;fill:#000000;fill-opacity:0.0479798;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" - d="m 40,257.36221 256,0 -256,256 z" - id="rect4252" - inkscape:connector-curvature="0" - sodipodi:nodetypes="cccc" /> - <g - id="g4300"> - <g - style="fill:#000000;fill-opacity:1;opacity:0.291;filter:url(#filter4248)" - id="g4202" - transform="matrix(0.60632857,0,0,0.60632857,-37.462675,74.399202)"> - <path - sodipodi:nodetypes="czccc" - inkscape:connector-curvature="0" - id="path4204" - d="m 437.97969,445.08937 c 0,0 11.49464,-4.59544 12.27285,0.25253 0.77821,4.84797 2.06459,45.23266 2.06459,45.23266 -8.36034,0.32794 -13.15013,-0.0886 -13.15013,-0.0886 z" - style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> - <path - sodipodi:nodetypes="ccccc" - inkscape:connector-curvature="0" - id="path4206" - d="m 439.49492,491.6046 12.68287,0.70015 0.54937,42.27954 -13.73731,0.25254 z" - style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> - <rect - style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" - id="rect4208" - width="120" - height="95" - x="280" - y="623.36218" /> - <rect - y="307.36221" - x="280" - height="95" - width="120" - id="rect4210" - style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> - <path - sodipodi:nodetypes="zcczz" - inkscape:connector-curvature="0" - id="path4212" - d="M 228.0862,442.4309 C 228.58744,435.98794 240,437.36221 240,437.36221 l 0,42.02031 c 0,0 -14.31567,-1.22669 -13.80125,-2.84014 0.51442,-1.61345 1.3862,-27.66851 1.88745,-34.11148 z" - style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> - <path - style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" - d="M 420,643.715 337.60905,658.36221 255,643.715 l 0,-20 165,0 z" - id="path4214" - inkscape:connector-curvature="0" - sodipodi:nodetypes="cccccc" /> - <path - sodipodi:nodetypes="cccccc" - inkscape:connector-curvature="0" - id="path4216" - d="M 255,382.36221 337.39095,367.715 420,382.36221 l 0,20 -165,0 z" - style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> - <path - sodipodi:nodetypes="cczcc" - inkscape:connector-curvature="0" - id="path4218" - d="m 438.52906,535.82255 c 0,0 5.15979,0.84007 13.83236,0.44761 0.13423,13.76866 -1.20901,37.74804 -1.85634,42.35471 -0.64733,4.60667 -11.01016,-0.50508 -11.01016,-0.50508 z" - style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> - <path - sodipodi:nodetypes="zzzzzzzzz" - inkscape:connector-curvature="0" - id="path4220" - d="m 244.85206,406.56127 c 16.07143,-13.92858 66.12644,-13.34299 97.65304,-13.30725 31.5266,0.0357 73.56632,-0.53467 90.70918,15.17961 17.14286,15.71428 12.91706,70.98675 13.01566,106.0726 0.0986,35.08586 5.19864,81.42741 -13.01565,99.64169 C 415,632.3622 371.12033,628.47664 339.15317,628.18658 307.186,627.89652 263.91063,632.7014 245.3392,615.91569 226.76777,599.12997 231.43107,540.45867 231.61582,505.9352 c 0.18475,-34.52347 -2.83519,-85.44536 13.23624,-99.37393 z" - style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> - <rect - ry="20" - rx="20" - y="422.36221" - x="260" - height="174.99998" - width="155" - id="rect4222" - style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> - <rect - y="442.36221" - x="280" - height="135" - width="120" - id="rect4224" - style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> - <path - sodipodi:nodetypes="cccccccc" - inkscape:connector-curvature="0" - id="path4226" - d="m 375,442.36221 25,0 0,135 -25,0 0,-109.75206 -7.32361,-5.3033 7.32361,-4.9245 z" - style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> - </g> - <path - sodipodi:nodetypes="czccc" - inkscape:connector-curvature="0" - id="rect4177" - d="m 228.09692,344.2696 c 0,0 6.96953,-2.78634 7.44138,0.15312 0.47185,2.93946 1.25182,27.42585 1.25182,27.42585 -5.06911,0.19884 -7.9733,-0.0537 -7.9733,-0.0537 z" - style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> - <path - sodipodi:nodetypes="ccccc" - inkscape:connector-curvature="0" - id="rect4179" - d="m 229.01565,372.47312 7.68999,0.42452 0.3331,25.63529 -8.32933,0.15312 z" - style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> - <rect - style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" - id="rect4167" - width="72.75943" - height="57.601215" - x="132.30933" - y="452.36151" /> - <rect - y="260.76169" - x="132.30933" - height="57.601215" - width="72.75943" - id="rect4165" - style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> - <path - sodipodi:nodetypes="zcczz" - inkscape:connector-curvature="0" - id="rect4169" - d="m 100.8325,342.6577 c 0.30392,-3.90655 7.22368,-3.07329 7.22368,-3.07329 l 0,25.47811 c 0,0 -8.679998,-0.74378 -8.36809,-1.72206 0.311907,-0.97828 0.84049,-16.77621 1.14441,-20.68276 z" - style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> - <path - style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" - d="m 217.19532,464.702 -49.95598,8.88102 -50.08823,-8.88102 0,-12.12657 100.04421,0 z" - id="path4175" - inkscape:connector-curvature="0" - sodipodi:nodetypes="cccccc" /> - <path - sodipodi:nodetypes="cccccc" - inkscape:connector-curvature="0" - id="rect4172" - d="m 117.15111,306.23633 49.95599,-8.88102 50.08822,8.88102 0,12.12658 -100.04421,0 z" - style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> - <path - sodipodi:nodetypes="cczcc" - inkscape:connector-curvature="0" - id="rect4181" - d="m 228.43002,399.28372 c 0,0 3.12853,0.50936 8.38696,0.2714 0.0814,8.34833 -0.73306,22.88772 -1.12555,25.68087 -0.3925,2.79316 -6.67578,-0.30624 -6.67578,-0.30624 z" - style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> - <path - sodipodi:nodetypes="zzzzzzzzz" - inkscape:connector-curvature="0" - id="rect4149" - d="m 110.99812,320.90892 c 9.74457,-8.4453 40.09435,-8.09024 59.20983,-8.06857 19.11548,0.0217 44.60536,-0.32419 54.99957,9.20383 10.39421,9.52802 7.83198,43.0413 7.89177,64.31485 0.0598,21.27356 3.15208,49.37176 -7.89176,60.4156 -11.04385,11.04384 -37.64935,8.68791 -57.03195,8.51204 -19.38261,-0.17587 -45.6217,2.73747 -56.88209,-7.44019 -11.26039,-10.17766 -8.4329,-45.75175 -8.32088,-66.68431 0.11202,-20.93257 -1.71905,-51.80796 8.02551,-60.25325 z" - style="opacity:1;fill:#cbcbcb;fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> - <path - style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" - d="m 133.22587,330.48948 69.72779,0 c 6.71812,0 11.83367,5.41484 12.12657,12.12657 1.19073,27.28478 1.19022,54.56956 0,81.85435 -0.29278,6.71174 -5.40845,12.12657 -12.12657,12.12657 l -69.72779,0 c -6.71812,0 -11.82926,-5.41504 -12.12657,-12.12657 -1.18246,-26.69356 -1.65764,-53.74075 0,-81.85435 0.39543,-6.70647 5.40845,-12.12657 12.12657,-12.12657 z" - id="rect4152" - inkscape:connector-curvature="0" - sodipodi:nodetypes="sssssssss" /> - <rect - y="342.61606" - x="131.62029" - height="81.854355" - width="72.75943" - id="rect4154" - style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> - <path - sodipodi:nodetypes="cccccccc" - inkscape:connector-curvature="0" - id="rect4156" - d="m 189.2215,342.61605 15.15821,0 0,81.85436 -15.15821,0 0,-66.54581 -4.44052,-3.21555 4.44052,-2.98586 z" - style="opacity:1;fill:#78d3fc;fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> - </g> - <path - style="fill:#000000" - d="m 143.63128,393.17695 c -0.82884,-0.82884 0.32908,-1.46136 2.67524,-1.46136 3.02637,0 3.07586,-0.7116 0.31911,-4.58902 l -2.10477,-2.96041 2.0287,-2.94922 c 1.15063,-1.67272 2.20678,-4.13671 2.44014,-5.69282 0.40696,-2.71383 0.44252,-2.74828 3.27625,-3.17322 1.57564,-0.23629 4.03472,-1.23453 5.46462,-2.21832 1.42988,-0.98379 2.85437,-1.78871 3.16551,-1.78871 0.31114,0 1.68177,0.80847 3.04585,1.7966 1.40341,1.01663 3.70432,1.98019 5.29992,2.21946 2.92933,0.43928 2.99923,0.52347 3.81465,4.59457 0.23714,1.18397 1.22649,3.16119 2.19857,4.39382 0.97208,1.23265 1.76741,2.42825 1.76741,2.6569 0,0.22864 -0.83031,1.62253 -1.84514,3.09753 -2.44659,3.556 -2.38325,4.49115 0.32038,4.72947 1.19102,0.10499 2.22891,0.46766 2.30641,0.80594 0.15778,0.68864 -33.49245,1.21919 -34.17285,0.53879 z m 27.8729,-2.84521 c 0.009,-0.76112 0.83738,-2.4679 1.83992,-3.79283 l 1.82279,-2.40898 -1.58789,-2.08183 c -0.87334,-1.14501 -1.90888,-3.37431 -2.30119,-4.954 -0.68475,-2.75721 -0.82407,-2.89364 -3.48101,-3.40876 -1.52223,-0.29514 -3.68339,-1.22898 -4.80255,-2.0752 l -2.03486,-1.53859 -2.27046,1.53481 c -2.19134,1.48132 -2.85113,1.74296 -6.34208,2.51493 -1.32103,0.29212 -1.68348,0.80695 -2.01126,2.85674 -0.2199,1.37522 -1.11243,3.57721 -1.98338,4.8933 l -1.58355,2.39291 1.54803,2.0343 c 0.85141,1.11887 1.73796,2.79542 1.97011,3.72567 l 0.42209,1.69138 10.38909,0 c 10.35877,0 10.38914,-0.004 10.4062,-1.38385 z m -16.16204,-1.17442 c -3.00082,-0.83158 -3.29439,-2.70542 -0.30753,-1.96294 1.0994,0.27329 2.9676,0.49689 4.15156,0.49689 1.18396,0 3.05216,-0.2236 4.15155,-0.49689 1.34833,-0.33517 1.9989,-0.27586 1.9989,0.18225 0,1.61808 -6.44052,2.76557 -9.99448,1.78069 z m -1.87921,-5.21512 c -0.23497,-0.23497 -0.42721,-1.51123 -0.42721,-2.83614 0,-2.76084 1.40937,-2.98541 1.73071,-0.27578 0.21201,1.78766 -0.62633,3.78908 -1.3035,3.11192 z m 10.02856,-2.68238 c 0,-1.7768 0.25627,-2.46018 0.92256,-2.46018 0.6663,0 0.92257,0.68338 0.92257,2.46018 0,1.7768 -0.25627,2.46018 -0.92257,2.46018 -0.66629,0 -0.92256,-0.68338 -0.92256,-2.46018 z m -22.75668,2.7677 c 0,-0.69366 0.43166,-0.94682 1.38386,-0.81158 0.76111,0.10809 1.38385,0.47331 1.38385,0.81158 0,0.33828 -0.62274,0.70349 -1.38385,0.81159 -0.9522,0.13523 -1.38386,-0.11793 -1.38386,-0.81159 z m 37.8226,0.30318 c -0.46699,-0.7556 1.22568,-1.49279 2.13592,-0.93022 0.35999,0.22248 0.4953,0.66216 0.30068,0.97707 -0.46943,0.75955 -1.95589,0.73096 -2.4366,-0.0469 z m -32.49939,-13.42132 c -1.23387,-1.36341 -1.29125,-1.95046 -0.19065,-1.95046 1.05106,0 3.00139,2.11681 2.45435,2.66385 -0.65422,0.65422 -1.17438,0.49029 -2.2637,-0.71339 z m 27.38286,0.11435 c 0.23773,-1.20797 2.11252,-2.50883 2.72827,-1.89307 0.48678,0.48678 -1.47947,2.90348 -2.36232,2.90348 -0.31065,0 -0.47533,-0.45468 -0.36595,-1.01041 z m -13.38512,-4.7488 c -0.52662,-1.37234 -0.0519,-3.6431 0.82178,-3.93083 0.51752,-0.17043 0.76881,0.45533 0.76881,1.91443 0,2.29458 -0.99824,3.56005 -1.59059,2.0164 z" - id="path4285" - inkscape:connector-curvature="0" - sodipodi:nodetypes="ssscsssssssssssssssscsssscsssscsscsssssssssssssssssssssscssccssssssssssss" /> - <text - xml:space="preserve" - style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" - x="136.46957" - y="405.82156" - id="text4342" - sodipodi:linespacing="125%"><tspan - sodipodi:role="line" - id="tspan4344" - x="136.46957" - y="405.82156" - style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:10px;font-family:Ubuntu;-inkscape-font-specification:Ubuntu">Tomorrow</tspan></text> - </g> -</svg> diff --git a/rockwork/rockwork.url-dispatcher b/rockwork/rockwork.url-dispatcher deleted file mode 100644 index 3453482..0000000 --- a/rockwork/rockwork.url-dispatcher +++ /dev/null @@ -1,5 +0,0 @@ -[ - { - "protocol": "pebblejs" - } -] diff --git a/rockwork/servicecontrol.cpp b/rockwork/servicecontrol.cpp index 4d6903f..ced7f1a 100644 --- a/rockwork/servicecontrol.cpp +++ b/rockwork/servicecontrol.cpp @@ -5,84 +5,42 @@ #include <QDebug> #include <QCoreApplication> #include <QProcess> +#include <QDBusReply> -ServiceControl::ServiceControl(QObject *parent) : QObject(parent) +ServiceControl::ServiceControl(QObject *parent) : QObject(parent), + systemd(new QDBusInterface("org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + QDBusConnection::sessionBus(), this)) { + systemd->call("Subscribe"); -} + QDBusReply<QDBusObjectPath> unit = systemd->call("LoadUnit", ROCKPOOLD_SYSTEMD_UNIT); + if (unit.isValid()) { + unitPath = unit.value(); -QString ServiceControl::serviceName() const -{ - return m_serviceName; -} + getUnitProperties(); -void ServiceControl::setServiceName(const QString &serviceName) -{ - if (m_serviceName != serviceName) { - m_serviceName = serviceName; - emit serviceNameChanged(); + QDBusConnection::sessionBus().connect( + "org.freedesktop.systemd1", unitPath.path(), + "org.freedesktop.DBus.Properties", "PropertiesChanged", + this, SLOT(onPropertiesChanged(QString,QMap<QString,QVariant>,QStringList))); + } else { + qWarning() << unit.error().message(); } } -bool ServiceControl::serviceFileInstalled() const +void ServiceControl::onPropertiesChanged(QString interface, QMap<QString,QVariant> changed, QStringList invalidated) { - if (m_serviceName.isEmpty()) { - qDebug() << "Service name not set."; - return false; - } - QFile f(QDir::homePath() + "/.config/upstart/" + m_serviceName + ".conf"); - return f.exists(); -} - -bool ServiceControl::installServiceFile() -{ - if (m_serviceName.isEmpty()) { - qDebug() << "Service name not set. Cannot generate service file."; - return false; - } - - QFile f(QDir::homePath() + "/.config/upstart/" + m_serviceName + ".conf"); - if (f.exists()) { - qDebug() << "Service file already existing..."; - return false; - } - - if (!f.open(QFile::WriteOnly | QFile::Truncate)) { - qDebug() << "Cannot create service file"; - return false; - } - - QString appDir = qApp->applicationDirPath(); - // Try to replace version with "current" to be more robust against updates - appDir.replace(QRegExp("rockwork.mzanetti\/[0-9.]*\/"), "rockwork.mzanetti/current/"); - - f.write("start on started unity8\n"); - f.write("pre-start script\n"); - f.write(" initctl set-env LD_LIBRARY_PATH=" + appDir.toUtf8() + "/../:$LD_LIBRARY_PATH\n"); - f.write("end script\n"); - f.write("exec " + appDir.toUtf8() + "/" + m_serviceName.toUtf8() + "\n"); - f.close(); - return true; -} - -bool ServiceControl::removeServiceFile() -{ - if (m_serviceName.isEmpty()) { - qDebug() << "Service name not set."; - return false; - } - QFile f(QDir::homePath() + "/.config/upstart/" + m_serviceName + ".conf"); - return f.remove(); + qDebug() << Q_FUNC_INFO << interface << changed << invalidated; + if (interface != "org.freedesktop.systemd1.Unit") return; + if (invalidated.contains("UnitFileState") || invalidated.contains("ActiveState")) + getUnitProperties(); } bool ServiceControl::serviceRunning() const { - QProcess p; - p.start("initctl", {"status", m_serviceName}); - p.waitForFinished(); - QByteArray output = p.readAll(); - qDebug() << output; - return output.contains("running"); + return unitProperties["UnitFileState"].toString() == "enabled"; } bool ServiceControl::setServiceRunning(bool running) @@ -97,22 +55,49 @@ bool ServiceControl::setServiceRunning(bool running) bool ServiceControl::startService() { - qDebug() << "should start service"; - int ret = QProcess::execute("start", {m_serviceName}); - return ret == 0; + QDBusError reply; + systemd->call("EnableUnitFiles", QStringList() << ROCKPOOLD_SYSTEMD_UNIT, false, true); + if (reply.isValid()) { + qWarning() << reply.message(); + return false; + } else { + systemd->call("Reload"); + return true; + } } bool ServiceControl::stopService() { - qDebug() << "should stop service"; - int ret = QProcess::execute("stop", {m_serviceName}); - return ret == 0; + QDBusError reply; + systemd->call("DisableUnitFiles", QStringList() << ROCKPOOLD_SYSTEMD_UNIT, false); + if (reply.isValid()) { + qWarning() << reply.message(); + return false; + } else { + systemd->call("Reload"); + return true; + } } bool ServiceControl::restartService() { - qDebug() << "should stop service"; - int ret = QProcess::execute("restart", {m_serviceName}); - return ret == 0; + return stopService() && startService(); } +void ServiceControl::getUnitProperties() +{ + QDBusMessage request = QDBusMessage::createMethodCall( + "org.freedesktop.systemd1", unitPath.path(), + "org.freedesktop.DBus.Properties", "GetAll"); + request << "org.freedesktop.systemd1.Unit"; + QDBusReply<QVariantMap> reply = QDBusConnection::sessionBus().call(request); + if (reply.isValid()) { + QVariantMap newProperties = reply.value(); + //bool emitEnabledChanged = (unitProperties["UnitFileState"] != newProperties["UnitFileState"]); + bool emitRunningChanged = (unitProperties["ActiveState"] != newProperties["ActiveState"]); + unitProperties = newProperties; + if (emitRunningChanged) emit serviceRunning(); + } else { + qWarning() << reply.error().message(); + } +} diff --git a/rockwork/servicecontrol.h b/rockwork/servicecontrol.h index 4689506..ebab061 100644 --- a/rockwork/servicecontrol.h +++ b/rockwork/servicecontrol.h @@ -1,38 +1,37 @@ #ifndef SERVICECONTROL_H #define SERVICECONTROL_H +#include <QDBusInterface> #include <QObject> +static const QString ROCKPOOLD_SYSTEMD_UNIT("rockpoold.service"); + class ServiceControl : public QObject { Q_OBJECT - Q_PROPERTY(QString serviceName READ serviceName WRITE setServiceName NOTIFY serviceNameChanged) - Q_PROPERTY(bool serviceFileInstalled READ serviceFileInstalled NOTIFY serviceFileInstalledChanged) Q_PROPERTY(bool serviceRunning READ serviceRunning WRITE setServiceRunning NOTIFY serviceRunningChanged) public: explicit ServiceControl(QObject *parent = 0); - QString serviceName() const; - void setServiceName(const QString &serviceName); - - bool serviceFileInstalled() const; - Q_INVOKABLE bool installServiceFile(); - Q_INVOKABLE bool removeServiceFile(); - bool serviceRunning() const; bool setServiceRunning(bool running); Q_INVOKABLE bool startService(); Q_INVOKABLE bool stopService(); Q_INVOKABLE bool restartService(); +private slots: + void getUnitProperties(); + void onPropertiesChanged(QString interface, QMap<QString, QVariant> changed, QStringList invalidated); + signals: - void serviceNameChanged(); - void serviceFileInstalledChanged(); void serviceRunningChanged(); private: - QString m_serviceName; + QDBusInterface *systemd; + QDBusObjectPath unitPath; + QVariantMap unitProperties; + }; #endif // SERVICECONTROL_H diff --git a/rockwork/snowywhite.png b/rockwork/snowywhite.png Binary files differdeleted file mode 100644 index 1a354b4..0000000 --- a/rockwork/snowywhite.png +++ /dev/null diff --git a/rockwork/snowywhite.svg b/rockwork/snowywhite.svg deleted file mode 100644 index 0544670..0000000 --- a/rockwork/snowywhite.svg +++ /dev/null @@ -1,241 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?> -<!-- Created with Inkscape (http://www.inkscape.org/) --> - -<svg - xmlns:dc="http://purl.org/dc/elements/1.1/" - xmlns:cc="http://creativecommons.org/ns#" - xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" - xmlns:svg="http://www.w3.org/2000/svg" - xmlns="http://www.w3.org/2000/svg" - xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" - xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" - width="72.248886mm" - height="72.248886mm" - viewBox="0 0 255.99999 255.99999" - id="svg2" - version="1.1" - inkscape:version="0.91 r13725" - sodipodi:docname="snowywhite.svg"> - <defs - id="defs4"> - <filter - inkscape:collect="always" - style="color-interpolation-filters:sRGB" - id="filter4364" - x="-0.059098901" - width="1.1181978" - y="-0.032575137" - height="1.0651503"> - <feGaussianBlur - inkscape:collect="always" - stdDeviation="5.5784918" - id="feGaussianBlur4366" /> - </filter> - </defs> - <sodipodi:namedview - id="base" - pagecolor="#ffffff" - bordercolor="#666666" - borderopacity="1.0" - inkscape:pageopacity="0.0" - inkscape:pageshadow="2" - inkscape:zoom="3.959798" - inkscape:cx="89.121544" - inkscape:cy="77.044911" - inkscape:document-units="px" - inkscape:current-layer="layer1" - showgrid="true" - fit-margin-top="0" - fit-margin-left="0" - fit-margin-right="0" - fit-margin-bottom="0" - inkscape:window-width="2880" - inkscape:window-height="1752" - inkscape:window-x="0" - inkscape:window-y="48" - inkscape:window-maximized="1"> - <inkscape:grid - type="xygrid" - id="grid4136" - originx="-40.000001" - originy="-539" - snapvisiblegridlinesonly="true" - enabled="false" /> - </sodipodi:namedview> - <metadata - id="metadata7"> - <rdf:RDF> - <cc:Work - rdf:about=""> - <dc:format>image/svg+xml</dc:format> - <dc:type - rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> - <dc:title></dc:title> - </cc:Work> - </rdf:RDF> - </metadata> - <g - inkscape:label="Layer 1" - inkscape:groupmode="layer" - id="layer1" - transform="translate(-40,-257.36221)"> - <g - transform="matrix(0.60632857,0,0,0.60632857,-37.462675,74.399202)" - id="g4202" - style="opacity:0.581;fill:#000000;fill-opacity:1;filter:url(#filter4364)"> - <path - style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" - d="m 437.97969,445.08937 c 0,0 11.49464,-4.59544 12.27285,0.25253 0.77821,4.84797 2.06459,45.23266 2.06459,45.23266 -8.36034,0.32794 -13.15013,-0.0886 -13.15013,-0.0886 z" - id="path4204" - inkscape:connector-curvature="0" - sodipodi:nodetypes="czccc" /> - <path - style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" - d="m 439.49492,491.6046 12.68287,0.70015 0.54937,42.27954 -13.73731,0.25254 z" - id="path4206" - inkscape:connector-curvature="0" - sodipodi:nodetypes="ccccc" /> - <rect - y="623.36218" - x="280" - height="95" - width="120" - id="rect4208" - style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> - <rect - style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" - id="rect4210" - width="120" - height="95" - x="280" - y="307.36221" /> - <path - style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" - d="M 228.0862,442.4309 C 228.58744,435.98794 240,437.36221 240,437.36221 l 0,42.02031 c 0,0 -14.31567,-1.22669 -13.80125,-2.84014 0.51442,-1.61345 1.3862,-27.66851 1.88745,-34.11148 z" - id="path4212" - inkscape:connector-curvature="0" - sodipodi:nodetypes="zcczz" /> - <path - sodipodi:nodetypes="cccccc" - inkscape:connector-curvature="0" - id="path4214" - d="M 420,643.715 337.60905,658.36221 255,643.715 l 0,-20 165,0 z" - style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> - <path - style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" - d="M 255,382.36221 337.39095,367.715 420,382.36221 l 0,20 -165,0 z" - id="path4216" - inkscape:connector-curvature="0" - sodipodi:nodetypes="cccccc" /> - <path - style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" - d="m 438.52906,535.82255 c 0,0 5.15979,0.84007 13.83236,0.44761 0.13423,13.76866 -1.20901,37.74804 -1.85634,42.35471 -0.64733,4.60667 -11.01016,-0.50508 -11.01016,-0.50508 z" - id="path4218" - inkscape:connector-curvature="0" - sodipodi:nodetypes="cczcc" /> - <path - style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" - d="m 244.85206,406.56127 c 16.07143,-13.92858 66.12644,-13.34299 97.65304,-13.30725 31.5266,0.0357 73.56632,-0.53467 90.70918,15.17961 17.14286,15.71428 12.91706,70.98675 13.01566,106.0726 0.0986,35.08586 5.19864,81.42741 -13.01565,99.64169 C 415,632.3622 371.12033,628.47664 339.15317,628.18658 307.186,627.89652 263.91063,632.7014 245.3392,615.91569 226.76777,599.12997 231.43107,540.45867 231.61582,505.9352 c 0.18475,-34.52347 -2.83519,-85.44536 13.23624,-99.37393 z" - id="path4220" - inkscape:connector-curvature="0" - sodipodi:nodetypes="zzzzzzzzz" /> - <rect - style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" - id="rect4222" - width="155" - height="174.99998" - x="260" - y="422.36221" - rx="20" - ry="20" /> - <rect - style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" - id="rect4224" - width="120" - height="135" - x="280" - y="442.36221" /> - <path - style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" - d="m 375,442.36221 25,0 0,135 -25,0 0,-109.75206 -7.32361,-5.3033 7.32361,-4.9245 z" - id="path4226" - inkscape:connector-curvature="0" - sodipodi:nodetypes="cccccccc" /> - </g> - <path - style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" - d="m 228.09692,344.2696 c 0,0 6.96953,-2.78634 7.44138,0.15312 0.47185,2.93946 1.25182,27.42585 1.25182,27.42585 -5.06911,0.19884 -7.9733,-0.0537 -7.9733,-0.0537 z" - id="rect4177" - inkscape:connector-curvature="0" - sodipodi:nodetypes="czccc" /> - <path - style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" - d="m 229.01565,372.47312 7.68999,0.42452 0.3331,25.63529 -8.32933,0.15312 z" - id="rect4179" - inkscape:connector-curvature="0" - sodipodi:nodetypes="ccccc" /> - <rect - y="452.36151" - x="132.30933" - height="57.601215" - width="72.75943" - id="rect4167" - style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> - <rect - style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" - id="rect4165" - width="72.75943" - height="57.601215" - x="132.30933" - y="260.76169" /> - <path - style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" - d="m 100.8325,342.6577 c 0.30392,-3.90655 7.22368,-3.07329 7.22368,-3.07329 l 0,25.47811 c 0,0 -8.679998,-0.74378 -8.36809,-1.72206 0.311907,-0.97828 0.84049,-16.77621 1.14441,-20.68276 z" - id="rect4169" - inkscape:connector-curvature="0" - sodipodi:nodetypes="zcczz" /> - <path - sodipodi:nodetypes="cccccc" - inkscape:connector-curvature="0" - id="path4175" - d="m 217.19532,464.702 -49.95598,8.88102 -50.08823,-8.88102 0,-12.12657 100.04421,0 z" - style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> - <path - style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" - d="m 117.15111,306.23633 49.95599,-8.88102 50.08822,8.88102 0,12.12658 -100.04421,0 z" - id="rect4172" - inkscape:connector-curvature="0" - sodipodi:nodetypes="cccccc" /> - <path - style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" - d="m 228.43002,399.28372 c 0,0 3.12853,0.50936 8.38696,0.2714 0.0814,8.34833 -0.73306,22.88772 -1.12555,25.68087 -0.3925,2.79316 -6.67578,-0.30624 -6.67578,-0.30624 z" - id="rect4181" - inkscape:connector-curvature="0" - sodipodi:nodetypes="cczcc" /> - <path - style="opacity:1;fill:#cbcbcb;fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" - d="m 110.99812,320.90892 c 9.74457,-8.4453 40.09435,-8.09024 59.20983,-8.06857 19.11548,0.0217 44.60536,-0.32419 54.99957,9.20383 10.39421,9.52802 7.83198,43.0413 7.89177,64.31485 0.0598,21.27356 3.15208,49.37176 -7.89176,60.4156 -11.04385,11.04384 -37.64935,8.68791 -57.03195,8.51204 -19.38261,-0.17587 -45.6217,2.73747 -56.88209,-7.44019 -11.26039,-10.17766 -8.4329,-45.75175 -8.32088,-66.68431 0.11202,-20.93257 -1.71905,-51.80796 8.02551,-60.25325 z" - id="rect4149" - inkscape:connector-curvature="0" - sodipodi:nodetypes="zzzzzzzzz" /> - <path - sodipodi:nodetypes="sssssssss" - inkscape:connector-curvature="0" - id="rect4152" - d="m 133.22587,330.48948 69.72779,0 c 6.71812,0 11.83367,5.41484 12.12657,12.12657 1.19073,27.28478 1.19022,54.56956 0,81.85435 -0.29278,6.71174 -5.40845,12.12657 -12.12657,12.12657 l -69.72779,0 c -6.71812,0 -11.82926,-5.41504 -12.12657,-12.12657 -1.18246,-26.69356 -1.65764,-53.74075 0,-81.85435 0.39543,-6.70647 5.40845,-12.12657 12.12657,-12.12657 z" - style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> - <rect - style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" - id="rect4154" - width="72.75943" - height="81.854355" - x="131.62029" - y="342.61606" /> - <path - style="opacity:1;fill:#78d3fc;fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" - d="m 189.2215,342.61605 15.15821,0 0,81.85436 -15.15821,0 0,-66.54581 -4.44052,-3.21555 4.44052,-2.98586 z" - id="rect4156" - inkscape:connector-curvature="0" - sodipodi:nodetypes="cccccccc" /> - </g> -</svg> diff --git a/rockworkd/core.cpp b/rockworkd/core.cpp index 38a25c5..eb98dfd 100644 --- a/rockworkd/core.cpp +++ b/rockworkd/core.cpp @@ -3,7 +3,7 @@ #include "pebblemanager.h" #include "dbusinterface.h" -#include "platformintegration/ubuntu/ubuntuplatform.h" +#include "platformintegration/sailfish/sailfishplatform.h" #ifdef ENABLE_TESTING #include "platformintegration/testing/testingplatform.h" #endif @@ -41,7 +41,7 @@ void Core::init() #ifdef ENABLE_TESTING m_platform = new TestingPlatform(this); #else - m_platform = new UbuntuPlatform(this); + m_platform = new SailfishPlatform(this); #endif m_pebbleManager = new PebbleManager(this); diff --git a/rockworkd/jsfiles.qrc b/rockworkd/jsfiles.qrc deleted file mode 100644 index 807350d..0000000 --- a/rockworkd/jsfiles.qrc +++ /dev/null @@ -1,2 +0,0 @@ -<RCC/> - diff --git a/rockworkd/libpebble/bluez/bluezclient.cpp b/rockworkd/libpebble/bluez/bluezclient.cpp index 8cdf848..313c540 100644 --- a/rockworkd/libpebble/bluez/bluezclient.cpp +++ b/rockworkd/libpebble/bluez/bluezclient.cpp @@ -1,5 +1,6 @@ #include "bluezclient.h" #include "dbus-shared.h" +#include "device.h" #include <QDBusConnection> #include <QDBusReply> @@ -26,32 +27,84 @@ BluezClient::BluezClient(QObject *parent): InterfaceList ifaces = objectList.value(path); if (ifaces.contains(BLUEZ_DEVICE_IFACE)) { QString candidatePath = path.path(); + qDebug() << "have device" << candidatePath; auto properties = ifaces.value(BLUEZ_DEVICE_IFACE); addDevice(path, properties); } } + + if (m_devices.isEmpty()) { + // Try with bluez 4 + QDBusConnection system = QDBusConnection::systemBus(); + + QDBusReply<QList<QDBusObjectPath> > listAdaptersReply = system.call( + QDBusMessage::createMethodCall("org.bluez", "/", "org.bluez.Manager", + "ListAdapters")); + if (!listAdaptersReply.isValid()) { + qWarning() << listAdaptersReply.error().message(); + return; + } + + QList<QDBusObjectPath> adapters = listAdaptersReply.value(); + + if (adapters.isEmpty()) { + qWarning() << "No BT adapters found"; + return; + } + + QDBusReply<QVariantMap> adapterPropertiesReply = system.call( + QDBusMessage::createMethodCall("org.bluez", adapters[0].path(), "org.bluez.Adapter", + "GetProperties")); + if (!adapterPropertiesReply.isValid()) { + qWarning() << adapterPropertiesReply.error().message(); + return; + } + + QList<QDBusObjectPath> devices; + adapterPropertiesReply.value()["Devices"].value<QDBusArgument>() >> devices; + + foreach (QDBusObjectPath path, devices) { + QDBusReply<QVariantMap> devicePropertiesReply = system.call( + QDBusMessage::createMethodCall("org.bluez", path.path(), "org.bluez.Device", + "GetProperties")); + if (!devicePropertiesReply.isValid()) { + qCritical() << devicePropertiesReply.error().message(); + continue; + } + + const QVariantMap &dict = devicePropertiesReply.value(); + + QString name = dict["Name"].toString(); + if (name.startsWith("Pebble") && !name.startsWith("Pebble Time LE") && !name.startsWith("Pebble-LE")) { + qDebug() << "Found Pebble:" << name; + addDevice(path, dict); + } + } + } } } -QList<Device> BluezClient::pairedPebbles() const +QList<BluezDevice> BluezClient::pairedPebbles() const { - QList<Device> ret; - if (m_bluezManager.isValid()) { - foreach (const Device &dev, m_devices) { - ret << dev; - } + QList<BluezDevice> ret; + + foreach (const BluezDevice &dev, m_devices) { + ret << dev; } + return ret; + } void BluezClient::addDevice(const QDBusObjectPath &path, const QVariantMap &properties) { QString address = properties.value("Address").toString(); QString name = properties.value("Name").toString(); + qDebug() << "Adding device" << address << name; if (name.startsWith("Pebble") && !name.startsWith("Pebble Time LE") && !name.startsWith("Pebble-LE") && !m_devices.contains(address)) { qDebug() << "Found new Pebble:" << address << name; - Device device; + BluezDevice device; device.address = QBluetoothAddress(address); device.name = name; device.path = path.path(); @@ -70,6 +123,26 @@ void BluezClient::slotInterfacesAdded(const QDBusObjectPath &path, InterfaceList } } +void BluezClient::slotDevicePairingDone(bool success) +{ + qDebug() << "pairing done" << success; + if (!success) { + return; + } + + Device *device = static_cast<Device*>(sender()); + device->deleteLater(); + + if (!m_devices.contains(device->getAddress())) { + BluezDevice bluezDevice; + bluezDevice.address = QBluetoothAddress(device->getAddress()); + bluezDevice.name = device->getName(); + bluezDevice.path = device->getPath(); + m_devices.insert(device->getAddress(), bluezDevice); + emit devicesChanged(); + } +} + void BluezClient::slotInterfacesRemoved(const QDBusObjectPath &path, const QStringList &ifaces) { qDebug() << "interfaces removed" << path.path() << ifaces; diff --git a/rockworkd/libpebble/bluez/bluezclient.h b/rockworkd/libpebble/bluez/bluezclient.h index f8e5749..cbe7c0f 100644 --- a/rockworkd/libpebble/bluez/bluezclient.h +++ b/rockworkd/libpebble/bluez/bluezclient.h @@ -11,7 +11,7 @@ #include "bluez_adapter1.h" #include "bluez_agentmanager1.h" -class Device { +class BluezDevice { public: QBluetoothAddress address; QString name; @@ -26,14 +26,15 @@ public: BluezClient(QObject *parent = 0); - QList<Device> pairedPebbles() const; + QList<BluezDevice> pairedPebbles() const; private slots: void addDevice(const QDBusObjectPath &path, const QVariantMap &properties); void slotInterfacesAdded(const QDBusObjectPath&path, InterfaceList ifaces); - void slotInterfacesRemoved(const QDBusObjectPath&path, const QStringList &ifaces); - + void slotDevicePairingDone(bool success); + void slotInterfacesRemoved(const QDBusObjectPath&path, const QStringList &ifaces); + signals: void devicesChanged(); @@ -45,7 +46,7 @@ private: FreeDesktopProperties *m_bluezAdapterProperties = nullptr; - QHash<QString, Device> m_devices; + QHash<QString, BluezDevice> m_devices; }; #endif // BLUEZCLIENT_H diff --git a/rockworkd/libpebble/bluez/device.cpp b/rockworkd/libpebble/bluez/device.cpp new file mode 100644 index 0000000..9a0e9c3 --- /dev/null +++ b/rockworkd/libpebble/bluez/device.cpp @@ -0,0 +1,498 @@ +/* + * Copyright (C) 2013-2015 Canonical Ltd + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 3 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * Authors: + * Charles Kerr <charles.kerr@canonical.com> + */ + +#include "device.h" + +#include <QDBusReply> +#include <QDebug> // qWarning() +#include <QThread> +#include <QTimer> + +#include "dbus-shared.h" + +Device::Device(const QString &path, QDBusConnection &bus) : + m_strength(Device::None) +{ + initDevice(path, bus); +} + +void Device::initDevice(const QString &path, QDBusConnection &bus) +{ + /* whenever any of the properties changes, + trigger the catch-all deviceChanged() signal */ + QObject::connect(this, SIGNAL(nameChanged()), this, SIGNAL(deviceChanged())); + QObject::connect(this, SIGNAL(iconNameChanged()), this, SIGNAL(deviceChanged())); + QObject::connect(this, SIGNAL(addressChanged()), this, SIGNAL(deviceChanged())); + QObject::connect(this, SIGNAL(pairedChanged()), this, SIGNAL(deviceChanged())); + QObject::connect(this, SIGNAL(trustedChanged()), this, SIGNAL(deviceChanged())); + QObject::connect(this, SIGNAL(typeChanged()), this, SIGNAL(deviceChanged())); + QObject::connect(this, SIGNAL(connectionChanged()), this, SIGNAL(deviceChanged())); + QObject::connect(this, SIGNAL(strengthChanged()), this, SIGNAL(deviceChanged())); + + m_bluezDevice.reset(new BluezDevice1(BLUEZ_SERVICE, path, bus)); + /* Give our calls a bit more time than the default 25 seconds to + * complete whatever they are doing. In some situations (e.g. with + * specific devices) the default doesn't seem to be enough to. */ + m_bluezDevice->setTimeout(60 * 1000 /* 60 seconds */); + + m_bluezDeviceProperties.reset(new FreeDesktopProperties(BLUEZ_SERVICE, path, bus)); + + QObject::connect(m_bluezDeviceProperties.data(), SIGNAL(PropertiesChanged(const QString&, const QVariantMap&, const QStringList&)), + this, SLOT(slotPropertiesChanged(const QString&, const QVariantMap&, const QStringList&))); + + Q_EMIT(pathChanged()); + + watchCall(m_bluezDeviceProperties->GetAll(BLUEZ_DEVICE_IFACE), [=](QDBusPendingCallWatcher *watcher) { + QDBusPendingReply<QVariantMap> reply = *watcher; + + if (reply.isError()) { + qWarning() << "Failed to retrieve properties for device" << m_bluezDevice->path(); + watcher->deleteLater(); + return; + } + + auto properties = reply.argumentAt<0>(); + setProperties(properties); + + watcher->deleteLater(); + }); +} + +void Device::slotPropertiesChanged(const QString &interface, const QVariantMap &changedProperties, + const QStringList &invalidatedProperties) +{ + Q_UNUSED(invalidatedProperties); + + if (interface != BLUEZ_DEVICE_IFACE) + return; + + setProperties(changedProperties); +} + +void Device::setProperties(const QMap<QString,QVariant> &properties) +{ + QMapIterator<QString,QVariant> it(properties); + while (it.hasNext()) { + it.next(); + updateProperty(it.key(), it.value()); + } +} + +void Device::setConnectAfterPairing(bool value) +{ + if (m_connectAfterPairing == value) + return; + + m_connectAfterPairing = value; +} + +void Device::disconnect() +{ + setConnection(Device::Disconnecting); + + QDBusPendingCall call = m_bluezDevice->Disconnect(); + + QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(call, this); + QObject::connect(watcher, &QDBusPendingCallWatcher::finished, [this](QDBusPendingCallWatcher *watcher) { + QDBusPendingReply<void> reply = *watcher; + + if (reply.isError()) { + qWarning() << "Could not disconnect device:" + << reply.error().message(); + + // Make sure we switch the connection indicator back to + // a sane state + updateConnection(); + } + + watcher->deleteLater(); + }); +} + +void Device::connectAfterPairing() +{ + if (!m_connectAfterPairing) + return; + + connect(); +} + +void Device::pair() +{ + if (m_paired) { + // If we are already paired we just have to make sure we + // trigger the connection process if we have to + connectAfterPairing(); + return; + } + + setConnection(Device::Connecting); + + m_isPairing = true; + + auto call = m_bluezDevice->asyncCall("Pair"); + + QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(call, this); + QObject::connect(watcher, &QDBusPendingCallWatcher::finished, [this](QDBusPendingCallWatcher *watcher) { + QDBusPendingReply<void> reply = *watcher; + bool success = true; + + if (reply.isError()) { + qWarning() << "Failed to pair with device:" + << reply.error().message(); + updateConnection(); + success = false; + } + + m_isPairing = false; + + Q_EMIT(pairingDone(success)); + + watcher->deleteLater(); + }); +} + +void Device::cancelPairing() +{ + if (!m_isPairing) + return; + + auto call = m_bluezDevice->asyncCall("CancelPairing"); + + QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(call, this); + QObject::connect(watcher, &QDBusPendingCallWatcher::finished, [this](QDBusPendingCallWatcher *watcher) { + QDBusPendingReply<void> reply = *watcher; + + if (reply.isError()) { + qWarning() << "Failed to cancel pairing attempt with device:" + << reply.error().message(); + updateConnection(); + } else { + // Only mark us a not pairing when call succeeded + m_isPairing = false; + } + + watcher->deleteLater(); + }); +} + +void Device::connect() +{ + // If we have just paired then the device switched to connected = true for + // a short moment as BlueZ opened up a RFCOMM channel to perform SDP. If + // we should connect with the device on specific profiles now we go ahead + // here even if we're marked as connected as this still doesn't mean we're + // connected on any profile. Calling org.bluez.Device1.Connect multiple + // times doesn't hurt an will not fail. + if (m_isConnected && !m_connectAfterPairing) + return; + + setConnection(Device::Connecting); + + QDBusPendingCall call = m_bluezDevice->asyncCall("Connect"); + + QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(call, this); + QObject::connect(watcher, &QDBusPendingCallWatcher::finished, [this](QDBusPendingCallWatcher *watcher) { + QDBusPendingReply<void> reply = *watcher; + + if (reply.isError()) { + qWarning() << "Could not connect device:" + << reply.error().message(); + } else { + makeTrusted(true); + } + + // Regardless if the Connected property has changed or not we update + // the connection state here as the connection process is over now + // and we should have received any state change already at this + // point. + updateConnection(); + + watcher->deleteLater(); + }); +} + +void Device::slotMakeTrustedDone(QDBusPendingCallWatcher *call) +{ + QDBusPendingReply<void> reply = *call; + + if (reply.isError()) { + qWarning() << "Could not mark device as trusted:" + << reply.error().message(); + } + + call->deleteLater(); +} + +void Device::makeTrusted(bool trusted) +{ + auto call = m_bluezDeviceProperties->Set(BLUEZ_DEVICE_IFACE, "Trusted", QDBusVariant(trusted)); + + auto watcher = new QDBusPendingCallWatcher(call, this); + QObject::connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)), + this, SLOT(slotMakeTrustedDone(QDBusPendingCallWatcher*))); +} + +void Device::setName(const QString &name) +{ + if (m_name != name) { + m_name = name; + Q_EMIT(nameChanged()); + } +} + +void Device::setIconName(const QString &iconName) +{ + if (m_iconName != iconName) { + m_iconName = iconName; + Q_EMIT(iconNameChanged()); + } +} + +void Device::setAddress(const QString &address) +{ + if (m_address != address) { + m_address = address; + Q_EMIT(addressChanged()); + } +} + +void Device::setType(Type type) +{ + if (m_type != type) { + m_type = type; + Q_EMIT(typeChanged()); + updateIcon(); + } +} + +void Device::setPaired(bool paired) +{ + if (m_paired != paired) { + m_paired = paired; + Q_EMIT(pairedChanged()); + } +} + +void Device::setTrusted(bool trusted) +{ + if (m_trusted != trusted) { + m_trusted = trusted; + Q_EMIT(trustedChanged()); + } +} + +void Device::setConnection(Connection connection) +{ + if (m_connection != connection) { + m_connection = connection; + Q_EMIT(connectionChanged()); + } +} + +void Device::updateIcon() +{ + /* bluez-provided icon is unreliable? In testing I'm getting + an "audio-card" icon from bluez for my NoiseHush N700 headset. + Try to guess the icon from the device type, + and use the bluez-provided icon as a fallback */ + + const auto type = getType(); + + switch (type) { + case Type::Headset: + setIconName("image://theme/audio-headset-symbolic"); + break; + case Type::Headphones: + setIconName("image://theme/audio-headphones-symbolic"); + break; + case Type::Carkit: + setIconName("image://theme/audio-carkit-symbolic"); + break; + case Type::Speakers: + case Type::OtherAudio: + setIconName("image://theme/audio-speakers-symbolic"); + break; + case Type::Mouse: + setIconName("image://theme/input-mouse-symbolic"); + break; + case Type::Keyboard: + setIconName("image://theme/input-keyboard-symbolic"); + break; + case Type::Cellular: + setIconName("image://theme/phone-cellular-symbolic"); + break; + case Type::Smartphone: + setIconName("image://theme/phone-smartphone-symbolic"); + break; + case Type::Phone: + setIconName("image://theme/phone-uncategorized-symbolic"); + break; + case Type::Computer: + setIconName("image://theme/computer-symbolic"); + break; + default: + setIconName(QString("image://theme/%1").arg(m_fallbackIconName)); + } +} + +void Device::updateConnection() +{ + Connection c; + + c = m_isConnected ? Connection::Connected : Connection::Disconnected; + + setConnection(c); +} + +void Device::updateProperty(const QString &key, const QVariant &value) +{ + if (key == "Name") { + setName(value.toString()); + } else if (key == "Address") { + setAddress(value.toString()); + } else if (key == "Connected") { + m_isConnected = value.toBool(); + updateConnection(); + } else if (key == "Class") { + setType(getTypeFromClass(value.toUInt())); + } else if (key == "Paired") { + setPaired(value.toBool()); + + if (m_paired && m_connectAfterPairing) { + connectAfterPairing(); + return; + } + + updateConnection(); + } else if (key == "Trusted") { + setTrusted(value.toBool()); + } else if (key == "Icon") { + m_fallbackIconName = value.toString(); + updateIcon (); + } else if (key == "RSSI") { + m_strength = getStrengthFromRssi(value.toInt()); + Q_EMIT(strengthChanged()); + } +} + +/* Determine the Type from the bits in the Class of Device (CoD) field. + https://www.bluetooth.org/en-us/specification/assigned-numbers/baseband */ +Device::Type Device::getTypeFromClass (quint32 c) +{ + switch ((c & 0x1f00) >> 8) { + case 0x01: + return Type::Computer; + + case 0x02: + switch ((c & 0xfc) >> 2) { + case 0x01: + return Type::Cellular; + case 0x03: + return Type::Smartphone; + case 0x04: + return Type::Modem; + default: + return Type::Phone; + } + break; + + case 0x03: + return Type::Network; + + case 0x04: + switch ((c & 0xfc) >> 2) { + case 0x01: + case 0x02: + return Type::Headset; + + case 0x05: + return Type::Speakers; + + case 0x06: + return Type::Headphones; + + case 0x08: + return Type::Carkit; + + case 0x0b: // vcr + case 0x0c: // video camera + case 0x0d: // camcorder + return Type::Video; + + default: + return Type::OtherAudio; + } + break; + + case 0x05: + switch ((c & 0xc0) >> 6) { + case 0x00: + switch ((c & 0x1e) >> 2) { + case 0x01: + case 0x02: + return Type::Joypad; + } + break; + + case 0x01: + return Type::Keyboard; + + case 0x02: + switch ((c & 0x1e) >> 2) { + case 0x05: + return Type::Tablet; + default: + return Type::Mouse; + } + } + break; + + case 0x06: + if ((c & 0x80) != 0) + return Type::Printer; + if ((c & 0x20) != 0) + return Type::Camera; + break; + + case 0x07: + if ((c & 0x4) != 0) + return Type::Watch; + break; + } + + return Type::Other; +} + +Device::Strength Device::getStrengthFromRssi(int rssi) +{ + /* Modelled similar to what Mac OS X does. + * See http://www.cnet.com/how-to/how-to-check-bluetooth-connection-strength-in-os-x/ */ + + if (rssi >= -60) + return Excellent; + else if (rssi < -60 && rssi >= -70) + return Good; + else if (rssi < -70 && rssi >= -90) + return Fair; + else if (rssi < -90) + return Poor; + + return None; +} diff --git a/rockworkd/libpebble/bluez/device.h b/rockworkd/libpebble/bluez/device.h new file mode 100644 index 0000000..bcc044b --- /dev/null +++ b/rockworkd/libpebble/bluez/device.h @@ -0,0 +1,172 @@ +/* + * Copyright (C) 2013-2015 Canonical Ltd + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 3 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * Authors: + * Charles Kerr <charles.kerr@canonical.com> + */ + +#ifndef USS_BLUETOOTH_DEVICE_H +#define USS_BLUETOOTH_DEVICE_H + +#include <QDBusConnection> +#include <QDBusInterface> +#include <QDBusPendingCallWatcher> +#include <QSharedPointer> +#include <QString> + +#include "freedesktop_properties.h" +#include "bluez_device1.h" + +struct Device: QObject +{ + Q_OBJECT + + Q_PROPERTY(QString path + READ getPath + NOTIFY pathChanged) + + Q_PROPERTY(QString name + READ getName + NOTIFY nameChanged) + + Q_PROPERTY(QString iconName + READ getIconName + NOTIFY iconNameChanged) + + Q_PROPERTY(QString address + READ getAddress + NOTIFY addressChanged) + + Q_PROPERTY(Type type + READ getType + NOTIFY typeChanged) + + Q_PROPERTY(bool paired + READ isPaired + NOTIFY pairedChanged) + + Q_PROPERTY(bool trusted + READ isTrusted + WRITE makeTrusted + NOTIFY trustedChanged) + + Q_PROPERTY(Connection connection + READ getConnection + NOTIFY connectionChanged) + + Q_PROPERTY(Strength strength + READ getStrength + NOTIFY strengthChanged) + +public: + + enum Type { Other, Computer, Cellular, Smartphone, Phone, Modem, Network, + Headset, Speakers, Headphones, Video, OtherAudio, Joypad, + Keypad, Keyboard, Tablet, Mouse, Printer, Camera, Carkit, Watch }; + + enum Strength { None, Poor, Fair, Good, Excellent }; + + enum Connection { Disconnected=1, Connecting=2, + Connected=4, Disconnecting=8 }; + + Q_ENUMS(Type Strength Connection) + + Q_DECLARE_FLAGS(Connections, Connection) + +Q_SIGNALS: + void pathChanged(); + void nameChanged(); + void iconNameChanged(); + void addressChanged(); + void typeChanged(); + void pairedChanged(); + void trustedChanged(); + void connectionChanged(); + void strengthChanged(); + void deviceChanged(); // catchall for any change + void pairingDone(bool success); + +public: + const QString& getName() const { return m_name; } + const QString& getAddress() const { return m_address; } + const QString& getIconName() const { return m_iconName; } + Type getType() const { return m_type; } + bool isPaired() const { return m_paired; } + bool isTrusted() const { return m_trusted; } + Connection getConnection() const { return m_connection; } + Strength getStrength() const { return m_strength; } + QString getPath() const { return m_bluezDevice ? m_bluezDevice->path() : QString(); } + + private: + QString m_name; + QString m_state; + QString m_address; + QString m_iconName; + QString m_fallbackIconName; + Type m_type = Type::Other; + bool m_paired = false; + bool m_trusted = false; + Connection m_connection = Connection::Disconnected; + Strength m_strength = Strength::None; + bool m_isConnected = false; + bool m_connectAfterPairing = false; + QScopedPointer<BluezDevice1> m_bluezDevice; + QScopedPointer<FreeDesktopProperties> m_bluezDeviceProperties; + bool m_isPairing = false; + + protected: + void setName(const QString &name); + void setIconName(const QString &name); + void setAddress(const QString &address); + void setType(Type type); + void setPaired(bool paired); + void setTrusted(bool trusted); + void setConnection(Connection connection); + void setStrength(Strength strength); + void updateIcon(); + void updateConnection(); + + public: + Device() {} + Device(const QString &path, QDBusConnection &bus); + ~Device() {} + bool isValid() const { return getType() != Type::Other; } + void pair(); + Q_INVOKABLE void cancelPairing(); + void connect(); + void makeTrusted(bool trusted); + void disconnect(); + void setProperties(const QMap<QString,QVariant> &properties); + void setConnectAfterPairing(bool value); + + private Q_SLOTS: + void slotPropertiesChanged(const QString &interface, const QVariantMap &changedProperties, + const QStringList &invalidatedProperties); + void slotMakeTrustedDone(QDBusPendingCallWatcher *call); + + private: + void initDevice(const QString &path, QDBusConnection &bus); + void updateProperties(QSharedPointer<QDBusInterface>); + void updateProperty(const QString &key, const QVariant &value); + static Type getTypeFromClass(quint32 bluetoothClass); + Device::Strength getStrengthFromRssi(int rssi); + void connectAfterPairing(); +}; + +Q_DECLARE_METATYPE(Device*) + +Q_DECLARE_OPERATORS_FOR_FLAGS(Device::Connections) + +#endif // USS_BLUETOOTH_DEVICE_H diff --git a/rockworkd/libpebble/jskit/typedarray.js b/rockworkd/libpebble/jskit/typedarray.js index d4e00c6..eec78a2 100644 --- a/rockworkd/libpebble/jskit/typedarray.js +++ b/rockworkd/libpebble/jskit/typedarray.js @@ -61,7 +61,7 @@ return Object(v); } function ToInt32(v) { return v >> 0; } - function ToUint32(v) { return v >> 0; } //ROCKWORK HACK ALERT: it appears that QT doesn't do the >>> properly, using >> here instead (should be close enough) + function ToUint32(v) { return v >>> 0; } // Snapshot intrinsics var LN2 = Math.LN2, @@ -135,21 +135,23 @@ function packU8Clamped(n) { n = round(Number(n)); return [n < 0 ? 0 : n > 0xff ? 0xff : n & 0xff]; } - function packI16(n) { return [n & 0xff, (n >> 8) & 0xff]; } - function unpackI16(bytes) { return as_signed(bytes[1] << 8 | bytes[0], 16); } + function packI16(n) { return [(n >> 8) & 0xff, n & 0xff]; } + function unpackI16(bytes) { return as_signed(bytes[0] << 8 | bytes[1], 16); } - function packU16(n) { return [n & 0xff, (n >> 8) & 0xff]; } - function unpackU16(bytes) { return as_unsigned(bytes[1] << 8 | bytes[0], 16); } + function packU16(n) { return [(n >> 8) & 0xff, n & 0xff]; } + function unpackU16(bytes) { return as_unsigned(bytes[0] << 8 | bytes[1], 16); } - function packI32(n) { return [n & 0xff, (n >> 8) & 0xff, (n >> 16) & 0xff, (n >> 24) & 0xff]; } - function unpackI32(bytes) { return as_signed(bytes[3] << 24 | bytes[2] << 16 | bytes[1] << 8 | bytes[0], 32); } + function packI32(n) { return [(n >> 24) & 0xff, (n >> 16) & 0xff, (n >> 8) & 0xff, n & 0xff]; } + function unpackI32(bytes) { return as_signed(bytes[0] << 24 | bytes[1] << 16 | bytes[2] << 8 | bytes[3], 32); } - function packU32(n) { return [n & 0xff, (n >> 8) & 0xff, (n >> 16) & 0xff, (n >> 24) & 0xff]; } - function unpackU32(bytes) { return as_unsigned(bytes[3] << 24 | bytes[2] << 16 | bytes[1] << 8 | bytes[0], 32); } + function packU32(n) { return [(n >> 24) & 0xff, (n >> 16) & 0xff, (n >> 8) & 0xff, n & 0xff]; } + function unpackU32(bytes) { return as_unsigned(bytes[0] << 24 | bytes[1] << 16 | bytes[2] << 8 | bytes[3], 32); } function packIEEE754(v, ebits, fbits) { - var bias = (1 << (ebits - 1)) - 1; + var bias = (1 << (ebits - 1)) - 1, + s, e, f, ln, + i, bits, str, bytes; function roundToEven(n) { var w = floor(n), f = n - w; @@ -161,7 +163,6 @@ } // Compute sign, exponent, fraction - var s, e, f; if (v !== v) { // NaN // http://dev.w3.org/2006/webapi/WebIDL/#es-type-mapping @@ -175,28 +176,20 @@ v = abs(v); if (v >= pow(2, 1 - bias)) { - // Normalized e = min(floor(log(v) / LN2), 1023); - var significand = v / pow(2, e); - if (significand < 1) { - e -= 1; - significand *= 2; + f = roundToEven(v / pow(2, e) * pow(2, fbits)); + if (f / pow(2, fbits) >= 2) { + e = e + 1; + f = 1; } - if (significand >= 2) { - e += 1; - significand /= 2; - } - var d = pow(2, fbits); - f = roundToEven(significand * d) - d; - e += bias; - if (f / d >= 1) { - e += 1; - f = 0; - } - if (e > 2 * bias) { + if (e > bias) { // Overflow e = (1 << ebits) - 1; f = 0; + } else { + // Normalized + e = e + bias; + f = f - pow(2, fbits); } } else { // Denormalized @@ -206,17 +199,17 @@ } // Pack sign, exponent, fraction - var bits = [], i; + bits = []; for (i = fbits; i; i -= 1) { bits.push(f % 2 ? 1 : 0); f = floor(f / 2); } for (i = ebits; i; i -= 1) { bits.push(e % 2 ? 1 : 0); e = floor(e / 2); } bits.push(s ? 1 : 0); bits.reverse(); - var str = bits.join(''); + str = bits.join(''); // Bits to bytes - var bytes = []; + bytes = []; while (str.length) { - bytes.unshift(parseInt(str.substring(0, 8), 2)); + bytes.push(parseInt(str.substring(0, 8), 2)); str = str.substring(8); } return bytes; @@ -227,8 +220,8 @@ var bits = [], i, j, b, str, bias, s, e, f; - for (i = 0; i < bytes.length; ++i) { - b = bytes[i]; + for (i = bytes.length; i; i -= 1) { + b = bytes[i - 1]; for (j = 8; j; j -= 1) { bits.push(b % 2 ? 1 : 0); b = b >> 1; } diff --git a/rockworkd/libpebble/pebble.cpp b/rockworkd/libpebble/pebble.cpp index 0f76097..d2e44f5 100644 --- a/rockworkd/libpebble/pebble.cpp +++ b/rockworkd/libpebble/pebble.cpp @@ -134,7 +134,7 @@ bool Pebble::connected() const void Pebble::connect() { - qDebug() << "Connecting to Pebble:" << m_name << m_address; + qDebug() << "Connecting to Pebble:" << m_name << m_address.toString(); m_connection->connectPebble(m_address); } diff --git a/rockworkd/libpebble/watchconnection.cpp b/rockworkd/libpebble/watchconnection.cpp index 0778a1d..dabacf4 100644 --- a/rockworkd/libpebble/watchconnection.cpp +++ b/rockworkd/libpebble/watchconnection.cpp @@ -32,7 +32,7 @@ UploadManager *WatchConnection::uploadManager() const void WatchConnection::scheduleReconnect() { - if (m_connectionAttempts == 0) { + if (m_connectionAttempts < 2) { reconnect(); } else if (m_connectionAttempts < 25) { qDebug() << "Attempting to reconnect in 10 seconds"; @@ -49,21 +49,27 @@ void WatchConnection::scheduleReconnect() void WatchConnection::reconnect() { QBluetoothLocalDevice localBtDev; + qDebug() << "Reconnection"; if (localBtDev.pairingStatus(m_pebbleAddress) == QBluetoothLocalDevice::Unpaired) { // Try again in one 10 secs, give the user some time to pair it + qDebug() << "Unpaired."; m_connectionAttempts = 1; scheduleReconnect(); return; } if (m_socket) { + qDebug() << "Socket exists."; if (m_socket->state() == QBluetoothSocket::ConnectedState) { qDebug() << "Already connected."; return; } - delete m_socket; + m_socket->deleteLater(); } + m_connectionAttempts++; + + qDebug() << "Creating socket."; m_socket = new QBluetoothSocket(QBluetoothServiceInfo::RfcommProtocol, this); connect(m_socket, &QBluetoothSocket::connected, this, &WatchConnection::pebbleConnected); connect(m_socket, &QBluetoothSocket::readyRead, this, &WatchConnection::readyRead); @@ -71,7 +77,6 @@ void WatchConnection::reconnect() connect(m_socket, &QBluetoothSocket::disconnected, this, &WatchConnection::pebbleDisconnected); //connect(socket, SIGNAL(bytesWritten(qint64)), SLOT(onBytesWritten(qint64))); - m_connectionAttempts++; // FIXME: Assuming port 1 (with Pebble) m_socket->connectToService(m_pebbleAddress, 1); @@ -141,8 +146,12 @@ void WatchConnection::pebbleConnected() void WatchConnection::pebbleDisconnected() { qDebug() << "Disconnected"; - m_socket->close(); + emit watchDisconnected(); + QBluetoothSocket *socket = qobject_cast<QBluetoothSocket *>(sender()); + if (!socket) return; + + socket->deleteLater(); if (!m_reconnectTimer.isActive()) { scheduleReconnect(); } @@ -152,7 +161,6 @@ void WatchConnection::socketError(QBluetoothSocket::SocketError error) { Q_UNUSED(error); // We seem to get UnknownError anyways all the time qDebug() << "SocketError" << error; - m_socket->close(); emit watchConnectionFailed(); if (!m_reconnectTimer.isActive()) { scheduleReconnect(); diff --git a/rockworkd/pebblemanager.cpp b/rockworkd/pebblemanager.cpp index 126000e..842dff0 100644 --- a/rockworkd/pebblemanager.cpp +++ b/rockworkd/pebblemanager.cpp @@ -26,8 +26,8 @@ QList<Pebble *> PebbleManager::pebbles() const void PebbleManager::loadPebbles() { - QList<Device> pairedPebbles = m_bluezClient->pairedPebbles(); - foreach (const Device &device, pairedPebbles) { + QList<BluezDevice> pairedPebbles = m_bluezClient->pairedPebbles(); + foreach (const BluezDevice &device, pairedPebbles) { qDebug() << "loading pebble" << device.address.toString(); Pebble *pebble = get(device.address); if (!pebble) { @@ -46,7 +46,7 @@ void PebbleManager::loadPebbles() QList<Pebble*> pebblesToRemove; foreach (Pebble *pebble, m_pebbles) { bool found = false; - foreach (const Device &dev, pairedPebbles) { + foreach (const BluezDevice &dev, pairedPebbles) { if (dev.address == pebble->address()) { found = true; break; @@ -59,7 +59,7 @@ void PebbleManager::loadPebbles() while (!pebblesToRemove.isEmpty()) { Pebble *pebble = pebblesToRemove.takeFirst(); - qDebug() << "Removing pebble" << pebble->address(); + qDebug() << "Removing pebble" << pebble->address().toString(); m_pebbles.removeOne(pebble); emit pebbleRemoved(pebble); pebble->deleteLater(); diff --git a/rockworkd/platformintegration/sailfish/callchannelobserver.cpp b/rockworkd/platformintegration/sailfish/callchannelobserver.cpp new file mode 100644 index 0000000..a9f41f3 --- /dev/null +++ b/rockworkd/platformintegration/sailfish/callchannelobserver.cpp @@ -0,0 +1,166 @@ +#include "callchannelobserver.h" + +#include <TelepathyQt/Contact> +#include <TelepathyQt/PendingContactInfo> + +#include <QContactFetchRequest> +#include <QContactPhoneNumber> +#include <QContactFilter> +#include <QContactDetail> +#include <QContactDisplayLabel> + +QTCONTACTS_USE_NAMESPACE + +TelepathyMonitor::TelepathyMonitor(QObject *parent): + QObject(parent) +{ + Tp::registerTypes(); + QTimer::singleShot(0, this, SLOT(accountManagerSetup())); + QMap<QString, QString> parameters; + parameters.insert(QString::fromLatin1("mergePresenceChanges"), QString::fromLatin1("false")); + m_contactManager = new QContactManager("", parameters, this); +} + +void TelepathyMonitor::hangupCall(uint cookie) +{ + if (m_currentCalls.contains(cookie)) { + m_currentCalls.value(cookie)->hangup(); + } +} + +void TelepathyMonitor::accountManagerSetup() +{ + m_accountManager = Tp::AccountManager::create(Tp::AccountFactory::create(QDBusConnection::sessionBus(), + Tp::Account::FeatureCore), + Tp::ConnectionFactory::create(QDBusConnection::sessionBus(), + Tp::Connection::FeatureCore)); + connect(m_accountManager->becomeReady(), + SIGNAL(finished(Tp::PendingOperation*)), + SLOT(accountManagerReady(Tp::PendingOperation*))); +} + +void TelepathyMonitor::accountManagerReady(Tp::PendingOperation* operation) +{ + if (operation->isError()) { + qDebug() << "TelepathyMonitor: accountManager init error."; + QTimer::singleShot(1000, this, SLOT(accountManagerSetup())); // again + return; + } + qDebug() << "Telepathy account manager ready"; + + foreach (const Tp::AccountPtr& account, m_accountManager->allAccounts()) { + connect(account->becomeReady(Tp::Account::FeatureCapabilities), + SIGNAL(finished(Tp::PendingOperation*)), + SLOT(accountReady(Tp::PendingOperation*))); + } + + connect(m_accountManager.data(), SIGNAL(newAccount(Tp::AccountPtr)), SLOT(newAccount(Tp::AccountPtr))); +} + +void TelepathyMonitor::newAccount(const Tp::AccountPtr& account) +{ + connect(account->becomeReady(Tp::Account::FeatureCapabilities), + SIGNAL(finished(Tp::PendingOperation*)), + SLOT(accountReady(Tp::PendingOperation*))); +} + +void TelepathyMonitor::accountReady(Tp::PendingOperation* operation) +{ + if (operation->isError()) { + qDebug() << "TelepathyAccount: Operation failed (accountReady)"; + return; + } + + Tp::PendingReady* pendingReady = qobject_cast<Tp::PendingReady*>(operation); + if (pendingReady == 0) { + qDebug() << "Rejecting account because could not understand ready status"; + return; + } + checkAndAddAccount(Tp::AccountPtr::qObjectCast(pendingReady->proxy())); +} + +void TelepathyMonitor::onCallStarted(Tp::CallChannelPtr callChannel) +{ + // Haven't figured how to send outgoing calls to pebble yet... discard it + if (callChannel->initiatorContact()->id().isEmpty()) { + qWarning() << "ignoring phone call. looks like it's an outgoing one"; + return; + } + + m_cookie++; + m_currentCalls.insert(m_cookie, callChannel.data()); + m_currentCallStates.insert(m_cookie, Tp::CallStateInitialising); + + callChannel->becomeReady(Tp::CallChannel::FeatureCallState); + + connect(callChannel.data(), &Tp::CallChannel::callStateChanged, this, &TelepathyMonitor::callStateChanged); + + QString number = callChannel->initiatorContact()->id(); + qDebug() << "call started" << number; + + // try to match the contact info + QContactFetchRequest *request = new QContactFetchRequest(this); + request->setFilter(QContactPhoneNumber::match(number)); + + // lambda function to update the notification + QObject::connect(request, &QContactAbstractRequest::stateChanged, [this, request, number](QContactAbstractRequest::State state) { + qDebug() << "request returned"; + if (!request || state != QContactAbstractRequest::FinishedState) { + qDebug() << "error fetching contact" << state; + return; + } + + QContact contact; + + // create the snap decision only after the contact match finishes + if (request->contacts().size() > 0) { + // use the first match + contact = request->contacts().at(0); + + qDebug() << "have contact" << contact.detail<QContactDisplayLabel>().label(); + emit this->incomingCall(m_cookie, number, contact.detail<QContactDisplayLabel>().label()); + } else { + qDebug() << "unknown contact" << number; + emit this->incomingCall(m_cookie, number, QString()); + } + }); + + request->setManager(m_contactManager); + request->start(); +} + +void TelepathyMonitor::callStateChanged(Tp::CallState state) +{ + qDebug() << "call state changed1"; + Tp::CallChannel *channel = qobject_cast<Tp::CallChannel*>(sender()); + uint cookie = m_currentCalls.key(channel); + + qDebug() << "call state changed2" << state << "cookie:" << cookie; + + switch (state) { + case Tp::CallStateActive: + emit callStarted(cookie); + m_currentCallStates[cookie] = Tp::CallStateActive; + break; + case Tp::CallStateEnded: { + Tp::CallState oldState = m_currentCallStates.value(cookie); + emit callEnded(cookie, oldState != Tp::CallStateActive); + m_currentCalls.take(cookie); + m_currentCallStates.take(cookie); + break; + } + default: + break; + } +} + +void TelepathyMonitor::checkAndAddAccount(const Tp::AccountPtr& account) +{ + Tp::ConnectionCapabilities caps = account->capabilities(); + // TODO: Later on we will need to filter for the right capabilities, and also allow dynamic account detection + // Don't check caps for now as a workaround for https://bugs.launchpad.net/ubuntu/+source/media-hub/+bug/1409125 + // at least until we are able to find out the root cause of it (check rev 107 for the caps check) + auto tcm = new TelepathyCallMonitor(account); + connect(tcm, &TelepathyCallMonitor::callStarted, this, &TelepathyMonitor::onCallStarted); + m_callMonitors.append(tcm); +} diff --git a/rockworkd/platformintegration/sailfish/callchannelobserver.h b/rockworkd/platformintegration/sailfish/callchannelobserver.h new file mode 100644 index 0000000..ba3415d --- /dev/null +++ b/rockworkd/platformintegration/sailfish/callchannelobserver.h @@ -0,0 +1,74 @@ +#ifndef CALLCHANNELOBSERVER_H +#define CALLCHANNELOBSERVER_H + +#include <TelepathyQt/AccountManager> +#include <TelepathyQt/SimpleCallObserver> +#include <TelepathyQt/PendingOperation> +#include <TelepathyQt/PendingReady> +#include <TelepathyQt/PendingAccount> +#include <TelepathyQt/CallChannel> + +#include <QContactManager> + +QTCONTACTS_USE_NAMESPACE + +class TelepathyCallMonitor : public QObject +{ + Q_OBJECT +public: + TelepathyCallMonitor(const Tp::AccountPtr& account): + mAccount(account), + mCallObserver(Tp::SimpleCallObserver::create(mAccount)) { + connect(mCallObserver.data(), SIGNAL(callStarted(Tp::CallChannelPtr)), SIGNAL(callStarted(Tp::CallChannelPtr))); +// connect(mCallObserver.data(), SIGNAL(callEnded(Tp::CallChannelPtr,QString,QString)), SIGNAL(callEnded())); +// connect(mCallObserver.data(), SIGNAL(streamedMediaCallStarted(Tp::StreamedMediaChannelPtr)), SIGNAL(offHook())); +// connect(mCallObserver.data(), SIGNAL(streamedMediaCallEnded(Tp::StreamedMediaChannelPtr,QString,QString)), SIGNAL(onHook())); + } + +signals: + void callStarted(Tp::CallChannelPtr callChannel); + void callEnded(); + +private: + Tp::AccountPtr mAccount; + Tp::SimpleCallObserverPtr mCallObserver; +}; + +class TelepathyMonitor: public QObject +{ + Q_OBJECT +public: + TelepathyMonitor(QObject *parent = 0); + + void hangupCall(uint cookie); + +private slots: + void accountManagerSetup(); + void accountManagerReady(Tp::PendingOperation* operation); + + void newAccount(const Tp::AccountPtr& account); + void accountReady(Tp::PendingOperation* operation); + + void onCallStarted(Tp::CallChannelPtr callChannel); + void callStateChanged(Tp::CallState state); + +signals: + void incomingCall(uint cookie, const QString &number, const QString &name); + void callStarted(uint cookie); + void callEnded(uint cookie, bool missed); + +private: + void checkAndAddAccount(const Tp::AccountPtr& account); + +private: + Tp::AccountManagerPtr m_accountManager; + QList<TelepathyCallMonitor*> m_callMonitors; + QContactManager *m_contactManager; + + QHash<uint, Tp::CallChannel*> m_currentCalls; + QHash<uint, Tp::CallState> m_currentCallStates; + + uint m_cookie = 0; +}; + +#endif // CALLCHANNELOBSERVER_H diff --git a/rockworkd/platformintegration/sailfish/organizeradapter.cpp b/rockworkd/platformintegration/sailfish/organizeradapter.cpp new file mode 100644 index 0000000..416aad2 --- /dev/null +++ b/rockworkd/platformintegration/sailfish/organizeradapter.cpp @@ -0,0 +1,97 @@ +#include "organizeradapter.h" + +#include <QOrganizerItemFetchRequest> +#include <QDebug> +#include <QOrganizerEventOccurrence> +#include <QOrganizerItemDetail> +# include <extendedcalendar.h> +# include <extendedstorage.h> + +QTORGANIZER_USE_NAMESPACE + +#define MANAGER "eds" +#define MANAGER_FALLBACK "memory" + +OrganizerAdapter::OrganizerAdapter(QObject *parent) : QObject(parent) +{ + QString envManager(qgetenv("ALARM_BACKEND")); + if (envManager.isEmpty()) + envManager = MANAGER; + if (!QOrganizerManager::availableManagers().contains(envManager)) { + envManager = MANAGER_FALLBACK; + } + m_manager = new QOrganizerManager(envManager); + m_manager->setParent(this); + connect(m_manager, &QOrganizerManager::dataChanged, this, &OrganizerAdapter::refresh); + + mKCal::ExtendedCalendar::Ptr calendar = mKCal::ExtendedCalendar::Ptr ( new mKCal::ExtendedCalendar( QLatin1String( "UTC" ) ) ); + mKCal::ExtendedStorage::Ptr storage = mKCal::ExtendedCalendar::defaultStorage( calendar ); + if (storage->open()) { + mKCal::Notebook::List notebooks = storage->notebooks(); + qDebug()<< "Notebooks: " + notebooks.count(); + for (int ii = 0; ii < notebooks.count(); ++ii) { + if (!notebooks.at(ii)->isReadOnly()) { + m_calendars << CalendarInfo(normalizeCalendarName(notebooks.at(ii)->name()), notebooks.at(ii)->uid()); + qDebug()<< "Notebook: " << notebooks.at(ii)->name() << notebooks.at(ii)->uid(); + } + } + } +} + +QString OrganizerAdapter::normalizeCalendarName(QString name) +{ + if (name == "qtn_caln_personal_caln") { + return tr("Personal"); + } + + return name; +} + +void OrganizerAdapter::refresh() +{ + QList<CalendarEvent> items; + foreach (const QOrganizerItem &item, m_manager->items()) { + QOrganizerEvent organizerEvent(item); + if (organizerEvent.displayLabel().isEmpty()) { + continue; + } + CalendarEvent event; + event.setId(organizerEvent.id().toString()); + event.setTitle(organizerEvent.displayLabel()); + event.setDescription(organizerEvent.description()); + event.setStartTime(organizerEvent.startDateTime()); + event.setEndTime(organizerEvent.endDateTime()); + event.setLocation(organizerEvent.location()); + event.setComment(organizerEvent.comments().join(";")); + QStringList attendees; + foreach (const QOrganizerItemDetail &attendeeDetail, organizerEvent.details(QOrganizerItemDetail::TypeEventAttendee)) { + attendees.append(attendeeDetail.value(QOrganizerItemDetail::TypeEventAttendee + 1).toString()); + } + event.setGuests(attendees); + event.setRecurring(organizerEvent.recurrenceRules().count() > 0); + + items.append(event); + + quint64 startTimestamp = QDateTime::currentMSecsSinceEpoch(); + startTimestamp -= (1000 * 60 * 60 * 24 * 7); + + foreach (const QOrganizerItem &occurranceItem, m_manager->itemOccurrences(item, QDateTime::fromMSecsSinceEpoch(startTimestamp), QDateTime::currentDateTime().addDays(7))) { + QOrganizerEventOccurrence organizerOccurrance(occurranceItem); + event.setId(organizerOccurrance.id().toString()); + event.setStartTime(organizerOccurrance.startDateTime()); + event.setEndTime(organizerOccurrance.endDateTime()); + items.append(event); + } + } + + if (m_items != items) { + m_items = items; + emit itemsChanged(m_items); + } + +} + +QList<CalendarEvent> OrganizerAdapter::items() const +{ + return m_items; +} diff --git a/rockworkd/platformintegration/sailfish/organizeradapter.h b/rockworkd/platformintegration/sailfish/organizeradapter.h new file mode 100644 index 0000000..04ebfa3 --- /dev/null +++ b/rockworkd/platformintegration/sailfish/organizeradapter.h @@ -0,0 +1,44 @@ +#ifndef ORGANIZERADAPTER_H +#define ORGANIZERADAPTER_H + +#include "libpebble/calendarevent.h" + +#include <QObject> + +#include <QOrganizerManager> +#include <QOrganizerAbstractRequest> +#include <QOrganizerEvent> + +QTORGANIZER_USE_NAMESPACE + +struct CalendarInfo +{ + QString name; + QString notebookUID; + + CalendarInfo(const QString &name, const QString ¬ebookUID = QString()) + : name(name), notebookUID(notebookUID) {} +}; + +class OrganizerAdapter : public QObject +{ + Q_OBJECT +public: + explicit OrganizerAdapter(QObject *parent = 0); + + QList<CalendarEvent> items() const; + QString normalizeCalendarName(QString name); + +public slots: + void refresh(); + +signals: + void itemsChanged(const QList<CalendarEvent> &items); + +private: + QOrganizerManager *m_manager; + QList<CalendarEvent> m_items; + QList<CalendarInfo> m_calendars; +}; + +#endif // ORGANIZERADAPTER_H diff --git a/rockworkd/platformintegration/sailfish/sailfishplatform.cpp b/rockworkd/platformintegration/sailfish/sailfishplatform.cpp new file mode 100644 index 0000000..09e1426 --- /dev/null +++ b/rockworkd/platformintegration/sailfish/sailfishplatform.cpp @@ -0,0 +1,313 @@ +#include "sailfishplatform.h" + +#include "callchannelobserver.h" +#include "organizeradapter.h" +#include "syncmonitorclient.h" + +#include <QDBusConnection> +#include <QDBusConnectionInterface> +#include <QDebug> + +SailfishPlatform::SailfishPlatform(QObject *parent): + PlatformInterface(parent), + _pulseBus(NULL), + _maxVolume(0) +{ + // Notifications + QDBusConnection::sessionBus().registerObject("/org/freedesktop/Notifications", this, QDBusConnection::ExportAllSlots); + m_iface = new QDBusInterface("org.freedesktop.DBus", "/org/freedesktop/DBus", "org.freedesktop.DBus"); + m_iface->call("AddMatch", "interface='org.freedesktop.Notifications',member='Notify',type='method_call',eavesdrop='true'"); + m_iface->call("AddMatch", "interface='org.freedesktop.Notifications',member='CloseNotification',type='method_call',eavesdrop='true'"); + + // Music + QDBusConnectionInterface *iface = QDBusConnection::sessionBus().interface(); + const QStringList &services = iface->registeredServiceNames(); + foreach (QString service, services) { + if (service.startsWith("org.mpris.MediaPlayer2.")) { + qDebug() << "have mpris service" << service; + m_mprisService = service; + fetchMusicMetadata(); + QDBusConnection::sessionBus().connect(m_mprisService, "/org/mpris/MediaPlayer2", "", "PropertiesChanged", this, SLOT(mediaPropertiesChanged(QString,QVariantMap,QStringList))); + break; + } + } + + QDBusMessage call = QDBusMessage::createMethodCall("org.PulseAudio1", "/org/pulseaudio/server_lookup1", "org.freedesktop.DBus.Properties", "Get" ); + call << "org.PulseAudio.ServerLookup1" << "Address"; + QDBusReply<QDBusVariant> lookupReply = QDBusConnection::sessionBus().call(call); + if (lookupReply.isValid()) { + // + qDebug() << "PulseAudio Bus address: " << lookupReply.value().variant().toString(); + _pulseBus = new QDBusConnection(QDBusConnection::connectToPeer(lookupReply.value().variant().toString(), "org.PulseAudio1")); + } + // Query max volume + call = QDBusMessage::createMethodCall("com.Meego.MainVolume2", "/com/meego/mainvolume2", + "org.freedesktop.DBus.Properties", "Get"); + call << "com.Meego.MainVolume2" << "StepCount"; + QDBusReply<QDBusVariant> volumeMaxReply = _pulseBus->call(call); + if (volumeMaxReply.isValid()) { + _maxVolume = volumeMaxReply.value().variant().toUInt(); + qDebug() << "Max volume: " << _maxVolume; + } + else { + qWarning() << "Could not read volume max, cannot adjust volume: " << volumeMaxReply.error().message(); + } + + // Calls + m_telepathyMonitor = new TelepathyMonitor(this); + connect(m_telepathyMonitor, &TelepathyMonitor::incomingCall, this, &SailfishPlatform::incomingCall); + connect(m_telepathyMonitor, &TelepathyMonitor::callStarted, this, &SailfishPlatform::callStarted); + connect(m_telepathyMonitor, &TelepathyMonitor::callEnded, this, &SailfishPlatform::callEnded); + + // Organizer + m_organizerAdapter = new OrganizerAdapter(this); + m_organizerAdapter->refresh(); + connect(m_organizerAdapter, &OrganizerAdapter::itemsChanged, this, &SailfishPlatform::organizerItemsChanged); + m_syncMonitorClient = new SyncMonitorClient(this); + connect(m_syncMonitorClient, &SyncMonitorClient::stateChanged, [this]() { if (m_syncMonitorClient->state() == "idle") m_organizerAdapter->refresh();}); + m_syncTimer.start(1000 * 60 * 60); + connect(&m_syncTimer, &QTimer::timeout, [this]() { m_syncMonitorClient->sync({"calendar"});}); + m_syncMonitorClient->sync({"calendar"}); +} + +QDBusInterface *SailfishPlatform::interface() const +{ + return m_iface; +} + +uint SailfishPlatform::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() << "Notification received" << app_name << replaces_id << app_icon << summary << body << actions << hints << expire_timeout; + QString owner = hints.value("x-nemo-owner", "").toString(); + + // Look up the notification category and its parameters + QString category = hints.value("category", "").toString(); + QHash<QString, QString> categoryParams = this->getCategoryParams(category); + + // Ignore transient and hidden notifications (notif hints override category hints) + // Hack this to accept transient -preview and -summary notifications, as we don't know how to decode the actual notifs yet + if (hints.value("transient", categoryParams.value("transient", "false")).toString() == "true") { + qDebug() << "Ignoring transient notification from " << owner; + return 0; + } + else if (hints.value("x-nemo-hidden", "false").toString() == "true" ) { + qDebug() << "Ignoring hidden notification from " << owner; + return 0; + } + + Notification n(app_name); + if (owner == "twitter-notifications-client") { + n.setType(Notification::NotificationTypeTwitter); + n.setSourceName("Twitter"); + } else if (category == "x-nemo.email") { + if (app_name.toLower().contains("gmail")) { + n.setType(Notification::NotificationTypeGMail); + n.setSourceName("GMail"); + } + else { + n.setType(Notification::NotificationTypeEmail); + n.setSubject(app_name); + } + } else if (owner == "facebook-notifications-client") { + n.setType(Notification::NotificationTypeFacebook); + n.setSourceName("Facebook"); + } else if (hints.value("x-nemo-origin-package").toString() == "org.telegram.messenger" + || category.startsWith("harbour.sailorgram")) { + n.setType(Notification::NotificationTypeTelegram); + n.setSourceName("Telegram"); + } else if (hints.value("x-nemo-origin-package").toString() == "com.google.android.apps.babel" + || owner == "harbour-hangish") { + n.setType(Notification::NotificationTypeHangout); + n.setSourceName("Hangouts"); + } else if (hints.value("x-nemo-origin-package").toString() == "com.whatsapp" + || owner.toLower().contains("whatsup")) { + n.setType(Notification::NotificationTypeWhatsApp); + n.setSourceName("Whatsapp"); + } else if (app_name.contains("indicator-datetime")) { + n.setType(Notification::NotificationTypeReminder); + n.setSourceName("reminders"); + } else { + n.setType(Notification::NotificationTypeGeneric); + } + n.setSender(summary); + n.setBody(body); + foreach (const QString &action, actions) { + if (action == "default") { + n.setActToken(hints.value("x-nemo-remote-action-default").toString()); + break; + } + } + qDebug() << "have act token" << n.actToken(); + + emit notificationReceived(n); + // We never return something. We're just snooping in... + setDelayedReply(true); + return 0; +} + + QHash<QString, QString> SailfishPlatform::getCategoryParams(QString category) + { + if (!category.isEmpty()) { + QString categoryConfigFile = QString("/usr/share/lipstick/notificationcategories/%1.conf").arg(category); + QFile testFile(categoryConfigFile); + if (testFile.exists()) { + QHash<QString, QString> categories; + QSettings settings(categoryConfigFile, QSettings::IniFormat); + const QStringList settingKeys = settings.allKeys(); + foreach (const QString &settingKey, settingKeys) { + categories[settingKey] = settings.value(settingKey).toString(); + } + return categories; + } + } + return QHash<QString, QString>(); + } + +void SailfishPlatform::sendMusicControlCommand(MusicControlButton controlButton) +{ + QString method; + switch (controlButton) { + case MusicControlPlayPause: + method = "PlayPause"; + break; + case MusicControlSkipBack: + method = "Previous"; + break; + case MusicControlSkipNext: + method = "Next"; + break; + default: + ; + } + + if (!method.isEmpty()) { + QDBusMessage call = QDBusMessage::createMethodCall(m_mprisService, "/org/mpris/MediaPlayer2", "org.mpris.MediaPlayer2.Player", method); + QDBusError err = QDBusConnection::sessionBus().call(call); + + if (err.isValid()) { + qWarning() << "Error calling mpris method on" << m_mprisService << ":" << err.message(); + } + return; + } + + if (controlButton == MusicControlVolumeUp || controlButton == MusicControlVolumeDown) { + QDBusMessage call = QDBusMessage::createMethodCall("com.Meego.MainVolume2", "/com/meego/mainvolume2", + "org.freedesktop.DBus.Properties", "Get"); + call << "com.Meego.MainVolume2" << "CurrentStep"; + + QDBusReply<QDBusVariant> volumeReply = _pulseBus->call(call); + if (volumeReply.isValid()) { + // Decide the new value for volume, taking limits into account + uint volume = volumeReply.value().variant().toUInt(); + uint newVolume; + qDebug() << "Current volume: " << volumeReply.value().variant().toUInt(); + if (controlButton == MusicControlVolumeUp && volume < _maxVolume-1 ) { + newVolume = volume + 1; + } + else if (controlButton == MusicControlVolumeDown && volume > 0) { + newVolume = volume - 1; + } + else { + qDebug() << "Volume already at limit"; + newVolume = volume; + } + + // If we have a new volume level, change it + if (newVolume != volume) { + qDebug() << "Setting volume: " << newVolume; + + call = QDBusMessage::createMethodCall("com.Meego.MainVolume2", "/com/meego/mainvolume2", + "org.freedesktop.DBus.Properties", "Set"); + call << "com.Meego.MainVolume2" << "CurrentStep" << QVariant::fromValue(QDBusVariant(newVolume)); + + QDBusError err = _pulseBus->call(call); + if (err.isValid()) { + qWarning() << err.message(); + } + } + } + } +} + +MusicMetaData SailfishPlatform::musicMetaData() const +{ + return m_musicMetaData; +} + +void SailfishPlatform::hangupCall(uint cookie) +{ + m_telepathyMonitor->hangupCall(cookie); +} + +QList<CalendarEvent> SailfishPlatform::organizerItems() const +{ + return m_organizerAdapter->items(); +} + +void SailfishPlatform::actionTriggered(const QString &actToken) +{ + QVariantMap action; + // Extract the element of the DBus call + QStringList elements(actToken.split(' ', QString::SkipEmptyParts)); + if (elements.size() <= 3) { + qWarning() << "Unable to decode invalid remote action:" << actToken; + } else { + int index = 0; + action.insert(QStringLiteral("service"), elements.at(index++)); + action.insert(QStringLiteral("path"), elements.at(index++)); + action.insert(QStringLiteral("iface"), elements.at(index++)); + action.insert(QStringLiteral("method"), elements.at(index++)); + + if (index < elements.size()) { + QVariantList args; + while (index < elements.size()) { + const QString &arg(elements.at(index++)); + const QByteArray buffer(QByteArray::fromBase64(arg.toUtf8())); + + QDataStream stream(buffer); + QVariant var; + stream >> var; + args.append(var); + } + action.insert(QStringLiteral("arguments"), args); + } + qDebug() << "Calling: " << action; + QDBusMessage call = QDBusMessage::createMethodCall(action.value("service").toString(), action.value("path").toString(), action.value("iface").toString(), action.value("method").toString()); + if (action.contains("arguments")) call.setArguments(action.value("arguments").toList()); + QDBusConnection::sessionBus().call(call); + } +} + +void SailfishPlatform::fetchMusicMetadata() +{ + if (!m_mprisService.isEmpty()) { + QDBusMessage call = QDBusMessage::createMethodCall(m_mprisService, "/org/mpris/MediaPlayer2", "org.freedesktop.DBus.Properties", "Get"); + call << "org.mpris.MediaPlayer2.Player" << "Metadata"; + QDBusPendingCall pcall = QDBusConnection::sessionBus().asyncCall(call); + QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pcall, this); + connect(watcher, &QDBusPendingCallWatcher::finished, this, &SailfishPlatform::fetchMusicMetadataFinished); + } +} + +void SailfishPlatform::fetchMusicMetadataFinished(QDBusPendingCallWatcher *watcher) +{ + watcher->deleteLater(); + QDBusReply<QDBusVariant> reply = watcher->reply(); + if (reply.isValid()) { + QVariantMap curMetadata = qdbus_cast<QVariantMap>(reply.value().variant().value<QDBusArgument>()); + m_musicMetaData.artist = curMetadata.value("xesam:artist").toString(); + m_musicMetaData.album = curMetadata.value("xesam:album").toString(); + m_musicMetaData.title = curMetadata.value("xesam:title").toString(); + emit musicMetadataChanged(m_musicMetaData); + } else { + qWarning() << reply.error().message(); + } +} + +void SailfishPlatform::mediaPropertiesChanged(const QString &interface, const QVariantMap &changedProps, const QStringList &invalidatedProps) +{ + Q_UNUSED(interface) + Q_UNUSED(changedProps) + Q_UNUSED(invalidatedProps) + fetchMusicMetadata(); +} diff --git a/rockworkd/platformintegration/sailfish/sailfishplatform.h b/rockworkd/platformintegration/sailfish/sailfishplatform.h new file mode 100644 index 0000000..e18b986 --- /dev/null +++ b/rockworkd/platformintegration/sailfish/sailfishplatform.h @@ -0,0 +1,58 @@ +#ifndef SAILFISHPLATFORM_H +#define SAILFISHPLATFORM_H + +#include "libpebble/platforminterface.h" +#include "libpebble/enums.h" + +#include <QDBusInterface> +#include <TelepathyQt/AbstractClientObserver> + +class QDBusPendingCallWatcher; +class TelepathyMonitor; +class OrganizerAdapter; +class SyncMonitorClient; + +class SailfishPlatform : public PlatformInterface, public QDBusContext +{ + Q_OBJECT + Q_CLASSINFO("D-Bus Interface", "org.freedesktop.Notifications") + Q_PROPERTY(QDBusInterface* interface READ interface) + + +public: + SailfishPlatform(QObject *parent = 0); + QDBusInterface* interface() const; + + void sendMusicControlCommand(MusicControlButton controlButton) override; + MusicMetaData musicMetaData() const override; + void hangupCall(uint cookie) override; + QHash<QString, QString> getCategoryParams(QString category); + + QList<CalendarEvent> organizerItems() const override; + + void actionTriggered(const QString &actToken) override; + +public slots: + 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); + + +private slots: + void fetchMusicMetadata(); + void fetchMusicMetadataFinished(QDBusPendingCallWatcher *watcher); + void mediaPropertiesChanged(const QString &interface, const QVariantMap &changedProps, const QStringList &invalidatedProps); + +private: + QDBusInterface *m_iface; + + QString m_mprisService; + MusicMetaData m_musicMetaData; + QDBusConnection *_pulseBus; + uint _maxVolume; + + TelepathyMonitor *m_telepathyMonitor; + OrganizerAdapter *m_organizerAdapter; + SyncMonitorClient *m_syncMonitorClient; + QTimer m_syncTimer; +}; + +#endif // SAILFISHPLATFORM_H diff --git a/rockworkd/platformintegration/sailfish/syncmonitorclient.cpp b/rockworkd/platformintegration/sailfish/syncmonitorclient.cpp new file mode 100644 index 0000000..b43509e --- /dev/null +++ b/rockworkd/platformintegration/sailfish/syncmonitorclient.cpp @@ -0,0 +1,100 @@ +/* + * Copyright 2014 Canonical Ltd. + * + * This file is part of sync-monitor. + * + * sync-monitor is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 3. + * + * contact-service-app is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <QDebug> +#include <QTimer> + +#include "syncmonitorclient.h" + +#define SYNCMONITOR_DBUS_SERVICE_NAME "com.canonical.SyncMonitor" +#define SYNCMONITOR_DBUS_OBJECT_PATH "/com/canonical/SyncMonitor" +#define SYNCMONITOR_DBUS_INTERFACE "com.canonical.SyncMonitor" + + +SyncMonitorClient::SyncMonitorClient(QObject *parent) + : QObject(parent), + m_iface(0) +{ + m_iface = new QDBusInterface(SYNCMONITOR_DBUS_SERVICE_NAME, + SYNCMONITOR_DBUS_OBJECT_PATH, + SYNCMONITOR_DBUS_INTERFACE); + if (m_iface->lastError().isValid()) { + qWarning() << "Fail to connect with sync monitor:" << m_iface->lastError(); + return; + } + + connect(m_iface, SIGNAL(stateChanged()), SIGNAL(stateChanged())); + connect(m_iface, SIGNAL(enabledServicesChanged()), SIGNAL(enabledServicesChanged())); + m_iface->call("attach"); +} + +SyncMonitorClient::~SyncMonitorClient() +{ + if (m_iface) { + m_iface->call("detach"); + delete m_iface; + m_iface = 0; + } +} + +QString SyncMonitorClient::state() const +{ + if (m_iface) { + return m_iface->property("state").toString(); + } else { + return ""; + } +} + +QStringList SyncMonitorClient::enabledServices() const +{ + if (m_iface) { + return m_iface->property("enabledServices").toStringList(); + } else { + return QStringList(); + } +} + +/*! + Start a new sync for specified services +*/ +void SyncMonitorClient::sync(const QStringList &services) +{ + if (m_iface) { + qDebug() << "starting sync!"; + m_iface->call("sync", services); + } +} + +/*! + Cancel current sync for specified services +*/ +void SyncMonitorClient::cancel(const QStringList &services) +{ + if (m_iface) { + m_iface->call("cancel", services); + } +} + +/*! + Chek if a specific service is enabled or not +*/ +bool SyncMonitorClient::serviceIsEnabled(const QString &service) +{ + return enabledServices().contains(service); +} diff --git a/rockworkd/platformintegration/sailfish/syncmonitorclient.h b/rockworkd/platformintegration/sailfish/syncmonitorclient.h new file mode 100644 index 0000000..1587ba5 --- /dev/null +++ b/rockworkd/platformintegration/sailfish/syncmonitorclient.h @@ -0,0 +1,51 @@ +/* + * Copyright 2014 Canonical Ltd. + * + * This file is part of sync-monitor. + * + * sync-monitor is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 3. + * + * contact-service-app is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef SYNCMONITOR_QML_H +#define SYNCMONITOR_QML_H + +#include <QObject> +#include <QDBusInterface> + +class SyncMonitorClient : public QObject +{ + Q_OBJECT + Q_PROPERTY(QString state READ state NOTIFY stateChanged) + Q_PROPERTY(QStringList enabledServices READ enabledServices NOTIFY enabledServicesChanged) + +public: + SyncMonitorClient(QObject *parent = 0); + ~SyncMonitorClient(); + + QString state() const; + QStringList enabledServices() const; + +Q_SIGNALS: + void stateChanged(); + void enabledServicesChanged(); + +public Q_SLOTS: + void sync(const QStringList &services); + void cancel(const QStringList &services); + bool serviceIsEnabled(const QString &service); + +private: + QDBusInterface *m_iface; +}; + +#endif diff --git a/rockworkd/platformintegration/sailfish/voicecallhandler.cpp b/rockworkd/platformintegration/sailfish/voicecallhandler.cpp new file mode 100644 index 0000000..2ae5087 --- /dev/null +++ b/rockworkd/platformintegration/sailfish/voicecallhandler.cpp @@ -0,0 +1,372 @@ +#include "voicecallhandler.h"
+
+#include <QDebug>
+#include <QDBusInterface>
+#include <QDBusPendingReply>
+#include <QDBusReply>
+#include <QVariantMap>
+
+/*!
+ \class VoiceCallHandler
+ \brief This is the D-Bus proxy for communicating with the voice call manager
+ from a declarative context, this interface specifically interfaces with
+ the managers' voice call handler instances.
+*/
+class VoiceCallHandlerPrivate
+{
+ Q_DECLARE_PUBLIC(VoiceCallHandler)
+
+public:
+ VoiceCallHandlerPrivate(VoiceCallHandler *q, const QString &pHandlerId)
+ : q_ptr(q), handlerId(pHandlerId), interface(NULL)
+ , duration(0), status(0), emergency(false), incoming(false)
+ , multiparty(false) , forwarded(false), remoteHeld(false)
+ { /* ... */ }
+
+ VoiceCallHandler *q_ptr;
+
+ QString handlerId;
+
+ QDBusInterface *interface;
+
+ int duration;
+ int status;
+ QString statusText;
+ QString lineId;
+ QString providerId;
+ QDateTime startedAt;
+ bool emergency;
+ bool incoming;
+ bool multiparty;
+ bool forwarded;
+ bool remoteHeld;
+};
+
+/*!
+ Constructs a new proxy interface for the provided voice call handlerId.
+*/
+VoiceCallHandler::VoiceCallHandler(const QString &handlerId, QObject *parent)
+ : QObject(parent), l(metaObject()->className()), d_ptr(new VoiceCallHandlerPrivate(this, handlerId))
+{
+ Q_D(VoiceCallHandler);
+ qCDebug(l) << QString("Creating D-Bus interface to: ") + handlerId;
+ d->interface = new QDBusInterface("org.nemomobile.voicecall",
+ "/calls/" + handlerId,
+ "org.nemomobile.voicecall.VoiceCall",
+ QDBusConnection::sessionBus(),
+ this);
+ this->initialize(true);
+}
+
+VoiceCallHandler::~VoiceCallHandler()
+{
+ Q_D(VoiceCallHandler);
+ delete d;
+}
+
+void VoiceCallHandler::initialize(bool notifyError)
+{
+ Q_D(VoiceCallHandler);
+
+ if (d->interface->isValid()) {
+ if (getProperties()) {
+ emit durationChanged();
+ emit statusChanged();
+ emit lineIdChanged();
+ emit startedAtChanged();
+ emit multipartyChanged();
+ emit emergencyChanged();
+ emit forwardedChanged();
+
+ connect(d->interface, SIGNAL(error(QString)), SIGNAL(error(QString)));
+ connect(d->interface, SIGNAL(statusChanged(int, QString)), SLOT(onStatusChanged(int, QString)));
+ connect(d->interface, SIGNAL(lineIdChanged(QString)), SLOT(onLineIdChanged(QString)));
+ connect(d->interface, SIGNAL(durationChanged(int)), SLOT(onDurationChanged(int)));
+ connect(d->interface, SIGNAL(startedAtChanged(QDateTime)), SLOT(onStartedAtChanged(QDateTime)));
+ connect(d->interface, SIGNAL(emergencyChanged(bool)), SLOT(onEmergencyChanged(bool)));
+ connect(d->interface, SIGNAL(multipartyChanged(bool)), SLOT(onMultipartyChanged(bool)));
+ connect(d->interface, SIGNAL(forwardedChanged(bool)), SLOT(onForwardedChanged(bool)));
+ connect(d->interface, SIGNAL(remoteHeldChanged(bool)), SLOT(onRemoteHeldChanged(bool)));
+ }
+ else {
+ if (notifyError) emit this->error("Failed to get VoiceCall properties from VCM D-Bus service.");
+ }
+ }
+ else {
+ qCCritical(l) << d->interface->lastError().name() << d->interface->lastError().message();
+ }
+}
+
+bool VoiceCallHandler::getProperties()
+{
+ Q_D(VoiceCallHandler);
+
+ QDBusInterface props(d->interface->service(), d->interface->path(),
+ "org.freedesktop.DBus.Properties", d->interface->connection());
+
+ QDBusReply<QVariantMap> reply = props.call("GetAll", d->interface->interface());
+ if (reply.isValid()) {
+ QVariantMap props = reply.value();
+ qCDebug(l) << props;
+ d->providerId = props["providerId"].toString();
+ d->duration = props["duration"].toInt();
+ d->status = props["status"].toInt();
+ d->statusText = props["statusText"].toString();
+ d->lineId = props["lineId"].toString();
+ d->startedAt = QDateTime::fromMSecsSinceEpoch(props["startedAt"].toULongLong());
+ d->multiparty = props["isMultiparty"].toBool();
+ d->emergency = props["isEmergency"].toBool();
+ d->forwarded = props["isForwarded"].toBool();
+ d->incoming = props["isIncoming"].toBool();
+ d->remoteHeld = props["isIncoming"].toBool();
+ return true;
+ }
+ else {
+ qCCritical(l) << "Failed to get VoiceCall properties from VCM D-Bus service.";
+ return false;
+ }
+}
+
+void VoiceCallHandler::onDurationChanged(int duration)
+{
+ Q_D(VoiceCallHandler);
+ //qCDebug(l) <<"onDurationChanged"<<duration;
+ d->duration = duration;
+ emit durationChanged();
+}
+
+void VoiceCallHandler::onStatusChanged(int status, QString statusText)
+{
+ Q_D(VoiceCallHandler);
+ qCDebug(l) <<"onStatusChanged" << status << statusText;
+ d->status = status;
+ d->statusText = statusText;
+ if (status) getProperties(); // make sure all properties are present
+ emit statusChanged();
+}
+
+void VoiceCallHandler::onLineIdChanged(QString lineId)
+{
+ Q_D(VoiceCallHandler);
+ qCDebug(l) << "onLineIdChanged" << lineId;
+ d->lineId = lineId;
+ emit lineIdChanged();
+}
+
+void VoiceCallHandler::onStartedAtChanged(const QDateTime &startedAt)
+{
+ Q_D(VoiceCallHandler);
+ qCDebug(l) << "onStartedAtChanged" << startedAt;
+ d->startedAt = d->interface->property("startedAt").toDateTime();
+ emit startedAtChanged();
+}
+
+void VoiceCallHandler::onEmergencyChanged(bool isEmergency)
+{
+ Q_D(VoiceCallHandler);
+ qCDebug(l) << "onEmergencyChanged" << isEmergency;
+ d->emergency = isEmergency;
+ emit emergencyChanged();
+}
+
+void VoiceCallHandler::onMultipartyChanged(bool isMultiparty)
+{
+ Q_D(VoiceCallHandler);
+ qCDebug(l) << "onMultipartyChanged" << isMultiparty;
+ d->multiparty = isMultiparty;
+ emit multipartyChanged();
+}
+
+void VoiceCallHandler::onForwardedChanged(bool isForwarded)
+{
+ Q_D(VoiceCallHandler);
+ qCDebug(l) << "onForwardedChanged" << isForwarded;
+ d->forwarded = isForwarded;
+ emit forwardedChanged();
+}
+
+void VoiceCallHandler::onRemoteHeldChanged(bool isRemoteHeld)
+{
+ Q_D(VoiceCallHandler);
+ qCDebug(l) << "onRemoteHeldChanged" << isRemoteHeld;
+ d->forwarded = isRemoteHeld;
+ emit remoteHeldChanged();
+}
+
+/*!
+ Returns this voice calls' handler id.
+ */
+QString VoiceCallHandler::handlerId() const
+{
+ Q_D(const VoiceCallHandler);
+ return d->handlerId;
+}
+
+/*!
+ Returns this voice calls' provider id.
+ */
+QString VoiceCallHandler::providerId() const
+{
+ Q_D(const VoiceCallHandler);
+ return d->providerId;
+}
+
+/*!
+ Returns this voice calls' call status.
+ */
+int VoiceCallHandler::status() const
+{
+ Q_D(const VoiceCallHandler);
+ return d->status;
+}
+
+/*!
+ Returns this voice calls' call status as a symbolic string.
+ */
+QString VoiceCallHandler::statusText() const
+{
+ Q_D(const VoiceCallHandler);
+ return d->statusText;
+}
+
+/*!
+ Returns this voice calls' remote end-point line id.
+ */
+QString VoiceCallHandler::lineId() const
+{
+ Q_D(const VoiceCallHandler);
+ return d->lineId;
+}
+
+/*!
+ Returns this voice calls' started at property.
+ */
+QDateTime VoiceCallHandler::startedAt() const
+{
+ Q_D(const VoiceCallHandler);
+ return d->startedAt;
+}
+
+/*!
+ Returns this voice calls' duration property.
+ */
+int VoiceCallHandler::duration() const
+{
+ Q_D(const VoiceCallHandler);
+ return d->duration;
+}
+
+/*!
+ Returns this voice calls' incoming call flag property.
+ */
+bool VoiceCallHandler::isIncoming() const
+{
+ Q_D(const VoiceCallHandler);
+ return d->incoming;
+}
+
+/*!
+ Returns this voice calls' multiparty flag property.
+ */
+bool VoiceCallHandler::isMultiparty() const
+{
+ Q_D(const VoiceCallHandler);
+ return d->multiparty;
+}
+
+/*!
+ Returns this voice calls' forwarded flag property.
+ */
+bool VoiceCallHandler::isForwarded() const
+{
+ Q_D(const VoiceCallHandler);
+ return d->forwarded;
+}
+
+/*!
+ Returns this voice calls' emergency flag property.
+ */
+bool VoiceCallHandler::isEmergency() const
+{
+ Q_D(const VoiceCallHandler);
+ return d->emergency;
+}
+
+/*!
+ Returns this voice calls' remoteHeld flag property.
+ */
+bool VoiceCallHandler::isRemoteHeld() const
+{
+ Q_D(const VoiceCallHandler);
+ return d->remoteHeld;
+}
+
+/*!
+ Initiates answering this call, if the call is an incoming call.
+ */
+void VoiceCallHandler::answer()
+{
+ Q_D(VoiceCallHandler);
+ QDBusPendingCall call = d->interface->asyncCall("answer");
+
+ QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(call, this);
+ QObject::connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)), SLOT(onPendingCallFinished(QDBusPendingCallWatcher*)));
+}
+
+/*!
+ Initiates droping the call, unless the call is disconnected.
+ */
+void VoiceCallHandler::hangup()
+{
+ Q_D(VoiceCallHandler);
+ QDBusPendingCall call = d->interface->asyncCall("hangup");
+
+ QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(call, this);
+ QObject::connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)), SLOT(onPendingCallFinished(QDBusPendingCallWatcher*)));
+}
+
+/*!
+ Initiates holding the call, unless the call is disconnected.
+ */
+void VoiceCallHandler::hold(bool on)
+{
+ Q_D(VoiceCallHandler);
+ QDBusPendingCall call = d->interface->asyncCall("hold", on);
+
+ QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(call, this);
+ QObject::connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)), SLOT(onPendingCallFinished(QDBusPendingCallWatcher*)));
+}
+
+/*!
+ Initiates deflecting the call to the provided target phone number.
+ */
+void VoiceCallHandler::deflect(const QString &target)
+{
+ Q_D(VoiceCallHandler);
+ QDBusPendingCall call = d->interface->asyncCall("deflect", target);
+
+ QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(call, this);
+ QObject::connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)), SLOT(onPendingCallFinished(QDBusPendingCallWatcher*)));
+}
+
+void VoiceCallHandler::sendDtmf(const QString &tones)
+{
+ Q_D(VoiceCallHandler);
+ QDBusPendingCall call = d->interface->asyncCall("sendDtmf", tones);
+
+ QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(call, this);
+ QObject::connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)), SLOT(onPendingCallFinished(QDBusPendingCallWatcher*)));
+}
+
+void VoiceCallHandler::onPendingCallFinished(QDBusPendingCallWatcher *watcher)
+{
+ QDBusPendingReply<bool> reply = *watcher;
+
+ if (reply.isError()) {
+ qCCritical(l) << QString::fromLatin1("Received error reply for member: %1 (%2)").arg(reply.reply().member()).arg(reply.error().message());
+ emit this->error(reply.error().message());
+ watcher->deleteLater();
+ } else {
+ qCDebug(l) << QString::fromLatin1("Received successful reply for member: %1").arg(reply.reply().member());
+ }
+}
diff --git a/rockworkd/platformintegration/sailfish/voicecallhandler.h b/rockworkd/platformintegration/sailfish/voicecallhandler.h new file mode 100644 index 0000000..e718abb --- /dev/null +++ b/rockworkd/platformintegration/sailfish/voicecallhandler.h @@ -0,0 +1,96 @@ +#ifndef VOICECALLHANDLER_H
+#define VOICECALLHANDLER_H
+
+#include <QObject>
+#include <QDateTime>
+#include <QDBusPendingCallWatcher>
+#include <QLoggingCategory>
+
+class VoiceCallHandler : public QObject
+{
+ Q_OBJECT
+ QLoggingCategory l;
+
+ Q_ENUMS(VoiceCallStatus)
+
+ Q_PROPERTY(QString handlerId READ handlerId CONSTANT)
+ Q_PROPERTY(QString providerId READ providerId CONSTANT)
+ Q_PROPERTY(int status READ status NOTIFY statusChanged)
+ Q_PROPERTY(QString statusText READ statusText NOTIFY statusChanged)
+ Q_PROPERTY(QString lineId READ lineId NOTIFY lineIdChanged)
+ Q_PROPERTY(QDateTime startedAt READ startedAt NOTIFY startedAtChanged)
+ Q_PROPERTY(int duration READ duration NOTIFY durationChanged)
+ Q_PROPERTY(bool isIncoming READ isIncoming CONSTANT)
+ Q_PROPERTY(bool isEmergency READ isEmergency NOTIFY emergencyChanged)
+ Q_PROPERTY(bool isMultiparty READ isMultiparty NOTIFY multipartyChanged)
+ Q_PROPERTY(bool isForwarded READ isForwarded NOTIFY forwardedChanged)
+ Q_PROPERTY(bool isRemoteHeld READ isRemoteHeld NOTIFY remoteHeldChanged)
+
+public:
+ enum VoiceCallStatus {
+ STATUS_NULL,
+ STATUS_ACTIVE,
+ STATUS_HELD,
+ STATUS_DIALING,
+ STATUS_ALERTING,
+ STATUS_INCOMING,
+ STATUS_WAITING,
+ STATUS_DISCONNECTED
+ };
+
+ explicit VoiceCallHandler(const QString &handlerId, QObject *parent = 0);
+ ~VoiceCallHandler();
+
+ QString handlerId() const;
+ QString providerId() const;
+ int status() const;
+ QString statusText() const;
+ QString lineId() const;
+ QDateTime startedAt() const;
+ int duration() const;
+ bool isIncoming() const;
+ bool isMultiparty() const;
+ bool isEmergency() const;
+ bool isForwarded() const;
+ bool isRemoteHeld() const;
+
+Q_SIGNALS:
+ void error(const QString &error);
+ void statusChanged();
+ void lineIdChanged();
+ void durationChanged();
+ void startedAtChanged();
+ void emergencyChanged();
+ void multipartyChanged();
+ void forwardedChanged();
+ void remoteHeldChanged();
+
+public Q_SLOTS:
+ void answer();
+ void hangup();
+ void hold(bool on);
+ void deflect(const QString &target);
+ void sendDtmf(const QString &tones);
+
+protected Q_SLOTS:
+ void initialize(bool notifyError = false);
+ bool getProperties();
+
+ void onPendingCallFinished(QDBusPendingCallWatcher *watcher);
+ void onDurationChanged(int duration);
+ void onStatusChanged(int status, QString statusText);
+ void onLineIdChanged(QString lineId);
+ void onStartedAtChanged(const QDateTime &startedAt);
+ void onEmergencyChanged(bool isEmergency);
+ void onMultipartyChanged(bool isMultiparty);
+ void onForwardedChanged(bool isForwarded);
+ void onRemoteHeldChanged(bool isRemoteHeld);
+
+private:
+ class VoiceCallHandlerPrivate *d_ptr;
+
+ Q_DISABLE_COPY(VoiceCallHandler)
+ Q_DECLARE_PRIVATE(VoiceCallHandler)
+};
+
+#endif // VOICECALLHANDLER_H
diff --git a/rockworkd/platformintegration/sailfish/voicecallmanager.cpp b/rockworkd/platformintegration/sailfish/voicecallmanager.cpp new file mode 100644 index 0000000..afb3629 --- /dev/null +++ b/rockworkd/platformintegration/sailfish/voicecallmanager.cpp @@ -0,0 +1,315 @@ +#include "voicecallmanager.h" + +#include <QDebug> +#include <QTimer> +#include <QDBusInterface> +#include <QDBusPendingReply> + +class VoiceCallManagerPrivate +{ + Q_DECLARE_PUBLIC(VoiceCallManager) + +public: + VoiceCallManagerPrivate(VoiceCallManager *q) + : q_ptr(q), + interface(NULL), + activeVoiceCall(NULL), + connected(false) + { /*...*/ } + + VoiceCallManager *q_ptr; + + QDBusInterface *interface; + + QList<VoiceCallHandler*> voicecalls; + QHash<QString,VoiceCallProviderData> providers; + + VoiceCallHandler* activeVoiceCall; + + bool connected; +}; + +VoiceCallManager::VoiceCallManager(Settings *settings, QObject *parent) + : QObject(parent), l(metaObject()->className()), d_ptr(new VoiceCallManagerPrivate(this)), settings(settings) +{ + this->initialize(); +} + +VoiceCallManager::~VoiceCallManager() +{ + Q_D(VoiceCallManager); + delete d; +} + +void VoiceCallManager::initialize(bool notifyError) +{ + Q_D(VoiceCallManager); + bool success = false; + + delete d->interface; + d->interface = new QDBusInterface("org.nemomobile.voicecall", + "/", + "org.nemomobile.voicecall.VoiceCallManager", + QDBusConnection::sessionBus(), + this); + + if(d->interface->isValid()) + { + success = true; + success &= (bool)QObject::connect(d->interface, SIGNAL(error(QString)), SIGNAL(error(QString))); + success &= (bool)QObject::connect(d->interface, SIGNAL(voiceCallsChanged()), SLOT(onVoiceCallsChanged())); + success &= (bool)QObject::connect(d->interface, SIGNAL(providersChanged()), SLOT(onProvidersChanged())); + success &= (bool)QObject::connect(d->interface, SIGNAL(activeVoiceCallChanged()), SLOT(onActiveVoiceCallChanged())); + success &= (bool)QObject::connect(d->interface, SIGNAL(audioModeChanged()), SIGNAL(audioModeChanged())); + success &= (bool)QObject::connect(d->interface, SIGNAL(audioRoutedChanged()), SIGNAL(audioRoutedChanged())); + success &= (bool)QObject::connect(d->interface, SIGNAL(microphoneMutedChanged()), SIGNAL(microphoneMutedChanged())); + success &= (bool)QObject::connect(d->interface, SIGNAL(speakerMutedChanged()), SIGNAL(speakerMutedChanged())); + + onVoiceCallsChanged(); + onActiveVoiceCallChanged(); + } + + if(!(d->connected = success)) + { + QTimer::singleShot(2000, this, SLOT(initialize())); + if(notifyError) emit this->error("Failed to connect to VCM D-Bus service."); + } +} + +QDBusInterface* VoiceCallManager::interface() const +{ + Q_D(const VoiceCallManager); + return d->interface; +} + +VoiceCallHandlerList VoiceCallManager::voiceCalls() const +{ + Q_D(const VoiceCallManager); + return d->voicecalls; +} + +VoiceCallProviderHash VoiceCallManager::providers() const +{ + Q_D(const VoiceCallManager); + return d->providers; +} + +QString VoiceCallManager::defaultProviderId() const +{ + Q_D(const VoiceCallManager); + if(d->providers.count() == 0) { + qCDebug(l) << Q_FUNC_INFO << "No provider added"; + return QString::null; + } + + QStringList keys = d->providers.keys(); + qSort(keys); + + VoiceCallProviderData provider = d->providers.value(keys.value(0)); + return provider.id; +} + +VoiceCallHandler* VoiceCallManager::activeVoiceCall() const +{ + Q_D(const VoiceCallManager); + return d->activeVoiceCall; +} + +QString VoiceCallManager::audioMode() const +{ + Q_D(const VoiceCallManager); + return d->interface->property("audioMode").toString(); +} + +bool VoiceCallManager::isAudioRouted() const +{ + Q_D(const VoiceCallManager); + return d->interface->property("isAudioRouted").toBool(); +} + +bool VoiceCallManager::isMicrophoneMuted() const +{ + Q_D(const VoiceCallManager); + return d->interface->property("isMicrophoneMuted").toBool(); +} + +bool VoiceCallManager::isSpeakerMuted() const +{ + Q_D(const VoiceCallManager); + return d->interface->property("isSpeakerMuted").toBool(); +} + +void VoiceCallManager::dial(const QString &provider, const QString &msisdn) +{ + Q_D(VoiceCallManager); + QDBusPendingCall call = d->interface->asyncCall("dial", provider, msisdn); + + QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(call, this); + QObject::connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)), SLOT(onPendingCallFinished(QDBusPendingCallWatcher*))); +} + +void VoiceCallManager::hangupAll() +{ + foreach (VoiceCallHandler* handler, voiceCalls()) { + handler->hangup(); + } +} + +void VoiceCallManager::silenceRingtone() +{ + Q_D(const VoiceCallManager); + QDBusPendingCall call = d->interface->asyncCall("silenceRingtone"); + QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(call, this); + QObject::connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)), SLOT(onPendingSilenceFinished(QDBusPendingCallWatcher*))); +} + +/* + - Use of method calls instead of property setters to allow status checking. + */ +bool VoiceCallManager::setAudioMode(const QString &mode) +{ + Q_D(const VoiceCallManager); + QDBusPendingReply<bool> reply = d->interface->call("setAudioMode", mode); + return reply.isError() ? false : reply.value(); +} + +bool VoiceCallManager::setAudioRouted(bool on) +{ + Q_D(const VoiceCallManager); + QDBusPendingReply<bool> reply = d->interface->call("setAudioRouted", on); + return reply.isError() ? false : reply.value(); +} + +bool VoiceCallManager::setMuteMicrophone(bool on) +{ + Q_D(VoiceCallManager); + QDBusPendingReply<bool> reply = d->interface->call("setMuteMicrophone", on); + return reply.isError() ? false : reply.value(); +} + +bool VoiceCallManager::setMuteSpeaker(bool on) +{ + Q_D(VoiceCallManager); + QDBusPendingReply<bool> reply = d->interface->call("setMuteSpeaker", on); + return reply.isError() ? false : reply.value(); +} + +void VoiceCallManager::onVoiceCallsChanged() +{ + Q_D(VoiceCallManager); + QStringList nIds = d->interface->property("voiceCalls").toStringList(); + QStringList oIds; + + QStringList added; + QStringList removed; + + // Map current call handlers to handler ids for easy indexing. + foreach(VoiceCallHandler *handler, d->voicecalls) + { + oIds.append(handler->handlerId()); + } + + // Index new handlers to be added. + foreach(QString nId, nIds) + { + if(!oIds.contains(nId)) added.append(nId); + } + + // Index old handlers to be removed. + foreach(QString oId, oIds) + { + if(!nIds.contains(oId)) removed.append(oId); + } + + // Remove handlers that need to be removed. + foreach(QString removeId, removed) + { + for (int i = 0; i < d->voicecalls.count(); ++i) { + VoiceCallHandler *handler = d->voicecalls.at(i); + if(handler->handlerId() == removeId) + { + handler->disconnect(this); + d->voicecalls.removeAt(i); + handler->deleteLater(); + break; + } + } + } + + // Add handlers that need to be added. + foreach(QString addId, added) + { + VoiceCallHandler *handler = new VoiceCallHandler(addId, this); + d->voicecalls.append(handler); + } + + emit this->voiceCallsChanged(); +} + +void VoiceCallManager::onProvidersChanged() +{ + Q_D(VoiceCallManager); + d->providers.clear(); + foreach(QString provider, d->interface->property("providers").toStringList()) + { + QStringList parts = provider.split(':'); + d->providers.insert(parts.first(), VoiceCallProviderData(parts.first(), + parts.last(), + parts.first())); + } + + emit this->providersChanged(); +} + +void VoiceCallManager::onActiveVoiceCallChanged() +{ + Q_D(VoiceCallManager); + QString voiceCallId = d->interface->property("activeVoiceCall").toString(); + + if(d->voicecalls.count() == 0 || voiceCallId.isNull() || voiceCallId.isEmpty()) + { + d->activeVoiceCall = NULL; + } + else + { + bool found = false; + d->activeVoiceCall = NULL; + foreach(VoiceCallHandler* handler, d->voicecalls) + { + if(handler->handlerId() == voiceCallId) + { + d->activeVoiceCall = handler; + found = true; + } + if(!found) d->activeVoiceCall = NULL; + } + } + + emit this->activeVoiceCallChanged(); +} + +void VoiceCallManager::onPendingCallFinished(QDBusPendingCallWatcher *watcher) +{ + QDBusPendingReply<bool> reply = *watcher; + + if (reply.isError()) { + emit this->error(reply.error().message()); + } else { + qCDebug(l) << QString("Received successful reply for member: ") + reply.reply().member(); + } + + watcher->deleteLater(); +} + +void VoiceCallManager::onPendingSilenceFinished(QDBusPendingCallWatcher *watcher) +{ + QDBusPendingReply<> reply = *watcher; + + if (reply.isError()) { + emit this->error(reply.error().message()); + } else { + qCDebug(l) << QString("Received successful reply for member: ") + reply.reply().member(); + } + + watcher->deleteLater(); +} diff --git a/rockworkd/platformintegration/sailfish/voicecallmanager.h b/rockworkd/platformintegration/sailfish/voicecallmanager.h new file mode 100644 index 0000000..ec51230 --- /dev/null +++ b/rockworkd/platformintegration/sailfish/voicecallmanager.h @@ -0,0 +1,111 @@ +#ifndef VOICECALLMANAGER_H +#define VOICECALLMANAGER_H + +#include "voicecallhandler.h" +#include "settings.h" + +#include <QObject> +#include <QDBusInterface> +#include <QDBusPendingCallWatcher> +#include <QLoggingCategory> + +class VoiceCallProviderData +{ +public: + VoiceCallProviderData() {/*..*/} + VoiceCallProviderData(const QString &pId, const QString &pType, const QString &pLabel) + : id(pId), type(pType), label(pLabel) {/*...*/} + + QString id; + QString type; + QString label; +}; + +typedef QHash<QString,VoiceCallProviderData> VoiceCallProviderHash; + +typedef QList<VoiceCallHandler*> VoiceCallHandlerList; + +class VoiceCallManager : public QObject +{ + Q_OBJECT + QLoggingCategory l; + + Q_PROPERTY(QDBusInterface* interface READ interface) + + Q_PROPERTY(VoiceCallHandlerList voiceCalls READ voiceCalls NOTIFY voiceCallsChanged) + Q_PROPERTY(VoiceCallProviderHash providers READ providers NOTIFY providersChanged) + + Q_PROPERTY(QString defaultProviderId READ defaultProviderId NOTIFY defaultProviderChanged) + + Q_PROPERTY(VoiceCallHandler* activeVoiceCall READ activeVoiceCall NOTIFY activeVoiceCallChanged) + + Q_PROPERTY(QString audioMode READ audioMode WRITE setAudioMode NOTIFY audioModeChanged) + Q_PROPERTY(bool isAudioRouted READ isAudioRouted WRITE setAudioRouted NOTIFY audioRoutedChanged) + Q_PROPERTY(bool isMicrophoneMuted READ isMicrophoneMuted WRITE setMuteMicrophone NOTIFY microphoneMutedChanged) + Q_PROPERTY(bool isSpeakerMuted READ isSpeakerMuted WRITE setMuteSpeaker NOTIFY speakerMutedChanged) + +public: + explicit VoiceCallManager(Settings *settings, QObject *parent = 0); + ~VoiceCallManager(); + + QDBusInterface* interface() const; + + VoiceCallHandlerList voiceCalls() const; + VoiceCallProviderHash providers() const; + + QString defaultProviderId() const; + + VoiceCallHandler* activeVoiceCall() const; + + QString audioMode() const; + bool isAudioRouted() const; + + bool isMicrophoneMuted() const; + bool isSpeakerMuted() const; + +Q_SIGNALS: + void error(const QString &message); + + void providersChanged(); + void voiceCallsChanged(); + + void defaultProviderChanged(); + + void activeVoiceCallChanged(); + + void audioModeChanged(); + void audioRoutedChanged(); + void microphoneMutedChanged(); + void speakerMutedChanged(); + +public Q_SLOTS: + void dial(const QString &providerId, const QString &msisdn); + void hangupAll(); + + void silenceRingtone(); + + bool setAudioMode(const QString &mode); + bool setAudioRouted(bool on); + bool setMuteMicrophone(bool on = true); + bool setMuteSpeaker(bool on = true); + +protected Q_SLOTS: + void initialize(bool notifyError = false); + + void onProvidersChanged(); + void onVoiceCallsChanged(); + void onActiveVoiceCallChanged(); + + void onPendingCallFinished(QDBusPendingCallWatcher *watcher); + void onPendingSilenceFinished(QDBusPendingCallWatcher *watcher); + +private: + class VoiceCallManagerPrivate *d_ptr; + + Settings *settings; + + Q_DISABLE_COPY(VoiceCallManager) + Q_DECLARE_PRIVATE(VoiceCallManager) +}; + +#endif // VOICECALLMANAGER_H diff --git a/rockworkd/rockpoold.service b/rockworkd/rockpoold.service new file mode 100644 index 0000000..8f87f15 --- /dev/null +++ b/rockworkd/rockpoold.service @@ -0,0 +1,11 @@ +[Unit] +Description=Rockpool daemon +Requires=dbus.socket bluetooth.target +After=pre-user-session.target lipstick.service dbus.socket bluetooth.target + +[Service] +ExecStart=/usr/bin/rockworkd +Restart=always + +[Install] +WantedBy=user-session.target diff --git a/rockworkd/rockworkd.pro b/rockworkd/rockworkd.pro index edb97f9..53e37ff 100644 --- a/rockworkd/rockworkd.pro +++ b/rockworkd/rockworkd.pro @@ -1,3 +1,147 @@ +<<<<<<< HEAD +QT += core bluetooth dbus network contacts qml location organizer
+QT -= gui
+
+include(../version.pri)
+
+TARGET = rockpoold
+
+CONFIG += c++11
+CONFIG += console
+CONFIG += link_pkgconfig
+
+INCLUDEPATH += /usr/include/telepathy-qt5/ $$[QT_HOST_PREFIX]/include/quazip/
+LIBS += -lquazip -ltelepathy-qt5
+
+PKGCONFIG += libmkcal-qt5 libkcalcoren-qt5
+INCLUDEPATH += /usr/include/mkcal-qt5 /usr/include/kcalcoren-qt5
+
+SOURCES += main.cpp \
+ libpebble/watchconnection.cpp \
+ libpebble/pebble.cpp \
+ libpebble/watchdatareader.cpp \
+ libpebble/watchdatawriter.cpp \
+ libpebble/notificationendpoint.cpp \
+ libpebble/musicendpoint.cpp \
+ libpebble/phonecallendpoint.cpp \
+ libpebble/musicmetadata.cpp \
+ libpebble/jskit/jskitmanager.cpp \
+ libpebble/jskit/jskitconsole.cpp \
+ libpebble/jskit/jskitgeolocation.cpp \
+ libpebble/jskit/jskitlocalstorage.cpp \
+ libpebble/jskit/jskitpebble.cpp \
+ libpebble/jskit/jskitxmlhttprequest.cpp \
+ libpebble/jskit/jskittimer.cpp \
+ libpebble/jskit/jskitperformance.cpp \
+ libpebble/appinfo.cpp \
+ libpebble/appmanager.cpp \
+ libpebble/appmsgmanager.cpp \
+ libpebble/uploadmanager.cpp \
+ libpebble/bluez/bluezclient.cpp \
+ libpebble/bluez/bluez_agentmanager1.cpp \
+ libpebble/bluez/bluez_adapter1.cpp \
+ libpebble/bluez/bluez_device1.cpp \
+ libpebble/bluez/freedesktop_objectmanager.cpp \
+ libpebble/bluez/freedesktop_properties.cpp \
+ libpebble/bluez/device.cpp \
+ core.cpp \
+ pebblemanager.cpp \
+ dbusinterface.cpp \
+# Platform integration part
+ platformintegration/sailfish/sailfishplatform.cpp \
+ platformintegration/sailfish/callchannelobserver.cpp \
+# platformintegration/sailfish/voicecallmanager.cpp \
+# platformintegration/sailfish/voicecallhandler.cpp \
+ libpebble/blobdb.cpp \
+ libpebble/timelineitem.cpp \
+ libpebble/notification.cpp \
+ platformintegration/sailfish/organizeradapter.cpp \
+ libpebble/calendarevent.cpp \
+ platformintegration/sailfish/syncmonitorclient.cpp \
+ libpebble/appmetadata.cpp \
+ libpebble/appdownloader.cpp \
+ libpebble/screenshotendpoint.cpp \
+ libpebble/firmwaredownloader.cpp \
+ libpebble/bundle.cpp \
+ libpebble/watchlogendpoint.cpp \
+ libpebble/ziphelper.cpp \
+ libpebble/healthparams.cpp \
+ libpebble/dataloggingendpoint.cpp
+
+HEADERS += \
+ libpebble/watchconnection.h \
+ libpebble/pebble.h \
+ libpebble/watchdatareader.h \
+ libpebble/watchdatawriter.h \
+ libpebble/notificationendpoint.h \
+ libpebble/musicendpoint.h \
+ libpebble/musicmetadata.h \
+ libpebble/phonecallendpoint.h \
+ libpebble/platforminterface.h \
+ libpebble/jskit/jskitmanager.h \
+ libpebble/jskit/jskitconsole.h \
+ libpebble/jskit/jskitgeolocation.h \
+ libpebble/jskit/jskitlocalstorage.h \
+ libpebble/jskit/jskitpebble.h \
+ libpebble/jskit/jskitxmlhttprequest.h \
+ libpebble/jskit/jskittimer.h \
+ libpebble/jskit/jskitperformance.h \
+ libpebble/appinfo.h \
+ libpebble/appmanager.h \
+ libpebble/appmsgmanager.h \
+ libpebble/uploadmanager.h \
+ libpebble/bluez/bluezclient.h \
+ libpebble/bluez/bluez_agentmanager1.h \
+ libpebble/bluez/bluez_adapter1.h \
+ libpebble/bluez/bluez_device1.h \
+ libpebble/bluez/freedesktop_objectmanager.h \
+ libpebble/bluez/freedesktop_properties.h \
+ libpebble/bluez/device.h \
+ core.h \
+ pebblemanager.h \
+ dbusinterface.h \
+# Platform integration part
+ platformintegration/sailfish/sailfishplatform.h \
+ platformintegration/sailfish/callchannelobserver.h \
+# platformintegration/sailfish/voicecallmanager.h \
+# platformintegration/sailfish/voicecallhandler.h \
+ libpebble/blobdb.h \
+ libpebble/timelineitem.h \
+ libpebble/notification.h \
+ platformintegration/sailfish/organizeradapter.h \
+ libpebble/calendarevent.h \
+ platformintegration/sailfish/syncmonitorclient.h \
+ libpebble/appmetadata.h \
+ libpebble/appdownloader.h \
+ libpebble/enums.h \
+ libpebble/screenshotendpoint.h \
+ libpebble/firmwaredownloader.h \
+ libpebble/bundle.h \
+ libpebble/watchlogendpoint.h \
+ libpebble/ziphelper.h \
+ libpebble/healthparams.h \
+ libpebble/dataloggingendpoint.h
+
+testing: {
+ SOURCES += platformintegration/testing/testingplatform.cpp
+ HEADERS += platformintegration/testing/testingplatform.h
+ RESOURCES += platformintegration/testing/testui.qrc
+ DEFINES += ENABLE_TESTING
+ QT += qml quick
+}
+
+INSTALLS += target systemd
+
+systemd.files = $${TARGET}.service
+systemd.path = /usr/lib/systemd/user
+
+# Default rules for deployment.
+target.path = /usr/bin
+
+RESOURCES += \
+ libpebble/jskit/jsfiles.qrc
+
+======= QT += core bluetooth dbus network contacts qml location organizer websockets QT -= gui @@ -146,3 +290,4 @@ QMAKE_POST_LINK = sed -i s/@VERSION@/$$VERSION/g $$OUT_PWD/../manifest.json || e RESOURCES += \ libpebble/jskit/jsfiles.qrc +>>>>>>> refs/heads/rockwork diff --git a/rpm/rockpool.changes b/rpm/rockpool.changes new file mode 100644 index 0000000..fee8c03 --- /dev/null +++ b/rpm/rockpool.changes @@ -0,0 +1,2 @@ +* Thu Jan 21 2016 Andrew Branson <andrew@andrewbranson.net> 0.1
+- Initial Merge of pebbled and rockwork
diff --git a/rpm/rockpool.spec b/rpm/rockpool.spec new file mode 100644 index 0000000..57e470b --- /dev/null +++ b/rpm/rockpool.spec @@ -0,0 +1,97 @@ +# +# Do NOT Edit the Auto-generated Part! +# Generated by: spectacle version 0.27 +# + +Name: rockpool + +# >> macros +# << macros + +%{!?qtc_qmake:%define qtc_qmake %qmake} +%{!?qtc_qmake5:%define qtc_qmake5 %qmake5} +%{!?qtc_make:%define qtc_make make} +%{?qtc_builddir:%define _builddir %qtc_builddir} +Summary: Support for Pebble watches in SailfishOS +Version: 0.1 +Release: 1 +Group: Qt/Qt +License: GPL3 +URL: http://getpebble.com/ +Source0: %{name}-%{version}.tar.xz +Source100: rockpool.yaml +Requires: sailfishsilica-qt5 >= 0.10.9 +Requires: systemd-user-session-targets +Requires: nemo-qml-plugin-dbus-qt5 +Requires: quazip +BuildRequires: pkgconfig(Qt5DBus) +BuildRequires: pkgconfig(Qt5Bluetooth) +BuildRequires: pkgconfig(Qt5Contacts) +BuildRequires: pkgconfig(Qt5Quick) +BuildRequires: pkgconfig(Qt5Qml) +BuildRequires: pkgconfig(Qt5Core) +BuildRequires: pkgconfig(Qt5Network) +BuildRequires: pkgconfig(Qt5Location) +BuildRequires: pkgconfig(Qt5Organizer) +BuildRequires: pkgconfig(mlite5) +BuildRequires: pkgconfig(sailfishapp) >= 0.0.10 +BuildRequires: pkgconfig(icu-i18n) +BuildRequires: pkgconfig(zlib) +BuildRequires: pkgconfig(libmkcal-qt5) +BuildRequires: pkgconfig(libkcalcoren-qt5) +BuildRequires: desktop-file-utils + +%description +Support for Pebble watch on SailfishOS devices. + + +%prep +%setup -q -n %{name}-%{version} + +# >> setup +# << setup + +%build +# >> build pre +# << build pre + +%qtc_qmake5 \ + VERSION='%{version}-%{release}' + +%qtc_make %{?_smp_mflags} + +# >> build post +# << build post + +%install +rm -rf %{buildroot} +# >> install pre +# << install pre +%qmake5_install + +# >> install post +mkdir -p %{buildroot}%{_libdir}/systemd/user/user-session.target.wants +ln -s ../rockpoold.service %{buildroot}%{_libdir}/systemd/user/user-session.target.wants/ +# << install post + +desktop-file-install --delete-original \ + --dir %{buildroot}%{_datadir}/applications \ + %{buildroot}%{_datadir}/applications/*.desktop + +%post +# >> post +su nemo -c 'systemctl --user daemon-reload' +su nemo -c 'systemctl --user try-restart rockpoold.service' +update-desktop-database +# << post + +%files +%defattr(-,root,root,-) +%{_bindir} +%{_datadir}/%{name}/qml +%{_datadir}/applications/%{name}.desktop +%{_datadir}/icons/hicolor/86x86/apps/%{name}.png +%{_libdir}/systemd/user/%{name}d.service +%{_libdir}/systemd/user/user-session.target.wants/%{name}d.service +# >> files +# << files diff --git a/rpm/rockpool.yaml b/rpm/rockpool.yaml new file mode 100644 index 0000000..6d17a53 --- /dev/null +++ b/rpm/rockpool.yaml @@ -0,0 +1,43 @@ +Name: rockpool
+Summary: Support for Pebble watches in SailfishOS
+Version: 0.1
+Release: 1
+Group: Qt/Qt
+URL: http://getpebble.com/
+License: GPL3
+Sources:
+- '%{name}-%{version}.tar.xz'
+Description: |
+ Support for Pebble watch on SailfishOS devices.
+Configure: none
+Builder: qtc5
+QMakeOptions:
+- VERSION='%{version}-%{release}'
+PkgConfigBR:
+- Qt5DBus
+- Qt5Bluetooth
+- Qt5Contacts
+- Qt5Quick
+- Qt5Qml
+- Qt5Core
+- Qt5Network
+- Qt5Location
+- Qt5Organizer
+- mlite5
+- sailfishapp >= 0.0.10
+- icu-i18n
+- zlib
+- libmkcal-qt5
+- libkcalcoren-qt5
+Requires:
+- sailfishsilica-qt5 >= 0.10.9
+- systemd-user-session-targets
+- nemo-qml-plugin-dbus-qt5
+- quazip
+Files:
+- '%{_bindir}'
+- '%{_datadir}/%{name}/qml'
+- '%{_datadir}/applications/%{name}.desktop'
+- '%{_datadir}/icons/hicolor/86x86/apps/%{name}.png'
+- '%{_libdir}/systemd/user/%{name}d.service'
+- '%{_libdir}/systemd/user/user-session.target.wants/%{name}d.service'
|
