Merge lp:~nick-dedekind/unity8/menu.width.fix into lp:unity8
- menu.width.fix
- Merge into trunk
Proposed by
Nick Dedekind
Status: | Merged | ||||
---|---|---|---|---|---|
Approved by: | Albert Astals Cid | ||||
Approved revision: | 2771 | ||||
Merged at revision: | 2784 | ||||
Proposed branch: | lp:~nick-dedekind/unity8/menu.width.fix | ||||
Merge into: | lp:unity8 | ||||
Diff against target: |
806 lines (+352/-194) 4 files modified
qml/ApplicationMenus/MenuPopup.qml (+178/-139) tests/qmltests/ApplicationMenuDataLoader.qml (+13/-5) tests/qmltests/ApplicationMenus/tst_MenuBar.qml (+5/-5) tests/qmltests/ApplicationMenus/tst_MenuPopup.qml (+156/-45) |
||||
To merge this branch: | bzr merge lp:~nick-dedekind/unity8/menu.width.fix | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Albert Astals Cid (community) | Approve | ||
Unity8 CI Bot | continuous-integration | Approve | |
Review via email: mp+315021@code.launchpad.net |
Commit message
Fixed menu layout width calculations.
Description of the change
* Are there any related MPs required for this MP to build/function as expected? Please list.
No
* Did you perform an exploratory manual test run of your code change and any related functionality?
Yes
* If you changed the packaging (debian), did you subscribe the ubuntu-unity team to this MP?
N/A
* If you changed the UI, has there been a design review?
N/A
To post a comment you must log in.
Revision history for this message
Unity8 CI Bot (unity8-ci-bot) wrote : | # |
review:
Approve
(continuous-integration)
Revision history for this message
Albert Astals Cid (aacid) wrote : | # |
* Did you perform an exploratory manual test run of the code change and any related functionality?
Yes
* Did CI run pass? If not, please explain why.
Yes
review:
Approve
- 2772. By Nick Dedekind
-
color fixes
- 2773. By Nick Dedekind
-
Auto scroll. Maximum height to bottom of screen
- 2774. By Nick Dedekind
-
Added overflow button
- 2775. By Nick Dedekind
-
enabled only when item enabled
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'qml/ApplicationMenus/MenuPopup.qml' |
2 | --- qml/ApplicationMenus/MenuPopup.qml 2017-01-09 15:26:05 +0000 |
3 | +++ qml/ApplicationMenus/MenuPopup.qml 2017-01-18 14:44:04 +0000 |
4 | @@ -26,19 +26,7 @@ |
5 | objectName: "menu" |
6 | backgroundColor: theme.palette.normal.overlay |
7 | |
8 | - property alias unityMenuModel: listView.model |
9 | - |
10 | - readonly property real __ajustedMinimumHeight: { |
11 | - if (listView.contentHeight > __minimumHeight) { |
12 | - return units.gu(30); |
13 | - } |
14 | - return Math.max(listView.contentHeight, units.gu(2)); |
15 | - } |
16 | - |
17 | - readonly property real __minimumWidth: units.gu(20) |
18 | - readonly property real __minimumHeight: units.gu(30) |
19 | - readonly property real __maximumWidth: Screen.width * 0.7 |
20 | - readonly property real __maximumHeight: Screen.height * 0.7 |
21 | + property alias unityMenuModel: repeater.model |
22 | |
23 | function show() { |
24 | visible = true; |
25 | @@ -63,18 +51,23 @@ |
26 | d.dismissAll(); |
27 | } |
28 | |
29 | - implicitWidth: container.width |
30 | - implicitHeight: MathUtils.clamp(listView.contentHeight, __ajustedMinimumHeight, __maximumHeight) |
31 | + implicitWidth: focusScope.width |
32 | + implicitHeight: focusScope.height |
33 | |
34 | MenuNavigator { |
35 | id: d |
36 | objectName: "d" |
37 | - itemView: listView |
38 | + itemView: repeater |
39 | |
40 | property Item currentItem: null |
41 | property Item hoveredItem: null |
42 | readonly property int currentIndex: currentItem ? currentItem.__ownIndex : -1 |
43 | |
44 | + property real __minimumWidth: units.gu(20) |
45 | + property real __maximumWidth: Screen.width * 0.7 |
46 | + property real __minimumHeight: units.gu(2) |
47 | + property real __maximumHeight: Screen.height * 0.7 |
48 | + |
49 | signal dismissAll() |
50 | |
51 | onCurrentItemChanged: { |
52 | @@ -86,13 +79,26 @@ |
53 | } |
54 | |
55 | onSelect: { |
56 | - currentItem = listView.itemAt(index); |
57 | + currentItem = repeater.itemAt(index); |
58 | + if (currentItem) { |
59 | + if (currentItem.y < listView.contentY) { |
60 | + listView.contentY = currentItem.y; |
61 | + } else if (currentItem.y + currentItem.height > listView.contentY + listView.height) { |
62 | + listView.contentY = currentItem.y + currentItem.height - listView.height; |
63 | + } |
64 | + } |
65 | } |
66 | } |
67 | |
68 | + MouseArea { |
69 | + // Eat events. |
70 | + anchors.fill: parent |
71 | + } |
72 | + |
73 | Item { |
74 | id: focusScope |
75 | - anchors.fill: parent |
76 | + width: container.width |
77 | + height: container.height |
78 | focus: visible |
79 | |
80 | Keys.onUpPressed: d.selectPrevious(d.currentIndex) |
81 | @@ -108,17 +114,17 @@ |
82 | id: container |
83 | objectName: "container" |
84 | |
85 | - width: listView.contentWidth |
86 | - height: parent.height |
87 | + height: MathUtils.clamp(listView.contentHeight, d.__minimumHeight, d.__maximumHeight) |
88 | + width: menuColumn.width |
89 | spacing: 0 |
90 | |
91 | - // FIXME use ListView.header - tried but was flaky with positionViewAtIndex. |
92 | + // Header - scroll up |
93 | Item { |
94 | - Layout.fillWidth: true; |
95 | - Layout.maximumHeight: units.gu(3) |
96 | - Layout.minimumHeight: units.gu(3) |
97 | + Layout.fillWidth: true |
98 | + height: units.gu(3) |
99 | visible: listView.contentHeight > root.height |
100 | enabled: !listView.atYBeginning |
101 | + z: 1 |
102 | |
103 | Rectangle { |
104 | color: enabled ? theme.palette.normal.overlayText : |
105 | @@ -143,47 +149,35 @@ |
106 | MouseArea { |
107 | anchors.fill: parent |
108 | onPressed: { |
109 | - var index = listView.indexAt(0, listView.contentY); |
110 | - listView.positionViewAtIndex(index-1, ListView.Beginning); |
111 | + var item = menuColumn.childAt(0, listView.contentY); |
112 | + if (item) { |
113 | + var previousItem = item; |
114 | + do { |
115 | + previousItem = repeater.itemAt(previousItem.__ownIndex-1); |
116 | + if (!previousItem) { |
117 | + listView.contentY = 0; |
118 | + return; |
119 | + } |
120 | + } while (previousItem.__isSeparator); |
121 | + |
122 | + listView.contentY = previousItem.y |
123 | + } |
124 | } |
125 | } |
126 | } |
127 | |
128 | - ListView { |
129 | + // Menu Items |
130 | + Flickable { |
131 | id: listView |
132 | - objectName: "listView" |
133 | + clip: interactive |
134 | + |
135 | Layout.fillHeight: true |
136 | Layout.fillWidth: true |
137 | - contentWidth: MathUtils.clamp(contentItem.childrenRect.width, |
138 | - __minimumWidth, |
139 | - __maximumWidth) |
140 | - |
141 | - orientation: Qt.Vertical |
142 | - interactive: contentHeight > height |
143 | - clip: interactive |
144 | - highlightFollowsCurrentItem: false |
145 | - |
146 | - highlight: Rectangle { |
147 | - color: "transparent" |
148 | - border.width: units.dp(1) |
149 | - border.color: UbuntuColors.orange |
150 | - z: 1 |
151 | - |
152 | - width: listView.width |
153 | - height: d.currentItem ? d.currentItem.height : 0 |
154 | - y: d.currentItem ? d.currentItem.y : 0 |
155 | - visible: d.currentItem |
156 | - } |
157 | - |
158 | - function itemAt(index) { |
159 | - if (index > count || index < 0) return null; |
160 | - currentIndex = index; |
161 | - return currentItem; |
162 | - } |
163 | + contentHeight: menuColumn.height |
164 | + interactive: height < contentHeight |
165 | |
166 | MouseArea { |
167 | - id: menuMouseArea |
168 | - anchors.fill: listView |
169 | + anchors.fill: parent |
170 | hoverEnabled: true |
171 | propagateComposedEvents: true // propogate events so we send clicks to children. |
172 | z: 1 // on top so we override any other hovers |
173 | @@ -195,7 +189,7 @@ |
174 | |
175 | if (!d.hoveredItem || !d.currentItem || |
176 | !d.hoveredItem.contains(Qt.point(pos.x - d.currentItem.x, pos.y - d.currentItem.y))) { |
177 | - d.hoveredItem = listView.itemAt(listView.indexAt(pos.x, pos.y)); |
178 | + d.hoveredItem = menuColumn.childAt(pos.x, pos.y) |
179 | if (!d.hoveredItem || !d.hoveredItem.enabled) |
180 | return false; |
181 | d.currentItem = d.hoveredItem; |
182 | @@ -216,89 +210,123 @@ |
183 | } |
184 | } |
185 | |
186 | - delegate: Loader { |
187 | - id: loader |
188 | - objectName: root.objectName + "-item" + __ownIndex |
189 | - |
190 | - property int __ownIndex: index |
191 | - |
192 | - width: root.width |
193 | - enabled: model.isSeparator ? false : model.sensitive |
194 | - |
195 | - sourceComponent: { |
196 | - if (model.isSeparator) { |
197 | - return separatorComponent; |
198 | - } |
199 | - return menuItemComponent; |
200 | - } |
201 | - |
202 | - property Item popup: null |
203 | - |
204 | - Component { |
205 | - id: menuItemComponent |
206 | - MenuItem { |
207 | - id: menuItem |
208 | - menuData: model |
209 | - objectName: loader.objectName + "-actionItem" |
210 | - |
211 | - action.onTriggered: { |
212 | - d.currentItem = loader; |
213 | - |
214 | - if (hasSubmenu) { |
215 | - if (!popup) { |
216 | - var model = root.unityMenuModel.submenu(__ownIndex); |
217 | - popup = submenuComponent.createObject(focusScope, { |
218 | - objectName: loader.objectName + "-", |
219 | - unityMenuModel: model, |
220 | - x: Qt.binding(function() { return root.width }), |
221 | - y: Qt.binding(function() { return loader.y }) |
222 | - }); |
223 | - } else if (popup) { |
224 | - popup.visible = true; |
225 | - } |
226 | - popup.retreat.connect(function() { |
227 | - popup.destroy(); |
228 | - popup = null; |
229 | - menuItem.forceActiveFocus(); |
230 | - }) |
231 | - } else { |
232 | - root.unityMenuModel.activate(__ownIndex); |
233 | - } |
234 | - } |
235 | - |
236 | - Connections { |
237 | - target: d |
238 | - onCurrentIndexChanged: { |
239 | - if (popup && d.currentIndex != __ownIndex) { |
240 | - popup.visible = false; |
241 | - } |
242 | - } |
243 | - onDismissAll: { |
244 | - if (popup) { |
245 | - popup.destroy(); |
246 | - popup = null; |
247 | - } |
248 | - } |
249 | - } |
250 | - } |
251 | - } |
252 | - |
253 | - Component { |
254 | - id: separatorComponent |
255 | - ListItems.ThinDivider { |
256 | - objectName: loader.objectName + "-separator" |
257 | - } |
258 | - } |
259 | - } |
260 | - } // ListView |
261 | - |
262 | - // FIXME use ListView.footer - tried but was flaky with positionViewAtIndex. |
263 | + ColumnLayout { |
264 | + id: menuColumn |
265 | + spacing: 0 |
266 | + |
267 | + width: MathUtils.clamp(implicitWidth, d.__minimumWidth, d.__maximumWidth) |
268 | + |
269 | + Repeater { |
270 | + id: repeater |
271 | + |
272 | + Loader { |
273 | + id: loader |
274 | + objectName: root.objectName + "-item" + __ownIndex |
275 | + |
276 | + property int __ownIndex: index |
277 | + property bool __isSeparator: model.isSeparator |
278 | + |
279 | + enabled: __isSeparator ? false : model.sensitive |
280 | + |
281 | + sourceComponent: { |
282 | + if (model.isSeparator) { |
283 | + return separatorComponent; |
284 | + } |
285 | + return menuItemComponent; |
286 | + } |
287 | + |
288 | + property Item popup: null |
289 | + |
290 | + Layout.fillWidth: true |
291 | + |
292 | + Component { |
293 | + id: menuItemComponent |
294 | + MenuItem { |
295 | + id: menuItem |
296 | + menuData: model |
297 | + objectName: loader.objectName + "-actionItem" |
298 | + |
299 | + width: MathUtils.clamp(implicitWidth, d.__minimumWidth, d.__maximumWidth) |
300 | + |
301 | + action.onTriggered: { |
302 | + d.currentItem = loader; |
303 | + |
304 | + if (hasSubmenu) { |
305 | + if (!popup) { |
306 | + var model = root.unityMenuModel.submenu(__ownIndex); |
307 | + popup = submenuComponent.createObject(focusScope, { |
308 | + objectName: loader.objectName + "-", |
309 | + unityMenuModel: model, |
310 | + x: Qt.binding(function() { return root.width }), |
311 | + y: Qt.binding(function() { |
312 | + var dummy = listView.contentY; // force a recalc on contentY change. |
313 | + return mapToItem(container, 0, y).y; |
314 | + }) |
315 | + }); |
316 | + } else if (popup) { |
317 | + popup.visible = true; |
318 | + } |
319 | + popup.retreat.connect(function() { |
320 | + popup.destroy(); |
321 | + popup = null; |
322 | + menuItem.forceActiveFocus(); |
323 | + }) |
324 | + } else { |
325 | + root.unityMenuModel.activate(__ownIndex); |
326 | + } |
327 | + } |
328 | + |
329 | + Connections { |
330 | + target: d |
331 | + onCurrentIndexChanged: { |
332 | + if (popup && d.currentIndex != __ownIndex) { |
333 | + popup.visible = false; |
334 | + } |
335 | + } |
336 | + onDismissAll: { |
337 | + if (popup) { |
338 | + popup.destroy(); |
339 | + popup = null; |
340 | + } |
341 | + } |
342 | + } |
343 | + } |
344 | + } |
345 | + |
346 | + Component { |
347 | + id: separatorComponent |
348 | + ListItems.ThinDivider { |
349 | + objectName: loader.objectName + "-separator" |
350 | + implicitHeight: units.dp(2) |
351 | + } |
352 | + } |
353 | + } |
354 | + |
355 | + } |
356 | + } |
357 | + |
358 | + // Highlight |
359 | + Rectangle { |
360 | + color: "transparent" |
361 | + border.width: units.dp(1) |
362 | + border.color: UbuntuColors.orange |
363 | + z: 1 |
364 | + |
365 | + width: listView.width |
366 | + height: d.currentItem ? d.currentItem.height : 0 |
367 | + y: d.currentItem ? d.currentItem.y : 0 |
368 | + visible: d.currentItem |
369 | + } |
370 | + |
371 | + } // Flickable |
372 | + |
373 | + // Header - scroll down |
374 | Item { |
375 | - Layout.fillWidth: true; |
376 | - Layout.maximumHeight: units.gu(3) |
377 | - Layout.minimumHeight: units.gu(3) |
378 | + Layout.fillWidth: true |
379 | + height: units.gu(3) |
380 | visible: listView.contentHeight > root.height |
381 | enabled: !listView.atYEnd |
382 | + z: 1 |
383 | |
384 | Rectangle { |
385 | color: enabled ? theme.palette.normal.overlayText : |
386 | @@ -323,8 +351,19 @@ |
387 | MouseArea { |
388 | anchors.fill: parent |
389 | onPressed: { |
390 | - var index = listView.indexAt(0, listView.contentY); |
391 | - listView.positionViewAtIndex(index+1, ListView.Beginning); |
392 | + var item = menuColumn.childAt(0, listView.contentY + listView.height); |
393 | + if (item) { |
394 | + var nextItem = item; |
395 | + do { |
396 | + nextItem = repeater.itemAt(nextItem.__ownIndex+1); |
397 | + if (!nextItem) { |
398 | + listView.contentY = listView.contentHeight - listView.height; |
399 | + return; |
400 | + } |
401 | + } while (nextItem.__isSeparator); |
402 | + |
403 | + listView.contentY = nextItem.y - listView.height |
404 | + } |
405 | } |
406 | } |
407 | } |
408 | |
409 | === modified file 'tests/qmltests/ApplicationMenuDataLoader.qml' |
410 | --- tests/qmltests/ApplicationMenuDataLoader.qml 2017-01-06 14:07:36 +0000 |
411 | +++ tests/qmltests/ApplicationMenuDataLoader.qml 2017-01-18 14:44:04 +0000 |
412 | @@ -10,6 +10,7 @@ |
413 | |
414 | Connections { |
415 | id: sMgrHandler |
416 | + target: null |
417 | onSurfaceCreated: { |
418 | var fakeMenuPath = "/" + surface.persistentId.replace(/\W+/g, ""); |
419 | |
420 | @@ -25,21 +26,28 @@ |
421 | var data = []; |
422 | if (root === undefined) root = true; |
423 | |
424 | - if (prefix === undefined) prefix = "menu" |
425 | - |
426 | for (var i = 0; i < length; i++) { |
427 | |
428 | + var menuName = prefix; |
429 | + if (menuName === undefined) { |
430 | + var chars = Math.random() * 20; |
431 | + menuName = ""; |
432 | + for (var x = 0; x < chars; x++) { |
433 | + menuName += String.fromCharCode((Math.random() * 26) + 65); |
434 | + } |
435 | + } |
436 | + |
437 | var menuCode = String.fromCharCode(i+65); |
438 | |
439 | var isSeparator = !root && separatorInterval > 0 && ((i+1) % separatorInterval == 0); |
440 | var row = { |
441 | "rowData": { // 1 |
442 | - "label": prefix + "&" + menuCode, |
443 | + "label": menuName + "&" + menuCode, |
444 | "sensitive": true, |
445 | "isSeparator": isSeparator, |
446 | "icon": "", |
447 | "ext": {}, |
448 | - "action": prefix + menuCode, |
449 | + "action": menuName + menuCode, |
450 | "actionState": {}, |
451 | "isCheck": false, |
452 | "isRadio": false, |
453 | @@ -49,7 +57,7 @@ |
454 | } |
455 | var isSubmenu = root === undefined || root === true || (submenuInterval > 0 && ((i+1) % submenuInterval == 0)); |
456 | if (isSubmenu && !isSeparator && depth > 1) { |
457 | - row["submenu"] = generateTestData(length, depth-1, submenuInterval, separatorInterval, prefix + menuCode + ".", false); |
458 | + row["submenu"] = generateTestData(length, depth-1, submenuInterval, separatorInterval,prefix, false); |
459 | } |
460 | data[i] = row; |
461 | } |
462 | |
463 | === modified file 'tests/qmltests/ApplicationMenus/tst_MenuBar.qml' |
464 | --- tests/qmltests/ApplicationMenus/tst_MenuBar.qml 2017-01-09 15:26:05 +0000 |
465 | +++ tests/qmltests/ApplicationMenus/tst_MenuBar.qml 2017-01-18 14:44:04 +0000 |
466 | @@ -65,7 +65,7 @@ |
467 | |
468 | unityMenuModel: UnityMenuModel { |
469 | id: menuBackend |
470 | - modelData: appMenuData.generateTestData(7,5,2,3,"menu") |
471 | + modelData: appMenuData.generateTestData(17,5,2,3) |
472 | } |
473 | } |
474 | } |
475 | @@ -83,12 +83,12 @@ |
476 | |
477 | function init() { |
478 | menuBar.dismiss(); |
479 | - menuBackend.modelData = appMenuData.generateTestData(5,5,2,3,"menu") |
480 | + menuBackend.modelData = appMenuData.generateTestData(5,5,2,3) |
481 | activatedSpy.clear(); |
482 | } |
483 | |
484 | function test_mouseNavigation() { |
485 | - menuBackend.modelData = appMenuData.generateTestData(3,3,0,0,"menu"); |
486 | + menuBackend.modelData = appMenuData.generateTestData(3,3,0,0); |
487 | wait(50) // wait for row to build |
488 | var priv = findInvisibleChild(menuBar, "d"); |
489 | |
490 | @@ -114,7 +114,7 @@ |
491 | } |
492 | |
493 | function test_keyboardNavigation_RightKeySelectsNextMenuItem(data) { |
494 | - menuBackend.modelData = appMenuData.generateTestData(3,3,0,0,"menu"); |
495 | + menuBackend.modelData = appMenuData.generateTestData(3,3,0,0); |
496 | var priv = findInvisibleChild(menuBar, "d"); |
497 | |
498 | var menuItem0 = findChild(menuBar, "menuBar-item0"); verify(menuItem0); |
499 | @@ -139,7 +139,7 @@ |
500 | } |
501 | |
502 | function test_keyboardNavigation_LeftKeySelectsPreviousMenuItem(data) { |
503 | - menuBackend.modelData = appMenuData.generateTestData(3,3,0,0,"menu"); |
504 | + menuBackend.modelData = appMenuData.generateTestData(3,3,0,0); |
505 | var priv = findInvisibleChild(menuBar, "d"); |
506 | |
507 | var menuItem0 = findChild(menuBar, "menuBar-item0"); verify(menuItem0); |
508 | |
509 | === modified file 'tests/qmltests/ApplicationMenus/tst_MenuPopup.qml' |
510 | --- tests/qmltests/ApplicationMenus/tst_MenuPopup.qml 2017-01-09 15:26:05 +0000 |
511 | +++ tests/qmltests/ApplicationMenus/tst_MenuPopup.qml 2017-01-18 14:44:04 +0000 |
512 | @@ -1,4 +1,4 @@ |
513 | -/* |
514 | +/* |
515 | * Copyright (C) 2016 Canonical, Ltd. |
516 | * |
517 | * This program is free software; you can redistribute it and/or modify |
518 | @@ -28,8 +28,8 @@ |
519 | |
520 | Item { |
521 | id: root |
522 | - width: Math.max(units.gu(100), page.width + units.gu(6)) |
523 | - height: Math.max(units.gu(50), page.height + units.gu(6)) |
524 | + width: Math.max(units.gu(100), loader.width + units.gu(6)) |
525 | + height: Math.max(units.gu(50), loader.height + units.gu(6)) |
526 | |
527 | Binding { |
528 | target: MouseTouchAdaptor |
529 | @@ -39,25 +39,37 @@ |
530 | |
531 | ApplicationMenuDataLoader { id: appMenuData } |
532 | |
533 | - MenuPopup { |
534 | - id: page |
535 | - |
536 | - anchors { |
537 | - left: parent.left |
538 | - top: parent.top |
539 | - leftMargin: units.gu(3) |
540 | - topMargin: units.gu(3) |
541 | - } |
542 | - |
543 | - unityMenuModel: UnityMenuModel { |
544 | - id: menuBackend |
545 | - modelData: appMenuData.generateTestData(7,5,2,3,"menu") |
546 | + Loader { |
547 | + id: loader |
548 | + sourceComponent: MenuPopup { |
549 | + anchors { |
550 | + left: parent ? parent.left : undefined |
551 | + top: parent ? parent.top : undefined |
552 | + leftMargin: units.gu(3) |
553 | + topMargin: units.gu(3) |
554 | + } |
555 | + |
556 | + unityMenuModel: UnityMenuModel { |
557 | + modelData: [{ |
558 | + "rowData": { |
559 | + "label": "Short", |
560 | + }}, { |
561 | + "rowData": { |
562 | + "label": "This is a long menu item which tests width", |
563 | + }} |
564 | + ] |
565 | + } |
566 | + |
567 | + Binding { |
568 | + target: activatedSpy |
569 | + property: "target" |
570 | + value: unityMenuModel |
571 | + } |
572 | } |
573 | } |
574 | |
575 | SignalSpy { |
576 | id: activatedSpy |
577 | - target: menuBackend |
578 | signalName: "activated" |
579 | } |
580 | |
581 | @@ -66,14 +78,20 @@ |
582 | name: "MenuPopup" |
583 | when: windowShown |
584 | |
585 | + property var menu: loader.status === Loader.Ready ? loader.item : null |
586 | + |
587 | function init() { |
588 | - page.show(); |
589 | + loader.active = true; |
590 | + menu.show(); |
591 | } |
592 | |
593 | function cleanup() { |
594 | - page.reset(); |
595 | + menu.reset(); |
596 | wait(100); // let the page dismiss |
597 | activatedSpy.clear(); |
598 | + |
599 | + loader.active = false; |
600 | + tryCompare(loader, "item", null); |
601 | } |
602 | |
603 | // visit and verify that all the backend menus have been created |
604 | @@ -90,6 +108,7 @@ |
605 | // recurse into submenu |
606 | var submenu = rows[i]["submenu"]; |
607 | if (submenu) { |
608 | + waitForRendering(menuItem); |
609 | mouseClick(menuItem, menuItem.width/2, menuItem.height/2); |
610 | tryCompare(menuPriv, "currentItem", menuItem); |
611 | |
612 | @@ -113,15 +132,15 @@ |
613 | } |
614 | |
615 | function test_mouseNavigation(data) { |
616 | - menuBackend.modelData = data.testData; |
617 | + menu.unityMenuModel.modelData = data.testData; |
618 | |
619 | - recurseMenuConstruction(data.testData, page); |
620 | + recurseMenuConstruction(data.testData, menu); |
621 | } |
622 | |
623 | function test_checkableMenuTogglesOnClick() { |
624 | - menuBackend.modelData = appMenuData.singleCheckable; |
625 | + menu.unityMenuModel.modelData = appMenuData.singleCheckable; |
626 | |
627 | - var menuItem = findChild(page, "menu-item0-actionItem"); |
628 | + var menuItem = findChild(menu, "menu-item0-actionItem"); |
629 | verify(menuItem); |
630 | compare(menuItem.action.checkable, true, "Menu item should be checkable"); |
631 | compare(menuItem.action.checked, false, "Menu item should not be checked"); |
632 | @@ -132,13 +151,13 @@ |
633 | } |
634 | |
635 | function test_keyboardNavigation_DownKeySelectsAndOpensNextMenuItemAndRotates() { |
636 | - menuBackend.modelData = appMenuData.generateTestData(3,3,0,0,"menu",false); |
637 | - |
638 | - var item0 = findChild(page, "menu-item0"); verify(item0); |
639 | - var item1 = findChild(page, "menu-item1"); verify(item1); |
640 | - var item2 = findChild(page, "menu-item2"); verify(item2); |
641 | - |
642 | - var priv = findInvisibleChild(page, "d"); |
643 | + menu.unityMenuModel.modelData = appMenuData.generateTestData(3,3,0,0,"menu",false); |
644 | + |
645 | + var item0 = findChild(menu, "menu-item0"); verify(item0); |
646 | + var item1 = findChild(menu, "menu-item1"); verify(item1); |
647 | + var item2 = findChild(menu, "menu-item2"); verify(item2); |
648 | + |
649 | + var priv = findInvisibleChild(menu, "d"); |
650 | |
651 | keyClick(Qt.Key_Down, Qt.NoModifier); |
652 | compare(priv.currentItem, item0, "CurrentItem should have moved to item 0"); |
653 | @@ -154,13 +173,13 @@ |
654 | } |
655 | |
656 | function test_keyboardNavigation_UpKeySelectsAndOpensPreviousMenuItemAndRotates() { |
657 | - menuBackend.modelData = appMenuData.generateTestData(3,3,0,0,"menu",false); |
658 | - |
659 | - var item0 = findChild(page, "menu-item0"); verify(item0); |
660 | - var item1 = findChild(page, "menu-item1"); verify(item1); |
661 | - var item2 = findChild(page, "menu-item2"); verify(item2); |
662 | - |
663 | - var priv = findInvisibleChild(page, "d"); |
664 | + menu.unityMenuModel.modelData = appMenuData.generateTestData(3,3,0,0,"menu",false); |
665 | + |
666 | + var item0 = findChild(menu, "menu-item0"); verify(item0); |
667 | + var item1 = findChild(menu, "menu-item1"); verify(item1); |
668 | + var item2 = findChild(menu, "menu-item2"); verify(item2); |
669 | + |
670 | + var priv = findInvisibleChild(menu, "d"); |
671 | |
672 | keyClick(Qt.Key_Down, Qt.NoModifier); |
673 | compare(priv.currentItem, item0, "CurrentItem should have moved to item 2"); |
674 | @@ -176,17 +195,17 @@ |
675 | } |
676 | |
677 | function test_keyboardNavigation_RightKeyEntersSubMenu() { |
678 | - menuBackend.modelData = appMenuData.generateTestData(3,3,1,0,"menu",false); |
679 | - |
680 | - var menuItem = findChild(page, "menu-item0"); |
681 | - |
682 | - var priv = findInvisibleChild(page, "d"); |
683 | + menu.unityMenuModel.modelData = appMenuData.generateTestData(3,3,1,0,"menu",false); |
684 | + |
685 | + var menuItem = findChild(menu, "menu-item0"); |
686 | + |
687 | + var priv = findInvisibleChild(menu, "d"); |
688 | priv.currentItem = menuItem; |
689 | |
690 | keyClick(Qt.Key_Right, Qt.NoModifier); |
691 | tryCompareFunction(function() { return menuItem.popup !== null && menuItem.popup.visible }, true); |
692 | |
693 | - var submenu0 = findChild(page, "menu-item0-menu"); verify(submenu0); |
694 | + var submenu0 = findChild(menu, "menu-item0-menu"); verify(submenu0); |
695 | var submenu0item0 = findChild(submenu0, "menu-item0-menu-item0"); verify(submenu0item0); |
696 | |
697 | var submenu0Priv = findInvisibleChild(submenu0, "d"); verify(submenu0Priv); |
698 | @@ -194,14 +213,106 @@ |
699 | } |
700 | |
701 | function test_keyboardNavigation_LeftKeyClosesSubMenu() { |
702 | - menuBackend.modelData = appMenuData.generateTestData(3,3,1,0,"menu",false); |
703 | + menu.unityMenuModel.modelData = appMenuData.generateTestData(3,3,1,0,"menu",false); |
704 | |
705 | - var menuItem = findChild(page, "menu-item0"); verify(menuItem); |
706 | + var menuItem = findChild(menu, "menu-item0"); verify(menuItem); |
707 | mouseClick(menuItem, menuItem.width/2, menuItem.height/2); |
708 | tryCompareFunction(function() { return menuItem.popup !== null && menuItem.popup.visible }, true); |
709 | |
710 | keyClick(Qt.Key_Left, Qt.NoModifier); |
711 | tryCompareFunction(function() { return menuItem.popup !== null && menuItem.popup.visible }, false); |
712 | } |
713 | + |
714 | + function test_differentSizes() { |
715 | + var differentSizesMenu = [{ |
716 | + "rowData": { "label": "Short" }}, { |
717 | + "rowData": { "label": "This is a long menu item which tests width" } |
718 | + }]; |
719 | + |
720 | + menu.unityMenuModel.modelData = differentSizesMenu; |
721 | + |
722 | + waitForRendering(menu); |
723 | + var longWidth = menu.width; |
724 | + differentSizesMenu.pop(); |
725 | + menu.unityMenuModel.modelData = differentSizesMenu; |
726 | + |
727 | + waitForRendering(menu); |
728 | + verify(menu.width < longWidth); |
729 | + } |
730 | + |
731 | + function test_minimumWidth() { |
732 | + var shortMenu = [{ |
733 | + "rowData": { "label": "Short" } |
734 | + }]; |
735 | + menu.unityMenuModel.modelData = shortMenu; |
736 | + |
737 | + var priv = findInvisibleChild(menu, "d"); |
738 | + priv.__minimumWidth = 0; |
739 | + priv.__maximumWidth = 1000; |
740 | + tryCompareFunction(function() { return menu.width > priv.__minimumWidth; }, true); |
741 | + |
742 | + priv.__minimumWidth = 300; |
743 | + tryCompare(menu, "width", priv.__minimumWidth); |
744 | + } |
745 | + |
746 | + function test_maximumWidth() { |
747 | + var longMenu = [{ |
748 | + "rowData": { "label": "This is a long menu item which tests width" } |
749 | + }]; |
750 | + |
751 | + var priv = findInvisibleChild(menu, "d"); |
752 | + priv.__minimumWidth = 0; |
753 | + priv.__maximumWidth = 100; |
754 | + |
755 | + menu.unityMenuModel.modelData = longMenu; |
756 | + tryCompare(menu, "width", priv.__maximumWidth); |
757 | + |
758 | + priv.__maximumWidth = 200; |
759 | + tryCompare(menu, "width", priv.__maximumWidth); |
760 | + |
761 | + priv.__maximumWidth = 1200; |
762 | + tryCompareFunction(function() { return menu.width < priv.__maximumWidth; }, true); |
763 | + } |
764 | + |
765 | + function test_minimumHeight() { |
766 | + var shortMenu = [{ |
767 | + "rowData": { "label": "menu1" } |
768 | + }]; |
769 | + menu.unityMenuModel.modelData = shortMenu; |
770 | + |
771 | + var priv = findInvisibleChild(menu, "d"); |
772 | + priv.__minimumHeight = 0; |
773 | + priv.__maximumHeight = 1000; |
774 | + tryCompareFunction(function() { return menu.height > priv.__minimumHeight; }, true); |
775 | + |
776 | + priv.__minimumHeight = 300; |
777 | + tryCompare(menu, "height", priv.__minimumHeight); |
778 | + } |
779 | + |
780 | + function test_maximumHeight() { |
781 | + var shortMenu = [{ |
782 | + "rowData": { "label": "menu1" }}, { |
783 | + "rowData": { "label": "menu2" }}, { |
784 | + "rowData": { "label": "menu3" }}, { |
785 | + "rowData": { "label": "menu4" }}, { |
786 | + "rowData": { "label": "menu5" }}, { |
787 | + "rowData": { "label": "menu6" }}, { |
788 | + "rowData": { "label": "menu7" }}, { |
789 | + "rowData": { "label": "menu8" }}, { |
790 | + "rowData": { "label": "menu9" } |
791 | + }]; |
792 | + menu.unityMenuModel.modelData = shortMenu; |
793 | + |
794 | + var priv = findInvisibleChild(menu, "d"); |
795 | + priv.__minimumHeight = 0; |
796 | + priv.__maximumHeight = 100; |
797 | + tryCompare(menu, "height", priv.__maximumHeight); |
798 | + |
799 | + priv.__maximumHeight = 200; |
800 | + tryCompare(menu, "height", priv.__maximumHeight); |
801 | + |
802 | + priv.__maximumHeight = 1200; |
803 | + tryCompareFunction(function() { return menu.height < priv.__maximumHeight; }, true); |
804 | + } |
805 | } |
806 | } |
PASSED: Continuous integration, rev:2771 /unity8- jenkins. ubuntu. com/job/ lp-unity8- ci/2944/ /unity8- jenkins. ubuntu. com/job/ build/3841 /unity8- jenkins. ubuntu. com/job/ test-0- autopkgtest/ label=amd64, release= xenial+ overlay, testname= qmluitests. sh/2234 /unity8- jenkins. ubuntu. com/job/ test-0- autopkgtest/ label=amd64, release= zesty,testname= qmluitests. sh/2234 /unity8- jenkins. ubuntu. com/job/ build-0- fetch/3869 /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=amd64, release= xenial+ overlay/ 3712 /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=amd64, release= xenial+ overlay/ 3712/artifact/ output/ *zip*/output. zip /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=amd64, release= zesty/3712 /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=amd64, release= zesty/3712/ artifact/ output/ *zip*/output. zip /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=armhf, release= xenial+ overlay/ 3712 /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=armhf, release= xenial+ overlay/ 3712/artifact/ output/ *zip*/output. zip /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=armhf, release= zesty/3712 /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=armhf, release= zesty/3712/ artifact/ output/ *zip*/output. zip /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=i386, release= xenial+ overlay/ 3712 /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=i386, release= xenial+ overlay/ 3712/artifact/ output/ *zip*/output. zip /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=i386, release= zesty/3712 /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=i386, release= zesty/3712/ artifact/ output/ *zip*/output. zip
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild: /unity8- jenkins. ubuntu. com/job/ lp-unity8- ci/2944/ rebuild
https:/