Merge lp:~nik90/ubuntu-clock-app/12-alarm-list-design-spec into lp:ubuntu-clock-app
- 12-alarm-list-design-spec
- Merge into trunk
Proposed by
Nekhelesh Ramananthan
Status: | Superseded |
---|---|
Proposed branch: | lp:~nik90/ubuntu-clock-app/12-alarm-list-design-spec |
Merge into: | lp:ubuntu-clock-app |
Diff against target: |
961 lines (+299/-279) 14 files modified
app/alarm/AlarmDelegate.qml (+7/-31) app/alarm/AlarmList.qml (+2/-1) app/alarm/AlarmPage.qml (+2/-1) app/alarm/AlarmUtils.qml (+52/-15) app/alarm/EditAlarmPage.qml (+1/-2) app/clock/ClockPage.qml (+11/-2) app/clock/MainClock.qml (+0/-39) app/components/Clock.qml (+1/-1) app/components/Utils.js (+0/-25) app/ubuntu-clock-app.qml (+37/-6) app/upstreamcomponents/PageWithBottomEdge.qml (+167/-154) app/worldclock/UserWorldCityList.qml (+0/-2) tests/autopilot/ubuntu_clock_app/emulators.py (+2/-0) tests/unit/tst_alarm.qml (+17/-0) |
To merge this branch: | bzr merge lp:~nik90/ubuntu-clock-app/12-alarm-list-design-spec |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Ubuntu Clock Developers | Pending | ||
Review via email:
|
Commit message
Always the the remaining time to alarm for single type alarms
Description of the change
Always the the remaining time to alarm for single type alarms
To post a comment you must log in.
- 109. By Nekhelesh Ramananthan
-
Added units test for the alarm utils library
- 110. By Nekhelesh Ramananthan
-
Improved readability of alarm repeat test by properly using alarm daysOfWeek enum instead of numeric value
- 111. By Nekhelesh Ramananthan
-
Do not show remaining time to alarm if the alarm is disabled
- 112. By Nekhelesh Ramananthan
-
Split qml tests into smaller ones
- 113. By Nekhelesh Ramananthan
-
Merged prerequisite branch
- 114. By Nekhelesh Ramananthan
-
Updated debian changelog
- 115. By Nekhelesh Ramananthan
-
Fixed AP tests
Unmerged revisions
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'app/alarm/AlarmDelegate.qml' |
2 | --- app/alarm/AlarmDelegate.qml 2014-09-03 22:51:48 +0000 |
3 | +++ app/alarm/AlarmDelegate.qml 2014-10-05 00:32:38 +0000 |
4 | @@ -23,6 +23,8 @@ |
5 | ListItemWithActions { |
6 | id: root |
7 | |
8 | + property var localTime |
9 | + |
10 | width: parent ? parent.width : 0 |
11 | height: units.gu(6) |
12 | color: "Transparent" |
13 | @@ -39,6 +41,7 @@ |
14 | |
15 | fontSize: "medium" |
16 | text: Qt.formatTime(date) |
17 | + opacity: model.enabled ? 1.0 : 0.8 |
18 | } |
19 | |
20 | Column { |
21 | @@ -70,9 +73,9 @@ |
22 | |
23 | fontSize: "xx-small" |
24 | width: parent.width |
25 | - visible: type === Alarm.Repeating || _internalTimerLoader.sourceComponent != undefined |
26 | wrapMode: Text.WrapAtWordBoundaryOrAnywhere |
27 | - text: alarmUtils.format_day_string(daysOfWeek, type) |
28 | + text: type === Alarm.Repeating ? alarmUtils.format_day_string(daysOfWeek, type) |
29 | + : alarmUtils.get_time_to_next_alarm(model.date - localTime) |
30 | } |
31 | } |
32 | |
33 | @@ -126,35 +129,8 @@ |
34 | if (model.status === Alarm.Ready) { |
35 | alarmStatus.checked = model.enabled; |
36 | |
37 | - if(alarmStatus.checked) { |
38 | - var timeObject = alarmUtils.get_time_to_next_alarm(model.date - new Date()) |
39 | - var alarmETA |
40 | - |
41 | - // TRANSLATORS: the first argument is the number of days, |
42 | - // followed by hour and minute (eg. in 1d 20h 3m) |
43 | - if(timeObject.days) { |
44 | - alarmETA = i18n.tr("in %1d %1h %2m") |
45 | - .arg(timeObject.days) |
46 | - .arg(timeObject.hours) |
47 | - .arg(timeObject.minutes) |
48 | - } |
49 | - |
50 | - // TRANSLATORS: the first argument is the number of |
51 | - // hours followed by the minutes (eg. in 4h 3m) |
52 | - else if (timeObject.hours) { |
53 | - alarmETA = i18n.tr("in %1h %2m") |
54 | - .arg(timeObject.hours) |
55 | - .arg(timeObject.minutes) |
56 | - } |
57 | - |
58 | - // TRANSLATORS: the argument is the number of |
59 | - // minutes to the alarm (eg. in 3m) |
60 | - else { |
61 | - alarmETA = i18n.tr("in %1m") |
62 | - .arg(timeObject.minutes) |
63 | - } |
64 | - |
65 | - alarmSubtitle.text = alarmETA |
66 | + if(alarmStatus.checked && type === Alarm.Repeating) { |
67 | + alarmSubtitle.text = alarmUtils.get_time_to_next_alarm(model.date - localTime) |
68 | _internalTimerLoader.sourceComponent = _internalTimerComponent |
69 | } |
70 | } |
71 | |
72 | === modified file 'app/alarm/AlarmList.qml' |
73 | --- app/alarm/AlarmList.qml 2014-09-25 11:26:43 +0000 |
74 | +++ app/alarm/AlarmList.qml 2014-10-05 00:32:38 +0000 |
75 | @@ -21,13 +21,13 @@ |
76 | import Ubuntu.Components.ListItems 1.0 as ListItem |
77 | import "../components" |
78 | import "../upstreamcomponents" |
79 | -import "../components/Utils.js" as Utils |
80 | |
81 | MultipleSelectionListView { |
82 | id: alarmListView |
83 | objectName: "alarmListView" |
84 | |
85 | property var _currentSwipedItem: null |
86 | + property var localTime |
87 | |
88 | function _updateSwipeState(item) |
89 | { |
90 | @@ -60,6 +60,7 @@ |
91 | objectName: "alarm" + index |
92 | |
93 | property var removalAnimation |
94 | + localTime: alarmListView.localTime |
95 | |
96 | function remove() { |
97 | removalAnimation.start() |
98 | |
99 | === modified file 'app/alarm/AlarmPage.qml' |
100 | --- app/alarm/AlarmPage.qml 2014-09-26 12:24:11 +0000 |
101 | +++ app/alarm/AlarmPage.qml 2014-10-05 00:32:38 +0000 |
102 | @@ -26,7 +26,7 @@ |
103 | title: i18n.tr("Alarms") |
104 | objectName: 'AlarmPage' |
105 | |
106 | - Component.onCompleted: console.log("Alarm Page loaded") |
107 | + Component.onCompleted: console.log("[LOG]: Alarm Page loaded") |
108 | |
109 | flickable: null |
110 | |
111 | @@ -127,6 +127,7 @@ |
112 | id: alarmListView |
113 | listModel: alarmModel |
114 | anchors.fill: parent |
115 | + localTime: clockTime |
116 | } |
117 | |
118 | EmptyState { |
119 | |
120 | === modified file 'app/alarm/AlarmUtils.qml' |
121 | --- app/alarm/AlarmUtils.qml 2014-09-03 22:36:07 +0000 |
122 | +++ app/alarm/AlarmUtils.qml 2014-10-05 00:32:38 +0000 |
123 | @@ -50,21 +50,40 @@ |
124 | } |
125 | } |
126 | |
127 | - function get_time_to_next_alarm ( datetime_offset ) { |
128 | - // increase by a minute, so we could make a nicer time |
129 | - // to the next alarm, otherwise a minute always missing |
130 | - // which makes it look odd |
131 | - datetime_offset += 60000; |
132 | - |
133 | - var days_in_offset = Math.floor( datetime_offset / ( 3600000 * 24 ) ); |
134 | - var hours_in_offset = Math.floor( datetime_offset / 3600000 % 24 ); |
135 | - var minutes_in_offset = Math.floor( datetime_offset / 60000 % 60 ); |
136 | - |
137 | - return { |
138 | - days : days_in_offset, |
139 | - hours : hours_in_offset, |
140 | - minutes : minutes_in_offset |
141 | - } |
142 | + // Function to format the time to next alarm into a string |
143 | + function get_time_to_next_alarm(totalTime) { |
144 | + if(totalTime < 0) { |
145 | + return i18n.tr("Alarm Passed") |
146 | + } |
147 | + |
148 | + var timeObject = _split_time(totalTime); |
149 | + var alarmETA |
150 | + |
151 | + // TRANSLATORS: the first argument is the number of days, |
152 | + // followed by hour and minute (eg. in 1d 20h 3m) |
153 | + if(timeObject.days) { |
154 | + alarmETA = i18n.tr("in %1d %2h %3m") |
155 | + .arg(timeObject.days) |
156 | + .arg(timeObject.hours) |
157 | + .arg(timeObject.minutes) |
158 | + } |
159 | + |
160 | + // TRANSLATORS: the first argument is the number of |
161 | + // hours followed by the minutes (eg. in 4h 3m) |
162 | + else if (timeObject.hours) { |
163 | + alarmETA = i18n.tr("in %1h %2m") |
164 | + .arg(timeObject.hours) |
165 | + .arg(timeObject.minutes) |
166 | + } |
167 | + |
168 | + // TRANSLATORS: the argument is the number of |
169 | + // minutes to the alarm (eg. in 3m) |
170 | + else { |
171 | + alarmETA = i18n.tr("in %1m") |
172 | + .arg(timeObject.minutes) |
173 | + } |
174 | + |
175 | + return alarmETA; |
176 | } |
177 | |
178 | // Function return the alarm dayOfWeek according to the day provided |
179 | @@ -84,6 +103,24 @@ |
180 | INTERNAL FUNCTIONS |
181 | */ |
182 | |
183 | + // Function to split time (in ms) into days, hours and minutes |
184 | + function _split_time(totalTime) { |
185 | + // increase by a minute, so we could make a nicer time |
186 | + // to the next alarm, otherwise a minute always missing |
187 | + // which makes it look odd |
188 | + totalTime += 60000; |
189 | + |
190 | + var days_in_offset = Math.floor(totalTime / ( 3600000 * 24)); |
191 | + var hours_in_offset = Math.floor(totalTime / 3600000 % 24); |
192 | + var minutes_in_offset = Math.floor(totalTime / 60000 % 60); |
193 | + |
194 | + return { |
195 | + days : days_in_offset, |
196 | + hours : hours_in_offset, |
197 | + minutes : minutes_in_offset |
198 | + } |
199 | + } |
200 | + |
201 | // Function to determine the locale's weekdays value |
202 | function _get_weekdays() { |
203 | var weekDays = 0 |
204 | |
205 | === modified file 'app/alarm/EditAlarmPage.qml' |
206 | --- app/alarm/EditAlarmPage.qml 2014-09-25 11:26:43 +0000 |
207 | +++ app/alarm/EditAlarmPage.qml 2014-10-05 00:32:38 +0000 |
208 | @@ -23,7 +23,6 @@ |
209 | import Ubuntu.Components.Pickers 1.0 |
210 | import Ubuntu.Components.ListItems 1.0 as ListItem |
211 | import "../components" |
212 | -import "../components/Utils.js" as Utils |
213 | |
214 | Page { |
215 | id: _addAlarmPage |
216 | @@ -177,7 +176,7 @@ |
217 | |
218 | onErrorChanged: { |
219 | if (error !== Alarm.NoError) { |
220 | - Utils.log(debugMode, "Error saving alarm, code: " + error) |
221 | + console.log("[LOG]: Error saving alarm, code: " + error) |
222 | } |
223 | } |
224 | |
225 | |
226 | === modified file 'app/clock/ClockPage.qml' |
227 | --- app/clock/ClockPage.qml 2014-09-26 11:36:12 +0000 |
228 | +++ app/clock/ClockPage.qml 2014-10-05 00:32:38 +0000 |
229 | @@ -22,7 +22,6 @@ |
230 | import "../components" |
231 | import "../upstreamcomponents" |
232 | import "../worldclock" |
233 | -import "../components/Utils.js" as Utils |
234 | |
235 | PageWithBottomEdge { |
236 | id: _clockPage |
237 | @@ -31,15 +30,25 @@ |
238 | // Property to keep track of the clock mode |
239 | property alias isDigital: clock.isDigital |
240 | |
241 | + // Property to keep track of the clock time |
242 | + property alias clockTime: clock.analogTime |
243 | + |
244 | flickable: null |
245 | |
246 | - Component.onCompleted: Utils.log(debugMode, "Clock Page loaded") |
247 | + Component.onCompleted: { |
248 | + console.log("[LOG]: Clock Page loaded") |
249 | + _clockPage.setBottomEdgePage(Qt.resolvedUrl("../alarm/AlarmPage.qml"), {}) |
250 | + } |
251 | |
252 | Flickable { |
253 | id: _flickable |
254 | |
255 | Component.onCompleted: otherElementsStartUpAnimation.start() |
256 | |
257 | + onFlickStarted: { |
258 | + forceActiveFocus() |
259 | + } |
260 | + |
261 | anchors.fill: parent |
262 | contentWidth: parent.width |
263 | contentHeight: clock.height + date.height + locationRow.height |
264 | |
265 | === modified file 'app/clock/MainClock.qml' |
266 | --- app/clock/MainClock.qml 2014-08-24 12:47:50 +0000 |
267 | +++ app/clock/MainClock.qml 2014-10-05 00:32:38 +0000 |
268 | @@ -17,7 +17,6 @@ |
269 | */ |
270 | |
271 | import QtQuick 2.3 |
272 | -import DateTime 1.0 |
273 | import Ubuntu.Components 1.1 |
274 | import "../components" |
275 | |
276 | @@ -30,44 +29,6 @@ |
277 | |
278 | isMainClock: true |
279 | |
280 | - Connections { |
281 | - target: clockApp |
282 | - onApplicationStateChanged: { |
283 | - localTimeSource.update() |
284 | - } |
285 | - } |
286 | - |
287 | - DateTime { |
288 | - id: localTimeSource |
289 | - updateInterval: isDigital ? 1000 : 10 |
290 | - } |
291 | - |
292 | - /* |
293 | - Create a new Date() object and pass the date, month, year, hour, minute |
294 | - and second received from the DateTime plugin manually to ensure the |
295 | - timezone info is set correctly. |
296 | - |
297 | - Javascript Month is 0-11 while QDateTime month is 1-12. Hence the -1 |
298 | - is required. |
299 | - */ |
300 | - |
301 | - /* |
302 | - FIXME: When the upstream QT bug at |
303 | - https://bugreports.qt-project.org/browse/QTBUG-40275 is fixed it will be |
304 | - possible to receive a datetime object directly instead of using this hack. |
305 | - */ |
306 | - analogTime: new Date |
307 | - ( |
308 | - localTimeSource.localDateString.split(":")[0], |
309 | - localTimeSource.localDateString.split(":")[1]-1, |
310 | - localTimeSource.localDateString.split(":")[2], |
311 | - localTimeSource.localTimeString.split(":")[0], |
312 | - localTimeSource.localTimeString.split(":")[1], |
313 | - localTimeSource.localTimeString.split(":")[2], |
314 | - localTimeSource.localTimeString.split(":")[3] |
315 | - ) |
316 | - time: Qt.formatTime(analogTime) |
317 | - |
318 | isDigital: clockModeDocument.contents.digitalMode ? true : false |
319 | |
320 | Component.onCompleted: { |
321 | |
322 | === modified file 'app/components/Clock.qml' |
323 | --- app/components/Clock.qml 2014-09-06 15:16:43 +0000 |
324 | +++ app/components/Clock.qml 2014-10-05 00:32:38 +0000 |
325 | @@ -18,7 +18,6 @@ |
326 | |
327 | import QtQuick 2.3 |
328 | import Ubuntu.Components 1.1 |
329 | -import "Utils.js" as Utils |
330 | |
331 | /* |
332 | Generic clock component which has a digital and analog mode. A flip animation |
333 | @@ -148,6 +147,7 @@ |
334 | enabled: isMainClock |
335 | anchors.fill: parent |
336 | onClicked: { |
337 | + forceActiveFocus() |
338 | clockFlipAnimation.start() |
339 | } |
340 | } |
341 | |
342 | === removed file 'app/components/Utils.js' |
343 | --- app/components/Utils.js 2014-07-17 12:21:45 +0000 |
344 | +++ app/components/Utils.js 1970-01-01 00:00:00 +0000 |
345 | @@ -1,25 +0,0 @@ |
346 | -/* |
347 | - * Copyright (C) 2014 Canonical Ltd |
348 | - * |
349 | - * This file is part of Ubuntu Clock App |
350 | - * |
351 | - * Ubuntu Clock App is free software: you can redistribute it and/or modify |
352 | - * it under the terms of the GNU General Public License version 3 as |
353 | - * published by the Free Software Foundation. |
354 | - * |
355 | - * Ubuntu Clock App is distributed in the hope that it will be useful, |
356 | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
357 | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
358 | - * GNU General Public License for more details. |
359 | - * |
360 | - * You should have received a copy of the GNU General Public License |
361 | - * along with this program. If not, see <http://www.gnu.org/licenses/>. |
362 | - */ |
363 | - |
364 | -.pragma library |
365 | - |
366 | -function log (debugMode, message) { |
367 | - if (debugMode) { |
368 | - console.log("[LOG]" + message) |
369 | - } |
370 | -} |
371 | |
372 | === modified file 'app/ubuntu-clock-app.qml' |
373 | --- app/ubuntu-clock-app.qml 2014-08-26 20:20:37 +0000 |
374 | +++ app/ubuntu-clock-app.qml 2014-10-05 00:32:38 +0000 |
375 | @@ -17,12 +17,12 @@ |
376 | */ |
377 | |
378 | import QtQuick 2.3 |
379 | +import DateTime 1.0 |
380 | import U1db 1.0 as U1db |
381 | import Ubuntu.Components 1.1 |
382 | import "clock" |
383 | import "alarm" |
384 | import "components" |
385 | -import "components/Utils.js" as Utils |
386 | |
387 | MainView { |
388 | id: clockApp |
389 | @@ -30,9 +30,6 @@ |
390 | // Property to store the state of an application (active or suspended) |
391 | property bool applicationState: Qt.application.active |
392 | |
393 | - // Property to enable/disable the debug mode to show more console output |
394 | - property bool debugMode: true |
395 | - |
396 | // objectName for functional testing purposes (autopilot-qt5) |
397 | objectName: "clock" |
398 | |
399 | @@ -77,7 +74,16 @@ |
400 | |
401 | AlarmModel { |
402 | id: alarmModel |
403 | - Component.onCompleted: Utils.log(debugMode, "Alarm Database loaded") |
404 | + Component.onCompleted: console.log("[LOG]: Alarm Database loaded") |
405 | + } |
406 | + |
407 | + DateTime { |
408 | + id: localTimeSource |
409 | + updateInterval: clockModeDocument.contents.digitalMode ? 1000 : 10 |
410 | + } |
411 | + |
412 | + onApplicationStateChanged: { |
413 | + localTimeSource.update() |
414 | } |
415 | |
416 | PageStack { |
417 | @@ -97,11 +103,36 @@ |
418 | */ |
419 | |
420 | /* |
421 | + Create a new Date() object and pass the date, month, year, hour, minute |
422 | + and second received from the DateTime plugin manually to ensure the |
423 | + timezone info is set correctly. |
424 | + |
425 | + Javascript Month is 0-11 while QDateTime month is 1-12. Hence the -1 |
426 | + is required. |
427 | + */ |
428 | + |
429 | + /* |
430 | + FIXME: When the upstream QT bug at |
431 | + https://bugreports.qt-project.org/browse/QTBUG-40275 is fixed it will be |
432 | + possible to receive a datetime object directly instead of using this hack. |
433 | + */ |
434 | + |
435 | + clockTime: new Date |
436 | + ( |
437 | + localTimeSource.localDateString.split(":")[0], |
438 | + localTimeSource.localDateString.split(":")[1]-1, |
439 | + localTimeSource.localDateString.split(":")[2], |
440 | + localTimeSource.localTimeString.split(":")[0], |
441 | + localTimeSource.localTimeString.split(":")[1], |
442 | + localTimeSource.localTimeString.split(":")[2], |
443 | + localTimeSource.localTimeString.split(":")[3] |
444 | + ) |
445 | + |
446 | + /* |
447 | #TODO: The bottom edge title should reflect the time to the next |
448 | alarm. For instance it should read "Next alarm in 9h23m". |
449 | */ |
450 | bottomEdgeTitle: i18n.tr("Alarms") |
451 | - bottomEdgePageComponent: AlarmPage {} |
452 | } |
453 | } |
454 | } |
455 | |
456 | === modified file 'app/upstreamcomponents/PageWithBottomEdge.qml' |
457 | --- app/upstreamcomponents/PageWithBottomEdge.qml 2014-09-20 10:47:21 +0000 |
458 | +++ app/upstreamcomponents/PageWithBottomEdge.qml 2014-10-05 00:32:38 +0000 |
459 | @@ -62,7 +62,7 @@ |
460 | |
461 | */ |
462 | |
463 | -import QtQuick 2.3 |
464 | +import QtQuick 2.2 |
465 | import Ubuntu.Components 1.1 |
466 | |
467 | Page { |
468 | @@ -71,7 +71,7 @@ |
469 | property alias bottomEdgePageComponent: edgeLoader.sourceComponent |
470 | property alias bottomEdgePageSource: edgeLoader.source |
471 | property alias bottomEdgeTitle: tipLabel.text |
472 | - property alias bottomEdgeEnabled: bottomEdge.visible |
473 | + property bool bottomEdgeEnabled: true |
474 | property int bottomEdgeExpandThreshold: page.height * 0.2 |
475 | property int bottomEdgeExposedArea: bottomEdge.state !== "expanded" ? (page.height - bottomEdge.y - bottomEdge.tipHeight) : _areaWhenExpanded |
476 | property bool reloadBottomEdgePage: true |
477 | @@ -87,6 +87,9 @@ |
478 | signal bottomEdgeReleased() |
479 | signal bottomEdgeDismissed() |
480 | |
481 | + function giveFocus() { |
482 | + tip.forceActiveFocus() |
483 | + } |
484 | |
485 | function showBottomEdgePage(source, properties) |
486 | { |
487 | @@ -142,13 +145,123 @@ |
488 | z: 1 |
489 | } |
490 | |
491 | - Timer { |
492 | - id: hideIndicator |
493 | - |
494 | - interval: 3000 |
495 | - running: true |
496 | - repeat: false |
497 | - onTriggered: tip.hiden = true |
498 | + UbuntuShape { |
499 | + id: tip |
500 | + objectName: "bottomEdgeTip" |
501 | + |
502 | + property bool hiden: (activeFocus === false) || |
503 | + ((bottomEdge.y - units.gu(1)) < tip.y) |
504 | + |
505 | + enabled: mouseArea.enabled |
506 | + visible: page.bottomEdgeEnabled |
507 | + anchors { |
508 | + bottom: parent.bottom |
509 | + horizontalCenter: bottomEdge.horizontalCenter |
510 | + bottomMargin: hiden ? - height + units.gu(1) : -units.gu(1) |
511 | + Behavior on bottomMargin { |
512 | + SequentialAnimation { |
513 | + // wait some msecs in case of the focus change again, to avoid flickering |
514 | + PauseAnimation { |
515 | + duration: 300 |
516 | + } |
517 | + UbuntuNumberAnimation { |
518 | + duration: UbuntuAnimation.SnapDuration |
519 | + } |
520 | + } |
521 | + } |
522 | + } |
523 | + |
524 | + z: 1 |
525 | + width: tipLabel.paintedWidth + units.gu(6) |
526 | + height: bottomEdge.tipHeight + units.gu(1) |
527 | + color: Theme.palette.normal.overlay |
528 | + Label { |
529 | + id: tipLabel |
530 | + |
531 | + anchors { |
532 | + top: parent.top |
533 | + left: parent.left |
534 | + right: parent.right |
535 | + } |
536 | + height: bottomEdge.tipHeight |
537 | + verticalAlignment: Text.AlignVCenter |
538 | + horizontalAlignment: Text.AlignHCenter |
539 | + opacity: tip.hiden ? 0.0 : 1.0 |
540 | + Behavior on opacity { |
541 | + UbuntuNumberAnimation { |
542 | + duration: UbuntuAnimation.SnapDuration |
543 | + } |
544 | + } |
545 | + } |
546 | + } |
547 | + |
548 | + Rectangle { |
549 | + id: shadow |
550 | + |
551 | + anchors { |
552 | + left: parent.left |
553 | + right: parent.right |
554 | + bottom: parent.bottom |
555 | + } |
556 | + height: units.gu(1) |
557 | + z: 1 |
558 | + opacity: 0.0 |
559 | + gradient: Gradient { |
560 | + GradientStop { position: 0.0; color: "transparent" } |
561 | + GradientStop { position: 1.0; color: Qt.rgba(0, 0, 0, 0.2) } |
562 | + } |
563 | + } |
564 | + |
565 | + MouseArea { |
566 | + id: mouseArea |
567 | + |
568 | + property real previousY: -1 |
569 | + property string dragDirection: "None" |
570 | + |
571 | + preventStealing: true |
572 | + drag { |
573 | + axis: Drag.YAxis |
574 | + target: bottomEdge |
575 | + minimumY: bottomEdge.pageStartY |
576 | + maximumY: page.height |
577 | + } |
578 | + enabled: edgeLoader.status == Loader.Ready |
579 | + visible: page.bottomEdgeEnabled |
580 | + |
581 | + anchors { |
582 | + left: parent.left |
583 | + right: parent.right |
584 | + bottom: parent.bottom |
585 | + } |
586 | + height: bottomEdge.tipHeight |
587 | + z: 1 |
588 | + |
589 | + onReleased: { |
590 | + page.bottomEdgeReleased() |
591 | + if ((dragDirection === "BottomToTop") && |
592 | + bottomEdge.y < (page.height - bottomEdgeExpandThreshold - bottomEdge.tipHeight)) { |
593 | + bottomEdge.state = "expanded" |
594 | + } else { |
595 | + bottomEdge.state = "collapsed" |
596 | + } |
597 | + previousY = -1 |
598 | + dragDirection = "None" |
599 | + } |
600 | + |
601 | + onPressed: { |
602 | + previousY = mouse.y |
603 | + tip.forceActiveFocus() |
604 | + } |
605 | + |
606 | + onMouseYChanged: { |
607 | + var yOffset = previousY - mouseY |
608 | + // skip if was a small move |
609 | + if (Math.abs(yOffset) <= units.gu(2)) { |
610 | + return |
611 | + } |
612 | + previousY = mouseY |
613 | + dragDirection = yOffset > 0 ? "BottomToTop" : "TopToBottom" |
614 | + } |
615 | } |
616 | |
617 | FakeHeader { |
618 | @@ -177,7 +290,7 @@ |
619 | |
620 | z: 1 |
621 | color: Theme.palette.normal.background |
622 | - parent: page |
623 | + clip: true |
624 | anchors { |
625 | left: parent.left |
626 | right: parent.right |
627 | @@ -185,99 +298,7 @@ |
628 | height: page.height |
629 | y: height |
630 | |
631 | - UbuntuShape { |
632 | - id: tip |
633 | - objectName: "bottomEdgeTip" |
634 | - |
635 | - property bool hiden: false |
636 | - |
637 | - readonly property double visiblePosition: (page.height - bottomEdge.y) < units.gu(1) ? -bottomEdge.tipHeight + (page.height - bottomEdge.y) : 0 |
638 | - readonly property double invisiblePosition: (page.height - bottomEdge.y) < units.gu(1) ? -units.gu(1) : 0 |
639 | - |
640 | - z: -1 |
641 | - anchors.horizontalCenter: parent.horizontalCenter |
642 | - y: hiden ? invisiblePosition : visiblePosition |
643 | - |
644 | - width: tipLabel.paintedWidth + units.gu(6) |
645 | - height: bottomEdge.tipHeight + units.gu(1) |
646 | - color: Theme.palette.normal.overlay |
647 | - Label { |
648 | - id: tipLabel |
649 | - |
650 | - anchors { |
651 | - top: parent.top |
652 | - left: parent.left |
653 | - right: parent.right |
654 | - } |
655 | - height: bottomEdge.tipHeight |
656 | - verticalAlignment: Text.AlignVCenter |
657 | - horizontalAlignment: Text.AlignHCenter |
658 | - opacity: tip.hiden ? 0.0 : 1.0 |
659 | - Behavior on opacity { |
660 | - UbuntuNumberAnimation { |
661 | - duration: UbuntuAnimation.SnapDuration |
662 | - } |
663 | - } |
664 | - } |
665 | - Behavior on y { |
666 | - UbuntuNumberAnimation { |
667 | - duration: UbuntuAnimation.SnapDuration |
668 | - } |
669 | - } |
670 | - } |
671 | - |
672 | - Rectangle { |
673 | - id: shadow |
674 | - |
675 | - anchors { |
676 | - left: parent.left |
677 | - right: parent.right |
678 | - } |
679 | - height: units.gu(1) |
680 | - y: -height |
681 | - z: -2 |
682 | - opacity: 0.0 |
683 | - gradient: Gradient { |
684 | - GradientStop { position: 0.0; color: "transparent" } |
685 | - GradientStop { position: 1.0; color: Qt.rgba(0, 0, 0, 0.2) } |
686 | - } |
687 | - } |
688 | - |
689 | - MouseArea { |
690 | - id: mouseArea |
691 | - |
692 | - preventStealing: true |
693 | - drag { |
694 | - axis: Drag.YAxis |
695 | - target: bottomEdge |
696 | - minimumY: bottomEdge.pageStartY |
697 | - maximumY: page.height |
698 | - threshold: 100 |
699 | - } |
700 | - |
701 | - anchors { |
702 | - left: parent.left |
703 | - right: parent.right |
704 | - } |
705 | - height: bottomEdge.tipHeight |
706 | - y: -height |
707 | - |
708 | - onReleased: { |
709 | - page.bottomEdgeReleased() |
710 | - if (bottomEdge.y < (page.height - bottomEdgeExpandThreshold - bottomEdge.tipHeight)) { |
711 | - bottomEdge.state = "expanded" |
712 | - } else { |
713 | - bottomEdge.state = "collapsed" |
714 | - bottomEdge.y = bottomEdge.height |
715 | - } |
716 | - } |
717 | - |
718 | - onClicked: { |
719 | - tip.hiden = false |
720 | - hideIndicator.restart() |
721 | - } |
722 | - } |
723 | - |
724 | + visible: !page.isCollapsed |
725 | state: "collapsed" |
726 | states: [ |
727 | State { |
728 | @@ -290,14 +311,6 @@ |
729 | target: fakeHeader |
730 | y: -fakeHeader.height |
731 | } |
732 | - PropertyChanges { |
733 | - target: tip |
734 | - opacity: 1.0 |
735 | - } |
736 | - PropertyChanges { |
737 | - target: hideIndicator |
738 | - running: true |
739 | - } |
740 | }, |
741 | State { |
742 | name: "expanded" |
743 | @@ -309,10 +322,6 @@ |
744 | target: fakeHeader |
745 | y: 0 |
746 | } |
747 | - PropertyChanges { |
748 | - target: hideIndicator |
749 | - running: false |
750 | - } |
751 | }, |
752 | State { |
753 | name: "floating" |
754 | @@ -321,14 +330,6 @@ |
755 | target: shadow |
756 | opacity: 1.0 |
757 | } |
758 | - PropertyChanges { |
759 | - target: hideIndicator |
760 | - running: false |
761 | - } |
762 | - PropertyChanges { |
763 | - target: tip |
764 | - hiden: false |
765 | - } |
766 | } |
767 | ] |
768 | |
769 | @@ -336,18 +337,35 @@ |
770 | Transition { |
771 | to: "expanded" |
772 | SequentialAnimation { |
773 | + alwaysRunToEnd: true |
774 | ParallelAnimation { |
775 | - UbuntuNumberAnimation { |
776 | + SmoothedAnimation { |
777 | target: bottomEdge |
778 | property: "y" |
779 | - duration: UbuntuAnimation.SlowDuration |
780 | + duration: UbuntuAnimation.FastDuration |
781 | + easing.type: Easing.Linear |
782 | } |
783 | - UbuntuNumberAnimation { |
784 | + SmoothedAnimation { |
785 | target: fakeHeader |
786 | property: "y" |
787 | - duration: UbuntuAnimation.SlowDuration |
788 | + duration: UbuntuAnimation.FastDuration |
789 | + easing.type: Easing.Linear |
790 | } |
791 | } |
792 | + SmoothedAnimation { |
793 | + target: edgeLoader |
794 | + property: "anchors.topMargin" |
795 | + to: - units.gu(4) |
796 | + duration: UbuntuAnimation.FastDuration |
797 | + easing.type: Easing.Linear |
798 | + } |
799 | + SmoothedAnimation { |
800 | + target: edgeLoader |
801 | + property: "anchors.topMargin" |
802 | + to: 0 |
803 | + duration: UbuntuAnimation.FastDuration |
804 | + easing: UbuntuAnimation.StandardEasing |
805 | + } |
806 | ScriptAction { |
807 | script: page._pushPage() |
808 | } |
809 | @@ -357,6 +375,8 @@ |
810 | from: "expanded" |
811 | to: "collapsed" |
812 | SequentialAnimation { |
813 | + alwaysRunToEnd: true |
814 | + |
815 | ScriptAction { |
816 | script: { |
817 | Qt.inputMethod.hide() |
818 | @@ -366,12 +386,12 @@ |
819 | } |
820 | } |
821 | ParallelAnimation { |
822 | - UbuntuNumberAnimation { |
823 | + SmoothedAnimation { |
824 | target: bottomEdge |
825 | property: "y" |
826 | duration: UbuntuAnimation.SlowDuration |
827 | } |
828 | - UbuntuNumberAnimation { |
829 | + SmoothedAnimation { |
830 | target: fakeHeader |
831 | property: "y" |
832 | duration: UbuntuAnimation.SlowDuration |
833 | @@ -382,14 +402,14 @@ |
834 | // destroy current bottom page |
835 | if (page.reloadBottomEdgePage) { |
836 | edgeLoader.active = false |
837 | + } else { |
838 | + tip.forceActiveFocus() |
839 | } |
840 | |
841 | // notify |
842 | page.bottomEdgeDismissed() |
843 | |
844 | edgeLoader.active = true |
845 | - tip.hiden = false |
846 | - hideIndicator.restart() |
847 | } |
848 | } |
849 | } |
850 | @@ -404,30 +424,23 @@ |
851 | } |
852 | ] |
853 | |
854 | - Item { |
855 | + Loader { |
856 | + id: edgeLoader |
857 | + |
858 | + asynchronous: true |
859 | anchors.fill: parent |
860 | - clip: true |
861 | - |
862 | - Loader { |
863 | - id: edgeLoader |
864 | - |
865 | - z: 1 |
866 | - active: true |
867 | - asynchronous: true |
868 | - anchors.fill: parent |
869 | - |
870 | - //WORKAROUND: The SDK move the page contents down to allocate space for the header we need to avoid that during the page dragging |
871 | - Binding { |
872 | - target: edgeLoader.status === Loader.Ready ? edgeLoader : null |
873 | - property: "anchors.topMargin" |
874 | - value: edgeLoader.item && edgeLoader.item.flickable ? edgeLoader.item.flickable.contentY : 0 |
875 | - when: !page.isReady |
876 | - } |
877 | - |
878 | - onLoaded: { |
879 | - if (page.isReady && edgeLoader.item.active !== true) { |
880 | - page._pushPage() |
881 | - } |
882 | + //WORKAROUND: The SDK move the page contents down to allocate space for the header we need to avoid that during the page dragging |
883 | + Binding { |
884 | + target: edgeLoader.status === Loader.Ready ? edgeLoader : null |
885 | + property: "anchors.topMargin" |
886 | + value: edgeLoader.item && edgeLoader.item.flickable ? edgeLoader.item.flickable.contentY : 0 |
887 | + when: !page.isReady |
888 | + } |
889 | + |
890 | + onLoaded: { |
891 | + tip.forceActiveFocus() |
892 | + if (page.isReady && edgeLoader.item.active !== true) { |
893 | + page._pushPage() |
894 | } |
895 | } |
896 | } |
897 | |
898 | === modified file 'app/worldclock/UserWorldCityList.qml' |
899 | --- app/worldclock/UserWorldCityList.qml 2014-08-24 12:47:50 +0000 |
900 | +++ app/worldclock/UserWorldCityList.qml 2014-10-05 00:32:38 +0000 |
901 | @@ -21,8 +21,6 @@ |
902 | import U1db 1.0 as U1db |
903 | import Ubuntu.Components 1.1 |
904 | |
905 | -import "../components/Utils.js" as Utils |
906 | - |
907 | Column { |
908 | id: worldCityColumn |
909 | |
910 | |
911 | === modified file 'tests/autopilot/ubuntu_clock_app/emulators.py' |
912 | --- tests/autopilot/ubuntu_clock_app/emulators.py 2014-09-12 19:44:18 +0000 |
913 | +++ tests/autopilot/ubuntu_clock_app/emulators.py 2014-10-05 00:32:38 +0000 |
914 | @@ -91,6 +91,8 @@ |
915 | self.bottomEdgePageLoaded.wait_for(True) |
916 | try: |
917 | action_item = self.wait_select_single(objectName='bottomEdgeTip') |
918 | + action_item.hiden.wait_for(False) |
919 | + action_item.enabled.wait_for(True) |
920 | start_x = (action_item.globalRect.x + |
921 | (action_item.globalRect.width * 0.5)) |
922 | start_y = (action_item.globalRect.y + |
923 | |
924 | === modified file 'tests/unit/tst_alarm.qml' |
925 | --- tests/unit/tst_alarm.qml 2014-09-25 22:10:27 +0000 |
926 | +++ tests/unit/tst_alarm.qml 2014-10-05 00:32:38 +0000 |
927 | @@ -18,6 +18,7 @@ |
928 | |
929 | import QtQuick 2.3 |
930 | import QtTest 1.0 |
931 | +import DateTime 1.0 |
932 | import Ubuntu.Test 1.0 |
933 | import Ubuntu.Components 1.1 |
934 | import "../../app/alarm" |
935 | @@ -29,10 +30,26 @@ |
936 | height: units.gu(70) |
937 | useDeprecatedToolbar: false |
938 | |
939 | + property var clockTime: new Date |
940 | + ( |
941 | + localTimeSource.localDateString.split(":")[0], |
942 | + localTimeSource.localDateString.split(":")[1]-1, |
943 | + localTimeSource.localDateString.split(":")[2], |
944 | + localTimeSource.localTimeString.split(":")[0], |
945 | + localTimeSource.localTimeString.split(":")[1], |
946 | + localTimeSource.localTimeString.split(":")[2], |
947 | + localTimeSource.localTimeString.split(":")[3] |
948 | + ) |
949 | + |
950 | AlarmModel { |
951 | id: alarmModel |
952 | } |
953 | |
954 | + DateTime { |
955 | + id: localTimeSource |
956 | + updateInterval: 1000 |
957 | + } |
958 | + |
959 | PageStack { |
960 | id: pageStack |
961 | Component.onCompleted: push(alarmPage) |