on xenial help sign in
Add App Update page to wizard (this won't work)
34fcaf6Dalton Durst
qml/Wizard/Pages/78-app-update.qmlnew file+434
@@ -0,0 +1,434 @@
1+/*
2+ * This file is part of system-settings
3+ *
4+ * Copyright (C) 2013-2016 Canonical Ltd.
5+ *
6+ * Contact: Didier Roche <didier.roches@canonical.com>
7+ * Diego Sarmentero <diego.sarmentero@canonical.com>
8+ * Jonas G. Drange <jonas.drange@canonical.com>
9+ *
10+ * This program is free software: you can redistribute it and/or modify it
11+ * under the terms of the GNU General Public License version 3, as published
12+ * by the Free Software Foundation.
13+ *
14+ * This program is distributed in the hope that it will be useful, but
15+ * WITHOUT ANY WARRANTY; without even the implied warranties of
16+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
17+ * PURPOSE. See the GNU General Public License for more details.
18+ *
19+ * You should have received a copy of the GNU General Public License along
20+ * with this program. If not, see <http://www.gnu.org/licenses/>.
21+ */
22+
23+import QMenuModel 0.1
24+import QtQuick 2.4
25+import QtQuick.Layouts 1.1
26+import SystemSettings 1.0
27+import Ubuntu.Components 1.3
28+import Ubuntu.Components.ListItems 1.3 as ListItem
29+import Ubuntu.Components.Popups 1.3
30+import Ubuntu.SystemSettings.Update 1.0
31+import Ubuntu.Connectivity 1.0
32+import Wizard 0.1
33+import ".." as LocalComponents
34+
35+LocalComponents.Page {
36+ id: appUpdatePage
37+ objectName: "appUpdatePage"
38+
39+ title: i18n.tr("Update Apps")
40+ forwardButtonSourceComponent: forwardButton
41+
42+ property bool batchMode: false
43+ property bool havePower: (indicatorPower.deviceState === "charging") ||
44+ (indicatorPower.batteryLevel > 25)
45+ property bool online: NetworkingStatus.online
46+ property bool authenticated: UpdateManager.authenticated
47+ property bool forceCheck: false
48+
49+ property int updatesCount: {
50+ var count = 0;
51+ if (authenticated) {
52+ count += clickRepeater.count;
53+ }
54+ count += imageRepeater.count;
55+ return count;
56+ }
57+
58+ function check(force) {
59+ UpdateManager.check(UpdateManager.CheckClickIgnoreVersion);
60+ }
61+
62+ QDBusActionGroup {
63+ id: indicatorPower
64+ busType: 1
65+ busName: "com.canonical.indicator.power"
66+ objectPath: "/com/canonical/indicator/power"
67+ property var batteryLevel: action("battery-level").state || 0
68+ property var deviceState: action("device-state").state
69+ Component.onCompleted: start()
70+ }
71+
72+ DownloadHandler {
73+ id: downloadHandler
74+ updateModel: UpdateManager.model
75+ }
76+
77+ Flickable {
78+ id: scrollWidget
79+ anchors {
80+ top: parent.top
81+ left: parent.left
82+ right: parent.right
83+ bottom: configuration.top
84+ }
85+ clip: true
86+ contentHeight: content.height
87+ boundsBehavior: (contentHeight > parent.height) ?
88+ Flickable.DragAndOvershootBounds :
89+ Flickable.StopAtBounds
90+ flickableDirection: Flickable.VerticalFlick
91+
92+ Column {
93+ id: content
94+ anchors { left: parent.left; right: parent.right }
95+
96+ Global {
97+ id: glob
98+ objectName: "global"
99+ anchors { left: parent.left; right: parent.right }
100+
101+ height: hidden ? 0 : units.gu(8)
102+ clip: true
103+ status: UpdateManager.status
104+ batchMode: root.batchMode
105+ requireRestart: imageRepeater.count > 0
106+ updatesCount: root.updatesCount
107+ online: root.online
108+ onStop: UpdateManager.cancel()
109+
110+ onRequestInstall: {
111+ if (requireRestart) {
112+ var popup = PopupUtils.open(
113+ Qt.resolvedUrl("ImageUpdatePrompt.qml"), null, {
114+ havePowerForUpdate: root.havePower
115+ }
116+ );
117+ popup.requestSystemUpdate.connect(function () {
118+ install();
119+ });
120+ } else {
121+ install();
122+ }
123+ }
124+ onInstall: {
125+ root.batchMode = true
126+ if (requireRestart) {
127+ postAllBatchHandler.target = root;
128+ } else {
129+ postClickBatchHandler.target = root;
130+ }
131+ }
132+ }
133+
134+ Rectangle {
135+ id: overlay
136+ objectName: "overlay"
137+ anchors {
138+ left: parent.left
139+ leftMargin: units.gu(2)
140+ right: parent.right
141+ rightMargin: units.gu(2)
142+ }
143+ visible: placeholder.text
144+ color: theme.palette.normal.background
145+ height: units.gu(10)
146+
147+ Label {
148+ id: placeholder
149+ objectName: "overlayText"
150+ anchors.fill: parent
151+ verticalAlignment: Text.AlignVCenter
152+ horizontalAlignment: Text.AlignHCenter
153+ wrapMode: Text.WordWrap
154+ text: {
155+ var s = UpdateManager.status;
156+ if (!root.online) {
157+ return i18n.tr("Connect to the Internet to check for updates.");
158+ } else if (s === UpdateManager.StatusIdle && updatesCount === 0) {
159+ return i18n.tr("Software is up to date");
160+ } else if (s === UpdateManager.StatusServerError ||
161+ s === UpdateManager.StatusNetworkError) {
162+ return i18n.tr("The update server is not responding. Try again later.");
163+ }
164+ return "";
165+ }
166+ }
167+ }
168+
169+ SettingsItemTitle {
170+ id: updatesAvailableHeader
171+ text: i18n.tr("Updates Available")
172+ visible: imageUpdateCol.visible || clickUpdatesCol.visible
173+ }
174+
175+ Column {
176+ id: imageUpdateCol
177+ objectName: "imageUpdates"
178+ anchors { left: parent.left; right: parent.right }
179+ visible: {
180+ var s = UpdateManager.status;
181+ var haveUpdates = imageRepeater.count > 0;
182+ switch (s) {
183+ case UpdateManager.StatusCheckingClickUpdates:
184+ case UpdateManager.StatusIdle:
185+ return haveUpdates && online;
186+ }
187+ return false;
188+ }
189+
190+ Repeater {
191+ id: imageRepeater
192+ model: UpdateManager.imageUpdates
193+
194+ delegate: UpdateDelegate {
195+ objectName: "imageUpdatesDelegate-" + index
196+ width: imageUpdateCol.width
197+ updateState: model.updateState
198+ progress: model.progress
199+ version: remoteVersion
200+ size: model.size
201+ changelog: model.changelog
202+ error: model.error
203+ kind: model.kind
204+ iconUrl: model.iconUrl
205+ name: title
206+
207+ onResume: download()
208+ onRetry: download()
209+ onDownload: {
210+ if (SystemImage.downloadMode < 2) {
211+ SystemImage.downloadUpdate();
212+ SystemImage.forceAllowGSMDownload();
213+ } else {
214+ SystemImage.downloadUpdate();
215+ }
216+ }
217+ onPause: SystemImage.pauseDownload();
218+ onInstall: {
219+ var popup = PopupUtils.open(
220+ Qt.resolvedUrl("ImageUpdatePrompt.qml"), null, {
221+ havePowerForUpdate: root.havePower
222+ }
223+ );
224+ popup.requestSystemUpdate.connect(SystemImage.applyUpdate);
225+ }
226+ }
227+ }
228+ }
229+
230+ Column {
231+ id: clickUpdatesCol
232+ objectName: "clickUpdates"
233+ anchors { left: parent.left; right: parent.right }
234+ visible: {
235+ var s = UpdateManager.status;
236+ var haveUpdates = clickRepeater.count > 0;
237+ switch (s) {
238+ case UpdateManager.StatusCheckingImageUpdates:
239+ case UpdateManager.StatusIdle:
240+ return haveUpdates && online && authenticated;
241+ }
242+ return false;
243+ }
244+
245+ Repeater {
246+ id: clickRepeater
247+ model: UpdateManager.clickUpdates
248+
249+ delegate: ClickUpdateDelegate {
250+ objectName: "clickUpdatesDelegate" + index
251+ width: clickUpdatesCol.width
252+ updateState: model.updateState
253+ progress: model.progress
254+ version: remoteVersion
255+ size: model.size
256+ name: title
257+ iconUrl: model.iconUrl
258+ kind: model.kind
259+ changelog: model.changelog
260+ error: model.error
261+ signedUrl: signedDownloadUrl
262+
263+ onInstall: downloadHandler.createDownload(model);
264+ onPause: downloadHandler.pauseDownload(model)
265+ onResume: downloadHandler.resumeDownload(model)
266+ onRetry: {
267+ /* This creates a new signed URL with which we can
268+ retry the download. See onSignedUrlChanged. */
269+ UpdateManager.retry(model.identifier,
270+ model.revision);
271+ }
272+
273+ onSignedUrlChanged: {
274+ // If we have a signedUrl, user intend to retry.
275+ if (signedUrl) {
276+ downloadHandler.retryDownload(model);
277+ }
278+ }
279+
280+ Connections {
281+ target: glob
282+ onInstall: install()
283+ }
284+
285+ /* If we a downloadId, we expect UDM to restore it
286+ after some time. Workaround for lp:1603770. */
287+ Timer {
288+ id: downloadTimeout
289+ interval: 30000
290+ running: true
291+ onTriggered: {
292+ var s = updateState;
293+ if (model.downloadId
294+ || s === Update.StateQueuedForDownload
295+ || s === Update.StateDownloading) {
296+ downloadHandler.assertDownloadExist(model);
297+ }
298+ }
299+ }
300+ }
301+ }
302+ }
303+
304+ SettingsItemTitle {
305+ text: i18n.tr("Recent updates")
306+ visible: installedCol.visible
307+ }
308+
309+ Column {
310+ id: installedCol
311+ objectName: "installedUpdates"
312+ anchors { left: parent.left; right: parent.right }
313+ visible: installedRepeater.count > 0
314+
315+ Repeater {
316+ id: installedRepeater
317+ model: UpdateManager.installedUpdates
318+
319+ delegate: UpdateDelegate {
320+ objectName: "installedUpdateDelegate-" + index
321+ width: installedCol.width
322+ version: remoteVersion
323+ size: model.size
324+ name: title
325+ kind: model.kind
326+ iconUrl: model.iconUrl
327+ changelog: model.changelog
328+ updateState: Update.StateInstalled
329+ updatedAt: model.updatedAt
330+
331+ leadingActions: ListItemActions {
332+ actions: [
333+ Action {
334+ iconName: "delete"
335+ onTriggered: UpdateManager.remove(
336+ model.identifier, model.revision
337+ )
338+ }
339+ ]
340+ }
341+
342+ // Launchable if there's a package name on a click.
343+ launchable: (!!packageName &&
344+ model.kind === Update.KindClick)
345+
346+ onLaunch: UpdateManager.launch(identifier, revision);
347+ }
348+ }
349+ }
350+ } // Column inside flickable.
351+ } // Flickable
352+
353+ Column {
354+ id: configuration
355+
356+ height: childrenRect.height
357+
358+ anchors {
359+ bottom: parent.bottom
360+ left: parent.left
361+ right: parent.right
362+ }
363+
364+ ListItem.ThinDivider {}
365+
366+ ListItem.SingleValue {
367+ objectName: "configuration"
368+ text: i18n.tr("Update settings")
369+ progression: true
370+ onClicked: pageStack.addPageToNextColumn(
371+ root, Qt.resolvedUrl("UpdateSettings.qml"))
372+ }
373+ }
374+
375+ Connections {
376+ id: postClickBatchHandler
377+ ignoreUnknownSignals: true
378+ target: null
379+ onUpdatesCountChanged: {
380+ if (target.updatesCount === 0) {
381+ root.batchMode = false;
382+ target = null;
383+ }
384+ }
385+ }
386+
387+ Connections {
388+ id: postAllBatchHandler
389+ ignoreUnknownSignals: true
390+ target: null
391+ onUpdatesCountChanged: {
392+ if (target.updatesCount === 1) {
393+ SystemImage.updateDownloaded.connect(function () {
394+ SystemImage.applyUpdate();
395+ });
396+ SystemImage.downloadUpdate();
397+ }
398+ }
399+ }
400+
401+ Connections {
402+ target: NetworkingStatus
403+ onOnlineChanged: {
404+ if (!online) {
405+ UpdateManager.cancel();
406+ } else {
407+ UpdateManager.check(UpdateManager.CheckClickIgnoreVersion);
408+ }
409+ }
410+ }
411+
412+ Connections {
413+ target: SystemImage
414+ onUpdateFailed: {
415+ if (consecutiveFailureCount > SystemImage.failuresBeforeWarning) {
416+ var popup = PopupUtils.open(
417+ Qt.resolvedUrl("InstallationFailed.qml"), null, {
418+ text: lastReason
419+ }
420+ );
421+ }
422+ }
423+ }
424+
425+ Component {
426+ id: forwardButton
427+ LocalComponents.StackButton {
428+ text: i18n.tr("Skip")
429+ onClicked: pageStack.next()
430+ }
431+ }
432+
433+ Component.onCompleted: check()
434+}