on xenial help sign in
Added support and tests for expanding snap-decisions with more than 2 actions passed in.

Approved by PS Jenkins bot, Michael Zanetti.

commit5e8d7e4cf405a15c1e342f76b549aa02c4cdf0f5 authorMirco Müller <mirco.mueller@ubuntu.com> dateWed 3 Jul 2013, 16:14 (13 years ago) parentc3c198410fcc11
4 files changed+167−55
Notifications/Notification.qml+109−12 Notifications/Notifications.qml+10−13 Notifications/timings.js−23 tests/qmltests/Notifications/tst_Notifications.qml+48−7
Notifications/Notification.qml+109−12
@@ -30,10 +30,25 @@ UbuntuShape {
3030 property var type
3131 property var notification
3232
33− implicitHeight: childrenRect.height
33+ objectName: "background"
34+ implicitHeight: contentColumn.height + contentColumn.spacing * 2
3435 color: Qt.rgba(0, 0, 0, 0.85)
3536 opacity: 0
3637
38+ clip: true
39+
40+ Behavior on implicitHeight {
41+ id: heightBehavior
42+
43+ enabled: false
44+ UbuntuNumberAnimation {
45+ duration: UbuntuAnimation.SnapDuration
46+ }
47+ }
48+
49+ // delay enabling height behavior until the add transition is complete
50+ onOpacityChanged: if (opacity == 1) heightBehavior.enabled = true
51+
3752 MouseArea {
3853 id: interactiveArea
3954
@@ -52,7 +67,7 @@ UbuntuShape {
5267 top: parent.top
5368 margins: spacing
5469 }
55− height: childrenRect.height + spacing
70+
5671 spacing: units.gu(1)
5772
5873 Row {
@@ -125,30 +140,112 @@ UbuntuShape {
125140 }
126141 }
127142
128− Row {
143+ Item {
129144 id: buttonRow
130145
131146 objectName: "buttonRow"
132− spacing: contentColumn.spacing
133− layoutDirection: Qt.RightToLeft
147+ anchors {
148+ left: parent.left
149+ right: parent.right
150+ }
134151 visible: notification.type == Notification.SnapDecision
152+ height: units.gu(4)
153+
154+ property real buttonWidth: (width - contentColumn.spacing) / 2
155+ property bool expanded
156+
157+ Button {
158+ id: leftButton
159+
160+ objectName: "button1"
161+ width: parent.expanded ? parent.width : parent.buttonWidth
162+ anchors {
163+ top: parent.top
164+ bottom: parent.bottom
165+ }
166+ text: notification.type == Notification.SnapDecision && actionRepeater.count >= 2 ? actionRepeater.itemAt(1).actionLabel : ""
167+ color: "#cdcdcb"
168+ onClicked: {
169+ if (actionRepeater.count > 2) {
170+ buttonRow.expanded = !buttonRow.expanded
171+ } else {
172+ notification.notification.invokeAction(actionRepeater.itemAt(1).actionId)
173+ }
174+ }
175+
176+ Behavior on width {
177+ UbuntuNumberAnimation {
178+ duration: UbuntuAnimation.SnapDuration
179+ }
180+ }
181+ }
182+
183+ Button {
184+ id: rightButton
185+
186+ objectName: "button0"
187+ anchors {
188+ left: leftButton.right
189+ leftMargin: contentColumn.spacing
190+ right: parent.right
191+ }
192+ text: notification.type == Notification.SnapDecision && actionRepeater.count >= 1 ? actionRepeater.itemAt(0).actionLabel : ""
193+ anchors {
194+ top: parent.top
195+ bottom: parent.bottom
196+ }
197+ color: "#d85317"
198+ visible: width > 0
199+ onClicked: notification.notification.invokeAction(actionRepeater.itemAt(0).actionId)
200+ }
201+ }
202+
203+ Column {
204+ objectName: "buttonColumn"
205+ spacing: contentColumn.spacing
135206 anchors {
136207 left: parent.left
137208 right: parent.right
138209 }
139210
211+ // calculate initial position before Column takes over
212+ y: buttonRow.y + buttonRow.height + contentColumn.spacing
213+
214+ visible: notification.type == Notification.SnapDecision
215+ height: buttonRow.expanded ? implicitHeight : 0
216+
140217 Repeater {
141218 id: actionRepeater
219+
142220 model: notification.actions
221+ delegate: Loader {
222+ id: loader
143223
144− Button {
145− objectName: "button" + index
146− color: Positioner.isFirstItem ? "#d85317" : "#cdcdcb"
147− width: (buttonRow.width - buttonRow.spacing) / 2
148− height: units.gu(4)
149− text: label
150224 property string actionId: id
151− onClicked: notification.notification.invokeAction(id)
225+ property string actionLabel: label
226+
227+ anchors {
228+ left: parent.left
229+ right: parent.right
230+ }
231+
232+ Component {
233+ id: actionButton
234+
235+ Button {
236+ objectName: "button" + index
237+ anchors {
238+ left: parent.left
239+ right: parent.right
240+ }
241+
242+ text: loader.actionLabel
243+ height: units.gu(4)
244+ color: "#cdcdcb"
245+ onClicked: notification.notification.invokeAction(loader.actionId)
246+ }
247+ }
248+ sourceComponent: (index == 0 || index == 1) ? undefined : actionButton
152249 }
153250 }
154251 }
Notifications/Notifications.qml+10−13
@@ -17,7 +17,6 @@
1717import QtQuick 2.0
1818import Ubuntu.Components 0.1
1919import "../Components"
20−import "timings.js" as Timings
2120
2221ListView {
2322 id: notificationList
@@ -40,40 +39,38 @@ ListView {
4039 actions: model.actions
4140 notificationId: model.id
4241 notification: notificationList.model.getRaw(notificationId)
42+
43+ // make sure there's no opacity-difference between the several
44+ // elements in a notification
45+ layer.enabled: add.running || remove.running || populate.running
4346 }
4447
4548 populate: Transition {
46− NumberAnimation {
49+ UbuntuNumberAnimation {
4750 property: "opacity"
4851 to: 1
49− duration: Timings.snapBeat
50− easing.type: Timings.easing
52+ duration: UbuntuAnimation.SnapDuration
5153 }
5254 }
5355
5456 add: Transition {
55− NumberAnimation {
57+ UbuntuNumberAnimation {
5658 property: "opacity"
5759 to: 1
58− duration: Timings.snapBeat
59− easing.type: Timings.easing
60+ duration: UbuntuAnimation.SnapDuration
6061 }
6162 }
6263
6364 remove: Transition {
64− NumberAnimation {
65+ UbuntuNumberAnimation {
6566 property: "opacity"
6667 to: 0
67− duration: Timings.fastBeat
68− easing.type: Timings.easing
6968 }
7069 }
7170
7271 displaced: Transition {
73− NumberAnimation {
72+ UbuntuNumberAnimation {
7473 properties: "x,y"
75− duration: Timings.fastBeat
76− easing.type: Timings.easing
7774 }
7875 }
7976}
Notifications/timings.jsdeleted−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−var rhythm = 700;
18−var fastBeat = 0.5 * rhythm;
19−var snapBeat = 0.5 * fastBeat;
20−var slowBeat = rhythm;
21−var sleepyBeat = slowBeat * 2;
22−
23−var easing = Easing.OutQuint;
tests/qmltests/Notifications/tst_Notifications.qml+48−7
@@ -53,7 +53,10 @@ Row {
5353 icon: "../graphics/avatars/funky.png",
5454 secondaryIcon: "../graphics/applicationIcons/facebook.png",
5555 actions: [{ id: "ok_id", label: "Ok"},
56− { id: "cancel_id", label: "Cancel"}]
56+ { id: "cancel_id", label: "Cancel"},
57+ { id: "notreally_id", label: "Not really"},
58+ { id: "noway_id", label: "No way"},
59+ { id: "nada_id", label: "Nada"}]
5760 }
5861
5962 mockModel.append(n)
@@ -132,7 +135,7 @@ Row {
132135 id: interactiveControls
133136
134137 width: units.gu(30)
135− height: units.gu(71)
138+ height: units.gu(81)
136139 color: "grey"
137140
138141 Column {
@@ -193,7 +196,10 @@ Row {
193196 icon: "../graphics/avatars/funky.png",
194197 secondaryIcon: "../graphics/applicationIcons/facebook.png",
195198 actions: [{ id: "ok_id", label: "Ok"},
196− { id: "cancel_id", label: "Cancel"}],
199+ { id: "cancel_id", label: "Cancel"},
200+ { id: "notreally_id", label: "Not really"},
201+ { id: "noway_id", label: "No way"},
202+ { id: "nada_id", label: "Nada"}],
197203 summaryVisible: true,
198204 bodyVisible: true,
199205 interactiveAreaEnabled: false,
@@ -341,15 +347,50 @@ Row {
341347 var buttonAccept = findChild(buttonRow, "button0")
342348
343349 waitForRendering(notification)
344− mouseClick(buttonCancel, buttonCancel.width / 2, buttonCancel.height / 2)
345− actionSpy.wait()
346− compare(actionSpy.signalArguments[0][0], data.actions[1]["id"], "got wrong id for negative action")
347− actionSpy.clear()
348350
351+ // only test the left/cancel-button if two actions have been passed in
352+ if (data.actions.length == 2) {
353+ mouseClick(buttonCancel, buttonCancel.width / 2, buttonCancel.height / 2)
354+ actionSpy.wait()
355+ compare(actionSpy.signalArguments[0][0], data.actions[1]["id"], "got wrong id for negative action")
356+ actionSpy.clear()
357+ }
358+
359+ // click the positive/right button
349360 mouseClick(buttonAccept, buttonAccept.width / 2, buttonAccept.height / 2)
350361 actionSpy.wait()
351362 compare(actionSpy.signalArguments[0][0], data.actions[0]["id"], "got wrong id positive action")
352363 actionSpy.clear()
364+
365+ // check if there's more than one negative choice
366+ if (data.actions.length > 2) {
367+ var initialHeight = notification.height
368+
369+ // click to expand
370+ mouseClick(buttonCancel, buttonCancel.width / 2, buttonCancel.height / 2)
371+ waitForRendering(notification)
372+ actionSpy.clear()
373+ 
374+ // test the additional buttons
375+ for (var i = 2; i < data.actions.length; i++) {
376+ waitForRendering(notification)
377+ var buttonColumn = findChild(notification, "buttonColumn")
378+ var button = findChild(buttonColumn, "button" + i)
379+ mouseClick(button, button.width / 2, button.height / 2)
380+ actionSpy.wait()
381+ compare(actionSpy.signalArguments[0][0], data.actions[i]["id"], "got wrong id for additional negative action")
382+ actionSpy.clear()
383+ }
384+
385+ // click to collapse
386+ mouseClick(buttonCancel, buttonCancel.width / 2, buttonCancel.height / 2)
387+ waitForRendering(notification)
388+ tryCompare(notification, "height", initialHeight)
389+ } else {
390+ mouseClick(buttonCancel, buttonCancel.width / 2, buttonCancel.height / 2)
391+ actionSpy.wait()
392+ compare(actionSpy.signalArguments[0][0], data.actions[1]["id"], "got wrong id for negative action")
393+ }
353394 }
354395 }
355396 }