on xenial help sign in
Merge pull request #58 from ubports/xenial_-_wizard-app-update_-_dirty

Add after update wizard

commite4ced8eb15c3045a122f997b631f6729b3339023 authorMarius Gripsgard <marius@ubports.com> dateTue 14 Aug 2018, 11:24 (8 years ago) parent51467d0cbb272f
25 files changed+1587−440
plugins/Wizard/System.cpp+60−3 plugins/Wizard/System.h+17 qml/Shell.qml+2−1 qml/Wizard/Components/InputMethod.qml+9−9 qml/Wizard/Page.qml+5 qml/Wizard/Pages.qml+48−7 qml/Wizard/Pages/10-welcome-update.qml+137 qml/Wizard/Pages/10-welcome.qml+2 qml/Wizard/Pages/11-changelog.qml+61 qml/Wizard/Pages/30-wifi.qml+1 qml/Wizard/Pages/40-location.qml−290 qml/Wizard/Pages/50-timezone.qml+1 qml/Wizard/Pages/60-account.qml+1 qml/Wizard/Pages/70-passwd-type.qml+1 qml/Wizard/Pages/75-report-check.qml+1 qml/Wizard/Pages/76-app-update.qml+235 qml/Wizard/Pages/78-firmware-update.qml+233 qml/Wizard/Pages/77-system-update.qml → qml/Wizard/Pages/79-system-update.qml qml/Wizard/Pages/80-finished.qml+4−2 qml/Wizard/Pages/ClickUpdateDelegate.qml+26 qml/Wizard/Pages/DownloadHandler.qml+204 qml/Wizard/Pages/GlobalUpdateControls.qml+145 qml/Wizard/Pages/UpdateDelegate.qml+389 qml/Wizard/Pages/here-terms.qml−126 qml/Wizard/Wizard.qml+5−2
plugins/Wizard/System.cpp+60−3
@@ -1,4 +1,5 @@
11/*
2+ * Copyright (C) 2018 The UBports project
23 * Copyright (C) 2014-2016 Canonical Ltd.
34 *
45 * This program is free software: you can redistribute it and/or modify it
@@ -46,29 +47,85 @@ QString System::wizardEnabledPath()
4647 return QDir::home().filePath(QStringLiteral(".config/ubuntu-system-settings/wizard-has-run"));
4748}
4849
50+QString System::currentFrameworkPath()
51+{
52+ QFileInfo f("/usr/share/click/frameworks/current");
53+ return f.canonicalFilePath();
54+}
55+
56+/*
57+wizardEnabled and isUpdate logic
58+
59+if wizard-has-run does NOT exist == is new install
60+if wizard-has-run exists but does NOT match current framework == is update
61+if wizard-has-run exists but does match current framework == show no wizard
62+*/
63+
64+bool System::wizardPathExists() {
65+ return QFile::exists(wizardEnabledPath());
66+}
67+
4968bool System::wizardEnabled() const
5069{
51− return !QFile::exists(wizardEnabledPath());
70+ if (!wizardPathExists()) {
71+ return true;
72+ }
73+ return isUpdate();
74+}
75+
76+QString System::readCurrentFramework()
77+{
78+ QFile f(currentFrameworkPath());
79+ if (!f.open(QFile::ReadOnly | QFile::Text)) return "";
80+ QTextStream in(&f);
81+ return in.readAll();
82+}
83+
84+QString System::readWizardEnabled()
85+{
86+ QFile f(wizardEnabledPath());
87+ if (!f.open(QFile::ReadOnly | QFile::Text)) return "";
88+ QTextStream in(&f);
89+ return in.readAll();
90+}
91+
92+QString System::version() const
93+{
94+ return readCurrentFramework();
95+}
96+
97+bool System::isUpdate() const
98+{
99+ if (!wizardPathExists()) {
100+ return false;
101+ }
102+
103+ return readCurrentFramework() != readWizardEnabled();
52104}
53105
54106void System::setWizardEnabled(bool enabled)
55107{
56− if (wizardEnabled() == enabled)
108+ if (wizardEnabled() == enabled && !isUpdate())
57109 return;
58110
59111 if (enabled) {
60112 QFile::remove(wizardEnabledPath());
61113 } else {
62114 QDir(wizardEnabledPath()).mkpath(QStringLiteral(".."));
63− QFile(wizardEnabledPath()).open(QIODevice::WriteOnly);
115+ if (QFile::exists(wizardEnabledPath())) {
116+ QFile::remove(wizardEnabledPath());
117+ }
118+ QFile::copy(currentFrameworkPath(), wizardEnabledPath());
64119 m_fsWatcher.addPath(wizardEnabledPath());
65120 Q_EMIT wizardEnabledChanged();
121+ Q_EMIT isUpdateChanged();
66122 }
67123}
68124
69125void System::watcherFileChanged()
70126{
71127 Q_EMIT wizardEnabledChanged();
128+ Q_EMIT isUpdateChanged();
72129 m_fsWatcher.removePath(wizardEnabledPath());
73130}
74131
plugins/Wizard/System.h+17
@@ -1,4 +1,5 @@
11/*
2+ * Copyright (C) 2018 The UBports project
23 * Copyright (C) 2014-2016 Canonical Ltd.
34 *
45 * This program is free software: you can redistribute it and/or modify it
@@ -18,6 +19,7 @@
1819#define WIZARD_SYSTEM_H
1920
2021#include <QFileSystemWatcher>
22+#include <QVersionNumber>
2123#include <QObject>
2224#include <QString>
2325
@@ -25,12 +27,21 @@ class System : public QObject
2527{
2628 Q_OBJECT
2729 Q_PROPERTY(bool wizardEnabled READ wizardEnabled WRITE setWizardEnabled NOTIFY wizardEnabledChanged)
30+ Q_PROPERTY(QString version READ version NOTIFY versionChanged)
31+ Q_PROPERTY(bool isUpdate READ isUpdate NOTIFY isUpdateChanged)
2832
2933public:
3034 System();
3135 ~System() = default;
3236
37+ /**
38+ * Checks whether the wizard is enabled for first-run or otherwise.
39+ */
3340 bool wizardEnabled() const;
41+
42+ QString version() const;
43+ bool isUpdate() const;
44+
3445 void setWizardEnabled(bool enabled);
3546
3647public Q_SLOTS:
@@ -42,6 +53,8 @@ public Q_SLOTS:
4253
4354Q_SIGNALS:
4455 void wizardEnabledChanged();
56+ void versionChanged();
57+ void isUpdateChanged();
4558
4659private Q_SLOTS:
4760 void watcherFileChanged();
@@ -50,7 +63,11 @@ private:
5063 Q_DISABLE_COPY(System)
5164
5265 static QString wizardEnabledPath();
66+ static QString currentFrameworkPath();
5367 static void setSessionVariable(const QString &variable, const QString &value);
68+ static QString readCurrentFramework();
69+ static QString readWizardEnabled();
70+ static bool wizardPathExists();
5471
5572 QFileSystemWatcher m_fsWatcher;
5673};
qml/Shell.qml+2−1
@@ -1,4 +1,5 @@
11/*
2+ * Copyright (C) 2018 The UBports project
23 * Copyright (C) 2013-2016 Canonical, Ltd.
34 *
45 * This program is free software; you can redistribute it and/or modify
@@ -346,7 +347,7 @@ StyledItem {
346347 hides: [launcher, panel.indicators]
347348 tabletMode: shell.usageScenario != "phone"
348349 launcherOffset: launcher.progress
349− forcedUnlock: wizard.active || shell.mode === "full-shell"
350+ forcedUnlock: wizard.active && !wizard.isUpdate || shell.mode === "full-shell"
350351 background: wallpaperResolver.cachedBackground
351352 hasCustomBackground: wallpaperResolver.hasCustomBackground
352353 allowFingerprint: !dialogs.hasActiveDialog &&
qml/Wizard/Components/InputMethod.qml+9−9
@@ -21,19 +21,19 @@ import Ubuntu.Components 0.1
2121// TODO: try to share this code with that from the unity8 shell
2222
2323Item {
24− id: root
24+ id: inputMethodRoot
2525
2626 Connections {
2727 target: SurfaceManager
2828 onSurfaceCreated: {
2929 if (surface.type == MirSurfaceItem.InputMethod) {
30− root.surface = surface;
30+ inputMethodRoot.surface = surface;
3131 }
3232 }
3333
3434 onSurfaceDestroyed: {
35− if (root.surface == surface) {
36− root.surface = null;
35+ if (inputMethodRoot.surface == surface) {
36+ inputMethodRoot.surface = null;
3737 surface.parent = null;
3838 }
3939 if (!surface.parent) {
@@ -71,7 +71,7 @@ Item {
7171 visible: false
7272 // half-way down because the vkb occupies only the lower half of the surface
7373 // TODO: consider keyboard rotation
74− y: root.parent.height / 2.0
74+ y: inputMethodRoot.parent.height / 2.0
7575 }
7676 }
7777 ]
@@ -89,17 +89,17 @@ Item {
8989 ignoreUnknownSignals: true // don't wanna spam the log when surface is null
9090 onStateChanged: {
9191 if (state == MirSurfaceItem.Minimized) {
92− root.hide();
92+ inputMethodRoot.hide();
9393 } else if (state == MirSurfaceItem.Maximized) {
94− root.show();
94+ inputMethodRoot.show();
9595 }
9696 }
9797 }
9898
9999 onSurfaceChanged: {
100100 if (surface) {
101− surface.parent = root;
102− surface.anchors.fill = root;
101+ surface.parent = inputMethodRoot;
102+ surface.anchors.fill = inputMethodRoot;
103103 }
104104 }
105105
qml/Wizard/Page.qml+5
@@ -1,4 +1,5 @@
11/*
2+ * Copyright (C) 2018 The UBports project
23 * Copyright (C) 2013-2016 Canonical, Ltd.
34 *
45 * This program is free software; you can redistribute it and/or modify
@@ -50,6 +51,10 @@ Item {
5051 property bool skipValid: true
5152 property bool skip: false
5253
54+ // Marks if should be only shown if update or install
55+ property bool onlyOnUpdate: false
56+ property bool onlyOnInstall: false
57+
5358 property bool hasBackButton: true
5459 property string backButtonText: i18n.ctr("Button: Go back one page in the Wizard", "Back")
5560 property bool customBack: false
qml/Wizard/Pages.qml+48−7
@@ -1,4 +1,5 @@
11/*
2+ * Copyright (C) 2018 The UBports project
23 * Copyright (C) 2013-2016 Canonical, Ltd.
34 *
45 * This program is free software; you can redistribute it and/or modify
@@ -105,6 +106,37 @@ StyledItem {
105106 id: pageList
106107 }
107108
109+ ActivityIndicator {
110+ id: pagesSpinner
111+ anchors.centerIn: parent
112+ z: 100
113+ running: false
114+ visible: running
115+
116+ NumberAnimation on opacity {
117+ id: fadeInAnimation
118+ from: 0
119+ to: 1
120+ duration: 200
121+ }
122+
123+ onVisibleChanged: {
124+ if (visible) {
125+ opacity = 0;
126+ fadeInAnimation.start();
127+ }
128+ }
129+ }
130+
131+ Timer {
132+ id: impatientLoadingTimer
133+ interval: 1700
134+ onTriggered: {
135+ console.warn("Impatient timer going off. Fix the wizard, it's too slow at skipping pages.")
136+ pagesSpinner.running = true;
137+ }
138+ }
139+
108140 PageStack {
109141 id: pageStack
110142 objectName: "pageStack"
@@ -139,18 +171,21 @@ StyledItem {
139171
140172 function load(path) {
141173 if (currentPage) {
142− currentPage.enabled = false
174+ currentPage.enabled = false;
143175 }
144176
145177 // First load it invisible, check that we should actually use
146178 // this page, and either skip it or continue.
147− push(path, {"opacity": 0, "enabled": false})
179+ push(path, {"opacity": 0, "enabled": false});
148180
149181 timeout.restart();
182+ impatientLoadingTimer.start();
183+
184+ console.info("Loading page " + currentPage.objectName);
150185
151186 // Check for immediate skip or not. We may have to wait for
152187 // skipValid to be assigned (see Connections object below)
153− checkSkip()
188+ checkSkip();
154189
155190 var isPrimaryPage = !currentPage.customTitle;
156191 if (isPrimaryPage) {
@@ -162,13 +197,19 @@ StyledItem {
162197
163198 function checkSkip() {
164199 if (!currentPage) { // may have had a parse error
165− next()
200+ console.warn("Wizard page skipped due to possible parse error.");
201+ next();
166202 } else if (currentPage.skipValid) {
167203 if (currentPage.skip) {
168− next()
204+ next();
205+ } else if ((currentPage.onlyOnUpdate && !wizard.isUpdate) ||
206+ (currentPage.onlyOnInstall && wizard.isUpdate)) {
207+ next();
169208 } else {
170− currentPage.opacity = 1
171− currentPage.enabled = true
209+ impatientLoadingTimer.stop()
210+ pagesSpinner.running = false;
211+ currentPage.opacity = 1;
212+ currentPage.enabled = true;
172213 timeout.stop();
173214 }
174215 }
qml/Wizard/Pages/10-welcome-update.qmlnew file+137
@@ -0,0 +1,137 @@
1+/*
2+ * Copyright (C) 2018 The UBports project
3+ *
4+ * Written by: Marius Gripsgard <marius@ubports.com>
5+ *
6+ * This program is free software; you can redistribute it and/or modify
7+ * it under the terms of the GNU General Public License as published by
8+ * the Free Software Foundation; version 3.
9+ *
10+ * This program is distributed in the hope that it will be useful,
11+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+ * GNU General Public License for more details.
14+ *
15+ * You should have received a copy of the GNU General Public License
16+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
17+ */
18+
19+import QtQuick 2.4
20+import Ubuntu.Components 1.3
21+import Wizard 0.1
22+import ".." as LocalComponents
23+
24+LocalComponents.Page {
25+ objectName: "welcomeUpdate"
26+
27+ hasBackButton: false
28+ customTitle: true
29+ buttonBarVisible: false
30+ onlyOnUpdate: true
31+
32+ Component.onCompleted: {
33+ state = "reanchored";
34+ }
35+
36+ states: State {
37+ name: "reanchored"
38+ AnchorChanges { target: bgImage; anchors.top: parent.top; anchors.bottom: parent.bottom }
39+ AnchorChanges { target: column;
40+ anchors.verticalCenter: parent.verticalCenter;
41+ anchors.top: undefined
42+ }
43+ }
44+
45+ SequentialAnimation {
46+ id: splashAnimation
47+ PauseAnimation { duration: UbuntuAnimation.BriskDuration }
48+ SmoothedAnimation {
49+ target: bgImage
50+ property: "height"
51+ to: units.gu(16)
52+ duration: UbuntuAnimation.BriskDuration
53+ }
54+ NumberAnimation {
55+ target: bgImage
56+ property: 'opacity'
57+ from: 1
58+ to: 0
59+ }
60+ }
61+
62+ Image {
63+ id: bgImage
64+ source: wideMode ? "data/Desktop_splash_screen_bkg.png" : "data/Phone_splash_screen_bkg.png"
65+ scale: Image.PreserveAspectFit
66+ anchors.left: parent.left
67+ anchors.right: parent.right
68+ anchors.bottom: parent.top // outside to let it slide down
69+ visible: opacity > 0
70+ }
71+
72+ Item {
73+ id: column
74+ anchors.leftMargin: leftMargin
75+ anchors.rightMargin: rightMargin
76+ anchors.left: parent.left
77+ anchors.right: parent.right
78+ anchors.top: parent.bottom // outside to let it slide in
79+ height: childrenRect.height
80+ visible: opacity > 0
81+
82+ Label {
83+ id: welcomeLabel
84+ anchors.left: parent.left
85+ anchors.right: parent.right
86+ horizontalAlignment: Text.AlignHCenter
87+ wrapMode: Text.Wrap
88+ fontSize: "x-large"
89+ font.weight: Font.Light
90+ lineHeight: 1.2
91+ text: i18n.tr("Welcome to ") + System.version.split("Base-Version: ")[1]
92+ color: whiteColor
93+ }
94+
95+ Label {
96+ id: welcomeText
97+ anchors.left: parent.left
98+ anchors.right: parent.right
99+ anchors.top: welcomeLabel.bottom
100+ anchors.topMargin: units.gu(2)
101+ horizontalAlignment: Text.AlignHCenter
102+ wrapMode: Text.Wrap
103+ fontSize: "large"
104+ font.weight: Font.Light
105+ lineHeight: 1.2
106+ text: i18n.tr("We will make sure your device is ready to use ") + System.version.split("Base-Version: ")[1]
107+ color: whiteColor
108+ }
109+
110+ Rectangle {
111+ anchors {
112+ top: welcomeText.bottom
113+ horizontalCenter: parent.horizontalCenter
114+ topMargin: units.gu(4)
115+ }
116+ color: "transparent"
117+ border.width: units.dp(1)
118+ border.color: whiteColor
119+ radius: units.dp(4)
120+ width: buttonLabel.paintedWidth + units.gu(6)
121+ height: buttonLabel.paintedHeight + units.gu(1.8)
122+
123+ Label {
124+ id: buttonLabel
125+ color: whiteColor
126+ text: i18n.tr("Next")
127+ fontSize: "medium"
128+ anchors.centerIn: parent
129+ }
130+ AbstractButton {
131+ objectName: "nextButton"
132+ anchors.fill: parent
133+ onClicked: pageStack.next();
134+ }
135+ }
136+ }
137+}
qml/Wizard/Pages/10-welcome.qml+2
@@ -1,4 +1,5 @@
11/*
2+ * Copyright (C) 2018 The UBports project
23 * Copyright (C) 2013-2016 Canonical, Ltd.
34 *
45 * This program is free software; you can redistribute it and/or modify
@@ -27,6 +28,7 @@ LocalComponents.Page {
2728
2829 title: i18n.tr("Language")
2930 forwardButtonSourceComponent: forwardButton
31+ onlyOnInstall: true
3032
3133 UbuntuLanguagePlugin {
3234 id: plugin
qml/Wizard/Pages/11-changelog.qmlnew file+61
@@ -0,0 +1,61 @@
1+/*
2+ * Copyright (C) 2018 The UBports project
3+ *
4+ * Written by: Dalton Durst <dalton@ubports.com>
5+ * Marius Gripsgard <marius@ubports.com>
6+ *
7+ * This program is free software; you can redistribute it and/or modify
8+ * it under the terms of the GNU General Public License as published by
9+ * the Free Software Foundation; version 3.
10+ *
11+ * This program is distributed in the hope that it will be useful,
12+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+ * GNU General Public License for more details.
15+ *
16+ * You should have received a copy of the GNU General Public License
17+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
18+ */
19+
20+import QtQuick 2.4
21+import Ubuntu.Components 1.3
22+import AccountsService 0.1
23+import ".." as LocalComponents
24+
25+LocalComponents.Page {
26+ objectName: "changelogPage"
27+ title: i18n.tr("What's new")
28+
29+ forwardButtonSourceComponent: forwardButton
30+ onlyOnUpdate: true
31+
32+
33+ Column {
34+ id: column
35+ spacing: units.gu(2)
36+
37+ anchors {
38+ fill: content
39+ leftMargin: wideMode ? parent.leftMargin : staticMargin
40+ rightMargin: wideMode ? parent.rightMargin : staticMargin
41+ topMargin: staticMargin
42+ }
43+
44+ Label {
45+ text: "This is where cool stuff would go"
46+ }
47+ }
48+
49+ Component {
50+ id: forwardButton
51+ LocalComponents.StackButton {
52+ text: i18n.tr("Next")
53+ onClicked: {
54+ if (d.validName) {
55+ AccountsService.realName = d.validName;
56+ }
57+ pageStack.next();
58+ }
59+ }
60+ }
61+}
qml/Wizard/Pages/30-wifi.qml+1
@@ -32,6 +32,7 @@ LocalComponents.Page {
3232 forwardButtonSourceComponent: forwardButton
3333
3434 readonly property bool connected: Connectivity.online
35+ skip: connected
3536
3637 function getExtendedProperty(object, propertyName, defaultValue) {
3738 if (object && object.hasOwnProperty(propertyName)) {
qml/Wizard/Pages/40-location.qmldeleted−290
@@ -1,290 +0,0 @@
1−/*
2− * Copyright (C) 2013-2016 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−import QtQuick 2.4
18−import AccountsService 0.1
19−import QMenuModel 0.1 as QMenuModel
20−import Qt.labs.folderlistmodel 2.1
21−import Ubuntu.Components 1.3
22−import ".." as LocalComponents
23−
24−LocalComponents.Page {
25− objectName: "locationPage"
26−
27− title: i18n.tr("Location Services")
28− forwardButtonSourceComponent: forwardButton
29−
30− readonly property bool pathSet: AccountsService.hereLicensePathValid
31− skipValid: pathSet && (AccountsService.hereLicensePath === "" || termsModel.count > 0)
32− skip: skipValid && (AccountsService.hereLicensePath === "" || termsModel.count === 2) // no files but . and ..
33−
34− FolderListModel {
35− id: termsModel
36− folder: AccountsService.hereLicensePath
37− nameFilters: ["*.html"]
38− showOnlyReadable: true
39− showDotAndDotDot: true // so that count == 0 means we're not done scanning yet
40− }
41−
42− QMenuModel.QDBusActionGroup {
43− id: locationActionGroup
44− objectName: "locationActionGroup"
45− busType: QMenuModel.DBus.SessionBus
46− busName: "com.canonical.indicator.location"
47− objectPath: "/com/canonical/indicator/location"
48− property variant location: action("location-detection-enabled")
49− property variant gps: action("gps-detection-enabled")
50− Component.onCompleted: start()
51− }
52−
53− Item {
54− id: column
55− anchors.fill: content
56− anchors.topMargin: customMargin
57− anchors.leftMargin: wideMode ? parent.leftMargin : 0
58− anchors.rightMargin: wideMode ? parent.rightMargin : 0
59−
60− Item {
61− id: hereCheckGroup
62− anchors {
63− left: parent.left
64− right: parent.right
65− top: parent.top
66− }
67− height: hereCheckLabel.height + hereTermsLabel.height
68−
69− Label {
70− id: hereCheckLabel
71− objectName: "hereCheckLabel"
72− anchors {
73− left: parent.left
74− right: hereTermsCheck.left
75− top: parent.top
76− leftMargin: column.anchors.leftMargin == 0 ? staticMargin : 0
77− rightMargin: units.gu(2)
78− }
79− lineHeight: 1.2
80− wrapMode: Text.WordWrap
81− color: textColor
82− font.weight: checked ? Font.Normal : Font.Light
83− text: i18n.tr("Use GPS, Wi-Fi hotspots and mobile network anonymously to detect location (recommended)")
84− property bool checked: true
85− }
86−
87− Label {
88− id: hereTermsLabel
89− objectName: "hereTermsLabel"
90− anchors {
91− left: parent.left
92− right: hereTermsCheck.left
93− top: hereCheckLabel.bottom
94− topMargin: units.gu(1)
95− leftMargin: column.anchors.leftMargin == 0 ? staticMargin : 0
96− rightMargin: units.gu(2)
97− }
98−
99− wrapMode: Text.WordWrap
100− color: textColor
101− font.weight: Font.Light
102− fontSize: "small"
103− lineHeight: 1.2
104− linkColor: UbuntuColors.orange
105− text: i18n.tr("By selecting this option you agree to the Nokia HERE %1.")
106− .arg("<a href='#'>" + i18n.ctr("part of: Nokia HERE terms and conditions", "terms and conditions") + "</a>")
107− Mouse.forwardTo: hereCheckArea // clicking on the link also selects this group
108− Mouse.priority: Mouse.AfterItem
109− onLinkActivated: {
110− pageStack.load(Qt.resolvedUrl("here-terms.qml"));
111− }
112− }
113−
114− Image {
115− id: hereTermsCheck
116− fillMode: Image.PreserveAspectFit
117− height: units.gu(1.5)
118− source: "data/Tick@30.png"
119− opacity: hereCheckLabel.checked ? 1 : 0
120− anchors.right: parent.right
121− anchors.verticalCenter: hereCheckLabel.verticalCenter
122− anchors.rightMargin: column.anchors.rightMargin == 0 ? staticMargin : 0
123− }
124−
125− MouseArea {
126− id: hereCheckArea
127− anchors.fill: parent
128− z: hereCheckGroup.z - 1 // so that the link can be activated
129− onClicked: {
130− if (!hereCheckLabel.checked) {
131− hereCheckLabel.checked = true;
132− gpsCheckLabel.checked = false;
133− nopeCheckLabel.checked = false;
134− }
135− }
136− }
137− }
138−
139− Rectangle {
140− id: divider
141− anchors.left: parent.left
142− anchors.right: parent.right
143− anchors.top: hereCheckGroup.bottom
144− anchors.topMargin: units.gu(3)
145− height: units.dp(1)
146− color: dividerColor
147− }
148−
149− Label {
150− id: gpsCheckLabel
151− objectName: "gpsCheckLabel"
152− anchors {
153− left: parent.left
154− right: parent.right
155− top: divider.bottom
156− topMargin: units.gu(3)
157− leftMargin: column.anchors.leftMargin == 0 ? staticMargin : 0
158− rightMargin: units.gu(2)
159− }
160− text: i18n.tr("GPS only")
161− wrapMode: Text.WordWrap
162− color: textColor
163− font.weight: checked ? Font.Normal : Font.Light
164− width: content.width
165− property bool checked: false
166−
167− MouseArea {
168− anchors.fill: parent
169− onClicked: {
170− if (!gpsCheckLabel.checked) {
171− hereCheckLabel.checked = false;
172− gpsCheckLabel.checked = true;
173− nopeCheckLabel.checked = false;
174− }
175− }
176− }
177− }
178−
179− Image {
180− fillMode: Image.PreserveAspectFit
181− height: units.gu(1.5)
182− source: "data/Tick@30.png"
183− opacity: gpsCheckLabel.checked ? 1 : 0
184− anchors.right: parent.right
185− anchors.verticalCenter: gpsCheckLabel.verticalCenter
186− anchors.rightMargin: column.anchors.rightMargin == 0 ? staticMargin : 0
187− }
188−
189− Rectangle {
190− id: divider2
191− anchors.left: parent.left
192− anchors.right: parent.right
193− anchors.top: gpsCheckLabel.bottom
194− anchors.topMargin: units.gu(3)
195− height: units.dp(1)
196− color: dividerColor
197− }
198−
199− Label {
200− id: nopeCheckLabel
201− objectName: "nopeCheckLabel"
202− anchors {
203− left: parent.left
204− right: parent.right
205− top: divider2.bottom
206− topMargin: units.gu(3)
207− leftMargin: column.anchors.leftMargin == 0 ? staticMargin : 0
208− rightMargin: units.gu(2)
209− }
210− wrapMode: Text.WordWrap
211− color: textColor
212− font.weight: checked ? Font.Normal : Font.Light
213− width: content.width
214− text: i18n.tr("Don't use my location")
215− property bool checked: false
216−
217− MouseArea {
218− anchors.fill: parent
219− onClicked: {
220− if (!nopeCheckLabel.checked) {
221− hereCheckLabel.checked = false;
222− gpsCheckLabel.checked = false;
223− nopeCheckLabel.checked = true;
224− }
225− }
226− }
227− }
228−
229− Image {
230− fillMode: Image.PreserveAspectFit
231− height: units.gu(1.5)
232− source: "data/Tick@30.png"
233− opacity: nopeCheckLabel.checked ? 1 : 0
234− anchors.right: parent.right
235− anchors.verticalCenter: nopeCheckLabel.verticalCenter
236− anchors.rightMargin: column.anchors.rightMargin == 0 ? staticMargin : 0
237− }
238−
239− Rectangle {
240− id: divider3
241− anchors.left: parent.left
242− anchors.right: parent.right
243− anchors.top: nopeCheckLabel.bottom
244− anchors.topMargin: units.gu(3)
245− height: units.dp(1)
246− color: dividerColor
247− }
248−
249− Label {
250− id: infoLabel
251− anchors {
252− left: parent.left
253− right: parent.right
254− top: divider3.bottom
255− topMargin: units.gu(4)
256− leftMargin: column.anchors.leftMargin == 0 ? staticMargin : 0
257− rightMargin: column.anchors.rightMargin == 0 ? staticMargin : 0
258− }
259− wrapMode: Text.Wrap
260− text: i18n.tr("You can change it later in System Settings.")
261− color: textColor
262− fontSize: "small"
263− font.weight: Font.Light
264− width: content.width
265− }
266− }
267−
268− Component {
269− id: forwardButton
270− LocalComponents.StackButton {
271− text: i18n.tr("Next")
272− onClicked: {
273− var locationOn = gpsCheckLabel.checked || hereCheckLabel.checked;
274− var gpsOn = gpsCheckLabel.checked || hereCheckLabel.checked;
275− var hereOn = hereCheckLabel.checked;
276−
277− // location service doesn't currently listen to updateState
278− // requests, so we activate the actions if needed.
279− if (locationActionGroup.location.state != locationOn) {
280− locationActionGroup.location.activate();
281− }
282− if (locationActionGroup.gps.state != gpsOn) {
283− locationActionGroup.gps.activate();
284− }
285− AccountsService.hereEnabled = hereOn;
286− pageStack.next();
287− }
288− }
289− }
290−}
qml/Wizard/Pages/50-timezone.qml+1
@@ -36,6 +36,7 @@ LocalComponents.Page {
3636
3737 // for testing
3838 readonly property alias tdModule: timeDatePanel
39+ onlyOnInstall: true
3940
4041 function highlightTimezone(offset) {
4142 highlightImage.source = "data/timezonemap/timezone_" + offset + ".png";
qml/Wizard/Pages/60-account.qml+1
@@ -24,6 +24,7 @@ LocalComponents.Page {
2424 title: i18n.tr("Personalize Your Device")
2525
2626 forwardButtonSourceComponent: forwardButton
27+ onlyOnInstall: true
2728
2829 QtObject {
2930 id: d
qml/Wizard/Pages/70-passwd-type.qml+1
@@ -44,6 +44,7 @@ LocalComponents.Page {
4444 // or this isn't the first time the wizard has been run, etc). We can't
4545 // properly set the password again, so let's not pretend we can.
4646 skip: securityPrivacy.securityType !== UbuntuSecurityPrivacyPanel.Swipe
47+ onlyOnInstall: true
4748
4849 function indexToMethod(index) {
4950 if (index === 0/* || index === 1*/)
qml/Wizard/Pages/75-report-check.qml+1
@@ -27,6 +27,7 @@ LocalComponents.Page {
2727 forwardButtonSourceComponent: !webview.visible ? forwardButton : null
2828 customBack: true
2929 customTitle: webview.visible
30+ onlyOnInstall: true
3031
3132 skip: !diagnostics.reportCrashes // skip the page when the system is configured not to report crashes
3233
qml/Wizard/Pages/76-app-update.qmlnew file+235
@@ -0,0 +1,235 @@
1+/*
2+ * Copyright (C) 2018 The UBports project
3+ *
4+ * Written by: Dalton Durst <dalton@ubports.com>
5+ * Marius Gripsgard <marius@ubports.com>
6+ *
7+ * This program is free software: you can redistribute it and/or modify it
8+ * under the terms of the GNU General Public License version 3, as published
9+ * by the Free Software Foundation.
10+ *
11+ * This program is distributed in the hope that it will be useful, but
12+ * WITHOUT ANY WARRANTY; without even the implied warranties of
13+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
14+ * PURPOSE. See the GNU General Public License for more details.
15+ *
16+ * You should have received a copy of the GNU General Public License along
17+ * with this program. If not, see <http://www.gnu.org/licenses/>.
18+ */
19+
20+import QMenuModel 0.1
21+import QtQuick 2.4
22+import QtQuick.Layouts 1.1
23+import Ubuntu.Components 1.3
24+import Ubuntu.Components.ListItems 1.3 as ListItem
25+import Ubuntu.Components.Popups 1.3
26+import Ubuntu.SystemSettings.Update 1.0
27+import Ubuntu.Connectivity 1.0
28+import Wizard 0.1
29+import ".." as LocalComponents
30+
31+LocalComponents.Page {
32+ id: appUpdatePage
33+ objectName: "appUpdatePage"
34+
35+ title: i18n.tr("Update Apps")
36+ forwardButtonSourceComponent: forwardButton
37+
38+ property bool batchMode: false
39+ property bool online: NetworkingStatus.online
40+ property bool authenticated: UpdateManager.authenticated
41+
42+ onlyOnUpdate: true
43+
44+ property int updatesCount: {
45+ var count = 0;
46+ if (authenticated) {
47+ count += clickRepeater.count;
48+ }
49+ return count;
50+ }
51+
52+ function check(force) {
53+ UpdateManager.check(UpdateManager.CheckClickIgnoreVersion);
54+ }
55+
56+ DownloadHandler {
57+ id: downloadHandler
58+ updateModel: UpdateManager.model
59+ }
60+
61+ Flickable {
62+ id: scrollWidget
63+ anchors {
64+ fill: content
65+ leftMargin: parent.leftMargin
66+ rightMargin: parent.rightMargin
67+ }
68+ clip: true
69+ contentHeight: scrollWidgetContent.height
70+ boundsBehavior: (contentHeight > scrollWidgetContent.height) ?
71+ Flickable.DragAndOvershootBounds :
72+ Flickable.StopAtBounds
73+ flickableDirection: Flickable.VerticalFlick
74+
75+ Column {
76+ id: scrollWidgetContent
77+ anchors {
78+ left: parent.left
79+ right: parent.right
80+ }
81+
82+ GlobalUpdateControls {
83+ id: g
84+ objectName: "global"
85+ anchors { left: parent.left; right: parent.right }
86+
87+ height: hidden ? 0 : units.gu(8)
88+ clip: true
89+ status: UpdateManager.status
90+ batchMode: appUpdatePage.batchMode
91+ updatesCount: appUpdatePage.updatesCount
92+ online: appUpdatePage.online
93+ onStop: UpdateManager.cancel()
94+
95+ onRequestInstall: {
96+ install();
97+ }
98+ onInstall: {
99+ appUpdatePage.batchMode = true
100+ postClickBatchHandler.target = appUpdatePage;
101+ }
102+ }
103+
104+ Rectangle {
105+ id: overlay
106+ objectName: "overlay"
107+ anchors {
108+ left: parent.left
109+ leftMargin: units.gu(2)
110+ right: parent.right
111+ rightMargin: units.gu(2)
112+ }
113+ visible: placeholder.text
114+ color: theme.palette.normal.background
115+ height: units.gu(10)
116+
117+ Label {
118+ id: placeholder
119+ objectName: "overlayText"
120+ anchors.fill: parent
121+ verticalAlignment: Text.AlignVCenter
122+ horizontalAlignment: Text.AlignHCenter
123+ wrapMode: Text.WordWrap
124+ text: {
125+ var s = UpdateManager.status;
126+ if (!appUpdatePage.online) {
127+ return i18n.tr("Connect to the Internet to check for updates.");
128+ } else if (s === UpdateManager.StatusIdle && updatesCount === 0) {
129+ return i18n.tr("Software is up to date");
130+ } else if (s === UpdateManager.StatusServerError ||
131+ s === UpdateManager.StatusNetworkError) {
132+ return i18n.tr("The update server is not responding. Try again later.");
133+ }
134+ return "";
135+ }
136+ }
137+ }
138+
139+ Column {
140+ id: clickUpdatesCol
141+ objectName: "clickUpdates"
142+ anchors { left: parent.left; right: parent.right }
143+ visible: {
144+ var s = UpdateManager.status;
145+ var haveUpdates = clickRepeater.count > 0;
146+ switch (s) {
147+ case UpdateManager.StatusCheckingImageUpdates:
148+ case UpdateManager.StatusIdle:
149+ return haveUpdates && online && authenticated;
150+ }
151+ return false;
152+ }
153+
154+ Repeater {
155+ id: clickRepeater
156+ model: UpdateManager.clickUpdates
157+
158+ delegate: ClickUpdateDelegate {
159+ objectName: "clickUpdatesDelegate" + index
160+ width: clickUpdatesCol.width
161+ updateState: model.updateState
162+ progress: model.progress
163+ version: remoteVersion
164+ size: model.size
165+ name: title
166+ iconUrl: model.iconUrl
167+ kind: model.kind
168+ error: model.error
169+ signedUrl: signedDownloadUrl
170+
171+ onInstall: downloadHandler.createDownload(model);
172+ onPause: downloadHandler.pauseDownload(model)
173+ onResume: downloadHandler.resumeDownload(model)
174+ onRetry: {
175+ /* This creates a new signed URL with which we can
176+ retry the download. See onSignedUrlChanged. */
177+ UpdateManager.retry(model.identifier,
178+ model.revision);
179+ }
180+
181+ onSignedUrlChanged: {
182+ // If we have a signedUrl, user intend to retry.
183+ if (signedUrl) {
184+ downloadHandler.retryDownload(model);
185+ }
186+ }
187+
188+ Connections {
189+ target: g
190+ onInstall: install()
191+ }
192+
193+ /* If we a downloadId, we expect UDM to restore it
194+ after some time. Workaround for lp:1603770. */
195+ Timer {
196+ id: downloadTimeout
197+ interval: 30000
198+ running: true
199+ onTriggered: {
200+ var s = updateState;
201+ if (model.downloadId
202+ || s === Update.StateQueuedForDownload
203+ || s === Update.StateDownloading) {
204+ downloadHandler.assertDownloadExist(model);
205+ }
206+ }
207+ }
208+ }
209+ }
210+ }
211+ } // Column inside flickable
212+ } // Flickable
213+
214+ Connections {
215+ id: postClickBatchHandler
216+ ignoreUnknownSignals: true
217+ target: null
218+ onUpdatesCountChanged: {
219+ if (target.updatesCount === 0) {
220+ appUpdatePage.batchMode = false;
221+ target = null;
222+ }
223+ }
224+ }
225+
226+ Component.onCompleted: check()
227+
228+ Component {
229+ id: forwardButton
230+ LocalComponents.StackButton {
231+ text: (UpdateManager.status === UpdateManager.StatusIdle && updatesCount === 0) ? i18n.tr("Next") : i18n.tr("Skip")
232+ onClicked: pageStack.next()
233+ }
234+ }
235+}
qml/Wizard/Pages/78-firmware-update.qmlnew file+233
@@ -0,0 +1,233 @@
1+/*
2+ * Copyright (C) 2018 The UBports project
3+ *
4+ * Written by: Marius Gripsgard <marius@ubports.com>
5+ *
6+ * This program is free software; you can redistribute it and/or modify
7+ * it under the terms of the GNU General Public License as published by
8+ * the Free Software Foundation; version 3.
9+ *
10+ * This program is distributed in the hope that it will be useful,
11+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+ * GNU General Public License for more details.
14+ *
15+ * You should have received a copy of the GNU General Public License
16+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
17+ */
18+
19+import QtQuick 2.4
20+import QtQuick.Layouts 1.1
21+import Ubuntu.Components 1.3
22+import Ubuntu.SystemSettings.Update 1.0
23+import Ubuntu.Connectivity 1.0
24+import Wizard 0.1
25+import ".." as LocalComponents
26+
27+LocalComponents.Page {
28+ id: systemUpdatePage
29+ objectName: "firmwareUpdatePage"
30+
31+ title: i18n.tr("Firmware Update")
32+ forwardButtonSourceComponent: forwardButton
33+
34+ skip: !SystemImage.supportsFirmwareUpdate() || !online
35+
36+ property bool online: NetworkingStatus.online
37+ property bool hasUpdate: false
38+ property bool isUpdating: false
39+ property bool isChecking: true
40+ property var partitions: ""
41+
42+ function check() {
43+ if (!SystemImage.supportsFirmwareUpdate())
44+ return pageStack.next();
45+ systemUpdatePage.isChecking = true
46+ SystemImage.checkForFirmwareUpdate()
47+ }
48+
49+ function flash() {
50+ if (!SystemImage.supportsFirmwareUpdate())
51+ return pageStack.next();
52+ systemUpdatePage.isUpdating = true
53+ SystemImage.updateFirmware()
54+ }
55+
56+ Connections {
57+ target: SystemImage
58+ onCheckForFirmwareUpdateDone: {
59+ var updateobj = JSON.parse(updateObj);
60+ if (Array.isArray(updateobj) && updateobj.length > 0) {
61+ for (var u in updateobj) {
62+ console.log(u)
63+ if (systemUpdatePage.partitions === "")
64+ systemUpdatePage.partitions += updateobj[u].file
65+ else
66+ systemUpdatePage.partitions += ", " + updateobj[u].file
67+ }
68+ systemUpdatePage.hasUpdate = true;
69+ }
70+ console.log(updateobj);
71+ systemUpdatePage.isChecking = false;
72+ }
73+ onUpdateFirmwareDone: {
74+ var updateobj = JSON.parse(updateObj);
75+ if (Array.isArray(updateobj) && updateobj.length === 0) {
76+ // This means success!
77+ systemUpdatePage.hasUpdate = false;
78+ systemUpdatePage.partitions = "";
79+ System.skipUntilFinishedPage();
80+ SystemImage.reboot();
81+ return;
82+ }
83+ console.log(updateobj);
84+ systemUpdatePage.isUpdating = false;
85+ }
86+ }
87+
88+ Column {
89+ id: column
90+ anchors {
91+ fill: content
92+ leftMargin: systemUpdatePage.leftMargin
93+ rightMargin: systemUpdatePage.rightMargin
94+ topMargin: systemUpdatePage.customMargin
95+ }
96+ spacing: units.gu(3)
97+ opacity: spinner.visible ? 0.5 : 1
98+ Behavior on opacity {
99+ UbuntuNumberAnimation {}
100+ }
101+
102+ Label {
103+ anchors.horizontalCenter: parent.horizontalCenter
104+ font.weight: Font.Light
105+ wrapMode: Text.Wrap
106+ textSize: Label.Medium
107+ text: systemUpdatePage.hasUpdate ? i18n.tr("There is a firmware update available!")
108+ : i18n.tr("Firmware is up to date!")
109+
110+ }
111+
112+ GridLayout {
113+ rows: 3
114+ columns: 2
115+ rowSpacing: units.gu(1)
116+ columnSpacing: units.gu(2)
117+ anchors.horizontalCenter: parent.horizontalCenter
118+ visible: hasUpdate
119+
120+ Icon {
121+ Layout.rowSpan: 3
122+ Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter
123+ width: units.gu(5)
124+ height: width
125+ name: "security-alert"
126+ }
127+
128+ Label {
129+ font.weight: Font.Normal
130+ textSize: Label.Medium
131+ text: i18n.tr("Firmware Update")
132+ }
133+
134+ Label {
135+ font.weight: Font.Light
136+ fontSize: "small"
137+ text: systemUpdatePage.partitions
138+ }
139+
140+ Label {
141+ font.weight: Font.Light
142+ fontSize: "small"
143+ text: i18n.tr("The device will automatically restart after installing is done.")
144+ }
145+ }
146+
147+ Rectangle {
148+ anchors.left: parent.left
149+ anchors.leftMargin: 3
150+ anchors.horizontalCenter: parent.horizontalCenter
151+ color: theme.palette.normal.foreground
152+ radius: units.dp(4)
153+ width: buttonLabel.paintedWidth + units.gu(3)
154+ height: buttonLabel.paintedHeight + units.gu(1.8)
155+ visible: hasUpdate
156+
157+ Label {
158+ id: buttonLabel
159+ text: i18n.tr("Install and restart now")
160+ font.weight: Font.Light
161+ anchors.horizontalCenter: parent.horizontalCenter
162+ anchors.centerIn: parent
163+ }
164+
165+ AbstractButton {
166+ id: button
167+ objectName: "installButton"
168+ anchors.fill: parent
169+ anchors.horizontalCenter: parent.horizontalCenter
170+ onClicked: {
171+ systemUpdatePage.flash()
172+ }
173+ }
174+
175+ transformOrigin: Item.Top
176+ scale: button.pressed ? 0.98 : 1.0
177+ Behavior on scale {
178+ ScaleAnimator {
179+ duration: UbuntuAnimation.SnapDuration
180+ easing.type: Easing.Linear
181+ }
182+ }
183+ }
184+ }
185+
186+ Column {
187+ id: spinner
188+ anchors.centerIn: systemUpdatePage
189+ visible: systemUpdatePage.isChecking || systemUpdatePage.isUpdating
190+ spacing: units.gu(1)
191+
192+ ActivityIndicator {
193+ anchors.horizontalCenter: parent.horizontalCenter
194+ running: parent.visible
195+ }
196+
197+ Label {
198+ wrapMode: Text.Wrap
199+ width: systemUpdatePage.width - units.gu(3)
200+ fontSize: "small"
201+ text: i18n.tr("Downloading and Flashing firmware updates, this could take a few minutes...")
202+ visible: systemUpdatePage.isUpdating
203+ }
204+
205+ Label {
206+ wrapMode: Text.Wrap
207+ fontSize: "small"
208+ text: i18n.tr("Checking for firmware update")
209+ visible: systemUpdatePage.isChecking
210+ }
211+
212+ Component.onCompleted: systemUpdatePage.check()
213+
214+ }
215+
216+ Connections {
217+ target: NetworkingStatus
218+ onOnlineChanged: {
219+ if (online) {
220+ systemUpdatePage.check()
221+ }
222+ }
223+ }
224+
225+ Component {
226+ id: forwardButton
227+ LocalComponents.StackButton {
228+ text: !systemUpdatePage.hasUpdate && !systemUpdatePage.spinner
229+ ? i18n.tr("Next") : i18n.tr("Skip")
230+ onClicked: pageStack.next()
231+ }
232+ }
233+}
qml/Wizard/Pages/77-system-update.qml → qml/Wizard/Pages/79-system-update.qmlrenamed

The content is the same.

qml/Wizard/Pages/80-finished.qml+4−2
@@ -1,4 +1,5 @@
11/*
2+ * Copyright (C) 2018 The UBports project
23 * Copyright (C) 2013-2016 Canonical, Ltd.
34 *
45 * This program is free software; you can redistribute it and/or modify
@@ -16,6 +17,7 @@
1617
1718import QtQuick 2.4
1819import Ubuntu.Components 1.3
20+import Wizard 0.1
1921import ".." as LocalComponents
2022
2123LocalComponents.Page {
@@ -86,7 +88,7 @@ LocalComponents.Page {
8688 fontSize: "x-large"
8789 font.weight: Font.Light
8890 lineHeight: 1.2
89− text: i18n.tr("Welcome to Ubuntu")
91+ text: (System.isUpdate) ? i18n.tr("Welcome Back") : i18n.tr("Welcome to Ubuntu")
9092 color: whiteColor
9193 }
9294
@@ -121,7 +123,7 @@ LocalComponents.Page {
121123 Label {
122124 id: buttonLabel
123125 color: whiteColor
124− text: i18n.tr("Get Started")
126+ text: (System.isUpdate) ? i18n.tr("Continue") : i18n.tr("Get Started")
125127 fontSize: "medium"
126128 anchors.centerIn: parent
127129 }
qml/Wizard/Pages/ClickUpdateDelegate.qmlnew file+26
@@ -0,0 +1,26 @@
1+/*
2+ * This file is part of system-settings
3+ *
4+ * Copyright (C) 2016 Canonical Ltd.
5+ *
6+ * This program is free software: you can redistribute it and/or modify it
7+ * under the terms of the GNU General Public License version 3, as published
8+ * by the Free Software Foundation.
9+ *
10+ * This program is distributed in the hope that it will be useful, but
11+ * WITHOUT ANY WARRANTY; without even the implied warranties of
12+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
13+ * PURPOSE. See the GNU General Public License for more details.
14+ *
15+ * You should have received a copy of the GNU General Public License along
16+ * with this program. If not, see <http://www.gnu.org/licenses/>.
17+ */
18+
19+import QtQuick 2.4
20+import Ubuntu.SystemSettings.Update 1.0
21+
22+UpdateDelegate {
23+ id: update
24+
25+ property string signedUrl
26+}
qml/Wizard/Pages/DownloadHandler.qmlnew file+204
@@ -0,0 +1,204 @@
1+/*
2+ * This file is part of system-settings
3+ *
4+ * Copyright (C) 2016 Canonical Ltd.
5+ *
6+ * This program is free software: you can redistribute it and/or modify it
7+ * under the terms of the GNU General Public License version 3, as published
8+ * by the Free Software Foundation.
9+ *
10+ * This program is distributed in the hope that it will be useful, but
11+ * WITHOUT ANY WARRANTY; without even the implied warranties of
12+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
13+ * PURPOSE. See the GNU General Public License for more details.
14+ *
15+ * You should have received a copy of the GNU General Public License along
16+ * with this program. If not, see <http://www.gnu.org/licenses/>.
17+ *
18+ */
19+import QtQuick 2.4
20+import Ubuntu.DownloadManager 1.2
21+
22+Item {
23+ id: downloadHandler
24+ property var updateModel
25+ property alias downloads: downloadManager.downloads
26+ property var udm: DownloadManager {
27+ id: downloadManager
28+ onDownloadFinished: {
29+ updateModel.setInstalled(download.metadata.custom.identifier,
30+ download.metadata.custom.revision);
31+ }
32+ onDownloadPaused: {
33+ updateModel.pauseUpdate(download.metadata.custom.identifier,
34+ download.metadata.custom.revision)
35+ }
36+ onDownloadResumed: {
37+ updateModel.resumeUpdate(download.metadata.custom.identifier,
38+ download.metadata.custom.revision)
39+ }
40+ onDownloadCanceled: {
41+ updateModel.cancelUpdate(download.metadata.custom.identifier,
42+ download.metadata.custom.revision)
43+ }
44+ onErrorFound: {
45+ updateModel.setError(download.metadata.custom.identifier,
46+ download.metadata.custom.revision,
47+ download.errorMessage)
48+ }
49+ onDownloadsChanged: restoreDownloads()
50+ Component.onCompleted: restoreDownloads()
51+ }
52+
53+ function downloadAll() {
54+
55+ }
56+
57+ function restoreDownloads() {
58+ var dl;
59+ for (var i = 0; i<downloads.length; i++) {
60+ dl = downloads[i];
61+ if (!dl._bound) {
62+ /* We only bind those signals here, that the UDM does not
63+ receive, i.e. processing and progressChanged. */
64+ dl.progressChanged.connect(onDownloadProgress.bind(dl));
65+ dl.processing.connect(onDownloadProcessing.bind(dl));
66+ dl._bound = true;
67+ }
68+ }
69+ }
70+
71+ function resumeDownload(click) {
72+ var download = getDownloadFor(click);
73+ if (download && !download.downloading && !download.isCompleted) {
74+ download.resume();
75+ }
76+ }
77+
78+ function pauseDownload(click) {
79+ var download = getDownloadFor(click);
80+ if (download && download.downloading) {
81+ download.pause();
82+ }
83+ }
84+
85+ // Return download for a click update.
86+ function getDownloadFor(click) {
87+ var cust;
88+ var dl;
89+
90+ for (var i = 0; i<downloads.length; i++) {
91+ dl = downloads[i];
92+ if (dl.errorMessage || dl.isCompleted) {
93+ // Ignore failed and completed downloads.
94+ continue;
95+ }
96+
97+ cust = downloads[i].metadata.custom;
98+ if (cust.identifier === click.identifier && cust.revision === click.revision) {
99+ return downloads[i];
100+ }
101+ }
102+ return null;
103+ }
104+
105+ function hasExistingDownload(click) {
106+ var existingDownload = getDownloadFor(click);
107+ return (existingDownload !== null &&
108+ !existingDownload.errorMessage &&
109+ !existingDownload.isCompleted);
110+ }
111+
112+ function retryDownload(click) {
113+ return createDownload(click, true);
114+ }
115+
116+ function createDownload(click, useSignedUrl) {
117+ if (hasExistingDownload(click)) {
118+ return null;
119+ }
120+ var downloadUrl = click.downloadUrl;
121+ var metadata = {
122+ "command": click.command,
123+ "title": click.title,
124+ "showInIndicator": false
125+ };
126+ var metadataObj = mdt.createObject(root, metadata);
127+ metadataObj.custom = {
128+ "identifier": click.identifier,
129+ "package-name": click.identifier,
130+ "revision": click.revision,
131+ };
132+
133+ var hdrs = {}
134+ if (useSignedUrl) {
135+ if (!click.signedDownloadUrl) {
136+ console.warn('The signed download URL was empty.');
137+ }
138+ downloadUrl = click.signedDownloadUrl;
139+ } else {
140+ // If we're using an unsigned URL, we need to provide this header.
141+ hdrs["X-Click-Token"] = click.token;
142+ }
143+
144+ var singleDownloadObj = sdl.createObject(root, {
145+ "autoStart": true,
146+ "hash": click.downloadHash,
147+ "algorithm": "sha512",
148+ "headers": hdrs,
149+ "metadata": metadataObj,
150+ "revision": click.revision,
151+ "identifier": click.identifier
152+ });
153+ singleDownloadObj.download(downloadUrl);
154+ return singleDownloadObj;
155+ }
156+
157+ function onDownloadProgress(progress) {
158+ updateModel.setProgress(this.metadata.custom.identifier,
159+ this.metadata.custom.revision,
160+ this.progress);
161+ }
162+
163+ function onDownloadProcessing() {
164+ updateModel.processUpdate(this.metadata.custom.identifier,
165+ this.metadata.custom.revision);
166+ }
167+
168+ /* If a update's model has a downloadId, check if UDM knows it. If not,
169+ treat this as a failure. Workaround for lp:1603770. */
170+ function assertDownloadExist(click) {
171+ if (!getDownloadFor(click)) {
172+ updateModel.setError(
173+ click.identifier, click.revision,
174+ i18n.tr("Installation failed")
175+ );
176+ }
177+ }
178+
179+ Component {
180+ id: sdl
181+ SingleDownload {
182+ id: download
183+ objectName: "singleDownload"
184+ property bool _bound: true
185+
186+ onDownloadIdChanged: {
187+ updateModel.queueUpdate(metadata.custom.identifier,
188+ metadata.custom.revision,
189+ downloadId);
190+ }
191+ onStarted: {
192+ updateModel.startUpdate(metadata.custom.identifier,
193+ metadata.custom.revision);
194+ }
195+ onProgressChanged: onDownloadProgress.call(download)
196+ onProcessing: onDownloadProcessing.call(download)
197+ }
198+ }
199+
200+ Component {
201+ id: mdt
202+ Metadata {}
203+ }
204+}
qml/Wizard/Pages/GlobalUpdateControls.qmlnew file+145
@@ -0,0 +1,145 @@
1+/*
2+ * This file is part of system-settings
3+ *
4+ * Copyright (C) 2016 Canonical Ltd.
5+ *
6+ * This program is free software: you can redistribute it and/or modify it
7+ * under the terms of the GNU General Public License version 3, as published
8+ * by the Free Software Foundation.
9+ *
10+ * This program is distributed in the hope that it will be useful, but
11+ * WITHOUT ANY WARRANTY; without even the implied warranties of
12+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
13+ * PURPOSE. See the GNU General Public License for more details.
14+ *
15+ * You should have received a copy of the GNU General Public License along
16+ * with this program. If not, see <http://www.gnu.org/licenses/>.
17+ */
18+
19+import QtQuick 2.4
20+import QtQuick.Layouts 1.1
21+import Ubuntu.Components 1.3
22+import Ubuntu.Components.ListItems 1.3 as ListItems
23+import Ubuntu.SystemSettings.Update 1.0
24+
25+Item {
26+ id: g
27+
28+ property bool batchMode
29+ property int status // A UpdateManager::Status
30+ property bool requireRestart: false
31+ property int updatesCount: 0
32+ property bool online: false
33+
34+ property bool hidden: {
35+ switch (status) {
36+ case UpdateManager.StatusNetworkError:
37+ case UpdateManager.StatusServerError:
38+ return true;
39+ }
40+ return !online ||
41+ (updatesCount <= 1 && status === UpdateManager.StatusIdle) ||
42+ batchMode
43+ }
44+
45+ signal stop()
46+ signal requestInstall()
47+ signal install()
48+
49+ Behavior on height {
50+ UbuntuNumberAnimation {}
51+ }
52+
53+ RowLayout {
54+ id: checking
55+ spacing: units.gu(2)
56+ anchors {
57+ fill: parent
58+ margins: units.gu(2)
59+ }
60+
61+ Behavior on opacity {
62+ UbuntuNumberAnimation {}
63+ }
64+
65+ opacity: visible ? 1 : 0
66+ visible: {
67+ switch (g.status) {
68+ case UpdateManager.StatusCheckingClickUpdates:
69+ case UpdateManager.StatusCheckingImageUpdates:
70+ case UpdateManager.StatusCheckingAllUpdates:
71+ return true;
72+ }
73+ return false;
74+ }
75+
76+ ActivityIndicator {
77+ running: parent.visible
78+ }
79+
80+ Label {
81+ objectName: "checkLabel"
82+ Layout.fillWidth: true
83+ elide: Text.ElideRight
84+ text: i18n.tr("Checking for updates…")
85+ }
86+
87+ Button {
88+ objectName: "updatesGlobalStopButton"
89+ text: i18n.tr("Stop")
90+ onClicked: g.stop()
91+ Layout.alignment: Qt.AlignRight | Qt.AlignVCenter
92+ }
93+ }
94+
95+ RowLayout {
96+ id: install
97+ anchors {
98+ fill: parent
99+ margins: units.gu(2)
100+ }
101+ spacing: units.gu(2)
102+
103+ Behavior on opacity {
104+ UbuntuNumberAnimation {}
105+ }
106+
107+ opacity: visible ? 1 : 0
108+ visible: {
109+ var canInstall = g.status === UpdateManager.StatusIdle;
110+ return canInstall && updatesCount > 1;
111+ }
112+
113+ Label {
114+ objectName: "updatesGlobalInfoLabel"
115+ // // TRANSLATORS: %1 is number of software updates available.
116+ text: i18n.tr("%1 update available",
117+ "%1 updates available",
118+ updatesCount).arg(updatesCount)
119+ Layout.fillWidth: true
120+ }
121+
122+ Button {
123+ objectName: "updatesGlobalInstallButton"
124+ text: {
125+ if (g.requireRestart === true) {
126+ return i18n.tr("Update all…");
127+ } else {
128+ return i18n.tr("Update all");
129+ }
130+ }
131+ onClicked: g.requestInstall()
132+ color: theme.palette.normal.positive
133+ strokeColor: "transparent"
134+ }
135+ }
136+
137+ ListItems.ThinDivider {
138+ visible: !g.hidden
139+ anchors {
140+ left: parent.left
141+ right: parent.right
142+ bottom: parent.bottom
143+ }
144+ }
145+}
qml/Wizard/Pages/UpdateDelegate.qmlnew file+389
@@ -0,0 +1,389 @@
1+/*
2+ * This file is part of system-settings
3+ *
4+ * Copyright (C) 2016 Canonical Ltd.
5+ *
6+ * Contact: Jonas G. Drange <jonas.drange@canonical.com>
7+ *
8+ * This program is free software: you can redistribute it and/or modify it
9+ * under the terms of the GNU General Public License version 3, as published
10+ * by the Free Software Foundation.
11+ *
12+ * This program is distributed in the hope that it will be useful, but
13+ * WITHOUT ANY WARRANTY; without even the implied warranties of
14+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
15+ * PURPOSE. See the GNU General Public License for more details.
16+ *
17+ * You should have received a copy of the GNU General Public License along
18+ * with this program. If not, see <http://www.gnu.org/licenses/>.
19+ *
20+ */
21+
22+import QtQuick 2.4
23+import QtQuick.Layouts 1.1
24+import Ubuntu.Components 1.3
25+import Ubuntu.Components.ListItems 1.3 as ListItems
26+import Ubuntu.Components.Themes 1.3
27+import Ubuntu.SystemSettings.Update 1.0
28+
29+ListItem {
30+ id: update
31+
32+ property int updateState // This is an Update::State
33+ property int kind // This is an Update::Kind
34+ property real size
35+ property string version
36+ property string downloadId
37+ property date updatedAt
38+ property bool launchable: false
39+
40+ property alias name: nameLabel.text
41+ property alias error: errorElementDetail.text
42+ property alias iconUrl: icon.source
43+ property alias progress: progressBar.value
44+
45+ signal retry()
46+ signal download()
47+ signal pause()
48+ signal resume()
49+ signal install()
50+ signal launch()
51+
52+ height: layout.height + (divider.visible ? divider.height : 0)
53+ Behavior on height {
54+ animation: UbuntuNumberAnimation {}
55+ }
56+
57+ SlotsLayout {
58+ id: layout
59+ mainSlot: ColumnLayout {
60+ spacing: units.gu(1)
61+ // Width the parent, minus the icon and some padding
62+ width: parent.width - (icon.width + (layout.padding.top * 3))
63+
64+ RowLayout {
65+ spacing: units.gu(2)
66+
67+ Label {
68+ id: nameLabel
69+ verticalAlignment: Text.AlignVCenter
70+ elide: Text.ElideMiddle
71+ Layout.fillWidth: true
72+ Layout.fillHeight: true
73+ }
74+
75+ Button {
76+ id: button
77+ objectName: "updateButton"
78+ Layout.alignment: Qt.AlignRight | Qt.AlignVCenter
79+ visible: {
80+ switch (updateState) {
81+ case Update.StateInstalled:
82+ return launchable;
83+ default:
84+ return true;
85+ }
86+ }
87+ enabled: {
88+ switch(updateState) {
89+ case Update.StateAvailable:
90+ case Update.StateDownloading:
91+ case Update.StateDownloadingAutomatically:
92+ case Update.StateDownloadPaused:
93+ case Update.StateAutomaticDownloadPaused:
94+ case Update.StateInstallPaused:
95+ case Update.StateDownloaded:
96+ case Update.StateFailed:
97+ return true;
98+
99+ // Enabled if installed and a click app (can launch).
100+ case Update.StateInstalled:
101+ return kind === Update.KindClick;
102+
103+ case Update.StateInstalling:
104+ case Update.StateInstallingAutomatically:
105+ case Update.StateUnavailable:
106+ case Update.StateInstallFinished:
107+ case Update.StateQueuedForDownload:
108+ case Update.StateUnknown:
109+ default:
110+ return false;
111+ }
112+ }
113+ text: {
114+ switch(updateState) {
115+ case Update.StateUnknown:
116+ case Update.StateUnavailable:
117+ case Update.StateFailed:
118+ return i18n.tr("Retry");
119+
120+ case Update.StateAvailable:
121+ case Update.StateQueuedForDownload:
122+ if (update.kind === Update.KindClick) {
123+ return i18n.tr("Update");
124+ } else {
125+ return i18n.tr("Download");
126+ }
127+
128+ case Update.StateDownloadPaused:
129+ case Update.StateAutomaticDownloadPaused:
130+ case Update.StateInstallPaused:
131+ return i18n.tr("Resume");
132+
133+ case Update.StateDownloading:
134+ case Update.StateDownloadingAutomatically:
135+ case Update.StateInstalling:
136+ case Update.StateInstallingAutomatically:
137+ case Update.StateInstallFinished:
138+ return i18n.tr("Pause");
139+
140+ case Update.StateDownloaded:
141+ if (kind === Update.KindImage) {
142+ return i18n.tr("Install…");
143+ } else {
144+ return i18n.tr("Install");
145+ }
146+
147+ case Update.StateInstalled:
148+ return i18n.tr("Open");
149+
150+ default:
151+ console.error("Unknown update state", updateState);
152+ }
153+ }
154+
155+ onClicked: {
156+ switch (updateState) {
157+
158+ // Retries.
159+ case Update.StateUnknown:
160+ case Update.StateUnavailable:
161+ case Update.StateFailed:
162+ update.retry();
163+ break;
164+
165+ case Update.StateDownloadPaused:
166+ case Update.StateAutomaticDownloadPaused:
167+ case Update.StateInstallPaused:
168+ update.resume();
169+ break;
170+
171+ case Update.StateAvailable:
172+ if (kind === Update.KindClick) {
173+ update.install();
174+ } else {
175+ update.download();
176+ }
177+ break;
178+
179+ case Update.StateDownloaded:
180+ update.install();
181+ break;
182+
183+ case Update.StateDownloading:
184+ case Update.StateDownloadingAutomatically:
185+ case Update.StateInstalling:
186+ case Update.StateInstallingAutomatically:
187+ update.pause();
188+ break;
189+
190+ case Update.StateInstalled:
191+ update.launch();
192+ break;
193+ }
194+ }
195+ } // Button
196+ } // Name/button RowLayout
197+
198+ RowLayout {
199+ spacing: units.gu(2)
200+
201+ Label {
202+ id: downloadLabel
203+ objectName: "updateDownloadLabel"
204+
205+ Layout.alignment: Qt.AlignRight | Qt.AlignVCenter
206+
207+ visible: text !== ""
208+
209+ fontSize: "small"
210+ text: {
211+ switch (updateState) {
212+
213+ case Update.StateInstalling:
214+ case Update.StateInstallingAutomatically:
215+ case Update.StateInstallPaused:
216+ return i18n.tr("Installing");
217+
218+ case Update.StateInstallPaused:
219+ case Update.StateDownloadPaused:
220+ return i18n.tr("Paused");
221+
222+ case Update.StateQueuedForDownload:
223+ return i18n.tr("Waiting to download");
224+
225+ case Update.StateDownloading:
226+ return i18n.tr("Downloading");
227+
228+ default:
229+ return "";
230+ }
231+ }
232+ }
233+
234+ Label {
235+ id: statusLabel
236+ objectName: "updateStatusLabel"
237+
238+ visible: text !== ""
239+ Layout.alignment: Qt.AlignRight | Qt.AlignVCenter
240+ Layout.fillWidth: true
241+
242+ horizontalAlignment: Text.AlignRight
243+ fontSize: "small"
244+
245+ text: {
246+
247+ function humanFileSize(bytes, si) {
248+ var thresh = si ? 1000 : 1024;
249+ if(Math.abs(bytes) < thresh) {
250+ return bytes + ' B';
251+ }
252+ var units = si
253+ ? ['kB','MB','GB','TB','PB','EB','ZB','YB']
254+ : ['KiB','MiB','GiB','TiB','PiB','EiB','ZiB','YiB'];
255+ var u = -1;
256+ do {
257+ bytes /= thresh;
258+ ++u;
259+ } while(Math.abs(bytes) >= thresh && u < units.length - 1);
260+ return bytes.toFixed(1)+' '+units[u];
261+ }
262+
263+ switch (updateState) {
264+ case Update.StateAvailable:
265+ return humanFileSize(size, 1000);
266+
267+ case Update.StateDownloading:
268+ case Update.StateDownloadingAutomatically:
269+ case Update.StateDownloadPaused:
270+ case Update.StateAutomaticDownloadPaused:
271+ var down = humanFileSize((size / 100) * progress, 1000);
272+ var left = humanFileSize(size, 1000);
273+ if (progress > 100) {
274+ return left;
275+ } else {
276+ /* TRANSLATORS: %1 is the human readable amount
277+ of bytes downloaded, and %2 is the total to be
278+ downloaded. */
279+ return i18n.tr("%1 of %2").arg(down).arg(left);
280+ }
281+
282+ case Update.StateDownloaded:
283+ return i18n.tr("Downloaded");
284+
285+ case Update.StateInstallFinished:
286+ return i18n.tr("Installed");
287+
288+ case Update.StateInstalled:
289+ /* TRANSLATORS: %1 is the date at which this
290+ update was applied. */
291+ return i18n.tr("Updated %1").arg(
292+ updatedAt.toLocaleDateString(Qt.locale(), "d MMMM")
293+ );
294+ default:
295+ return "";
296+ }
297+ }
298+
299+ /* Seems AlignRight causes a rendering issue that can be
300+ fixed by doing an explicit doLayout. */
301+ Component.onCompleted: doLayout()
302+ }
303+ }
304+
305+ Column {
306+ id: error
307+ objectName: "updateError"
308+ spacing: units.gu(1)
309+ height: childrenRect.height
310+ Layout.fillWidth: true
311+ visible: errorElementDetail.text
312+
313+ Label {
314+ id: errorElementTitle
315+ text: i18n.tr("Update failed")
316+ color: UbuntuColors.red
317+ }
318+
319+ Label {
320+ id: errorElementDetail
321+ anchors { left: parent.left; right: parent.right }
322+ fontSize: "small"
323+ wrapMode: Text.WrapAnywhere
324+ }
325+ } // Error column
326+
327+ ProgressBar {
328+ id: progressBar
329+ objectName: "updateProgressbar"
330+
331+ visible: {
332+ switch (updateState) {
333+ case Update.StateQueuedForDownload:
334+ case Update.StateDownloading:
335+ case Update.StateDownloadPaused:
336+ case Update.StateInstalling:
337+ case Update.StateInstallPaused:
338+ return true;
339+
340+ default:
341+ return false;
342+ }
343+ }
344+ Layout.maximumHeight: units.gu(0.5)
345+ Layout.fillWidth: true
346+ indeterminate: update.progress < 0 || update.progress > 100
347+ minimumValue: 0
348+ maximumValue: 100
349+ showProgressPercentage: false
350+
351+ Behavior on value {
352+ animation: UbuntuNumberAnimation {}
353+ }
354+ } // Progress bar
355+ } // Layout for the rest of the stuff
356+
357+ Item {
358+ SlotsLayout.position: SlotsLayout.Leading;
359+ width: units.gu(4)
360+ height: width
361+
362+ Image {
363+ id: icon
364+ visible: kind === Update.KindImage && !fallback.visible
365+ anchors.fill: parent
366+ asynchronous: true
367+ smooth: true
368+ mipmap: true
369+ }
370+
371+ UbuntuShape {
372+ id: shape
373+ visible: kind !== Update.KindImage && !fallback.visible
374+ anchors.fill: parent
375+ source: icon
376+ }
377+
378+ Image {
379+ id: fallback
380+ visible: icon.status === Image.Error
381+ source : Qt.resolvedUrl("/usr/share/icons/suru/apps/scalable/ubuntu-logo-symbolic.svg")
382+ anchors.fill: parent
383+ asynchronous: true
384+ smooth: true
385+ mipmap: true
386+ }
387+ }
388+ }
389+}
qml/Wizard/Pages/here-terms.qmldeleted−126
@@ -1,126 +0,0 @@
1−/*
2− * Copyright (C) 2014-2016 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−import QtQuick 2.4
18−import Ubuntu.Components 1.3
19−import Ubuntu.Web 0.2
20−import ".." as LocalComponents
21−
22−LocalComponents.Page {
23− objectName: "hereTermsPage"
24−
25− title: i18n.tr("Terms & Conditions")
26− customBack: true
27− customTitle: true
28−
29− onBackClicked: {
30− if (webview.visible) {
31− showBrowser(false);
32− } else {
33− pageStack.prev();
34− }
35− }
36−
37− function showBrowser(show) {
38− if (show) {
39− label1.visible = false;
40− label2.visible = false;
41− label3.visible = false;
42− label4.visible = false;
43− webview.visible = true;
44− } else {
45− webview.visible = false;
46− label1.visible = true;
47− label2.visible = true;
48− label3.visible = true;
49− label4.visible = true;
50− }
51− }
52−
53− Column {
54− id: column
55− anchors.fill: content
56− anchors.leftMargin: staticMargin
57− anchors.rightMargin: wideMode ? parent.rightMargin : staticMargin
58− spacing: units.gu(3)
59−
60− Label {
61− id: label1
62− anchors.left: parent.left
63− anchors.right: parent.right
64− wrapMode: Text.Wrap
65− color: textColor
66− fontSize: "small"
67− font.weight: Font.Light
68− lineHeight: 1.2
69− text: i18n.tr("Your device uses positioning technologies provided by HERE.")
70− }
71−
72− Label {
73− id: label2
74− anchors.left: parent.left
75− anchors.right: parent.right
76− wrapMode: Text.Wrap
77− color: textColor
78− fontSize: "small"
79− font.weight: Font.Light
80− lineHeight: 1.2
81− text: i18n.tr("To provide you with positioning services and to improve their quality, HERE collects information about nearby cell towers and Wi-Fi hotspots around your current location whenever your position is being found.")
82− }
83−
84− Label {
85− id: label3
86− anchors.left: parent.left
87− anchors.right: parent.right
88− wrapMode: Text.Wrap
89− color: textColor
90− fontSize: "small"
91− font.weight: Font.Light
92− lineHeight: 1.2
93− text: i18n.tr("The information collected is used to analyze the service and to improve the use of service, but not to identify you personally.")
94− }
95−
96− Label {
97− id: label4
98− anchors.left: parent.left
99− anchors.right: parent.right
100− wrapMode: Text.Wrap
101− color: textColor
102− fontSize: "small"
103− font.weight: Font.Light
104− lineHeight: 1.2
105− linkColor: UbuntuColors.orange
106− text: i18n.tr("By continuing, you agree to the HERE platform %1 and %2.")
107− .arg("<a href=\"http://here.com/terms/service-terms\">" + i18n.tr("Service Terms") + "</a>")
108− .arg("<a href=\"http://here.com/privacy/privacy-policy\">" + i18n.tr("Privacy Policy") + "</a>");
109− onLinkActivated: {
110− showBrowser(true);
111− webview.url = link;
112− }
113− }
114−
115− WebView {
116− id: webview
117− objectName: "webview"
118− anchors.left: parent.left
119− anchors.right: parent.right
120− anchors.leftMargin: -leftMargin
121− anchors.rightMargin: -rightMargin
122− height: parent.height
123− visible: false
124− }
125− }
126−}
qml/Wizard/Wizard.qml+5−2
@@ -1,4 +1,5 @@
11/*
2+ * Copyright (C) 2018 The UBports project
23 * Copyright (C) 2013, 2015 Canonical, Ltd.
34 *
45 * This program is free software; you can redistribute it and/or modify
@@ -20,7 +21,7 @@ import Wizard 0.1
2021import "../Components"
2122
2223Showable {
23− id: root
24+ id: wizard
2425
2526 // This is a bool instead of an alias because Loader classes like to emit
2627 // changed signals for 'active' during startup even if they aren't actually
@@ -29,6 +30,8 @@ Showable {
2930 // expected behavior of no emission on startup.
3031 readonly property bool active: loader.active
3132
33+ property bool isUpdate: System.isUpdate
34+
3235 // The wizard should be run at a later time if, for example, unity8 is
3336 // in greeter mode
3437 property bool deferred: false
@@ -49,7 +52,7 @@ Showable {
4952
5053 Connections {
5154 target: loader.item
52− onQuit: root.hide()
55+ onQuit: wizard.hide()
5356 }
5457 }
5558}