on xenial help sign in
replace the QuickList's Popover with an own implementation
c51540fMichael Zanetti
Launcher/LauncherPanel.qml+86−47
@@ -21,6 +21,7 @@ import Unity 0.1
21import Unity.Launcher 0.1
21import Unity.Launcher 0.1
22import Ubuntu.Components.Popups 0.1
22import Ubuntu.Components.Popups 0.1
23import "../Components/ListItems"
23import "../Components/ListItems"
24+import "../Components/"
24
25
25Item {
26Item {
26 id: root
27 id: root
@@ -28,10 +29,10 @@ Item {
28 rotation: inverted ? 180 : 0
29 rotation: inverted ? 180 : 0
29
30
30 property var model
31 property var model
31− property bool inverted: true
32+ property bool inverted: false
32 property bool dragging: false
33 property bool dragging: false
33 property bool moving: launcherListView.moving || launcherListView.flicking
34 property bool moving: launcherListView.moving || launcherListView.flicking
34− property bool preventHiding: moving || dndArea.draggedIndex >= 0 || dndArea.quickListPopover !== null || dndArea.pressed
35+ property bool preventHiding: moving || dndArea.draggedIndex >= 0 || quickList.state === "open" || dndArea.pressed
35 property int highlightIndex: -1
36 property int highlightIndex: -1
36
37
37 signal applicationSelected(string appId)
38 signal applicationSelected(string appId)
@@ -278,7 +279,6 @@ Item {
278 property bool postDragging: false
279 property bool postDragging: false
279 property int startX
280 property int startX
280 property int startY
281 property int startY
281− property var quickListPopover: null
282
282
283 onPressed: {
283 onPressed: {
284 selectedItem = launcherListView.itemAt(mouseX, mouseY + launcherListView.realContentY)
284 selectedItem = launcherListView.itemAt(mouseX, mouseY + launcherListView.realContentY)
@@ -357,11 +357,10 @@ Item {
357 draggedIndex = Math.floor((mouseY + launcherListView.realContentY) / launcherListView.realItemHeight);
357 draggedIndex = Math.floor((mouseY + launcherListView.realContentY) / launcherListView.realItemHeight);
358
358
359 // Opening QuickList
359 // Opening QuickList
360− var quickListModel = launcherListView.model.get(draggedIndex).quickList
360+ quickList.item = selectedItem;
361− var quickListAppId = launcherListView.model.get(draggedIndex).appId
361+ quickList.model = launcherListView.model.get(draggedIndex).quickList;
362−
362+ quickList.appId = launcherListView.model.get(draggedIndex).appId;
363− quickListPopover = PopupUtils.open(popoverComponent, selectedItem,
363+ quickList.state = "open";
364− {model: quickListModel, appId: quickListAppId})
365
364
366 launcherListView.interactive = false
365 launcherListView.interactive = false
367
366
@@ -387,7 +386,7 @@ Item {
387 var distance = Math.max(Math.abs(mouseX - startX), Math.abs(mouseY - startY))
386 var distance = Math.max(Math.abs(mouseX - startX), Math.abs(mouseY - startY))
388 if (!preDragging && distance > units.gu(1.5)) {
387 if (!preDragging && distance > units.gu(1.5)) {
389 preDragging = true;
388 preDragging = true;
390− PopupUtils.close(quickListPopover)
389+ quickList.state = "";
391 }
390 }
392 if (distance > launcherListView.itemHeight) {
391 if (distance > launcherListView.itemHeight) {
393 selectedItem.dragging = true
392 selectedItem.dragging = true
@@ -482,53 +481,93 @@ Item {
482 }
481 }
483 }
482 }
484
483
485− Component {
484+ UbuntuShapeForItem {
486− id: popoverComponent
485+ id: quickListShape
486+ objectName: "quickListShape"
487+ anchors.fill: quickList
488+ opacity: quickList.state === "open" ? 0.8 : 0
489+ visible: opacity > 0
490+
491+ Behavior on opacity {
492+ UbuntuNumberAnimation {}
493+ }
494+
495+ image: quickList
496+
497+ Image {
498+ anchors {
499+ right: parent.left
500+ rightMargin: -units.dp(4)
501+ verticalCenter: parent.verticalCenter
502+ verticalCenterOffset: -quickList.offset
503+ }
504+ height: units.gu(1)
505+ width: units.gu(2)
506+ source: "graphics/quicklist_tooltip.png"
507+ rotation: 90
508+ }
509+
510+ InverseMouseArea {
511+ anchors.fill: parent
512+ enabled: quickList.state == "open"
513+ onClicked: {
514+ quickList.state = ""
515+ }
516+ }
517+
518+ }
519+
520+ Rectangle {
521+ id: quickList
522+ objectName: "quickList"
523+ color: "#221e1c"
524+ width: units.gu(30)
525+ height: quickListColumn.height
526+ anchors {
527+ left: root.inverted ? undefined : parent.right
528+ right: root.inverted ? parent.left : undefined
529+ margins: units.gu(1)
487
530
488− Popover {
531+ }
489− id: popover
532+ y: itemCenter - (height / 2) + offset
490− property var model
491− property string appId
492− contentWidth: quickListColumn.width
493− foregroundStyle: QuicklistForegroundStyle {}
494
533
495− // FIXME: There's a bug in the Popover positioning that it covers the item in case it is rotated.
534+ property var model
496− // https://bugs.launchpad.net/ubuntu-ui-toolkit/+bug/1204470
535+ property string appId
497− // For now, let's move the Popover around with callerMargin.
536+ property var item
498− // Remove popupMargin once the bug is fixed.
499− property int popupMargin: root.inverted ? launcherListView.itemHeight : 0;
500
537
501− callerMargin: units.gu(1) + popupMargin
538+ // internal
539+ property int itemCenter: item ? root.mapFromItem(quickList.item).y + (item.height / 2) : units.gu(1)
540+ property int offset: itemCenter + (height/2) + units.gu(1) > parent.height ? -itemCenter - (height/2) - units.gu(1) + parent.height :
541+ itemCenter - (height/2) < units.gu(1) ? (height/2) - itemCenter + units.gu(1) : 0
502
542
503− Column {
543+ Column {
504− id: quickListColumn
544+ id: quickListColumn
505− width: units.gu(30)
545+ width: parent.width
506− height: childrenRect.height
546+ height: childrenRect.height
507
547
508− Repeater {
548+ Repeater {
509− id: popoverRepeater
549+ id: popoverRepeater
510− model: popover.model
550+ model: quickList.model
511
551
512− ListItems.Standard {
552+ ListItems.Standard {
513− objectName: "quickListEntry" + index
553+ objectName: "quickListEntry" + index
514− text: (model.clickable ? "" : "<b>") + model.label + (model.clickable ? "" : "</b>")
554+ text: (model.clickable ? "" : "<b>") + model.label + (model.clickable ? "" : "</b>")
515− highlightWhenPressed: model.clickable
555+ highlightWhenPressed: model.clickable
516
556
517− // FIXME: This is a workaround for the theme not being context sensitive. I.e. the
557+ // FIXME: This is a workaround for the theme not being context sensitive. I.e. the
518− // ListItems don't know that they are sitting in a themed Popover where the color
558+ // ListItems don't know that they are sitting in a themed Popover where the color
519− // needs to be inverted.
559+ // needs to be inverted.
520− __foregroundColor: Theme.palette.selected.backgroundText
560+ __foregroundColor: Theme.palette.selected.backgroundText
521
561
522− onClicked: {
562+ onClicked: {
523− if (!model.clickable) {
563+ if (!model.clickable) {
524− return;
564+ return;
525− }
526− PopupUtils.close(popover);
527− // Unsetting model to prevent showing changing entries during fading out
528− // that may happen because of triggering an action.
529− LauncherModel.quickListActionInvoked(appId, index);
530− popoverRepeater.model = undefined;
531 }
565 }
566+ quickList.state = "";
567+ // Unsetting model to prevent showing changing entries during fading out
568+ // that may happen because of triggering an action.
569+ LauncherModel.quickListActionInvoked(quickList.appId, index);
570+ quickList.model = undefined;
532 }
571 }
533 }
572 }
534 }
573 }
Launcher/QuicklistForegroundStyle.qmldeleted−23
@@ -1,23 +0,0 @@
1−/*
2− * Copyright (C) 2013 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU 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 General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−import Ubuntu.Components.Themes.Ambiance 0.1
18−
19−PopoverForegroundStyle {
20− bubbleColor: "#221e1c"
21− bubbleOpacity: 0.9
22− arrowSource: "graphics/quicklist_tooltip.png"
23−}
tests/qmltests/Launcher/tst_Launcher.qml+48−11
@@ -38,6 +38,7 @@ Item {
38 property string lastSelectedApplication
38 property string lastSelectedApplication
39
39
40 onLauncherApplicationSelected: {
40 onLauncherApplicationSelected: {
41+ print("sleected", appId)
41 lastSelectedApplication = appId
42 lastSelectedApplication = appId
42 }
43 }
43
44
@@ -363,25 +364,60 @@ Item {
363 var draggedItem = findChild(launcher, "launcherDelegate5")
364 var draggedItem = findChild(launcher, "launcherDelegate5")
364 var item0 = findChild(launcher, "launcherDelegate0")
365 var item0 = findChild(launcher, "launcherDelegate0")
365 var fakeDragItem = findChild(launcher, "fakeDragItem")
366 var fakeDragItem = findChild(launcher, "fakeDragItem")
366− var dndArea = findChild(launcher, "dndArea")
367+ var quickListShape = findChild(launcher, "quickListShape")
367
368
368 // Initial state
369 // Initial state
369− compare(dndArea.quickListPopover, null)
370+ compare(quickListShape.visible, false)
370
371
371 // Doing longpress
372 // Doing longpress
372 mousePress(draggedItem, draggedItem.width / 2, draggedItem.height / 2)
373 mousePress(draggedItem, draggedItem.width / 2, draggedItem.height / 2)
373 tryCompare(fakeDragItem, "visible", true) // Wait longpress happening
374 tryCompare(fakeDragItem, "visible", true) // Wait longpress happening
374− verify(dndArea.quickListPopover != null)
375+ tryCompare(quickListShape, "visible", true)
375
376
376 // Dragging a bit (> 1.5 gu)
377 // Dragging a bit (> 1.5 gu)
377 mouseMove(draggedItem, -units.gu(2), draggedItem.height / 2)
378 mouseMove(draggedItem, -units.gu(2), draggedItem.height / 2)
378
379
379 // QuickList needs to be closed when a drag operation starts
380 // QuickList needs to be closed when a drag operation starts
380− tryCompare(dndArea, "quickListPopover", null)
381+ tryCompare(quickListShape, "visible", false)
381
382
382 mouseRelease(draggedItem);
383 mouseRelease(draggedItem);
383 }
384 }
384
385
386+ function test_quicklist_positioning_data() {
387+ return [
388+ {tag: "top", flickTo: "top", itemIndex: 0},
389+ {tag: "bottom", flickTo: "bottom", itemIndex: 9}
390+ ];
391+ }
392+
393+ function test_quicklist_positioning(data) {
394+ revealer.dragLauncherIntoView();
395+ var quickList = findChild(launcher, "quickList")
396+ var draggedItem = findChild(launcher, "launcherDelegate" + data.itemIndex)
397+ var quickListShape = findChild(launcher, "quickListShape")
398+
399+ // Position launcher to where we need it
400+ var listView = findChild(launcher, "launcherListView");
401+ listView.flick(0, units.gu(200) * (data.flickTo === "top" ? 1 : -1));
402+ tryCompare(listView, "flicking", false);
403+
404+ // Doing longpress
405+ mousePress(draggedItem, draggedItem.width / 2, draggedItem.height / 2)
406+ tryCompare(quickListShape, "opacity", 0.8)
407+ mouseRelease(draggedItem);
408+
409+ verify(quickList.y >= units.gu(1))
410+ verify(quickList.y + quickList.height + units.gu(1) <= launcher.height)
411+
412+ // Click somewhere in the empty space to dismiss the quicklist
413+ mouseClick(launcher, launcher.width - units.gu(1), units.gu(1));
414+ tryCompare(quickListShape, "visible", false)
415+
416+ // Click somewhere in the empty space to dismiss the launcher
417+ mouseClick(launcher, launcher.width - units.gu(1), units.gu(1));
418+ revealer.waitUntilLauncherDisappears()
419+ }
420+
385 function test_quicklist_click_data() {
421 function test_quicklist_click_data() {
386 return [
422 return [
387 {tag: "non-clickable", index: 1, clickable: false },
423 {tag: "non-clickable", index: 1, clickable: false },
@@ -392,19 +428,20 @@ Item {
392 function test_quicklist_click(data) {
428 function test_quicklist_click(data) {
393 revealer.dragLauncherIntoView();
429 revealer.dragLauncherIntoView();
394 var clickedItem = findChild(launcher, "launcherDelegate5")
430 var clickedItem = findChild(launcher, "launcherDelegate5")
395− var dndArea = findChild(launcher, "dndArea")
431+ var quickList = findChild(launcher, "quickList")
432+ var quickListShape = findChild(launcher, "quickListShape")
396
433
397 // Initial state
434 // Initial state
398− compare(dndArea.quickListPopover, null)
435+ tryCompare(quickListShape, "visible", false)
399
436
400 // Doing longpress
437 // Doing longpress
401 mousePress(clickedItem, clickedItem.width / 2, clickedItem.height / 2)
438 mousePress(clickedItem, clickedItem.width / 2, clickedItem.height / 2)
402 tryCompare(clickedItem, "itemOpacity", 0) // Wait for longpress to happen
439 tryCompare(clickedItem, "itemOpacity", 0) // Wait for longpress to happen
403− verify(dndArea.quickListPopover != null)
440+ verify(quickListShape.visible, "QuickList must be visible")
404
441
405 mouseRelease(clickedItem);
442 mouseRelease(clickedItem);
406
443
407− var quickListEntry = findChild(dndArea.quickListPopover, "quickListEntry" + data.index)
444+ var quickListEntry = findChild(quickList, "quickListEntry" + data.index)
408
445
409 signalSpy.clear();
446 signalSpy.clear();
410 signalSpy.signalName = "quickListTriggered"
447 signalSpy.signalName = "quickListTriggered"
@@ -413,7 +450,7 @@ Item {
413
450
414 if (data.clickable) {
451 if (data.clickable) {
415 // QuickList needs to be closed when some clickable item is clicked
452 // QuickList needs to be closed when some clickable item is clicked
416− tryCompare(dndArea, "quickListPopover", null)
453+ tryCompare(quickListShape, "visible", false)
417
454
418 compare(signalSpy.count, 1, "Quicklist signal wasn't triggered")
455 compare(signalSpy.count, 1, "Quicklist signal wasn't triggered")
419 compare(signalSpy.signalArguments[0][0], LauncherModel.get(5).appId)
456 compare(signalSpy.signalArguments[0][0], LauncherModel.get(5).appId)
@@ -422,13 +459,13 @@ Item {
422 } else {
459 } else {
423
460
424 // QuickList must not be closed when a non-clickable item is clicked
461 // QuickList must not be closed when a non-clickable item is clicked
425− verify(dndArea.quickListPopover != null)
462+ verify(quickListShape.visible, "QuickList must be visible")
426
463
427 compare(signalSpy.count, 0, "Quicklist signal must NOT be triggered when clicking a non-clickable item")
464 compare(signalSpy.count, 0, "Quicklist signal must NOT be triggered when clicking a non-clickable item")
428
465
429 // Click somewhere in the empty space to dismiss the quicklist
466 // Click somewhere in the empty space to dismiss the quicklist
430 mouseClick(launcher, launcher.width - units.gu(1), units.gu(1));
467 mouseClick(launcher, launcher.width - units.gu(1), units.gu(1));
431− tryCompare(dndArea, "quickListPopover", null)
468+ tryCompare(quickListShape, "visible", false)
432 }
469 }
433 }
470 }
434 }
471 }