on xenial help sign in
updates to transfer items
39e63c8Nick Dedekind
plugins/Unity/Indicators/qml/MenuItemFactory.qml+123−5
@@ -19,7 +19,8 @@
19
19
20import QtQuick 2.0
20import QtQuick 2.0
21import Ubuntu.Settings.Menus 0.1 as Menus
21import Ubuntu.Settings.Menus 0.1 as Menus
22+import Ubuntu.Settings.Components 0.1 as SettingsComponents
22−import QMenuModel 0.1 as QMenuModel
23+import QMenuModel 0.1
23import Utils 0.1 as Utils
24import Utils 0.1 as Utils
24import Ubuntu.Components.ListItems 0.1 as ListItems
25import Ubuntu.Components.ListItems 0.1 as ListItems
25import Ubuntu.Components 0.1
26import Ubuntu.Components 0.1
@@ -27,6 +28,7 @@ import Ubuntu.Components 0.1
27Item {
28Item {
28 id: menuFactory
29 id: menuFactory
29
30
31+ property var rootModel: null
30 property var menuModel: null
32 property var menuModel: null
31
33
32 property var _map: {
34 property var _map: {
@@ -41,6 +43,7 @@ Item {
41 "com.canonical.indicator.switch" : switchMenu,
43 "com.canonical.indicator.switch" : switchMenu,
42 "com.canonical.indicator.alarm" : alarmMenu,
44 "com.canonical.indicator.alarm" : alarmMenu,
43 "com.canonical.indicator.appointment" : appointmentMenu,
45 "com.canonical.indicator.appointment" : appointmentMenu,
46+ "com.canonical.indicator.transfer" : transferMenu,
44
47
45 "com.canonical.indicator.messages.messageitem" : messageItem,
48 "com.canonical.indicator.messages.messageitem" : messageItem,
46 "com.canonical.indicator.messages.sourceitem" : groupedMessage,
49 "com.canonical.indicator.messages.sourceitem" : groupedMessage,
@@ -330,7 +333,7 @@ Item {
330 property int menuIndex: -1
333 property int menuIndex: -1
331 property var extendedData: menuData && menuData.ext || undefined
334 property var extendedData: menuData && menuData.ext || undefined
332
335
333− property var strengthAction: QMenuModel.UnityMenuAction {
336+ property var strengthAction: UnityMenuAction {
334 model: menuModel
337 model: menuModel
335 index: menuIndex
338 index: menuIndex
336 name: getExtendedProperty(extendedData, "xCanonicalWifiApStrengthAction", "")
339 name: getExtendedProperty(extendedData, "xCanonicalWifiApStrengthAction", "")
@@ -442,17 +445,17 @@ Item {
442 property int menuIndex: -1
445 property int menuIndex: -1
443 property var extendedData: menuData && menuData.ext || undefined
446 property var extendedData: menuData && menuData.ext || undefined
444
447
445− property var playAction: QMenuModel.UnityMenuAction {
448+ property var playAction: UnityMenuAction {
446 model: menuModel
449 model: menuModel
447 index: menuIndex
450 index: menuIndex
448 name: getExtendedProperty(extendedData, "xCanonicalPlayAction", "")
451 name: getExtendedProperty(extendedData, "xCanonicalPlayAction", "")
449 }
452 }
450− property var nextAction: QMenuModel.UnityMenuAction {
453+ property var nextAction: UnityMenuAction {
451 model: menuModel
454 model: menuModel
452 index: menuIndex
455 index: menuIndex
453 name: getExtendedProperty(extendedData, "xCanonicalNextAction", "")
456 name: getExtendedProperty(extendedData, "xCanonicalNextAction", "")
454 }
457 }
455− property var previousAction: QMenuModel.UnityMenuAction {
458+ property var previousAction: UnityMenuAction {
456 model: menuModel
459 model: menuModel
457 index: menuIndex
460 index: menuIndex
458 name: getExtendedProperty(extendedData, "xCanonicalPreviousAction", "")
461 name: getExtendedProperty(extendedData, "xCanonicalPreviousAction", "")
@@ -489,6 +492,121 @@ Item {
489 }
492 }
490 }
493 }
491
494
495+ Component {
496+ id: transferMenu
497+ Menus.TransferMenu {
498+ objectName: "transferMenu"
499+ id: transfer
500+ property QtObject menuData: null
501+ property var menuModel: menuFactory.menuModel
502+ property int menuIndex: -1
503+ property var extendedData: menuData && menuData.ext || undefined
504+ property var uid: getExtendedProperty(extendedData, "xCanonicalUid", undefined)
505+
506+ text: menuData && menuData.label || ""
507+ iconSource: menuData && menuData.icon || "image://theme/save"
508+ maximum: 1.0
509+ enabled: menuData && menuData.sensitive || false
510+ removable: true
511+ confirmRemoval: true
512+
513+ QDBusActionGroup {
514+ id: actionGroup
515+ busType: 1
516+ busName: rootModel.busName
517+ objectPath: rootModel.actions["indicator"]
518+
519+ property QtObject activateAction: action("activate-transfer")
520+ property QtObject cancelAction: action("cancel-transfer")
521+ property QtObject pauseAction: action("pause-transfer")
522+ property QtObject resumeAction: action("resume-transfer")
523+ property QtObject transferStates: action("transfer-states")
524+
525+ Component.onCompleted: actionGroup.start()
526+ }
527+
528+ property var transferStateProperties: uid !== undefined && actionGroup.transferStates.valid && actionGroup.transferStates.state[uid] || undefined
529+
530+ property var transferState : transferStateProperties !== undefined && transferStateProperties["state"] || undefined
531+ property var secondsLeft : transferStateProperties !== undefined && transferStateProperties["seconds-left"]
532+
533+ active: transferStateProperties !== undefined && transferState !== Menus.TransferState.FINISHED
534+ progress : transferStateProperties !== undefined && transferStateProperties["percent"] || 0.0
535+
536+ property var timeRemaining: {
537+ if (secondsLeft === undefined) return undefined;
538+
539+ var remaining = "";
540+ var hours = Math.floor(secondsLeft / (60 * 60));
541+ var minutes = Math.floor(secondsLeft / 60) % 60;
542+ var seconds = secondsLeft % 60;
543+ if (hours > 0) {
544+ remaining += hours + (hours == 1 ? " hour" : " hours");
545+ }
546+ if (minutes > 0) {
547+ if (remaining != "") remaining += ", ";
548+ remaining += minutes + (minutes == 1 ? " minute" : " minutes");
549+ }
550+ // don't include seconds if hours > 0
551+ if (hours == 0 && minutes < 5 && seconds > 0) {
552+ if (remaining != "") remaining += ", ";
553+ remaining += seconds + (seconds == 1 ? " second" : " seconds");
554+ }
555+ if (remaining == "")
556+ remaining = "0 seconds";
557+ return remaining + " remaining";
558+ }
559+
560+ stateText: {
561+ switch (transferState) {
562+ case Menus.TransferState.QUEUED:
563+ return i18n.tr("In queue...");
564+ case Menus.TransferState.HASHING:
565+ case Menus.TransferState.PROCESSING:
566+ case Menus.TransferState.RUNNING:
567+ return timeRemaining === undefined ? "Downloading" : timeRemaining;
568+ case Menus.TransferState.PAUSED:
569+ return i18n.tr("Paused, tap to resume");
570+ case Menus.TransferState.CANCELED:
571+ return i18n.tr("Canceled");
572+ case Menus.TransferState.FINISHED:
573+ return i18n.tr("Finished");
574+ case Menus.TransferState.ERROR:
575+ return i18n.tr("Failed, tap to retry");
576+ }
577+ return "";
578+ }
579+
580+ onMenuModelChanged: {
581+ loadAttributes();
582+ }
583+ onMenuIndexChanged: {
584+ loadAttributes();
585+ }
586+ onTriggered: {
587+ actionGroup.activateAction.activate(uid);
588+ shell.hideIndicatorMenu(UbuntuAnimation.BriskDuration);
589+ }
590+
591+ function loadAttributes() {
592+ if (!menuModel || menuIndex == -1) return;
593+ menuModel.loadExtendedAttributes(menuIndex, {'x-canonical-uid': 'string'});
594+ }
595+
596+ function cancel() {
597+ actionGroup.cancelAction.activate(uid);
598+ }
599+
600+ function pause() {
601+ actionGroup.pauseAction.activate(uid);
602+ }
603+
604+ function resume() {
605+ actionGroup.resumeAction.activate(uid);
606+ }
607+ }
608+ }
609+
492 function load(modelData) {
610 function load(modelData) {
493 if (modelData.type !== undefined) {
611 if (modelData.type !== undefined) {
494 var component = _map[modelData.type];
612 var component = _map[modelData.type];
plugins/Unity/Indicators/qml/qmldir−2
@@ -6,5 +6,3 @@ CachedUnityMenuModel 0.1 CachedUnityMenuModel.qml
6IndicatorBase 0.1 IndicatorBase.qml
6IndicatorBase 0.1 IndicatorBase.qml
7MenuItemFactory 0.1 MenuItemFactory.qml
7MenuItemFactory 0.1 MenuItemFactory.qml
8MessageMenuItemFactory 0.1 MessageMenuItemFactory.qml
8MessageMenuItemFactory 0.1 MessageMenuItemFactory.qml
9−
10−internal RemoveBackground RemoveBackground.qml
qml/Panel/Indicators/DefaultIndicatorPage.qml+4
@@ -135,6 +135,9 @@ Indicators.IndicatorBase {
135 right: parent.right
135 right: parent.right
136 }
136 }
137
137
138+ Component.onCompleted: console.log("created")
139+ Component.onDestruction: console.log("destroyed")
140+
138 sourceComponent: factory.load(model)
141 sourceComponent: factory.load(model)
139
142
140 onLoaded: {
143 onLoaded: {
@@ -176,6 +179,7 @@ Indicators.IndicatorBase {
176
179
177 Indicators.MenuItemFactory {
180 Indicators.MenuItemFactory {
178 id: factory
181 id: factory
182+ rootModel: main.menuModel ? main.menuModel : null
179 menuModel: mainMenu.model ? mainMenu.model : null
183 menuModel: mainMenu.model ? mainMenu.model : null
180 }
184 }
181
185
tests/qmltests/Panel/Indicators/tst_MenuItemFactory.qml+31
@@ -97,6 +97,7 @@ Item {
97 { tag: 'switch2', type: "com.canonical.indicator.switch", objectName: "switchMenu" },
97 { tag: 'switch2', type: "com.canonical.indicator.switch", objectName: "switchMenu" },
98 { tag: 'alarm', type: "com.canonical.indicator.alarm", objectName: "alarmMenu" },
98 { tag: 'alarm', type: "com.canonical.indicator.alarm", objectName: "alarmMenu" },
99 { tag: 'appointment', type: "com.canonical.indicator.appointment", objectName: "appointmentMenu" },
99 { tag: 'appointment', type: "com.canonical.indicator.appointment", objectName: "appointmentMenu" },
100+ { tag: 'transfer', type: "com.canonical.indicator.transfer", objectName: "transferMenu" },
100
101
101 { tag: 'messageItem', type: "com.canonical.indicator.messages.messageitem", objectName: "messageItem" },
102 { tag: 'messageItem', type: "com.canonical.indicator.messages.messageitem", objectName: "messageItem" },
102 { tag: 'sourceItem', type: "com.canonical.indicator.messages.sourceitem", objectName: "groupedMessage" },
103 { tag: 'sourceItem', type: "com.canonical.indicator.messages.sourceitem", objectName: "groupedMessage" },
@@ -427,6 +428,36 @@ Item {
427 compare(loader.item.enabled, data.enabled, "Enabled does not match data");
428 compare(loader.item.enabled, data.enabled, "Enabled does not match data");
428 }
429 }
429
430
431+ function test_create_transferMenu_data() {
432+ return [
433+ {label: "testLabel1", enabled: true, active: true, icon: "file:///testIcon1", progress: 0.1 },
434+ {label: "testLabel2", enabled: false, active: false, icon: "file:///testIcon2", progress: 0.5 },
435+ ];
436+ }
437+
438+ function test_create_transferMenu(data) {
439+ menuData.type = "com.canonical.indicator.transfer";
440+ menuData.label = data.label;
441+ menuData.sensitive = data.enabled;
442+ menuData.icon = data.icon;
443+ menuData.ext = {
444+ 'xCanonicalActive': data.active,
445+ 'maxValue': 1.0
446+ };
447+ menuData.actionState = data.progress;
448+
449+ loader.data = menuData;
450+ loader.sourceComponent = factory.load(menuData);
451+ tryCompareFunction(function() { return loader.item != undefined; }, true);
452+ compare(loader.item.objectName, "transferMenu", "Should have created a transfer menu");
453+
454+ compare(loader.item.text, data.label, "Label does not match data");
455+ compare(loader.item.iconSource, data.icon, "Icon does not match data");
456+ compare(loader.item.progress, data.progress, "Icon does not match data");
457+ compare(loader.item.active, data.active, "Active does not match data");
458+ compare(loader.item.enabled, data.enabled, "Enabled does not match data");
459+ }
460+
430 function test_create_wifiSection_data() {
461 function test_create_wifiSection_data() {
431 return [
462 return [
432 {label: "testLabel1", busy: false },
463 {label: "testLabel1", busy: false },