Merge lp:~renatofilho/ubuntu-calendar-app/account-name-and-calendars into lp:ubuntu-calendar-app
- account-name-and-calendars
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | Bill Filler |
Approved revision: | 884 |
Merged at revision: | 858 |
Proposed branch: | lp:~renatofilho/ubuntu-calendar-app/account-name-and-calendars |
Merge into: | lp:ubuntu-calendar-app |
Prerequisite: | lp:~renatofilho/ubuntu-calendar-app/fix-model-update-after-save |
Diff against target: |
1199 lines (+464/-157) 19 files modified
AgendaView.qml (+1/-1) CalendarChoicePopup.qml (+16/-0) DayView.qml (+7/-2) EventActions.qml (+2/-2) EventBubble.qml (+12/-5) EventDetails.qml (+7/-10) EventListModel.qml (+65/-31) MonthView.qml (+6/-1) MonthWithEventsComponent.qml (+2/-1) NewEvent.qml (+41/-37) RemindersModel.qml (+80/-1) RemindersPage.qml (+108/-0) SettingsPage.qml (+12/-2) TimeLineBase.qml (+23/-6) TimeLineBaseComponent.qml (+1/-10) WeekView.qml (+21/-8) calendar.qml (+50/-36) calendar_canvas_worker.js (+1/-1) tests/unittests/tst_event_list_model.qml (+9/-3) |
To merge this branch: | bzr merge lp:~renatofilho/ubuntu-calendar-app/account-name-and-calendars |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
system-apps-ci-bot | continuous-integration | Needs Fixing | |
Jenkins Bot | continuous-integration | Approve | |
Kunal Parmar | Pending | ||
Review via email: mp+297113@code.launchpad.net |
Commit message
Show the account name as subtitle for calendars.
Description of the change
Jenkins Bot (ubuntu-core-apps-jenkins-bot) wrote : | # |
- 855. By Renato Araujo Oliveira Filho
-
Create active property to allow disable 'autoUpdate' even if the sync is not running.
Avoid conflicts with 'autoUpdate' changes. - 856. By Renato Araujo Oliveira Filho
-
Disable 'sync' button only if is sync is running.
Jenkins Bot (ubuntu-core-apps-jenkins-bot) wrote : | # |
PASSED: Continuous integration, rev:856
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild:
https:/
- 857. By Renato Araujo Oliveira Filho
-
Disable model update if the app is not active.
- 858. By Renato Araujo Oliveira Filho
-
Fix typo.
Jenkins Bot (ubuntu-core-apps-jenkins-bot) wrote : | # |
PASSED: Continuous integration, rev:858
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild:
https:/
- 859. By Renato Araujo Oliveira Filho
-
Fix typo.
- 860. By Renato Araujo Oliveira Filho
-
Add more debug.
Jenkins Bot (ubuntu-core-apps-jenkins-bot) wrote : | # |
PASSED: Continuous integration, rev:860
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild:
https:/
- 861. By Renato Araujo Oliveira Filho
-
Avoid reload events if the model has invalid filter.
Jenkins Bot (ubuntu-core-apps-jenkins-bot) wrote : | # |
PASSED: Continuous integration, rev:861
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild:
https:/
- 862. By Renato Araujo Oliveira Filho
-
Set year as initial view if settings is empty.
Jenkins Bot (ubuntu-core-apps-jenkins-bot) wrote : | # |
PASSED: Continuous integration, rev:862
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild:
https:/
- 863. By Renato Araujo Oliveira Filho
-
Remove debug messages.
Jenkins Bot (ubuntu-core-apps-jenkins-bot) wrote : | # |
PASSED: Continuous integration, rev:863
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild:
https:/
- 864. By Renato Araujo Oliveira Filho
-
Allow to enter custom values for reminders.
- 865. By Renato Araujo Oliveira Filho
-
Force focus on interval field in custom reminder dialog.
Jenkins Bot (ubuntu-core-apps-jenkins-bot) wrote : | # |
PASSED: Continuous integration, rev:865
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild:
https:/
- 866. By Renato Araujo Oliveira Filho
-
Removed debug message.
- 867. By Renato Araujo Oliveira Filho
-
Avoid runtinme warnings.
Jenkins Bot (ubuntu-core-apps-jenkins-bot) wrote : | # |
PASSED: Continuous integration, rev:867
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild:
https:/
- 868. By Renato Araujo Oliveira Filho
-
Removed more debug messages.
Jenkins Bot (ubuntu-core-apps-jenkins-bot) wrote : | # |
PASSED: Continuous integration, rev:868
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild:
https:/
- 869. By Renato Araujo Oliveira Filho
-
Pla hepatic feedback after click and hold over a event bubble.
Jenkins Bot (ubuntu-core-apps-jenkins-bot) wrote : | # |
PASSED: Continuous integration, rev:869
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild:
https:/
system-apps-ci-bot (system-apps-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:869
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
Click here to trigger a rebuild:
https:/
- 870. By Renato Araujo Oliveira Filho
-
Added 'qtdeclarative5
-qtorganizer- plugin' as build dep, necessary for tests.
Jenkins Bot (ubuntu-core-apps-jenkins-bot) wrote : | # |
PASSED: Continuous integration, rev:870
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild:
https:/
system-apps-ci-bot (system-apps-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:870
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
Click here to trigger a rebuild:
https:/
- 871. By Renato Araujo Oliveira Filho
-
Trunk merged.
- 872. By Renato Araujo Oliveira Filho
-
Updated test.
Jenkins Bot (ubuntu-core-apps-jenkins-bot) wrote : | # |
PASSED: Continuous integration, rev:872
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild:
https:/
system-apps-ci-bot (system-apps-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:872
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
Click here to trigger a rebuild:
https:/
system-apps-ci-bot (system-apps-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:872
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
Click here to trigger a rebuild:
https:/
- 873. By Renato Araujo Oliveira Filho
-
Show 'No reminder' if the reminder list is empty.
Jenkins Bot (ubuntu-core-apps-jenkins-bot) wrote : | # |
PASSED: Continuous integration, rev:873
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild:
https:/
system-apps-ci-bot (system-apps-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:873
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
FAILURE: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
FAILURE: https:/
Click here to trigger a rebuild:
https:/
system-apps-ci-bot (system-apps-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:873
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
FAILURE: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
FAILURE: https:/
Click here to trigger a rebuild:
https:/
- 874. By Renato Araujo Oliveira Filho
-
Make sure that the calendar list is updated if the collections changed.
Jenkins Bot (ubuntu-core-apps-jenkins-bot) wrote : | # |
PASSED: Continuous integration, rev:874
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild:
https:/
system-apps-ci-bot (system-apps-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:874
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
Click here to trigger a rebuild:
https:/
- 875. By Renato Araujo Oliveira Filho
-
Sort collections by name;
Full expand calendar selector when clicked;
Jenkins Bot (ubuntu-core-apps-jenkins-bot) wrote : | # |
PASSED: Continuous integration, rev:875
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild:
https:/
system-apps-ci-bot (system-apps-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:875
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
Click here to trigger a rebuild:
https:/
- 876. By Renato Araujo Oliveira Filho
-
Make sure that new floating event is drawed over the other events.
Jenkins Bot (ubuntu-core-apps-jenkins-bot) wrote : | # |
PASSED: Continuous integration, rev:876
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild:
https:/
- 877. By Renato Araujo Oliveira Filho
-
Fallback to month view in case of no previous page selected.
Jenkins Bot (ubuntu-core-apps-jenkins-bot) wrote : | # |
PASSED: Continuous integration, rev:877
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild:
https:/
system-apps-ci-bot (system-apps-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:876
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
Click here to trigger a rebuild:
https:/
system-apps-ci-bot (system-apps-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:877
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
Click here to trigger a rebuild:
https:/
- 878. By Renato Araujo Oliveira Filho
-
Push tabs on main stack after component completed.
Jenkins Bot (ubuntu-core-apps-jenkins-bot) wrote : | # |
PASSED: Continuous integration, rev:878
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild:
https:/
system-apps-ci-bot (system-apps-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:878
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
Click here to trigger a rebuild:
https:/
- 879. By Renato Araujo Oliveira Filho
-
Does not update model if the page is not active.
- 880. By Renato Araujo Oliveira Filho
-
Update collections list when new event page is activated.
Jenkins Bot (ubuntu-core-apps-jenkins-bot) wrote : | # |
PASSED: Continuous integration, rev:880
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild:
https:/
system-apps-ci-bot (system-apps-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:880
https:/
Executed test runs:
SUCCESS: https:/
FAILURE: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
Click here to trigger a rebuild:
https:/
- 881. By Renato Araujo Oliveira Filho
-
only auto update view if it is active.
- 882. By Renato Araujo Oliveira Filho
-
Destroy all events bubble durin the destruction.
- 883. By Renato Araujo Oliveira Filho
-
Update view when page became active.
- 884. By Renato Araujo Oliveira Filho
-
Make collections model always active.
Jenkins Bot (ubuntu-core-apps-jenkins-bot) wrote : | # |
PASSED: Continuous integration, rev:884
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild:
https:/
system-apps-ci-bot (system-apps-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:884
https:/
Executed test runs:
SUCCESS: https:/
FAILURE: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
Preview Diff
1 | === modified file 'AgendaView.qml' |
2 | --- AgendaView.qml 2016-07-21 21:44:34 +0000 |
3 | +++ AgendaView.qml 2016-07-21 21:44:34 +0000 |
4 | @@ -68,7 +68,7 @@ |
5 | startPeriod: anchorDate.midnight(); |
6 | endPeriod: anchorDate.addDays(7).endOfDay() |
7 | filter: model.filter |
8 | - autoUpdate: root.tabSelected |
9 | + active: root.tabSelected && root.active |
10 | sortOrders: [ |
11 | SortOrder{ |
12 | blankPolicy: SortOrder.BlanksFirst |
13 | |
14 | === modified file 'CalendarChoicePopup.qml' |
15 | --- CalendarChoicePopup.qml 2016-03-22 12:29:05 +0000 |
16 | +++ CalendarChoicePopup.qml 2016-07-21 21:44:34 +0000 |
17 | @@ -21,6 +21,7 @@ |
18 | import Ubuntu.Components 1.3 |
19 | import Ubuntu.SyncMonitor 0.1 |
20 | import Ubuntu.Components.Popups 1.3 |
21 | +import Ubuntu.OnlineAccounts 0.1 |
22 | |
23 | Page { |
24 | id: calendarChoicePage |
25 | @@ -29,6 +30,15 @@ |
26 | property var model |
27 | signal collectionUpdated() |
28 | |
29 | + function accountFromId(accountId) |
30 | + { |
31 | + if (accountId && accountId >= 0) { |
32 | + return Manager.loadAccount(accountId) |
33 | + } |
34 | + |
35 | + return null |
36 | + } |
37 | + |
38 | visible: false |
39 | header: PageHeader { |
40 | title: i18n.tr("Calendars") |
41 | @@ -96,7 +106,13 @@ |
42 | ListItemLayout { |
43 | id: calendarsListLayout |
44 | |
45 | + Account { |
46 | + id: delegateAccount |
47 | + objectHandle: calendarChoicePage.accountFromId(modelData.extendedMetaData("collection-account-id")) |
48 | + } |
49 | + |
50 | title.text: modelData.name |
51 | + subtitle.text: delegateAccount.objectHandle ? delegateAccount.displayName : "" |
52 | title.objectName: "calendarName" |
53 | |
54 | CheckBox { |
55 | |
56 | === modified file 'DayView.qml' |
57 | --- DayView.qml 2016-07-21 21:44:34 +0000 |
58 | +++ DayView.qml 2016-07-21 21:44:34 +0000 |
59 | @@ -163,7 +163,7 @@ |
60 | startDay: anchorDate.addDays(dayViewPath.loopCurrentIndex + dayViewPath.indexType(index)) |
61 | keyboardEventProvider: dayViewPath |
62 | modelFilter: dayViewPage.model ? dayViewPage.model.filter : null |
63 | - autoUpdate: dayViewPage.tabSelected |
64 | + autoUpdate: dayViewPage.tabSelected && dayViewPage.active && PathView.isCurrentItem |
65 | |
66 | onPressAndHoldAt: { |
67 | dayViewPage.pressAndHoldAt(date, allDay) |
68 | @@ -178,10 +178,15 @@ |
69 | Connections{ |
70 | target: dayViewPage |
71 | onTabSelectedChanged: { |
72 | - if(tabSelected){ |
73 | + if(dayViewPage.tabSelected){ |
74 | timeLineView.scrollToTime(new Date()); |
75 | } |
76 | } |
77 | + onActiveChanged: { |
78 | + if (dayViewPage.active) { |
79 | + timeLineView.update() |
80 | + } |
81 | + } |
82 | onEventSaved: { |
83 | timeLineView.update() |
84 | } |
85 | |
86 | === modified file 'EventActions.qml' |
87 | --- EventActions.qml 2016-03-16 20:35:07 +0000 |
88 | +++ EventActions.qml 2016-07-21 21:44:34 +0000 |
89 | @@ -28,7 +28,7 @@ |
90 | property alias syncCalendarAction: _syncCalendarAction |
91 | property alias settingsAction: _settingsAction |
92 | property Settings settings |
93 | - readonly property bool syncInProgress: (syncMonitor.state === "syncing") |
94 | + readonly property bool syncInProgress: (syncMonitor.state !== "") && (syncMonitor.state === "syncing") |
95 | |
96 | Action { |
97 | id: _syncCalendarAction |
98 | @@ -38,7 +38,7 @@ |
99 | // Currently ,there is no way we can increase width of action menu currently. |
100 | text: enabled ? i18n.tr("Sync") : i18n.tr("Syncing") |
101 | onTriggered: syncMonitor.sync(["calendar"]) |
102 | - enabled: !syncInProgress |
103 | + enabled: !actionPool.syncInProgress |
104 | visible: syncMonitor.enabledServices ? syncMonitor.serviceIsEnabled("calendar") : false |
105 | } |
106 | |
107 | |
108 | === modified file 'EventBubble.qml' |
109 | --- EventBubble.qml 2016-04-06 18:46:29 +0000 |
110 | +++ EventBubble.qml 2016-07-21 21:44:34 +0000 |
111 | @@ -74,7 +74,9 @@ |
112 | updateTitle() |
113 | |
114 | //Accepted events: Solid collection color with white text. |
115 | - infoBubble.backgroundColor = collection.color |
116 | + if (collection) |
117 | + infoBubble.backgroundColor = collection.color |
118 | + |
119 | infoBubble.backgroundOpacity = 1 |
120 | infoBubble.titleColor = "white"; |
121 | infoBubble.strikeoutTitle = false; |
122 | @@ -98,8 +100,8 @@ |
123 | |
124 | } |
125 | } else { |
126 | - // Past events: As per accepted events, but at 75% transparency. |
127 | - infoBubble.backgroundOpacity = 0.25 |
128 | + // Past events: As per accepted events, but at 60% transparency. |
129 | + infoBubble.backgroundOpacity = 0.4 |
130 | } |
131 | } |
132 | } |
133 | @@ -219,8 +221,13 @@ |
134 | } |
135 | |
136 | onPressAndHold: { |
137 | - isLiveEditing = true; |
138 | - infoBubble.z += 1; |
139 | + if (event && model && model.collectionIsReadOnlyFromId(event.collectionId)) { |
140 | + console.debug("Read-only event can not be dragged") |
141 | + } else { |
142 | + isLiveEditing = true; |
143 | + infoBubble.z += 1; |
144 | + Haptics.play() |
145 | + } |
146 | } |
147 | } |
148 | } |
149 | |
150 | === modified file 'EventDetails.qml' |
151 | --- EventDetails.qml 2016-07-21 21:44:34 +0000 |
152 | +++ EventDetails.qml 2016-07-21 21:44:34 +0000 |
153 | @@ -147,16 +147,13 @@ |
154 | function updateReminder(event) { |
155 | //TODO: implment support for display information about all reminder |
156 | // We can have multiples Audible and Visible reminders. |
157 | - var reminder = event.detail(Detail.AudibleReminder) |
158 | - if(reminder) { |
159 | - for(var i=0; i<reminderModel.count; i++) { |
160 | - if(reminder.secondsBeforeStart === reminderModel.get(i).value) { |
161 | - reminderLayout.subtitle.text = reminderModel.get(i).label |
162 | - } |
163 | - } |
164 | - } else { |
165 | - reminderLayout.subtitle.text = reminderModel.get(0).label |
166 | - } |
167 | + var reminder = event.detail(Detail.VisualReminder) |
168 | + // fallback to Audible reminders |
169 | + if (!reminder) |
170 | + reminder = event.detail(Detail.AudibleReminder) |
171 | + |
172 | + var interval = reminder ? reminder.secondsBeforeStart : -1 |
173 | + reminderLayout.subtitle.text = reminderModel.intervalToString(interval) |
174 | } |
175 | |
176 | function getDate(e) { |
177 | |
178 | === modified file 'EventListModel.qml' |
179 | --- EventListModel.qml 2016-07-21 21:44:34 +0000 |
180 | +++ EventListModel.qml 2016-07-21 21:44:34 +0000 |
181 | @@ -1,4 +1,4 @@ |
182 | -/* |
183 | +/* |
184 | * Copyright (C) 2013-2014 Canonical Ltd |
185 | * |
186 | * This file is part of Ubuntu Calendar App |
187 | @@ -24,14 +24,22 @@ |
188 | id: eventModel |
189 | manager:"eds" |
190 | |
191 | + readonly property bool appIsActive: (Qt.application.state === Qt.ApplicationActive) |
192 | + property bool active: false |
193 | property var listeners:[]; |
194 | property bool isLoading: false |
195 | + property bool live: false |
196 | // disable update while syncing to avoid tons of unecessary update |
197 | + // disable update if the app is not active |
198 | property var _priv: Binding { |
199 | target: eventModel |
200 | property: "autoUpdate" |
201 | - value: false |
202 | - when: mainView.syncInProgress |
203 | + value: mainView.syncInProgress ? (false || live) |
204 | + : (eventModel.active && eventModel.appIsActive) || live |
205 | + } |
206 | + |
207 | + function _sortCollections(collectionA, collectionB) { |
208 | + return collectionA.name.localeCompare(collectionB.name) |
209 | } |
210 | |
211 | function addModelChangeListener(listener){ |
212 | @@ -62,14 +70,22 @@ |
213 | }); |
214 | } |
215 | |
216 | - onModelChanged: { |
217 | - isLoading = false |
218 | - if(listeners === undefined){ |
219 | - return; |
220 | - } |
221 | - for(var i=0; i < listeners.length ;++i){ |
222 | - (listeners[i])(); |
223 | - } |
224 | + function collectionIsReadOnlyFromId(collectionId) |
225 | + { |
226 | + if (collectionId === "") |
227 | + return false |
228 | + |
229 | + var cal = eventModel.collection(collectionId) |
230 | + return collectionIsReadOnly(cal) |
231 | + } |
232 | + |
233 | + function collectionIsReadOnly(collection) |
234 | + { |
235 | + if (!collection) |
236 | + return false |
237 | + |
238 | + return collection.extendedMetaData("collection-readonly") === true || |
239 | + collection.extendedMetaData("collection-sync-readonly") === true |
240 | } |
241 | |
242 | function getCollections(){ |
243 | @@ -81,6 +97,7 @@ |
244 | cals.push(cal); |
245 | } |
246 | } |
247 | + cals.sort(eventModel._sortCollections) |
248 | return cals; |
249 | } |
250 | |
251 | @@ -91,24 +108,12 @@ |
252 | var cal = collections[i]; |
253 | if( cal.extendedMetaData("collection-type") === "Calendar" && |
254 | cal.extendedMetaData("collection-selected") === true && |
255 | - cal.extendedMetaData("collection-readonly") === false) { |
256 | - cals.push(cal); |
257 | - } |
258 | - } |
259 | - return cals; |
260 | - } |
261 | - |
262 | - function getWritableCollections(){ |
263 | - var cals = []; |
264 | - var collections = eventModel.collections; |
265 | - for(var i = 0 ; i < collections.length ; ++i) { |
266 | - var cal = collections[i]; |
267 | - if( cal.extendedMetaData("collection-type") === "Calendar" && |
268 | - cal.extendedMetaData("collection-readonly") === false ) { |
269 | - cals.push(cal); |
270 | - } |
271 | - } |
272 | - return cals; |
273 | + !collectionIsReadOnly(cal)) { |
274 | + cals.push(cal); |
275 | + } |
276 | + } |
277 | + cals.sort(eventModel._sortCollections); |
278 | + return cals |
279 | } |
280 | |
281 | function getDefaultCollection() { |
282 | @@ -172,9 +177,26 @@ |
283 | |
284 | function updateIfNecessary() |
285 | { |
286 | - console.debug("UpdateIfNecessary:" + eventModel + " has autoUpdate?" + autoUpdate) |
287 | - if (!autoUpdate) |
288 | + if (!autoUpdate) { |
289 | update() |
290 | + } |
291 | + } |
292 | + |
293 | + // init model with invalid filter |
294 | + filter: InvalidFilter { objectName: "invalidFilter" } |
295 | + |
296 | + onModelChanged: { |
297 | + isLoading = false |
298 | + if(listeners === undefined){ |
299 | + return; |
300 | + } |
301 | + for(var i=0; i < listeners.length ;++i){ |
302 | + (listeners[i])(); |
303 | + } |
304 | + } |
305 | + |
306 | + onFilterChanged: { |
307 | + updateIfNecessary() |
308 | } |
309 | |
310 | onStartPeriodChanged: { |
311 | @@ -192,4 +214,16 @@ |
312 | eventModel.update() |
313 | } |
314 | } |
315 | + |
316 | + onActiveChanged: { |
317 | + if (active) { |
318 | + updateIfNecessary() |
319 | + } |
320 | + } |
321 | + |
322 | + Component.onCompleted: { |
323 | + if (active) { |
324 | + updateIfNecessary() |
325 | + } |
326 | + } |
327 | } |
328 | |
329 | === modified file 'MonthView.qml' |
330 | --- MonthView.qml 2016-07-21 21:44:34 +0000 |
331 | +++ MonthView.qml 2016-07-21 21:44:34 +0000 |
332 | @@ -99,7 +99,7 @@ |
333 | currentYear: indexDate.getFullYear() |
334 | displayLunarCalendar: monthViewPage.displayLunarCalendar |
335 | |
336 | - autoUpdate: monthViewPage.tabSelected |
337 | + autoUpdate: monthViewPage.tabSelected && monthViewPage.active && PathView.isCurrentItem |
338 | modelFilter: eventModel.filter |
339 | width: parent.width - units.gu(4) |
340 | height: parent.height |
341 | @@ -115,6 +115,11 @@ |
342 | // make sure that the model is updated after create a new event if it is marked as auto-update false |
343 | Connections { |
344 | target: monthViewPage |
345 | + onActiveChanged: { |
346 | + if (monthViewPage.active) { |
347 | + monthDelegate.update() |
348 | + } |
349 | + } |
350 | onEventSaved: { |
351 | monthDelegate.update() |
352 | } |
353 | |
354 | === modified file 'MonthWithEventsComponent.qml' |
355 | --- MonthWithEventsComponent.qml 2016-07-21 21:44:34 +0000 |
356 | +++ MonthWithEventsComponent.qml 2016-07-21 21:44:34 +0000 |
357 | @@ -26,7 +26,7 @@ |
358 | objectName: "MonthComponent" |
359 | |
360 | property bool isActive: false |
361 | - property alias autoUpdate: mainModel.autoUpdate |
362 | + property alias autoUpdate: mainModel.active |
363 | property var modelFilter: invalidFilter |
364 | |
365 | function refresh() { |
366 | @@ -62,6 +62,7 @@ |
367 | |
368 | InvalidFilter { |
369 | id: invalidFilter |
370 | + objectName: "invalidFilter" |
371 | } |
372 | |
373 | EventListModel { |
374 | |
375 | === modified file 'NewEvent.qml' |
376 | --- NewEvent.qml 2016-07-21 21:44:34 +0000 |
377 | +++ NewEvent.qml 2016-07-21 21:44:34 +0000 |
378 | @@ -169,7 +169,12 @@ |
379 | } |
380 | } |
381 | } |
382 | - var reminder = e.detail(Detail.AudibleReminder); |
383 | + |
384 | + var reminder = e.detail(Detail.VisualReminder) |
385 | + // fallback to audible |
386 | + if (!reminder) |
387 | + reminder = e.detail(Detail.AudibleReminder) |
388 | + |
389 | if (reminder) { |
390 | root.reminderValue = reminder.secondsBeforeStart |
391 | } else { |
392 | @@ -233,12 +238,14 @@ |
393 | } |
394 | } |
395 | |
396 | - // update audible reminder time if necessary |
397 | - // TODO: we only support audible reminders for now |
398 | - var reminder = event.detail(Detail.AudibleReminder); |
399 | + // update the first reminder time if necessary |
400 | + var reminder = event.detail(Detail.VisualReminder) |
401 | + if (!reminder) |
402 | + reminder = event.detail(Detail.AudibleReminder) |
403 | + |
404 | if (root.reminderValue >= 0) { |
405 | if (!reminder) { |
406 | - reminder = Qt.createQmlObject("import QtOrganizer 5.0; AudibleReminder {}", event, "") |
407 | + reminder = Qt.createQmlObject("import QtOrganizer 5.0; VisualReminder {}", event, "") |
408 | reminder.repetitionCount = 0 |
409 | reminder.repetitionDelay = 0 |
410 | } |
411 | @@ -256,7 +263,6 @@ |
412 | } |
413 | |
414 | model.saveItem(event) |
415 | - console.debug("Save item. Model is autoUpdate?" + model.autoUpdate) |
416 | root.eventSaved(event); |
417 | model.updateIfNecessary() |
418 | |
419 | @@ -577,9 +583,30 @@ |
420 | margins: units.gu(2) |
421 | } |
422 | |
423 | - containerHeight: itemHeight * 4 |
424 | + containerHeight: (model && (model.length > 1) ? itemHeight * model.length : itemHeight) |
425 | model: root.model ? root.model.getWritableAndSelectedCollections() : [] |
426 | |
427 | + Connections { |
428 | + target: root.model ? root.model : null |
429 | + onModelChanged: { |
430 | + calendarsOption.model = root.model.getWritableAndSelectedCollections() |
431 | + } |
432 | + onCollectionsChanged: { |
433 | + calendarsOption.model = root.model.getWritableAndSelectedCollections() |
434 | + } |
435 | + } |
436 | + |
437 | + Connections { |
438 | + target: root |
439 | + onActiveChanged: { |
440 | + if (root.active) { |
441 | + calendarsOption.model = root.model.getWritableAndSelectedCollections() |
442 | + } |
443 | + } |
444 | + } |
445 | + |
446 | + onExpansionCompleted: flickable.makeMeVisible(calendarsOption) |
447 | + |
448 | delegate: OptionSelectorDelegate{ |
449 | text: modelData.name |
450 | |
451 | @@ -718,31 +745,15 @@ |
452 | |
453 | property int reminderValue: -1 |
454 | |
455 | - onReminderValueChanged: updateReminderLabel() |
456 | - |
457 | ListItemLayout { |
458 | id: eventReminderLayout |
459 | title.text: i18n.tr("Reminder") |
460 | + summary.text: reminderModel.intervalToString(eventReminder.reminderValue) |
461 | ProgressionSlot {} |
462 | } |
463 | |
464 | - function updateReminderLabel() { |
465 | - if (eventReminder.reminderValue !== -1) { |
466 | - for (var i=0; i<reminderModel.count; i++) { |
467 | - if (reminderModel.get(i).value === eventReminder.reminderValue) { |
468 | - eventReminderLayout.summary.text = reminderModel.get(i).label |
469 | - return |
470 | - } |
471 | - } |
472 | - } else { |
473 | - eventReminderLayout.summary.text = reminderModel.get(0).label |
474 | - return |
475 | - } |
476 | - } |
477 | - |
478 | RemindersModel { |
479 | id: reminderModel |
480 | - onLoaded: eventReminder.updateReminderLabel() |
481 | } |
482 | |
483 | onClicked:{ |
484 | @@ -751,22 +762,15 @@ |
485 | stack = bottomEdgePageStack |
486 | } |
487 | |
488 | - var reminderSelectedIndex = 0 |
489 | - if (eventReminder.reminderValue !== -1) { |
490 | - for (var i=0; i<reminderModel.count; ++i) { |
491 | - if (reminderModel.get(i).value === eventReminder.reminderValue) { |
492 | - reminderSelectedIndex = i |
493 | - } |
494 | - } |
495 | - } |
496 | - |
497 | - var reminderPick = stack.push(Qt.resolvedUrl("OptionSelectorPage.qml"), |
498 | + reminderModel.reset() |
499 | + var reminderPick = stack.push(Qt.resolvedUrl("RemindersPage.qml"), |
500 | {"title": i18n.tr("Reminder"), |
501 | "model": reminderModel, |
502 | - "selectedIndex": reminderSelectedIndex}) |
503 | - reminderPick.selectedIndexChanged.connect(function() { |
504 | - root.reminderValue = reminderModel.get(reminderPick.selectedIndex).value |
505 | + "interval": eventReminder.reminderValue}) |
506 | + reminderPick.intervalChanged.connect(function() { |
507 | + root.reminderValue = reminderPick.interval |
508 | }) |
509 | + |
510 | } |
511 | } |
512 | } |
513 | |
514 | === modified file 'RemindersModel.qml' |
515 | --- RemindersModel.qml 2016-03-14 14:30:16 +0000 |
516 | +++ RemindersModel.qml 2016-07-21 21:44:34 +0000 |
517 | @@ -17,19 +17,92 @@ |
518 | */ |
519 | |
520 | import QtQuick 2.4 |
521 | +import Ubuntu.Components 1.3 |
522 | |
523 | ListModel { |
524 | id: reminderModel |
525 | |
526 | + property bool ready: false |
527 | + |
528 | signal loaded() |
529 | |
530 | - Component.onCompleted: { |
531 | + function intervalToString(interval) { |
532 | + if (interval < 0) |
533 | + return i18n.tr("No Reminder") |
534 | + |
535 | + if (interval === 0) |
536 | + return i18n.tr("On Event") |
537 | + |
538 | + var result = "" |
539 | + |
540 | + // Weeks |
541 | + var weeks = 0 |
542 | + if (interval >= 604800) { |
543 | + weeks = Math.floor(interval/604800) |
544 | + interval = interval % 604800 |
545 | + result = i18n.tr("%1 week", "%1 weeks", weeks).arg(weeks) |
546 | + } |
547 | + |
548 | + // Days |
549 | + var days = 0 |
550 | + if (interval >= 86400) { |
551 | + days = Math.floor(interval/86400) |
552 | + interval = interval % 86400 |
553 | + if (result.length > 0) { |
554 | + result = " " + result |
555 | + } |
556 | + result = i18n.tr("%1 day", "%1 days", days).arg(days) |
557 | + } |
558 | + |
559 | + // Hours |
560 | + var hours = 0 |
561 | + if (interval >= 3600) { |
562 | + hours = Math.floor(interval/3600) |
563 | + interval = interval % 3600 |
564 | + if (result.length > 0) { |
565 | + result = " " + result |
566 | + } |
567 | + result = i18n.tr("%1 hour", "%1 hours", hours).arg(hours) |
568 | + |
569 | + } |
570 | + |
571 | + if (interval > 0) { |
572 | + var minutes = Math.floor(interval/60) |
573 | + if (result.length > 0) { |
574 | + result = " " + result |
575 | + } |
576 | + result = i18n.tr("%1 minute", "%1 minutes", minutes).arg(minutes) |
577 | + } |
578 | + |
579 | + return result |
580 | + } |
581 | + |
582 | + function indexFromInterval(interval) |
583 | + { |
584 | + for (var i=0; i<reminderModel.count; ++i) { |
585 | + if (reminderModel.get(i).value == interval) |
586 | + return i |
587 | + } |
588 | + |
589 | + // custom |
590 | + return -1 |
591 | + } |
592 | + |
593 | + function intervalFromIndex(index) |
594 | + { |
595 | + return reminderModel.get(index).value |
596 | + } |
597 | + |
598 | + function reset() |
599 | + { |
600 | + clear() |
601 | reminderModel.append({ "label": i18n.tr("No Reminder"), "value": -1 }) |
602 | // TRANSLATORS: this refers to when a reminder should be shown as a notification |
603 | // in the indicators. "On Event" means that it will be shown right at the time |
604 | // the event starts, not any time before |
605 | reminderModel.append({ "label": i18n.tr("On Event"), "value": 0 }) |
606 | reminderModel.append({ "label": i18n.tr("5 minutes"), "value": 300 }) |
607 | + reminderModel.append({ "label": i18n.tr("10 minutes"), "value": 600 }) |
608 | reminderModel.append({ "label": i18n.tr("15 minutes"), "value": 900 }) |
609 | reminderModel.append({ "label": i18n.tr("30 minutes"), "value": 1800 }) |
610 | reminderModel.append({ "label": i18n.tr("1 hour"), "value": 3600 }) |
611 | @@ -38,6 +111,12 @@ |
612 | reminderModel.append({ "label": i18n.tr("2 days"), "value": 172800 }) |
613 | reminderModel.append({ "label": i18n.tr("1 week"), "value": 604800 }) |
614 | reminderModel.append({ "label": i18n.tr("2 weeks"), "value": 1209600 }) |
615 | + reminderModel.append({ "label": i18n.tr("Custom"), "value": -2 }) |
616 | + } |
617 | + |
618 | + Component.onCompleted: { |
619 | + reset() |
620 | + ready = true |
621 | reminderModel.loaded() |
622 | } |
623 | } |
624 | |
625 | === added file 'RemindersPage.qml' |
626 | --- RemindersPage.qml 1970-01-01 00:00:00 +0000 |
627 | +++ RemindersPage.qml 2016-07-21 21:44:34 +0000 |
628 | @@ -0,0 +1,108 @@ |
629 | +/* |
630 | + * Copyright (C) 2016 Canonical Ltd |
631 | + * |
632 | + * This file is part of Ubuntu Calendar App |
633 | + * |
634 | + * Ubuntu Calendar App is free software: you can redistribute it and/or modify |
635 | + * it under the terms of the GNU General Public License version 3 as |
636 | + * published by the Free Software Foundation. |
637 | + * |
638 | + * Ubuntu Calendar App is distributed in the hope that it will be useful, |
639 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
640 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
641 | + * GNU General Public License for more details. |
642 | + * |
643 | + * You should have received a copy of the GNU General Public License |
644 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
645 | + */ |
646 | + |
647 | +import QtQuick 2.4 |
648 | +import Ubuntu.Components 1.3 |
649 | +import Ubuntu.Components.Popups 1.3 |
650 | + |
651 | +OptionSelectorPage { |
652 | + id: optionSelectorPage |
653 | + |
654 | + property int interval: -1 |
655 | + |
656 | + function refresh() |
657 | + { |
658 | + if (!model.ready) |
659 | + return |
660 | + |
661 | + var newIndex = model.indexFromInterval(interval) |
662 | + // append custom interval |
663 | + if (newIndex === -1) { |
664 | + var strInteval = model.intervalToString(interval) |
665 | + var value = { "label": strInteval, "value": interval } |
666 | + |
667 | + // find position for new interval |
668 | + for (var i=0; i<model.count; ++i) { |
669 | + if (model.get(i).value > interval) { |
670 | + model.insert(i, value) |
671 | + newIndex = i |
672 | + break |
673 | + } |
674 | + } |
675 | + |
676 | + if (newIndex === -1) { |
677 | + model.append(value) |
678 | + newIndex = (model.count - 1) |
679 | + } |
680 | + } |
681 | + |
682 | + selectedIndex = newIndex |
683 | + } |
684 | + |
685 | + Component { |
686 | + id: dialogCustomInterval |
687 | + Dialog { |
688 | + id: dialog |
689 | + |
690 | + title: i18n.tr("Custom reminder") |
691 | + text: "How many minutes before event?" |
692 | + TextField { |
693 | + id: customInteval |
694 | + |
695 | + validator: IntValidator{ bottom: 1; } |
696 | + inputMethodHints: Qt.ImhDigitsOnly |
697 | + } |
698 | + |
699 | + Button { |
700 | + text: i18n.tr("Cancel") |
701 | + onClicked: { |
702 | + selectedIndex = model.indexFromInterval(interval) |
703 | + PopupUtils.close(dialog) |
704 | + } |
705 | + } |
706 | + Button { |
707 | + enabled: !!customInteval.text.trim() |
708 | + text: i18n.tr("Ok") |
709 | + onClicked: { |
710 | + if (customInteval.text > 0) { |
711 | + var minutes = parseInt(customInteval.text.trim()) |
712 | + if (minutes > 0) { |
713 | + optionSelectorPage.interval = minutes * 60 |
714 | + optionSelectorPage.refresh() |
715 | + } |
716 | + } |
717 | + PopupUtils.close(dialog) |
718 | + } |
719 | + } |
720 | + |
721 | + Component.onCompleted: customInteval.forceActiveFocus() |
722 | + } |
723 | + } |
724 | + |
725 | + model: RemindersModel { |
726 | + onLoaded: refresh() |
727 | + } |
728 | + onSelectedIndexChanged: { |
729 | + var newInterval = model.intervalFromIndex(selectedIndex) |
730 | + if (newInterval === -2) { |
731 | + PopupUtils.open(dialogCustomInterval) |
732 | + } else { |
733 | + interval = newInterval |
734 | + } |
735 | + } |
736 | +} |
737 | |
738 | === modified file 'SettingsPage.qml' |
739 | --- SettingsPage.qml 2016-03-17 17:45:21 +0000 |
740 | +++ SettingsPage.qml 2016-07-21 21:44:34 +0000 |
741 | @@ -170,8 +170,18 @@ |
742 | id: defaultCalendarOptionSelector |
743 | |
744 | text: i18n.tr("Default calendar") |
745 | - model: settingsPage.eventModel ? settingsPage.eventModel.getWritableAndSelectedCollections() : null |
746 | - containerHeight: itemHeight * 4 |
747 | + model: settingsPage.eventModel ? settingsPage.eventModel.getWritableAndSelectedCollections() : [] |
748 | + containerHeight: (model && (model.length > 1) ? itemHeight * model.length : itemHeight) |
749 | + |
750 | + Connections { |
751 | + target: settingsPage.eventModel ? settingsPage.eventModel : null |
752 | + onModelChanged: { |
753 | + defaultCalendarOptionSelector.model = settingsPage.eventModel.getWritableAndSelectedCollections() |
754 | + } |
755 | + onCollectionsChanged: { |
756 | + defaultCalendarOptionSelector.model = settingsPage.eventModel.getWritableAndSelectedCollections() |
757 | + } |
758 | + } |
759 | |
760 | delegate: OptionSelectorDelegate { |
761 | text: modelData.name |
762 | |
763 | === modified file 'TimeLineBase.qml' |
764 | --- TimeLineBase.qml 2016-04-27 20:02:38 +0000 |
765 | +++ TimeLineBase.qml 2016-07-21 21:44:34 +0000 |
766 | @@ -85,6 +85,7 @@ |
767 | var events = messageObject.reply |
768 | var dirty = false |
769 | for (var i=0; i < events.length; i++) { |
770 | + var eventId = events[i].eventId |
771 | createVisual(events[i]) |
772 | } |
773 | } |
774 | @@ -126,23 +127,28 @@ |
775 | |
776 | function createEvents() { |
777 | if(!bubbleOverLay || bubbleOverLay == undefined || model === undefined || model === null) { |
778 | - console.debug("\tabort.") |
779 | + console.debug("\t*************************************abort event drawinig******************.") |
780 | return; |
781 | } |
782 | |
783 | // check if there is any update in progress |
784 | if (intern.busy) { |
785 | - console.debug("Work script still busy, postpone update") |
786 | + console.debug("************************Work script still busy, postpone update**************") |
787 | // mark as dirsty to triggere a new update after the message arrives |
788 | intern.dirty = true |
789 | return; |
790 | } |
791 | |
792 | - intern.busy = true |
793 | + |
794 | intern.dirty = false |
795 | - destroyAllChildren(); |
796 | + hideAllChildren(); |
797 | intern.eventsById = {} |
798 | |
799 | + if (model.filter.objectName === "invalidFilter") { |
800 | + return |
801 | + } |
802 | + |
803 | + intern.busy = true |
804 | var startDate = day.midnight() |
805 | var itemsOfTheDay = model.itemsByTimePeriod(startDate, startDate.endOfDay()) |
806 | if (itemsOfTheDay.length === 0) { |
807 | @@ -161,7 +167,7 @@ |
808 | bubbleOverLay.showSeparator(); |
809 | } |
810 | |
811 | - function destroyAllChildren() { |
812 | + function hideAllChildren() { |
813 | separator.visible = false |
814 | for(var i=0; i < children.length; i++) { |
815 | var child = children[i] |
816 | @@ -177,6 +183,15 @@ |
817 | } |
818 | } |
819 | |
820 | + function destroyAllChildren() { |
821 | + hideAllChildren() |
822 | + for(var i=0; i < intern.unUsedEvents.length; i++) { |
823 | + var child = intern.unUsedEvents[i] |
824 | + child.destroy() |
825 | + } |
826 | + intern.unUsedEvents = [] |
827 | + } |
828 | + |
829 | function getUnusedEventBubble() { |
830 | var unusedEvent = null |
831 | if (intern.unUsedEvents.length > 0) { |
832 | @@ -209,7 +224,6 @@ |
833 | isLiveEditing: overlayMouseArea.creatingEvent |
834 | visible: overlayMouseArea.creatingEvent |
835 | sizeOfRow: 1.0 |
836 | - z: 100 |
837 | onVisibleChanged: { |
838 | if (visible) |
839 | y = event ? CanlendarCanvas.minutesSince(bubbleOverLay.day, event.startDateTime) * bubbleOverLay.minuteHeight : 0 |
840 | @@ -268,6 +282,7 @@ |
841 | temporaryEvent.model = bubbleOverLay.model |
842 | temporaryEvent.event = event |
843 | temporaryEvent.resize() |
844 | + temporaryEvent.z = 1000 |
845 | creatingEvent = true |
846 | } |
847 | |
848 | @@ -330,4 +345,6 @@ |
849 | bubbleOverLay.idleCreateEvents() |
850 | } |
851 | } |
852 | + |
853 | + Component.onDestruction: destroyAllChildren() |
854 | } |
855 | |
856 | === modified file 'TimeLineBaseComponent.qml' |
857 | --- TimeLineBaseComponent.qml 2016-07-21 21:44:34 +0000 |
858 | +++ TimeLineBaseComponent.qml 2016-07-21 21:44:34 +0000 |
859 | @@ -36,7 +36,7 @@ |
860 | property int weekNumber: startDay.weekNumber(Qt.locale().firstDayOfWeek); |
861 | property alias contentY: timeLineView.contentY |
862 | property alias contentInteractive: timeLineView.interactive |
863 | - property alias autoUpdate: mainModel.autoUpdate |
864 | + property alias autoUpdate: mainModel.active |
865 | property var modelFilter: invalidFilter |
866 | property var selectedDay; |
867 | |
868 | @@ -134,7 +134,6 @@ |
869 | |
870 | function update() |
871 | { |
872 | - console.debug("will update model if necessary.") |
873 | mainModel.updateIfNecessary() |
874 | } |
875 | |
876 | @@ -184,16 +183,9 @@ |
877 | repeat: false |
878 | onTriggered: { |
879 | mainModel.filter = Qt.binding(function() { return root.modelFilter} ) |
880 | - if (!mainModel.autoUpdate) { |
881 | - mainModel.update() |
882 | - } |
883 | } |
884 | } |
885 | |
886 | - InvalidFilter { |
887 | - id: invalidFilter |
888 | - } |
889 | - |
890 | EventListModel { |
891 | id: mainModel |
892 | objectName: "timeLineBaseEventListModel:" + root.objectName |
893 | @@ -201,7 +193,6 @@ |
894 | manager:"eds" |
895 | startPeriod: startDay.midnight(); |
896 | endPeriod: type == ViewType.ViewTypeWeek ? startPeriod.addDays(6).endOfDay(): startPeriod.endOfDay() |
897 | - filter: invalidFilter |
898 | |
899 | onStartPeriodChanged: idleRefresh.reset() |
900 | onEndPeriodChanged: idleRefresh.reset() |
901 | |
902 | === modified file 'WeekView.qml' |
903 | --- WeekView.qml 2016-07-21 21:44:34 +0000 |
904 | +++ WeekView.qml 2016-07-21 21:44:34 +0000 |
905 | @@ -97,13 +97,15 @@ |
906 | interval: 200 |
907 | repeat:false |
908 | onTriggered: { |
909 | - if (scrollToDate) { |
910 | - if (scrollToTime) |
911 | - weekViewPath.currentItem.item.scrollToDateAndTime(scrollToDate); |
912 | - else |
913 | - weekViewPath.currentItem.item.scrollToDate(scrollToDate); |
914 | - } else { |
915 | - weekViewPath.currentItem.item.scrollToBegin() |
916 | + if (weekViewPath.currentItem && weekViewPath.currentItem.item) { |
917 | + if (scrollToDate) { |
918 | + if (scrollToTime) |
919 | + weekViewPath.currentItem.item.scrollToDateAndTime(scrollToDate); |
920 | + else |
921 | + weekViewPath.currentItem.item.scrollToDate(scrollToDate); |
922 | + } else { |
923 | + weekViewPath.currentItem.item.scrollToBegin() |
924 | + } |
925 | } |
926 | |
927 | scrollToDate = null |
928 | @@ -194,7 +196,6 @@ |
929 | keyboardEventProvider: weekViewPath |
930 | selectedDay: weekViewPage.selectedDay |
931 | modelFilter: weekViewPage.model ? weekViewPage.model.filter : null |
932 | - autoUpdate: weekViewPage.tabSelected |
933 | |
934 | onDateSelected: { |
935 | weekViewPage.dateSelected(date); |
936 | @@ -240,6 +241,11 @@ |
937 | // make sure that the model is updated after create a new event if it is marked as auto-update false |
938 | Connections { |
939 | target: weekViewPage |
940 | + onActiveChanged: { |
941 | + if (weekViewPage.active) { |
942 | + timeLineView.update() |
943 | + } |
944 | + } |
945 | onEventSaved: { |
946 | timeLineView.update() |
947 | } |
948 | @@ -270,6 +276,13 @@ |
949 | } |
950 | } |
951 | } |
952 | + |
953 | + Binding { |
954 | + target: item |
955 | + property: "autoUpdate" |
956 | + value: (weekViewPage.tabSelected && weekViewPage.active && PathView.isCurrentItem) |
957 | + when: (timelineLoader.status === Loader.Ready) |
958 | + } |
959 | } |
960 | } |
961 | } |
962 | |
963 | === modified file 'calendar.qml' |
964 | --- calendar.qml 2016-04-28 13:44:33 +0000 |
965 | +++ calendar.qml 2016-07-21 21:44:34 +0000 |
966 | @@ -139,8 +139,6 @@ |
967 | PageStack { |
968 | id: pageStack |
969 | |
970 | - Component.onCompleted: push(tabs) |
971 | - |
972 | // This is for wait that the app is load when newEvent is invoked by argument |
973 | Timer { |
974 | id: timer |
975 | @@ -184,6 +182,7 @@ |
976 | |
977 | InvalidFilter { |
978 | id: invalidFilter |
979 | + objectName: "invalidFilter" |
980 | } |
981 | |
982 | IntersectionFilter { |
983 | @@ -197,33 +196,7 @@ |
984 | objectName: "calendarEventList" |
985 | |
986 | property bool isReady: false |
987 | - |
988 | - startPeriod: tabs.currentDay |
989 | - endPeriod: tabs.currentDay |
990 | - |
991 | - filter: invalidFilter |
992 | - |
993 | - onCollectionsChanged: { |
994 | - if (!isReady) |
995 | - return |
996 | - |
997 | - var collectionIds = enabledColections() |
998 | - var oldCollections = collectionFilter.ids |
999 | - var needsUpdate = false |
1000 | - if (collectionIds.length != oldCollections.length) { |
1001 | - needsUpdate = true |
1002 | - } else { |
1003 | - for(var i=oldCollections.length - 1; i >=0 ; i--) { |
1004 | - if (collectionIds.indexOf(oldCollections[i]) === -1) { |
1005 | - needsUpdate = true |
1006 | - break; |
1007 | - } |
1008 | - } |
1009 | - } |
1010 | - |
1011 | - if (needsUpdate) |
1012 | - collectionFilter.ids = collectionIds; |
1013 | - } |
1014 | + property alias collectionsToFilter: collectionFilter.ids |
1015 | |
1016 | function enabledColections() |
1017 | { |
1018 | @@ -271,6 +244,39 @@ |
1019 | requestId = eventModel.fetchItems(eventId); |
1020 | } |
1021 | |
1022 | + // force this model to never disable the auto-update |
1023 | + live: true |
1024 | + active: true |
1025 | + startPeriod: tabs.currentDay |
1026 | + endPeriod: tabs.currentDay |
1027 | + |
1028 | + filter: invalidFilter |
1029 | + |
1030 | + onCollectionsChanged: { |
1031 | + if (!isReady) { |
1032 | + return |
1033 | + } |
1034 | + |
1035 | + var collectionIds = enabledColections() |
1036 | + var oldCollections = collectionFilter.ids |
1037 | + var needsUpdate = false |
1038 | + if (collectionIds.length != oldCollections.length) { |
1039 | + needsUpdate = true |
1040 | + } else { |
1041 | + for(var i=oldCollections.length - 1; i >=0 ; i--) { |
1042 | + if (collectionIds.indexOf(oldCollections[i]) === -1) { |
1043 | + needsUpdate = true |
1044 | + break; |
1045 | + } |
1046 | + } |
1047 | + } |
1048 | + |
1049 | + if (needsUpdate) { |
1050 | + eventModel.collectionsToFilter = collectionIds |
1051 | + updateIfNecessary() |
1052 | + } |
1053 | + } |
1054 | + |
1055 | Component.onCompleted: { |
1056 | delayedApplyFilter(); |
1057 | |
1058 | @@ -292,12 +298,19 @@ |
1059 | property alias showWeekNumber: mainView.displayWeekNumber |
1060 | property alias showLunarCalendar: mainView.displayLunarCalendar |
1061 | property alias reminderDefaultValue: mainView.reminderDefaultValue |
1062 | + |
1063 | + function defaultViewIndexValue(fallback) { |
1064 | + return defaultViewIndex != -1 ? defaultViewIndex : fallback |
1065 | + } |
1066 | + |
1067 | } |
1068 | |
1069 | Tabs{ |
1070 | id: tabs |
1071 | Keys.forwardTo: [tabs.currentPage] |
1072 | |
1073 | + selectedTabIndex: -1 |
1074 | + |
1075 | property bool isReady: false |
1076 | property var currentDay: DateExt.today(); |
1077 | property var selectedDay; |
1078 | @@ -451,16 +464,17 @@ |
1079 | else { |
1080 | // Due to bug #1231558 {if (args.defaultArgument.at(0))} is always true |
1081 | // After the fix we can delete this else |
1082 | - tabs.selectedTabIndex = settings.defaultViewIndex; |
1083 | + tabs.selectedTabIndex = settings.defaultViewIndexValue(1) |
1084 | } |
1085 | } // End of if about args.values |
1086 | else { |
1087 | - tabs.selectedTabIndex = settings.defaultViewIndex; |
1088 | + tabs.selectedTabIndex = settings.defaultViewIndexValue(1) |
1089 | } |
1090 | tabs.starttime = -1 |
1091 | tabs.endtime = -1 |
1092 | tabs.eventId = "" |
1093 | tabs.isReady = true |
1094 | + pageStack.push(tabs) |
1095 | // WORKAROUND: Due the missing feature on SDK, they can not detect if |
1096 | // there is a mouse attached to device or not. And this will cause the |
1097 | // bootom edge component to not work correct on desktop. |
1098 | @@ -651,7 +665,7 @@ |
1099 | } |
1100 | |
1101 | reminderValue: mainView.reminderDefaultValue |
1102 | - model: eventModel.isReady ? eventModel : null |
1103 | + model: eventModel.isReady && eventModel.collectionsToFilter ? eventModel : null |
1104 | bootomEdgeEnabled: tabSelected |
1105 | displayLunarCalendar: mainView.displayLunarCalendar |
1106 | |
1107 | @@ -669,7 +683,7 @@ |
1108 | showDate(tabs.currentDay) |
1109 | } |
1110 | } |
1111 | - } |
1112 | + } |
1113 | } |
1114 | |
1115 | Component { |
1116 | @@ -691,7 +705,7 @@ |
1117 | } |
1118 | |
1119 | reminderValue: mainView.reminderDefaultValue |
1120 | - model: eventModel.isReady ? eventModel : null |
1121 | + model: eventModel.isReady && eventModel.collectionsToFilter ? eventModel : null |
1122 | bootomEdgeEnabled: tabSelected |
1123 | displayLunarCalendar: mainView.displayLunarCalendar |
1124 | |
1125 | @@ -742,7 +756,7 @@ |
1126 | } |
1127 | |
1128 | reminderValue: mainView.reminderDefaultValue |
1129 | - model: eventModel.isReady ? eventModel : null |
1130 | + model: eventModel.isReady && eventModel.collectionsToFilter ? eventModel : null |
1131 | bootomEdgeEnabled: tabSelected |
1132 | displayLunarCalendar: mainView.displayLunarCalendar |
1133 | |
1134 | @@ -773,7 +787,7 @@ |
1135 | readonly property bool tabSelected: tabs.selectedTab === agendaTab |
1136 | |
1137 | reminderValue: mainView.reminderDefaultValue |
1138 | - model: eventModel.isReady ? eventModel : null |
1139 | + model: eventModel.isReady && eventModel.collectionsToFilter ? eventModel : null |
1140 | bootomEdgeEnabled: tabs.selectedTabIndex === agendaTab.index |
1141 | |
1142 | onDateSelected: { |
1143 | |
1144 | === modified file 'calendar_canvas_worker.js' |
1145 | --- calendar_canvas_worker.js 2016-03-02 13:47:59 +0000 |
1146 | +++ calendar_canvas_worker.js 2016-07-21 21:44:34 +0000 |
1147 | @@ -81,7 +81,7 @@ |
1148 | var lines = [] |
1149 | |
1150 | while (events.length > 0) { |
1151 | - var aux = {"startTime": 0, "ednTime": 0} |
1152 | + var aux = {"startTime": 0, "endTime": 0} |
1153 | var eventA = events[0] |
1154 | events.splice(0, 1) |
1155 | var line = [eventA] |
1156 | |
1157 | === modified file 'tests/unittests/tst_event_list_model.qml' |
1158 | --- tests/unittests/tst_event_list_model.qml 2016-04-26 19:42:33 +0000 |
1159 | +++ tests/unittests/tst_event_list_model.qml 2016-07-21 21:44:34 +0000 |
1160 | @@ -10,16 +10,23 @@ |
1161 | id: root |
1162 | name: "Event List Model tests" |
1163 | |
1164 | + QtObject { |
1165 | + id: mainView |
1166 | + property bool syncInProgress: false |
1167 | + } |
1168 | + |
1169 | Component { |
1170 | id: modelComp |
1171 | |
1172 | EventListModel { |
1173 | id: eventModel |
1174 | |
1175 | + active: true |
1176 | manager: "memory" |
1177 | startPeriod: new Date(2016, 7, 1, 0, 0, 0, 0) |
1178 | endPeriod: new Date(2016, 8, 1, 0, 0, 0, 0) |
1179 | autoUpdate: true |
1180 | + filter: null |
1181 | } |
1182 | } |
1183 | |
1184 | @@ -51,14 +58,13 @@ |
1185 | function create_events(data) |
1186 | { |
1187 | var model = modelComp.createObject(root, {}); |
1188 | - var spy = spyComp.createObject(root, {'target': model}) |
1189 | |
1190 | for(var i=0; i < data.length; i++) { |
1191 | var ev = create_event_from_data(model, data[i]) |
1192 | model.saveItem(ev) |
1193 | - tryCompare(spy, 'count', i+1) |
1194 | } |
1195 | - compare(model.itemCount, data.length) |
1196 | + model.updateIfNecessary() |
1197 | + tryCompare(model, 'itemCount', data.length) |
1198 | return model |
1199 | } |
1200 |
PASSED: Continuous integration, rev:854 /core-apps- jenkins. ubuntu. com/job/ calendar- app-ci/ 854/ /core-apps- jenkins. ubuntu. com/job/ generic- update- mp/918/ console
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild: /core-apps- jenkins. ubuntu. com/job/ calendar- app-ci/ 854/rebuild
https:/