on 42301fa help sign in
unity8/qml/Panel/Indicators/MenuItemFactory.qml
1003 lines 37 kB history raw
1/*
2 * Copyright 2013,2015 Canonical Ltd.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
17import QtQuick 2.4
18import Ubuntu.Settings.Menus 0.1 as Menus
19import Ubuntu.Settings.Components 0.1
20import QMenuModel 0.1
21import Utils 0.1 as Utils
22import Ubuntu.Components.ListItems 1.3 as ListItems
23import Ubuntu.Components 1.3
24import Unity.Session 0.1
26Item {
27 id: menuFactory
29 property var rootModel: null
30 property var menuModel: null
32 property var _map: {
33 "default": {
34 "unity.widgets.systemsettings.tablet.volumecontrol" : sliderMenu,
35 "unity.widgets.systemsettings.tablet.switch" : switchMenu,
37 "com.canonical.indicator.button" : buttonMenu,
38 "com.canonical.indicator.div" : separatorMenu,
39 "com.canonical.indicator.section" : sectionMenu,
40 "com.canonical.indicator.progress" : progressMenu,
41 "com.canonical.indicator.slider" : sliderMenu,
42 "com.canonical.indicator.switch" : switchMenu,
43 "com.canonical.indicator.alarm" : alarmMenu,
44 "com.canonical.indicator.appointment" : appointmentMenu,
45 "com.canonical.indicator.transfer" : transferMenu,
46 "com.canonical.indicator.button-section" : buttonSectionMenu,
47 "com.canonical.indicator.link" : linkMenu,
49 "com.canonical.indicator.messages.messageitem" : messageItem,
50 "com.canonical.indicator.messages.sourceitem" : groupedMessage,
52 "com.canonical.unity.slider" : sliderMenu,
53 "com.canonical.unity.switch" : switchMenu,
55 "com.canonical.unity.media-player" : mediaPayerMenu,
56 "com.canonical.unity.playback-item" : playbackItemMenu,
58 "unity.widgets.systemsettings.tablet.wifisection" : wifiSection,
59 "unity.widgets.systemsettings.tablet.accesspoint" : accessPoint,
60 "com.canonical.indicator.network.modeminfoitem" : modeminfoitem,
62 "com.canonical.indicator.calendar": calendarMenu,
63 "com.canonical.indicator.location": timezoneMenu,
65 "indicator.user-menu-item": userMenuItem,
66 "indicator.guest-menu-item": userMenuItem
67 },
68 "indicator-messages" : {
69 "com.canonical.indicator.button" : messagesButtonMenu
70 }
71 }
73 function getExtendedProperty(object, propertyName, defaultValue) {
74 if (object && object.hasOwnProperty(propertyName)) {
75 return object[propertyName];
76 }
77 return defaultValue;
78 }
80 Component {
81 id: separatorMenu;
83 Menus.SeparatorMenu {
84 objectName: "separatorMenu"
85 }
86 }
88 Component {
89 id: sliderMenu;
91 Menus.SliderMenu {
92 id: sliderItem
93 objectName: "sliderMenu"
94 property QtObject menuData: null
95 property var menuModel: menuFactory.menuModel
96 property int menuIndex: -1
97 property var extendedData: menuData && menuData.ext || undefined
98 property var serverValue: getExtendedProperty(menuData, "actionState", undefined)
100 text: menuData && menuData.label || ""
101 iconSource: menuData && menuData.icon || ""
102 minIcon: getExtendedProperty(extendedData, "minIcon", "")
103 maxIcon: getExtendedProperty(extendedData, "maxIcon", "")
105 minimumValue: getExtendedProperty(extendedData, "minValue", 0.0)
106 maximumValue: {
107 var maximum = getExtendedProperty(extendedData, "maxValue", 1.0);
108 if (maximum <= minimumValue) {
109 return minimumValue + 1;
110 }
111 return maximum;
112 }
113 enabled: menuData && menuData.sensitive || false
114 highlightWhenPressed: false
116 onMenuModelChanged: {
117 loadAttributes();
118 }
119 onMenuIndexChanged: {
120 loadAttributes();
121 }
123 function loadAttributes() {
124 if (!menuModel || menuIndex == -1) return;
125 menuModel.loadExtendedAttributes(menuIndex, {'min-value': 'double',
126 'max-value': 'double',
127 'min-icon': 'icon',
128 'max-icon': 'icon',
129 'x-canonical-sync-action': 'string'});
130 }
132 ServerPropertySynchroniser {
133 id: sliderPropertySync
134 objectName: "sync"
135 syncTimeout: Utils.Constants.indicatorValueTimeout
136 bufferedSyncTimeout: true
137 maximumWaitBufferInterval: 16
139 serverTarget: sliderItem
140 serverProperty: "serverValue"
141 userTarget: sliderItem
142 userProperty: "value"
144 onSyncTriggered: menuModel.changeState(menuIndex, value)
145 }
147 UnityMenuAction {
148 model: menuModel
149 index: menuIndex
150 name: getExtendedProperty(extendedData, "xCanonicalSyncAction", "")
151 onStateChanged: {
152 sliderPropertySync.reset();
153 sliderPropertySync.updateUserValue();
154 }
155 }
156 }
157 }
159 Component {
160 id: buttonMenu;
162 Menus.ButtonMenu {
163 objectName: "buttonMenu"
164 property QtObject menuData: null
165 property var menuModel: menuFactory.menuModel
166 property int menuIndex: -1
168 buttonText: menuData && menuData.label || ""
169 enabled: menuData && menuData.sensitive || false
170 highlightWhenPressed: false
172 onTriggered: {
173 menuModel.activate(menuIndex);
174 }
175 }
176 }
178 Component {
179 id: messagesButtonMenu;
181 Item {
182 objectName: "messagesButtonMenu"
183 property QtObject menuData: null
184 property var menuModel: menuFactory.menuModel
185 property int menuIndex: -1
187 implicitHeight: units.gu(5)
188 enabled: menuData && menuData.sensitive || false
190 Label {
191 id: buttonMenuLabel
192 text: menuData && menuData.label || ""
193 anchors.centerIn: parent
194 font.bold: true
195 }
197 MouseArea {
198 anchors {
199 fill: buttonMenuLabel
200 margins: units.gu(-1)
201 }
202 onClicked: menuModel.activate(menuIndex);
203 }
204 }
205 }
207 Component {
208 id: sectionMenu;
210 Menus.SectionMenu {
211 objectName: "sectionMenu"
212 property QtObject menuData: null
213 property var menuIndex: undefined
215 text: menuData && menuData.label || ""
216 busy: false
217 }
218 }
220 Component {
221 id: progressMenu;
223 Menus.ProgressValueMenu {
224 objectName: "progressMenu"
225 property QtObject menuData: null
226 property int menuIndex: -1
228 text: menuData && menuData.label || ""
229 iconSource: menuData && menuData.icon || ""
230 value : menuData && menuData.actionState || 0.0
231 highlightWhenPressed: false
232 }
233 }
235 Component {
236 id: standardMenu;
238 Menus.StandardMenu {
239 objectName: "standardMenu"
240 property QtObject menuData: null
241 property int menuIndex: -1
243 text: menuData && menuData.label || ""
244 iconSource: menuData && menuData.icon || ""
245 enabled: menuData && menuData.sensitive || false
246 highlightWhenPressed: false
248 onTriggered: {
249 menuModel.activate(menuIndex);
250 }
252 // FIXME : At the moment, the indicators aren't using
253 // com.canonical.indicators.link for settings menu. Need to fudge it.
254 property bool settingsMenu: menuData && menuData.action.indexOf("settings") > -1 || false
255 backColor: settingsMenu ? Qt.rgba(1,1,1,0.07) : "transparent"
256 component: settingsMenu ? buttonForSettings : undefined
257 Component {
258 id: buttonForSettings
259 Icon {
260 name: "settings"
261 height: units.gu(3)
262 width: height
263 color: theme.palette.normal.backgroundText
264 }
265 }
266 }
267 }
269 Component {
270 id: linkMenu;
272 Menus.StandardMenu {
273 objectName: "linkMenu"
274 property QtObject menuData: null
275 property int menuIndex: -1
277 text: menuData && menuData.label || ""
278 iconSource: menuData && menuData.icon || ""
279 enabled: menuData && menuData.sensitive || false
280 highlightWhenPressed: false
282 onTriggered: {
283 menuModel.activate(menuIndex);
284 }
286 backColor: Qt.rgba(1,1,1,0.07)
288 component: menuData.icon ? icon : undefined
289 Component {
290 id: icon
291 Icon {
292 source: menuData.icon
293 height: units.gu(3)
294 width: height
295 color: theme.palette.normal.backgroundText
296 }
297 }
298 }
299 }
301 Component {
302 id: checkableMenu;
304 Menus.CheckableMenu {
305 id: checkItem
306 objectName: "checkableMenu"
307 property QtObject menuData: null
308 property int menuIndex: -1
309 property bool serverChecked: menuData && menuData.isToggled || false
311 text: menuData && menuData.label || ""
312 enabled: menuData && menuData.sensitive || false
313 checked: serverChecked
314 highlightWhenPressed: false
316 ServerPropertySynchroniser {
317 objectName: "sync"
318 syncTimeout: Utils.Constants.indicatorValueTimeout
320 serverTarget: checkItem
321 serverProperty: "serverChecked"
322 userTarget: checkItem
323 userProperty: "checked"
325 onSyncTriggered: menuModel.activate(checkItem.menuIndex)
326 }
327 }
328 }
330 Component {
331 id: switchMenu;
333 Menus.SwitchMenu {
334 id: switchItem
335 objectName: "switchMenu"
336 property QtObject menuData: null
337 property int menuIndex: -1
338 property bool serverChecked: menuData && menuData.isToggled || false
340 text: menuData && menuData.label || ""
341 iconSource: menuData && menuData.icon || ""
342 enabled: menuData && menuData.sensitive || false
343 checked: serverChecked
344 highlightWhenPressed: false
346 ServerPropertySynchroniser {
347 objectName: "sync"
348 syncTimeout: Utils.Constants.indicatorValueTimeout
350 serverTarget: switchItem
351 serverProperty: "serverChecked"
352 userTarget: switchItem
353 userProperty: "checked"
355 onSyncTriggered: menuModel.activate(switchItem.menuIndex);
356 }
357 }
358 }
360 Component {
361 id: alarmMenu;
363 Menus.EventMenu {
364 id: alarmItem
365 objectName: "alarmMenu"
366 property QtObject menuData: null
367 property var menuModel: menuFactory.menuModel
368 property int menuIndex: -1
369 property var extendedData: menuData && menuData.ext || undefined
371 property date serverTime: new Date(getExtendedProperty(extendedData, "xCanonicalTime", 0) * 1000)
372 LiveTimer {
373 frequency: LiveTimer.Relative
374 relativeTime: alarmItem.serverTime
375 onTrigger: alarmItem.serverTime = new Date(getExtendedProperty(extendedData, "xCanonicalTime", 0) * 1000)
376 }
378 text: menuData && menuData.label || ""
379 iconSource: menuData && menuData.icon || "image://theme/alarm-clock"
380 time: i18n.relativeDateTime(serverTime)
381 enabled: menuData && menuData.sensitive || false
382 highlightWhenPressed: false
384 onMenuModelChanged: {
385 loadAttributes();
386 }
387 onMenuIndexChanged: {
388 loadAttributes();
389 }
390 onTriggered: {
391 menuModel.activate(menuIndex);
392 }
394 function loadAttributes() {
395 if (!menuModel || menuIndex == -1) return;
396 menuModel.loadExtendedAttributes(menuIndex, {'x-canonical-time': 'int64'});
397 }
398 }
399 }
401 Component {
402 id: appointmentMenu;
404 Menus.EventMenu {
405 id: appointmentItem
406 objectName: "appointmentMenu"
407 property QtObject menuData: null
408 property var menuModel: menuFactory.menuModel
409 property int menuIndex: -1
410 property var extendedData: menuData && menuData.ext || undefined
412 property date serverTime: new Date(getExtendedProperty(extendedData, "xCanonicalTime", 0) * 1000)
413 LiveTimer {
414 frequency: LiveTimer.Relative
415 relativeTime: appointmentItem.serverTime
416 onTrigger: appointmentItem.serverTime = new Date(getExtendedProperty(extendedData, "xCanonicalTime", 0) * 1000)
417 }
419 text: menuData && menuData.label || ""
420 iconSource: menuData && menuData.icon || "image://theme/calendar"
421 time: i18n.relativeDateTime(serverTime)
422 eventColor: getExtendedProperty(extendedData, "xCanonicalColor", Qt.rgba(0.0, 0.0, 0.0, 0.0))
423 enabled: menuData && menuData.sensitive || false
424 highlightWhenPressed: false
426 onMenuModelChanged: {
427 loadAttributes();
428 }
429 onMenuIndexChanged: {
430 loadAttributes();
431 }
432 onTriggered: {
433 menuModel.activate(menuIndex);
434 }
436 function loadAttributes() {
437 if (!menuModel || menuIndex == -1) return;
438 menuModel.loadExtendedAttributes(menuIndex, {'x-canonical-color': 'string',
439 'x-canonical-time': 'int64'});
440 }
441 }
442 }
444 Component {
445 id: userMenuItem
447 Menus.UserSessionMenu {
448 objectName: "userSessionMenu"
449 highlightWhenPressed: false
451 property QtObject menuData: null
452 property var menuModel: menuFactory.menuModel
453 property int menuIndex: -1
455 name: menuData && menuData.label || "" // label is the user's real name
456 iconSource: menuData && menuData.icon || ""
458 // would be better to compare with the logname but sadly the indicator doesn't expose that
459 active: DBusUnitySessionService.RealName() !== "" ? DBusUnitySessionService.RealName() == name
460 : DBusUnitySessionService.UserName() == name
462 onTriggered: {
463 menuModel.activate(menuIndex);
464 }
465 }
466 }
468 Component {
469 id: calendarMenu
471 Menus.CalendarMenu {
472 objectName: "calendarMenu"
473 highlightWhenPressed: false
474 focus: true
475 }
476 }
478 Component {
479 id: timezoneMenu
481 Menus.TimeZoneMenu {
482 id: tzMenuItem
483 objectName: "timezoneMenu"
485 property QtObject menuData: null
486 property var menuModel: menuFactory.menuModel
487 property int menuIndex: -1
488 property var extendedData: menuData && menuData.ext || undefined
489 readonly property string tz: getExtendedProperty(extendedData, "xCanonicalTimezone", "UTC")
490 property var updateTimer: Timer {
491 repeat: true
492 running: tzMenuItem.visible // only run when we're open
493 onTriggered: tzMenuItem.time = Utils.TimezoneFormatter.currentTimeInTimezone(tzMenuItem.tz)
494 }
496 city: menuData && menuData.label || ""
497 time: Utils.TimezoneFormatter.currentTimeInTimezone(tz)
498 enabled: menuData && menuData.sensitive || false
500 onMenuModelChanged: {
501 loadAttributes();
502 }
503 onMenuIndexChanged: {
504 loadAttributes();
505 }
506 onTriggered: {
507 tzActionGroup.setLocation.activate(tz);
508 }
510 QDBusActionGroup {
511 id: tzActionGroup
512 busType: DBus.SessionBus
513 busName: "com.canonical.indicator.datetime"
514 objectPath: "/com/canonical/indicator/datetime"
516 property variant setLocation: action("set-location")
518 Component.onCompleted: tzActionGroup.start()
519 }
521 function loadAttributes() {
522 if (!menuModel || menuIndex == -1) return;
523 menuModel.loadExtendedAttributes(menuIndex, {'x-canonical-timezone': 'string'});
524 }
525 }
526 }
528 Component {
529 id: wifiSection;
531 Menus.SectionMenu {
532 objectName: "wifiSection"
533 property QtObject menuData: null
534 property var menuModel: menuFactory.menuModel
535 property int menuIndex: -1
536 property var extendedData: menuData && menuData.ext || undefined
538 text: menuData && menuData.label || ""
539 busy: getExtendedProperty(extendedData, "xCanonicalBusyAction", false)
541 onMenuModelChanged: {
542 loadAttributes();
543 }
544 onMenuIndexChanged: {
545 loadAttributes();
546 }
548 function loadAttributes() {
549 if (!menuModel || menuIndex == -1) return;
550 menuModel.loadExtendedAttributes(menuIndex, {'x-canonical-busy-action': 'bool'})
551 }
552 }
553 }
555 Component {
556 id: accessPoint;
558 Menus.AccessPointMenu {
559 id: apItem
560 objectName: "accessPoint"
561 property QtObject menuData: null
562 property var menuModel: menuFactory.menuModel
563 property int menuIndex: -1
564 property var extendedData: menuData && menuData.ext || undefined
565 property bool serverChecked: menuData && menuData.isToggled || false
567 property var strengthAction: UnityMenuAction {
568 model: menuModel
569 index: menuIndex
570 name: getExtendedProperty(extendedData, "xCanonicalWifiApStrengthAction", "")
571 }
573 text: menuData && menuData.label || ""
574 enabled: menuData && menuData.sensitive || false
575 active: serverChecked
576 secure: getExtendedProperty(extendedData, "xCanonicalWifiApIsSecure", false)
577 adHoc: getExtendedProperty(extendedData, "xCanonicalWifiApIsAdhoc", false)
578 signalStrength: {
579 if (strengthAction.valid) {
580 var state = strengthAction.state; // handle both int and uchar
581 // FIXME remove the special casing when we switch to indicator-network completely
582 if (typeof state == "string") {
583 return state.charCodeAt();
584 }
585 return state;
586 }
587 return 0;
588 }
589 highlightWhenPressed: false
591 onMenuModelChanged: {
592 loadAttributes();
593 }
594 onMenuIndexChanged: {
595 loadAttributes();
596 }
598 function loadAttributes() {
599 if (!menuModel || menuIndex == -1) return;
600 menuModel.loadExtendedAttributes(menuIndex, {'x-canonical-wifi-ap-is-adhoc': 'bool',
601 'x-canonical-wifi-ap-is-secure': 'bool',
602 'x-canonical-wifi-ap-strength-action': 'string'});
603 }
605 ServerPropertySynchroniser {
606 objectName: "sync"
607 syncTimeout: Utils.Constants.indicatorValueTimeout
609 serverTarget: apItem
610 serverProperty: "serverChecked"
611 userTarget: apItem
612 userProperty: "active"
613 userTrigger: "onTriggered"
615 onSyncTriggered: menuModel.activate(apItem.menuIndex)
616 }
617 }
618 }
620 Component {
621 id: modeminfoitem;
622 Menus.ModemInfoItem {
623 objectName: "modemInfoItem"
624 property QtObject menuData: null
625 property var menuModel: menuFactory.menuModel
626 property int menuIndex: -1
627 property var extendedData: menuData && menuData.ext || undefined
628 highlightWhenPressed: false
630 property var statusLabelAction: UnityMenuAction {
631 model: menuModel
632 index: menuIndex
633 name: getExtendedProperty(extendedData, "xCanonicalModemStatusLabelAction", "")
634 }
635 statusText: statusLabelAction.valid ? statusLabelAction.state : ""
637 property var statusIconAction: UnityMenuAction {
638 model: menuModel
639 index: menuIndex
640 name: getExtendedProperty(extendedData, "xCanonicalModemStatusIconAction", "")
641 }
642 statusIcon: statusIconAction.valid ? statusIconAction.state : ""
644 property var connectivityIconAction: UnityMenuAction {
645 model: menuModel
646 index: menuIndex
647 name: getExtendedProperty(extendedData, "xCanonicalModemConnectivityIconAction", "")
648 }
649 connectivityIcon: connectivityIconAction.valid ? connectivityIconAction.state : ""
651 property var simIdentifierLabelAction: UnityMenuAction {
652 model: menuModel
653 index: menuIndex
654 name: getExtendedProperty(extendedData, "xCanonicalModemSimIdentifierLabelAction", "")
655 }
656 simIdentifierText: simIdentifierLabelAction.valid ? simIdentifierLabelAction.state : ""
658 property var roamingAction: UnityMenuAction {
659 model: menuModel
660 index: menuIndex
661 name: getExtendedProperty(extendedData, "xCanonicalModemRoamingAction", "")
662 }
663 roaming: roamingAction.valid ? roamingAction.state : false
665 property var unlockAction: UnityMenuAction {
666 model: menuModel
667 index: menuIndex
668 name: getExtendedProperty(extendedData, "xCanonicalModemLockedAction", "")
669 }
670 onUnlock: {
671 unlockAction.activate();
672 }
673 locked: unlockAction.valid ? unlockAction.state : false
675 onMenuModelChanged: {
676 loadAttributes();
677 }
678 onMenuIndexChanged: {
679 loadAttributes();
680 }
682 function loadAttributes() {
683 if (!menuModel || menuIndex == -1) return;
684 menuModel.loadExtendedAttributes(menuIndex, {'x-canonical-modem-status-label-action': 'string',
685 'x-canonical-modem-status-icon-action': 'string',
686 'x-canonical-modem-connectivity-icon-action': 'string',
687 'x-canonical-modem-sim-identifier-label-action': 'string',
688 'x-canonical-modem-roaming-action': 'string',
689 'x-canonical-modem-locked-action': 'string'});
690 }
691 }
692 }
694 Component {
695 id: messageItem
697 MessageMenuItemFactory {
698 objectName: "messageItem"
699 menuModel: menuFactory.menuModel
700 }
701 }
703 Component {
704 id: groupedMessage
706 Menus.GroupedMessageMenu {
707 objectName: "groupedMessage"
708 property QtObject menuData: null
709 property var menuModel: menuFactory.menuModel
710 property int menuIndex: -1
711 property var extendedData: menuData && menuData.ext || undefined
713 text: menuData && menuData.label || ""
714 iconSource: getExtendedProperty(extendedData, "icon", "image://theme/message")
715 count: menuData && menuData.actionState.length > 0 ? menuData.actionState[0] : "0"
716 enabled: menuData && menuData.sensitive || false
717 highlightWhenPressed: false
718 removable: true
720 onMenuModelChanged: {
721 loadAttributes();
722 }
723 onMenuIndexChanged: {
724 loadAttributes();
725 }
726 onClicked: {
727 menuModel.activate(menuIndex, true);
728 }
729 onDismissed: {
730 menuModel.activate(menuIndex, false);
731 }
733 function loadAttributes() {
734 if (!menuModel || menuIndex == -1) return;
735 menuModel.loadExtendedAttributes(modelIndex, {'icon': 'icon'});
736 }
737 }
738 }
740 Component {
741 id: mediaPayerMenu;
743 Menus.MediaPlayerMenu {
744 objectName: "mediaPayerMenu"
745 property QtObject menuData: null
746 property var menuModel: menuFactory.menuModel
747 property int menuIndex: -1
748 property var actionState: menuData && menuData.actionState || undefined
749 property bool running: getExtendedProperty(actionState, "running", false)
751 playerIcon: menuData && menuData.icon || "image://theme/stock_music"
752 playerName: menuData && menuData.label || i18n.tr("Nothing is playing")
754 albumArt: getExtendedProperty(actionState, "art-url", "image://theme/stock_music")
755 song: getExtendedProperty(actionState, "title", "")
756 artist: getExtendedProperty(actionState, "artist", "")
757 album: getExtendedProperty(actionState, "album", "")
758 showTrack: running && (state == "Playing" || state == "Paused")
759 state: getExtendedProperty(actionState, "state", "")
760 enabled: menuData && menuData.sensitive || false
761 highlightWhenPressed: false
762 showDivider: false
764 onTriggered: {
765 model.activate(modelIndex);
766 }
767 }
768 }
770 Component {
771 id: playbackItemMenu;
773 Menus.PlaybackItemMenu {
774 objectName: "playbackItemMenu"
775 property QtObject menuData: null
776 property var menuModel: menuFactory.menuModel
777 property int menuIndex: -1
778 property var extendedData: menuData && menuData.ext || undefined
780 property var playAction: UnityMenuAction {
781 model: menuModel
782 index: menuIndex
783 name: getExtendedProperty(extendedData, "xCanonicalPlayAction", "")
784 }
785 property var nextAction: UnityMenuAction {
786 model: menuModel
787 index: menuIndex
788 name: getExtendedProperty(extendedData, "xCanonicalNextAction", "")
789 }
790 property var previousAction: UnityMenuAction {
791 model: menuModel
792 index: menuIndex
793 name: getExtendedProperty(extendedData, "xCanonicalPreviousAction", "")
794 }
796 playing: playAction.state === "Playing"
797 canPlay: playAction.valid
798 canGoNext: nextAction.valid
799 canGoPrevious: previousAction.valid
800 enabled: menuData && menuData.sensitive || false
801 highlightWhenPressed: false
803 onPlay: {
804 playAction.activate();
805 }
806 onNext: {
807 nextAction.activate();
808 }
809 onPrevious: {
810 previousAction.activate();
811 }
812 onMenuModelChanged: {
813 loadAttributes();
814 }
815 onMenuIndexChanged: {
816 loadAttributes();
817 }
819 function loadAttributes() {
820 if (!menuModel || menuIndex == -1) return;
821 menuModel.loadExtendedAttributes(modelIndex, {'x-canonical-play-action': 'string',
822 'x-canonical-next-action': 'string',
823 'x-canonical-previous-action': 'string'});
824 }
825 }
826 }
828 Component {
829 id: transferMenu
831 Menus.TransferMenu {
832 objectName: "transferMenu"
833 id: transfer
834 property QtObject menuData: null
835 property var menuModel: menuFactory.menuModel
836 property int menuIndex: -1
837 property var extendedData: menuData && menuData.ext || undefined
838 property var uid: getExtendedProperty(extendedData, "xCanonicalUid", undefined)
840 text: menuData && menuData.label || ""
841 iconSource: menuData && menuData.icon || "image://theme/transfer-none"
842 maximum: 1.0
843 enabled: menuData && menuData.sensitive || false
844 highlightWhenPressed: false
845 removable: true
846 confirmRemoval: true
848 QDBusActionGroup {
849 id: actionGroup
850 busType: 1
851 busName: rootModel.busName
852 objectPath: rootModel.actions["indicator"]
854 property var activateAction: action("activate-transfer")
855 property var cancelAction: action("cancel-transfer")
856 property var transferStateAction: uid !== undefined ? action("transfer-state."+uid) : null
858 Component.onCompleted: actionGroup.start()
859 }
861 property var transferState: {
862 if (actionGroup.transferStateAction === null) return undefined;
863 return actionGroup.transferStateAction.valid ? actionGroup.transferStateAction.state : undefined
864 }
866 property var runningState : transferState !== undefined ? transferState["state"] : undefined
867 property var secondsLeft : transferState !== undefined ? transferState["seconds-left"] : undefined
869 active: runningState !== undefined && runningState !== Menus.TransferState.Finished
870 progress: transferState !== undefined ? transferState["percent"] : 0.0
872 // TODO - Should be in the SDK
873 property var timeRemaining: {
874 if (secondsLeft === undefined) return undefined;
876 var remaining = "";
877 var hours = Math.floor(secondsLeft / (60 * 60));
878 var minutes = Math.floor(secondsLeft / 60) % 60;
879 var seconds = secondsLeft % 60;
880 if (hours > 0) {
881 remaining += i18n.tr("%1 hour", "%1 hours", hours).arg(hours)
882 }
883 if (minutes > 0) {
884 if (remaining != "") remaining += ", ";
885 remaining += i18n.tr("%1 minute", "%1 minutes", minutes).arg(minutes)
886 }
887 // don't include seconds if hours > 0
888 if (hours == 0 && minutes < 5 && seconds > 0) {
889 if (remaining != "") remaining += ", ";
890 remaining += i18n.tr("%1 second", "%1 seconds", seconds).arg(seconds)
891 }
892 if (remaining == "")
893 remaining = i18n.tr("0 seconds");
894 // Translators: String like "1 hour, 2 minutes, 3 seconds remaining"
895 return i18n.tr("%1 remaining").arg(remaining);
896 }
898 stateText: {
899 switch (runningState) {
900 case Menus.TransferState.Queued:
901 return i18n.tr("In queue…");
902 case Menus.TransferState.Hashing:
903 case Menus.TransferState.Processing:
904 case Menus.TransferState.Running:
905 return timeRemaining === undefined ? i18n.tr("Downloading") : timeRemaining;
906 case Menus.TransferState.Paused:
907 return i18n.tr("Paused, tap to resume");
908 case Menus.TransferState.Canceled:
909 return i18n.tr("Canceled");
910 case Menus.TransferState.Finished:
911 return i18n.tr("Finished");
912 case Menus.TransferState.Error:
913 return i18n.tr("Failed, tap to retry");
914 }
915 return "";
916 }
918 onMenuModelChanged: {
919 loadAttributes();
920 }
921 onMenuIndexChanged: {
922 loadAttributes();
923 }
924 onTriggered: {
925 actionGroup.activateAction.activate(uid);
926 }
927 onItemRemoved: {
928 actionGroup.cancelAction.activate(uid);
929 }
931 function loadAttributes() {
932 if (!menuModel || menuIndex == -1) return;
933 menuModel.loadExtendedAttributes(menuIndex, {'x-canonical-uid': 'string'});
934 }
935 }
936 }
938 Component {
939 id: buttonSectionMenu;
941 Menus.StandardMenu {
942 objectName: "buttonSectionMenu"
943 property QtObject menuData: null
944 property var menuModel: menuFactory.menuModel
945 property int menuIndex: -1
946 property var extendedData: menuData && menuData.ext || undefined
948 iconSource: menuData && menuData.icon || ""
949 enabled: menuData && menuData.sensitive || false
950 highlightWhenPressed: false
951 text: menuData && menuData.label || ""
952 foregroundColor: theme.palette.normal.backgroundText
954 onMenuModelChanged: {
955 loadAttributes();
956 }
957 onMenuIndexChanged: {
958 loadAttributes();
959 }
960 function loadAttributes() {
961 if (!menuModel || menuIndex == -1) return;
962 menuModel.loadExtendedAttributes(menuIndex, {'x-canonical-extra-label': 'string'});
963 }
965 component: Component {
966 Button {
967 objectName: "buttonSectionMenuControl"
968 text: getExtendedProperty(extendedData, "xCanonicalExtraLabel", "")
970 onClicked: {
971 menuModel.activate(menuIndex);
972 }
973 }
974 }
975 }
976 }
978 function load(modelData, context) {
979 if (modelData.type !== undefined && modelData.type !== "") {
980 var component = undefined;
982 var contextComponents = _map[context];
983 if (contextComponents !== undefined) {
984 component = contextComponents[modelData.type];
985 }
987 if (component === undefined) {
988 component = _map["default"][modelData.type];
989 }
990 if (component !== undefined) {
991 return component;
992 }
993 console.debug("Don't know how to make " + modelData.type + " for " + context);
994 }
995 if (modelData.isCheck || modelData.isRadio) {
996 return checkableMenu;
997 }
998 if (modelData.isSeparator) {
999 return separatorMenu;
1001 return standardMenu;