on xenial help sign in
app & touch menu tweaks
commit3281137efb7f861e2e7d27e01a6805aa322eddd3 authorNick Dedekind <nick.dedekind@canonical.com> dateTue 4 Oct 2016, 12:44 (10 years ago) parent38c91bc
11 files changed+236−144
qml/ApplicationMenus/ApplicationMenuItemFactory.qml+135 qml/ApplicationMenus/MenuBarLoader.qml+4−4 qml/ApplicationMenus/MenuItemLoader.qml+8−5 qml/ApplicationMenus/MenuLoader.qml+7−1 qml/Panel/Indicators/MenuItemFactory.qml → qml/Panel/Indicators/IndicatorMenuItemFactory.qml+1−86 qml/Panel/MenuContent.qml−1 qml/Panel/Panel.qml+11−3 qml/Panel/PanelMenuPage.qml+37−23 tests/qmltests/Panel/Indicators/tst_MenuItemFactory.qml → tests/qmltests/Panel/Indicators/tst_IndicatorMenuItemFactory.qml+2−2 tests/qmltests/Panel/tst_Panel.qml+18−6 tests/qmltests/Stages/DesktopMenuData.qml+13−13
qml/ApplicationMenus/ApplicationMenuItemFactory.qmlnew file+135
@@ -0,0 +1,135 @@
1+/*
2+ * Copyright 2016 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+ */
16+
17+import QtQuick 2.4
18+import Ubuntu.Settings.Menus 0.1 as Menus
19+import Ubuntu.Settings.Components 0.1
20+import QMenuModel 0.1
21+import Utils 0.1 as Utils
22+import Ubuntu.Components.ListItems 1.3 as ListItems
23+import Ubuntu.Components 1.3
24+
25+Object {
26+ id: menuFactory
27+
28+ property string context
29+ property var rootModel: null
30+ property var menuModel: null
31+
32+ Component {
33+ id: applicationMenu;
34+
35+ ListItem {
36+ property QtObject menuData: null
37+ property int menuIndex: -1
38+
39+ height: layout.height
40+ enabled: menuData && menuData.sensitive || false
41+ divider.visible: false
42+
43+ onClicked: {
44+ menuModel.activate(menuIndex);
45+ }
46+
47+ Action {
48+ id: action
49+ text: menuData.label.replace("_", "&")
50+ }
51+
52+ ListItemLayout {
53+ id: layout
54+ title.text: action.text
55+
56+ Icon {
57+ source: menuData && menuData.icon || ""
58+ SlotsLayout.position: SlotsLayout.Leading
59+ height: units.gu(3)
60+ }
61+
62+ Label {
63+ text: menuData.shortcut
64+ visible: menuData.shortcut && QuickUtils.keyboardAttached
65+ SlotsLayout.position: SlotsLayout.Trailing
66+ color: enabled ? theme.palette.normal.backgroundSecondaryText :
67+ theme.palette.disabled.backgroundSecondaryText
68+ }
69+ }
70+ }
71+ }
72+
73+ Component {
74+ id: submenu
75+
76+ ListItem {
77+ property QtObject menuData: null
78+ property int menuIndex: -1
79+
80+ height: layout.height
81+ enabled: menuData && menuData.sensitive || false
82+ divider.visible: false
83+
84+ onClicked: {
85+ menuModel.activate(menuIndex);
86+ }
87+
88+ Action {
89+ id: action
90+ text: menuData.label.replace("_", "&")
91+ }
92+
93+ ListItemLayout {
94+ id: layout
95+ title.text: action.text
96+
97+ Icon {
98+ source: menuData && menuData.icon || ""
99+ SlotsLayout.position: SlotsLayout.Leading
100+ height: units.gu(3)
101+ }
102+
103+ Icon {
104+ name: "toolkit_chevron-ltr_1gu"
105+ SlotsLayout.position: SlotsLayout.Trailing
106+ width: units.gu(2)
107+ color: enabled ? theme.palette.normal.backgroundSecondaryText :
108+ theme.palette.disabled.backgroundSecondaryText
109+ }
110+ }
111+ }
112+ }
113+
114+ Component {
115+ id: applicationMenuSeparator;
116+
117+ ListItems.Divider {
118+ }
119+ }
120+
121+ function load(modelData) {
122+ if (modelData.isSeparator) {
123+ return applicationMenuSeparator;
124+ }
125+ if (modelData.isRadio) {
126+ }
127+ if (modelData.isCheck) {
128+
129+ }
130+ if (modelData.hasSubmenu) {
131+ return submenu;
132+ }
133+ return applicationMenu;
134+ }
135+}
qml/ApplicationMenus/MenuBarLoader.qml+4−4
@@ -30,6 +30,9 @@ Item {
3030
3131 readonly property bool showRequested: altFilter.longAltPressed || d.currentItem != null
3232
33+ implicitWidth: row.width + units.gu(1)
34+ height: parent.height
35+
3336 WindowInputFilter {
3437 id: altFilter
3538 property bool altPressed: false
@@ -63,9 +66,6 @@ Item {
6366 }
6467 }
6568
66− implicitWidth: row.width + units.gu(1)
67− height: parent.height
68−
6969 InverseMouseArea {
7070 acceptedButtons: Qt.LeftButton | Qt.MiddleButton | Qt.RightButton
7171 anchors.fill: parent
@@ -80,7 +80,7 @@ Item {
8080 ActionContext {
8181 id: menuBarContext
8282 objectName: "menuBarContext"
83− active: d.currentItem == null && altFilter.altPressed
83+ active: true
8484 }
8585
8686 Row {
qml/ApplicationMenus/MenuItemLoader.qml+8−5
@@ -32,11 +32,10 @@ ActionItem {
3232 val += units.gu(1) + icon.width
3333 }
3434 val += units.gu(1) + title.contentWidth;
35− if (shortcut != undefined) {
36− val += units.gu(3) + shortcutLabel.contentWidth;
37− }
3835 if (hasSubmenu) {
3936 val += units.gu(1) + chevronIcon.width;
37+ } else if (shortcut != undefined) {
38+ val += units.gu(3) + shortcutLabel.contentWidth;
4039 }
4140 return val + units.gu(1);
4241 }
@@ -111,9 +110,11 @@ ActionItem {
111110 elide: Text.ElideNone
112111 wrapMode: Text.NoWrap
113112 clip: true
113+ color: enabled ? theme.palette.normal.backgroundSecondaryText :
114+ theme.palette.disabled.backgroundSecondaryText
114115
115− visible: root.shortcut != undefined
116− text: root.shortcut ? root.shortcut : ""
116+ visible: menuData.shortcut != undefined && !root.hasSubmenu && QuickUtils.keyboardAttached
117+ text: menuData.shortcut ? menuData.shortcut : ""
117118 }
118119 }
119120
@@ -121,6 +122,8 @@ ActionItem {
121122 id: chevronIcon
122123 width: units.gu(2)
123124 height: units.gu(2)
125+ color: enabled ? theme.palette.normal.backgroundSecondaryText :
126+ theme.palette.disabled.backgroundSecondaryText
124127
125128 visible: root.hasSubmenu
126129 name: "chevron"
qml/ApplicationMenus/MenuLoader.qml+7−1
@@ -133,6 +133,12 @@ UbuntuShape {
133133 }
134134 }
135135
136+ ActionContext {
137+ id: menuContext
138+ objectName: "menuContext"
139+ active: true
140+ }
141+
136142 ColumnLayout {
137143 id: container
138144 objectName: "container"
@@ -256,7 +262,7 @@ UbuntuShape {
256262
257263 property Item popup: null
258264
259− onTriggered: {
265+ action.onTriggered: {
260266 if (hasSubmenu) {
261267 if (!popup) {
262268 var model = root.unityMenuModel.submenu(__ownIndex);
qml/Panel/Indicators/MenuItemFactory.qml → qml/Panel/Indicators/IndicatorMenuItemFactory.qmlrenamed+1−86
@@ -25,7 +25,7 @@ import Ubuntu.Components 1.3
2525import Unity.Session 0.1
2626import Unity.Platform 1.0
2727
28−Item {
28+Object {
2929 id: menuFactory
3030
3131 property string context
@@ -1042,92 +1042,7 @@ Item {
10421042 }
10431043 }
10441044
1045− Component {
1046− id: applicationMenu;
1047−
1048− ListItem {
1049− property QtObject menuData: null
1050− property int menuIndex: -1
1051−
1052− height: layout.height
1053− enabled: menuData && menuData.sensitive || false
1054− divider.visible: false
1055−
1056− onClicked: {
1057− menuModel.activate(menuIndex);
1058− }
1059−
1060− ListItemLayout {
1061− id: layout
1062− title.text: menuData && menuData.label || ""
1063−
1064− Icon {
1065− source: menuData && menuData.icon || ""
1066− SlotsLayout.position: SlotsLayout.Leading
1067− height: units.gu(3)
1068− }
1069−
1070− }
1071− }
1072− }
1073−
1074− Component {
1075− id: submenu
1076−
1077− ListItem {
1078− property QtObject menuData: null
1079− property int menuIndex: -1
1080−
1081− height: layout.height
1082− enabled: menuData && menuData.sensitive || false
1083− divider.visible: false
1084−
1085− onClicked: {
1086− menuModel.activate(menuIndex);
1087− }
1088−
1089− ListItemLayout {
1090− id: layout
1091− title.text: menuData && menuData.label || ""
1092−
1093− Icon {
1094− source: menuData && menuData.icon || ""
1095− SlotsLayout.position: SlotsLayout.Leading
1096− height: units.gu(3)
1097− }
1098−
1099− Icon {
1100− name: "toolkit_chevron-ltr_1gu"
1101− SlotsLayout.position: SlotsLayout.Trailing
1102− width: units.gu(2)
1103− }
1104− }
1105− }
1106− }
1107−
1108− Component {
1109− id: applicationMenuSeparator;
1110−
1111− ListItems.Divider {
1112− }
1113− }
1114−
11151045 function load(modelData) {
1116− if (context == "application-menu") {
1117− if (modelData.isSeparator) {
1118− return applicationMenuSeparator;
1119− }
1120− if (modelData.isRadio) {
1121− }
1122− if (modelData.isCheck) {
1123−
1124− }
1125− if (modelData.hasSubmenu) {
1126− return submenu;
1127− }
1128− return applicationMenu;
1129− }
1130−
11311046 // tweak indicator-session items
11321047 if (context === "indicator-session") {
11331048 if ((modelData.action === "indicator.logout" || modelData.action === "indicator.suspend" || modelData.action === "indicator.hibernate" ||
qml/Panel/MenuContent.qml−1
@@ -61,7 +61,6 @@ Rectangle {
6161
6262 width: ListView.view.width
6363 height: ListView.view.height
64− objectName: item ? item.context : ""
6564 asynchronous: true
6665 visible: ListView.isCurrentItem
6766
qml/Panel/Panel.qml+11−3
@@ -199,9 +199,12 @@ Item {
199199
200200 pageDelegate: PanelMenuPage {
201201 id: page
202− context: "application-menu"
203202 menuModel: __applicationMenus.model
204203 submenuIndex: modelIndex
204+
205+ factory: ApplicationMenuItemFactory {
206+ rootModel: __applicationMenus.model
207+ }
205208 }
206209
207210 enabled: !root.locked && model
@@ -440,11 +443,16 @@ Item {
440443
441444 pageDelegate: PanelMenuPage {
442445 id: page
443− objectName: context + "-page"
444− context: modelData.identifier
446+ objectName: modelData.identifier + "-page"
445447 submenuIndex: 0
446448
447449 menuModel: delegate.menuModel
450+
451+ factory: IndicatorMenuItemFactory {
452+ context: modelData.identifier
453+ rootModel: delegate.menuModel
454+ }
455+
448456 IndicatorDelegate {
449457 id: delegate
450458 busName: modelData.indicatorProperties.busName
qml/Panel/PanelMenuPage.qml+37−23
@@ -1,5 +1,5 @@
11/*
2− * Copyright 2013-2014 Canonical Ltd.
2+ * Copyright 2013-2016 Canonical Ltd.
33 *
44 * This program is free software; you can redistribute it and/or modify
55 * it under the terms of the GNU Lesser General Public License as published by
@@ -25,26 +25,47 @@ PageStack {
2525 id: root
2626
2727 property var submenuIndex: undefined
28− property string context
2928 property QtObject menuModel: null
29+ property Component factory
3030
3131 Connections {
32+ id: dynamicChanges
3233 target: root.menuModel
34+ property bool ready: false
3335
3436 // fix async creation with signal from model before it's finished.
35− onRowsInserted: root.reset()
36− onRowsRemoved: root.reset()
37− onModelReset: root.reset()
37+ onRowsInserted: {
38+ if (submenuIndex !== undefined && first <= submenuIndex) {
39+ reset(true);
40+ }
41+ }
42+ onRowsRemoved: {
43+ if (submenuIndex !== undefined && first <= submenuIndex) {
44+ reset(true);
45+ }
46+ }
47+ onModelReset: {
48+ if (root.submenuIndex !== undefined) {
49+ reset(true);
50+ }
51+ }
3852 }
3953
4054 Component.onCompleted: {
41− reset();
55+ reset(true);
56+ dynamicChanges.ready = true;
4257 }
4358
44− function reset() {
45− clear();
46− var model = submenuIndex == undefined ? menuModel : menuModel.submenu(submenuIndex)
47− push(pageComponent, { "menuModel": model });
59+ function reset(clearModel) {
60+ if (clearModel) {
61+ clear();
62+ var model = submenuIndex == undefined ? menuModel : menuModel.submenu(submenuIndex)
63+ if (model) {
64+ push(pageComponent, { "menuModel": model });
65+ }
66+ } else {
67+ root.currentPage.reset();
68+ }
4869 }
4970
5071 Component {
@@ -56,13 +77,12 @@ PageStack {
5677 property alias title: backLabel.title
5778 property bool isSubmenu: false
5879
59− MenuItemFactory {
60− id: factory
61− context: root.context
62− rootModel: root.menuModel ? root.menuModel : null
63− menuModel: mainMenu.model ? mainMenu.model : null
80+ function reset() {
81+ mainMenu.positionViewAtBeginning();
6482 }
6583
84+ property QtObject factory: root.factory.createObject(page, { menuModel: page.menuModel } )
85+
6686 header: PageHeader {
6787 id: backLabel
6888 visible: page.isSubmenu
@@ -151,7 +171,7 @@ PageStack {
151171 visible: status == Loader.Ready
152172
153173 property int modelIndex: index
154− sourceComponent: factory.load(model)
174+ sourceComponent: page.factory.load(model)
155175
156176 onLoaded: {
157177 if (item.hasOwnProperty("selected")) {
@@ -174,7 +194,7 @@ PageStack {
174194 if (model.hasSubmenu) {
175195 root.push(pageComponent, {
176196 "isSubmenu": true,
177− "title": model.label,
197+ "title": model.label.replace(/_|&/, ""),
178198 "menuModel": page.menuModel.submenu(modelIndex)
179199 });
180200 }
@@ -202,10 +222,4 @@ PageStack {
202222 }
203223 }
204224 }
205−
206−// function reset()
207−// {
208−// menuStack.reset();
209−// mainMenu.positionViewAtBeginning();
210−// }
211225}
tests/qmltests/Panel/Indicators/tst_MenuItemFactory.qml → tests/qmltests/Panel/Indicators/tst_IndicatorMenuItemFactory.qmlrenamed+2−2
@@ -28,7 +28,7 @@ Item {
2828 width: units.gu(40)
2929 height: units.gu(70)
3030
31− MenuItemFactory {
31+ IndicatorMenuItemFactory {
3232 id: factory
3333 menuModel: UnityMenuModel {}
3434 }
@@ -51,7 +51,7 @@ Item {
5151 }
5252
5353 UT.UnityTestCase {
54− name: "MenuItemFactory"
54+ name: "IndicatorMenuItemFactory"
5555 when: windowShown
5656
5757 property QtObject menuData: QtObject {
tests/qmltests/Panel/tst_Panel.qml+18−6
@@ -37,20 +37,18 @@ PanelTest {
3737 color: "black"
3838
3939 Binding {
40− target: mouseEmulation
41− property: "checked"
42− value: !windowControlsCB.checked
40+ target: QuickUtils
41+ property: "keyboardAttached"
42+ value: keyboardAttached.checked
4343 }
4444
4545 DesktopMenuData { id: appMenuData }
4646
4747 Component.onCompleted: {
48− QuickUtils.keyboardAttached = true;
4948 theme.name = "Ubuntu.Components.Themes.SuruDark"
5049
5150 ApplicationMenuRegistry.RegisterSurfaceMenu("dialerAppSurfaceId", "/dialerapp", "/dialerapp", ":2");
5251 Indicators.UnityMenuModelCache.setCachedModelData("/dialerapp", appMenuData.dialerData);
53− PanelState.title = "AppMenu";
5452 }
5553
5654 Rectangle {
@@ -78,7 +76,7 @@ PanelTest {
7876 Panel {
7977 id: panel
8078 anchors.fill: parent
81− mode: "staged"
79+ mode: modeSelector.model[modeSelector.selectedIndex]
8280
8381 indicatorMenuWidth: parent.width > units.gu(60) ? units.gu(40) : parent.width
8482 applicationMenuWidth: parent.width > units.gu(60) ? units.gu(40) : parent.width
@@ -109,12 +107,14 @@ PanelTest {
109107 Layout.fillWidth: false
110108
111109 ListItem.ItemSelector {
110+ id: modeSelector
112111 anchors { left: parent.left; right: parent.right }
113112 activeFocusOnPress: false
114113 text: "Mode"
115114 model: ["staged", "windowed" ]
116115 onSelectedIndexChanged: {
117116 panel.mode = model[selectedIndex];
117+ keyboardAttached.checked = panel.mode == "windowed"
118118 }
119119 }
120120
@@ -223,6 +223,18 @@ PanelTest {
223223 MouseTouchEmulationCheckbox {
224224 id: mouseEmulation
225225 color: "white"
226+ checked: panel.mode == "staged"
227+ }
228+
229+ RowLayout {
230+ Layout.fillWidth: true
231+ CheckBox {
232+ id: keyboardAttached
233+ }
234+ Label {
235+ text: "Keyboard Attached"
236+ color: "white"
237+ }
226238 }
227239 }
228240 }
tests/qmltests/Stages/DesktopMenuData.qml+13−13
@@ -5,38 +5,39 @@ QtObject {
55 property var dialerData: [{
66 "rowData": { // 1.1
77 "label": "&dialer1",
8− "action": "dialer1",
9− "shortcut": "Alt+F"
8+ "action": "dialer1"
109 },
1110 "submenu": [{
1211 "rowData": { // 1.1
13− "label": "menu1.1",
12+ "label": "&menu1.1",
1413 "action": "menu1.1",
15− "shortcut": "Alt+0"
14+ "shortcut": "Ctrl+m"
1615 }}, {
1716 "rowData": { // 1.2
18− "label": "menu1.2",
17+ "label": "m&enu1.2",
1918 "action": "menu1.2",
20− "shortcut": "Alt+1"
19+ "shortcut": "Ctrl+e"
2120 },
2221 "submenu": [{
2322 "rowData": { // 1.2.1
24− "label": "menu1.2.1",
25− "action": "menu1.2.1",
26− "shortcut": ""
23+ "label": "me&nu1.2.1",
24+ "action": "menu1.2.1"
2725 }}, {
2826 "rowData": { // 1.2.2
2927 "label": "menu1.2.2",
3028 "action": "menu1.2.2"
3129 }}, {
3230 "rowData": { // 1.2.3
33− "sensitive": false,
3431 "isSeparator": true
3532 }}, {
3633 "rowData": { // row 1.2.4
3734 "label": "menu1.2.4",
3835 "action": "menu1.2.4",
3936 "isToggled": true
37+ }}, {
38+ "rowData": { // row 1.2.5
39+ "label": "menu1.2.5",
40+ "sensitive": false,
4041 }}
4142 ]}, {
4243 "rowData": { // 1.3
@@ -46,13 +47,12 @@ QtObject {
4647 "rowData": { // row 1.4
4748 "label": "menu1.4",
4849 "action": "menu1.4",
49− "shortcut": "Alt+2"
50+ "shortcut": "Ctrl+n"
5051 }}
5152 ]}, {
5253 "rowData": { // 2
5354 "label": "d&ialer2",
54− "action": "dialer2",
55− "shortcut": "Alt+E"
55+ "action": "dialer2"
5656 },
5757 "submenu": [{
5858 "rowData": { // 2.1