Merge lp:~renatofilho/qtorganizer5-eds/calendar-with-account-id into lp:qtorganizer5-eds

Proposed by Renato Araujo Oliveira Filho
Status: Merged
Approved by: Bill Filler
Approved revision: 117
Merged at revision: 106
Proposed branch: lp:~renatofilho/qtorganizer5-eds/calendar-with-account-id
Merge into: lp:qtorganizer5-eds
Diff against target: 999 lines (+394/-90)
20 files modified
CMakeLists.txt (+1/-0)
debian/control (+2/-1)
organizer/CMakeLists.txt (+3/-0)
organizer/qorganizer-eds-engine.cpp (+67/-20)
organizer/qorganizer-eds-enginedata.cpp (+1/-1)
organizer/qorganizer-eds-fetchrequestdata.cpp (+3/-0)
organizer/qorganizer-eds-parseeventthread.cpp (+12/-0)
organizer/qorganizer-eds-parseeventthread.h (+2/-0)
organizer/qorganizer-eds-requestdata.h (+5/-1)
organizer/qorganizer-eds-savecollectionrequestdata.cpp (+20/-14)
organizer/qorganizer-eds-source-registry.cpp (+38/-0)
organizer/qorganizer-eds-source-registry.h (+4/-0)
organizer/qorganizer-eds-viewwatcher.cpp (+25/-13)
organizer/qorganizer-eds-viewwatcher.h (+8/-0)
tests/unittest/CMakeLists.txt (+1/-0)
tests/unittest/collections-test.cpp (+113/-0)
tests/unittest/eds-base-test.cpp (+19/-19)
tests/unittest/eds-base-test.h (+2/-0)
tests/unittest/gscopedpointer.h (+43/-0)
tests/unittest/parseecal-test.cpp (+25/-21)
To merge this branch: bzr merge lp:~renatofilho/qtorganizer5-eds/calendar-with-account-id
Reviewer Review Type Date Requested Status
system-apps-ci-bot continuous-integration Needs Fixing
PS Jenkins bot continuous-integration Approve
Ubuntu Phablet Team Pending
Review via email: mp+294981@code.launchpad.net

Commit message

Create a "collection-account-id" meta data property to store the account id which the source is linked.

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

Does not use source name as part of collection id.

103. By Renato Araujo Oliveira Filho

Use ubuntu eds extensions for calendar sources.

104. By Renato Araujo Oliveira Filho

Add "evolution-data-server-ubuntu-dev" as build dep.

105. By Renato Araujo Oliveira Filho

Print a warning message if it fails to create ubuntu extension.

106. By Renato Araujo Oliveira Filho

Implemented support for extra medata in the collections.

Will be used by syncMonitor to store sync url.

107. By Renato Araujo Oliveira Filho

Fixed sync writable property.

108. By Renato Araujo Oliveira Filho

check if the source has a ubuntu extension.

109. By Renato Araujo Oliveira Filho

Make a copy of calendar items on parse thread to avoid it to be destroyed outside of the thread.

110. By Renato Araujo Oliveira Filho

Trunk merged.

111. By Renato Araujo Oliveira Filho

Print warning message on trigger parse only once.

112. By Renato Araujo Oliveira Filho

Avoid crash during the engine destruction.

113. By Renato Araujo Oliveira Filho

Avoid crash if request is cancelled during the query.

Revision history for this message
system-apps-ci-bot (system-apps-ci-bot) wrote :

FAILED: Continuous integration, rev:113
https://jenkins.canonical.com/system-apps/job/lp-qtorganizer5-eds-ci/1/
Executed test runs:
    FAILURE: https://jenkins.canonical.com/system-apps/job/build/687/console
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-0-fetch/687
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-1-sourcepkg/release=vivid+overlay/645
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-1-sourcepkg/release=xenial+overlay/645
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-1-sourcepkg/release=yakkety/645
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=vivid+overlay/639/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=xenial+overlay/639/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=yakkety/639/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=vivid+overlay/639/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=xenial+overlay/639/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=yakkety/639/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=vivid+overlay/639/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=xenial+overlay/639/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=yakkety/639/console

Click here to trigger a rebuild:
https://jenkins.canonical.com/system-apps/job/lp-qtorganizer5-eds-ci/1/rebuild

review: Needs Fixing (continuous-integration)
114. By Renato Araujo Oliveira Filho

Emit 'collectionsModified' when necessary.

Revision history for this message
system-apps-ci-bot (system-apps-ci-bot) wrote :

FAILED: Continuous integration, rev:114
https://jenkins.canonical.com/system-apps/job/lp-qtorganizer5-eds-ci/4/
Executed test runs:
    FAILURE: https://jenkins.canonical.com/system-apps/job/build/823/console
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-0-fetch/823
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-1-sourcepkg/release=vivid+overlay/758
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-1-sourcepkg/release=xenial+overlay/758
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-1-sourcepkg/release=yakkety/758
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=vivid+overlay/760/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=xenial+overlay/760/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=yakkety/760/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=vivid+overlay/760/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=xenial+overlay/760/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=yakkety/760/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=vivid+overlay/760/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=xenial+overlay/760/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=yakkety/760/console

Click here to trigger a rebuild:
https://jenkins.canonical.com/system-apps/job/lp-qtorganizer5-eds-ci/4/rebuild

review: Needs Fixing (continuous-integration)
115. By Renato Araujo Oliveira Filho

Use a batch operation to send event changes signal.

Revision history for this message
system-apps-ci-bot (system-apps-ci-bot) wrote :

FAILED: Continuous integration, rev:115
https://jenkins.canonical.com/system-apps/job/lp-qtorganizer5-eds-ci/5/
Executed test runs:
    FAILURE: https://jenkins.canonical.com/system-apps/job/build/862/console
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-0-fetch/862
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-1-sourcepkg/release=vivid+overlay/782
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-1-sourcepkg/release=xenial+overlay/782
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-1-sourcepkg/release=yakkety/782
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=vivid+overlay/784/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=xenial+overlay/784/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=yakkety/784/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=vivid+overlay/784/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=xenial+overlay/784/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=yakkety/784/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=vivid+overlay/784/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=xenial+overlay/784/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=yakkety/784/console

Click here to trigger a rebuild:
https://jenkins.canonical.com/system-apps/job/lp-qtorganizer5-eds-ci/5/rebuild

review: Needs Fixing (continuous-integration)
116. By Renato Araujo Oliveira Filho

Fixed memory leaks.

Revision history for this message
system-apps-ci-bot (system-apps-ci-bot) wrote :

FAILED: Continuous integration, rev:116
https://jenkins.canonical.com/system-apps/job/lp-qtorganizer5-eds-ci/6/
Executed test runs:
    FAILURE: https://jenkins.canonical.com/system-apps/job/build/864/console
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-0-fetch/864
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-1-sourcepkg/release=vivid+overlay/784
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-1-sourcepkg/release=xenial+overlay/784
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-1-sourcepkg/release=yakkety/784
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=vivid+overlay/786/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=xenial+overlay/786/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=yakkety/786/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=vivid+overlay/786/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=xenial+overlay/786/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=yakkety/786/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=vivid+overlay/786/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=xenial+overlay/786/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=yakkety/786/console

Click here to trigger a rebuild:
https://jenkins.canonical.com/system-apps/job/lp-qtorganizer5-eds-ci/6/rebuild

review: Needs Fixing (continuous-integration)
117. By Renato Araujo Oliveira Filho

Trunk merged.

Revision history for this message
system-apps-ci-bot (system-apps-ci-bot) wrote :

FAILED: Continuous integration, rev:117
https://jenkins.canonical.com/system-apps/job/lp-qtorganizer5-eds-ci/7/
Executed test runs:
    FAILURE: https://jenkins.canonical.com/system-apps/job/build/932/console
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-0-fetch/932
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-1-sourcepkg/release=vivid+overlay/839
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-1-sourcepkg/release=xenial+overlay/839
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-1-sourcepkg/release=yakkety/839
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=vivid+overlay/836/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=xenial+overlay/836/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=yakkety/836/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=vivid+overlay/836/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=xenial+overlay/836/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=yakkety/836/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=vivid+overlay/836/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=xenial+overlay/836/console
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=yakkety/836/console

Click here to trigger a rebuild:
https://jenkins.canonical.com/system-apps/job/lp-qtorganizer5-eds-ci/7/rebuild

review: Needs Fixing (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'CMakeLists.txt'
2--- CMakeLists.txt 2016-01-11 21:15:32 +0000
3+++ CMakeLists.txt 2016-07-11 14:47:56 +0000
4@@ -15,6 +15,7 @@
5 pkg_check_modules(GIO REQUIRED gio-2.0>=2.32)
6 pkg_check_modules(EDATASERVER REQUIRED libedataserver-1.2>=3.8)
7 pkg_check_modules(ECAL REQUIRED REQUIRED libecal-1.2>=3.8)
8+pkg_check_modules(UEDS REQUIRED REQUIRED evolution-data-server-ubuntu)
9
10 set(CMAKE_INCLUDE_CURRENT_DIR ON)
11 set(CMAKE_AUTOMOC ON)
12
13=== modified file 'debian/control'
14--- debian/control 2015-07-23 13:48:21 +0000
15+++ debian/control 2016-07-11 14:47:56 +0000
16@@ -12,7 +12,8 @@
17 qtpim5-dev,
18 evolution-data-server,
19 dbus-test-runner,
20- gvfs-daemons
21+ gvfs-daemons,
22+ evolution-data-server-ubuntu-dev
23 Standards-Version: 3.9.4
24 Homepage: https://launchpad.net/qtorganizer5-eds
25 # If you aren't a member of ~phablet-team but need to upload packaging changes,
26
27=== modified file 'organizer/CMakeLists.txt'
28--- organizer/CMakeLists.txt 2016-01-11 20:54:42 +0000
29+++ organizer/CMakeLists.txt 2016-07-11 14:47:56 +0000
30@@ -56,12 +56,14 @@
31 ${GIO_INCLUDE_DIRS}
32 ${ECAL_INCLUDE_DIRS}
33 ${EDATASERVER_INCLUDE_DIRS}
34+ ${UEDS_INCLIDE_DIRS}
35 )
36
37 target_link_libraries(${QORGANIZER_BACKEND}-lib
38 ${GLIB_LIBRARIES}
39 ${ECAL_LIBRARIES}
40 ${EDATASERVER_LIBRARIES}
41+ ${UEDS_LIBRARIES}
42 )
43
44 target_link_libraries(${QORGANIZER_BACKEND}
45@@ -69,6 +71,7 @@
46 ${GLIB_LIBRARIES}
47 ${ECAL_LIBRARIES}
48 ${EDATASERVER_LIBRARIES}
49+ ${UEDS_LIBRARIES}
50 )
51
52 qt5_use_modules(${QORGANIZER_BACKEND}-lib Core Organizer)
53
54=== modified file 'organizer/qorganizer-eds-engine.cpp'
55--- organizer/qorganizer-eds-engine.cpp 2016-05-05 22:13:05 +0000
56+++ organizer/qorganizer-eds-engine.cpp 2016-07-11 14:47:56 +0000
57@@ -271,10 +271,12 @@
58 // check if request was destroyed by the caller
59 if (data->isLive()) {
60 QOrganizerItemFetchRequest *req = data->request<QOrganizerItemFetchRequest>();
61- data->appendResults(data->parent()->parseEvents(data->collection(),
62- events,
63- false,
64- req->fetchHint().detailTypesHint()));
65+ if (req) {
66+ data->appendResults(data->parent()->parseEvents(data->collection(),
67+ events,
68+ false,
69+ req->fetchHint().detailTypesHint()));
70+ }
71 itemsAsyncStart(data);
72 } else {
73 releaseRequestData(data);
74@@ -814,6 +816,7 @@
75 QOrganizerCollectionId collection = data->next();
76 for(; !collection.isNull(); collection = data->next()) {
77 EClient *client = data->parent()->d->m_sourceRegistry->client(collection.toString());
78+ Q_ASSERT(client);
79 data->setClient(client);
80 g_object_unref(client);
81 GSList *ids = data->compIds();
82@@ -1270,18 +1273,35 @@
83 void QOrganizerEDSEngine::onSourceAdded(const QString &collectionId)
84 {
85 d->watch(collectionId);
86- Q_EMIT collectionsAdded(QList<QOrganizerCollectionId>() << QOrganizerCollectionId::fromString(collectionId));
87+ QOrganizerCollectionId id = QOrganizerCollectionId::fromString(collectionId);
88+
89+ Q_EMIT collectionsAdded(QList<QOrganizerCollectionId>() << id);
90+
91+ QList<QPair<QOrganizerCollectionId, QOrganizerManager::Operation> > ops;
92+ ops << qMakePair(id, QOrganizerManager::Add);
93+ Q_EMIT collectionsModified(ops);
94 }
95
96 void QOrganizerEDSEngine::onSourceRemoved(const QString &collectionId)
97 {
98 d->unWatch(collectionId);
99- Q_EMIT collectionsRemoved(QList<QOrganizerCollectionId>() << QOrganizerCollectionId::fromString(collectionId));
100+ QOrganizerCollectionId id = QOrganizerCollectionId::fromString(collectionId);
101+
102+ Q_EMIT collectionsRemoved(QList<QOrganizerCollectionId>() << id);
103+
104+ QList<QPair<QOrganizerCollectionId, QOrganizerManager::Operation> > ops;
105+ ops << qMakePair(id, QOrganizerManager::Remove);
106+ Q_EMIT collectionsModified(ops);
107 }
108
109 void QOrganizerEDSEngine::onSourceUpdated(const QString &collectionId)
110 {
111- Q_EMIT collectionsChanged(QList<QOrganizerCollectionId>() << QOrganizerCollectionId::fromString(collectionId));
112+ QOrganizerCollectionId id = QOrganizerCollectionId::fromString(collectionId);
113+ Q_EMIT collectionsChanged(QList<QOrganizerCollectionId>() << id);
114+
115+ QList<QPair<QOrganizerCollectionId, QOrganizerManager::Operation> > ops;
116+ ops << qMakePair(id, QOrganizerManager::Change);
117+ Q_EMIT collectionsModified(ops);
118 }
119
120 void QOrganizerEDSEngine::onViewChanged(QOrganizerItemChangeSet *change)
121@@ -1383,6 +1403,7 @@
122 item->saveDetail(&etr);
123 }
124 e_cal_component_free_datetime(dt);
125+ g_free(dt);
126 }
127
128 void QOrganizerEDSEngine::parseTodoStartTime(ECalComponent *comp, QOrganizerItem *item)
129@@ -1398,6 +1419,7 @@
130 item->saveDetail(&etr);
131 }
132 e_cal_component_free_datetime(dt);
133+ g_free(dt);
134 }
135
136 void QOrganizerEDSEngine::parseEndTime(ECalComponent *comp, QOrganizerItem *item)
137@@ -1413,6 +1435,7 @@
138 item->saveDetail(&etr);
139 }
140 e_cal_component_free_datetime(dt);
141+ g_free(dt);
142 }
143
144 void QOrganizerEDSEngine::parseWeekRecurrence(struct icalrecurrencetype *rule, QtOrganizer::QOrganizerRecurrenceRule *qRule)
145@@ -1951,24 +1974,40 @@
146 ECalComponentAlarmTrigger trigger;
147 e_cal_component_alarm_get_trigger(alarm.data(), &trigger);
148 int relSecs = 0;
149+ bool fail = false;
150 if (trigger.type == E_CAL_COMPONENT_ALARM_TRIGGER_RELATIVE_START) {
151+
152 relSecs = - icaldurationtype_as_int(trigger.u.rel_duration);
153 if (relSecs < 0) {
154+ //WORKAROUND: Print warning only once, avoid flood application output
155+ static bool relativeStartwarningPrinted = false;
156 relSecs = 0;
157- qWarning() << "QOrganizer does not support triggers after event start";
158+ if (!relativeStartwarningPrinted) {
159+ fail = true;
160+ relativeStartwarningPrinted = true;
161+ qWarning() << "QOrganizer does not support triggers after event start";
162+ }
163 }
164 } else if (trigger.type != E_CAL_COMPONENT_ALARM_TRIGGER_NONE) {
165- qWarning() << "QOrganizer only supports triggers relative to event start.";
166- }
167- aDetail->setSecondsBeforeStart(relSecs);
168-
169- ECalComponentAlarmRepeat aRepeat;
170- e_cal_component_alarm_get_repeat(alarm.data(), &aRepeat);
171- aDetail->setRepetition(aRepeat.repetitions, icaldurationtype_as_int(aRepeat.duration));
172-
173- item->saveDetail(aDetail);
174+ fail = true;
175+ //WORKAROUND: Print warning only once, avoid flood application output
176+ static bool warningPrinted = false;
177+ if (!warningPrinted) {
178+ qWarning() << "QOrganizer only supports triggers relative to event start.:" << trigger.type;
179+ warningPrinted = true;
180+ }
181+ }
182+
183+ if (!fail) {
184+ aDetail->setSecondsBeforeStart(relSecs);
185+ ECalComponentAlarmRepeat aRepeat;
186+ e_cal_component_alarm_get_repeat(alarm.data(), &aRepeat);
187+ aDetail->setRepetition(aRepeat.repetitions, icaldurationtype_as_int(aRepeat.duration));
188+ item->saveDetail(aDetail);
189+ }
190 delete aDetail;
191 }
192+ cal_obj_uid_list_free(alarms);
193 }
194
195 void QOrganizerEDSEngine::parseEventsAsync(const QMap<QString, GSList *> &events,
196@@ -1980,7 +2019,15 @@
197 QMap<QOrganizerEDSCollectionEngineId*, GSList*> request;
198 Q_FOREACH(const QString &collectionId, events.keys()) {
199 QOrganizerEDSCollectionEngineId *collection = d->m_sourceRegistry->collectionEngineId(collectionId);
200- request.insert(collection, events.value(collectionId));
201+ if (isIcalEvents) {
202+ request.insert(collection,
203+ g_slist_copy_deep(events.value(collectionId),
204+ (GCopyFunc) icalcomponent_new_clone, NULL));
205+ } else {
206+ request.insert(collection,
207+ g_slist_copy_deep(events.value(collectionId),
208+ (GCopyFunc) g_object_ref, NULL));
209+ }
210 }
211
212 // the thread will destroy itself when done
213@@ -2208,7 +2255,7 @@
214 {
215 QOrganizerItemRecurrence rec = item.detail(QOrganizerItemDetail::TypeRecurrence);
216 if (!rec.isEmpty()) {
217- GSList *periodList = 0;
218+ GSList *periodList = NULL;
219 Q_FOREACH(const QDate &dt, rec.recurrenceDates()) {
220 ECalComponentPeriod *period = g_new0(ECalComponentPeriod, 1);
221 period->start = icaltime_from_timet(QDateTime(dt).toTime_t(), FALSE);
222@@ -2741,7 +2788,7 @@
223 // use component tz on recurrence id
224 ECalComponentDateTime dt;
225 e_cal_component_get_dtstart(comp, &dt);
226- dt.value = g_new(icaltimetype, 1);
227+ dt.value = g_new0(icaltimetype, 1);
228 *dt.value = icaltime_from_string(rId.toUtf8().data());
229
230 recur_id.type = E_CAL_COMPONENT_RANGE_SINGLE;
231
232=== modified file 'organizer/qorganizer-eds-enginedata.cpp'
233--- organizer/qorganizer-eds-enginedata.cpp 2013-12-04 23:07:24 +0000
234+++ organizer/qorganizer-eds-enginedata.cpp 2016-07-11 14:47:56 +0000
235@@ -37,7 +37,7 @@
236 m_viewWatchers.clear();
237
238 if (m_sourceRegistry) {
239- delete m_sourceRegistry;
240+ m_sourceRegistry->deleteLater();
241 m_sourceRegistry = 0;
242 }
243 }
244
245=== modified file 'organizer/qorganizer-eds-fetchrequestdata.cpp'
246--- organizer/qorganizer-eds-fetchrequestdata.cpp 2016-03-07 17:40:10 +0000
247+++ organizer/qorganizer-eds-fetchrequestdata.cpp 2016-07-11 14:47:56 +0000
248@@ -221,6 +221,9 @@
249 {
250 int count = 0;
251 QOrganizerItemFetchRequest *req = request<QOrganizerItemFetchRequest>();
252+ if (!req) {
253+ return 0;
254+ }
255 QOrganizerItemFilter filter = req->filter();
256 QList<QOrganizerItemSortOrder> sorting = req->sorting();
257
258
259=== modified file 'organizer/qorganizer-eds-parseeventthread.cpp'
260--- organizer/qorganizer-eds-parseeventthread.cpp 2015-04-11 00:00:05 +0000
261+++ organizer/qorganizer-eds-parseeventthread.cpp 2016-07-11 14:47:56 +0000
262@@ -21,6 +21,18 @@
263 connect(this, SIGNAL(finished()), SLOT(deleteLater()));
264 }
265
266+QOrganizerParseEventThread::~QOrganizerParseEventThread()
267+{
268+ Q_FOREACH(GSList *components ,m_events.values()) {
269+ if (m_isIcalEvents) {
270+ g_slist_free_full(components, (GDestroyNotify)icalcomponent_free);
271+ } else {
272+ g_slist_free_full(components, (GDestroyNotify)g_object_unref);
273+ }
274+ }
275+ m_events.clear();
276+}
277+
278 void QOrganizerParseEventThread::start(QMap<QOrganizerEDSCollectionEngineId *, GSList *> events,
279 bool isIcalEvents,
280 QList<QOrganizerItemDetail::DetailType> detailsHint)
281
282=== modified file 'organizer/qorganizer-eds-parseeventthread.h'
283--- organizer/qorganizer-eds-parseeventthread.h 2015-04-10 19:52:26 +0000
284+++ organizer/qorganizer-eds-parseeventthread.h 2016-07-11 14:47:56 +0000
285@@ -40,6 +40,7 @@
286 QOrganizerParseEventThread(QObject *source,
287 const QByteArray &slot,
288 QObject *parent = 0);
289+ ~QOrganizerParseEventThread();
290
291 void start(QMap<QOrganizerEDSCollectionEngineId *, GSList *> events,
292 bool isIcalEvents,
293@@ -48,6 +49,7 @@
294 private:
295 QPointer<QObject> m_source;
296 QMetaMethod m_slot;
297+ bool m_abort;
298
299 // parse data
300 QMap<QOrganizerEDSCollectionEngineId *, GSList *> m_events;
301
302=== modified file 'organizer/qorganizer-eds-requestdata.h'
303--- organizer/qorganizer-eds-requestdata.h 2016-01-12 13:10:01 +0000
304+++ organizer/qorganizer-eds-requestdata.h 2016-07-11 14:47:56 +0000
305@@ -47,7 +47,11 @@
306
307 template<class T>
308 T* request() const {
309- return qobject_cast<T*>(m_req.data());
310+ if (m_req) {
311+ return qobject_cast<T*>(m_req.data());
312+ } else {
313+ return 0;
314+ }
315 }
316
317 template<class T>
318
319=== modified file 'organizer/qorganizer-eds-savecollectionrequestdata.cpp'
320--- organizer/qorganizer-eds-savecollectionrequestdata.cpp 2016-03-15 13:05:04 +0000
321+++ organizer/qorganizer-eds-savecollectionrequestdata.cpp 2016-07-11 14:47:56 +0000
322@@ -26,6 +26,8 @@
323 #include <QtOrganizer/QOrganizerCollectionSaveRequest>
324 #include <QtOrganizer/QOrganizerCollectionChangeSet>
325
326+#include <evolution-data-server-ubuntu/e-source-ubuntu.h>
327+
328 using namespace QtOrganizer;
329
330 SaveCollectionRequestData::SaveCollectionRequestData(QOrganizerEDSEngine *engine,
331@@ -160,20 +162,11 @@
332 int index = 0;
333 Q_FOREACH(const QOrganizerCollection &collection, request<QOrganizerCollectionSaveRequest>()->collections()) {
334 ESource *source = 0;
335- bool isNew = true;
336- if (collection.id().isNull()) {
337- GError *gError = 0;
338- source = e_source_new(0, 0, &gError);
339- if (gError) {
340- m_errorMap.insert(index, QOrganizerManager::UnspecifiedError);
341- qWarning() << "Fail to create source:" << gError->message;
342- g_error_free(gError);
343- Q_ASSERT(false);
344- }
345- e_source_set_parent(source, "local-stub");
346+ bool isNew = collection.id().isNull();
347+ if (isNew) {
348+ source = SourceRegistry::newSourceFromCollection(collection);
349 } else {
350 source = m_parent->d->m_sourceRegistry->source(collection.id().toString());
351- isNew = false;
352 }
353
354 QVariant callendarType = collection.extendedMetaData(COLLECTION_CALLENDAR_TYPE_METADATA);
355@@ -187,7 +180,6 @@
356 extCalendar = E_SOURCE_BACKEND(e_source_get_extension(source, E_SOURCE_EXTENSION_CALENDAR));
357 }
358
359-
360 if (source) {
361 if (isNew) {
362 if (extCalendar) {
363@@ -213,6 +205,21 @@
364 bool isDefault = collection.extendedMetaData(COLLECTION_DEFAULT_METADATA).toBool();
365 g_object_set_data(G_OBJECT(source), "is-default", GINT_TO_POINTER(isDefault));
366
367+ // Ubuntu extension
368+ QVariant accountId = collection.extendedMetaData(COLLECTION_ACCOUNT_ID_METADATA);
369+ QVariant readOnly = collection.extendedMetaData(COLLECTION_SYNC_READONLY_METADATA);
370+ QVariant metadata = collection.extendedMetaData(COLLECTION_DATA_METADATA);
371+ if (accountId.isValid() ||
372+ readOnly.isValid() ||
373+ metadata.isValid()) {
374+
375+ ESourceUbuntu *extUbuntu = E_SOURCE_UBUNTU(e_source_get_extension(source, E_SOURCE_EXTENSION_UBUNTU));
376+ e_source_ubuntu_set_writable(extUbuntu, readOnly.isValid() ? !readOnly.toBool() : true);
377+ e_source_ubuntu_set_account_id(extUbuntu, accountId.toUInt());
378+ e_source_ubuntu_set_metadata(extUbuntu, metadata.toString().toUtf8().constData());
379+ e_source_ubuntu_set_autoremove(extUbuntu, TRUE);
380+ }
381+
382 m_sources.insert(index, source);
383 if (isNew) {
384 m_sourcesToCreate.insert(index, source);
385@@ -223,4 +230,3 @@
386 }
387 }
388 }
389-
390
391=== modified file 'organizer/qorganizer-eds-source-registry.cpp'
392--- organizer/qorganizer-eds-source-registry.cpp 2016-03-17 17:01:35 +0000
393+++ organizer/qorganizer-eds-source-registry.cpp 2016-07-11 14:47:56 +0000
394@@ -2,6 +2,7 @@
395 #include "config.h"
396
397 #include <QtCore/QDebug>
398+#include <evolution-data-server-ubuntu/e-source-ubuntu.h>
399
400 using namespace QtOrganizer;
401
402@@ -310,11 +311,33 @@
403 QOrganizerCollectionId id(*edsId);
404 QOrganizerCollection collection;
405
406+ // id
407 collection.setId(id);
408+
409 updateCollection(&collection, isDefault, source);
410 return collection;
411 }
412
413+ESource *SourceRegistry::newSourceFromCollection(const QtOrganizer::QOrganizerCollection &collection)
414+{
415+ if (!collection.id().isNull()) {
416+ qWarning() << "Fail to create source from collection: Collection already has id.";
417+ return NULL;
418+ }
419+
420+ GError *gError = 0;
421+ ESource *source = e_source_new(NULL, NULL, &gError);
422+
423+ if (gError) {
424+ qWarning() << "Fail to create source:" << gError->message;
425+ g_error_free(gError);
426+ return NULL;
427+ }
428+
429+ e_source_set_parent(source, "local-stub");
430+ return source;
431+}
432+
433 QByteArray SourceRegistry::defaultCollectionId() const
434 {
435 QVariant id = m_settings.value(DEFAULT_COLLECTION_SETTINGS);
436@@ -426,4 +449,19 @@
437
438 // default
439 collection->setExtendedMetaData(COLLECTION_DEFAULT_METADATA, isDefault);
440+
441+ // Ubuntu Extension
442+ ESourceUbuntu *extUbuntu = E_SOURCE_UBUNTU(e_source_get_extension(source, E_SOURCE_EXTENSION_UBUNTU));
443+ if (extUbuntu) {
444+ collection->setExtendedMetaData(COLLECTION_ACCOUNT_ID_METADATA, e_source_ubuntu_get_account_id(extUbuntu));
445+ writable = e_source_ubuntu_get_writable(extUbuntu) == TRUE;
446+ collection->setExtendedMetaData(COLLECTION_SYNC_READONLY_METADATA, !writable);
447+ if (!writable) {
448+ // Set account as read-only if not writable
449+ collection->setExtendedMetaData(COLLECTION_READONLY_METADATA, true);
450+ }
451+ const gchar *data = e_source_ubuntu_get_metadata(extUbuntu);
452+ collection->setExtendedMetaData(COLLECTION_DATA_METADATA, data ? QString::fromUtf8(data) : QString());
453+ }
454+
455 }
456
457=== modified file 'organizer/qorganizer-eds-source-registry.h'
458--- organizer/qorganizer-eds-source-registry.h 2016-03-17 17:01:35 +0000
459+++ organizer/qorganizer-eds-source-registry.h 2016-07-11 14:47:56 +0000
460@@ -33,6 +33,9 @@
461 #define COLLECTION_SELECTED_METADATA "collection-selected"
462 #define COLLECTION_READONLY_METADATA "collection-readonly"
463 #define COLLECTION_DEFAULT_METADATA "collection-default"
464+#define COLLECTION_SYNC_READONLY_METADATA "collection-sync-readonly"
465+#define COLLECTION_ACCOUNT_ID_METADATA "collection-account-id"
466+#define COLLECTION_DATA_METADATA "collection-metadata"
467
468 class SourceRegistry : public QObject
469 {
470@@ -61,6 +64,7 @@
471 static QtOrganizer::QOrganizerCollection parseSource(ESource *source,
472 bool isDefault,
473 QOrganizerEDSCollectionEngineId **edsId);
474+ static ESource *newSourceFromCollection(const QtOrganizer::QOrganizerCollection &collection);
475
476 Q_SIGNALS:
477 void sourceAdded(const QString &collectionId);
478
479=== modified file 'organizer/qorganizer-eds-viewwatcher.cpp'
480--- organizer/qorganizer-eds-viewwatcher.cpp 2014-10-09 02:55:01 +0000
481+++ organizer/qorganizer-eds-viewwatcher.cpp 2016-07-11 14:47:56 +0000
482@@ -47,6 +47,8 @@
483 (GAsyncReadyCallback) ViewWatcher::viewReady,
484 this);
485 wait();
486+ m_dirty.setSingleShot(true);
487+ connect(&m_dirty, SIGNAL(timeout()), SLOT(flush()));
488 }
489
490 ViewWatcher::~ViewWatcher()
491@@ -108,7 +110,12 @@
492 }
493
494 if (m_eView) {
495- e_cal_client_view_stop(m_eView, 0);
496+ GError *gErr = 0;
497+ e_cal_client_view_stop(m_eView, &gErr);
498+ if (gErr) {
499+ qWarning() << "Fail to stop view" << gErr->message;
500+ g_error_free(gErr);
501+ }
502 g_clear_object(&m_eView);
503 }
504
505@@ -148,15 +155,24 @@
506 return result;
507 }
508
509+void ViewWatcher::notify()
510+{
511+ m_dirty.start(500);
512+}
513+
514+void ViewWatcher::flush()
515+{
516+ m_engineData->emitSharedSignals(&m_changeSet);
517+ m_changeSet.clearAll();
518+}
519+
520 void ViewWatcher::onObjectsAdded(ECalClientView *view,
521 GSList *objects,
522 ViewWatcher *self)
523 {
524 Q_UNUSED(view);
525-
526- QOrganizerItemChangeSet changeSet;
527- changeSet.insertAddedItems(self->parseItemIds(objects));
528- self->m_engineData->emitSharedSignals(&changeSet);
529+ self->m_changeSet.insertAddedItems(self->parseItemIds(objects));
530+ self->notify();
531 }
532
533 void ViewWatcher::onObjectsRemoved(ECalClientView *view,
534@@ -164,16 +180,14 @@
535 ViewWatcher *self)
536 {
537 Q_UNUSED(view);
538- QOrganizerItemChangeSet changeSet;
539
540 for (GSList *l = objects; l; l = l->next) {
541 ECalComponentId *id = static_cast<ECalComponentId*>(l->data);
542 QOrganizerEDSEngineId *itemId = new QOrganizerEDSEngineId(self->m_collectionId,
543 QString::fromUtf8(id->uid));
544- changeSet.insertRemovedItem(QOrganizerItemId(itemId));
545+ self->m_changeSet.insertRemovedItem(QOrganizerItemId(itemId));
546 }
547-
548- self->m_engineData->emitSharedSignals(&changeSet);
549+ self->notify();
550 }
551
552 void ViewWatcher::onObjectsModified(ECalClientView *view,
553@@ -182,8 +196,6 @@
554 {
555 Q_UNUSED(view);
556
557- QOrganizerItemChangeSet changeSet;
558- changeSet.insertChangedItems(self->parseItemIds(objects));
559-
560- self->m_engineData->emitSharedSignals(&changeSet);
561+ self->m_changeSet.insertChangedItems(self->parseItemIds(objects));
562+ self->notify();
563 }
564
565=== modified file 'organizer/qorganizer-eds-viewwatcher.h'
566--- organizer/qorganizer-eds-viewwatcher.h 2013-12-03 01:23:34 +0000
567+++ organizer/qorganizer-eds-viewwatcher.h 2016-07-11 14:47:56 +0000
568@@ -24,6 +24,7 @@
569 #include <QtCore/QList>
570 #include <QtCore/QObject>
571 #include <QtCore/QEventLoop>
572+#include <QtCore/QTimer>
573
574 #include <libecal/libecal.h>
575
576@@ -40,6 +41,9 @@
577 void clear();
578 void wait();
579
580+private Q_SLOTS:
581+ void flush();
582+
583 private:
584 QString m_collectionId;
585 QOrganizerEDSEngineData *m_engineData;
586@@ -47,8 +51,12 @@
587 ECalClient *m_eClient;
588 ECalClientView *m_eView;
589 QEventLoop *m_eventLoop;
590+ QOrganizerItemChangeSet m_changeSet;
591+ QTimer m_dirty;
592
593 QList<QtOrganizer::QOrganizerItemId> parseItemIds(GSList *objects);
594+ void notify();
595+
596
597 static void clientConnected(GObject *sourceObject, GAsyncResult *res, ViewWatcher *self);
598 static void viewReady(GObject *sourceObject, GAsyncResult *res, ViewWatcher *self);
599
600=== modified file 'tests/unittest/CMakeLists.txt'
601--- tests/unittest/CMakeLists.txt 2016-01-12 13:10:01 +0000
602+++ tests/unittest/CMakeLists.txt 2016-07-11 14:47:56 +0000
603@@ -3,6 +3,7 @@
604 ${TESTNAME}.cpp
605 eds-base-test.cpp
606 eds-base-test.h
607+ gscopedpointer.h
608 )
609 qt5_use_modules(${TESTNAME} Core Organizer Test)
610
611
612=== modified file 'tests/unittest/collections-test.cpp'
613--- tests/unittest/collections-test.cpp 2016-03-14 20:19:46 +0000
614+++ tests/unittest/collections-test.cpp 2016-07-11 14:47:56 +0000
615@@ -218,6 +218,7 @@
616 QTRY_VERIFY(updateCollection.count() > 0);
617 QList<QVariant> args = updateCollection.takeFirst();
618 QCOMPARE(args.count(), 1);
619+ QCOMPARE(args[0].value<QList<QOrganizerCollectionId> >().count(), 1);
620 QCOMPARE(args[0].value<QList<QOrganizerCollectionId> >().at(0).toString(), collection.id().toString());
621
622
623@@ -351,6 +352,118 @@
624 // wait collection to became the default one
625 QTRY_COMPARE_WITH_TIMEOUT(m_engineRead->defaultCollection(0).id(), newCollection.id(), 5000);
626 }
627+
628+ void testSaveCollectionWithAccountId()
629+ {
630+ static QString newCollectionId = uniqueCollectionName();
631+
632+ // Create a collection
633+ QOrganizerCollection collection;
634+ QtOrganizer::QOrganizerManager::Error error;
635+ collection.setMetaData(QOrganizerCollection::KeyName, newCollectionId);
636+ collection.setExtendedMetaData(COLLECTION_ACCOUNT_ID_METADATA, 99);
637+
638+ QSignalSpy createCollection(m_engineRead, SIGNAL(collectionsAdded(QList<QOrganizerCollectionId>)));
639+ QVERIFY(m_engineWrite->saveCollection(&collection, &error));
640+ QTRY_COMPARE(createCollection.count(), 1);
641+
642+ // check if collection contains the account id in the id
643+ QCOMPARE(collection.extendedMetaData(COLLECTION_ACCOUNT_ID_METADATA).toInt(), 99);
644+
645+ // Query for collection
646+ QOrganizerCollection newCollection = m_engineRead->collection(collection.id(), 0);
647+
648+ // check account field
649+ QCOMPARE(newCollection.extendedMetaData(COLLECTION_ACCOUNT_ID_METADATA).toInt(), 99);
650+ }
651+
652+ void testSaveCollectionWithMetadata()
653+ {
654+ static QString newCollectionId = uniqueCollectionName();
655+
656+ // Create a collection
657+ QOrganizerCollection collection;
658+ QtOrganizer::QOrganizerManager::Error error;
659+ collection.setMetaData(QOrganizerCollection::KeyName, newCollectionId);
660+ collection.setExtendedMetaData(COLLECTION_DATA_METADATA, QStringLiteral("string metadata"));
661+
662+ QSignalSpy createCollection(m_engineRead, SIGNAL(collectionsAdded(QList<QOrganizerCollectionId>)));
663+ QVERIFY(m_engineWrite->saveCollection(&collection, &error));
664+ QTRY_COMPARE(createCollection.count(), 1);
665+
666+ // check if collection contains the metadata
667+ QCOMPARE(collection.extendedMetaData(COLLECTION_DATA_METADATA).toString(), QStringLiteral("string metadata"));
668+
669+ // Query for collection
670+ QOrganizerCollection newCollection = m_engineRead->collection(collection.id(), 0);
671+
672+ // check account field
673+ QCOMPARE(newCollection.extendedMetaData(COLLECTION_DATA_METADATA).toString(), QStringLiteral("string metadata"));
674+ }
675+
676+ void testSaveCollectionWithSyncWritable()
677+ {
678+ static QString newCollectionId = uniqueCollectionName();
679+
680+ // Create a collection
681+ QOrganizerCollection collection;
682+ QtOrganizer::QOrganizerManager::Error error;
683+ collection.setMetaData(QOrganizerCollection::KeyName, newCollectionId);
684+ collection.setExtendedMetaData(COLLECTION_SYNC_READONLY_METADATA, true);
685+ QCOMPARE(collection.extendedMetaData(COLLECTION_SYNC_READONLY_METADATA).toBool(), true);
686+
687+ QSignalSpy createCollection(m_engineRead, SIGNAL(collectionsAdded(QList<QOrganizerCollectionId>)));
688+ QVERIFY(m_engineWrite->saveCollection(&collection, &error));
689+ QTRY_COMPARE(createCollection.count(), 1);
690+
691+ // check if collection was marked as read-only
692+ QCOMPARE(collection.extendedMetaData(COLLECTION_SYNC_READONLY_METADATA).toBool(), true);
693+ QCOMPARE(collection.extendedMetaData(COLLECTION_READONLY_METADATA).toBool(), true);
694+
695+ // Query for collection
696+ QOrganizerCollection newCollection = m_engineRead->collection(collection.id(), 0);
697+
698+ // check if collection was marked as read-only
699+ QCOMPARE(newCollection.extendedMetaData(COLLECTION_SYNC_READONLY_METADATA).toBool(), true);
700+ QCOMPARE(newCollection.extendedMetaData(COLLECTION_READONLY_METADATA).toBool(), true);
701+ }
702+
703+ void testModifyMetaDataUpdateCollection()
704+ {
705+ static QString newCollectionId = uniqueCollectionName();
706+
707+ // Create a collection
708+ QOrganizerCollection collection;
709+ QtOrganizer::QOrganizerManager::Error error;
710+ collection.setMetaData(QOrganizerCollection::KeyName, newCollectionId);
711+ collection.setExtendedMetaData(COLLECTION_SYNC_READONLY_METADATA, true);
712+ QCOMPARE(collection.extendedMetaData(COLLECTION_SYNC_READONLY_METADATA).toBool(), true);
713+
714+ QSignalSpy createCollection(m_engineRead, &QOrganizerManagerEngine::collectionsAdded);
715+ QVERIFY(m_engineWrite->saveCollection(&collection, &error));
716+ QTRY_COMPARE(createCollection.count(), 1);
717+ QTest::qWait(1000);
718+
719+ // check if collection update signal is fired
720+ QSignalSpy collectionsModified(m_engineRead, &QOrganizerManagerEngine::collectionsModified);
721+ QSignalSpy collectionsChanged(m_engineRead, &QOrganizerManagerEngine::collectionsChanged);
722+
723+ // Modify collection on EDS
724+ const QString metadataValue = QStringLiteral("new metadata");
725+ QTRY_COMPARE(collectionsChanged.count(), 0);
726+ qDebug() << "WIll update metadata";
727+ setCollectionMetadata(collection.id(), metadataValue);
728+
729+ // it will fire two signals
730+ // 1- Property change
731+ // 2- Source write
732+ QTRY_COMPARE(collectionsChanged.count(), 2);
733+ QTRY_COMPARE(collectionsModified.count(), 2);
734+
735+ // check if the metadata was changed
736+ QOrganizerCollection newCollection = m_engineRead->collection(collection.id(), 0);
737+ QCOMPARE(newCollection.extendedMetaData(COLLECTION_DATA_METADATA).toString(), metadataValue);
738+ }
739 };
740
741 const QString CollectionTest::collectionTypePropertyName = QStringLiteral("collection-type");
742
743=== modified file 'tests/unittest/eds-base-test.cpp'
744--- tests/unittest/eds-base-test.cpp 2016-05-06 14:31:43 +0000
745+++ tests/unittest/eds-base-test.cpp 2016-07-11 14:47:56 +0000
746@@ -19,33 +19,17 @@
747 #include "config.h"
748 #include "eds-base-test.h"
749 #include "qorganizer-eds-engine.h"
750+#include "gscopedpointer.h"
751
752 #include <QtCore>
753 #include <QtTest>
754
755 #include <libecal/libecal.h>
756
757+#include <evolution-data-server-ubuntu/e-source-ubuntu.h>
758+
759 using namespace QtOrganizer;
760
761-class GScopedPointerUnref
762-{
763-public:
764- static inline void cleanup(void *pointer)
765- {
766- if (pointer) {
767- g_clear_object(&pointer);
768- }
769- }
770-};
771-
772-template<class KLASS>
773-class GScopedPointer : public QScopedPointer<KLASS, GScopedPointerUnref>
774-{
775-public:
776- GScopedPointer(KLASS* obj = 0)
777- : QScopedPointer<KLASS, GScopedPointerUnref>(obj)
778- {}
779-};
780
781 EDSBaseTest::EDSBaseTest()
782 {
783@@ -74,6 +58,22 @@
784 QTest::qWait(1000);
785 }
786
787+void EDSBaseTest::setCollectionMetadata(const QOrganizerCollectionId &collectionId, const QString &metaData)
788+{
789+ GError *error = NULL;
790+ GScopedPointer<ESourceRegistry> sourceRegistry(e_source_registry_new_sync(NULL, &error));
791+ if (error) {
792+ qWarning() << "Fail to create source registry" << error->message;
793+ g_error_free(error);
794+ return;
795+ }
796+ GScopedPointer<ESource> calendar(e_source_registry_ref_source(sourceRegistry.data(),
797+ collectionId.toString().split(":").last().toUtf8().data()));
798+ ESourceUbuntu *ubuntu = E_SOURCE_UBUNTU(e_source_get_extension(calendar.data(), E_SOURCE_EXTENSION_UBUNTU));
799+ e_source_ubuntu_set_metadata(ubuntu, metaData.toUtf8().constData());
800+ e_source_write_sync(calendar.data(), NULL, NULL);
801+}
802+
803 QString EDSBaseTest::getEventFromEvolution(const QOrganizerItemId &id,
804 const QOrganizerCollectionId &collectionId)
805 {
806
807=== modified file 'tests/unittest/eds-base-test.h'
808--- tests/unittest/eds-base-test.h 2015-04-09 00:03:01 +0000
809+++ tests/unittest/eds-base-test.h 2016-07-11 14:47:56 +0000
810@@ -37,6 +37,8 @@
811 virtual void cleanup();
812
813
814+ void setCollectionMetadata(const QtOrganizer::QOrganizerCollectionId &collectionId,
815+ const QString &metaData);
816 QString getEventFromEvolution(const QtOrganizer::QOrganizerItemId &id,
817 const QtOrganizer::QOrganizerCollectionId &collectionId = QtOrganizer::QOrganizerCollectionId());
818 QString uniqueCollectionName() const;
819
820=== added file 'tests/unittest/gscopedpointer.h'
821--- tests/unittest/gscopedpointer.h 1970-01-01 00:00:00 +0000
822+++ tests/unittest/gscopedpointer.h 2016-07-11 14:47:56 +0000
823@@ -0,0 +1,43 @@
824+/*
825+ * Copyright 2016 Canonical Ltd.
826+ *
827+ * This file is part of qtorganizer5-eds.
828+ *
829+ * contact-service-app is free software; you can redistribute it and/or modify
830+ * it under the terms of the GNU General Public License as published by
831+ * the Free Software Foundation; version 3.
832+ *
833+ * contact-service-app is distributed in the hope that it will be useful,
834+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
835+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
836+ * GNU General Public License for more details.
837+ *
838+ * You should have received a copy of the GNU General Public License
839+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
840+ */
841+
842+#ifndef __GSCOPEDPOINTER__
843+#define __GSCOPEDPOINTER__
844+
845+
846+class GScopedPointerUnref
847+{
848+public:
849+ static inline void cleanup(void *pointer)
850+ {
851+ if (pointer) {
852+ g_clear_object(&pointer);
853+ }
854+ }
855+};
856+
857+template<class KLASS>
858+class GScopedPointer : public QScopedPointer<KLASS, GScopedPointerUnref>
859+{
860+public:
861+ GScopedPointer(KLASS* obj = 0)
862+ : QScopedPointer<KLASS, GScopedPointerUnref>(obj)
863+ {}
864+};
865+
866+#endif
867
868=== modified file 'tests/unittest/parseecal-test.cpp'
869--- tests/unittest/parseecal-test.cpp 2015-04-10 18:20:07 +0000
870+++ tests/unittest/parseecal-test.cpp 2016-07-11 14:47:56 +0000
871@@ -21,6 +21,8 @@
872 #include "qorganizer-eds-engine.h"
873 #undef private
874
875+#include "gscopedpointer.h"
876+
877 #include <QObject>
878 #include <QtTest>
879 #include <QDebug>
880@@ -56,25 +58,25 @@
881 QDateTime endTime(startTime);
882 endTime = endTime.addDays(2);
883
884- ECalComponent *comp = e_cal_component_new();
885- e_cal_component_set_new_vtype(comp, E_CAL_COMPONENT_EVENT);
886+ GScopedPointer<ECalComponent> comp(e_cal_component_new());
887+ e_cal_component_set_new_vtype(comp.data(), E_CAL_COMPONENT_EVENT);
888
889 ECalComponentDateTime dt;
890
891 struct icaltimetype itt = icaltime_from_timet(startTime.toTime_t(), FALSE);
892 dt.value = &itt;
893 dt.tzid = "";
894- e_cal_component_set_dtstart(comp, &dt);
895+ e_cal_component_set_dtstart(comp.data(), &dt);
896
897 QOrganizerEvent item;
898- QOrganizerEDSEngine::parseStartTime(comp, &item);
899+ QOrganizerEDSEngine::parseStartTime(comp.data(), &item);
900 QCOMPARE(item.startDateTime().toTime_t(), startTime.toTime_t());
901
902 itt = icaltime_from_timet(endTime.toTime_t(), FALSE);
903 dt.value = &itt;
904- e_cal_component_set_dtend(comp, &dt);
905+ e_cal_component_set_dtend(comp.data(), &dt);
906
907- QOrganizerEDSEngine::parseEndTime(comp, &item);
908+ QOrganizerEDSEngine::parseEndTime(comp.data(), &item);
909 QCOMPARE(item.endDateTime().toTime_t(), endTime.toTime_t());
910 }
911
912@@ -89,15 +91,15 @@
913 QCOMPARE(aReminder.secondsBeforeStart(), 10);
914 event.saveDetail(&aReminder);
915
916- ECalComponent *comp = e_cal_component_new();
917- e_cal_component_set_new_vtype(comp, E_CAL_COMPONENT_EVENT);
918-
919- QOrganizerEDSEngine::parseReminders(event, comp);
920-
921- GList *aIds = e_cal_component_get_alarm_uids(comp);
922+ GScopedPointer<ECalComponent> comp(e_cal_component_new());
923+ e_cal_component_set_new_vtype(comp.data(), E_CAL_COMPONENT_EVENT);
924+
925+ QOrganizerEDSEngine::parseReminders(event, comp.data());
926+
927+ GList *aIds = e_cal_component_get_alarm_uids(comp.data());
928 QCOMPARE(g_list_length(aIds), (guint) 1);
929
930- ECalComponentAlarm *alarm = e_cal_component_get_alarm(comp, (const gchar*)aIds->data);
931+ ECalComponentAlarm *alarm = e_cal_component_get_alarm(comp.data(), (const gchar*)aIds->data);
932 QVERIFY(alarm);
933
934 ECalComponentAlarmAction aAction;
935@@ -114,13 +116,14 @@
936 QCOMPARE(aRepeat.repetitions, aReminder.repetitionCount());
937 QCOMPARE(icaldurationtype_as_int(aRepeat.duration), aReminder.repetitionDelay());
938
939- g_object_unref(comp);
940+ e_cal_component_alarm_free(alarm);
941+ cal_obj_uid_list_free(aIds);
942 }
943
944 void testParseRemindersECalComponent2QOrganizerEvent()
945 {
946- ECalComponent *comp = e_cal_component_new();
947- e_cal_component_set_new_vtype(comp, E_CAL_COMPONENT_EVENT);
948+ GScopedPointer<ECalComponent> comp(e_cal_component_new());
949+ e_cal_component_set_new_vtype(comp.data(), E_CAL_COMPONENT_EVENT);
950
951 ECalComponentAlarm *alarm = e_cal_component_alarm_new();
952 e_cal_component_alarm_set_action(alarm, E_CAL_COMPONENT_ALARM_DISPLAY);
953@@ -135,18 +138,16 @@
954 aRepeat.duration = icaldurationtype_from_int(100);
955 e_cal_component_alarm_set_repeat(alarm, aRepeat);
956
957- e_cal_component_add_alarm(comp, alarm);
958+ e_cal_component_add_alarm(comp.data(), alarm);
959 e_cal_component_alarm_free(alarm);
960
961 QOrganizerItem alarmItem;
962- QOrganizerEDSEngine::parseReminders(comp, &alarmItem);
963+ QOrganizerEDSEngine::parseReminders(comp.data(), &alarmItem);
964
965 QOrganizerItemVisualReminder vReminder = alarmItem.detail(QOrganizerItemDetail::TypeVisualReminder);
966 QCOMPARE(vReminder.repetitionCount(), 5);
967 QCOMPARE(vReminder.repetitionDelay(), 100);
968 QCOMPARE(vReminder.secondsBeforeStart(), 10);
969-
970- g_object_unref(comp);
971 }
972
973 void testParseRecurenceQOrganizerEvent2ECalComponent()
974@@ -323,6 +324,8 @@
975 }
976 }
977
978+ e_cal_component_free_recur_list(recurList);
979+
980 // invert
981 QOrganizerEvent event2;
982 QOrganizerEDSEngine::parseRecurrence(comp, &event2);
983@@ -384,7 +387,7 @@
984 QVERIFY(icalcomponent_is_valid(ical));
985
986 QList<QOrganizerItemDetail::DetailType> detailsHint;
987- GSList *events = g_slist_append(0, ical);
988+ GSList *events = g_slist_append(events, ical);
989 QMap<QString, GSList*> eventMap;
990 eventMap.insert(engine->defaultCollection(0).id().toString(), events);
991 engine->parseEventsAsync(eventMap, true, detailsHint, this, SLOT(onEventAsyncParsed(QList<QOrganizerItem>)));
992@@ -412,6 +415,7 @@
993 QCOMPARE(vreminder.message(), QStringLiteral("alarm to parse"));
994
995 g_slist_free_full(events, (GDestroyNotify)icalcomponent_free);
996+ icalcomponent_free(ical);
997 delete engine;
998 }
999 };

Subscribers

People subscribed via source and target branches