Merge lp:~renatofilho/qtorganizer5-eds/fix-query-with-detached-events into lp:qtorganizer5-eds

Proposed by Renato Araujo Oliveira Filho
Status: Merged
Approved by: Bill Filler
Approved revision: 90
Merged at revision: 93
Proposed branch: lp:~renatofilho/qtorganizer5-eds/fix-query-with-detached-events
Merge into: lp:qtorganizer5-eds
Prerequisite: lp:~renatofilho/qtorganizer5-eds/optimize-query
Diff against target: 421 lines (+221/-50)
5 files modified
organizer/qorganizer-eds-engine.cpp (+77/-20)
organizer/qorganizer-eds-engine.h (+3/-1)
organizer/qorganizer-eds-fetchrequestdata.cpp (+63/-29)
organizer/qorganizer-eds-fetchrequestdata.h (+5/-0)
tests/unittest/recurrence-test.cpp (+73/-0)
To merge this branch: bzr merge lp:~renatofilho/qtorganizer5-eds/fix-query-with-detached-events
Reviewer Review Type Date Requested Status
PS Jenkins bot continuous-integration Approve
Ubuntu Phablet Team Pending
Review via email: mp+282767@code.launchpad.net

Commit message

Populate event list with detached events.

Make sure that detached events appear on the list while fetching events.

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

Check if request still valid bofere parse items on thread.

89. By Renato Araujo Oliveira Filho

Fixed event recurrence cb signature.

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

Avoid crash when searching with invalid filter.

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

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'organizer/qorganizer-eds-engine.cpp'
2--- organizer/qorganizer-eds-engine.cpp 2016-01-25 14:17:34 +0000
3+++ organizer/qorganizer-eds-engine.cpp 2016-01-25 14:17:34 +0000
4@@ -133,7 +133,6 @@
5 itemsAsyncStart(data);
6 } else {
7 data->finish();
8- releaseRequestData(data);
9 }
10 }
11
12@@ -175,16 +174,63 @@
13 void QOrganizerEDSEngine::itemsAsyncDone(FetchRequestData *data)
14 {
15 if (data->isLive()) {
16+ data->compileCurrentIds();
17+ itemsAsyncFetchDeatachedItems(data);
18+ } else {
19+ releaseRequestData(data);
20+ }
21+}
22+
23+void QOrganizerEDSEngine::itemsAsyncFetchDeatachedItems(FetchRequestData *data)
24+{
25+ QString parentId = data->nextParentId();
26+ if (!parentId.isEmpty()) {
27+ e_cal_client_get_objects_for_uid(E_CAL_CLIENT(data->client()),
28+ parentId.toUtf8().data(),
29+ data->cancellable(),
30+ (GAsyncReadyCallback) QOrganizerEDSEngine::itemsAsyncListByIdListed,
31+ data);
32+ } else {
33 itemsAsyncStart(data);
34- } else {
35- releaseRequestData(data);
36- }
37-}
38-
39-void QOrganizerEDSEngine::itemsAsyncListed(ECalComponent *comp,
40- time_t instanceStart,
41- time_t instanceEnd,
42- FetchRequestData *data)
43+ }
44+}
45+
46+void QOrganizerEDSEngine::itemsAsyncListByIdListed(GObject *source,
47+ GAsyncResult *res,
48+ FetchRequestData *data)
49+{
50+ Q_UNUSED(source);
51+ GError *gError = 0;
52+ GSList *events = 0;
53+ e_cal_client_get_objects_for_uid_finish(E_CAL_CLIENT(data->client()),
54+ res,
55+ &events,
56+ &gError);
57+ if (gError) {
58+ qWarning() << "Fail to list deatached events in calendar" << gError->message;
59+ g_error_free(gError);
60+ gError = 0;
61+ if (data->isLive()) {
62+ data->finish(QOrganizerManager::InvalidCollectionError);
63+ } else {
64+ releaseRequestData(data);
65+ }
66+ return;
67+ }
68+
69+ for(GSList *e = events; e != NULL; e = e->next) {
70+ icalcomponent * ical = e_cal_component_get_icalcomponent(static_cast<ECalComponent*>(e->data));
71+ data->appendDeatachedResult(ical);
72+ }
73+
74+ itemsAsyncFetchDeatachedItems(data);
75+}
76+
77+
78+gboolean QOrganizerEDSEngine::itemsAsyncListed(ECalComponent *comp,
79+ time_t instanceStart,
80+ time_t instanceEnd,
81+ FetchRequestData *data)
82 {
83 Q_UNUSED(instanceStart);
84 Q_UNUSED(instanceEnd);
85@@ -194,7 +240,9 @@
86 if (icalComp) {
87 data->appendResult(icalComp);
88 }
89+ return TRUE;
90 }
91+ return FALSE;
92 }
93
94 void QOrganizerEDSEngine::itemsAsyncListedAsComps(GObject *source,
95@@ -662,7 +710,9 @@
96 QOrganizerEDSEngineId *eid = new QOrganizerEDSEngineId(currentCollectionId,
97 QString::fromUtf8(uid));
98 item.setId(QOrganizerItemId(eid));
99- item.setGuid(QString::fromUtf8(uid));
100+ item.setGuid(QString("%1/%2")
101+ .arg(eid->m_collectionId)
102+ .arg(eid->m_itemId));
103
104 QOrganizerEDSCollectionEngineId *edsCollectionId = new QOrganizerEDSCollectionEngineId(currentCollectionId);
105 item.setCollectionId(QOrganizerCollectionId(edsCollectionId));
106@@ -2349,12 +2399,21 @@
107 QOrganizerItem *item,
108 QOrganizerEDSCollectionEngineId *edsCollectionId)
109 {
110+
111 ECalComponentId *id = e_cal_component_get_id(comp);
112 QOrganizerEDSEngineId *edsParentId = 0;
113- QOrganizerEDSEngineId *edsId = QOrganizerEDSEngineId::fromComponentId(edsCollectionId->m_collectionId, id, &edsParentId);
114-
115+ QOrganizerEDSEngineId *edsId;
116+
117+ if (!edsCollectionId) {
118+ qWarning() << "Parse Id with null collection";
119+ return;
120+ }
121+
122+ edsId = QOrganizerEDSEngineId::fromComponentId(edsCollectionId->m_collectionId, id, &edsParentId);
123 item->setId(QOrganizerItemId(edsId));
124- item->setGuid(QString::fromUtf8(id->uid));
125+ item->setGuid(QString("%1/%2")
126+ .arg(edsCollectionId->m_collectionId)
127+ .arg(edsId->m_itemId));
128
129 if (edsParentId) {
130 QOrganizerItemParent itemParent = item->detail(QOrganizerItemDetail::TypeParent);
131@@ -2633,14 +2692,12 @@
132 e_cal_component_set_uid(comp, cId.toUtf8().data());
133
134 if (!rId.isEmpty()) {
135- ECalComponentRange *recur_id;
136+ ECalComponentRange recur_id;
137 struct icaltimetype tt = icaltime_from_string(rId.toUtf8().data());
138
139- recur_id = g_new0 (ECalComponentRange, 1);
140- recur_id->type = E_CAL_COMPONENT_RANGE_SINGLE;
141- recur_id->datetime.value = &tt;
142- e_cal_component_set_recurid(comp, recur_id);
143- g_free (recur_id);
144+ recur_id.type = E_CAL_COMPONENT_RANGE_SINGLE;
145+ recur_id.datetime.value = &tt;
146+ e_cal_component_set_recurid(comp, &recur_id);
147 }
148 }
149 }
150
151=== modified file 'organizer/qorganizer-eds-engine.h'
152--- organizer/qorganizer-eds-engine.h 2016-01-25 14:17:34 +0000
153+++ organizer/qorganizer-eds-engine.h 2016-01-25 14:17:34 +0000
154@@ -217,9 +217,11 @@
155 // glib callback
156 void itemsAsync(QtOrganizer::QOrganizerItemFetchRequest *req);
157 static void itemsAsyncStart(FetchRequestData *data);
158- static void itemsAsyncListed(ECalComponent *comp, time_t instanceStart, time_t instanceEnd, FetchRequestData *data);
159+ static gboolean itemsAsyncListed(ECalComponent *comp, time_t instanceStart, time_t instanceEnd, FetchRequestData *data);
160 static void itemsAsyncDone(FetchRequestData *data);
161 static void itemsAsyncListedAsComps(GObject *source, GAsyncResult *res, FetchRequestData *data);
162+ static void itemsAsyncFetchDeatachedItems(FetchRequestData *data);
163+ static void itemsAsyncListByIdListed(GObject *source, GAsyncResult *res, FetchRequestData *data);
164
165 void itemsByIdAsync(QtOrganizer::QOrganizerItemFetchByIdRequest *req);
166 static void itemsByIdAsyncStart(FetchByIdRequestData *data);
167
168=== modified file 'organizer/qorganizer-eds-fetchrequestdata.cpp'
169--- organizer/qorganizer-eds-fetchrequestdata.cpp 2016-01-25 14:17:34 +0000
170+++ organizer/qorganizer-eds-fetchrequestdata.cpp 2016-01-25 14:17:34 +0000
171@@ -17,6 +17,7 @@
172 */
173
174 #include "qorganizer-eds-fetchrequestdata.h"
175+#include "qorganizer-eds-engineid.h"
176
177 #include <QtCore/QDebug>
178
179@@ -64,6 +65,16 @@
180 }
181 }
182
183+QString FetchRequestData::nextParentId()
184+{
185+ QString nextId;
186+ if (!m_currentParentIds.isEmpty()) {
187+ nextId = m_currentParentIds.values().first();
188+ m_currentParentIds.remove(nextId);
189+ }
190+ return nextId;
191+}
192+
193 QString FetchRequestData::collection() const
194 {
195 return m_current;
196@@ -119,6 +130,16 @@
197 RequestData::cancel();
198 }
199
200+void FetchRequestData::compileCurrentIds()
201+{
202+ for(GSList *e = m_currentComponents; e != NULL; e = e->next) {
203+ icalcomponent *icalComp = static_cast<icalcomponent *>(e->data);
204+ if (e_cal_util_component_has_recurrences (icalComp)) {
205+ m_currentParentIds.insert(QString::fromUtf8(icalcomponent_get_uid(icalComp)));
206+ }
207+ }
208+}
209+
210 void FetchRequestData::finish(QOrganizerManager::Error error,
211 QOrganizerAbstractRequest::State state)
212 {
213@@ -126,21 +147,18 @@
214 m_parseListener = new FetchRequestDataParseListener(this,
215 error,
216 state);
217-#if 1
218- parent()->parseEventsAsync(m_components,
219- true,
220- request<QOrganizerItemFetchRequest>()->fetchHint().detailTypesHint(),
221- m_parseListener,
222- SLOT(onParseDone(QList<QtOrganizer::QOrganizerItem>)));
223-#else
224- Q_FOREACH(const QString &id, m_components.keys()) {
225- appendResults(parent()->parseEvents(id, m_components[id], true, request<QOrganizerItemFetchRequest>()->fetchHint().detailTypesHint()));
226+ QOrganizerItemFetchRequest *req = request<QOrganizerItemFetchRequest>();
227+ if (req) {
228+ parent()->parseEventsAsync(m_components,
229+ true,
230+ req->fetchHint().detailTypesHint(),
231+ m_parseListener,
232+ SLOT(onParseDone(QList<QtOrganizer::QOrganizerItem>)));
233+
234+ return;
235 }
236- finishContinue(error, state);
237-#endif
238- } else {
239- finishContinue(error, state);
240 }
241+ finishContinue(error, state);
242 }
243
244 void FetchRequestData::finishContinue(QOrganizerManager::Error error,
245@@ -169,27 +187,43 @@
246 m_currentComponents = g_slist_append(m_currentComponents, comp);
247 }
248
249+void FetchRequestData::appendDeatachedResult(icalcomponent *comp)
250+{
251+ const gchar *uid;
252+ struct icaltimetype rid;
253+
254+ uid = icalcomponent_get_uid(comp);
255+ rid = icalcomponent_get_recurrenceid(comp);
256+
257+ for(GSList *e=m_currentComponents; e != NULL; e = e->next) {
258+ icalcomponent *ical = static_cast<icalcomponent *>(e->data);
259+ if ((g_strcmp0(uid, icalcomponent_get_uid(ical)) == 0) &&
260+ (icaltime_compare(rid, icalcomponent_get_recurrenceid(ical)) == 0)) {
261+
262+ // replace instance event
263+ icalcomponent_free (ical);
264+ e->data = icalcomponent_new_clone(comp);
265+ QString itemId = QString("%1/%2#%3")
266+ .arg(QString(m_current).replace(QOrganizerEDSEngineId::managerUriStatic() + ":", ""))
267+ .arg(QString::fromUtf8(uid))
268+ .arg(QString::fromUtf8(icaltime_as_ical_string(rid)));
269+ m_deatachedIds.append(itemId);
270+ break;
271+ }
272+ }
273+}
274+
275 int FetchRequestData::appendResults(QList<QOrganizerItem> results)
276 {
277 int count = 0;
278- // check if we really need filter or sort the result
279 QOrganizerItemFetchRequest *req = request<QOrganizerItemFetchRequest>();
280 QOrganizerItemFilter filter = req->filter();
281- if ((filter.type() == QOrganizerItemFilter::DefaultFilter) &&
282- req->sorting().isEmpty()) {
283- m_results += results;
284- count = results.size();
285- } else {
286- Q_FOREACH(const QOrganizerItem &item, results) {
287- if ((req->filter().type() == QOrganizerItemFilter::DefaultFilter) ||
288- QOrganizerManagerEngine::testFilter(req->filter(), item)) {
289- if (!req->sorting().isEmpty()) {
290- QOrganizerManagerEngine::addSorted(&m_results, item, req->sorting());
291- } else {
292- m_results << item;
293- }
294- count++;
295- }
296+ QList<QOrganizerItemSortOrder> sorting = req->sorting();
297+
298+ Q_FOREACH(QOrganizerItem item, results) {
299+ if (QOrganizerManagerEngine::testFilter(filter, item)) {
300+ QOrganizerManagerEngine::addSorted(&m_results, item, sorting);
301+ count++;
302 }
303 }
304 return count;
305
306=== modified file 'organizer/qorganizer-eds-fetchrequestdata.h'
307--- organizer/qorganizer-eds-fetchrequestdata.h 2016-01-25 14:17:34 +0000
308+++ organizer/qorganizer-eds-fetchrequestdata.h 2016-01-25 14:17:34 +0000
309@@ -33,16 +33,19 @@
310 ~FetchRequestData();
311
312 QString nextCollection();
313+ QString nextParentId();
314 QString collection() const;
315 time_t startDate() const;
316 time_t endDate() const;
317 bool hasDateInterval() const;
318 bool filterIsValid() const;
319 void cancel();
320+ void compileCurrentIds();
321
322 void finish(QtOrganizer::QOrganizerManager::Error error = QtOrganizer::QOrganizerManager::NoError,
323 QtOrganizer::QOrganizerAbstractRequest::State state = QtOrganizer::QOrganizerAbstractRequest::FinishedState);
324 void appendResult(icalcomponent *comp);
325+ void appendDeatachedResult(icalcomponent *comp);
326 int appendResults(QList<QtOrganizer::QOrganizerItem> results);
327 QString dateFilter();
328
329@@ -50,6 +53,8 @@
330 FetchRequestDataParseListener *m_parseListener;
331 QMap<QString, GSList*> m_components;
332 QStringList m_collections;
333+ QSet<QString> m_currentParentIds;
334+ QStringList m_deatachedIds;
335 QString m_current;
336 GSList* m_currentComponents;
337 QList<QtOrganizer::QOrganizerItem> m_results;
338
339=== modified file 'tests/unittest/recurrence-test.cpp'
340--- tests/unittest/recurrence-test.cpp 2015-02-26 17:30:35 +0000
341+++ tests/unittest/recurrence-test.cpp 2016-01-25 14:17:34 +0000
342@@ -632,6 +632,79 @@
343 QCOMPARE(savedRule.limitDate().isValid(), false);
344 QCOMPARE(savedRule.limitCount(), -1);
345 }
346+
347+ void testModifiedRecurrenceDescription()
348+ {
349+ static QString displayLabelValue = QStringLiteral("testModifiedRecurrenceDescription test");
350+ static QString descriptionValue = QStringLiteral("testModifiedRecurrenceDescription description");
351+
352+ // create a recurrence event
353+ QOrganizerEvent ev;
354+ ev.setCollectionId(m_collection.id());
355+ ev.setStartDateTime(QDateTime(QDate(2013, 12, 2), QTime(0,0,0)));
356+ ev.setEndDateTime(QDateTime(QDate(2013, 12, 2), QTime(0,30,0)));
357+ ev.setDisplayLabel(displayLabelValue);
358+ ev.setDescription(descriptionValue);
359+
360+ QOrganizerRecurrenceRule rule;
361+ rule.setFrequency(QOrganizerRecurrenceRule::Daily);
362+ rule.setLimit(QDate(2013, 12, 31));
363+ ev.setRecurrenceRule(rule);
364+
365+ QSignalSpy itemsAdded(m_engine, SIGNAL(itemsAdded(QList<QOrganizerItemId>)));
366+ QtOrganizer::QOrganizerManager::Error error;
367+ QMap<int, QtOrganizer::QOrganizerManager::Error> errorMap;
368+ QList<QOrganizerItem> items;
369+ items << ev;
370+ bool saveResult = m_engine->saveItems(&items,
371+ QList<QtOrganizer::QOrganizerItemDetail::DetailType>(),
372+ &errorMap,
373+ &error);
374+ QVERIFY(saveResult);
375+ QCOMPARE(error, QtOrganizer::QOrganizerManager::NoError);
376+ QTRY_COMPARE_WITH_TIMEOUT(itemsAdded.count(), 1, 10000);
377+
378+ // modify the second ocurrence
379+ QOrganizerItemSortOrder sort;
380+ QOrganizerItemFetchHint hint;
381+ QOrganizerItemCollectionFilter filter;
382+ filter.setCollectionId(m_collection.id());
383+
384+ items = m_engine->items(filter,
385+ QDateTime(QDate(2013, 12, 1), QTime(0,0,0)),
386+ QDateTime(QDate(2013, 12, 31), QTime(0,0,0)),
387+ 100,
388+ sort,
389+ hint,
390+ &error);
391+
392+ QOrganizerItem ocurr = items.at(1);
393+ ocurr.setDescription(QString("%1 modified").arg(descriptionValue));
394+ items.clear();
395+ items << ocurr;
396+ saveResult = m_engine->saveItems(&items,
397+ QList<QtOrganizer::QOrganizerItemDetail::DetailType>(),
398+ &errorMap,
399+ &error);
400+ QVERIFY(saveResult);
401+ QCOMPARE(error, QtOrganizer::QOrganizerManager::NoError);
402+ QVERIFY(errorMap.isEmpty());
403+ QTRY_COMPARE_WITH_TIMEOUT(itemsAdded.count(), 2, 10000);
404+
405+ // Fetch items by date and check if the modified recurrence has his own id
406+ items = m_engine->items(filter,
407+ QDateTime(QDate(2013, 12, 1), QTime(0,0,0)),
408+ QDateTime(QDate(2013, 12, 31), QTime(0,0,0)),
409+ 100,
410+ sort,
411+ hint,
412+ &error);
413+
414+ // Check if the modified item appear on the list
415+ QOrganizerItem ocurr1 = items.at(1);
416+ QCOMPARE(ocurr1.description(), QString("%1 modified").arg(descriptionValue));
417+ QVERIFY(!ocurr1.id().isNull());
418+ }
419 };
420
421 QTEST_MAIN(RecurrenceTest)

Subscribers

People subscribed via source and target branches