on xenial help sign in
fixes for topmost fullscreen notification, get rid of placeholder
c550de2Lukáš Tinkl
qml/Notifications/Notification.qml+14−27
@@ -55,29 +55,11 @@ StyledItem {
55 name: "Ubuntu.Components.Themes.Ambiance"
55 name: "Ubuntu.Components.Themes.Ambiance"
56 }
56 }
57
57
58− signal dismissed()
59−
60− readonly property bool expanded: {
58+ readonly property bool expanded: type === Notification.SnapDecision && // expand only snap decisions, if...
61− var result = false;
59+ (fullscreen || // - it's a fullscreen one
62−
63− if (type === Notification.SnapDecision) {
64− if (ListView.view.currentIndex === index || fullscreen) {
60+ ListView.view.currentIndex === index || // - it's the one the user clicked on
65− result = true;
66− } else {
67− if (ListView.view.count > 2) {
68− if (ListView.view.currentIndex === -1 && index == 1) {
61+ (ListView.view.currentIndex === -1 && index == 0) // - the first one after the user closed the previous one
69− result = true;
62+ )
70− } else {
71− result = false;
72− }
73− } else {
74− result = true;
75− }
76− }
77− }
78−
79− return result;
80− }
81
63
82 NotificationAudio {
64 NotificationAudio {
83 id: sound
65 id: sound
@@ -116,6 +98,13 @@ StyledItem {
116 }
98 }
117 }
99 }
118
100
101+ Binding {
102+ target: ListView.view
103+ property: "topmostIsFullscreen"
104+ value: fullscreen
105+ when: index == 0
106+ }
107+
119 function closeNotification() {
108 function closeNotification() {
120 if (index === ListView.view.currentIndex) { // reset to get the 1st snap decision expanded
109 if (index === ListView.view.currentIndex) { // reset to get the 1st snap decision expanded
121 ListView.view.currentIndex = -1;
110 ListView.view.currentIndex = -1;
@@ -125,7 +114,6 @@ StyledItem {
125 notification.notification.invokeAction(notification.actions.data(1, ActionModel.RoleActionId));
114 notification.notification.invokeAction(notification.actions.data(1, ActionModel.RoleActionId));
126
115
127 notification.notification.close();
116 notification.notification.close();
128− notification.dismissed()
129 }
117 }
130
118
131 Behavior on x {
119 Behavior on x {
@@ -144,7 +132,8 @@ StyledItem {
144 }
132 }
145 }
133 }
146
134
147− Behavior on height {
135+ Behavior on implicitHeight {
136+ enabled: !fullscreen
148 UbuntuNumberAnimation {
137 UbuntuNumberAnimation {
149 duration: UbuntuAnimation.SnapDuration
138 duration: UbuntuAnimation.SnapDuration
150 }
139 }
@@ -217,7 +206,6 @@ StyledItem {
217 onNameOwnerChanged: {
206 onNameOwnerChanged: {
218 if (lastNameOwner !== "" && nameOwner === "" && notification.notification !== undefined) {
207 if (lastNameOwner !== "" && nameOwner === "" && notification.notification !== undefined) {
219 notification.notification.close()
208 notification.notification.close()
220− notification.dismissed()
221 }
209 }
222 lastNameOwner = nameOwner
210 lastNameOwner = nameOwner
223 }
211 }
@@ -443,7 +431,6 @@ StyledItem {
443 }
431 }
444 onAccepted: {
432 onAccepted: {
445 notification.notification.invokeAction(actionRepeater.itemAt(0).actionId)
433 notification.notification.invokeAction(actionRepeater.itemAt(0).actionId)
446− notification.dismissed()
447 }
434 }
448 }
435 }
449 }
436 }
qml/Notifications/NotificationMenuItemFactory.qml−2
@@ -155,13 +155,11 @@ Loader {
155
155
156 onCancel: {
156 onCancel: {
157 menuModel.activate(menuIndex, false);
157 menuModel.activate(menuIndex, false);
158− notification.dismissed()
159 }
158 }
160
159
161 onEmergencyCall: {
160 onEmergencyCall: {
162 shell.startLockedApp("dialer-app");
161 shell.startLockedApp("dialer-app");
163 menuModel.activate(menuIndex, false);
162 menuModel.activate(menuIndex, false);
164− notification.dismissed()
165 }
163 }
166
164
167 property var extendedData: menuData && menuData.ext || undefined
165 property var extendedData: menuData && menuData.ext || undefined
qml/Notifications/Notifications.qml+3−25
@@ -26,7 +26,7 @@ ListView {
26 objectName: "notificationList"
26 objectName: "notificationList"
27 interactive: false
27 interactive: false
28
28
29− readonly property bool hasNotification: count > 1 // placeholder is index 0
29+ readonly property bool hasNotification: count > 0
30 property real margin
30 property real margin
31 property bool hasMouse
31 property bool hasMouse
32 property url background: ""
32 property url background: ""
@@ -42,17 +42,10 @@ ListView {
42 filterRegExp: RegExp(UnityNotifications.Notification.SnapDecision)
42 filterRegExp: RegExp(UnityNotifications.Notification.SnapDecision)
43 }
43 }
44
44
45− readonly property bool topmostIsFullscreen: fullscreenIndex != -1
45+ property bool topmostIsFullscreen: false
46 spacing: topmostIsFullscreen ? 0 : units.gu(1)
46 spacing: topmostIsFullscreen ? 0 : units.gu(1)
47
47
48− currentIndex: count > 1 ? 1 : -1
48+ currentIndex: -1
49−
50− property int fullscreenIndex: -1
51− onFullscreenIndexChanged: {
52− if (fullscreenIndex != -1) {
53− positionViewAtIndex(fullscreenIndex, ListView.Beginning);
54− }
55− }
56
49
57 delegate: Notification {
50 delegate: Notification {
58 objectName: "notification" + index
51 objectName: "notification" + index
@@ -76,21 +69,6 @@ ListView {
76 // elements in a notification
69 // elements in a notification
77 // FIXME: disabled all transitions because of LP: #1354406 workaround
70 // FIXME: disabled all transitions because of LP: #1354406 workaround
78 //layer.enabled: add.running || remove.running || populate.running
71 //layer.enabled: add.running || remove.running || populate.running
79−
80− onFullscreenChanged: updateListTopMostIsFullscreen();
81−
82− function updateListTopMostIsFullscreen() {
83− if (fullscreen) {
84− fullscreenIndex = index;
85− }
86− }
87−
88− onDismissed: {
89− if (fullscreenIndex == index) {
90− fullscreenIndex = -1;
91− notificationList.positionViewAtBeginning();
92− }
93− }
94 }
72 }
95
73
96 // FIXME: disabled all transitions because of LP: #1354406 workaround
74 // FIXME: disabled all transitions because of LP: #1354406 workaround
tests/mocks/Unity/Notifications/MockNotificationModel.cpp+4−6
@@ -1,5 +1,5 @@
1/*
1/*
2− * Copyright 2015 Canonical Ltd.
2+ * Copyright 2015-2016 Canonical Ltd.
3 *
3 *
4 * This program is free software; you can redistribute it and/or modify
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
5 * it under the terms of the GNU Lesser General Public License as published by
@@ -13,8 +13,6 @@
13 * You should have received a copy of the GNU Lesser General Public License
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/>.
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
15 *
16− * Authors:
17− * Mirco Mueller <mirco.mueller@canonical.com>
18 */
16 */
19
17
20#include "MockNotificationModel.h"
18#include "MockNotificationModel.h"
@@ -118,10 +116,10 @@ void MockNotificationModel::remove(const int id) {
118 }
116 }
119}
117}
120
118
121−void MockNotificationModel::removeSecond() {
119+void MockNotificationModel::removeFirst() {
122− if(m_queue.size() < 2)
120+ if(m_queue.isEmpty())
123 return;
121 return;
124− removeInternal(1);
122+ removeInternal(0);
125}
123}
126
124
127void MockNotificationModel::removeInternal(int loc) {
125void MockNotificationModel::removeInternal(int loc) {
tests/mocks/Unity/Notifications/MockNotificationModel.h+2−4
@@ -1,5 +1,5 @@
1/*
1/*
2− * Copyright 2015 Canonical Ltd.
2+ * Copyright 2015-2016 Canonical Ltd.
3 *
3 *
4 * This program is free software; you can redistribute it and/or modify
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
5 * it under the terms of the GNU Lesser General Public License as published by
@@ -13,8 +13,6 @@
13 * You should have received a copy of the GNU Lesser General Public License
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/>.
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
15 *
16− * Authors:
17− * Mirco Mueller <mirco.mueller@canonical.com>
18 */
16 */
19
17
20#ifndef MOCK_NOTIFICATION_MODEL_H
18#ifndef MOCK_NOTIFICATION_MODEL_H
@@ -48,7 +46,7 @@ public:
48
46
49 Q_INVOKABLE int queued() const;
47 Q_INVOKABLE int queued() const;
50 Q_INVOKABLE void remove(const int id);
48 Q_INVOKABLE void remove(const int id);
51− Q_INVOKABLE void removeSecond();
49+ Q_INVOKABLE void removeFirst();
52
50
53 int getCount() const;
51 int getCount() const;
54
52
tests/qmltests/Notifications/tst_Notifications.qml+6−23
@@ -1,5 +1,5 @@
1/*
1/*
2− * Copyright 2015 Canonical Ltd.
2+ * Copyright 2015-2016 Canonical Ltd.
3 *
3 *
4 * This program is free software; you can redistribute it and/or modify
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
5 * it under the terms of the GNU Lesser General Public License as published by
@@ -31,21 +31,6 @@ Item {
31 height: notificationsRect.height
31 height: notificationsRect.height
32 property int index: 0
32 property int index: 0
33
33
34− // add the default/PlaceHolder notification to the model
35− Component.onCompleted: {
36− var component = Qt.createComponent("Notification.qml")
37− var n = component.createObject("notification", {"nid": index++,
38− "type": Notification.PlaceHolder,
39− "hints": {},
40− "summary": "",
41− "body": "",
42− "icon": "",
43− "secondaryIcon": "",
44− "rawActions": []})
45− n.completed.connect(mockModel.onCompleted)
46− mockModel.append(n)
47− }
48−
49 Row {
34 Row {
50 id: rootRow
35 id: rootRow
51
36
@@ -157,15 +142,13 @@ Item {
157 }
142 }
158
143
159 function clearNotifications() {
144 function clearNotifications() {
160− while(mockModel.count > 1) {
145+ while(mockModel.count > 0) {
161− remove1stNotification()
146+ remove1stNotification();
162 }
147 }
163 }
148 }
164
149
165 function remove1stNotification() {
150 function remove1stNotification() {
166− if (mockModel.count > 1) {
151+ mockModel.removeFirst();
167− mockModel.removeSecond()
168− }
169 }
152 }
170
153
171 Rectangle {
154 Rectangle {
@@ -791,13 +774,13 @@ Item {
791 waitForRendering(notifications);
774 waitForRendering(notifications);
792
775
793 // first one should be expanded by default
776 // first one should be expanded by default
794− var notification1 = findChild(notifications, "notification1") // 0 is placeholder...
777+ var notification1 = findChild(notifications, "notification0")
795 verify(!!notification1, "notification wasn't found");
778 verify(!!notification1, "notification wasn't found");
796 waitForRendering(notification1);
779 waitForRendering(notification1);
797 verify(notification1.expanded);
780 verify(notification1.expanded);
798
781
799 // click the 2nd one, verify it's now expanded
782 // click the 2nd one, verify it's now expanded
800− var notification2 = findChild(notifications, "notification2") // 0 is placeholder...
783+ var notification2 = findChild(notifications, "notification1")
801 verify(!!notification2, "notification wasn't found");
784 verify(!!notification2, "notification wasn't found");
802 waitForRendering(notification2);
785 waitForRendering(notification2);
803 mouseClick(notification2);
786 mouseClick(notification2);
tests/qmltests/Notifications/tst_OptionToggle.qml+1−16
@@ -1,5 +1,5 @@
1/*
1/*
2− * Copyright 2015 Canonical Ltd.
2+ * Copyright 2015-2016 Canonical Ltd.
3 *
3 *
4 * This program is free software; you can redistribute it and/or modify
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
5 * it under the terms of the GNU Lesser General Public License as published by
@@ -51,21 +51,6 @@ Row {
51 function getRaw(id) {
51 function getRaw(id) {
52 return mockNotification.createObject(mockModel)
52 return mockNotification.createObject(mockModel)
53 }
53 }
54−
55− // add the default/PlaceHolder notification to the model
56− Component.onCompleted: {
57− var n = {
58− type: Notification.PlaceHolder,
59− hints: {},
60− summary: "",
61− body: "",
62− icon: "",
63− secondaryIcon: "",
64− actions: []
65− }
66−
67− append(n)
68− }
69 }
54 }
70
55
71 function addSnapDecisionNotification() {
56 function addSnapDecisionNotification() {
tests/qmltests/Notifications/tst_SwipeToAct.qml+4−18
@@ -1,5 +1,5 @@
1/*
1/*
2− * Copyright (C) 2014, 2015 Canonical, Ltd.
2+ * Copyright (C) 2014-2016 Canonical, Ltd.
3 *
3 *
4 * This program is free software; you can redistribute it and/or modify
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
5 * it under the terms of the GNU General Public License as published by
@@ -53,21 +53,6 @@ Item {
53 function getRaw(id) {
53 function getRaw(id) {
54 return mockNotification.createObject(mockModel)
54 return mockNotification.createObject(mockModel)
55 }
55 }
56−
57− // add the default/PlaceHolder notification to the model
58− Component.onCompleted: {
59− var n = {
60− type: Notification.PlaceHolder,
61− hints: {},
62− summary: "",
63− body: "",
64− icon: "",
65− secondaryIcon: "",
66− actions: []
67− }
68−
69− append(n)
70− }
71 }
56 }
72
57
73 function addSwipeToActNotification() {
58 function addSwipeToActNotification() {
@@ -93,8 +78,9 @@ Item {
93 }
78 }
94
79
95 function remove1stNotification() {
80 function remove1stNotification() {
96− if (mockModel.count > 0)
81+ if (mockModel.count > 0) {
97− mockModel.remove(0)
82+ mockModel.remove(0);
83+ }
98 }
84 }
99
85
100 Rectangle {
86 Rectangle {
tests/qmltests/Notifications/tst_VisualSnapDecisionsQueue.qml+7−23
@@ -47,21 +47,6 @@ Row {
47 function getRaw(id) {
47 function getRaw(id) {
48 return mockNotification.createObject(mockModel)
48 return mockNotification.createObject(mockModel)
49 }
49 }
50−
51− // add the default/PlaceHolder notification to the model
52− Component.onCompleted: {
53− var n = {
54− type: Notification.PlaceHolder,
55− hints: {},
56− summary: "",
57− body: "",
58− icon: "",
59− secondaryIcon: "",
60− actions: []
61− }
62−
63− append(n)
64− }
65 }
50 }
66
51
67 function addSomeSnapDecisionNotifications() {
52 function addSomeSnapDecisionNotifications() {
@@ -123,14 +108,13 @@ Row {
123 }
108 }
124
109
125 function clearNotifications() {
110 function clearNotifications() {
126− // remove all but the first (PlaceHolder) notification
127− mockModel.remove(1, mockModel.count - 1)
111+ mockModel.clear();
128 }
112 }
129
113
130 function removeTopMostNotification() {
114 function removeTopMostNotification() {
131− // leave real/first (PlaceHolder) notification untouched
132− if (mockModel.count > 1)
115+ if (mockModel.count > 0) {
133− mockModel.remove(1)
116+ mockModel.remove(0);
117+ }
134 }
118 }
135
119
136 Rectangle {
120 Rectangle {
@@ -205,11 +189,11 @@ Row {
205 notifications.forceLayout();
189 notifications.forceLayout();
206 waitForRendering(notifications);
190 waitForRendering(notifications);
207
191
208− var snap_decision = [findChild(notifications, "notification1"),
192+ var snap_decision = [findChild(notifications, "notification0"),
193+ findChild(notifications, "notification1"),
209 findChild(notifications, "notification2"),
194 findChild(notifications, "notification2"),
210 findChild(notifications, "notification3"),
195 findChild(notifications, "notification3"),
211− findChild(notifications, "notification4"),
196+ findChild(notifications, "notification4")]
212− findChild(notifications, "notification5")]
213
197
214 for (var index = 0; index < snap_decision.length; index++) {
198 for (var index = 0; index < snap_decision.length; index++) {
215 verify(snap_decision[index] !== undefined, index + ". snap-decision wasn't found");
199 verify(snap_decision[index] !== undefined, index + ". snap-decision wasn't found");