on xenial help sign in
Integrate notifications.
a467fa8Mirco Müller
Notifications/Notification.qml+10−7
@@ -16,18 +16,19 @@
16
16
17import QtQuick 2.0
17import QtQuick 2.0
18import Ubuntu.Components 0.1
18import Ubuntu.Components 0.1
19+import Unity.Notifications 1.0
19
20
20UbuntuShape {
21UbuntuShape {
21 id: notification
22 id: notification
22
23
23− property string type
24 property alias iconSource: avatarIcon.source
24 property alias iconSource: avatarIcon.source
25 property alias secondaryIconSource: secondaryIcon.source
25 property alias secondaryIconSource: secondaryIcon.source
26 property alias summary: summaryLabel.text
26 property alias summary: summaryLabel.text
27 property alias body: bodyLabel.text
27 property alias body: bodyLabel.text
28 property var actions
28 property var actions
29−
29+ property var notificationId
30− signal actionInvoked(string buttonId)
30+ property var type
31+ property var notification
31
32
32 implicitHeight: childrenRect.height
33 implicitHeight: childrenRect.height
33 color: Qt.rgba(0, 0, 0, 0.85)
34 color: Qt.rgba(0, 0, 0, 0.85)
@@ -38,8 +39,8 @@ UbuntuShape {
38
39
39 anchors.fill: contentColumn
40 anchors.fill: contentColumn
40 objectName: "interactiveArea"
41 objectName: "interactiveArea"
41− enabled: notification.type == "Notifications.Type.Interactive"
42+ enabled: notification.type == Notification.Interactive
42− onClicked: notification.actionInvoked(actions.get(0).id)
43+ onClicked: notification.notification.invokeAction(actionRepeater.itemAt(0).actionId)
43 }
44 }
44
45
45 Column {
46 Column {
@@ -130,13 +131,14 @@ UbuntuShape {
130 objectName: "buttonRow"
131 objectName: "buttonRow"
131 spacing: contentColumn.spacing
132 spacing: contentColumn.spacing
132 layoutDirection: Qt.RightToLeft
133 layoutDirection: Qt.RightToLeft
133− visible: notification.type == "Notifications.Type.SnapDecision"
134+ visible: notification.type == Notification.SnapDecision
134 anchors {
135 anchors {
135 left: parent.left
136 left: parent.left
136 right: parent.right
137 right: parent.right
137 }
138 }
138
139
139 Repeater {
140 Repeater {
141+ id: actionRepeater
140 model: notification.actions
142 model: notification.actions
141
143
142 Button {
144 Button {
@@ -145,7 +147,8 @@ UbuntuShape {
145 width: (buttonRow.width - buttonRow.spacing) / 2
147 width: (buttonRow.width - buttonRow.spacing) / 2
146 height: units.gu(4)
148 height: units.gu(4)
147 text: label
149 text: label
150+ property string actionId: id
148− onClicked: notification.actionInvoked(id)
151+ onClicked: notification.notification.invokeAction(id)
149 }
152 }
150 }
153 }
151 }
154 }
Notifications/Notifications.qml+4−2
@@ -20,9 +20,9 @@ import "../Components"
20import "timings.js" as Timings
20import "timings.js" as Timings
21
21
22ListView {
22ListView {
23− id: notificationRenderer
23+ id: notificationList
24
24
25− objectName: "notificationRenderer"
25+ objectName: "notificationList"
26 interactive: false
26 interactive: false
27
27
28 spacing: units.gu(.5)
28 spacing: units.gu(.5)
@@ -38,6 +38,8 @@ ListView {
38 summary: model.summary
38 summary: model.summary
39 body: model.body
39 body: model.body
40 actions: model.actions
40 actions: model.actions
41+ notificationId: model.id
42+ notification: notificationList.model.getRaw(notificationId)
41 }
43 }
42
44
43 populate: Transition {
45 populate: Transition {
Shell.qml+14
@@ -27,6 +27,8 @@ import "Components"
27import "Components/Math.js" as MathLocal
27import "Components/Math.js" as MathLocal
28import "Bottombar"
28import "Bottombar"
29import "SideStage"
29import "SideStage"
30+import "Notifications"
31+import Unity.Notifications 1.0 as NotificationBackend
30
32
31FocusScope {
33FocusScope {
32 id: shell
34 id: shell
@@ -170,6 +172,18 @@ FocusScope {
170 // greeterRevealer.animatedProgress are not animated
172 // greeterRevealer.animatedProgress are not animated
171 Behavior on disappearingAnimationProgress { SmoothedAnimation { velocity: 5 }}
173 Behavior on disappearingAnimationProgress { SmoothedAnimation { velocity: 5 }}
172 }
174 }
175+
176+ Notifications {
177+ id: notifications
178+
179+ model: NotificationBackend.Model
180+ anchors {
181+ fill: parent
182+ leftMargin: units.gu(1)
183+ rightMargin: units.gu(1)
184+ topMargin: panel.panelHeight + units.gu(1)
185+ }
186+ }
173 }
187 }
174
188
175
189
debian/control+2
@@ -40,6 +40,8 @@ Architecture: amd64 armhf i386
40Depends: indicators-client (>= 0.6.1),
40Depends: indicators-client (>= 0.6.1),
41 qtdeclarative5-dee-plugin,
41 qtdeclarative5-dee-plugin,
42 qtdeclarative5-ubuntu-ui-toolkit-plugin,
42 qtdeclarative5-ubuntu-ui-toolkit-plugin,
43+ qtdeclarative5-unity-notifications-plugin | unity-notifications-impl,
44+ unity-notifications-impl-1,
43 qtdeclarative5-xmllistmodel-plugin,
45 qtdeclarative5-xmllistmodel-plugin,
44 qtubuntu,
46 qtubuntu,
45 ${misc:Depends},
47 ${misc:Depends},
tests/qmltests/CMakeLists.txt+1−1
@@ -59,7 +59,7 @@ add_qml_test(Greeter Infographics IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} $
59add_qml_test(Hud Hud)
59add_qml_test(Hud Hud)
60add_qml_test(Hud Result)
60add_qml_test(Hud Result)
61add_qml_test(Launcher Launcher IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DEFAULT_IMPORT_PATHS})
61add_qml_test(Launcher Launcher IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DEFAULT_IMPORT_PATHS})
62−add_qml_test(Notifications Notifications)
62+add_qml_test(Notifications Notifications IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_CURRENT_SOURCE_DIR}/plugins)
63add_qml_test(Panel IndicatorRow)
63add_qml_test(Panel IndicatorRow)
64add_qml_test(Panel Indicators)
64add_qml_test(Panel Indicators)
65add_qml_test(Panel MenuContent)
65add_qml_test(Panel MenuContent)
tests/qmltests/Notifications/tst_Notifications.qml+30−12
@@ -20,17 +20,34 @@ import ".."
20import "../../../Notifications"
20import "../../../Notifications"
21import Ubuntu.Components 0.1
21import Ubuntu.Components 0.1
22import Unity.Test 0.1
22import Unity.Test 0.1
23+import Unity.Notifications 1.0
23
24
24Row {
25Row {
25 id: rootRow
26 id: rootRow
26
27
28+ Component {
29+ id: mockNotification
30+
31+ QtObject {
32+ function invokeAction(actionId) {
33+ mockModel.actionInvoked(actionId)
34+ }
35+ }
36+ }
37+
27 ListModel {
38 ListModel {
28 id: mockModel
39 id: mockModel
40+
41+ signal actionInvoked(string actionId)
42+
43+ function getRaw(id) {
44+ return mockNotification.createObject(mockModel)
45+ }
29 }
46 }
30
47
31 function addSnapDecisionNotification() {
48 function addSnapDecisionNotification() {
32 var n = {
49 var n = {
33− type: "Notifications.Type.SnapDecision",
50+ type: Notification.SnapDecision,
34 summary: "Tom Ato",
51 summary: "Tom Ato",
35 body: "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.",
52 body: "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.",
36 icon: "../graphics/avatars/funky.png",
53 icon: "../graphics/avatars/funky.png",
@@ -44,7 +61,7 @@ Row {
44
61
45 function addEphemeralNotification() {
62 function addEphemeralNotification() {
46 var n = {
63 var n = {
47− type: "Notifications.Type.Ephemeral",
64+ type: Notification.Ephemeral,
48 summary: "Cole Raby",
65 summary: "Cole Raby",
49 body: "I did not expect it to be that late.",
66 body: "I did not expect it to be that late.",
50 icon: "../graphics/avatars/amanda.png",
67 icon: "../graphics/avatars/amanda.png",
@@ -57,7 +74,7 @@ Row {
57
74
58 function addEphemeralIconSummaryNotification() {
75 function addEphemeralIconSummaryNotification() {
59 var n = {
76 var n = {
60− type: "Notifications.Type.Ephemeral",
77+ type: Notification.Ephemeral,
61 summary: "Photo upload completed",
78 summary: "Photo upload completed",
62 body: "",
79 body: "",
63 icon: "",
80 icon: "",
@@ -70,7 +87,7 @@ Row {
70
87
71 function addInteractiveNotification() {
88 function addInteractiveNotification() {
72 var n = {
89 var n = {
73− type: "Notifications.Type.Interactive",
90+ type: Notification.Interactive,
74 summary: "Interactive notification",
91 summary: "Interactive notification",
75 body: "This is a notification that can be clicked",
92 body: "This is a notification that can be clicked",
76 icon: "../graphics/avatars/anna_olsson.png",
93 icon: "../graphics/avatars/anna_olsson.png",
@@ -170,7 +187,7 @@ Row {
170 return [
187 return [
171 {
188 {
172 tag: "Snap Decision with secondary icon",
189 tag: "Snap Decision with secondary icon",
173− type: "Notifications.Type.SnapDecision",
190+ type: Notification.SnapDecision,
174 summary: "Tom Ato",
191 summary: "Tom Ato",
175 body: "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.",
192 body: "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.",
176 icon: "../graphics/avatars/funky.png",
193 icon: "../graphics/avatars/funky.png",
@@ -186,7 +203,7 @@ Row {
186 },
203 },
187 {
204 {
188 tag: "Ephemeral notification - icon-summary layout",
205 tag: "Ephemeral notification - icon-summary layout",
189− type: "Notifications.Type.Ephemeral",
206+ type: Notification.Ephemeral,
190 summary: "Photo upload completed",
207 summary: "Photo upload completed",
191 body: "",
208 body: "",
192 icon: "",
209 icon: "",
@@ -201,7 +218,7 @@ Row {
201 },
218 },
202 {
219 {
203 tag: "Ephemeral notification - check suppression of secondary icon for icon-summary layout",
220 tag: "Ephemeral notification - check suppression of secondary icon for icon-summary layout",
204− type: "Notifications.Type.Ephemeral",
221+ type: Notification.Ephemeral,
205 summary: "New comment successfully published",
222 summary: "New comment successfully published",
206 body: "",
223 body: "",
207 icon: "",
224 icon: "",
@@ -216,7 +233,7 @@ Row {
216 },
233 },
217 {
234 {
218 tag: "Interactive notification",
235 tag: "Interactive notification",
219− type: "Notifications.Type.Interactive",
236+ type: Notification.Interactive,
220 summary: "Interactive notification",
237 summary: "Interactive notification",
221 body: "This is a notification that can be clicked",
238 body: "This is a notification that can be clicked",
222 icon: "../graphics/avatars/amanda.png",
239 icon: "../graphics/avatars/amanda.png",
@@ -231,7 +248,7 @@ Row {
231 },
248 },
232 {
249 {
233 tag: "Snap Decision without secondary icon",
250 tag: "Snap Decision without secondary icon",
234− type: "Notifications.Type.SnapDecision",
251+ type: Notification.SnapDecision,
235 summary: "Bro Coly",
252 summary: "Bro Coly",
236 body: "At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.",
253 body: "At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.",
237 icon: "../graphics/avatars/anna_olsson.png",
254 icon: "../graphics/avatars/anna_olsson.png",
@@ -247,7 +264,7 @@ Row {
247 },
264 },
248 {
265 {
249 tag: "Ephemeral notification",
266 tag: "Ephemeral notification",
250− type: "Notifications.Type.Ephemeral",
267+ type: Notification.Ephemeral,
251 summary: "Cole Raby",
268 summary: "Cole Raby",
252 body: "I did not expect it to be that late.",
269 body: "I did not expect it to be that late.",
253 icon: "../graphics/avatars/funky.png",
270 icon: "../graphics/avatars/funky.png",
@@ -272,6 +289,8 @@ Row {
272
289
273 SignalSpy {
290 SignalSpy {
274 id: actionSpy
291 id: actionSpy
292+
293+ target: mockModel
275 signalName: "actionInvoked"
294 signalName: "actionInvoked"
276 }
295 }
277
296
@@ -303,7 +322,6 @@ Row {
303 compare(interactiveArea.enabled, data.interactiveAreaEnabled, "check for interactive area")
322 compare(interactiveArea.enabled, data.interactiveAreaEnabled, "check for interactive area")
304
323
305 if(data.interactiveAreaEnabled) {
324 if(data.interactiveAreaEnabled) {
306− actionSpy.target = notification
307 mouseClick(notification, notification.width / 2, notification.height / 2)
325 mouseClick(notification, notification.width / 2, notification.height / 2)
308 actionSpy.wait()
326 actionSpy.wait()
309 compare(actionSpy.signalArguments[0][0], data.actions[0]["id"], "got wrong id for interactive action")
327 compare(actionSpy.signalArguments[0][0], data.actions[0]["id"], "got wrong id for interactive action")
@@ -323,7 +341,6 @@ Row {
323 var buttonAccept = findChild(buttonRow, "button0")
341 var buttonAccept = findChild(buttonRow, "button0")
324
342
325 waitForRendering(notification)
343 waitForRendering(notification)
326− actionSpy.target = notification
327 mouseClick(buttonCancel, buttonCancel.width / 2, buttonCancel.height / 2)
344 mouseClick(buttonCancel, buttonCancel.width / 2, buttonCancel.height / 2)
328 actionSpy.wait()
345 actionSpy.wait()
329 compare(actionSpy.signalArguments[0][0], data.actions[1]["id"], "got wrong id for negative action")
346 compare(actionSpy.signalArguments[0][0], data.actions[1]["id"], "got wrong id for negative action")
@@ -332,6 +349,7 @@ Row {
332 mouseClick(buttonAccept, buttonAccept.width / 2, buttonAccept.height / 2)
349 mouseClick(buttonAccept, buttonAccept.width / 2, buttonAccept.height / 2)
333 actionSpy.wait()
350 actionSpy.wait()
334 compare(actionSpy.signalArguments[0][0], data.actions[0]["id"], "got wrong id positive action")
351 compare(actionSpy.signalArguments[0][0], data.actions[0]["id"], "got wrong id positive action")
352+ actionSpy.clear()
335 }
353 }
336 }
354 }
337 }
355 }
tests/qmltests/plugins/Unity/Notifications/notification.jsnew file+23
@@ -0,0 +1,23 @@
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+.pragma library
18+
19+var Confirmation = 0;
20+var Ephemeral = 1;
21+var Interactive = 2;
22+var SnapDecision = 3;
23+var PlaceHolder = 4;
tests/qmltests/plugins/Unity/Notifications/qmldirnew file+2
@@ -0,0 +1,2 @@
1+module Unity.Notifications
2+Notification 1.0 notification.js