Merge lp:~artmello/ubuntu-calendar-app/ubuntu-calendar-app-fix_1563316 into lp:ubuntu-calendar-app
- ubuntu-calendar-app-fix_1563316
- Merge into trunk
Status: | Merged | ||||
---|---|---|---|---|---|
Approved by: | Renato Araujo Oliveira Filho | ||||
Approved revision: | 814 | ||||
Merged at revision: | 811 | ||||
Proposed branch: | lp:~artmello/ubuntu-calendar-app/ubuntu-calendar-app-fix_1563316 | ||||
Merge into: | lp:ubuntu-calendar-app | ||||
Diff against target: |
397 lines (+256/-21) 4 files modified
EventBubble.qml (+42/-15) TimeLineBaseComponent.qml (+1/-1) tests/unittests/tst_calendar_canvas.qml (+5/-5) tests/unittests/tst_event_bubble.qml (+208/-0) |
||||
To merge this branch: | bzr merge lp:~artmello/ubuntu-calendar-app/ubuntu-calendar-app-fix_1563316 | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Renato Araujo Oliveira Filho (community) | Approve | ||
Jenkins Bot | continuous-integration | Approve | |
Review via email: mp+290317@code.launchpad.net |
Commit message
Change Event Bubble style depending if user is attending the event following design spec
Description of the change
Change Event Bubble style depending if user is attending the event following design spec
Testing
=======
Import from google account events with different attendee status (Yes/Maybe/No) both for future and past end times. Make sure that the event bubble is updated as expected
Jenkins Bot (ubuntu-core-apps-jenkins-bot) wrote : | # |
- 810. By Arthur Mello
-
Fix when requesting owner status for local events
Jenkins Bot (ubuntu-core-apps-jenkins-bot) wrote : | # |
PASSED: Continuous integration, rev:810
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild:
https:/
- 811. By Arthur Mello
-
Fix calendar canvas unittest
Jenkins Bot (ubuntu-core-apps-jenkins-bot) wrote : | # |
PASSED: Continuous integration, rev:811
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild:
https:/
- 812. By Arthur Mello
-
Merge with trunk
- 813. By Arthur Mello
-
Add unit test
Jenkins Bot (ubuntu-core-apps-jenkins-bot) wrote : | # |
PASSED: Continuous integration, rev:813
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild:
https:/
- 814. By Arthur Mello
-
Add border with same color as collection for unaswered events
Jenkins Bot (ubuntu-core-apps-jenkins-bot) wrote : | # |
PASSED: Continuous integration, rev:814
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild:
https:/
Renato Araujo Oliveira Filho (renatofilho) wrote : | # |
great job.
Preview Diff
1 | === modified file 'EventBubble.qml' |
2 | --- EventBubble.qml 2016-03-28 18:14:09 +0000 |
3 | +++ EventBubble.qml 2016-03-31 19:20:26 +0000 |
4 | @@ -38,7 +38,14 @@ |
5 | property Flickable flickable; |
6 | property bool isEventBubble: true |
7 | property real minimumHeight: units.gu(4) |
8 | + |
9 | + // Event bubble style |
10 | + property alias titleText: eventTitle.text |
11 | + property alias titleColor: eventTitle.color |
12 | property alias strikeoutTitle: eventTitle.font.strikeout |
13 | + property alias backgroundColor: bg.color |
14 | + property alias backgroundOpacity: bg.opacity |
15 | + property color borderColor: "white" |
16 | |
17 | readonly property bool isSingleLine: (infoBubble.height < (minimumHeight * 2)) |
18 | readonly property real startTimeInMinutes: event ? CanlendarCanvas.minutesSince(infoBubble.anchorDate, event.startDateTime) : 0.0 |
19 | @@ -52,10 +59,10 @@ |
20 | Connections { |
21 | target: model |
22 | ignoreUnknownSignals: true |
23 | - onCollectionsChanged: assignBgColor() |
24 | + onCollectionsChanged: updateEventBubbleStyle() |
25 | } |
26 | |
27 | - function assignBgColor() { |
28 | + function updateEventBubbleStyle() { |
29 | if (model && event ) { |
30 | var collection = model.collection( event.collectionId ); |
31 | var now = new Date(); |
32 | @@ -64,15 +71,35 @@ |
33 | endDateTime = event.startDateTime; |
34 | } |
35 | |
36 | + updateTitle() |
37 | + |
38 | + //Accepted events: Solid collection color with white text. |
39 | + infoBubble.backgroundColor = collection.color |
40 | + infoBubble.backgroundOpacity = 1 |
41 | + infoBubble.titleColor = "white"; |
42 | + infoBubble.strikeoutTitle = false; |
43 | + infoBubble.borderColor = "white"; |
44 | + |
45 | if( endDateTime >= now) { |
46 | - bg.color = collection.color |
47 | - |
48 | - if( getOwnersStatus(collection) === EventAttendee.StatusDeclined ) { |
49 | + var ownersStatus = getOwnersStatus(collection); |
50 | + if (ownersStatus === EventAttendee.StatusDeclined) { |
51 | + // Declined events: As per accepted events with strike-through text. |
52 | infoBubble.strikeoutTitle = true; |
53 | + |
54 | + } else if (ownersStatus === EventAttendee.StatusTentative) { |
55 | + //Maybe events: As per accepted events with ‘(?)’ placed before Event Title. |
56 | + infoBubble.titleText = "(?) " + infoBubble.titleText |
57 | + |
58 | + } else if (ownersStatus !== EventAttendee.StatusAccepted) { |
59 | + //Unresponded events: Accepted event colours inverted (i.e. collection color text/ outline on white background). |
60 | + infoBubble.backgroundColor = "white" |
61 | + infoBubble.titleColor = collection.color; |
62 | + infoBubble.borderColor = collection.color; |
63 | + |
64 | } |
65 | } else { |
66 | - //if event is on past then add some white color to original color |
67 | - bg.color = Qt.tint( collection.color, "#aaffffff" ); |
68 | + // Past events: As per accepted events, but at 75% transparency. |
69 | + infoBubble.backgroundOpacity = 0.25 |
70 | } |
71 | } |
72 | } |
73 | @@ -89,6 +116,8 @@ |
74 | } |
75 | } |
76 | } |
77 | + |
78 | + return EventAttendee.StatusAccepted; |
79 | } |
80 | |
81 | function updateTitle() { |
82 | @@ -106,12 +135,12 @@ |
83 | |
84 | //there is space for two lines |
85 | if (infoBubble.isSingleLine) { |
86 | - eventTitle.text = ("%1 %2").arg(timeString).arg(event.displayLabel); |
87 | + infoBubble.titleText = ("%1 %2").arg(timeString).arg(event.displayLabel); |
88 | } else { |
89 | - eventTitle.text = ("%1\n%2").arg(timeString).arg(event.displayLabel); |
90 | + infoBubble.titleText = ("%1\n%2").arg(timeString).arg(event.displayLabel); |
91 | } |
92 | } else { |
93 | - eventTitle.text = event.displayLabel |
94 | + infoBubble.titleText = event.displayLabel |
95 | } |
96 | } |
97 | |
98 | @@ -124,10 +153,9 @@ |
99 | height = Math.max(minimumHeight, durationInMinutes * parent.minuteHeight) |
100 | } |
101 | |
102 | - onIsSingleLineChanged: updateTitle() |
103 | + onIsSingleLineChanged: updateEventBubbleStyle() |
104 | onEventChanged: { |
105 | - assignBgColor() |
106 | - updateTitle() |
107 | + updateEventBubbleStyle() |
108 | resize() |
109 | } |
110 | |
111 | @@ -146,7 +174,7 @@ |
112 | Rectangle{ |
113 | id: bg |
114 | anchors.fill: parent |
115 | - border.color: isLiveEditing ? "red" : "white" |
116 | + border.color: isLiveEditing ? "red" : infoBubble.borderColor |
117 | } |
118 | |
119 | Label { |
120 | @@ -158,7 +186,6 @@ |
121 | } |
122 | clip: true |
123 | fontSize: "small" |
124 | - color: "White" |
125 | font.bold: true |
126 | } |
127 | |
128 | |
129 | === modified file 'TimeLineBaseComponent.qml' |
130 | --- TimeLineBaseComponent.qml 2016-03-22 13:52:25 +0000 |
131 | +++ TimeLineBaseComponent.qml 2016-03-31 19:20:26 +0000 |
132 | @@ -347,7 +347,7 @@ |
133 | onPositionChanged: { |
134 | dropArea.modifyEventForDrag(drag) |
135 | var eventBubble = drag.source; |
136 | - eventBubble.assignBgColor(); |
137 | + eventBubble.updateEventBubbleStyle(); |
138 | |
139 | if( eventBubble.y + eventBubble.height + units.gu(8) > timeLineView.contentY + timeLineView.height ) { |
140 | var diff = Math.abs((eventBubble.y + eventBubble.height + units.gu(8)) - |
141 | |
142 | === modified file 'tests/unittests/tst_calendar_canvas.qml' |
143 | --- tests/unittests/tst_calendar_canvas.qml 2016-03-02 00:24:42 +0000 |
144 | +++ tests/unittests/tst_calendar_canvas.qml 2016-03-31 19:20:26 +0000 |
145 | @@ -639,34 +639,34 @@ |
146 | compare(eventsA.event.displayLabel, "Event at 14:15 until 15:15") |
147 | compare(eventsA.y, 0) |
148 | compare(eventsA.intersectionCount, 5) |
149 | - fuzzyCompare(eventsA.width, 0.2, 0.1) |
150 | + fuzzyCompare(eventsA.width, 0.3, 0.1) |
151 | |
152 | //"Event at 14:30 until 15:00" |
153 | var eventsB = eventMap[1] |
154 | compare(eventsB.event.displayLabel, "Event at 14:30 until 15:00") |
155 | compare(eventsB.y, 1) |
156 | compare(eventsB.intersectionCount, 5) |
157 | - fuzzyCompare(eventsB.width, 0.2, 0.1) |
158 | + fuzzyCompare(eventsB.width, 0.3, 0.1) |
159 | |
160 | //"Event at 14:45 until 15:45" |
161 | var eventsC = eventMap[2] |
162 | compare(eventsC.event.displayLabel, "Event at 14:45 until 15:45") |
163 | compare(eventsC.y, 2) |
164 | compare(eventsC.intersectionCount, 5) |
165 | - fuzzyCompare(eventsC.width, 0.2, 0.1) |
166 | + fuzzyCompare(eventsC.width, 0.3, 0.1) |
167 | |
168 | //"Event at 15:30 until 16:30" |
169 | var eventsD = eventMap[3] |
170 | compare(eventsD.event.displayLabel, "Event at 15:30 until 16:30") |
171 | compare(eventsD.y, 0) |
172 | compare(eventsD.intersectionCount, 5) |
173 | - fuzzyCompare(eventsD.width, 0.2, 0.1) |
174 | + fuzzyCompare(eventsD.width, 0.3, 0.1) |
175 | |
176 | //"Event at 15:30 until 16:30 (1)" |
177 | var eventsE = eventMap[4] |
178 | compare(eventsE.event.displayLabel, "Event at 15:30 until 16:30 (1)") |
179 | compare(eventsE.y, 1) |
180 | compare(eventsE.intersectionCount, 5) |
181 | - fuzzyCompare(eventsE.width, 0.2, 0.1) |
182 | + fuzzyCompare(eventsE.width, 0.3, 0.1) |
183 | } |
184 | } |
185 | |
186 | === added file 'tests/unittests/tst_event_bubble.qml' |
187 | --- tests/unittests/tst_event_bubble.qml 1970-01-01 00:00:00 +0000 |
188 | +++ tests/unittests/tst_event_bubble.qml 2016-03-31 19:20:26 +0000 |
189 | @@ -0,0 +1,208 @@ |
190 | +import QtQuick 2.0 |
191 | +import QtTest 1.0 |
192 | +import QtOrganizer 5.0 |
193 | + |
194 | +TestCase{ |
195 | + id: root |
196 | + name: "Event Bubble tests" |
197 | + |
198 | + property OrganizerModel model: null |
199 | + property Collection collection: null |
200 | + property Event event: null |
201 | + property var eventBubble: null |
202 | + |
203 | + Component { |
204 | + id: modelComp |
205 | + |
206 | + OrganizerModel {} |
207 | + } |
208 | + |
209 | + Component { |
210 | + id: collectionComp |
211 | + |
212 | + Collection {} |
213 | + } |
214 | + |
215 | + Component { |
216 | + id: eventAttendeeComp |
217 | + |
218 | + EventAttendee {} |
219 | + } |
220 | + |
221 | + Component { |
222 | + id: eventComp |
223 | + |
224 | + Event {} |
225 | + } |
226 | + |
227 | + function create_model_from_data(data) |
228 | + { |
229 | + return modelComp.createObject(root, |
230 | + {"manager": data.manager, |
231 | + "startPeriod": data.startPeriod, |
232 | + "endPeriod": data.endPeriod, |
233 | + "autoUpdate": data.autoUpdate}) |
234 | + } |
235 | + |
236 | + function create_collection_from_data(data) |
237 | + { |
238 | + return collectionComp.createObject(root, |
239 | + {"name": data.name, |
240 | + "color": data.color}) |
241 | + } |
242 | + |
243 | + function create_event_attendee_from_data(data) |
244 | + { |
245 | + return eventAttendeeComp.createObject(root, |
246 | + {"emailAddress": data.emailAddress, |
247 | + "participationStatus": data.participationStatus}) |
248 | + } |
249 | + |
250 | + function create_event_from_data(data) |
251 | + { |
252 | + return eventComp.createObject(root, |
253 | + {"collectionId": data.collectionId, |
254 | + "allDay": data.allDay, |
255 | + "displayLabel": data.label, |
256 | + "startDateTime": data.startDate, |
257 | + "endDateTime": data.endDate, |
258 | + "attendees": data.attendees}) |
259 | + } |
260 | + |
261 | + function create_event_bubble(event) |
262 | + { |
263 | + var component = Qt.createComponent(Qt.resolvedUrl("../../EventBubble.qml")) |
264 | + if (component.status === Component.Ready) |
265 | + return component.createObject(root, {"model": root.model, "event": event}) |
266 | + |
267 | + return null |
268 | + } |
269 | + |
270 | + function get_collection_id_by_name(model, name) |
271 | + { |
272 | + for (var i = 0 ; i < model.collections.length ; ++i) { |
273 | + if (model.collections[i].name === name ) { |
274 | + return model.collections[i].collectionId |
275 | + } |
276 | + } |
277 | + return "" |
278 | + } |
279 | + |
280 | + function initTestCase() |
281 | + { |
282 | + var startPeriod = new Date(2016, 1, 1, 0, 0, 0, 0) |
283 | + var endPeriod = new Date(2017, 1, 1, 0, 0, 0, 0) |
284 | + var modelData = {"manager": "memory", |
285 | + "startPeriod": startPeriod, |
286 | + "endPeriod": endPeriod, |
287 | + "autoUpdate": true} |
288 | + root.model = create_model_from_data(modelData) |
289 | + |
290 | + var collectionData = {"name": "test@calendar.com", |
291 | + "color": "black" } |
292 | + root.collection = create_collection_from_data(collectionData) |
293 | + root.model.saveCollection(root.collection) |
294 | + } |
295 | + |
296 | + function init() |
297 | + { |
298 | + var collectionId = get_collection_id_by_name(root.model, root.collection.name) |
299 | + var startDate = new Date(2016, 3, 28, 14, 0,0 ) |
300 | + var endDate = new Date(2016, 3, 28, 15, 0,0 ) |
301 | + var eventData = {"collectionId": collectionId, |
302 | + "label": "Sample Test Event", |
303 | + "allDay": false, |
304 | + "startDate": startDate, |
305 | + "endDate": endDate} |
306 | + root.event = create_event_from_data(eventData) |
307 | + } |
308 | + |
309 | + function cleanup() |
310 | + { |
311 | + if (root.event) { |
312 | + root.event.destroy() |
313 | + root.event = null |
314 | + } |
315 | + |
316 | + if (root.eventBubble) { |
317 | + root.eventBubble.destroy() |
318 | + root.eventBubble = null |
319 | + } |
320 | + } |
321 | + |
322 | + function test_visual_style_future_accepted_event() |
323 | + { |
324 | + var eventAttendeeData = {"emailAddress": root.collection.name, |
325 | + "participationStatus": EventAttendee.StatusAccepted} |
326 | + |
327 | + var eventAttendee = create_event_attendee_from_data(eventAttendeeData) |
328 | + root.event.setDetail(eventAttendee) |
329 | + |
330 | + eventBubble = create_event_bubble(root.event) |
331 | + eventBubble.updateEventBubbleStyle() |
332 | + |
333 | + compare(eventBubble.backgroundColor, root.collection.color) |
334 | + compare(eventBubble.borderColor, "#ffffff") |
335 | + compare(eventBubble.backgroundOpacity, 1.0) |
336 | + compare(eventBubble.titleText, "Sample Test Event") |
337 | + compare(eventBubble.titleColor, "#ffffff") |
338 | + verify(!eventBubble.strikeoutTitle) |
339 | + } |
340 | + |
341 | + function test_visual_style_future_declined_event() |
342 | + { |
343 | + var eventAttendeeData = {"emailAddress": root.collection.name, |
344 | + "participationStatus": EventAttendee.StatusDeclined} |
345 | + |
346 | + var eventAttendee = create_event_attendee_from_data(eventAttendeeData) |
347 | + root.event.setDetail(eventAttendee) |
348 | + |
349 | + eventBubble = create_event_bubble(root.event) |
350 | + eventBubble.updateEventBubbleStyle() |
351 | + |
352 | + compare(eventBubble.backgroundColor, root.collection.color) |
353 | + compare(eventBubble.borderColor, "#ffffff") |
354 | + compare(eventBubble.backgroundOpacity, 1.0) |
355 | + compare(eventBubble.titleText, "Sample Test Event") |
356 | + compare(eventBubble.titleColor, "#ffffff") |
357 | + verify(eventBubble.strikeoutTitle) |
358 | + } |
359 | + |
360 | + function test_visual_style_future_maybe_event() |
361 | + { |
362 | + var eventAttendeeData = {"emailAddress": root.collection.name, |
363 | + "participationStatus": EventAttendee.StatusTentative} |
364 | + |
365 | + var eventAttendee = create_event_attendee_from_data(eventAttendeeData) |
366 | + root.event.setDetail(eventAttendee) |
367 | + |
368 | + eventBubble = create_event_bubble(root.event) |
369 | + eventBubble.updateEventBubbleStyle() |
370 | + |
371 | + compare(eventBubble.backgroundColor, root.collection.color) |
372 | + compare(eventBubble.borderColor, "#ffffff") |
373 | + compare(eventBubble.backgroundOpacity, 1.0) |
374 | + compare(eventBubble.titleText, "(?) Sample Test Event") |
375 | + compare(eventBubble.titleColor, "#ffffff") |
376 | + verify(!eventBubble.strikeoutTitle) |
377 | + } |
378 | + |
379 | + function test_visual_style_future_unknown_event() |
380 | + { |
381 | + var eventAttendeeData = {"emailAddress": root.collection.name, |
382 | + "participationStatus": EventAttendee.StatusUnknown} |
383 | + |
384 | + var eventAttendee = create_event_attendee_from_data(eventAttendeeData) |
385 | + root.event.setDetail(eventAttendee) |
386 | + |
387 | + eventBubble = create_event_bubble(root.event) |
388 | + eventBubble.updateEventBubbleStyle() |
389 | + |
390 | + compare(eventBubble.backgroundColor, "#ffffff") |
391 | + compare(eventBubble.borderColor, root.collection.color) |
392 | + compare(eventBubble.backgroundOpacity, 1.0) |
393 | + compare(eventBubble.titleText, "Sample Test Event") |
394 | + compare(eventBubble.titleColor, root.collection.color) |
395 | + verify(!eventBubble.strikeoutTitle) |
396 | + } |
397 | +} |
PASSED: Continuous integration, rev:809 /core-apps- jenkins. ubuntu. com/job/ calendar- app-ci/ 812/ /core-apps- jenkins. ubuntu. com/job/ generic- update- mp/831/ console
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild: /core-apps- jenkins. ubuntu. com/job/ calendar- app-ci/ 812/rebuild
https:/