Merge lp:~renatofilho/qtorganizer5-eds/tz-support into lp:qtorganizer5-eds

Proposed by Renato Araujo Oliveira Filho
Status: Merged
Approved by: Michael Sheldon
Approved revision: 48
Merged at revision: 45
Proposed branch: lp:~renatofilho/qtorganizer5-eds/tz-support
Merge into: lp:qtorganizer5-eds
Diff against target: 305 lines (+109/-35)
4 files modified
qorganizer/qorganizer-eds-engine.cpp (+55/-24)
qorganizer/qorganizer-eds-engine.h (+2/-1)
tests/unittest/event-test.cpp (+40/-0)
tests/unittest/recurrence-test.cpp (+12/-10)
To merge this branch: bzr merge lp:~renatofilho/qtorganizer5-eds/tz-support
Reviewer Review Type Date Requested Status
Michael Sheldon (community) Approve
PS Jenkins bot continuous-integration Approve
Review via email: mp+213714@code.launchpad.net

Commit message

Initial implementation of time zone support.

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
46. By Renato Araujo Oliveira Filho

Fixed tzid set when time zone is null.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
47. By Renato Araujo Oliveira Filho

Fixed datetime conversion when using timezones.

Revision history for this message
Alan Pope 🍺🐧🐱 πŸ¦„ (popey) wrote :

Tested this on my desktop which has multiple calendars synced (personal and work) and all events (created by people in different timezones) appeared in the right place.

Revision history for this message
Renato Araujo Oliveira Filho (renatofilho) wrote :

Are there any related MPs required for this MP to build/function as expected? NO

Is your branch in sync with latest trunk (e.g. bzr pull lp:trunk -> no changes): YES

Did you perform an exploratory manual test run of your code change and any related functionality on device or emulator? YES

Did you successfully run all tests found in your component's Test Plan (https://wiki.ubuntu.com/Process/Merges/TestPlan/qtorganizer5-eds) on device or emulator? YES

If you changed the UI, was the change specified/approved by design? NO UI CHANGE

If you changed the packaging (debian), did you subscribe a core-dev to this MP? NO PACKAGE CHANGE

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
48. By Renato Araujo Oliveira Filho

Fixed failing test when running on devices with different time zone.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Michael Sheldon (michael-sheldon) wrote :

Did you perform an exploratory manual test run of the code change and any related functionality on device or emulator?

 * Yes, synced events now display with correct timezone

Did CI run pass? If not, please explain why.

 * Yes

Have you checked that submitter has accurately filled out the submitter checklist and has taken no shortcut?

 * Yes

review: Approve
49. By Renato Araujo Oliveira Filho

Fixed timezone name parse.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'qorganizer/qorganizer-eds-engine.cpp'
2--- qorganizer/qorganizer-eds-engine.cpp 2014-03-06 21:31:03 +0000
3+++ qorganizer/qorganizer-eds-engine.cpp 2014-04-03 21:15:35 +0000
4@@ -34,9 +34,8 @@
5
6 #include <QtCore/qdebug.h>
7 #include <QtCore/QPointer>
8-#include <QtCore/qstringbuilder.h>
9-#include <QtCore/quuid.h>
10 #include <QtCore/QCoreApplication>
11+#include <QtCore/QTimeZone>
12
13 #include <QtOrganizer/QOrganizerEventAttendee>
14 #include <QtOrganizer/QOrganizerItemLocation>
15@@ -1094,10 +1093,37 @@
16 change->emitSignals(this);
17 }
18
19-QDateTime QOrganizerEDSEngine::fromIcalTime(struct icaltimetype value)
20-{
21- uint tmTime = icaltime_as_timet(value);
22- return QDateTime::fromTime_t(tmTime);
23+QDateTime QOrganizerEDSEngine::fromIcalTime(struct icaltimetype value, const char *tzId)
24+{
25+ uint tmTime;
26+
27+ if (tzId) {
28+ QByteArray tzName(tzId);
29+ // keep only the timezone name.
30+ tzName = tzName.replace("/freeassociation.sourceforge.net/Tzfile/", "");
31+ const icaltimezone *timezone = const_cast<const icaltimezone *>(icaltimezone_get_builtin_timezone(tzName.constData()));
32+ tmTime = icaltime_as_timet_with_zone(value, timezone);
33+ return QDateTime::fromTime_t(tmTime, QTimeZone(tzId));
34+ } else {
35+ tmTime = icaltime_as_timet(value);
36+ return QDateTime::fromTime_t(tmTime);
37+ }
38+}
39+
40+icaltimetype QOrganizerEDSEngine::fromQDateTime(const QDateTime &dateTime,
41+ bool allDay,
42+ QByteArray *tzId)
43+{
44+
45+ if (dateTime.timeSpec() == Qt::TimeZone) {
46+ const icaltimezone *timezone = 0;
47+ *tzId = dateTime.timeZone().id();
48+ timezone = const_cast<const icaltimezone *>(icaltimezone_get_builtin_timezone(tzId->constData()));
49+ return icaltime_from_timet_with_zone(dateTime.toTime_t(), allDay, timezone);
50+ } else {
51+ return icaltime_from_timet(dateTime.toTime_t(), allDay);
52+ }
53+
54 }
55
56 void QOrganizerEDSEngine::parseStartTime(ECalComponent *comp, QOrganizerItem *item)
57@@ -1106,7 +1132,7 @@
58 e_cal_component_get_dtstart(comp, dt);
59 if (dt->value) {
60 QOrganizerEventTime etr = item->detail(QOrganizerItemDetail::TypeEventTime);
61- etr.setStartDateTime(fromIcalTime(*dt->value));
62+ etr.setStartDateTime(fromIcalTime(*dt->value, dt->tzid));
63 if (icaltime_is_date(*dt->value) != etr.isAllDay()) {
64 etr.setAllDay(icaltime_is_date(*dt->value));
65 }
66@@ -1121,7 +1147,7 @@
67 e_cal_component_get_dtstart(comp, dt);
68 if (dt->value) {
69 QOrganizerTodoTime etr = item->detail(QOrganizerItemDetail::TypeTodoTime);
70- etr.setStartDateTime(fromIcalTime(*dt->value));
71+ etr.setStartDateTime(fromIcalTime(*dt->value, dt->tzid));
72 if (icaltime_is_date(*dt->value) != etr.isAllDay()) {
73 etr.setAllDay(icaltime_is_date(*dt->value));
74 }
75@@ -1136,7 +1162,7 @@
76 e_cal_component_get_dtend(comp, dt);
77 if (dt->value) {
78 QOrganizerEventTime etr = item->detail(QOrganizerItemDetail::TypeEventTime);
79- etr.setEndDateTime(fromIcalTime(*dt->value));
80+ etr.setEndDateTime(fromIcalTime(*dt->value, dt->tzid));
81 if (icaltime_is_date(*dt->value) != etr.isAllDay()) {
82 etr.setAllDay(icaltime_is_date(*dt->value));
83 }
84@@ -1217,7 +1243,7 @@
85 e_cal_component_get_rdate_list(comp, &periodList);
86 for(GSList *i = periodList; i != 0; i = i->next) {
87 ECalComponentPeriod *period = (ECalComponentPeriod*) i->data;
88- QDateTime dt = fromIcalTime(period->start);
89+ QDateTime dt = fromIcalTime(period->start, 0);
90 dates.insert(dt.date());
91 //TODO: period.end, period.duration
92 }
93@@ -1235,7 +1261,7 @@
94 e_cal_component_get_exdate_list(comp, &exdateList);
95 for(GSList *i = exdateList; i != 0; i = i->next) {
96 ECalComponentDateTime* dateTime = (ECalComponentDateTime*) i->data;
97- QDateTime dt = fromIcalTime(*dateTime->value);
98+ QDateTime dt = fromIcalTime(*dateTime->value, dateTime->tzid);
99 dates.insert(dt.date());
100 }
101 e_cal_component_free_exdate_list(exdateList);
102@@ -1280,7 +1306,7 @@
103 if (rule->count > 0) {
104 qRule.setLimit(rule->count);
105 } else {
106- QDateTime dt = fromIcalTime(rule->until);
107+ QDateTime dt = fromIcalTime(rule->until, 0);
108 if (dt.isValid()) {
109 qRule.setLimit(dt.date());
110 } else {
111@@ -1346,7 +1372,7 @@
112 e_cal_component_get_due(comp, &due);
113 if (due.value) {
114 QOrganizerTodoTime ttr = item->detail(QOrganizerItemDetail::TypeTodoTime);
115- ttr.setDueDateTime(fromIcalTime(*due.value));
116+ ttr.setDueDateTime(fromIcalTime(*due.value, due.tzid));
117 if (icaltime_is_date(*due.value) != ttr.isAllDay()) {
118 ttr.setAllDay(icaltime_is_date(*due.value));
119 }
120@@ -1488,7 +1514,7 @@
121 e_cal_component_get_dtstart(comp, &dt);
122 if (dt.value) {
123 QOrganizerJournalTime jtime;
124- jtime.setEntryDateTime(fromIcalTime(*dt.value));
125+ jtime.setEntryDateTime(fromIcalTime(*dt.value, dt.tzid));
126 journal->saveDetail(&jtime);
127 }
128 e_cal_component_free_datetime(&dt);
129@@ -1692,9 +1718,10 @@
130 {
131 QOrganizerEventTime etr = item.detail(QOrganizerItemDetail::TypeEventTime);
132 if (!etr.isEmpty()) {
133- struct icaltimetype ict = icaltime_from_timet(etr.startDateTime().toTime_t(), etr.isAllDay());
134+ QByteArray tzId;
135+ struct icaltimetype ict = fromQDateTime(etr.startDateTime(), etr.isAllDay(), &tzId);
136 ECalComponentDateTime dt;
137- dt.tzid = NULL;
138+ dt.tzid = tzId.isEmpty() ? NULL : tzId.constData();
139 dt.value = &ict;
140 e_cal_component_set_dtstart(comp, &dt);
141 }
142@@ -1704,9 +1731,10 @@
143 {
144 QOrganizerEventTime etr = item.detail(QOrganizerItemDetail::TypeEventTime);
145 if (!etr.isEmpty()) {
146- struct icaltimetype ict = icaltime_from_timet(etr.endDateTime().toTime_t(), etr.isAllDay());
147+ QByteArray tzId;
148+ struct icaltimetype ict = fromQDateTime(etr.endDateTime(), etr.isAllDay(), &tzId);
149 ECalComponentDateTime dt;
150- dt.tzid = NULL;
151+ dt.tzid = tzId.isEmpty() ? NULL : tzId.constData();
152 dt.value = &ict;
153 e_cal_component_set_dtend(comp, &dt);
154 }
155@@ -1716,9 +1744,10 @@
156 {
157 QOrganizerTodoTime etr = item.detail(QOrganizerItemDetail::TypeTodoTime);
158 if (!etr.isEmpty()) {
159- struct icaltimetype ict = icaltime_from_timet(etr.startDateTime().toTime_t(), etr.isAllDay());
160+ QByteArray tzId;
161+ struct icaltimetype ict = fromQDateTime(etr.startDateTime(), etr.isAllDay(), &tzId);
162 ECalComponentDateTime dt;
163- dt.tzid = NULL;
164+ dt.tzid = tzId.isEmpty() ? NULL : tzId.constData();
165 dt.value = &ict;
166 e_cal_component_set_dtstart(comp, &dt);;
167 }
168@@ -1888,9 +1917,10 @@
169 {
170 QOrganizerTodoTime ttr = item.detail(QOrganizerItemDetail::TypeTodoTime);
171 if (!ttr.isEmpty()) {
172- struct icaltimetype ict = icaltime_from_timet(ttr.dueDateTime().toTime_t(), ttr.isAllDay());
173+ QByteArray tzId;
174+ struct icaltimetype ict = fromQDateTime(ttr.dueDateTime(), ttr.isAllDay(), &tzId);
175 ECalComponentDateTime dt;
176- dt.tzid = NULL;
177+ dt.tzid = tzId.isEmpty() ? NULL : tzId.constData();
178 dt.value = &ict;
179 e_cal_component_set_due(comp, &dt);;
180 }
181@@ -2065,9 +2095,10 @@
182
183 QOrganizerJournalTime jtime = item.detail(QOrganizerItemDetail::TypeJournalTime);
184 if (!jtime.isEmpty()) {
185- struct icaltimetype ict = icaltime_from_timet(jtime.entryDateTime().toTime_t(), FALSE);
186+ QByteArray tzId;
187+ struct icaltimetype ict = fromQDateTime(jtime.entryDateTime(), false, &tzId);
188 ECalComponentDateTime dt;
189- dt.tzid = NULL;
190+ dt.tzid = tzId.isEmpty() ? NULL : tzId.constData();
191 dt.value = &ict;
192 e_cal_component_set_dtstart(comp, &dt);
193 }
194
195=== modified file 'qorganizer/qorganizer-eds-engine.h'
196--- qorganizer/qorganizer-eds-engine.h 2014-02-25 17:12:32 +0000
197+++ qorganizer/qorganizer-eds-engine.h 2014-04-03 21:15:35 +0000
198@@ -190,7 +190,8 @@
199 static void parseStatus(ECalComponent *comp, QtOrganizer::QOrganizerItem *item);
200 static void parseAttendeeList(ECalComponent *comp, QtOrganizer::QOrganizerItem *item);
201
202- static QDateTime fromIcalTime(struct icaltimetype value);
203+ static QDateTime fromIcalTime(struct icaltimetype value, const char *tzId);
204+ static icaltimetype fromQDateTime(const QDateTime &dateTime, bool allDay, QByteArray *tzId);
205
206 static QtOrganizer::QOrganizerItem *parseEvent(ECalComponent *comp);
207 static QtOrganizer::QOrganizerItem *parseToDo(ECalComponent *comp);
208
209=== modified file 'tests/unittest/event-test.cpp'
210--- tests/unittest/event-test.cpp 2014-02-28 16:05:35 +0000
211+++ tests/unittest/event-test.cpp 2014-04-03 21:15:35 +0000
212@@ -512,6 +512,46 @@
213 QOrganizerTodo newTodo = static_cast<QOrganizerTodo>(items[0]);
214 QCOMPARE(newTodo.startDateTime(), startDateTime);
215 }
216+
217+ void testCreateWithDiffTimeZone()
218+ {
219+ static QString displayLabelValue = QStringLiteral("Event with diff timezone");
220+ static QString descriptionValue = QStringLiteral("Event with diff timezone description");
221+ static QDateTime startDateTime = QDateTime(QDate(2013, 9, 3), QTime(0, 30, 0), QTimeZone("Asia/Bangkok"));
222+
223+ // create a new item
224+ QOrganizerTodo todo;
225+ todo.setCollectionId(m_collection.id());
226+ todo.setStartDateTime(startDateTime);
227+ todo.setDisplayLabel(displayLabelValue);
228+ todo.setDescription(descriptionValue);
229+
230+ QtOrganizer::QOrganizerManager::Error error;
231+ QMap<int, QtOrganizer::QOrganizerManager::Error> errorMap;
232+ QList<QOrganizerItem> items;
233+ items << todo;
234+ bool saveResult = m_engine->saveItems(&items,
235+ QList<QtOrganizer::QOrganizerItemDetail::DetailType>(),
236+ &errorMap,
237+ &error);
238+ QVERIFY(saveResult);
239+ QCOMPARE(error, QOrganizerManager::NoError);
240+ QVERIFY(errorMap.isEmpty());
241+
242+ // query by the new item
243+ QOrganizerItemFetchHint hint;
244+ QList<QOrganizerItemId> ids;
245+ ids << items[0].id();
246+ items = m_engine->items(ids, hint, &errorMap, &error);
247+ QCOMPARE(items.count(), 1);
248+
249+ // compare start datetime
250+ QOrganizerTodo newTodo = static_cast<QOrganizerTodo>(items[0]);
251+ QDateTime newStartDateTime = newTodo.startDateTime();
252+ QCOMPARE(newStartDateTime.timeSpec(), Qt::TimeZone);
253+ QCOMPARE(newStartDateTime.timeZone(), QTimeZone("Asia/Bangkok"));
254+ QCOMPARE(newTodo.startDateTime(), startDateTime);
255+ }
256 };
257
258 const QString EventTest::defaultCollectionName = QStringLiteral("TEST_EVENT_COLLECTION");
259
260=== modified file 'tests/unittest/recurrence-test.cpp'
261--- tests/unittest/recurrence-test.cpp 2014-03-06 21:31:03 +0000
262+++ tests/unittest/recurrence-test.cpp 2014-04-03 21:15:35 +0000
263@@ -160,11 +160,13 @@
264 {
265 static QString displayLabelValue = QStringLiteral("Monthly test");
266 static QString descriptionValue = QStringLiteral("Monthly description");
267+ static QDateTime eventStartDate = QDateTime(QDate(2013, 1, 1), QTime(0, 0, 0), Qt::UTC);
268+ static QDateTime eventEndDate = QDateTime(QDate(2013, 1, 1), QTime(0, 30, 0), Qt::UTC);
269
270 QOrganizerEvent ev;
271 ev.setCollectionId(m_collection.id());
272- ev.setStartDateTime(QDateTime(QDate(2013, 1, 1), QTime(0,0,0)));
273- ev.setEndDateTime(QDateTime(QDate(2013, 1, 1), QTime(0,30,0)));
274+ ev.setStartDateTime(eventStartDate);
275+ ev.setEndDateTime(eventEndDate);
276 ev.setDisplayLabel(displayLabelValue);
277 ev.setDescription(descriptionValue);
278
279@@ -192,19 +194,19 @@
280 QOrganizerItemFetchHint hint;
281 QOrganizerItemFilter filter;
282 items = m_engine->items(filter,
283- QDateTime(QDate(2013, 1, 1), QTime(0,0,0)),
284- QDateTime(QDate(2014, 1, 1), QTime(0,0,0)),
285- 100,
286- sort,
287- hint,
288- &error);
289+ eventStartDate,
290+ eventStartDate.addYears(1),
291+ 100,
292+ sort,
293+ hint,
294+ &error);
295 QCOMPARE(items.count(), 24);
296 for(int i=0; i < 12; i++) {
297 QOrganizerEventTime time = items[i*2].detail(QOrganizerItemDetail::TypeEventTime);
298- QCOMPARE(time.startDateTime(), QDateTime(QDate(2013, i+1, 1), QTime(0,0,0)));
299+ QCOMPARE(time.startDateTime(), eventStartDate.addMonths(i));
300
301 time = items[(i*2)+1].detail(QOrganizerItemDetail::TypeEventTime);
302- QCOMPARE(time.startDateTime(), QDateTime(QDate(2013, i+1, 5), QTime(0,0,0)));
303+ QCOMPARE(time.startDateTime(), QDateTime(QDate(2013, i+1, 5), QTime(0,0,0), Qt::UTC));
304 }
305 }
306

Subscribers

People subscribed via source and target branches