on 795e53c help sign in
unity8/qml/Notifications/Notification.qml
405 lines 13 kB history raw
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 */
17import QtQuick 2.0
18import QtMultimedia 5.0
19import Ubuntu.Components 0.1
20import Unity.Notifications 1.0
21import QMenuModel 0.1
22import Utils 0.1
24Item {
25 id: notification
27 property alias iconSource: icon.fileSource
28 property alias secondaryIconSource: secondaryIcon.source
29 property alias summary: summaryLabel.text
30 property alias body: bodyLabel.text
31 property var actions
32 property var notificationId
33 property var type
34 property var hints
35 property var notification
36 property color color
37 property bool fullscreen
38 property int maxHeight
39 property int margins
41 fullscreen: false
42 objectName: "background"
43 implicitHeight: type !== Notification.PlaceHolder ? (fullscreen ? maxHeight : contentColumn.height + contentColumn.spacing * 2) : 0
45 color: Qt.rgba(0.132, 0.117, 0.109, 0.97)
46 opacity: 0
48 state: {
49 var result = "";
51 if (type == Notification.SnapDecision) {
52 if (ListView.view.currentIndex == index) {
53 result = "expanded";
54 } else {
55 if (ListView.view.count > 2) {
56 if (ListView.view.currentIndex == -1 && index == 1) {
57 result = "expanded";
58 } else {
59 result = "contracted";
60 }
61 } else {
62 result = "expanded";
63 }
64 }
65 }
67 return result;
68 }
70 Audio {
71 id: sound
72 objectName: "sound"
73 source: hints["suppress-sound"] != "" ? hints["sound-file"] : undefined
74 }
76 onOpacityChanged: {
77 if (opacity == 1.0 && hints["suppress-sound"] != "true" && sound.source) {
78 sound.play();
79 }
80 }
82 Behavior on height {
83 id: normalHeightBehavior
85 //enabled: menuItemFactory.progress == 1
86 enabled: true
87 SequentialAnimation {
88 PauseAnimation {
89 duration: UbuntuAnimation.SnapDuration
90 }
91 UbuntuNumberAnimation {
92 duration: UbuntuAnimation.SnapDuration
93 }
94 }
95 }
97 states:[
98 State {
99 name: "contracted"
100 PropertyChanges {target: notification; height: units.gu(8)}
101 },
102 State {
103 name: "expanded"
104 PropertyChanges {target: notification; height: implicitHeight}
105 }
106 ]
108 clip: fullscreen ? false : true
110 visible: type != Notification.PlaceHolder
112 UbuntuShape {
113 id: shapedBack
115 visible: !fullscreen
116 anchors {
117 fill: parent
118 leftMargin: notification.margins
119 rightMargin: notification.margins
120 }
121 color: parent.color
122 opacity: parent.opacity
123 radius: "medium"
124 }
126 Rectangle {
127 id: nonShapedBack
129 visible: fullscreen
130 anchors.fill: parent
131 color: parent.color
132 opacity: parent.opacity
133 }
135 Item {
136 id: contents
137 anchors.fill: fullscreen ? nonShapedBack : shapedBack
139 UnityMenuModelPaths {
140 id: paths
142 source: hints["x-canonical-private-menu-model"]
144 busNameHint: "busName"
145 actionsHint: "actions"
146 menuObjectPathHint: "menuPath"
147 }
149 UnityMenuModel {
150 id: unityMenuModel
152 busName: paths.busName
153 actions: paths.actions
154 menuObjectPath: paths.menuObjectPath
155 }
157 Behavior on implicitHeight {
158 id: heightBehavior
160 enabled: false
161 UbuntuNumberAnimation {
162 duration: UbuntuAnimation.SnapDuration
163 }
164 }
166 // delay enabling height behavior until the add transition is complete
167 onOpacityChanged: if (opacity == 1) heightBehavior.enabled = true
169 MouseArea {
170 id: interactiveArea
172 anchors.fill: parent
173 objectName: "interactiveArea"
174 onClicked: {
175 if (notification.type == Notification.Interactive) {
176 notification.notification.invokeAction(actionRepeater.itemAt(0).actionId)
177 } else {
178 notificationList.currentIndex = index;
179 }
180 }
181 }
183 Column {
184 id: contentColumn
185 objectName: "contentColumn"
187 anchors {
188 left: parent.left
189 right: parent.right
190 top: parent.top
191 margins: fullscreen ? 0 : spacing
192 }
194 spacing: units.gu(1)
196 Row {
197 id: topRow
199 spacing: contentColumn.spacing
200 anchors {
201 left: parent.left
202 right: parent.right
203 }
205 ShapedIcon {
206 id: icon
208 objectName: "icon"
209 width: units.gu(6)
210 height: units.gu(6)
211 shaped: notification.hints["x-canonical-non-shaped-icon"] == "true" ? false : true
212 visible: iconSource !== undefined && iconSource != ""
213 }
215 Image {
216 id: secondaryIcon
218 objectName: "secondaryIcon"
219 width: units.gu(2)
220 height: units.gu(2)
221 visible: source !== undefined && source != ""
222 fillMode: Image.PreserveAspectCrop
223 }
225 Column {
226 id: labelColumn
227 width: parent.width - x
229 anchors.verticalCenter: (icon.visible && !bodyLabel.visible) ? icon.verticalCenter : undefined
231 Label {
232 id: summaryLabel
234 objectName: "summaryLabel"
235 anchors {
236 left: parent.left
237 right: parent.right
238 }
239 fontSize: "medium"
240 font.bold: true
241 color: Theme.palette.selected.backgroundText
242 elide: Text.ElideRight
243 }
245 Label {
246 id: bodyLabel
248 objectName: "bodyLabel"
249 anchors {
250 left: parent.left
251 right: parent.right
252 }
253 visible: body != ""
254 fontSize: "small"
255 color: Theme.palette.selected.backgroundText
256 opacity: 0.6
257 wrapMode: Text.WordWrap
258 maximumLineCount: 10
259 elide: Text.ElideRight
260 }
261 }
262 }
264 Column {
265 objectName: "dialogListView"
266 spacing: units.gu(2)
268 visible: count > 0
270 anchors.left: parent.left; anchors.right: parent.right
271 anchors.top: fullscreen ? parent.top : undefined
272 anchors.bottom: fullscreen ? parent.bottom : undefined
274 Repeater {
275 model: unityMenuModel
277 NotificationMenuItemFactory {
278 id: menuItemFactory
280 anchors.left: parent.left; anchors.right: parent.right
282 menuModel: unityMenuModel
283 menuData: model
284 menuIndex: index
285 maxHeight: notification.maxHeight
287 onLoaded: {
288 notification.fullscreen = Qt.binding(function() { return fullscreen; });
289 }
290 }
291 }
292 }
294 Item {
295 id: buttonRow
297 objectName: "buttonRow"
298 anchors {
299 left: parent.left
300 right: parent.right
301 }
302 visible: notification.type == Notification.SnapDecision && actionRepeater.count > 0
303 height: units.gu(5)
305 property real buttonWidth: (width - contentColumn.spacing) / 2
306 property bool expanded
308 Button {
309 id: leftButton
311 objectName: "button1"
312 width: parent.expanded ? parent.width : parent.buttonWidth
313 anchors {
314 top: parent.top
315 bottom: parent.bottom
316 }
317 text: notification.type == Notification.SnapDecision && actionRepeater.count >= 2 ? actionRepeater.itemAt(1).actionLabel : ""
318 gradient: UbuntuColors.greyGradient
319 onClicked: {
320 if (actionRepeater.count > 2) {
321 buttonRow.expanded = !buttonRow.expanded
322 } else {
323 notification.notification.invokeAction(actionRepeater.itemAt(1).actionId)
324 }
325 }
327 Behavior on width {
328 UbuntuNumberAnimation {
329 duration: UbuntuAnimation.SnapDuration
330 }
331 }
332 }
334 Button {
335 id: rightButton
337 objectName: "button0"
338 anchors {
339 left: leftButton.right
340 leftMargin: contentColumn.spacing
341 right: parent.right
342 }
343 text: notification.type == Notification.SnapDecision && actionRepeater.count >= 1 ? actionRepeater.itemAt(0).actionLabel : ""
344 anchors {
345 top: parent.top
346 bottom: parent.bottom
347 }
348 gradient: notification.hints["x-canonical-private-button-tint"] == "true" ? UbuntuColors.orangeGradient : UbuntuColors.greyGradient
349 visible: width > 0
350 onClicked: notification.notification.invokeAction(actionRepeater.itemAt(0).actionId)
351 }
352 }
354 Column {
355 objectName: "buttonColumn"
356 spacing: contentColumn.spacing
357 anchors {
358 left: parent.left
359 right: parent.right
360 }
362 // calculate initial position before Column takes over
363 y: buttonRow.y + buttonRow.height + contentColumn.spacing
365 visible: notification.type == Notification.SnapDecision && buttonRow.expanded
366 height: buttonRow.expanded ? implicitHeight : 0
368 Repeater {
369 id: actionRepeater
371 model: notification.actions
372 delegate: Loader {
373 id: loader
375 property string actionId: id
376 property string actionLabel: label
378 anchors {
379 left: parent.left
380 right: parent.right
381 }
383 Component {
384 id: actionButton
386 Button {
387 objectName: "button" + index
388 anchors {
389 left: parent.left
390 right: parent.right
391 }
393 text: loader.actionLabel
394 height: units.gu(5)
395 gradient: UbuntuColors.greyGradient
396 onClicked: notification.notification.invokeAction(loader.actionId)
397 }
398 }
399 sourceComponent: (index == 0 || index == 1) ? undefined : actionButton
400 }
401 }
402 }
403 }
404 }