2 * Copyright 2013 Canonical Ltd.
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.
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.
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/>.
17 * Nick Dedekind <nick.dedekind@canonical.com>
21 import Ubuntu.Settings.Menus 0.1 as Menus
22 import Ubuntu.Settings.Components 0.1 as SettingsComponents
24 import Utils 0.1 as Utils
25 import Ubuntu.Components.ListItems 0.1 as ListItems
26 import Ubuntu.Components 0.1
31 property var rootModel: null
32 property var menuModel: null
35 "unity.widgets.systemsettings.tablet.volumecontrol" : sliderMenu,
36 "unity.widgets.systemsettings.tablet.switch" : switchMenu,
38 "com.canonical.indicator.button" : buttonMenu,
39 "com.canonical.indicator.div" : separatorMenu,
40 "com.canonical.indicator.section" : sectionMenu,
41 "com.canonical.indicator.progress" : progressMenu,
42 "com.canonical.indicator.slider" : sliderMenu,
43 "com.canonical.indicator.switch" : switchMenu,
44 "com.canonical.indicator.alarm" : alarmMenu,
45 "com.canonical.indicator.appointment" : appointmentMenu,
46 "com.canonical.indicator.transfer" : transferMenu,
47 "com.canonical.indicator.button-section" : buttonSectionMenu,
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,
63 function getExtendedProperty(object, propertyName, defaultValue) {
64 if (object && object.hasOwnProperty(propertyName)) {
65 return object[propertyName];
74 objectName: "separatorMenu"
82 objectName: "sliderMenu"
83 property QtObject menuData: null
84 property var menuModel: menuFactory.menuModel
85 property int menuIndex: -1
86 property var extendedData: menuData && menuData.ext || undefined
87 property var serverValue: getExtendedProperty(menuData, "actionState", undefined)
89 text: menuData && menuData.label || ""
90 iconSource: menuData && menuData.icon || ""
91 minIcon: getExtendedProperty(extendedData, "minIcon", "")
92 maxIcon: getExtendedProperty(extendedData, "maxIcon", "")
94 minimumValue: getExtendedProperty(extendedData, "minValue", 0.0)
96 var maximum = getExtendedProperty(extendedData, "maxValue", 1.0);
97 if (maximum <= minimumValue) {
98 return minimumValue + 1;
102 enabled: menuData && menuData.sensitive || false
104 onMenuModelChanged: {
107 onMenuIndexChanged: {
110 onServerValueChanged: {
111 // value can be changed by slider, so a binding won't work.
112 if (serverValue !== undefined) {
117 menuModel.changeState(menuIndex, value);
120 function loadAttributes() {
121 if (!menuModel || menuIndex == -1) return;
122 menuModel.loadExtendedAttributes(menuIndex, {'min-value': 'double',
123 'max-value': 'double',
125 'max-icon': 'icon'});
134 objectName: "buttonMenu"
135 property QtObject menuData: null
136 property var menuModel: menuFactory.menuModel
137 property int menuIndex: -1
139 buttonText: menuData && menuData.label || ""
140 enabled: menuData && menuData.sensitive || false
143 menuModel.activate(menuIndex);
151 objectName: "sectionMenu"
152 property QtObject menuData: null
153 property var menuIndex: undefined
155 text: menuData && menuData.label || ""
163 Menus.ProgressValueMenu {
164 objectName: "progressMenu"
165 property QtObject menuData: null
166 property int menuIndex: -1
168 text: menuData && menuData.label || ""
169 iconSource: menuData && menuData.icon || ""
170 value : menuData && menuData.actionState || 0.0
171 enabled: menuData && menuData.sensitive || false
179 objectName: "standardMenu"
180 property QtObject menuData: null
181 property int menuIndex: -1
183 text: menuData && menuData.label || ""
184 iconSource: menuData && menuData.icon || ""
185 enabled: menuData && menuData.sensitive || false
188 menuModel.activate(menuIndex);
196 Menus.CheckableMenu {
197 objectName: "checkableMenu"
198 property QtObject menuData: null
199 property int menuIndex: -1
201 text: menuData && menuData.label || ""
202 enabled: menuData && menuData.sensitive || false
203 checked: menuData && menuData.isToggled || false
206 menuModel.activate(menuIndex);
216 objectName: "switchMenu"
217 property QtObject menuData: null
218 property int menuIndex: -1
220 text: menuData && menuData.label || ""
221 iconSource: menuData && menuData.icon || ""
222 enabled: menuData && menuData.sensitive || false
223 checked: menuData && menuData.isToggled || false
226 menuModel.activate(menuIndex);
235 objectName: "alarmMenu"
236 property QtObject menuData: null
237 property var menuModel: menuFactory.menuModel
238 property int menuIndex: -1
239 property var extendedData: menuData && menuData.ext || undefined
240 // TODO - bug #1260728
241 property var timeFormatter: Utils.GDateTimeFormatter {
242 time: getExtendedProperty(extendedData, "xCanonicalTime", 0)
243 format: getExtendedProperty(extendedData, "xCanonicalTimeFormat", "")
246 text: menuData && menuData.label || ""
247 iconSource: menuData && menuData.icon || "image://theme/alarm-clock"
248 time: timeFormatter.timeString
249 enabled: menuData && menuData.sensitive || false
251 onMenuModelChanged: {
254 onMenuIndexChanged: {
258 menuModel.activate(menuIndex);
261 function loadAttributes() {
262 if (!menuModel || menuIndex == -1) return;
263 menuModel.loadExtendedAttributes(menuIndex, {'x-canonical-time': 'int64',
264 'x-canonical-time-format': 'string'});
273 objectName: "appointmentMenu"
274 property QtObject menuData: null
275 property var menuModel: menuFactory.menuModel
276 property int menuIndex: -1
277 property var extendedData: menuData && menuData.ext || undefined
278 // TODO - bug #1260728
279 property var timeFormatter: Utils.GDateTimeFormatter {
280 time: getExtendedProperty(extendedData, "xCanonicalTime", 0)
281 format: getExtendedProperty(extendedData, "xCanonicalTimeFormat", "")
284 text: menuData && menuData.label || ""
285 iconSource: menuData && menuData.icon || "image://theme/calendar"
286 time: timeFormatter.timeString
287 eventColor: getExtendedProperty(extendedData, "xCanonicalColor", Qt.rgba(0.0, 0.0, 0.0, 0.0))
288 enabled: menuData && menuData.sensitive || false
290 onMenuModelChanged: {
293 onMenuIndexChanged: {
297 menuModel.activate(menuIndex);
300 function loadAttributes() {
301 if (!menuModel || menuIndex == -1) return;
302 menuModel.loadExtendedAttributes(menuIndex, {'x-canonical-color': 'string',
303 'x-canonical-time': 'int64',
304 'x-canonical-time-format': 'string'});
313 objectName: "wifiSection"
314 property QtObject menuData: null
315 property var menuModel: menuFactory.menuModel
316 property int menuIndex: -1
317 property var extendedData: menuData && menuData.ext || undefined
319 text: menuData && menuData.label || ""
320 busy: getExtendedProperty(extendedData, "xCanonicalBusyAction", false)
322 onMenuModelChanged: {
325 onMenuIndexChanged: {
329 function loadAttributes() {
330 if (!menuModel || menuIndex == -1) return;
331 menuModel.loadExtendedAttributes(menuIndex, {'x-canonical-busy-action': 'bool'})
339 Menus.AccessPointMenu {
340 objectName: "accessPoint"
341 property QtObject menuData: null
342 property var menuModel: menuFactory.menuModel
343 property int menuIndex: -1
344 property var extendedData: menuData && menuData.ext || undefined
346 property var strengthAction: UnityMenuAction {
349 name: getExtendedProperty(extendedData, "xCanonicalWifiApStrengthAction", "")
352 text: menuData && menuData.label || ""
353 enabled: menuData && menuData.sensitive || false
354 checked: menuData && menuData.isToggled || false
355 secure: getExtendedProperty(extendedData, "xCanonicalWifiApIsSecure", false)
356 adHoc: getExtendedProperty(extendedData, "xCanonicalWifiApIsAdhoc", false)
357 signalStrength: strengthAction.valid ? strengthAction.state : 0
359 onMenuModelChanged: {
362 onMenuIndexChanged: {
366 menuModel.activate(menuIndex);
369 function loadAttributes() {
370 if (!menuModel || menuIndex == -1) return;
371 menuModel.loadExtendedAttributes(menuIndex, {'x-canonical-wifi-ap-is-adhoc': 'bool',
372 'x-canonical-wifi-ap-is-secure': 'bool',
373 'x-canonical-wifi-ap-strength-action': 'string'});
381 objectName: "modemInfoItem"
382 property QtObject menuData: null
383 property var menuModel: menuFactory.menuModel
384 property int menuIndex: -1
385 property var extendedData: menuData && menuData.ext || undefined
387 property var statusLabelAction: UnityMenuAction {
390 name: getExtendedProperty(extendedData, "xCanonicalModemStatusLabelAction", "")
392 statusText: statusLabelAction.valid ? statusLabelAction.state : ""
394 property var statusIconAction: UnityMenuAction {
397 name: getExtendedProperty(extendedData, "xCanonicalModemStatusIconAction", "")
399 statusIcon: statusIconAction.valid ? statusIconAction.state : ""
401 property var connectivityIconAction: UnityMenuAction {
404 name: getExtendedProperty(extendedData, "xCanonicalModemConnectivityIconAction", "")
406 connectivityIcon: connectivityIconAction.valid ? connectivityIconAction.state : ""
408 property var simIdentifierLabelAction: UnityMenuAction {
411 name: getExtendedProperty(extendedData, "xCanonicalModemSimIdentifierLabelAction", "")
413 simIdentifierText: simIdentifierLabelAction.valid ? simIdentifierLabelAction.state : ""
415 property var roamingAction: UnityMenuAction {
418 name: getExtendedProperty(extendedData, "xCanonicalModemRoamingAction", "")
420 roaming: roamingAction.valid ? roamingAction.state : false
422 property var unlockAction: UnityMenuAction {
425 name: getExtendedProperty(extendedData, "xCanonicalModemLockedAction", "")
428 unlockAction.activate();
430 locked: unlockAction.valid ? unlockAction.state : false
432 onMenuModelChanged: {
435 onMenuIndexChanged: {
439 function loadAttributes() {
440 if (!menuModel || menuIndex == -1) return;
441 menuModel.loadExtendedAttributes(menuIndex, {'x-canonical-modem-status-label-action': 'string',
442 'x-canonical-modem-status-icon-action': 'string',
443 'x-canonical-modem-connectivity-icon-action': 'string',
444 'x-canonical-modem-sim-identifier-label-action': 'string',
445 'x-canonical-modem-roaming-action': 'string',
446 'x-canonical-modem-locked-action': 'string'});
454 MessageMenuItemFactory {
455 objectName: "messageItem"
456 menuModel: menuFactory.menuModel
463 Menus.GroupedMessageMenu {
464 objectName: "groupedMessage"
465 property QtObject menuData: null
466 property var menuModel: menuFactory.menuModel
467 property int menuIndex: -1
468 property var extendedData: menuData && menuData.ext || undefined
470 text: menuData && menuData.label || ""
471 iconSource: getExtendedProperty(extendedData, "icon", "qrc:/indicators/artwork/messaging/default_app.svg")
472 count: menuData && menuData.actionState.length > 0 ? menuData.actionState[0] : "0"
473 enabled: menuData && menuData.sensitive || false
476 onMenuModelChanged: {
479 onMenuIndexChanged: {
483 menuModel.activate(menuIndex, true);
486 menuModel.activate(menuIndex, false);
489 function loadAttributes() {
490 if (!menuModel || menuIndex == -1) return;
491 menuModel.loadExtendedAttributes(modelIndex, {'icon': 'icon'});
499 Menus.MediaPlayerMenu {
500 objectName: "mediaPayerMenu"
501 property QtObject menuData: null
502 property var menuModel: menuFactory.menuModel
503 property int menuIndex: -1
504 property var actionState: menuData && menuData.actionState || undefined
506 playerIcon: menuData && menuData.icon || ""
507 playerName: menuData && menuData.label || ""
509 albumArt: getExtendedProperty(actionState, "art-url", "")
510 song: getExtendedProperty(actionState, "title", "unknown")
511 artist: getExtendedProperty(actionState, "artist", "unknown")
512 album: getExtendedProperty(actionState, "album", "unknown")
513 running: getExtendedProperty(actionState, "running", false)
514 state: getExtendedProperty(actionState, "state", "")
515 enabled: menuData && menuData.sensitive || false
518 model.activate(modelIndex);
524 id: playbackItemMenu;
526 Menus.PlaybackItemMenu {
527 objectName: "playbackItemMenu"
528 property QtObject menuData: null
529 property var menuModel: menuFactory.menuModel
530 property int menuIndex: -1
531 property var extendedData: menuData && menuData.ext || undefined
533 property var playAction: UnityMenuAction {
536 name: getExtendedProperty(extendedData, "xCanonicalPlayAction", "")
538 property var nextAction: UnityMenuAction {
541 name: getExtendedProperty(extendedData, "xCanonicalNextAction", "")
543 property var previousAction: UnityMenuAction {
546 name: getExtendedProperty(extendedData, "xCanonicalPreviousAction", "")
549 playing: playAction.state === "Playing"
550 canPlay: playAction.valid
551 canGoNext: nextAction.valid
552 canGoPrevious: previousAction.valid
553 enabled: menuData && menuData.sensitive || false
556 playAction.activate();
559 nextAction.activate();
562 previousAction.activate();
564 onMenuModelChanged: {
567 onMenuIndexChanged: {
571 function loadAttributes() {
572 if (!menuModel || menuIndex == -1) return;
573 menuModel.loadExtendedAttributes(modelIndex, {'x-canonical-play-action': 'string',
574 'x-canonical-next-action': 'string',
575 'x-canonical-previous-action': 'string'});
584 objectName: "transferMenu"
586 property QtObject menuData: null
587 property var menuModel: menuFactory.menuModel
588 property int menuIndex: -1
589 property var extendedData: menuData && menuData.ext || undefined
590 property var uid: getExtendedProperty(extendedData, "xCanonicalUid", undefined)
592 text: menuData && menuData.label || ""
593 iconSource: menuData && menuData.icon || ""
595 enabled: menuData && menuData.sensitive || false
602 busName: rootModel.busName
603 objectPath: rootModel.actions["indicator"]
605 property var activateAction: action("activate-transfer")
606 property var cancelAction: action("cancel-transfer")
607 property var transferStateAction: uid !== undefined ? action("transfer-state."+uid) : null
609 Component.onCompleted: actionGroup.start()
612 property var transferState: {
613 if (actionGroup.transferStateAction === null) return undefined;
614 return actionGroup.transferStateAction.valid ? actionGroup.transferStateAction.state : undefined
617 property var runningState : transferState !== undefined ? transferState["state"] : undefined
618 property var secondsLeft : transferState !== undefined ? transferState["seconds-left"] : undefined
620 active: runningState !== undefined && runningState !== Menus.TransferState.Finished
621 progress: transferState !== undefined ? transferState["percent"] : 0.0
623 // TODO - Should be in the SDK
624 property var timeRemaining: {
625 if (secondsLeft === undefined) return undefined;
628 var hours = Math.floor(secondsLeft / (60 * 60));
629 var minutes = Math.floor(secondsLeft / 60) % 60;
630 var seconds = secondsLeft % 60;
632 remaining += hours + (hours == 1 ? " hour" : " hours");
635 if (remaining != "") remaining += ", ";
636 remaining += minutes + (minutes == 1 ? " minute" : " minutes");
638 // don't include seconds if hours > 0
639 if (hours == 0 && minutes < 5 && seconds > 0) {
640 if (remaining != "") remaining += ", ";
641 remaining += seconds + (seconds == 1 ? " second" : " seconds");
644 remaining = "0 seconds";
645 return remaining + " remaining";
649 switch (runningState) {
650 case Menus.TransferState.Queued:
651 return i18n.tr("In queue…");
652 case Menus.TransferState.Hashing:
653 case Menus.TransferState.Processing:
654 case Menus.TransferState.Running:
655 return timeRemaining === undefined ? i18n.tr("Downloading") : timeRemaining;
656 case Menus.TransferState.Paused:
657 return i18n.tr("Paused, tap to resume");
658 case Menus.TransferState.Canceled:
659 return i18n.tr("Canceled");
660 case Menus.TransferState.Finished:
661 return i18n.tr("Finished");
662 case Menus.TransferState.Error:
663 return i18n.tr("Failed, tap to retry");
668 onMenuModelChanged: {
671 onMenuIndexChanged: {
675 actionGroup.activateAction.activate(uid);
678 actionGroup.cancelAction.activate(uid);
681 function loadAttributes() {
682 if (!menuModel || menuIndex == -1) return;
683 menuModel.loadExtendedAttributes(menuIndex, {'x-canonical-uid': 'string'});
689 id: buttonSectionMenu;
692 objectName: "buttonSectionMenu"
693 property QtObject menuData: null
694 property var menuModel: menuFactory.menuModel
695 property int menuIndex: -1
696 property var extendedData: menuData && menuData.ext || undefined
698 iconSource: menuData && menuData.icon || ""
699 enabled: menuData && menuData.sensitive || false
700 text: menuData && menuData.label || ""
703 onMenuModelChanged: {
706 onMenuIndexChanged: {
709 function loadAttributes() {
710 if (!menuModel || menuIndex == -1) return;
711 menuModel.loadExtendedAttributes(menuIndex, {'x-canonical-extra-label': 'string'});
715 text: getExtendedProperty(extendedData, "xCanonicalExtraLabel", "")
718 menuModel.activate(menuIndex);
724 function load(modelData) {
725 if (modelData.type !== undefined) {
726 var component = _map[modelData.type];
727 if (component !== undefined) {
731 if (modelData.isCheck || modelData.isRadio) {
732 return checkableMenu;
734 if (modelData.isSeparator) {
735 return separatorMenu;