on b210fee help sign in
unity8/qml/Panel/Indicators/MenuItemFactory.qml
1004 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 enabled: menuData && menuData.sensitive || false
232 highlightWhenPressed: false
233 }
234 }
236 Component {
237 id: standardMenu;
239 Menus.StandardMenu {
240 objectName: "standardMenu"
241 property QtObject menuData: null
242 property int menuIndex: -1
244 text: menuData && menuData.label || ""
245 iconSource: menuData && menuData.icon || ""
246 enabled: menuData && menuData.sensitive || false
247 highlightWhenPressed: false
249 onTriggered: {
250 menuModel.activate(menuIndex);
251 }
253 // FIXME : At the moment, the indicators aren't using
254 // com.canonical.indicators.link for settings menu. Need to fudge it.
255 property bool settingsMenu: menuData && menuData.action.indexOf("settings") > -1 || false
256 backColor: settingsMenu ? Qt.rgba(1,1,1,0.07) : "transparent"
257 component: settingsMenu ? buttonForSettings : undefined
258 Component {
259 id: buttonForSettings
260 Icon {
261 name: "settings"
262 height: units.gu(3)
263 width: height
264 color: theme.palette.selected.backgroundText
265 }
266 }
267 }
268 }
270 Component {
271 id: linkMenu;
273 Menus.StandardMenu {
274 objectName: "linkMenu"
275 property QtObject menuData: null
276 property int menuIndex: -1
278 text: menuData && menuData.label || ""
279 iconSource: menuData && menuData.icon || ""
280 enabled: menuData && menuData.sensitive || false
281 highlightWhenPressed: false
283 onTriggered: {
284 menuModel.activate(menuIndex);
285 }
287 backColor: Qt.rgba(1,1,1,0.07)
289 component: menuData.icon ? icon : undefined
290 Component {
291 id: icon
292 Icon {
293 source: menuData.icon
294 height: units.gu(3)
295 width: height
296 color: theme.palette.selected.backgroundText
297 }
298 }
299 }
300 }
302 Component {
303 id: checkableMenu;
305 Menus.CheckableMenu {
306 id: checkItem
307 objectName: "checkableMenu"
308 property QtObject menuData: null
309 property int menuIndex: -1
310 property bool serverChecked: menuData && menuData.isToggled || false
312 text: menuData && menuData.label || ""
313 enabled: menuData && menuData.sensitive || false
314 checked: serverChecked
315 highlightWhenPressed: false
317 ServerPropertySynchroniser {
318 objectName: "sync"
319 syncTimeout: Utils.Constants.indicatorValueTimeout
321 serverTarget: checkItem
322 serverProperty: "serverChecked"
323 userTarget: checkItem
324 userProperty: "checked"
326 onSyncTriggered: menuModel.activate(checkItem.menuIndex)
327 }
328 }
329 }
331 Component {
332 id: switchMenu;
334 Menus.SwitchMenu {
335 id: switchItem
336 objectName: "switchMenu"
337 property QtObject menuData: null
338 property int menuIndex: -1
339 property bool serverChecked: menuData && menuData.isToggled || false
341 text: menuData && menuData.label || ""
342 iconSource: menuData && menuData.icon || ""
343 enabled: menuData && menuData.sensitive || false
344 checked: serverChecked
345 highlightWhenPressed: false
347 ServerPropertySynchroniser {
348 objectName: "sync"
349 syncTimeout: Utils.Constants.indicatorValueTimeout
351 serverTarget: switchItem
352 serverProperty: "serverChecked"
353 userTarget: switchItem
354 userProperty: "checked"
356 onSyncTriggered: menuModel.activate(switchItem.menuIndex);
357 }
358 }
359 }
361 Component {
362 id: alarmMenu;
364 Menus.EventMenu {
365 id: alarmItem
366 objectName: "alarmMenu"
367 property QtObject menuData: null
368 property var menuModel: menuFactory.menuModel
369 property int menuIndex: -1
370 property var extendedData: menuData && menuData.ext || undefined
372 property date serverTime: new Date(getExtendedProperty(extendedData, "xCanonicalTime", 0) * 1000)
373 LiveTimer {
374 frequency: LiveTimer.Relative
375 relativeTime: alarmItem.serverTime
376 onTrigger: alarmItem.serverTime = new Date(getExtendedProperty(extendedData, "xCanonicalTime", 0) * 1000)
377 }
379 text: menuData && menuData.label || ""
380 iconSource: menuData && menuData.icon || "image://theme/alarm-clock"
381 time: i18n.relativeDateTime(serverTime)
382 enabled: menuData && menuData.sensitive || false
383 highlightWhenPressed: false
385 onMenuModelChanged: {
386 loadAttributes();
387 }
388 onMenuIndexChanged: {
389 loadAttributes();
390 }
391 onTriggered: {
392 menuModel.activate(menuIndex);
393 }
395 function loadAttributes() {
396 if (!menuModel || menuIndex == -1) return;
397 menuModel.loadExtendedAttributes(menuIndex, {'x-canonical-time': 'int64'});
398 }
399 }
400 }
402 Component {
403 id: appointmentMenu;
405 Menus.EventMenu {
406 id: appointmentItem
407 objectName: "appointmentMenu"
408 property QtObject menuData: null
409 property var menuModel: menuFactory.menuModel
410 property int menuIndex: -1
411 property var extendedData: menuData && menuData.ext || undefined
413 property date serverTime: new Date(getExtendedProperty(extendedData, "xCanonicalTime", 0) * 1000)
414 LiveTimer {
415 frequency: LiveTimer.Relative
416 relativeTime: appointmentItem.serverTime
417 onTrigger: appointmentItem.serverTime = new Date(getExtendedProperty(extendedData, "xCanonicalTime", 0) * 1000)
418 }
420 text: menuData && menuData.label || ""
421 iconSource: menuData && menuData.icon || "image://theme/calendar"
422 time: i18n.relativeDateTime(serverTime)
423 eventColor: getExtendedProperty(extendedData, "xCanonicalColor", Qt.rgba(0.0, 0.0, 0.0, 0.0))
424 enabled: menuData && menuData.sensitive || false
425 highlightWhenPressed: false
427 onMenuModelChanged: {
428 loadAttributes();
429 }
430 onMenuIndexChanged: {
431 loadAttributes();
432 }
433 onTriggered: {
434 menuModel.activate(menuIndex);
435 }
437 function loadAttributes() {
438 if (!menuModel || menuIndex == -1) return;
439 menuModel.loadExtendedAttributes(menuIndex, {'x-canonical-color': 'string',
440 'x-canonical-time': 'int64'});
441 }
442 }
443 }
445 Component {
446 id: userMenuItem
448 Menus.UserSessionMenu {
449 objectName: "userSessionMenu"
450 highlightWhenPressed: false
452 property QtObject menuData: null
453 property var menuModel: menuFactory.menuModel
454 property int menuIndex: -1
456 name: menuData && menuData.label || "" // label is the user's real name
457 iconSource: menuData && menuData.icon || ""
459 // would be better to compare with the logname but sadly the indicator doesn't expose that
460 active: DBusUnitySessionService.RealName() !== "" ? DBusUnitySessionService.RealName() == name
461 : DBusUnitySessionService.UserName() == name
463 onTriggered: {
464 menuModel.activate(menuIndex);
465 }
466 }
467 }
469 Component {
470 id: calendarMenu
472 Menus.CalendarMenu {
473 objectName: "calendarMenu"
474 highlightWhenPressed: false
475 focus: true
476 }
477 }
479 Component {
480 id: timezoneMenu
482 Menus.TimeZoneMenu {
483 id: tzMenuItem
484 objectName: "timezoneMenu"
486 property QtObject menuData: null
487 property var menuModel: menuFactory.menuModel
488 property int menuIndex: -1
489 property var extendedData: menuData && menuData.ext || undefined
490 readonly property string tz: getExtendedProperty(extendedData, "xCanonicalTimezone", "UTC")
491 property var updateTimer: Timer {
492 repeat: true
493 running: tzMenuItem.visible // only run when we're open
494 onTriggered: tzMenuItem.time = Utils.TimezoneFormatter.currentTimeInTimezone(tzMenuItem.tz)
495 }
497 city: menuData && menuData.label || ""
498 time: Utils.TimezoneFormatter.currentTimeInTimezone(tz)
499 enabled: menuData && menuData.sensitive || false
501 onMenuModelChanged: {
502 loadAttributes();
503 }
504 onMenuIndexChanged: {
505 loadAttributes();
506 }
507 onTriggered: {
508 tzActionGroup.setLocation.activate(tz);
509 }
511 QDBusActionGroup {
512 id: tzActionGroup
513 busType: DBus.SessionBus
514 busName: "com.canonical.indicator.datetime"
515 objectPath: "/com/canonical/indicator/datetime"
517 property variant setLocation: action("set-location")
519 Component.onCompleted: tzActionGroup.start()
520 }
522 function loadAttributes() {
523 if (!menuModel || menuIndex == -1) return;
524 menuModel.loadExtendedAttributes(menuIndex, {'x-canonical-timezone': 'string'});
525 }
526 }
527 }
529 Component {
530 id: wifiSection;
532 Menus.SectionMenu {
533 objectName: "wifiSection"
534 property QtObject menuData: null
535 property var menuModel: menuFactory.menuModel
536 property int menuIndex: -1
537 property var extendedData: menuData && menuData.ext || undefined
539 text: menuData && menuData.label || ""
540 busy: getExtendedProperty(extendedData, "xCanonicalBusyAction", false)
542 onMenuModelChanged: {
543 loadAttributes();
544 }
545 onMenuIndexChanged: {
546 loadAttributes();
547 }
549 function loadAttributes() {
550 if (!menuModel || menuIndex == -1) return;
551 menuModel.loadExtendedAttributes(menuIndex, {'x-canonical-busy-action': 'bool'})
552 }
553 }
554 }
556 Component {
557 id: accessPoint;
559 Menus.AccessPointMenu {
560 id: apItem
561 objectName: "accessPoint"
562 property QtObject menuData: null
563 property var menuModel: menuFactory.menuModel
564 property int menuIndex: -1
565 property var extendedData: menuData && menuData.ext || undefined
566 property bool serverChecked: menuData && menuData.isToggled || false
568 property var strengthAction: UnityMenuAction {
569 model: menuModel
570 index: menuIndex
571 name: getExtendedProperty(extendedData, "xCanonicalWifiApStrengthAction", "")
572 }
574 text: menuData && menuData.label || ""
575 enabled: menuData && menuData.sensitive || false
576 active: serverChecked
577 secure: getExtendedProperty(extendedData, "xCanonicalWifiApIsSecure", false)
578 adHoc: getExtendedProperty(extendedData, "xCanonicalWifiApIsAdhoc", false)
579 signalStrength: {
580 if (strengthAction.valid) {
581 var state = strengthAction.state; // handle both int and uchar
582 // FIXME remove the special casing when we switch to indicator-network completely
583 if (typeof state == "string") {
584 return state.charCodeAt();
585 }
586 return state;
587 }
588 return 0;
589 }
590 highlightWhenPressed: false
592 onMenuModelChanged: {
593 loadAttributes();
594 }
595 onMenuIndexChanged: {
596 loadAttributes();
597 }
599 function loadAttributes() {
600 if (!menuModel || menuIndex == -1) return;
601 menuModel.loadExtendedAttributes(menuIndex, {'x-canonical-wifi-ap-is-adhoc': 'bool',
602 'x-canonical-wifi-ap-is-secure': 'bool',
603 'x-canonical-wifi-ap-strength-action': 'string'});
604 }
606 ServerPropertySynchroniser {
607 objectName: "sync"
608 syncTimeout: Utils.Constants.indicatorValueTimeout
610 serverTarget: apItem
611 serverProperty: "serverChecked"
612 userTarget: apItem
613 userProperty: "active"
614 userTrigger: "onTriggered"
616 onSyncTriggered: menuModel.activate(apItem.menuIndex)
617 }
618 }
619 }
621 Component {
622 id: modeminfoitem;
623 ModemInfoItem {
624 objectName: "modemInfoItem"
625 property QtObject menuData: null
626 property var menuModel: menuFactory.menuModel
627 property int menuIndex: -1
628 property var extendedData: menuData && menuData.ext || undefined
629 highlightWhenPressed: false
631 property var statusLabelAction: UnityMenuAction {
632 model: menuModel
633 index: menuIndex
634 name: getExtendedProperty(extendedData, "xCanonicalModemStatusLabelAction", "")
635 }
636 statusText: statusLabelAction.valid ? statusLabelAction.state : ""
638 property var statusIconAction: UnityMenuAction {
639 model: menuModel
640 index: menuIndex
641 name: getExtendedProperty(extendedData, "xCanonicalModemStatusIconAction", "")
642 }
643 statusIcon: statusIconAction.valid ? statusIconAction.state : ""
645 property var connectivityIconAction: UnityMenuAction {
646 model: menuModel
647 index: menuIndex
648 name: getExtendedProperty(extendedData, "xCanonicalModemConnectivityIconAction", "")
649 }
650 connectivityIcon: connectivityIconAction.valid ? connectivityIconAction.state : ""
652 property var simIdentifierLabelAction: UnityMenuAction {
653 model: menuModel
654 index: menuIndex
655 name: getExtendedProperty(extendedData, "xCanonicalModemSimIdentifierLabelAction", "")
656 }
657 simIdentifierText: simIdentifierLabelAction.valid ? simIdentifierLabelAction.state : ""
659 property var roamingAction: UnityMenuAction {
660 model: menuModel
661 index: menuIndex
662 name: getExtendedProperty(extendedData, "xCanonicalModemRoamingAction", "")
663 }
664 roaming: roamingAction.valid ? roamingAction.state : false
666 property var unlockAction: UnityMenuAction {
667 model: menuModel
668 index: menuIndex
669 name: getExtendedProperty(extendedData, "xCanonicalModemLockedAction", "")
670 }
671 onUnlock: {
672 unlockAction.activate();
673 }
674 locked: unlockAction.valid ? unlockAction.state : false
676 onMenuModelChanged: {
677 loadAttributes();
678 }
679 onMenuIndexChanged: {
680 loadAttributes();
681 }
683 function loadAttributes() {
684 if (!menuModel || menuIndex == -1) return;
685 menuModel.loadExtendedAttributes(menuIndex, {'x-canonical-modem-status-label-action': 'string',
686 'x-canonical-modem-status-icon-action': 'string',
687 'x-canonical-modem-connectivity-icon-action': 'string',
688 'x-canonical-modem-sim-identifier-label-action': 'string',
689 'x-canonical-modem-roaming-action': 'string',
690 'x-canonical-modem-locked-action': 'string'});
691 }
692 }
693 }
695 Component {
696 id: messageItem
698 MessageMenuItemFactory {
699 objectName: "messageItem"
700 menuModel: menuFactory.menuModel
701 }
702 }
704 Component {
705 id: groupedMessage
707 Menus.GroupedMessageMenu {
708 objectName: "groupedMessage"
709 property QtObject menuData: null
710 property var menuModel: menuFactory.menuModel
711 property int menuIndex: -1
712 property var extendedData: menuData && menuData.ext || undefined
714 text: menuData && menuData.label || ""
715 iconSource: getExtendedProperty(extendedData, "icon", "image://theme/message")
716 count: menuData && menuData.actionState.length > 0 ? menuData.actionState[0] : "0"
717 enabled: menuData && menuData.sensitive || false
718 highlightWhenPressed: false
719 removable: true
721 onMenuModelChanged: {
722 loadAttributes();
723 }
724 onMenuIndexChanged: {
725 loadAttributes();
726 }
727 onClicked: {
728 menuModel.activate(menuIndex, true);
729 }
730 onDismissed: {
731 menuModel.activate(menuIndex, false);
732 }
734 function loadAttributes() {
735 if (!menuModel || menuIndex == -1) return;
736 menuModel.loadExtendedAttributes(modelIndex, {'icon': 'icon'});
737 }
738 }
739 }
741 Component {
742 id: mediaPayerMenu;
744 Menus.MediaPlayerMenu {
745 objectName: "mediaPayerMenu"
746 property QtObject menuData: null
747 property var menuModel: menuFactory.menuModel
748 property int menuIndex: -1
749 property var actionState: menuData && menuData.actionState || undefined
750 property bool running: getExtendedProperty(actionState, "running", false)
752 playerIcon: menuData && menuData.icon || "image://theme/stock_music"
753 playerName: menuData && menuData.label || i18n.tr("Nothing is playing")
755 albumArt: getExtendedProperty(actionState, "art-url", "image://theme/stock_music")
756 song: getExtendedProperty(actionState, "title", "")
757 artist: getExtendedProperty(actionState, "artist", "")
758 album: getExtendedProperty(actionState, "album", "")
759 showTrack: running && (state == "Playing" || state == "Paused")
760 state: getExtendedProperty(actionState, "state", "")
761 enabled: menuData && menuData.sensitive || false
762 highlightWhenPressed: false
763 showDivider: false
765 onTriggered: {
766 model.activate(modelIndex);
767 }
768 }
769 }
771 Component {
772 id: playbackItemMenu;
774 Menus.PlaybackItemMenu {
775 objectName: "playbackItemMenu"
776 property QtObject menuData: null
777 property var menuModel: menuFactory.menuModel
778 property int menuIndex: -1
779 property var extendedData: menuData && menuData.ext || undefined
781 property var playAction: UnityMenuAction {
782 model: menuModel
783 index: menuIndex
784 name: getExtendedProperty(extendedData, "xCanonicalPlayAction", "")
785 }
786 property var nextAction: UnityMenuAction {
787 model: menuModel
788 index: menuIndex
789 name: getExtendedProperty(extendedData, "xCanonicalNextAction", "")
790 }
791 property var previousAction: UnityMenuAction {
792 model: menuModel
793 index: menuIndex
794 name: getExtendedProperty(extendedData, "xCanonicalPreviousAction", "")
795 }
797 playing: playAction.state === "Playing"
798 canPlay: playAction.valid
799 canGoNext: nextAction.valid
800 canGoPrevious: previousAction.valid
801 enabled: menuData && menuData.sensitive || false
802 highlightWhenPressed: false
804 onPlay: {
805 playAction.activate();
806 }
807 onNext: {
808 nextAction.activate();
809 }
810 onPrevious: {
811 previousAction.activate();
812 }
813 onMenuModelChanged: {
814 loadAttributes();
815 }
816 onMenuIndexChanged: {
817 loadAttributes();
818 }
820 function loadAttributes() {
821 if (!menuModel || menuIndex == -1) return;
822 menuModel.loadExtendedAttributes(modelIndex, {'x-canonical-play-action': 'string',
823 'x-canonical-next-action': 'string',
824 'x-canonical-previous-action': 'string'});
825 }
826 }
827 }
829 Component {
830 id: transferMenu
832 Menus.TransferMenu {
833 objectName: "transferMenu"
834 id: transfer
835 property QtObject menuData: null
836 property var menuModel: menuFactory.menuModel
837 property int menuIndex: -1
838 property var extendedData: menuData && menuData.ext || undefined
839 property var uid: getExtendedProperty(extendedData, "xCanonicalUid", undefined)
841 text: menuData && menuData.label || ""
842 iconSource: menuData && menuData.icon || "image://theme/transfer-none"
843 maximum: 1.0
844 enabled: menuData && menuData.sensitive || false
845 highlightWhenPressed: false
846 removable: true
847 confirmRemoval: true
849 QDBusActionGroup {
850 id: actionGroup
851 busType: 1
852 busName: rootModel.busName
853 objectPath: rootModel.actions["indicator"]
855 property var activateAction: action("activate-transfer")
856 property var cancelAction: action("cancel-transfer")
857 property var transferStateAction: uid !== undefined ? action("transfer-state."+uid) : null
859 Component.onCompleted: actionGroup.start()
860 }
862 property var transferState: {
863 if (actionGroup.transferStateAction === null) return undefined;
864 return actionGroup.transferStateAction.valid ? actionGroup.transferStateAction.state : undefined
865 }
867 property var runningState : transferState !== undefined ? transferState["state"] : undefined
868 property var secondsLeft : transferState !== undefined ? transferState["seconds-left"] : undefined
870 active: runningState !== undefined && runningState !== Menus.TransferState.Finished
871 progress: transferState !== undefined ? transferState["percent"] : 0.0
873 // TODO - Should be in the SDK
874 property var timeRemaining: {
875 if (secondsLeft === undefined) return undefined;
877 var remaining = "";
878 var hours = Math.floor(secondsLeft / (60 * 60));
879 var minutes = Math.floor(secondsLeft / 60) % 60;
880 var seconds = secondsLeft % 60;
881 if (hours > 0) {
882 remaining += i18n.tr("%1 hour", "%1 hours", hours).arg(hours)
883 }
884 if (minutes > 0) {
885 if (remaining != "") remaining += ", ";
886 remaining += i18n.tr("%1 minute", "%1 minutes", minutes).arg(minutes)
887 }
888 // don't include seconds if hours > 0
889 if (hours == 0 && minutes < 5 && seconds > 0) {
890 if (remaining != "") remaining += ", ";
891 remaining += i18n.tr("%1 second", "%1 seconds", seconds).arg(seconds)
892 }
893 if (remaining == "")
894 remaining = i18n.tr("0 seconds");
895 // Translators: String like "1 hour, 2 minutes, 3 seconds remaining"
896 return i18n.tr("%1 remaining").arg(remaining);
897 }
899 stateText: {
900 switch (runningState) {
901 case Menus.TransferState.Queued:
902 return i18n.tr("In queue…");
903 case Menus.TransferState.Hashing:
904 case Menus.TransferState.Processing:
905 case Menus.TransferState.Running:
906 return timeRemaining === undefined ? i18n.tr("Downloading") : timeRemaining;
907 case Menus.TransferState.Paused:
908 return i18n.tr("Paused, tap to resume");
909 case Menus.TransferState.Canceled:
910 return i18n.tr("Canceled");
911 case Menus.TransferState.Finished:
912 return i18n.tr("Finished");
913 case Menus.TransferState.Error:
914 return i18n.tr("Failed, tap to retry");
915 }
916 return "";
917 }
919 onMenuModelChanged: {
920 loadAttributes();
921 }
922 onMenuIndexChanged: {
923 loadAttributes();
924 }
925 onTriggered: {
926 actionGroup.activateAction.activate(uid);
927 }
928 onItemRemoved: {
929 actionGroup.cancelAction.activate(uid);
930 }
932 function loadAttributes() {
933 if (!menuModel || menuIndex == -1) return;
934 menuModel.loadExtendedAttributes(menuIndex, {'x-canonical-uid': 'string'});
935 }
936 }
937 }
939 Component {
940 id: buttonSectionMenu;
942 Menus.StandardMenu {
943 objectName: "buttonSectionMenu"
944 property QtObject menuData: null
945 property var menuModel: menuFactory.menuModel
946 property int menuIndex: -1
947 property var extendedData: menuData && menuData.ext || undefined
949 iconSource: menuData && menuData.icon || ""
950 enabled: menuData && menuData.sensitive || false
951 highlightWhenPressed: false
952 text: menuData && menuData.label || ""
953 foregroundColor: theme.palette.normal.backgroundText
955 onMenuModelChanged: {
956 loadAttributes();
957 }
958 onMenuIndexChanged: {
959 loadAttributes();
960 }
961 function loadAttributes() {
962 if (!menuModel || menuIndex == -1) return;
963 menuModel.loadExtendedAttributes(menuIndex, {'x-canonical-extra-label': 'string'});
964 }
966 component: Component {
967 Button {
968 objectName: "buttonSectionMenuControl"
969 text: getExtendedProperty(extendedData, "xCanonicalExtraLabel", "")
971 onClicked: {
972 menuModel.activate(menuIndex);
973 }
974 }
975 }
976 }
977 }
979 function load(modelData, context) {
980 if (modelData.type !== undefined && modelData.type !== "") {
981 var component = undefined;
983 var contextComponents = _map[context];
984 if (contextComponents !== undefined) {
985 component = contextComponents[modelData.type];
986 }
988 if (component === undefined) {
989 component = _map["default"][modelData.type];
990 }
991 if (component !== undefined) {
992 return component;
993 }
994 console.debug("Don't know how to make " + modelData.type + " for " + context);
995 }
996 if (modelData.isCheck || modelData.isRadio) {
997 return checkableMenu;
998 }
999 if (modelData.isSeparator) {
1000 return separatorMenu;
1002 return standardMenu;