2 * Copyright 2013,2015 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/>.
18import Ubuntu.Settings.Menus 0.1 as Menus
19import Ubuntu.Settings.Components 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
29 property var rootModel: null
30 property var menuModel: null
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
68 "indicator-messages" : {
69 "com.canonical.indicator.button" : messagesButtonMenu
73 function getExtendedProperty(object, propertyName, defaultValue) {
74 if (object && object.hasOwnProperty(propertyName)) {
75 return object[propertyName];
84 objectName: "separatorMenu"
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)
107 var maximum = getExtendedProperty(extendedData, "maxValue", 1.0);
108 if (maximum <= minimumValue) {
109 return minimumValue + 1;
113 enabled: menuData && menuData.sensitive || false
114 highlightWhenPressed: false
116 onMenuModelChanged: {
119 onMenuIndexChanged: {
123 function loadAttributes() {
124 if (!menuModel || menuIndex == -1) return;
125 menuModel.loadExtendedAttributes(menuIndex, {'min-value': 'double',
126 'max-value': 'double',
128 'max-icon': 'icon'});
131 ServerPropertySynchroniser {
133 syncTimeout: Utils.Constants.indicatorValueTimeout
134 bufferedSyncTimeout: true
135 maximumWaitBufferInterval: 16
137 serverTarget: sliderItem
138 serverProperty: "serverValue"
139 userTarget: sliderItem
140 userProperty: "value"
142 onSyncTriggered: menuModel.changeState(menuIndex, value)
151 objectName: "buttonMenu"
152 property QtObject menuData: null
153 property var menuModel: menuFactory.menuModel
154 property int menuIndex: -1
156 buttonText: menuData && menuData.label || ""
157 enabled: menuData && menuData.sensitive || false
158 highlightWhenPressed: false
161 menuModel.activate(menuIndex);
167 id: messagesButtonMenu;
170 objectName: "messagesButtonMenu"
171 property QtObject menuData: null
172 property var menuModel: menuFactory.menuModel
173 property int menuIndex: -1
175 implicitHeight: units.gu(5)
176 enabled: menuData && menuData.sensitive || false
180 text: menuData && menuData.label || ""
181 anchors.centerIn: parent
187 fill: buttonMenuLabel
188 margins: units.gu(-1)
190 onClicked: menuModel.activate(menuIndex);
199 objectName: "sectionMenu"
200 property QtObject menuData: null
201 property var menuIndex: undefined
203 text: menuData && menuData.label || ""
211 Menus.ProgressValueMenu {
212 objectName: "progressMenu"
213 property QtObject menuData: null
214 property int menuIndex: -1
216 text: menuData && menuData.label || ""
217 iconSource: menuData && menuData.icon || ""
218 value : menuData && menuData.actionState || 0.0
219 enabled: menuData && menuData.sensitive || false
220 highlightWhenPressed: false
228 objectName: "standardMenu"
229 property QtObject menuData: null
230 property int menuIndex: -1
232 text: menuData && menuData.label || ""
233 iconSource: menuData && menuData.icon || ""
234 enabled: menuData && menuData.sensitive || false
235 highlightWhenPressed: false
238 menuModel.activate(menuIndex);
241 // FIXME : At the moment, the indicators aren't using
242 // com.canonical.indicators.link for settings menu. Need to fudge it.
243 property bool settingsMenu: menuData && menuData.action.indexOf("settings") > -1 || false
244 backColor: settingsMenu ? Qt.rgba(1,1,1,0.07) : "transparent"
245 component: settingsMenu ? buttonForSettings : undefined
247 id: buttonForSettings
252 color: theme.palette.selected.backgroundText
262 objectName: "linkMenu"
263 property QtObject menuData: null
264 property int menuIndex: -1
266 text: menuData && menuData.label || ""
267 iconSource: menuData && menuData.icon || ""
268 enabled: menuData && menuData.sensitive || false
269 highlightWhenPressed: false
272 menuModel.activate(menuIndex);
275 backColor: Qt.rgba(1,1,1,0.07)
277 component: menuData.icon ? icon : undefined
281 source: menuData.icon
284 color: theme.palette.selected.backgroundText
293 Menus.CheckableMenu {
295 objectName: "checkableMenu"
296 property QtObject menuData: null
297 property int menuIndex: -1
298 property bool serverChecked: menuData && menuData.isToggled || false
300 text: menuData && menuData.label || ""
301 enabled: menuData && menuData.sensitive || false
302 checked: serverChecked
303 highlightWhenPressed: false
305 ServerPropertySynchroniser {
307 syncTimeout: Utils.Constants.indicatorValueTimeout
309 serverTarget: checkItem
310 serverProperty: "serverChecked"
311 userTarget: checkItem
312 userProperty: "checked"
314 onSyncTriggered: menuModel.activate(checkItem.menuIndex)
324 objectName: "switchMenu"
325 property QtObject menuData: null
326 property int menuIndex: -1
327 property bool serverChecked: menuData && menuData.isToggled || false
329 text: menuData && menuData.label || ""
330 iconSource: menuData && menuData.icon || ""
331 enabled: menuData && menuData.sensitive || false
332 checked: serverChecked
333 highlightWhenPressed: false
335 ServerPropertySynchroniser {
337 syncTimeout: Utils.Constants.indicatorValueTimeout
339 serverTarget: switchItem
340 serverProperty: "serverChecked"
341 userTarget: switchItem
342 userProperty: "checked"
344 onSyncTriggered: menuModel.activate(switchItem.menuIndex);
354 objectName: "alarmMenu"
355 property QtObject menuData: null
356 property var menuModel: menuFactory.menuModel
357 property int menuIndex: -1
358 property var extendedData: menuData && menuData.ext || undefined
360 property date serverTime: new Date(getExtendedProperty(extendedData, "xCanonicalTime", 0) * 1000)
362 frequency: LiveTimer.Relative
363 relativeTime: alarmItem.serverTime
364 onTrigger: alarmItem.serverTime = new Date(getExtendedProperty(extendedData, "xCanonicalTime", 0) * 1000)
367 text: menuData && menuData.label || ""
368 iconSource: menuData && menuData.icon || "image://theme/alarm-clock"
369 time: i18n.relativeDateTime(serverTime)
370 enabled: menuData && menuData.sensitive || false
371 highlightWhenPressed: false
373 onMenuModelChanged: {
376 onMenuIndexChanged: {
380 menuModel.activate(menuIndex);
383 function loadAttributes() {
384 if (!menuModel || menuIndex == -1) return;
385 menuModel.loadExtendedAttributes(menuIndex, {'x-canonical-time': 'int64'});
395 objectName: "appointmentMenu"
396 property QtObject menuData: null
397 property var menuModel: menuFactory.menuModel
398 property int menuIndex: -1
399 property var extendedData: menuData && menuData.ext || undefined
401 property date serverTime: new Date(getExtendedProperty(extendedData, "xCanonicalTime", 0) * 1000)
403 frequency: LiveTimer.Relative
404 relativeTime: appointmentItem.serverTime
405 onTrigger: appointmentItem.serverTime = new Date(getExtendedProperty(extendedData, "xCanonicalTime", 0) * 1000)
408 text: menuData && menuData.label || ""
409 iconSource: menuData && menuData.icon || "image://theme/calendar"
410 time: i18n.relativeDateTime(serverTime)
411 eventColor: getExtendedProperty(extendedData, "xCanonicalColor", Qt.rgba(0.0, 0.0, 0.0, 0.0))
412 enabled: menuData && menuData.sensitive || false
413 highlightWhenPressed: false
415 onMenuModelChanged: {
418 onMenuIndexChanged: {
422 menuModel.activate(menuIndex);
425 function loadAttributes() {
426 if (!menuModel || menuIndex == -1) return;
427 menuModel.loadExtendedAttributes(menuIndex, {'x-canonical-color': 'string',
428 'x-canonical-time': 'int64'});
436 Menus.UserSessionMenu {
437 objectName: "userSessionMenu"
438 highlightWhenPressed: false
440 property QtObject menuData: null
441 property var menuModel: menuFactory.menuModel
442 property int menuIndex: -1
444 name: menuData && menuData.label || "" // label is the user's real name
445 iconSource: menuData && menuData.icon || ""
447 // would be better to compare with the logname but sadly the indicator doesn't expose that
448 active: DBusUnitySessionService.RealName() !== "" ? DBusUnitySessionService.RealName() == name
449 : DBusUnitySessionService.UserName() == name
452 menuModel.activate(menuIndex);
461 objectName: "calendarMenu"
462 highlightWhenPressed: false
472 objectName: "timezoneMenu"
474 property QtObject menuData: null
475 property var menuModel: menuFactory.menuModel
476 property int menuIndex: -1
477 property var extendedData: menuData && menuData.ext || undefined
478 readonly property string tz: getExtendedProperty(extendedData, "xCanonicalTimezone", "UTC")
479 property var updateTimer: Timer {
481 running: tzMenuItem.visible // only run when we're open
482 onTriggered: tzMenuItem.time = Utils.TimezoneFormatter.currentTimeInTimezone(tzMenuItem.tz)
485 city: menuData && menuData.label || ""
486 time: Utils.TimezoneFormatter.currentTimeInTimezone(tz)
487 enabled: menuData && menuData.sensitive || false
489 onMenuModelChanged: {
492 onMenuIndexChanged: {
496 tzActionGroup.setLocation.activate(tz);
501 busType: DBus.SessionBus
502 busName: "com.canonical.indicator.datetime"
503 objectPath: "/com/canonical/indicator/datetime"
505 property variant setLocation: action("set-location")
507 Component.onCompleted: tzActionGroup.start()
510 function loadAttributes() {
511 if (!menuModel || menuIndex == -1) return;
512 menuModel.loadExtendedAttributes(menuIndex, {'x-canonical-timezone': 'string'});
521 objectName: "wifiSection"
522 property QtObject menuData: null
523 property var menuModel: menuFactory.menuModel
524 property int menuIndex: -1
525 property var extendedData: menuData && menuData.ext || undefined
527 text: menuData && menuData.label || ""
528 busy: getExtendedProperty(extendedData, "xCanonicalBusyAction", false)
530 onMenuModelChanged: {
533 onMenuIndexChanged: {
537 function loadAttributes() {
538 if (!menuModel || menuIndex == -1) return;
539 menuModel.loadExtendedAttributes(menuIndex, {'x-canonical-busy-action': 'bool'})
547 Menus.AccessPointMenu {
549 objectName: "accessPoint"
550 property QtObject menuData: null
551 property var menuModel: menuFactory.menuModel
552 property int menuIndex: -1
553 property var extendedData: menuData && menuData.ext || undefined
554 property bool serverChecked: menuData && menuData.isToggled || false
556 property var strengthAction: UnityMenuAction {
559 name: getExtendedProperty(extendedData, "xCanonicalWifiApStrengthAction", "")
562 text: menuData && menuData.label || ""
563 enabled: menuData && menuData.sensitive || false
564 active: serverChecked
565 secure: getExtendedProperty(extendedData, "xCanonicalWifiApIsSecure", false)
566 adHoc: getExtendedProperty(extendedData, "xCanonicalWifiApIsAdhoc", false)
567 signalStrength: strengthAction.valid ? strengthAction.state : 0
568 highlightWhenPressed: false
570 onMenuModelChanged: {
573 onMenuIndexChanged: {
577 function loadAttributes() {
578 if (!menuModel || menuIndex == -1) return;
579 menuModel.loadExtendedAttributes(menuIndex, {'x-canonical-wifi-ap-is-adhoc': 'bool',
580 'x-canonical-wifi-ap-is-secure': 'bool',
581 'x-canonical-wifi-ap-strength-action': 'string'});
584 ServerPropertySynchroniser {
586 syncTimeout: Utils.Constants.indicatorValueTimeout
589 serverProperty: "serverChecked"
591 userProperty: "active"
592 userTrigger: "onTriggered"
594 onSyncTriggered: menuModel.activate(apItem.menuIndex)
602 objectName: "modemInfoItem"
603 property QtObject menuData: null
604 property var menuModel: menuFactory.menuModel
605 property int menuIndex: -1
606 property var extendedData: menuData && menuData.ext || undefined
607 highlightWhenPressed: false
609 property var statusLabelAction: UnityMenuAction {
612 name: getExtendedProperty(extendedData, "xCanonicalModemStatusLabelAction", "")
614 statusText: statusLabelAction.valid ? statusLabelAction.state : ""
616 property var statusIconAction: UnityMenuAction {
619 name: getExtendedProperty(extendedData, "xCanonicalModemStatusIconAction", "")
621 statusIcon: statusIconAction.valid ? statusIconAction.state : ""
623 property var connectivityIconAction: UnityMenuAction {
626 name: getExtendedProperty(extendedData, "xCanonicalModemConnectivityIconAction", "")
628 connectivityIcon: connectivityIconAction.valid ? connectivityIconAction.state : ""
630 property var simIdentifierLabelAction: UnityMenuAction {
633 name: getExtendedProperty(extendedData, "xCanonicalModemSimIdentifierLabelAction", "")
635 simIdentifierText: simIdentifierLabelAction.valid ? simIdentifierLabelAction.state : ""
637 property var roamingAction: UnityMenuAction {
640 name: getExtendedProperty(extendedData, "xCanonicalModemRoamingAction", "")
642 roaming: roamingAction.valid ? roamingAction.state : false
644 property var unlockAction: UnityMenuAction {
647 name: getExtendedProperty(extendedData, "xCanonicalModemLockedAction", "")
650 unlockAction.activate();
652 locked: unlockAction.valid ? unlockAction.state : false
654 onMenuModelChanged: {
657 onMenuIndexChanged: {
661 function loadAttributes() {
662 if (!menuModel || menuIndex == -1) return;
663 menuModel.loadExtendedAttributes(menuIndex, {'x-canonical-modem-status-label-action': 'string',
664 'x-canonical-modem-status-icon-action': 'string',
665 'x-canonical-modem-connectivity-icon-action': 'string',
666 'x-canonical-modem-sim-identifier-label-action': 'string',
667 'x-canonical-modem-roaming-action': 'string',
668 'x-canonical-modem-locked-action': 'string'});
676 MessageMenuItemFactory {
677 objectName: "messageItem"
678 menuModel: menuFactory.menuModel
685 Menus.GroupedMessageMenu {
686 objectName: "groupedMessage"
687 property QtObject menuData: null
688 property var menuModel: menuFactory.menuModel
689 property int menuIndex: -1
690 property var extendedData: menuData && menuData.ext || undefined
692 text: menuData && menuData.label || ""
693 iconSource: getExtendedProperty(extendedData, "icon", "image://theme/message")
694 count: menuData && menuData.actionState.length > 0 ? menuData.actionState[0] : "0"
695 enabled: menuData && menuData.sensitive || false
696 highlightWhenPressed: false
699 onMenuModelChanged: {
702 onMenuIndexChanged: {
706 menuModel.activate(menuIndex, true);
709 menuModel.activate(menuIndex, false);
712 function loadAttributes() {
713 if (!menuModel || menuIndex == -1) return;
714 menuModel.loadExtendedAttributes(modelIndex, {'icon': 'icon'});
722 Menus.MediaPlayerMenu {
723 objectName: "mediaPayerMenu"
724 property QtObject menuData: null
725 property var menuModel: menuFactory.menuModel
726 property int menuIndex: -1
727 property var actionState: menuData && menuData.actionState || undefined
728 property bool running: getExtendedProperty(actionState, "running", false)
730 playerIcon: menuData && menuData.icon || "image://theme/stock_music"
731 playerName: menuData && menuData.label || i18n.tr("Nothing is playing")
733 albumArt: getExtendedProperty(actionState, "art-url", "image://theme/stock_music")
734 song: getExtendedProperty(actionState, "title", "")
735 artist: getExtendedProperty(actionState, "artist", "")
736 album: getExtendedProperty(actionState, "album", "")
737 showTrack: running && (state == "Playing" || state == "Paused")
738 state: getExtendedProperty(actionState, "state", "")
739 enabled: menuData && menuData.sensitive || false
740 highlightWhenPressed: false
744 model.activate(modelIndex);
750 id: playbackItemMenu;
752 Menus.PlaybackItemMenu {
753 objectName: "playbackItemMenu"
754 property QtObject menuData: null
755 property var menuModel: menuFactory.menuModel
756 property int menuIndex: -1
757 property var extendedData: menuData && menuData.ext || undefined
759 property var playAction: UnityMenuAction {
762 name: getExtendedProperty(extendedData, "xCanonicalPlayAction", "")
764 property var nextAction: UnityMenuAction {
767 name: getExtendedProperty(extendedData, "xCanonicalNextAction", "")
769 property var previousAction: UnityMenuAction {
772 name: getExtendedProperty(extendedData, "xCanonicalPreviousAction", "")
775 playing: playAction.state === "Playing"
776 canPlay: playAction.valid
777 canGoNext: nextAction.valid
778 canGoPrevious: previousAction.valid
779 enabled: menuData && menuData.sensitive || false
780 highlightWhenPressed: false
783 playAction.activate();
786 nextAction.activate();
789 previousAction.activate();
791 onMenuModelChanged: {
794 onMenuIndexChanged: {
798 function loadAttributes() {
799 if (!menuModel || menuIndex == -1) return;
800 menuModel.loadExtendedAttributes(modelIndex, {'x-canonical-play-action': 'string',
801 'x-canonical-next-action': 'string',
802 'x-canonical-previous-action': 'string'});
811 objectName: "transferMenu"
813 property QtObject menuData: null
814 property var menuModel: menuFactory.menuModel
815 property int menuIndex: -1
816 property var extendedData: menuData && menuData.ext || undefined
817 property var uid: getExtendedProperty(extendedData, "xCanonicalUid", undefined)
819 text: menuData && menuData.label || ""
820 iconSource: menuData && menuData.icon || "image://theme/transfer-none"
822 enabled: menuData && menuData.sensitive || false
823 highlightWhenPressed: false
830 busName: rootModel.busName
831 objectPath: rootModel.actions["indicator"]
833 property var activateAction: action("activate-transfer")
834 property var cancelAction: action("cancel-transfer")
835 property var transferStateAction: uid !== undefined ? action("transfer-state."+uid) : null
837 Component.onCompleted: actionGroup.start()
840 property var transferState: {
841 if (actionGroup.transferStateAction === null) return undefined;
842 return actionGroup.transferStateAction.valid ? actionGroup.transferStateAction.state : undefined
845 property var runningState : transferState !== undefined ? transferState["state"] : undefined
846 property var secondsLeft : transferState !== undefined ? transferState["seconds-left"] : undefined
848 active: runningState !== undefined && runningState !== Menus.TransferState.Finished
849 progress: transferState !== undefined ? transferState["percent"] : 0.0
851 // TODO - Should be in the SDK
852 property var timeRemaining: {
853 if (secondsLeft === undefined) return undefined;
856 var hours = Math.floor(secondsLeft / (60 * 60));
857 var minutes = Math.floor(secondsLeft / 60) % 60;
858 var seconds = secondsLeft % 60;
860 remaining += i18n.tr("%1 hour", "%1 hours", hours).arg(hours)
863 if (remaining != "") remaining += ", ";
864 remaining += i18n.tr("%1 minute", "%1 minutes", minutes).arg(minutes)
866 // don't include seconds if hours > 0
867 if (hours == 0 && minutes < 5 && seconds > 0) {
868 if (remaining != "") remaining += ", ";
869 remaining += i18n.tr("%1 second", "%1 seconds", seconds).arg(seconds)
872 remaining = i18n.tr("0 seconds");
873 // Translators: String like "1 hour, 2 minutes, 3 seconds remaining"
874 return i18n.tr("%1 remaining").arg(remaining);
878 switch (runningState) {
879 case Menus.TransferState.Queued:
880 return i18n.tr("In queue…");
881 case Menus.TransferState.Hashing:
882 case Menus.TransferState.Processing:
883 case Menus.TransferState.Running:
884 return timeRemaining === undefined ? i18n.tr("Downloading") : timeRemaining;
885 case Menus.TransferState.Paused:
886 return i18n.tr("Paused, tap to resume");
887 case Menus.TransferState.Canceled:
888 return i18n.tr("Canceled");
889 case Menus.TransferState.Finished:
890 return i18n.tr("Finished");
891 case Menus.TransferState.Error:
892 return i18n.tr("Failed, tap to retry");
897 onMenuModelChanged: {
900 onMenuIndexChanged: {
904 actionGroup.activateAction.activate(uid);
907 actionGroup.cancelAction.activate(uid);
910 function loadAttributes() {
911 if (!menuModel || menuIndex == -1) return;
912 menuModel.loadExtendedAttributes(menuIndex, {'x-canonical-uid': 'string'});
918 id: buttonSectionMenu;
921 objectName: "buttonSectionMenu"
922 property QtObject menuData: null
923 property var menuModel: menuFactory.menuModel
924 property int menuIndex: -1
925 property var extendedData: menuData && menuData.ext || undefined
927 iconSource: menuData && menuData.icon || ""
928 enabled: menuData && menuData.sensitive || false
929 highlightWhenPressed: false
930 text: menuData && menuData.label || ""
931 foregroundColor: theme.palette.normal.backgroundText
933 onMenuModelChanged: {
936 onMenuIndexChanged: {
939 function loadAttributes() {
940 if (!menuModel || menuIndex == -1) return;
941 menuModel.loadExtendedAttributes(menuIndex, {'x-canonical-extra-label': 'string'});
944 component: Component {
946 objectName: "buttonSectionMenuControl"
947 text: getExtendedProperty(extendedData, "xCanonicalExtraLabel", "")
950 menuModel.activate(menuIndex);
957 function load(modelData, context) {
958 if (modelData.type !== undefined && modelData.type !== "") {
959 var component = undefined;
961 var contextComponents = _map[context];
962 if (contextComponents !== undefined) {
963 component = contextComponents[modelData.type];
966 if (component === undefined) {
967 component = _map["default"][modelData.type];
969 if (component !== undefined) {
972 console.debug("Don't know how to make " + modelData.type + " for " + context);
974 if (modelData.isCheck || modelData.isRadio) {
975 return checkableMenu;
977 if (modelData.isSeparator) {
978 return separatorMenu;
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list