Merge lp:~renatofilho/qtorganizer5-eds/recurrence into lp:~ubuntu-sdk-team/qtorganizer5-eds/trunk

Proposed by Renato Araujo Oliveira Filho
Status: Merged
Approved by: Gustavo Pichorim Boiko
Approved revision: 25
Merged at revision: 12
Proposed branch: lp:~renatofilho/qtorganizer5-eds/recurrence
Merge into: lp:~ubuntu-sdk-team/qtorganizer5-eds/trunk
Diff against target: 2806 lines (+2033/-178)
17 files modified
qorganizer/CMakeLists.txt (+4/-1)
qorganizer/qorganizer-eds-collection-engineid.cpp (+12/-0)
qorganizer/qorganizer-eds-collection-engineid.h (+3/-0)
qorganizer/qorganizer-eds-engine.cpp (+922/-151)
qorganizer/qorganizer-eds-engine.h (+62/-17)
qorganizer/qorganizer-eds-fetchrequestdata.cpp (+19/-3)
qorganizer/qorganizer-eds-removecollectionrequestdata.cpp (+76/-0)
qorganizer/qorganizer-eds-removecollectionrequestdata.h (+44/-0)
qorganizer/qorganizer-eds-removerequestdata.cpp (+0/-3)
qorganizer/qorganizer-eds-requestdata.cpp (+2/-2)
qorganizer/qorganizer-eds-requestdata.h (+1/-1)
qorganizer/qorganizer-eds-savecollectionrequestdata.cpp (+139/-0)
qorganizer/qorganizer-eds-savecollectionrequestdata.h (+49/-0)
tests/unittest/CMakeLists.txt (+5/-0)
tests/unittest/collections-test.cpp (+191/-0)
tests/unittest/event-test.cpp (+138/-0)
tests/unittest/parseecal-test.cpp (+366/-0)
To merge this branch: bzr merge lp:~renatofilho/qtorganizer5-eds/recurrence
Reviewer Review Type Date Requested Status
PS Jenkins bot continuous-integration Approve
Gustavo Pichorim Boiko (community) Approve
Review via email: mp+184642@code.launchpad.net

Commit message

- Implemented recurrence support;
- Implemented support for different collection type.
- Implemented Reminder 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)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Gustavo Pichorim Boiko (boiko) wrote :

Looks good.

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

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'qorganizer/CMakeLists.txt'
2--- qorganizer/CMakeLists.txt 2013-08-14 21:23:01 +0000
3+++ qorganizer/CMakeLists.txt 2013-09-09 21:01:24 +0000
4@@ -7,8 +7,10 @@
5 qorganizer-eds-fetchrequestdata.cpp
6 qorganizer-eds-engine.cpp
7 qorganizer-eds-engineid.cpp
8+ qorganizer-eds-removecollectionrequestdata.cpp
9 qorganizer-eds-removerequestdata.cpp
10 qorganizer-eds-requestdata.cpp
11+ qorganizer-eds-savecollectionrequestdata.cpp
12 qorganizer-eds-saverequestdata.cpp
13 )
14
15@@ -17,8 +19,10 @@
16 qorganizer-eds-fetchrequestdata.h
17 qorganizer-eds-engine.h
18 qorganizer-eds-engineid.h
19+ qorganizer-eds-removecollectionrequestdata.h
20 qorganizer-eds-removerequestdata.h
21 qorganizer-eds-requestdata.h
22+ qorganizer-eds-savecollectionrequestdata.h
23 qorganizer-eds-saverequestdata.h
24 )
25
26@@ -53,7 +57,6 @@
27 ${EDATASERVER_LIBRARIES}
28 )
29
30-
31 qt5_use_modules(${QORGANIZER_BACKEND}-lib Core Organizer)
32 qt5_use_modules(${QORGANIZER_BACKEND} Core Organizer)
33
34
35=== modified file 'qorganizer/qorganizer-eds-collection-engineid.cpp'
36--- qorganizer/qorganizer-eds-collection-engineid.cpp 2013-08-14 21:23:01 +0000
37+++ qorganizer/qorganizer-eds-collection-engineid.cpp 2013-09-09 21:01:24 +0000
38@@ -18,12 +18,24 @@
39
40 #include "qorganizer-eds-collection-engineid.h"
41
42+
43+
44 QOrganizerEDSCollectionEngineId::QOrganizerEDSCollectionEngineId(ESource *source,
45 const QString &managerUri)
46 : m_managerUri(managerUri), m_esource(source)
47 {
48 g_object_ref(m_esource);
49 m_collectionId = QString::fromUtf8(e_source_get_uid(m_esource));
50+ if (e_source_has_extension(m_esource, E_SOURCE_EXTENSION_CALENDAR)) {
51+ m_sourceType = E_CAL_CLIENT_SOURCE_TYPE_EVENTS;
52+ } else if (e_source_has_extension(m_esource, E_SOURCE_EXTENSION_TASK_LIST)) {
53+ m_sourceType = E_CAL_CLIENT_SOURCE_TYPE_TASKS;
54+ } else if (e_source_has_extension(m_esource, E_SOURCE_EXTENSION_MEMO_LIST)) {
55+ m_sourceType = E_CAL_CLIENT_SOURCE_TYPE_MEMOS;
56+ } else {
57+ qWarning() << "Source extension not supported";
58+ Q_ASSERT(false);
59+ }
60 }
61
62 QOrganizerEDSCollectionEngineId::QOrganizerEDSCollectionEngineId()
63
64=== modified file 'qorganizer/qorganizer-eds-collection-engineid.h'
65--- qorganizer/qorganizer-eds-collection-engineid.h 2013-08-14 21:23:01 +0000
66+++ qorganizer/qorganizer-eds-collection-engineid.h 2013-09-09 21:01:24 +0000
67@@ -22,6 +22,7 @@
68 #include <QtOrganizer/QOrganizerCollectionEngineId>
69
70 #include <libedataserver/libedataserver.h>
71+#include <libecal/libecal.h>
72
73 class QOrganizerEDSCollectionEngineId : public QtOrganizer::QOrganizerCollectionEngineId
74 {
75@@ -39,6 +40,7 @@
76
77 QString toString() const;
78
79+
80 uint hash() const;
81
82 #ifndef QT_NO_DEBUG_STREAM
83@@ -49,6 +51,7 @@
84 QString m_collectionId;
85 QString m_managerUri;
86 ESource *m_esource;
87+ ECalClientSourceType m_sourceType;
88
89 QOrganizerEDSCollectionEngineId(ESource *source, const QString &managerUri);
90
91
92=== modified file 'qorganizer/qorganizer-eds-engine.cpp'
93--- qorganizer/qorganizer-eds-engine.cpp 2013-08-16 02:22:42 +0000
94+++ qorganizer/qorganizer-eds-engine.cpp 2013-09-09 21:01:24 +0000
95@@ -23,11 +23,14 @@
96 #include "qorganizer-eds-fetchrequestdata.h"
97 #include "qorganizer-eds-saverequestdata.h"
98 #include "qorganizer-eds-removerequestdata.h"
99+#include "qorganizer-eds-savecollectionrequestdata.h"
100+#include "qorganizer-eds-removecollectionrequestdata.h"
101
102 #include <QtCore/qdebug.h>
103 #include <QtCore/QPointer>
104 #include <QtCore/qstringbuilder.h>
105 #include <QtCore/quuid.h>
106+#include <QtCore/QCoreApplication>
107
108 #include <QtOrganizer/QOrganizerEventAttendee>
109 #include <QtOrganizer/QOrganizerItemLocation>
110@@ -36,11 +39,18 @@
111 #include <QtOrganizer/QOrganizerItemSaveRequest>
112 #include <QtOrganizer/QOrganizerItemRemoveRequest>
113 #include <QtOrganizer/QOrganizerCollectionFetchRequest>
114+#include <QtOrganizer/QOrganizerCollectionSaveRequest>
115+#include <QtOrganizer/QOrganizerCollectionRemoveRequest>
116 #include <QtOrganizer/QOrganizerEvent>
117 #include <QtOrganizer/QOrganizerTodo>
118 #include <QtOrganizer/QOrganizerTodoTime>
119 #include <QtOrganizer/QOrganizerJournal>
120 #include <QtOrganizer/QOrganizerJournalTime>
121+#include <QtOrganizer/QOrganizerItemIdFetchRequest>
122+#include <QtOrganizer/QOrganizerItemIdFilter>
123+#include <QtOrganizer/QOrganizerItemReminder>
124+#include <QtOrganizer/QOrganizerItemAudibleReminder>
125+#include <QtOrganizer/QOrganizerItemVisualReminder>
126
127 #include <glib.h>
128 #include <libecal/libecal.h>
129@@ -95,7 +105,7 @@
130 QOrganizerEDSCollectionEngineId *collection = data->nextCollection();
131 if (collection) {
132 e_cal_client_connect(collection->m_esource,
133- E_CAL_CLIENT_SOURCE_TYPE_EVENTS,
134+ collection->m_sourceType,
135 data->cancellable(),
136 (GAsyncReadyCallback) QOrganizerEDSEngine::itemsAsyncConnected,
137 data);
138@@ -115,7 +125,7 @@
139 EClient *client = e_cal_client_connect_finish(res, &gError);
140
141 if (gError) {
142- qWarning() << "Fail to open calendar" << gError->message;
143+ qWarning() << "Fail to open calendar:" << gError->message;
144 g_error_free(gError);
145 gError = 0;
146 data->finish(QOrganizerManager::InvalidCollectionError);
147@@ -150,26 +160,36 @@
148 delete data;
149 return;
150 } else {
151- qDebug() << "Query size:" << g_slist_length(events);
152 data->appendResults(parseEvents(data->collection(), events));
153 }
154 itemsAsyncStart(data);
155 }
156
157-
158-
159 QList<QOrganizerItem> QOrganizerEDSEngine::items(const QList<QOrganizerItemId> &itemIds,
160 const QOrganizerItemFetchHint &fetchHint,
161 QMap<int, QOrganizerManager::Error> *errorMap,
162 QOrganizerManager::Error *error)
163 {
164 qDebug() << Q_FUNC_INFO;
165- Q_UNUSED(fetchHint)
166- Q_UNUSED(itemIds);
167- Q_UNUSED(errorMap);
168-
169- QList<QOrganizerItem> items;
170- return items;
171+ QOrganizerItemIdFilter filter;
172+ filter.setIds(itemIds);
173+
174+ QOrganizerItemFetchRequest *req = new QOrganizerItemFetchRequest(this);
175+ req->setFilter(filter);
176+ req->setFetchHint(fetchHint);
177+
178+ startRequest(req);
179+ waitForRequestFinished(req, -1);
180+
181+ if (error) {
182+ *error = req->error();
183+ }
184+ // TODO implement correct reply for errorMap
185+ if (errorMap) {
186+ *errorMap = QMap<int, QOrganizerManager::Error>();
187+ }
188+ req->deleteLater();
189+ return req->items();
190 }
191
192 QList<QOrganizerItem> QOrganizerEDSEngine::items(const QOrganizerItemFilter &filter,
193@@ -181,12 +201,25 @@
194 QOrganizerManager::Error *error)
195 {
196 qDebug() << Q_FUNC_INFO;
197- QList<QOrganizerItem> list;
198- return list;
199+
200+ QOrganizerItemFetchRequest *req = new QOrganizerItemFetchRequest(this);
201+ req->setFilter(filter);
202+ req->setStartDate(startDateTime);
203+ req->setEndDate(endDateTime);
204+ req->setMaxCount(maxCount);
205+ req->setSorting(sortOrders);
206+ req->setFetchHint(fetchHint);
207+
208+ startRequest(req);
209+ waitForRequestFinished(req, -1);
210+
211+ if (error) {
212+ *error = req->error();
213+ }
214+ req->deleteLater();
215+ return req->items();
216 }
217
218-
219-
220 QList<QOrganizerItemId> QOrganizerEDSEngine::itemIds(const QOrganizerItemFilter &filter,
221 const QDateTime &startDateTime,
222 const QDateTime &endDateTime,
223@@ -224,6 +257,7 @@
224 {
225 qDebug() << Q_FUNC_INFO;
226 if (req->items().count() == 0) {
227+ qWarning() << "Items count is " << req->items().count();
228 QOrganizerManagerEngine::updateItemSaveRequest(req,
229 QList<QOrganizerItem>(),
230 QOrganizerManager::NoError,
231@@ -248,7 +282,7 @@
232
233 SaveRequestData *data = new SaveRequestData(this, req, collectionId);
234 e_cal_client_connect(collectionEngineId->m_esource,
235- E_CAL_CLIENT_SOURCE_TYPE_EVENTS,
236+ collectionEngineId->m_sourceType,
237 data->cancellable(),
238 (GAsyncReadyCallback) QOrganizerEDSEngine::saveItemsAsyncConnected,
239 data);
240@@ -258,6 +292,7 @@
241 GAsyncResult *res,
242 SaveRequestData *data)
243 {
244+ qDebug() << Q_FUNC_INFO;
245 Q_UNUSED(source_object);
246
247 GError *gError = 0;
248@@ -271,7 +306,7 @@
249 } else {
250 data->setClient(client);
251
252- GSList *comps = parseItems(data->request<QOrganizerItemSaveRequest>()->items());
253+ GSList *comps = parseItems(data->client(), data->request<QOrganizerItemSaveRequest>()->items());
254 if (comps) {
255 if (data->isNew()) {
256 e_cal_client_create_objects(E_CAL_CLIENT(client),
257@@ -300,6 +335,7 @@
258 GAsyncResult *res,
259 SaveRequestData *data)
260 {
261+ qDebug() << Q_FUNC_INFO;
262 Q_UNUSED(source_object);
263
264 GError *gError = 0;
265@@ -324,6 +360,7 @@
266 GAsyncResult *res,
267 SaveRequestData *data)
268 {
269+ qDebug() << Q_FUNC_INFO;
270 Q_UNUSED(source_object);
271
272 GError *gError = 0;
273@@ -334,7 +371,7 @@
274 &gError);
275
276 if (gError) {
277- qWarning() << "Fail to create items" << gError->message;
278+ qWarning() << "Fail to create items:" << gError->message;
279 g_error_free(gError);
280 gError = 0;
281 data->finish(QOrganizerManager::InvalidDetailError);
282@@ -367,7 +404,24 @@
283
284 {
285 qDebug() << Q_FUNC_INFO;
286- *error = QOrganizerManager::NoError;
287+
288+ QOrganizerItemSaveRequest *req = new QOrganizerItemSaveRequest(this);
289+ req->setItems(*items);
290+ req->setDetailMask(detailMask);
291+
292+ startRequest(req);
293+ waitForRequestFinished(req, -1);
294+
295+ *errorMap = req->errorMap();
296+ *error = req->error();
297+
298+ if (*error == QOrganizerManager::NoError) {
299+ *items = req->items();
300+ return true;
301+ } else {
302+ return false;
303+ }
304+
305 return true;
306 }
307
308@@ -392,9 +446,8 @@
309 QOrganizerCollectionId collection = data->begin();
310 if (!collection.isNull()) {
311 QOrganizerEDSCollectionEngineId *collectionEngineId = data->parent()->m_collectionsMap[collection.toString()];
312- qDebug() << "REmove items from sourcE: " << e_source_get_display_name(collectionEngineId->m_esource);
313 e_cal_client_connect(collectionEngineId->m_esource,
314- E_CAL_CLIENT_SOURCE_TYPE_EVENTS,
315+ collectionEngineId->m_sourceType,
316 data->cancellable(),
317 (GAsyncReadyCallback) QOrganizerEDSEngine::removeItemsAsyncConnected,
318 data);
319@@ -447,7 +500,6 @@
320 data->finish(QOrganizerManager::InvalidCollectionError);
321 delete data;
322 } else {
323- qDebug() << "Item removed";
324 data->commit();
325 removeItemsAsyncStart(data);
326 }
327@@ -479,23 +531,164 @@
328 QList<QOrganizerCollection> QOrganizerEDSEngine::collections(QOrganizerManager::Error* error)
329 {
330 qDebug() << Q_FUNC_INFO;
331- *error = QOrganizerManager::NoError;
332- return m_collections;
333+
334+ QOrganizerCollectionFetchRequest *req = new QOrganizerCollectionFetchRequest(this);
335+
336+ startRequest(req);
337+ waitForRequestFinished(req, -1);
338+
339+ *error = req->error();
340+
341+ if (*error == QOrganizerManager::NoError) {
342+ return req->collections();
343+ } else {
344+ return QList<QOrganizerCollection>();
345+ }
346 }
347
348 bool QOrganizerEDSEngine::saveCollection(QOrganizerCollection* collection, QOrganizerManager::Error* error)
349 {
350 qDebug() << Q_FUNC_INFO;
351- *error = QOrganizerManager::NoError;
352- return true;
353-
354+ QOrganizerCollectionSaveRequest *req = new QOrganizerCollectionSaveRequest(this);
355+ req->setCollection(*collection);
356+
357+ startRequest(req);
358+ waitForRequestFinished(req, -1);
359+
360+ *error = req->error();
361+ if ((*error == QOrganizerManager::NoError) &&
362+ (req->collections().count())) {
363+ *collection = req->collections()[0];
364+ return true;
365+ } else {
366+ return false;
367+ }
368+}
369+
370+void QOrganizerEDSEngine::saveCollectionAsync(QOrganizerCollectionSaveRequest *req)
371+{
372+ qDebug() << Q_FUNC_INFO;
373+
374+ if (req->collections().count() == 0) {
375+ QOrganizerManagerEngine::updateCollectionSaveRequest(req,
376+ QList<QOrganizerCollection>(),
377+ QOrganizerManager::NoError,
378+ QMap<int, QOrganizerManager::Error>(),
379+ QOrganizerAbstractRequest::FinishedState);
380+ return;
381+ }
382+
383+ GError *gError = 0;
384+ ESourceRegistry *registry = e_source_registry_new_sync(0, &gError);
385+ if (gError) {
386+ qWarning() << "Fail to create sourge registry:" << gError->message;
387+ g_error_free(gError);
388+ QOrganizerManagerEngine::updateCollectionSaveRequest(req,
389+ QList<QOrganizerCollection>(),
390+ QOrganizerManager::UnspecifiedError,
391+ QMap<int, QOrganizerManager::Error>(),
392+ QOrganizerAbstractRequest::FinishedState);
393+ return;
394+ }
395+ SaveCollectionRequestData *requestData = new SaveCollectionRequestData(this, req);
396+ saveCollectionAsyncStart(registry, requestData);
397+}
398+
399+void QOrganizerEDSEngine::saveCollectionAsyncStart(ESourceRegistry *registry, SaveCollectionRequestData *data)
400+{
401+ qDebug() << Q_FUNC_INFO;
402+
403+ ESource *source = data->begin();
404+ if (source) {
405+ e_source_registry_commit_source(registry,
406+ source,
407+ data->cancellable(),
408+ (GAsyncReadyCallback) QOrganizerEDSEngine::saveCollectionAsyncCommited,
409+ data);
410+ } else {
411+ data->finish();
412+ delete data;
413+ }
414+}
415+
416+void QOrganizerEDSEngine::saveCollectionAsyncCommited(GObject *source_object,
417+ GAsyncResult *res,
418+ SaveCollectionRequestData *data)
419+{
420+ qDebug() << Q_FUNC_INFO;
421+ GError *gError = 0;
422+ e_source_registry_commit_source_finish(E_SOURCE_REGISTRY(source_object), res, &gError);
423+ if (gError) {
424+ qWarning() << "Fail to commit source:" << gError->message;
425+ g_error_free(gError);
426+ data->commit(QOrganizerManager::InvalidCollectionError);
427+ } else {
428+ data->commit();
429+ }
430+
431+ saveCollectionAsyncStart(E_SOURCE_REGISTRY(source_object), data);
432 }
433
434 bool QOrganizerEDSEngine::removeCollection(const QOrganizerCollectionId& collectionId, QOrganizerManager::Error* error)
435 {
436 qDebug() << Q_FUNC_INFO;
437- *error = QOrganizerManager::NoError;
438- return true;
439+
440+ QOrganizerCollectionRemoveRequest *req = new QOrganizerCollectionRemoveRequest(this);
441+ req->setCollectionId(collectionId);
442+
443+ startRequest(req);
444+ waitForRequestFinished(req, -1);
445+
446+ *error = req->error();
447+ return(*error == QOrganizerManager::NoError);
448+}
449+
450+void QOrganizerEDSEngine::removeCollectionAsync(QtOrganizer::QOrganizerCollectionRemoveRequest *req)
451+{
452+ qDebug() << Q_FUNC_INFO;
453+
454+ if (req->collectionIds().count() == 0) {
455+ QOrganizerManagerEngine::updateCollectionRemoveRequest(req,
456+ QOrganizerManager::NoError,
457+ QMap<int, QOrganizerManager::Error>(),
458+ QOrganizerAbstractRequest::FinishedState);
459+ return;
460+ }
461+
462+ RemoveCollectionRequestData *requestData = new RemoveCollectionRequestData(this, req);
463+ removeCollectionAsyncStart(0, 0, requestData);
464+}
465+
466+void QOrganizerEDSEngine::removeCollectionAsyncStart(GObject *source_object,
467+ GAsyncResult *res,
468+ RemoveCollectionRequestData *data)
469+{
470+ if (source_object && res) {
471+ GError *gError = 0;
472+ e_source_remove_finish(E_SOURCE(source_object), res, &gError);
473+ if (gError) {
474+ qWarning() << "Fail to remove collection" << gError->message;
475+ g_error_free(gError);
476+ data->commit(QOrganizerManager::InvalidCollectionError);
477+ } else {
478+ data->commit();
479+ }
480+ }
481+
482+ ESource *source = data->begin();
483+ if (source) {
484+ if (e_source_get_removable(source)) {
485+ e_source_remove(source, data->cancellable(),
486+ (GAsyncReadyCallback) QOrganizerEDSEngine::removeCollectionAsyncStart,
487+ data);
488+ } else {
489+ qWarning() << "Source not removable";
490+ data->commit(QOrganizerManager::InvalidCollectionError);
491+ }
492+ } else {
493+ data->finish();
494+ delete data;
495+ }
496 }
497
498 void QOrganizerEDSEngine::requestDestroyed(QOrganizerAbstractRequest* req)
499@@ -511,7 +704,7 @@
500 if (!req)
501 return false;
502
503-
504+ updateRequestState(req, QOrganizerAbstractRequest::ActiveState);
505 switch (req->type())
506 {
507 case QOrganizerAbstractRequest::ItemFetchRequest:
508@@ -529,7 +722,14 @@
509 case QOrganizerAbstractRequest::ItemRemoveRequest:
510 removeItemsAsync(qobject_cast<QOrganizerItemRemoveRequest*>(req));
511 break;
512+ case QOrganizerAbstractRequest::CollectionSaveRequest:
513+ saveCollectionAsync(qobject_cast<QOrganizerCollectionSaveRequest*>(req));
514+ break;
515+ case QOrganizerAbstractRequest::CollectionRemoveRequest:
516+ removeCollectionAsync(qobject_cast<QOrganizerCollectionRemoveRequest*>(req));
517+ break;
518 default:
519+ updateRequestState(req, QOrganizerAbstractRequest::FinishedState);
520 qDebug() << "No implemented request" << req->type();
521 break;
522 }
523@@ -540,16 +740,20 @@
524 bool QOrganizerEDSEngine::cancelRequest(QOrganizerAbstractRequest* req)
525 {
526 qDebug() << Q_FUNC_INFO;
527- Q_UNUSED(req); // we can't cancel since we complete immediately
528+ Q_UNUSED(req);
529+ //TODO
530+ Q_ASSERT(false);
531 return false;
532 }
533
534 bool QOrganizerEDSEngine::waitForRequestFinished(QOrganizerAbstractRequest* req, int msecs)
535 {
536 qDebug() << Q_FUNC_INFO;
537- // in our implementation, we always complete any operation we start.
538 Q_UNUSED(msecs);
539- Q_UNUSED(req);
540+
541+ while(req->state() == QOrganizerAbstractRequest::ActiveState) {
542+ QCoreApplication::processEvents();
543+ }
544
545 return true;
546 }
547@@ -641,6 +845,23 @@
548 << QOrganizerItemType::TypeTodoOccurrence;
549 }
550
551+void QOrganizerEDSEngine::registerCollection(const QOrganizerCollection &collection, QOrganizerEDSCollectionEngineId *edsId)
552+{
553+ m_collections << collection;
554+ m_collectionsMap.insert(collection.id().toString(), edsId);
555+}
556+
557+void QOrganizerEDSEngine::unregisterCollection(const QOrganizerCollectionId &collectionId)
558+{
559+ Q_FOREACH(QOrganizerCollection col, m_collections) {
560+ if (col.id() == collectionId) {
561+ m_collections.removeAll(col);
562+ }
563+ }
564+
565+ m_collectionsMap.remove(collectionId.toString());
566+}
567+
568 void QOrganizerEDSEngine::loadCollections()
569 {
570 m_collections.clear();
571@@ -655,21 +876,24 @@
572 }
573
574 ESource *defaultSource = e_source_registry_ref_default_address_book(registry);
575- GList *sources = e_source_registry_list_sources(registry, E_SOURCE_EXTENSION_CALENDAR);
576+ GList *sources = e_source_registry_list_sources(registry, 0);
577 for(int i=0, iMax=g_list_length(sources); i < iMax; i++) {
578 ESource *source = E_SOURCE(g_list_nth_data(sources, i));
579- QOrganizerCollection collection;
580- QOrganizerEDSCollectionEngineId *edsId = new QOrganizerEDSCollectionEngineId(source, managerUri());
581- QOrganizerCollectionId id(edsId);
582- collection.setId(id);
583- collection.setMetaData(QOrganizerCollection::KeyName,
584- QString::fromUtf8(e_source_get_display_name(source)));
585- //TODO get metadata (color, etc..)
586- m_collections << collection;
587- m_collectionsMap.insert(id.toString(), edsId);
588-
589- if (e_source_compare_by_display_name(source, defaultSource) == 0) {
590- m_defaultCollection = collection;
591+
592+ if (e_source_has_extension(source, E_SOURCE_EXTENSION_CALENDAR) ||
593+ e_source_has_extension(source, E_SOURCE_EXTENSION_TASK_LIST) ||
594+ e_source_has_extension(source, E_SOURCE_EXTENSION_MEMO_LIST))
595+ {
596+ //TODO get metadata (color, etc..)
597+ QOrganizerEDSCollectionEngineId *edsId = 0;
598+ QOrganizerCollection collection = parseSource(source, managerUri(), &edsId);
599+
600+ registerCollection(collection, edsId);
601+
602+ if (e_source_compare_by_display_name(source, defaultSource) == 0) {
603+ qDebug() << "Default Source" << e_source_get_display_name(source);
604+ m_defaultCollection = collection;
605+ }
606 }
607 }
608
609@@ -681,35 +905,117 @@
610 qDebug() << m_collections.count() << "Collection loaded";
611 }
612
613+ESource *QOrganizerEDSEngine::findSource(const QtOrganizer::QOrganizerCollectionId &id) const
614+{
615+ if (!id.isNull() && m_collectionsMap.contains(id.toString())) {
616+ QOrganizerEDSCollectionEngineId *edsId = m_collectionsMap[id.toString()];
617+ Q_ASSERT(edsId);
618+ return edsId->m_esource;
619+ } else {
620+ return 0;
621+ }
622+}
623+
624+QOrganizerCollection QOrganizerEDSEngine::parseSource(ESource *source,
625+ const QString &managerUri,
626+ QOrganizerEDSCollectionEngineId **edsId)
627+{
628+ *edsId = new QOrganizerEDSCollectionEngineId(source, managerUri);
629+ QOrganizerCollectionId id(*edsId);
630+ QOrganizerCollection collection;
631+
632+ collection.setId(id);
633+ collection.setMetaData(QOrganizerCollection::KeyName,
634+ QString::fromUtf8(e_source_get_display_name(source)));
635+
636+ return collection;
637+}
638+
639+QOrganizerCollection QOrganizerEDSEngine::parseSource(ESource *source, const QString &managerUri)
640+{
641+ QOrganizerEDSCollectionEngineId *edsId = 0;
642+ return parseSource(source, managerUri, &edsId);
643+}
644+
645 QDateTime QOrganizerEDSEngine::fromIcalTime(struct icaltimetype value)
646 {
647- struct tm tmTime = icaltimetype_to_tm(&value);
648- g_date_time_new_from_unix_local(mktime(&tmTime));
649- return QDateTime::fromTime_t(mktime(&tmTime));
650+ uint tmTime = icaltime_as_timet(value);
651+ return QDateTime::fromTime_t(tmTime);
652 }
653
654 void QOrganizerEDSEngine::parseStartTime(ECalComponent *comp, QOrganizerItem *item)
655 {
656- ECalComponentDateTime dt;
657- e_cal_component_get_dtstart(comp, &dt);
658- if (dt.value) {
659+ ECalComponentDateTime *dt = g_new0(ECalComponentDateTime, 1);
660+ e_cal_component_get_dtstart(comp, dt);
661+ if (dt->value) {
662 QOrganizerEventTime etr = item->detail(QOrganizerItemDetail::TypeEventTime);
663- etr.setStartDateTime(fromIcalTime(*dt.value));
664+ etr.setStartDateTime(fromIcalTime(*dt->value));
665 item->saveDetail(&etr);
666 }
667- e_cal_component_free_datetime(&dt);
668+ e_cal_component_free_datetime(dt);
669 }
670
671 void QOrganizerEDSEngine::parseEndTime(ECalComponent *comp, QOrganizerItem *item)
672 {
673- ECalComponentDateTime dt;
674- e_cal_component_get_dtend(comp, &dt);
675- if (dt.value) {
676+ ECalComponentDateTime *dt = g_new0(ECalComponentDateTime, 1);
677+ e_cal_component_get_dtend(comp, dt);
678+ if (dt->value) {
679 QOrganizerEventTime etr = item->detail(QOrganizerItemDetail::TypeEventTime);
680- etr.setEndDateTime(fromIcalTime(*dt.value));
681+ etr.setEndDateTime(fromIcalTime(*dt->value));
682 item->saveDetail(&etr);
683 }
684- e_cal_component_free_datetime(&dt);
685+ e_cal_component_free_datetime(dt);
686+}
687+
688+void QOrganizerEDSEngine::parseWeekRecurrence(struct icalrecurrencetype *rule, QtOrganizer::QOrganizerRecurrenceRule *qRule)
689+{
690+ qRule->setFrequency(QOrganizerRecurrenceRule::Weekly);
691+
692+ QSet<Qt::DayOfWeek> daysOfWeek;
693+ for (int d=0; d < Qt::Sunday; d++) {
694+ short day = rule->by_day[d];
695+ if (day != ICAL_RECURRENCE_ARRAY_MAX) {
696+ daysOfWeek.insert(static_cast<Qt::DayOfWeek>(icalrecurrencetype_day_day_of_week(rule->by_day[d]) - 1));
697+ }
698+ }
699+ qRule->setDaysOfWeek(daysOfWeek);
700+}
701+
702+void QOrganizerEDSEngine::parseMonthRecurrence(struct icalrecurrencetype *rule, QtOrganizer::QOrganizerRecurrenceRule *qRule)
703+{
704+ qRule->setFrequency(QOrganizerRecurrenceRule::Monthly);
705+
706+ QSet<int> daysOfMonth;
707+ for (int d=0; d < ICAL_BY_MONTHDAY_SIZE; d++) {
708+ short day = rule->by_month_day[d];
709+ if (day != ICAL_RECURRENCE_ARRAY_MAX) {
710+ daysOfMonth.insert(day);
711+ }
712+ }
713+ qRule->setDaysOfMonth(daysOfMonth);
714+}
715+
716+void QOrganizerEDSEngine::parseYearRecurrence(struct icalrecurrencetype *rule, QtOrganizer::QOrganizerRecurrenceRule *qRule)
717+{
718+ qRule->setFrequency(QOrganizerRecurrenceRule::Yearly);
719+
720+ QSet<int> daysOfYear;
721+ for (int d=0; d < ICAL_BY_YEARDAY_SIZE; d++) {
722+ short day = rule->by_year_day[d];
723+ if (day != ICAL_RECURRENCE_ARRAY_MAX) {
724+ daysOfYear.insert(day);
725+ }
726+ }
727+ qRule->setDaysOfYear(daysOfYear);
728+
729+ QSet<QOrganizerRecurrenceRule::Month> monthOfYear;
730+ for (int d=0; d < ICAL_BY_MONTH_SIZE; d++) {
731+ short month = rule->by_month[d];
732+ if (month != ICAL_RECURRENCE_ARRAY_MAX) {
733+ monthOfYear.insert(static_cast<QOrganizerRecurrenceRule::Month>(month));
734+ }
735+ }
736+ qRule->setMonthsOfYear(monthOfYear);
737 }
738
739 void QOrganizerEDSEngine::parseRecurrence(ECalComponent *comp, QOrganizerItem *item)
740@@ -735,6 +1041,7 @@
741 if (e_cal_component_has_exdates(comp)) {
742 QSet<QDate> dates;
743 GSList *exdateList = 0;
744+
745 e_cal_component_get_exdate_list(comp, &exdateList);
746 for(GSList *i = exdateList; i != 0; i = i->next) {
747 ECalComponentDateTime* dateTime = (ECalComponentDateTime*) i->data;
748@@ -748,6 +1055,69 @@
749 item->saveDetail(&irec);
750 }
751
752+ // rules
753+ GSList *ruleList = 0;
754+ e_cal_component_get_rrule_list(comp, &ruleList);
755+ if (ruleList) {
756+ QSet<QOrganizerRecurrenceRule> qRules;
757+
758+ for(GSList *i = ruleList; i != 0; i = i->next) {
759+ struct icalrecurrencetype *rule = (struct icalrecurrencetype*) i->data;
760+ QOrganizerRecurrenceRule qRule;
761+ switch (rule->freq) {
762+ case ICAL_SECONDLY_RECURRENCE:
763+ case ICAL_MINUTELY_RECURRENCE:
764+ case ICAL_HOURLY_RECURRENCE:
765+ qWarning() << "Recurrence frequency not supported";
766+ break;
767+ case ICAL_DAILY_RECURRENCE:
768+ qRule.setFrequency(QOrganizerRecurrenceRule::Daily);
769+ break;
770+ case ICAL_WEEKLY_RECURRENCE:
771+ parseWeekRecurrence(rule, &qRule);
772+ break;
773+ case ICAL_MONTHLY_RECURRENCE:
774+ parseMonthRecurrence(rule, &qRule);
775+ break;
776+ case ICAL_YEARLY_RECURRENCE:
777+ parseYearRecurrence(rule, &qRule);
778+ break;
779+ case ICAL_NO_RECURRENCE:
780+ break;
781+ }
782+
783+
784+ if (rule->count > 0) {
785+ qRule.setLimit(rule->count);
786+ } else {
787+ QDateTime dt = fromIcalTime(rule->until);
788+ if (dt.isValid()) {
789+ qRule.setLimit(dt.date());
790+ } else {
791+ qRule.clearLimit();
792+ }
793+ }
794+ qRule.setInterval(rule->interval);
795+
796+ QSet<int> positions;
797+ for (int d=0; d < ICAL_BY_SETPOS_SIZE; d++) {
798+ short day = rule->by_set_pos[d];
799+ if (day != ICAL_RECURRENCE_ARRAY_MAX) {
800+ positions.insert(day);
801+ }
802+ }
803+ qRule.setPositions(positions);
804+
805+ qRules << qRule;
806+ }
807+
808+ if (!qRules.isEmpty()) {
809+ QOrganizerItemRecurrence irec = item->detail(QOrganizerItemDetail::TypeRecurrence);
810+ irec.setRecurrenceRules(qRules);
811+ item->saveDetail(&irec);
812+ }
813+ }
814+ // TODO: free ruleList;
815 // TODO: exeptions rules
816 }
817
818@@ -866,6 +1236,143 @@
819 return journal;
820 }
821
822+void QOrganizerEDSEngine::parseSummary(ECalComponent *comp, QtOrganizer::QOrganizerItem *item)
823+{
824+ ECalComponentText summary;
825+ e_cal_component_get_summary(comp, &summary);
826+ if (summary.value) {
827+ item->setDisplayLabel(QString::fromUtf8(summary.value));
828+ }
829+}
830+
831+void QOrganizerEDSEngine::parseDescription(ECalComponent *comp, QtOrganizer::QOrganizerItem *item)
832+{
833+
834+ GSList *descriptions = 0;
835+ e_cal_component_get_description_list(comp, &descriptions);
836+
837+ QStringList itemDescription;
838+
839+ for(GSList *descList = descriptions; descList != 0; descList = descList->next) {
840+ ECalComponentText *description = static_cast<ECalComponentText*>(descList->data);
841+ if (description) {
842+ itemDescription.append(QString::fromUtf8(description->value));
843+ }
844+ }
845+
846+ item->setDescription(itemDescription.join("\n"));
847+}
848+
849+void QOrganizerEDSEngine::parseComments(ECalComponent *comp, QtOrganizer::QOrganizerItem *item)
850+{
851+ GSList *comments = 0;
852+ e_cal_component_get_comment_list(comp, &comments);
853+ for(int ci=0, ciMax=g_slist_length(comments); ci < ciMax; ci++) {
854+ ECalComponentText *txt = static_cast<ECalComponentText*>(g_slist_nth_data(comments, ci));
855+ item->addComment(QString::fromUtf8(txt->value));
856+ }
857+ e_cal_component_free_text_list(comments);
858+}
859+
860+void QOrganizerEDSEngine::parseTags(ECalComponent *comp, QtOrganizer::QOrganizerItem *item)
861+{
862+ GSList *categories = 0;
863+ e_cal_component_get_categories_list(comp, &categories);
864+ for(GSList *tag=categories; tag != 0; tag = tag->next) {
865+ item->addTag(QString::fromUtf8(static_cast<gchar*>(tag->data)));
866+ }
867+ e_cal_component_free_categories_list(categories);
868+}
869+
870+QByteArray QOrganizerEDSEngine::dencodeAttachment(ECalComponentAlarm *alarm)
871+{
872+ QByteArray attachment;
873+
874+ icalattach *attach = 0;
875+ e_cal_component_alarm_get_attach(alarm, &attach);
876+ if (attach) {
877+ attachment = QByteArray::fromBase64(icalattach_get_url(attach));
878+ icalattach_unref(attach);
879+ }
880+
881+ return attachment;
882+}
883+
884+
885+void QOrganizerEDSEngine::parseVisualReminderAttachment(ECalComponentAlarm *alarm, QOrganizerItemReminder *aDetail)
886+{
887+ QByteArray attach = dencodeAttachment(alarm);
888+ if (!attach.isEmpty()) {
889+ QUrl url;
890+ QString txt;
891+
892+ QDataStream attachStream(&attach, QIODevice::ReadOnly);
893+
894+ attachStream >> url;
895+ attachStream >> txt;
896+
897+ aDetail->setValue(QOrganizerItemVisualReminder::FieldDataUrl, QVariant(url));
898+ aDetail->setValue(QOrganizerItemVisualReminder::FieldMessage, QVariant(txt));
899+ }
900+}
901+
902+
903+void QOrganizerEDSEngine::parseAudibleReminderAttachment(ECalComponentAlarm *alarm, QOrganizerItemReminder *aDetail)
904+{
905+ QByteArray attach = dencodeAttachment(alarm);
906+ if (!attach.isEmpty()) {
907+ QUrl url;
908+
909+ QDataStream attachStream(&attach, QIODevice::ReadOnly);
910+
911+ attachStream >> url;
912+
913+ aDetail->setValue(QOrganizerItemAudibleReminder::FieldDataUrl, QVariant(url));
914+ }
915+}
916+
917+void QOrganizerEDSEngine::parseReminders(ECalComponent *comp, QtOrganizer::QOrganizerItem *item)
918+{
919+ GList *alarms = e_cal_component_get_alarm_uids(comp);
920+ for(GList *a = alarms; a != 0; a = a->next) {
921+ QOrganizerItemReminder *aDetail = 0;
922+
923+ ECalComponentAlarm *alarm = e_cal_component_get_alarm(comp, static_cast<const gchar*>(a->data));
924+ if (!alarm) {
925+ continue;
926+ }
927+ ECalComponentAlarmAction aAction;
928+
929+ e_cal_component_alarm_get_action(alarm, &aAction);
930+ switch(aAction)
931+ {
932+ case E_CAL_COMPONENT_ALARM_DISPLAY:
933+ aDetail = new QOrganizerItemVisualReminder();
934+ parseVisualReminderAttachment(alarm, aDetail);
935+ break;
936+ case E_CAL_COMPONENT_ALARM_AUDIO:
937+ // use audio as fallback
938+ default:
939+ aDetail = new QOrganizerItemAudibleReminder();
940+ parseAudibleReminderAttachment(alarm, aDetail);
941+ break;
942+ }
943+
944+ ECalComponentAlarmTrigger trigger;
945+ e_cal_component_alarm_get_trigger(alarm, &trigger);
946+ if (trigger.type == E_CAL_COMPONENT_ALARM_TRIGGER_RELATIVE_START) {
947+ aDetail->setSecondsBeforeStart(icaldurationtype_as_int(trigger.u.rel_duration) * -1);
948+ }
949+
950+ ECalComponentAlarmRepeat aRepeat;
951+ e_cal_component_alarm_get_repeat(alarm, &aRepeat);
952+ aDetail->setRepetition(aRepeat.repetitions, icaldurationtype_as_int(aRepeat.duration));
953+
954+ item->saveDetail(aDetail);
955+ delete aDetail;
956+ }
957+}
958+
959 QList<QOrganizerItem> QOrganizerEDSEngine::parseEvents(QOrganizerEDSCollectionEngineId *collection, GSList *events)
960 {
961 QList<QOrganizerItem> items;
962@@ -905,32 +1412,11 @@
963 collection->managerUri());
964 item->setId(QOrganizerItemId(eid));
965 item->setCollectionId(cId);
966- qDebug() << ">>>>>>>>>>>>>>>>>>Loaded item id: " << item->id().toString();
967-
968- //summary
969- ECalComponentText summary;
970- e_cal_component_get_summary(comp, &summary);
971- if (summary.value) {
972- item->setDisplayLabel(QString::fromUtf8(summary.value));
973- }
974-
975- //comments
976- GSList *comments = 0;
977- e_cal_component_get_comment_list(comp, &comments);
978- for(int ci=0, ciMax=g_slist_length(comments); ci < ciMax; ci++) {
979- ECalComponentText *txt = static_cast<ECalComponentText*>(g_slist_nth_data(comments, ci));
980- item->addComment(QString::fromUtf8(txt->value));
981- }
982- e_cal_component_free_text_list(comments);
983-
984- //tags
985- GSList *categories = 0;
986- e_cal_component_get_categories_list(comp, &categories);
987- for(int ci=0, ciMax=g_slist_length(comments); ci < ciMax; ci++) {
988- item->addTag(QString::fromUtf8(static_cast<gchar*>(g_slist_nth_data(categories, ci))));
989- }
990- e_cal_component_free_categories_list(categories);
991-
992+ parseDescription(comp, item);
993+ parseSummary(comp, item);
994+ parseComments(comp, item);
995+ parseTags(comp, item);
996+ parseReminders(comp, item);
997
998 // //Attendee
999 // GList *attendeeList = 0;
1000@@ -958,10 +1444,12 @@
1001 {
1002 QOrganizerEventTime etr = item.detail(QOrganizerItemDetail::TypeEventTime);
1003 if (!etr.isEmpty()) {
1004- ECalComponentDateTime dt;
1005- struct icaltimetype itt = icaltime_from_timet(etr.startDateTime().toTime_t(), FALSE);
1006- dt.value = &itt;
1007- e_cal_component_set_dtstart(comp, &dt);
1008+ ECalComponentDateTime *dt = g_new0(ECalComponentDateTime, 1);
1009+ dt->value = g_new0(struct icaltimetype, 1);
1010+ *dt->value = icaltime_from_timet(etr.startDateTime().toTime_t(), FALSE);
1011+
1012+ e_cal_component_set_dtstart(comp, dt);
1013+ e_cal_component_free_datetime(dt);
1014 }
1015 }
1016
1017@@ -969,12 +1457,98 @@
1018 {
1019 QOrganizerEventTime etr = item.detail(QOrganizerItemDetail::TypeEventTime);
1020 if (!etr.isEmpty()) {
1021- ECalComponentDateTime dt;
1022- struct icaltimetype itt = icaltime_from_timet(etr.endDateTime().toTime_t(), FALSE);
1023- dt.value = &itt;
1024- e_cal_component_set_dtend(comp, &dt);;
1025- }
1026-}
1027+ ECalComponentDateTime *dt = g_new0(ECalComponentDateTime, 1);
1028+ dt->value = g_new0(struct icaltimetype, 1);
1029+ *dt->value = icaltime_from_timet(etr.endDateTime().toTime_t(), FALSE);
1030+ e_cal_component_set_dtend(comp, dt);
1031+ e_cal_component_free_datetime(dt);
1032+ }
1033+}
1034+
1035+void QOrganizerEDSEngine::parseTodoStartTime(const QOrganizerItem &item, ECalComponent *comp)
1036+{
1037+ QOrganizerTodoTime etr = item.detail(QOrganizerItemDetail::TypeTodoTime);
1038+ if (!etr.isEmpty()) {
1039+ ECalComponentDateTime *dt = g_new0(ECalComponentDateTime, 1);
1040+ dt->value = g_new0(struct icaltimetype, 1);
1041+ *dt->value = icaltime_from_timet(etr.startDateTime().toTime_t(), FALSE);
1042+
1043+ e_cal_component_set_dtstart(comp, dt);
1044+ e_cal_component_free_datetime(dt);
1045+ }
1046+}
1047+
1048+void QOrganizerEDSEngine::parseWeekRecurrence(const QOrganizerRecurrenceRule &qRule, struct icalrecurrencetype *rule)
1049+{
1050+ static QMap<Qt::DayOfWeek, icalrecurrencetype_weekday> daysOfWeekMap;
1051+ if (daysOfWeekMap.isEmpty()) {
1052+ daysOfWeekMap.insert(Qt::Monday, ICAL_MONDAY_WEEKDAY);
1053+ daysOfWeekMap.insert(Qt::Thursday, ICAL_THURSDAY_WEEKDAY);
1054+ daysOfWeekMap.insert(Qt::Wednesday, ICAL_WEDNESDAY_WEEKDAY);
1055+ daysOfWeekMap.insert(Qt::Tuesday, ICAL_TUESDAY_WEEKDAY);
1056+ daysOfWeekMap.insert(Qt::Friday, ICAL_FRIDAY_WEEKDAY);
1057+ daysOfWeekMap.insert(Qt::Saturday, ICAL_SATURDAY_WEEKDAY);
1058+ daysOfWeekMap.insert(Qt::Sunday, ICAL_SUNDAY_WEEKDAY);
1059+ }
1060+
1061+ QList<Qt::DayOfWeek> daysOfWeek = qRule.daysOfWeek().toList();
1062+ int c = 0;
1063+
1064+ rule->freq = ICAL_WEEKLY_RECURRENCE;
1065+ for(int d=Qt::Monday; d <= Qt::Sunday; d++) {
1066+ if (daysOfWeek.contains(static_cast<Qt::DayOfWeek>(d))) {
1067+ rule->by_day[c++] = daysOfWeekMap[static_cast<Qt::DayOfWeek>(d)];
1068+ }
1069+ }
1070+ for (int d = c; d < ICAL_BY_DAY_SIZE; d++) {
1071+ rule->by_day[d] = ICAL_RECURRENCE_ARRAY_MAX;
1072+ }
1073+}
1074+
1075+void QOrganizerEDSEngine::parseMonthRecurrence(const QOrganizerRecurrenceRule &qRule, struct icalrecurrencetype *rule)
1076+{
1077+ rule->freq = ICAL_MONTHLY_RECURRENCE;
1078+
1079+ QList<int> daysOfMonth = qRule.daysOfMonth().toList();
1080+ int c = 0;
1081+ for (int d=1; d < ICAL_BY_MONTHDAY_SIZE; d++) {
1082+ if (daysOfMonth.contains(d)) {
1083+ rule->by_month_day[c++] = d;
1084+ }
1085+ }
1086+ for (int d = c; d < ICAL_BY_MONTHDAY_SIZE; d++) {
1087+ rule->by_month_day[d] = ICAL_RECURRENCE_ARRAY_MAX;
1088+ }
1089+}
1090+
1091+void QOrganizerEDSEngine::parseYearRecurrence(const QOrganizerRecurrenceRule &qRule, struct icalrecurrencetype *rule)
1092+{
1093+ rule->freq = ICAL_YEARLY_RECURRENCE;
1094+
1095+ QList<int> daysOfYear = qRule.daysOfYear().toList();
1096+ int c = 0;
1097+ for (int d=1; d < ICAL_BY_YEARDAY_SIZE; d++) {
1098+ if (daysOfYear.contains(d)) {
1099+ rule->by_year_day[c++] = d;
1100+ }
1101+ }
1102+ for (int d = c; d < ICAL_BY_YEARDAY_SIZE; d++) {
1103+ rule->by_year_day[d] = ICAL_RECURRENCE_ARRAY_MAX;
1104+ }
1105+
1106+ c = 0;
1107+ QList<QOrganizerRecurrenceRule::Month> monthOfYear = qRule.monthsOfYear().toList();
1108+ for (int d=1; d < ICAL_BY_MONTH_SIZE; d++) {
1109+ if (monthOfYear.contains(static_cast<QOrganizerRecurrenceRule::Month>(d))) {
1110+ rule->by_month[c++] = d;
1111+ }
1112+ }
1113+ for (int d = c; d < ICAL_BY_YEARDAY_SIZE; d++) {
1114+ rule->by_month[d] = ICAL_RECURRENCE_ARRAY_MAX;
1115+ }
1116+}
1117+
1118+
1119
1120 void QOrganizerEDSEngine::parseRecurrence(const QOrganizerItem &item, ECalComponent *comp)
1121 {
1122@@ -983,7 +1557,7 @@
1123 GSList *periodList = 0;
1124 Q_FOREACH(QDate dt, rec.recurrenceDates()) {
1125 ECalComponentPeriod *period = g_new0(ECalComponentPeriod, 1);
1126- period->start = icaltime_from_timet(QDateTime(dt).toTime_t(), TRUE);
1127+ period->start = icaltime_from_timet(QDateTime(dt).toTime_t(), FALSE);
1128 periodList = g_slist_append(periodList, period);
1129 //TODO: period.end, period.duration
1130 }
1131@@ -992,15 +1566,58 @@
1132
1133 GSList *exdateList = 0;
1134 Q_FOREACH(QDate dt, rec.exceptionDates()) {
1135- ECalComponentDateTime dateTime;
1136- struct icaltimetype itt = icaltime_from_timet(QDateTime(dt).toTime_t(), TRUE);
1137- dateTime.value = &itt;
1138- exdateList = g_slist_append(exdateList, &dateTime);
1139+ ECalComponentDateTime *dateTime = g_new0(ECalComponentDateTime, 1);
1140+ struct icaltimetype *itt = g_new0(struct icaltimetype, 1);
1141+ *itt = icaltime_from_timet(QDateTime(dt).toTime_t(), FALSE);
1142+ dateTime->value = itt;
1143+ exdateList = g_slist_append(exdateList, dateTime);
1144 }
1145 e_cal_component_set_exdate_list(comp, exdateList);
1146 e_cal_component_free_exdate_list(exdateList);
1147+
1148+ GSList *ruleList = 0;
1149+ Q_FOREACH(QOrganizerRecurrenceRule qRule, rec.recurrenceRules()) {
1150+ struct icalrecurrencetype *rule = g_new0(struct icalrecurrencetype, 1);
1151+ switch(qRule.frequency()) {
1152+ case QOrganizerRecurrenceRule::Daily:
1153+ rule->freq = ICAL_DAILY_RECURRENCE;
1154+ break;
1155+ case QOrganizerRecurrenceRule::Weekly:
1156+ parseWeekRecurrence(qRule, rule);
1157+ break;
1158+ case QOrganizerRecurrenceRule::Monthly:
1159+ parseMonthRecurrence(qRule, rule);
1160+ break;
1161+ case QOrganizerRecurrenceRule::Yearly:
1162+ parseYearRecurrence(qRule, rule);
1163+ break;
1164+ case QOrganizerRecurrenceRule::Invalid:
1165+ rule->freq = ICAL_NO_RECURRENCE;
1166+ break;
1167+ }
1168+
1169+ if (qRule.limitDate().isValid()) {
1170+ rule->until = icaltime_from_timet(QDateTime(qRule.limitDate()).toTime_t(), TRUE);
1171+ rule->count = ICAL_RECURRENCE_ARRAY_MAX;
1172+ } else {
1173+ rule->count = qRule.limitCount();
1174+ }
1175+
1176+ QSet<int> positions = qRule.positions();
1177+ for (int d=1; d < ICAL_BY_SETPOS_SIZE; d++) {
1178+ if (positions.contains(d)) {
1179+ rule->by_set_pos[d] = d;
1180+ } else {
1181+ rule->by_set_pos[d] = ICAL_RECURRENCE_ARRAY_MAX;
1182+ }
1183+ }
1184+
1185+ rule->interval = qRule.interval();
1186+ ruleList = g_slist_append(ruleList, rule);
1187+ }
1188+ e_cal_component_set_rrule_list(comp, ruleList);
1189+ //TODO: free ruleList
1190 }
1191- // TODO: exeptions rules
1192 }
1193
1194 void QOrganizerEDSEngine::parsePriority(const QOrganizerItem &item, ECalComponent *comp)
1195@@ -1008,6 +1625,7 @@
1196 QOrganizerItemPriority priority = item.detail(QOrganizerItemDetail::TypePriority);
1197 if (!priority.isEmpty()) {
1198 gint iPriority = (gint) priority.priority();
1199+ qDebug() << "Priority" << iPriority;
1200 e_cal_component_set_priority(comp, &iPriority);
1201 }
1202 }
1203@@ -1024,10 +1642,14 @@
1204 {
1205 QOrganizerTodoTime ttr = item.detail(QOrganizerItemDetail::TypeTodoTime);
1206 if (!ttr.isEmpty()) {
1207- ECalComponentDateTime due;
1208+ qDebug() << "Due date" << ttr.dueDateTime();
1209+ ECalComponentDateTime *due = g_new0(ECalComponentDateTime, 1);
1210+ due->value = g_new0(struct icaltimetype, 1);
1211+
1212 struct icaltimetype itt = icaltime_from_timet(ttr.dueDateTime().toTime_t(), FALSE);
1213- due.value = &itt;
1214- e_cal_component_set_due(comp, &due);
1215+ *due->value = itt;
1216+ e_cal_component_set_due(comp, due);
1217+ e_cal_component_free_datetime(due);
1218 }
1219 }
1220
1221@@ -1035,6 +1657,7 @@
1222 {
1223 QOrganizerTodoProgress tp = item.detail(QOrganizerItemDetail::TypeTodoProgress);
1224 if (!tp.isEmpty()) {
1225+ qDebug() << "Progress" << tp.percentageComplete();
1226 e_cal_component_set_percent_as_int(comp, tp.percentageComplete());
1227 }
1228 }
1229@@ -1048,22 +1671,45 @@
1230 e_cal_component_set_status(comp, ICAL_STATUS_NONE);
1231 break;
1232 case QOrganizerTodoProgress::StatusInProgress:
1233+ qDebug() << "Set status in progress";
1234 e_cal_component_set_status(comp, ICAL_STATUS_INPROCESS);
1235 break;
1236 case QOrganizerTodoProgress::StatusComplete:
1237 e_cal_component_set_status(comp, ICAL_STATUS_COMPLETED);
1238 break;
1239 default:
1240+ qDebug() << "Set status cancelled";
1241 e_cal_component_set_status(comp, ICAL_STATUS_CANCELLED);
1242 break;
1243 }
1244 }
1245 }
1246
1247-ECalComponent *QOrganizerEDSEngine::parseEventItem(const QOrganizerItem &item)
1248-{
1249- ECalComponent *comp = e_cal_component_new();
1250- e_cal_component_set_new_vtype(comp, E_CAL_COMPONENT_EVENT);
1251+ECalComponent *QOrganizerEDSEngine::createDefaultComponent(ECalClient *client,
1252+ icalcomponent_kind iKind,
1253+ ECalComponentVType eType)
1254+{
1255+ ECalComponent *comp;
1256+ icalcomponent *icalcomp = 0;
1257+
1258+ if (client && !e_cal_client_get_default_object_sync(client, &icalcomp, NULL, NULL)) {
1259+ icalcomp = icalcomponent_new(iKind);
1260+ }
1261+
1262+ comp = e_cal_component_new();
1263+ if (icalcomp && !e_cal_component_set_icalcomponent(comp, icalcomp)) {
1264+ icalcomponent_free(icalcomp);
1265+ }
1266+
1267+ e_cal_component_set_new_vtype(comp, eType);
1268+
1269+ return comp;
1270+}
1271+
1272+ECalComponent *QOrganizerEDSEngine::parseEventItem(ECalClient *client, const QOrganizerItem &item)
1273+{
1274+ qDebug() << Q_FUNC_INFO;
1275+ ECalComponent *comp = createDefaultComponent(client, ICAL_VEVENT_COMPONENT, E_CAL_COMPONENT_EVENT);
1276
1277 parseStartTime(item, comp);
1278 parseEndTime(item, comp);
1279@@ -1074,12 +1720,12 @@
1280
1281 }
1282
1283-ECalComponent *QOrganizerEDSEngine::parseTodoItem(const QOrganizerItem &item)
1284+ECalComponent *QOrganizerEDSEngine::parseTodoItem(ECalClient *client, const QOrganizerItem &item)
1285 {
1286- ECalComponent *comp = e_cal_component_new();
1287- e_cal_component_set_new_vtype(comp, E_CAL_COMPONENT_TODO);
1288+ qDebug() << Q_FUNC_INFO;
1289+ ECalComponent *comp = createDefaultComponent(client, ICAL_VTODO_COMPONENT, E_CAL_COMPONENT_TODO);
1290
1291- parseStartTime(item, comp);
1292+ parseTodoStartTime(item, comp);
1293 parseDueDate(item, comp);
1294 parseRecurrence(item, comp);
1295 parsePriority(item, comp);
1296@@ -1089,10 +1735,10 @@
1297 return comp;
1298 }
1299
1300-ECalComponent *QOrganizerEDSEngine::parseJournalItem(const QOrganizerItem &item)
1301+ECalComponent *QOrganizerEDSEngine::parseJournalItem(ECalClient *client, const QOrganizerItem &item)
1302 {
1303- ECalComponent *comp = e_cal_component_new();
1304- e_cal_component_set_new_vtype(comp, E_CAL_COMPONENT_JOURNAL);
1305+ qDebug() << Q_FUNC_INFO;
1306+ ECalComponent *comp = createDefaultComponent(client, ICAL_VJOURNAL_COMPONENT, E_CAL_COMPONENT_JOURNAL);
1307
1308 QOrganizerJournalTime jtime = item.detail(QOrganizerItemDetail::TypeJournalTime);
1309 if (!jtime.isEmpty()) {
1310@@ -1105,7 +1751,147 @@
1311 return comp;
1312 }
1313
1314-GSList *QOrganizerEDSEngine::parseItems(QList<QOrganizerItem> items)
1315+void QOrganizerEDSEngine::parseSummary(const QOrganizerItem &item, ECalComponent *comp)
1316+{
1317+ //summary
1318+ if (!item.displayLabel().isEmpty()) {
1319+ ECalComponentText txt;
1320+ QByteArray str = item.displayLabel().toUtf8();
1321+ txt.altrep = 0;
1322+ txt.value = str.constData();
1323+ e_cal_component_set_summary(comp, &txt);
1324+ }
1325+}
1326+
1327+void QOrganizerEDSEngine::parseDescription(const QOrganizerItem &item, ECalComponent *comp)
1328+{
1329+ //description
1330+ if (item.description().isEmpty()) {
1331+ GSList *descriptions = 0;
1332+ QByteArray str = item.description().toUtf8();
1333+ ECalComponentText *txt = g_new0(ECalComponentText, 1);
1334+
1335+ txt->value = str.constData();
1336+ descriptions = g_slist_append(descriptions, txt);
1337+
1338+ e_cal_component_set_description_list(comp, descriptions);
1339+ e_cal_component_free_text_list(descriptions);
1340+ }
1341+}
1342+
1343+void QOrganizerEDSEngine::parseComments(const QOrganizerItem &item, ECalComponent *comp)
1344+{
1345+ //comments
1346+ GSList *comments = 0;
1347+ Q_FOREACH(QString comment, item.comments()) {
1348+ QByteArray str = comment.toUtf8();
1349+ ECalComponentText *txt = g_new0(ECalComponentText, 1);
1350+ txt->value = str.constData();
1351+ comments = g_slist_append(comments, txt);
1352+ }
1353+
1354+ if (comments) {
1355+ e_cal_component_set_comment_list(comp, comments);
1356+ e_cal_component_free_text_list(comments);
1357+ }
1358+}
1359+
1360+void QOrganizerEDSEngine::parseTags(const QOrganizerItem &item, ECalComponent *comp)
1361+{
1362+ //tags
1363+ GSList *categories = 0;
1364+ Q_FOREACH(QString tag, item.tags()) {
1365+ QByteArray str = tag.toUtf8();
1366+ ECalComponentText *txt = g_new0(ECalComponentText, 1);
1367+ txt->value = str.constData();
1368+ categories = g_slist_append(categories, txt);
1369+ }
1370+
1371+ if (categories) {
1372+ e_cal_component_set_categories_list(comp, categories);
1373+ e_cal_component_free_text_list(categories);
1374+ }
1375+}
1376+
1377+void QOrganizerEDSEngine::encodeAttachment(QByteArray data, ECalComponentAlarm *alarm)
1378+{
1379+ gchar *b64Bytes = strdup(data.toBase64());
1380+ icalattach *attach = icalattach_new_from_url(b64Bytes);
1381+
1382+ e_cal_component_alarm_set_attach(alarm, attach);
1383+
1384+ icalattach_unref(attach);
1385+}
1386+
1387+void QOrganizerEDSEngine::parseVisualReminderAttachment(const QOrganizerItemDetail &detail, ECalComponentAlarm *alarm)
1388+{
1389+ QByteArray attachBytes;
1390+
1391+ {
1392+ QDataStream attachData(&attachBytes, QIODevice::WriteOnly);
1393+
1394+ attachData << detail.value(QOrganizerItemVisualReminder::FieldDataUrl).toUrl();
1395+ attachData << detail.value(QOrganizerItemVisualReminder::FieldMessage).toString();
1396+ }
1397+
1398+ encodeAttachment(attachBytes, alarm);
1399+}
1400+
1401+void QOrganizerEDSEngine::parseAudibleReminderAttachment(const QOrganizerItemDetail &detail, ECalComponentAlarm *alarm)
1402+{
1403+ QByteArray attachBytes;
1404+
1405+ {
1406+ QDataStream attachData(&attachBytes, QIODevice::WriteOnly);
1407+ attachData << detail.value(QOrganizerItemAudibleReminder::FieldDataUrl).toUrl();
1408+ }
1409+
1410+ encodeAttachment(attachBytes, alarm);
1411+}
1412+
1413+void QOrganizerEDSEngine::parseReminders(const QOrganizerItem &item, ECalComponent *comp)
1414+{
1415+ //reminders
1416+ QList<QOrganizerItemDetail> reminders = item.details(QOrganizerItemDetail::TypeAudibleReminder);
1417+ reminders += item.details(QOrganizerItemDetail::TypeVisualReminder);
1418+
1419+ Q_FOREACH(const QOrganizerItemDetail &detail, reminders) {
1420+ const QOrganizerItemReminder *reminder = static_cast<const QOrganizerItemReminder*>(&detail);
1421+
1422+ ECalComponentAlarm *alarm = e_cal_component_alarm_new();
1423+ switch(reminder->type())
1424+ {
1425+ case QOrganizerItemReminder::TypeVisualReminder:
1426+ e_cal_component_alarm_set_action(alarm, E_CAL_COMPONENT_ALARM_DISPLAY);
1427+ parseVisualReminderAttachment(detail, alarm);
1428+ break;
1429+ case QOrganizerItemReminder::TypeAudibleReminder:
1430+ default:
1431+ // use audio as fallback
1432+ e_cal_component_alarm_set_action(alarm, E_CAL_COMPONENT_ALARM_AUDIO);
1433+ parseAudibleReminderAttachment(detail, alarm);
1434+ break;
1435+ }
1436+
1437+ if (reminder->secondsBeforeStart() > 0) {
1438+ ECalComponentAlarmTrigger trigger;
1439+ trigger.type = E_CAL_COMPONENT_ALARM_TRIGGER_RELATIVE_START;
1440+ trigger.u.rel_duration = icaldurationtype_from_int(- reminder->secondsBeforeStart());
1441+ e_cal_component_alarm_set_trigger(alarm, trigger);
1442+ }
1443+
1444+ ECalComponentAlarmRepeat aRepeat;
1445+ // TODO: check if this is really necessary
1446+ aRepeat.repetitions = reminder->repetitionCount(); //qMax(reminder->repetitionCount(), 1);
1447+ aRepeat.duration = icaldurationtype_from_int(reminder->repetitionDelay());
1448+ e_cal_component_alarm_set_repeat(alarm, aRepeat);
1449+
1450+ e_cal_component_add_alarm(comp, alarm);
1451+ e_cal_component_alarm_free(alarm);
1452+ }
1453+}
1454+
1455+GSList *QOrganizerEDSEngine::parseItems(ECalClient *client, QList<QOrganizerItem> items)
1456 {
1457 GSList *comps = 0;
1458
1459@@ -1114,13 +1900,13 @@
1460
1461 switch(item.type()) {
1462 case QOrganizerItemType::TypeEvent:
1463- comp = parseEventItem(item);
1464+ comp = parseEventItem(client, item);
1465 break;
1466 case QOrganizerItemType::TypeTodo:
1467- comp = parseTodoItem(item);
1468+ comp = parseTodoItem(client, item);
1469 break;
1470 case QOrganizerItemType::TypeJournal:
1471- comp = parseJournalItem(item);
1472+ comp = parseJournalItem(client, item);
1473 break;
1474 case QOrganizerItemType::TypeEventOccurrence:
1475 qWarning() << "Component TypeEventOccurrence not supported;";
1476@@ -1136,41 +1922,26 @@
1477
1478 // id
1479 if (!item.id().isNull()) {
1480- QOrganizerItemId id = item.id();
1481- QString cId = QOrganizerEDSEngineId::toComponentId(id);
1482- e_cal_component_set_uid(comp, cId.toUtf8().data());
1483- }
1484-
1485- //summary
1486- if (!item.displayLabel().isEmpty()) {
1487- ECalComponentText txt;
1488- txt.altrep = "";
1489- txt.value = item.displayLabel().toUtf8().data();
1490- e_cal_component_set_summary(comp, &txt);
1491- }
1492-
1493- //comments
1494- GSList *comments = 0;
1495- Q_FOREACH(QString comment, item.comments()) {
1496- ECalComponentText *txt = g_new0(ECalComponentText, 1);
1497- txt->value = comment.toUtf8().data();
1498- comments = g_slist_append(comments, txt);
1499- }
1500- e_cal_component_set_comment_list(comp, comments);
1501- e_cal_component_free_text_list(comments);
1502-
1503- //tags
1504- GSList *categories = 0;
1505- Q_FOREACH(QString tag, item.tags()) {
1506- ECalComponentText *txt = g_new0(ECalComponentText, 1);
1507- txt->value = tag.toUtf8().data();
1508- categories = g_slist_append(categories, txt);
1509- }
1510- e_cal_component_set_categories_list(comp, categories);
1511- e_cal_component_free_text_list(categories);
1512+ QOrganizerItemId id = item.id();
1513+ QString cId = QOrganizerEDSEngineId::toComponentId(id);
1514+ e_cal_component_set_uid(comp, cId.toUtf8().data());
1515+ }
1516+
1517+ parseSummary(item, comp);
1518+ parseDescription(item, comp);
1519+ parseComments(item, comp);
1520+ parseTags(item, comp);
1521+ parseReminders(item, comp);
1522+
1523+ if (!item.id().isNull()) {
1524+ e_cal_component_commit_sequence(comp);
1525+ } else {
1526+ e_cal_component_abort_sequence(comp);
1527+ }
1528
1529 comps = g_slist_append(comps,
1530 icalcomponent_new_clone(e_cal_component_get_icalcomponent(comp)));
1531+
1532 g_object_unref(comp);
1533 }
1534
1535
1536=== modified file 'qorganizer/qorganizer-eds-engine.h'
1537--- qorganizer/qorganizer-eds-engine.h 2013-08-16 02:22:42 +0000
1538+++ qorganizer/qorganizer-eds-engine.h 2013-09-09 21:01:24 +0000
1539@@ -29,11 +29,15 @@
1540 #include <QtOrganizer/QOrganizerItemFilter>
1541 #include <QtOrganizer/QOrganizerItemChangeSet>
1542 #include <QtOrganizer/QOrganizerCollectionId>
1543+#include <QtOrganizer/QOrganizerItemReminder>
1544
1545 #include <libecal/libecal.h>
1546+
1547 class FetchRequestData;
1548 class SaveRequestData;
1549 class RemoveRequestData;
1550+class SaveCollectionRequestData;
1551+class RemoveCollectionRequestData;
1552
1553 class QOrganizerEDSEngine : public QtOrganizer::QOrganizerManagerEngine
1554 {
1555@@ -135,36 +139,68 @@
1556 QList<FetchRequestData*> m_pendingFetchRequest;
1557
1558 void loadCollections();
1559+ void registerCollection(const QtOrganizer::QOrganizerCollection &collection, QOrganizerEDSCollectionEngineId *edsId);
1560+ void unregisterCollection(const QtOrganizer::QOrganizerCollectionId &collectionId);
1561+
1562+ ESource *findSource(const QtOrganizer::QOrganizerCollectionId &id) const;
1563+
1564+ static QtOrganizer::QOrganizerCollection parseSource(ESource *source, const QString &managerUri);
1565+ static QtOrganizer::QOrganizerCollection parseSource(ESource *source, const QString &managerUri, QOrganizerEDSCollectionEngineId **edsId);
1566 static QList<QtOrganizer::QOrganizerItem> parseEvents(QOrganizerEDSCollectionEngineId *collection, GSList *events);
1567- static GSList *parseItems(QList<QtOrganizer::QOrganizerItem> items);
1568-
1569- static QDateTime fromIcalTime(struct icaltimetype value);
1570+ static GSList *parseItems(ECalClient *client, QList<QtOrganizer::QOrganizerItem> items);
1571+
1572+ // QOrganizerItem -> ECalComponent
1573+ static void parseSummary(const QtOrganizer::QOrganizerItem &item, ECalComponent *comp);
1574+ static void parseDescription(const QtOrganizer::QOrganizerItem &item, ECalComponent *comp);
1575+ static void parseComments(const QtOrganizer::QOrganizerItem &item, ECalComponent *comp);
1576+ static void parseTags(const QtOrganizer::QOrganizerItem &item, ECalComponent *comp);
1577+ static void parseReminders(const QtOrganizer::QOrganizerItem &item, ECalComponent *comp);
1578+ static void encodeAttachment(QByteArray data, ECalComponentAlarm *alarm);
1579+ static void parseVisualReminderAttachment(const QtOrganizer::QOrganizerItemDetail &detail, ECalComponentAlarm *alarm);
1580+ static void parseAudibleReminderAttachment(const QtOrganizer::QOrganizerItemDetail &detail, ECalComponentAlarm *alarm);
1581+ static void parseStartTime(const QtOrganizer::QOrganizerItem &item, ECalComponent *comp);
1582+ static void parseEndTime(const QtOrganizer::QOrganizerItem &item, ECalComponent *comp);
1583+ static void parseTodoStartTime(const QtOrganizer::QOrganizerItem &item, ECalComponent *comp);
1584+ static void parseRecurrence(const QtOrganizer::QOrganizerItem &item, ECalComponent *comp);
1585+ static void parseWeekRecurrence(const QtOrganizer::QOrganizerRecurrenceRule &qRule, struct icalrecurrencetype *rule);
1586+ static void parseMonthRecurrence(const QtOrganizer::QOrganizerRecurrenceRule &qRule, struct icalrecurrencetype *rule);
1587+ static void parseYearRecurrence(const QtOrganizer::QOrganizerRecurrenceRule &qRule, struct icalrecurrencetype *rule);
1588+ static void parsePriority(const QtOrganizer::QOrganizerItem &item, ECalComponent *comp);
1589+ static void parseLocation(const QtOrganizer::QOrganizerItem &item, ECalComponent *comp);
1590+ static void parseDueDate(const QtOrganizer::QOrganizerItem &item, ECalComponent *comp);
1591+ static void parseProgress(const QtOrganizer::QOrganizerItem &item, ECalComponent *comp);
1592+ static void parseStatus(const QtOrganizer::QOrganizerItem &item, ECalComponent *comp);
1593+
1594+ // ECalComponent -> QOrganizerItem
1595+ static void parseSummary(ECalComponent *comp, QtOrganizer::QOrganizerItem *item);
1596+ static void parseDescription(ECalComponent *comp, QtOrganizer::QOrganizerItem *item);
1597+ static void parseComments(ECalComponent *comp, QtOrganizer::QOrganizerItem *item);
1598+ static void parseTags(ECalComponent *comp, QtOrganizer::QOrganizerItem *item);
1599+ static void parseReminders(ECalComponent *comp, QtOrganizer::QOrganizerItem *item);
1600+ static QByteArray dencodeAttachment(ECalComponentAlarm *alarm);
1601+ static void parseAudibleReminderAttachment(ECalComponentAlarm *alarm, QtOrganizer::QOrganizerItemReminder *aDetail);
1602+ static void parseVisualReminderAttachment(ECalComponentAlarm *alarm, QtOrganizer::QOrganizerItemReminder *aDetail);
1603 static void parseStartTime(ECalComponent *comp, QtOrganizer::QOrganizerItem *item);
1604 static void parseEndTime(ECalComponent *comp, QtOrganizer::QOrganizerItem *item);
1605 static void parseRecurrence(ECalComponent *comp, QtOrganizer::QOrganizerItem *item);
1606+ static void parseWeekRecurrence(struct icalrecurrencetype *rule, QtOrganizer::QOrganizerRecurrenceRule *qRule);
1607+ static void parseMonthRecurrence(struct icalrecurrencetype *rule, QtOrganizer::QOrganizerRecurrenceRule *qRule);
1608+ static void parseYearRecurrence(struct icalrecurrencetype *rule, QtOrganizer::QOrganizerRecurrenceRule *qRule);
1609 static void parsePriority(ECalComponent *comp, QtOrganizer::QOrganizerItem *item);
1610 static void parseLocation(ECalComponent *comp, QtOrganizer::QOrganizerItem *item);
1611 static void parseDueDate(ECalComponent *comp, QtOrganizer::QOrganizerItem *item);
1612 static void parseProgress(ECalComponent *comp, QtOrganizer::QOrganizerItem *item);
1613 static void parseStatus(ECalComponent *comp, QtOrganizer::QOrganizerItem *item);
1614
1615+ static QDateTime fromIcalTime(struct icaltimetype value);
1616 static QtOrganizer::QOrganizerItem *parseEvent(ECalComponent *comp);
1617 static QtOrganizer::QOrganizerItem *parseToDo(ECalComponent *comp);
1618 static QtOrganizer::QOrganizerItem *parseJournal(ECalComponent *comp);
1619
1620-
1621- static void parseStartTime(const QtOrganizer::QOrganizerItem &item, ECalComponent *comp);
1622- static void parseEndTime(const QtOrganizer::QOrganizerItem &item, ECalComponent *comp);
1623- static void parseRecurrence(const QtOrganizer::QOrganizerItem &item, ECalComponent *comp);
1624- static void parsePriority(const QtOrganizer::QOrganizerItem &item, ECalComponent *comp);
1625- static void parseLocation(const QtOrganizer::QOrganizerItem &item, ECalComponent *comp);
1626- static void parseDueDate(const QtOrganizer::QOrganizerItem &item, ECalComponent *comp);
1627- static void parseProgress(const QtOrganizer::QOrganizerItem &item, ECalComponent *comp);
1628- static void parseStatus(const QtOrganizer::QOrganizerItem &item, ECalComponent *comp);
1629-
1630- static ECalComponent *parseEventItem(const QtOrganizer::QOrganizerItem &item);
1631- static ECalComponent *parseTodoItem(const QtOrganizer::QOrganizerItem &item);
1632- static ECalComponent *parseJournalItem(const QtOrganizer::QOrganizerItem &item);
1633+ static ECalComponent *createDefaultComponent(ECalClient *client, icalcomponent_kind iKind, ECalComponentVType eType);
1634+ static ECalComponent *parseEventItem(ECalClient *client, const QtOrganizer::QOrganizerItem &item);
1635+ static ECalComponent *parseTodoItem(ECalClient *client, const QtOrganizer::QOrganizerItem &item);
1636+ static ECalComponent *parseJournalItem(ECalClient *client, const QtOrganizer::QOrganizerItem &item);
1637
1638 // glib callback
1639 void itemsAsync(QtOrganizer::QOrganizerItemFetchRequest *req);
1640@@ -181,6 +217,13 @@
1641 static void removeItemsAsyncStart(RemoveRequestData *data);
1642 static void removeItemsAsyncConnected(GObject *source_object, GAsyncResult *res, RemoveRequestData *data);
1643 static void removeItemsAsyncRemoved(GObject *source_object, GAsyncResult *res, RemoveRequestData *data);
1644+
1645+ void saveCollectionAsync(QtOrganizer::QOrganizerCollectionSaveRequest *req);
1646+ static void saveCollectionAsyncStart(ESourceRegistry *registry, SaveCollectionRequestData *data);
1647+ static void saveCollectionAsyncCommited(GObject *source_object, GAsyncResult *res, SaveCollectionRequestData *data);
1648+
1649+ void removeCollectionAsync(QtOrganizer::QOrganizerCollectionRemoveRequest *req);
1650+ static void removeCollectionAsyncStart(GObject *source_object, GAsyncResult *res, RemoveCollectionRequestData *data);
1651 /*
1652 QList<QtOrganizer::QOrganizerItem> internalItemOccurrences(const QtOrganizer::QOrganizerItem& parentItem,
1653 const QDateTime& periodStart,
1654@@ -200,7 +243,9 @@
1655 bool forExport) const;
1656 QtOrganizer::QOrganizerItem item(const QtOrganizer::QOrganizerItemId& organizeritemId) const;
1657 */
1658- friend class FetchRequestData;
1659+ friend class FetchRequestData;
1660+ friend class SaveCollectionRequestData;
1661+ friend class RemoveCollectionRequestData;
1662 };
1663
1664 #endif
1665
1666=== modified file 'qorganizer/qorganizer-eds-fetchrequestdata.cpp'
1667--- qorganizer/qorganizer-eds-fetchrequestdata.cpp 2013-08-14 21:23:01 +0000
1668+++ qorganizer/qorganizer-eds-fetchrequestdata.cpp 2013-09-09 21:01:24 +0000
1669@@ -60,14 +60,30 @@
1670
1671 void FetchRequestData::appendResults(QList<QOrganizerItem> results)
1672 {
1673- m_results += results;
1674+ QOrganizerItemFetchRequest *req = request<QOrganizerItemFetchRequest>();
1675+ Q_FOREACH(QOrganizerItem item, results) {
1676+ if (QOrganizerManagerEngine::testFilter(req->filter(), item)) {
1677+ m_results << item;
1678+ }
1679+ }
1680 }
1681
1682 QString FetchRequestData::dateFilter()
1683 {
1684+ QDateTime startDate = request<QOrganizerItemFetchRequest>()->startDate();
1685+ QDateTime endDate = request<QOrganizerItemFetchRequest>()->endDate();
1686+
1687+ if (!startDate.isValid()) {
1688+ startDate.setMSecsSinceEpoch(0);
1689+ }
1690+
1691+ if (!endDate.isValid()) {
1692+ endDate.setMSecsSinceEpoch(std::numeric_limits<qint64>::max());
1693+ }
1694+
1695 QString query = QString("(occur-in-time-range? "
1696 "(make-time \"%1\") (make-time \"%2\"))")
1697- .arg(isodate_from_time_t(request<QOrganizerItemFetchRequest>()->startDate().toTime_t()))
1698- .arg(isodate_from_time_t(request<QOrganizerItemFetchRequest>()->endDate().toTime_t()));
1699+ .arg(isodate_from_time_t(startDate.toTime_t()))
1700+ .arg(isodate_from_time_t(endDate.toTime_t()));
1701 return query;
1702 }
1703
1704=== added file 'qorganizer/qorganizer-eds-removecollectionrequestdata.cpp'
1705--- qorganizer/qorganizer-eds-removecollectionrequestdata.cpp 1970-01-01 00:00:00 +0000
1706+++ qorganizer/qorganizer-eds-removecollectionrequestdata.cpp 2013-09-09 21:01:24 +0000
1707@@ -0,0 +1,76 @@
1708+/*
1709+ * Copyright 2013 Canonical Ltd.
1710+ *
1711+ * This file is part of ubuntu-pim-service.
1712+ *
1713+ * contact-service-app is free software; you can redistribute it and/or modify
1714+ * it under the terms of the GNU General Public License as published by
1715+ * the Free Software Foundation; version 3.
1716+ *
1717+ * contact-service-app is distributed in the hope that it will be useful,
1718+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1719+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1720+ * GNU General Public License for more details.
1721+ *
1722+ * You should have received a copy of the GNU General Public License
1723+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1724+ */
1725+
1726+#include "qorganizer-eds-removecollectionrequestdata.h"
1727+#include "qorganizer-eds-engineid.h"
1728+
1729+#include <QtOrganizer/QOrganizerManagerEngine>
1730+#include <QtOrganizer/QOrganizerCollectionRemoveRequest>
1731+
1732+using namespace QtOrganizer;
1733+
1734+RemoveCollectionRequestData::RemoveCollectionRequestData(QOrganizerEDSEngine *engine, QtOrganizer::QOrganizerAbstractRequest *req)
1735+ : RequestData(engine, req),
1736+ m_currentCollection(0)
1737+{
1738+ m_pendingCollections = request<QOrganizerCollectionRemoveRequest>()->collectionIds();
1739+}
1740+
1741+RemoveCollectionRequestData::~RemoveCollectionRequestData()
1742+{
1743+}
1744+
1745+void RemoveCollectionRequestData::finish(QtOrganizer::QOrganizerManager::Error error)
1746+{
1747+ QOrganizerManagerEngine::updateCollectionRemoveRequest(request<QOrganizerCollectionRemoveRequest>(),
1748+ error,
1749+ m_errorMap,
1750+ QOrganizerAbstractRequest::FinishedState);
1751+
1752+ // emit collection removed signal
1753+ QList<QOrganizerCollectionId> removedIds = m_pendingCollections;
1754+ Q_FOREACH(int index, m_errorMap.keys()) {
1755+ removedIds.removeAt(index);
1756+ }
1757+
1758+ // remove source from engine
1759+ Q_FOREACH(QOrganizerCollectionId id, removedIds) {
1760+ parent()->unregisterCollection(id);
1761+ }
1762+
1763+ Q_EMIT parent()->collectionsRemoved(removedIds);
1764+}
1765+
1766+void RemoveCollectionRequestData::commit(QtOrganizer::QOrganizerManager::Error error)
1767+{
1768+ if (error != QOrganizerManager::NoError) {
1769+ m_errorMap.insert(m_currentCollection, error);
1770+ }
1771+
1772+ m_currentCollection++;
1773+}
1774+
1775+ESource *RemoveCollectionRequestData::begin()
1776+{
1777+ if (m_pendingCollections.count() > m_currentCollection) {
1778+ QOrganizerCollectionId cId = m_pendingCollections.at(m_currentCollection);
1779+ return parent()->findSource(cId);
1780+ } else {
1781+ return 0;
1782+ }
1783+}
1784
1785=== added file 'qorganizer/qorganizer-eds-removecollectionrequestdata.h'
1786--- qorganizer/qorganizer-eds-removecollectionrequestdata.h 1970-01-01 00:00:00 +0000
1787+++ qorganizer/qorganizer-eds-removecollectionrequestdata.h 2013-09-09 21:01:24 +0000
1788@@ -0,0 +1,44 @@
1789+/*
1790+ * Copyright 2013 Canonical Ltd.
1791+ *
1792+ * This file is part of ubuntu-pim-service.
1793+ *
1794+ * contact-service-app is free software; you can redistribute it and/or modify
1795+ * it under the terms of the GNU General Public License as published by
1796+ * the Free Software Foundation; version 3.
1797+ *
1798+ * contact-service-app is distributed in the hope that it will be useful,
1799+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1800+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1801+ * GNU General Public License for more details.
1802+ *
1803+ * You should have received a copy of the GNU General Public License
1804+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1805+ */
1806+
1807+#ifndef __QORGANIZER_EDS_REMOVECOLLECTIONQUESTDATA_H__
1808+#define __QORGANIZER_EDS_REMOVECOLLECTIONQUESTDATA_H__
1809+
1810+#include "qorganizer-eds-requestdata.h"
1811+
1812+#include <glib.h>
1813+
1814+class RemoveCollectionRequestData : public RequestData
1815+{
1816+public:
1817+ RemoveCollectionRequestData(QOrganizerEDSEngine *engine, QtOrganizer::QOrganizerAbstractRequest *req);
1818+ ~RemoveCollectionRequestData();
1819+
1820+ void finish(QtOrganizer::QOrganizerManager::Error error = QtOrganizer::QOrganizerManager::NoError);
1821+
1822+ ESource* begin();
1823+ void commit(QtOrganizer::QOrganizerManager::Error error = QtOrganizer::QOrganizerManager::NoError);
1824+
1825+private:
1826+ QList<QtOrganizer::QOrganizerCollectionId> m_pendingCollections;
1827+ QMap<int, QtOrganizer::QOrganizerManager::Error> m_errorMap;
1828+ int m_currentCollection;
1829+
1830+};
1831+
1832+#endif
1833
1834=== modified file 'qorganizer/qorganizer-eds-removerequestdata.cpp'
1835--- qorganizer/qorganizer-eds-removerequestdata.cpp 2013-08-14 21:23:01 +0000
1836+++ qorganizer/qorganizer-eds-removerequestdata.cpp 2013-09-09 21:01:24 +0000
1837@@ -56,7 +56,6 @@
1838 ECalComponentId *id = g_new0(ECalComponentId, 1);
1839
1840 id->uid = g_strdup(QOrganizerEDSEngineId::toComponentId(item.id()).toUtf8().data());
1841- qDebug() << "Remove item:" << id->uid;
1842 ids = g_slist_append(ids, id);
1843
1844 m_pendingItems.removeAll(item);
1845@@ -102,9 +101,7 @@
1846 QSet<QtOrganizer::QOrganizerCollectionId>::const_iterator i = m_pendingCollections.constBegin();
1847 m_pendingCollections.remove(*i);
1848 m_currentCollectionId = *i;
1849- qDebug() << "Will get item for sourcE:" << m_currentCollectionId.isNull() << m_currentCollectionId;
1850 m_currentCompIds = takeItemsIds(m_currentCollectionId);
1851- qDebug() << "DONE Will get item for sourcE:" << m_currentCollectionId.isNull() << m_currentCollectionId;
1852 return m_currentCollectionId;
1853 }
1854 return QOrganizerCollectionId();
1855
1856=== modified file 'qorganizer/qorganizer-eds-requestdata.cpp'
1857--- qorganizer/qorganizer-eds-requestdata.cpp 2013-08-14 21:23:01 +0000
1858+++ qorganizer/qorganizer-eds-requestdata.cpp 2013-09-09 21:01:24 +0000
1859@@ -51,9 +51,9 @@
1860 return !m_req.isNull();
1861 }
1862
1863-EClient *RequestData::client() const
1864+ECalClient *RequestData::client() const
1865 {
1866- return m_client;
1867+ return E_CAL_CLIENT(m_client);
1868 }
1869
1870 QOrganizerEDSEngine *RequestData::parent() const
1871
1872=== modified file 'qorganizer/qorganizer-eds-requestdata.h'
1873--- qorganizer/qorganizer-eds-requestdata.h 2013-08-14 21:23:01 +0000
1874+++ qorganizer/qorganizer-eds-requestdata.h 2013-09-09 21:01:24 +0000
1875@@ -35,7 +35,7 @@
1876 GCancellable* cancellable() const;
1877 bool isLive() const;
1878 void setClient(EClient *client);
1879- EClient *client() const;
1880+ ECalClient *client() const;
1881 virtual void finish(QtOrganizer::QOrganizerManager::Error error = QtOrganizer::QOrganizerManager::NoError) = 0;
1882 QOrganizerEDSEngine *parent() const;
1883 virtual void cancel();
1884
1885=== added file 'qorganizer/qorganizer-eds-savecollectionrequestdata.cpp'
1886--- qorganizer/qorganizer-eds-savecollectionrequestdata.cpp 1970-01-01 00:00:00 +0000
1887+++ qorganizer/qorganizer-eds-savecollectionrequestdata.cpp 2013-09-09 21:01:24 +0000
1888@@ -0,0 +1,139 @@
1889+/*
1890+ * Copyright 2013 Canonical Ltd.
1891+ *
1892+ * This file is part of ubuntu-pim-service.
1893+ *
1894+ * contact-service-app is free software; you can redistribute it and/or modify
1895+ * it under the terms of the GNU General Public License as published by
1896+ * the Free Software Foundation; version 3.
1897+ *
1898+ * contact-service-app is distributed in the hope that it will be useful,
1899+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1900+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1901+ * GNU General Public License for more details.
1902+ *
1903+ * You should have received a copy of the GNU General Public License
1904+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1905+ */
1906+
1907+#include "qorganizer-eds-savecollectionrequestdata.h"
1908+
1909+#include <QtOrganizer/QOrganizerManagerEngine>
1910+#include <QtOrganizer/QOrganizerCollectionSaveRequest>
1911+
1912+using namespace QtOrganizer;
1913+
1914+#define COLLECTION_CALLENDAR_TYPE_METADATA "collection-type"
1915+
1916+SaveCollectionRequestData::SaveCollectionRequestData(QOrganizerEDSEngine *engine,
1917+ QtOrganizer::QOrganizerAbstractRequest *req)
1918+ : RequestData(engine, req),
1919+ m_sources(0),
1920+ m_currentSource(0)
1921+{
1922+ parseCollections();
1923+}
1924+
1925+SaveCollectionRequestData::~SaveCollectionRequestData()
1926+{
1927+}
1928+
1929+
1930+void SaveCollectionRequestData::finish(QtOrganizer::QOrganizerManager::Error error)
1931+{
1932+ qDebug() << "update request collections" << m_results;
1933+
1934+ QOrganizerManagerEngine::updateCollectionSaveRequest(request<QOrganizerCollectionSaveRequest>(),
1935+ m_results,
1936+ error,
1937+ m_errorMap,
1938+ QOrganizerAbstractRequest::FinishedState);
1939+
1940+ QList<QOrganizerCollectionId> added;
1941+ Q_FOREACH(QOrganizerCollection col, m_results) {
1942+ added.append(col.id());
1943+ }
1944+ Q_EMIT parent()->collectionsAdded(added);
1945+}
1946+
1947+void SaveCollectionRequestData::commit(QtOrganizer::QOrganizerManager::Error error)
1948+{
1949+ if (error != QOrganizerManager::NoError) {
1950+ m_errorMap.insert(m_currentSource, error);
1951+ } else {
1952+ ESource *source = E_SOURCE(g_list_nth_data(m_sources, m_currentSource));
1953+ QOrganizerEDSCollectionEngineId *edsId = 0;
1954+
1955+ QOrganizerCollection collection = QOrganizerEDSEngine::parseSource(source, parent()->managerUri(), &edsId);
1956+ parent()->registerCollection(collection, edsId);
1957+
1958+ m_results.append(collection);
1959+ }
1960+ m_currentSource++;
1961+}
1962+
1963+GList *SaveCollectionRequestData::sources() const
1964+{
1965+ return m_sources;
1966+}
1967+
1968+QList<QOrganizerCollection> SaveCollectionRequestData::results() const
1969+{
1970+ return m_results;
1971+}
1972+
1973+void SaveCollectionRequestData::parseCollections()
1974+{
1975+ if (m_sources) {
1976+ g_list_free_full(m_sources, g_object_unref);
1977+ m_sources = 0;
1978+ }
1979+
1980+ m_errorMap.clear();
1981+ int index = 0;
1982+ Q_FOREACH(QOrganizerCollection collection, request<QOrganizerCollectionSaveRequest>()->collections()) {
1983+ ESource *source = 0;
1984+ if (collection.id().isNull()) {
1985+ GError *gError = 0;
1986+ source = e_source_new(0, 0, &gError);
1987+ if (gError) {
1988+ m_errorMap.insert(index, QOrganizerManager::UnspecifiedError);
1989+ qWarning() << "Fail to create source:" << gError->message;
1990+ g_error_free(gError);
1991+ }
1992+ } else {
1993+ qDebug() << "Collection update not implemented";
1994+ Q_ASSERT(FALSE);
1995+ }
1996+
1997+ QString name = collection.metaData(QOrganizerCollection::KeyName).toString();
1998+ e_source_set_display_name(source, name.toUtf8().data());
1999+ e_source_set_parent(source, "local-stub");
2000+
2001+ QVariant callendarType = collection.extendedMetaData(COLLECTION_CALLENDAR_TYPE_METADATA);
2002+ ESourceBackend *extCalendar = 0;
2003+
2004+ if (callendarType.toString() == E_SOURCE_EXTENSION_TASK_LIST) {
2005+ extCalendar = E_SOURCE_BACKEND(e_source_get_extension(source, E_SOURCE_EXTENSION_TASK_LIST));
2006+ } else if (callendarType.toString() == E_SOURCE_EXTENSION_MEMO_LIST) {
2007+ extCalendar = E_SOURCE_BACKEND(e_source_get_extension(source, E_SOURCE_EXTENSION_MEMO_LIST));
2008+ } else {
2009+ extCalendar = E_SOURCE_BACKEND(e_source_get_extension(source, E_SOURCE_EXTENSION_CALENDAR));
2010+ }
2011+
2012+ if (extCalendar) {
2013+ e_source_backend_set_backend_name(extCalendar, "local");
2014+ } else {
2015+ qWarning() << "Fail to get source callendar";
2016+ }
2017+ m_sources = g_list_append(m_sources, source);
2018+ index++;
2019+ }
2020+
2021+ qDebug() << "Request with" << g_list_length(m_sources) << "sources";
2022+}
2023+
2024+ESource *SaveCollectionRequestData::begin() const
2025+{
2026+ return E_SOURCE(g_list_nth_data(m_sources, m_currentSource));
2027+}
2028
2029=== added file 'qorganizer/qorganizer-eds-savecollectionrequestdata.h'
2030--- qorganizer/qorganizer-eds-savecollectionrequestdata.h 1970-01-01 00:00:00 +0000
2031+++ qorganizer/qorganizer-eds-savecollectionrequestdata.h 2013-09-09 21:01:24 +0000
2032@@ -0,0 +1,49 @@
2033+/*
2034+ * Copyright 2013 Canonical Ltd.
2035+ *
2036+ * This file is part of ubuntu-pim-service.
2037+ *
2038+ * contact-service-app is free software; you can redistribute it and/or modify
2039+ * it under the terms of the GNU General Public License as published by
2040+ * the Free Software Foundation; version 3.
2041+ *
2042+ * contact-service-app is distributed in the hope that it will be useful,
2043+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2044+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2045+ * GNU General Public License for more details.
2046+ *
2047+ * You should have received a copy of the GNU General Public License
2048+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2049+ */
2050+
2051+#ifndef __QORGANIZER_EDS_SAVECOLLECTIONREQUESTDATA_H__
2052+#define __QORGANIZER_EDS_SAVECOLLECTIONREQUESTDATA_H__
2053+
2054+#include "qorganizer-eds-requestdata.h"
2055+
2056+class SaveCollectionRequestData : public RequestData
2057+{
2058+public:
2059+ SaveCollectionRequestData(QOrganizerEDSEngine *engine,
2060+ QtOrganizer::QOrganizerAbstractRequest *req);
2061+ ~SaveCollectionRequestData();
2062+
2063+ void finish(QtOrganizer::QOrganizerManager::Error error = QtOrganizer::QOrganizerManager::NoError);
2064+ bool isNew(int index) const;
2065+
2066+ GList *sources() const;
2067+ QList<QtOrganizer::QOrganizerCollection> results() const;
2068+ ESource *begin() const;
2069+ void commit(QtOrganizer::QOrganizerManager::Error error = QtOrganizer::QOrganizerManager::NoError);
2070+
2071+private:
2072+ QMap<int, QtOrganizer::QOrganizerManager::Error> m_errorMap;
2073+ QList<QtOrganizer::QOrganizerCollection> m_results;
2074+ GList *m_sources;
2075+ int m_currentSource;
2076+
2077+ void parseCollections();
2078+
2079+};
2080+
2081+#endif
2082
2083=== modified file 'tests/unittest/CMakeLists.txt'
2084--- tests/unittest/CMakeLists.txt 2013-08-14 21:23:01 +0000
2085+++ tests/unittest/CMakeLists.txt 2013-09-09 21:01:24 +0000
2086@@ -39,3 +39,8 @@
2087 endif()
2088
2089 declare_test(itemid-test)
2090+declare_test(parseecal-test)
2091+# Jenkins will not be able to run these tests because they need EDS running
2092+# FIXME: Mock EDS to run the tests bellow
2093+#declare_test(collections-test)
2094+#declare_test(event-test)
2095
2096=== added file 'tests/unittest/collections-test.cpp'
2097--- tests/unittest/collections-test.cpp 1970-01-01 00:00:00 +0000
2098+++ tests/unittest/collections-test.cpp 2013-09-09 21:01:24 +0000
2099@@ -0,0 +1,191 @@
2100+/*
2101+ * Copyright 2013 Canonical Ltd.
2102+ *
2103+ * This file is part of qtorganizer5-eds.
2104+ *
2105+ * contact-service-app is free software; you can redistribute it and/or modify
2106+ * it under the terms of the GNU General Public License as published by
2107+ * the Free Software Foundation; version 3.
2108+ *
2109+ * contact-service-app is distributed in the hope that it will be useful,
2110+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2111+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2112+ * GNU General Public License for more details.
2113+ *
2114+ * You should have received a copy of the GNU General Public License
2115+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2116+ */
2117+
2118+
2119+#include <QObject>
2120+#include <QtTest>
2121+#include <QDebug>
2122+
2123+#include <QtOrganizer>
2124+
2125+#include "qorganizer-eds-engine.h"
2126+
2127+
2128+using namespace QtOrganizer;
2129+
2130+class CollectionTest : public QObject
2131+{
2132+ Q_OBJECT
2133+private:
2134+ static const QString defaultCollectionName;
2135+ static const QString defaultTaskCollectionName;
2136+ static const QString collectionTypePropertyName;
2137+ static const QString taskListTypeName;
2138+private Q_SLOTS:
2139+ void testCreateCollection()
2140+ {
2141+ QOrganizerEDSEngine *engine = QOrganizerEDSEngine::createEDSEngine(QMap<QString, QString>());
2142+
2143+ QOrganizerCollection collection;
2144+ QtOrganizer::QOrganizerManager::Error error;
2145+ collection.setMetaData(QOrganizerCollection::KeyName, defaultCollectionName);
2146+
2147+ QVERIFY(engine->saveCollection(&collection, &error));
2148+ QCOMPARE(error, QOrganizerManager::NoError);
2149+ QVERIFY(!collection.id().isNull());
2150+ }
2151+
2152+ void testCreateTaskList()
2153+ {
2154+ QOrganizerEDSEngine *engine = QOrganizerEDSEngine::createEDSEngine(QMap<QString, QString>());
2155+
2156+ QOrganizerCollection collection;
2157+ QtOrganizer::QOrganizerManager::Error error;
2158+ collection.setMetaData(QOrganizerCollection::KeyName, defaultTaskCollectionName);
2159+ collection.setExtendedMetaData(collectionTypePropertyName, taskListTypeName);
2160+
2161+ QSignalSpy createdCollection(engine, SIGNAL(collectionsAdded(QList<QOrganizerCollectionId>)));
2162+ QVERIFY(engine->saveCollection(&collection, &error));
2163+ QCOMPARE(error, QOrganizerManager::NoError);
2164+ QVERIFY(!collection.id().isNull());
2165+
2166+ //verify signal
2167+ QCOMPARE(createdCollection.count(), 1);
2168+ QList<QVariant> args = createdCollection.takeFirst();
2169+ QCOMPARE(args.count(), 1);
2170+
2171+ QVERIFY(engine->collections(&error).contains(collection));
2172+ delete engine;
2173+
2174+ // recreate and check if the new collection is listed
2175+ engine = QOrganizerEDSEngine::createEDSEngine(QMap<QString, QString>());
2176+ QVERIFY(engine->collections(&error).contains(collection));
2177+ }
2178+
2179+ void testCreateTask()
2180+ {
2181+ static QString displayLabelValue = QStringLiteral("Todo test");
2182+ static QString descriptionValue = QStringLiteral("Todo description");
2183+
2184+ QOrganizerEDSEngine *engine = QOrganizerEDSEngine::createEDSEngine(QMap<QString, QString>());
2185+
2186+ QOrganizerCollection collection;
2187+ QtOrganizer::QOrganizerManager::Error error;
2188+ collection.setMetaData(QOrganizerCollection::KeyName, defaultTaskCollectionName + "2");
2189+ collection.setExtendedMetaData(collectionTypePropertyName, taskListTypeName);
2190+ QVERIFY(engine->saveCollection(&collection, &error));
2191+
2192+ QOrganizerTodo todo;
2193+ todo.setCollectionId(collection.id());
2194+ todo.setStartDateTime(QDateTime(QDate(2013, 9, 3), QTime(0,30,0)));
2195+ todo.setDisplayLabel(displayLabelValue);
2196+ todo.setDescription(descriptionValue);
2197+
2198+ QMap<int, QtOrganizer::QOrganizerManager::Error> errorMap;
2199+ QList<QOrganizerItem> items;
2200+ QSignalSpy createdItem(engine, SIGNAL(itemsAdded(QList<QOrganizerItemId>)));
2201+ items << todo;
2202+ bool saveResult = engine->saveItems(&items,
2203+ QList<QtOrganizer::QOrganizerItemDetail::DetailType>(),
2204+ &errorMap,
2205+ &error);
2206+ QVERIFY(saveResult);
2207+ QCOMPARE(error, QOrganizerManager::NoError);
2208+ QVERIFY(errorMap.isEmpty());
2209+ QVERIFY(!items[0].id().isNull());
2210+
2211+ //verify signal
2212+ QCOMPARE(createdItem.count(), 1);
2213+ QList<QVariant> args = createdItem.takeFirst();
2214+ QCOMPARE(args.count(), 1);
2215+
2216+ // check if the item is listead inside the correct collection
2217+ QOrganizerItemSortOrder sort;
2218+ QOrganizerItemFetchHint hint;
2219+ QOrganizerItemCollectionFilter filter;
2220+
2221+ filter.setCollectionId(collection.id());
2222+
2223+ items = engine->items(filter,
2224+ QDateTime(),
2225+ QDateTime(),
2226+ 10,
2227+ sort,
2228+ hint,
2229+ &error);
2230+
2231+ QCOMPARE(items.count(), 1);
2232+ QOrganizerTodo result = static_cast<QOrganizerTodo>(items[0]);
2233+ todo = items[0];
2234+ QCOMPARE(result.id(), todo.id());
2235+ QCOMPARE(result.startDateTime(), todo.startDateTime());
2236+ QCOMPARE(result.displayLabel(), todo.displayLabel());
2237+ QCOMPARE(result.description(), todo.description());
2238+
2239+
2240+ // check if the item is listead by id
2241+ QList<QOrganizerItemId> ids;
2242+ ids << todo.id();
2243+
2244+ items = engine->items(ids, hint, &errorMap, &error);
2245+ QCOMPARE(items.count(), 1);
2246+ result = static_cast<QOrganizerTodo>(items[0]);
2247+ todo = items[0];
2248+ QCOMPARE(result.id(), todo.id());
2249+ QCOMPARE(result.startDateTime(), todo.startDateTime());
2250+ QCOMPARE(result.displayLabel(), todo.displayLabel());
2251+ QCOMPARE(result.description(), todo.description());
2252+
2253+ delete engine;
2254+ }
2255+
2256+ void testRemoveCollection()
2257+ {
2258+ static QString removableCollectionName = defaultTaskCollectionName + QStringLiteral("_REMOVABLE");
2259+
2260+ QOrganizerEDSEngine *engine = QOrganizerEDSEngine::createEDSEngine(QMap<QString, QString>());
2261+
2262+ // Create a collection
2263+ QOrganizerCollection collection;
2264+ QtOrganizer::QOrganizerManager::Error error;
2265+ collection.setMetaData(QOrganizerCollection::KeyName, removableCollectionName);
2266+ QVERIFY(engine->saveCollection(&collection, &error));
2267+ delete engine;
2268+
2269+ QTest::qSleep(1000);
2270+
2271+ engine = QOrganizerEDSEngine::createEDSEngine(QMap<QString, QString>());
2272+ // remove recent created collection
2273+ QVERIFY(engine->removeCollection(collection.id(), &error));
2274+
2275+ // Check if collection is not listed anymore
2276+ QTest::qSleep(1000);
2277+ QList<QOrganizerCollection> collections = engine->collections(&error);
2278+ QVERIFY(!collections.contains(collection));
2279+ }
2280+};
2281+
2282+const QString CollectionTest::defaultCollectionName = QStringLiteral("TEST COLLECTION");
2283+const QString CollectionTest::defaultTaskCollectionName = QStringLiteral("TEST COLLECTION TASK LIST");
2284+const QString CollectionTest::collectionTypePropertyName = QStringLiteral("collection-type");
2285+const QString CollectionTest::taskListTypeName = QStringLiteral("Task List");
2286+
2287+
2288+QTEST_MAIN(CollectionTest)
2289+
2290+#include "collections-test.moc"
2291
2292=== added file 'tests/unittest/event-test.cpp'
2293--- tests/unittest/event-test.cpp 1970-01-01 00:00:00 +0000
2294+++ tests/unittest/event-test.cpp 2013-09-09 21:01:24 +0000
2295@@ -0,0 +1,138 @@
2296+/*
2297+ * Copyright 2013 Canonical Ltd.
2298+ *
2299+ * This file is part of qtorganizer5-eds.
2300+ *
2301+ * contact-service-app is free software; you can redistribute it and/or modify
2302+ * it under the terms of the GNU General Public License as published by
2303+ * the Free Software Foundation; version 3.
2304+ *
2305+ * contact-service-app is distributed in the hope that it will be useful,
2306+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2307+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2308+ * GNU General Public License for more details.
2309+ *
2310+ * You should have received a copy of the GNU General Public License
2311+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2312+ */
2313+
2314+
2315+#include <QObject>
2316+#include <QtTest>
2317+#include <QDebug>
2318+
2319+#include <QtOrganizer>
2320+
2321+#include "qorganizer-eds-engine.h"
2322+
2323+
2324+using namespace QtOrganizer;
2325+
2326+class EventTest : public QObject
2327+{
2328+ Q_OBJECT
2329+private:
2330+ static const QString defaultCollectionName;
2331+ static const QString defaultTaskCollectionName;
2332+ static const QString collectionTypePropertyName;
2333+ static const QString taskListTypeName;
2334+
2335+private Q_SLOTS:
2336+ void testCreateEventWithReminder()
2337+ {
2338+ static QString displayLabelValue = QStringLiteral("Todo test");
2339+ static QString descriptionValue = QStringLiteral("Todo description");
2340+
2341+ QOrganizerEDSEngine *engine = QOrganizerEDSEngine::createEDSEngine(QMap<QString, QString>());
2342+
2343+ QOrganizerCollection collection;
2344+ QtOrganizer::QOrganizerManager::Error error;
2345+ collection.setMetaData(QOrganizerCollection::KeyName, defaultCollectionName);
2346+ collection.setExtendedMetaData(collectionTypePropertyName, taskListTypeName);
2347+
2348+ engine->saveCollection(&collection, &error);
2349+
2350+ QOrganizerTodo todo;
2351+ todo.setCollectionId(collection.id());
2352+ todo.setStartDateTime(QDateTime(QDate(2013, 9, 3), QTime(0,30,0)));
2353+ todo.setDisplayLabel(displayLabelValue);
2354+ todo.setDescription(descriptionValue);
2355+
2356+ QOrganizerItemVisualReminder vReminder;
2357+ vReminder.setDataUrl(QUrl("http://www.alarms.com"));
2358+ vReminder.setMessage("Test visual reminder");
2359+
2360+ QOrganizerItemAudibleReminder aReminder;
2361+ aReminder.setSecondsBeforeStart(10);
2362+ aReminder.setRepetition(10, 20);
2363+ aReminder.setDataUrl(QUrl("file://home/user/My Musics/play as alarm.wav"));
2364+
2365+
2366+ todo.saveDetail(&aReminder);
2367+ todo.saveDetail(&vReminder);
2368+
2369+ QMap<int, QtOrganizer::QOrganizerManager::Error> errorMap;
2370+ QList<QOrganizerItem> items;
2371+ items << todo;
2372+ bool saveResult = engine->saveItems(&items,
2373+ QList<QtOrganizer::QOrganizerItemDetail::DetailType>(),
2374+ &errorMap,
2375+ &error);
2376+ QVERIFY(saveResult);
2377+
2378+ // delete engine to make sure the new engine will be loaded from scratch
2379+ delete engine;
2380+
2381+ engine = QOrganizerEDSEngine::createEDSEngine(QMap<QString, QString>());
2382+
2383+ QOrganizerItemSortOrder sort;
2384+ QOrganizerItemFetchHint hint;
2385+ QOrganizerItemIdFilter filter;
2386+
2387+ QList<QOrganizerItemId> ids;
2388+ ids << items[0].id();
2389+ filter.setIds(ids);
2390+
2391+ items = engine->items(filter,
2392+ QDateTime(),
2393+ QDateTime(),
2394+ 10,
2395+ sort,
2396+ hint,
2397+ &error);
2398+ QCOMPARE(items.count(), 1);
2399+
2400+ // audible
2401+ QList<QOrganizerItemDetail> reminders = items[0].details(QOrganizerItemDetail::TypeAudibleReminder);
2402+ QCOMPARE(reminders.size(), 1);
2403+
2404+ QOrganizerItemAudibleReminder aReminder2 = reminders[0];
2405+ QCOMPARE(aReminder2.secondsBeforeStart(), aReminder.secondsBeforeStart());
2406+ QCOMPARE(aReminder2.repetitionCount(), aReminder.repetitionCount());
2407+ QCOMPARE(aReminder2.repetitionDelay(), aReminder.repetitionDelay());
2408+ QCOMPARE(aReminder2.dataUrl(), aReminder.dataUrl());
2409+ //QCOMPARE(aReminder2, aReminder);
2410+
2411+ // visual
2412+ reminders = items[0].details(QOrganizerItemDetail::TypeVisualReminder);
2413+ QCOMPARE(reminders.size(), 1);
2414+
2415+ QOrganizerItemVisualReminder vReminder2 = reminders[0];
2416+ //vReminder.setRepetition(1, 0);
2417+ QCOMPARE(vReminder2.secondsBeforeStart(), vReminder.secondsBeforeStart());
2418+ QCOMPARE(vReminder2.repetitionCount(), vReminder.repetitionCount());
2419+ QCOMPARE(vReminder2.repetitionDelay(), vReminder.repetitionDelay());
2420+ QCOMPARE(vReminder2.dataUrl(), vReminder.dataUrl());
2421+ QCOMPARE(vReminder2.message(), vReminder.message());
2422+ }
2423+};
2424+
2425+const QString EventTest::defaultCollectionName = QStringLiteral("TEST_EVENT_COLLECTION");
2426+const QString EventTest::defaultTaskCollectionName = QStringLiteral("TEST_EVENT_COLLECTION TASK LIST");
2427+const QString EventTest::collectionTypePropertyName = QStringLiteral("collection-type");
2428+const QString EventTest::taskListTypeName = QStringLiteral("Task List");
2429+
2430+
2431+QTEST_MAIN(EventTest)
2432+
2433+#include "event-test.moc"
2434
2435=== added file 'tests/unittest/parseecal-test.cpp'
2436--- tests/unittest/parseecal-test.cpp 1970-01-01 00:00:00 +0000
2437+++ tests/unittest/parseecal-test.cpp 2013-09-09 21:01:24 +0000
2438@@ -0,0 +1,366 @@
2439+/*
2440+ * Copyright 2013 Canonical Ltd.
2441+ *
2442+ * This file is part of qtorganizer5-eds.
2443+ *
2444+ * contact-service-app is free software; you can redistribute it and/or modify
2445+ * it under the terms of the GNU General Public License as published by
2446+ * the Free Software Foundation; version 3.
2447+ *
2448+ * contact-service-app is distributed in the hope that it will be useful,
2449+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2450+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2451+ * GNU General Public License for more details.
2452+ *
2453+ * You should have received a copy of the GNU General Public License
2454+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2455+ */
2456+
2457+//ugly hack but this allow us to test the engine without mock EDS
2458+#define private public
2459+#include "qorganizer-eds-engine.h"
2460+#undef private
2461+
2462+#include <QObject>
2463+#include <QtTest>
2464+#include <QDebug>
2465+
2466+#include <QtOrganizer>
2467+
2468+#include <libecal/libecal.h>
2469+
2470+using namespace QtOrganizer;
2471+
2472+class ParseEcalTest : public QObject
2473+{
2474+ Q_OBJECT
2475+
2476+private Q_SLOTS:
2477+ void testParseStartTime()
2478+ {
2479+ QDateTime startTime = QDateTime::currentDateTime();
2480+ QDateTime endTime(startTime);
2481+ endTime = endTime.addDays(2);
2482+
2483+ ECalComponent *comp = e_cal_component_new();
2484+ e_cal_component_set_new_vtype(comp, E_CAL_COMPONENT_EVENT);
2485+
2486+ ECalComponentDateTime dt;
2487+
2488+ struct icaltimetype itt = icaltime_from_timet(startTime.toTime_t(), FALSE);
2489+ dt.value = &itt;
2490+ dt.tzid = "";
2491+ e_cal_component_set_dtstart(comp, &dt);
2492+
2493+ QOrganizerEvent item;
2494+ QOrganizerEDSEngine::parseStartTime(comp, &item);
2495+ QCOMPARE(item.startDateTime().toTime_t(), startTime.toTime_t());
2496+
2497+ itt = icaltime_from_timet(endTime.toTime_t(), FALSE);
2498+ dt.value = &itt;
2499+ e_cal_component_set_dtend(comp, &dt);
2500+
2501+ QOrganizerEDSEngine::parseEndTime(comp, &item);
2502+ QCOMPARE(item.endDateTime().toTime_t(), endTime.toTime_t());
2503+ }
2504+
2505+ void testParseRemindersQOrganizerEvent2ECalComponent()
2506+ {
2507+ QOrganizerEvent event;
2508+ QOrganizerItemAudibleReminder aReminder;
2509+
2510+ // Check audible reminder
2511+ aReminder.setRepetition(10, 30);
2512+ aReminder.setSecondsBeforeStart(10);
2513+ QCOMPARE(aReminder.secondsBeforeStart(), 10);
2514+ event.saveDetail(&aReminder);
2515+
2516+ ECalComponent *comp = e_cal_component_new();
2517+ e_cal_component_set_new_vtype(comp, E_CAL_COMPONENT_EVENT);
2518+
2519+ QOrganizerEDSEngine::parseReminders(event, comp);
2520+
2521+ GList *aIds = e_cal_component_get_alarm_uids(comp);
2522+ QCOMPARE(g_list_length(aIds), (guint) 1);
2523+
2524+ ECalComponentAlarm *alarm = e_cal_component_get_alarm(comp, (const gchar*)aIds->data);
2525+ QVERIFY(alarm);
2526+
2527+ ECalComponentAlarmAction aAction;
2528+ e_cal_component_alarm_get_action(alarm, &aAction);
2529+ QCOMPARE(aAction, E_CAL_COMPONENT_ALARM_AUDIO);
2530+
2531+ ECalComponentAlarmTrigger trigger;
2532+ e_cal_component_alarm_get_trigger(alarm, &trigger);
2533+ QCOMPARE(trigger.type, E_CAL_COMPONENT_ALARM_TRIGGER_RELATIVE_START);
2534+ QCOMPARE(icaldurationtype_as_int(trigger.u.rel_duration) * -1, aReminder.secondsBeforeStart());
2535+
2536+ ECalComponentAlarmRepeat aRepeat;
2537+ e_cal_component_alarm_get_repeat(alarm, &aRepeat);
2538+ QCOMPARE(aRepeat.repetitions, aReminder.repetitionCount());
2539+ QCOMPARE(icaldurationtype_as_int(aRepeat.duration), aReminder.repetitionDelay());
2540+
2541+ g_object_unref(comp);
2542+ }
2543+
2544+ void testParseRemindersECalComponent2QOrganizerEvent()
2545+ {
2546+ ECalComponent *comp = e_cal_component_new();
2547+ e_cal_component_set_new_vtype(comp, E_CAL_COMPONENT_EVENT);
2548+
2549+ ECalComponentAlarm *alarm = e_cal_component_alarm_new();
2550+ e_cal_component_alarm_set_action(alarm, E_CAL_COMPONENT_ALARM_DISPLAY);
2551+
2552+ ECalComponentAlarmTrigger trigger;
2553+ trigger.type = E_CAL_COMPONENT_ALARM_TRIGGER_RELATIVE_START;
2554+ trigger.u.rel_duration = icaldurationtype_from_int(-10);
2555+ e_cal_component_alarm_set_trigger(alarm, trigger);
2556+
2557+ ECalComponentAlarmRepeat aRepeat;
2558+ aRepeat.repetitions = 5;
2559+ aRepeat.duration = icaldurationtype_from_int(100);
2560+ e_cal_component_alarm_set_repeat(alarm, aRepeat);
2561+
2562+ e_cal_component_add_alarm(comp, alarm);
2563+ e_cal_component_alarm_free(alarm);
2564+
2565+ QOrganizerItem alarmItem;
2566+ QOrganizerEDSEngine::parseReminders(comp, &alarmItem);
2567+
2568+ QOrganizerItemVisualReminder vReminder = alarmItem.detail(QOrganizerItemDetail::TypeVisualReminder);
2569+ QCOMPARE(vReminder.repetitionCount(), 5);
2570+ QCOMPARE(vReminder.repetitionDelay(), 100);
2571+ QCOMPARE(vReminder.secondsBeforeStart(), 10);
2572+
2573+ g_object_unref(comp);
2574+ }
2575+
2576+ void testParseRecurenceQOrganizerEvent2ECalComponent()
2577+ {
2578+ // by date
2579+ QOrganizerEvent event;
2580+ QOrganizerItemRecurrence rec;
2581+
2582+ QList<QDate> rDates;
2583+ rDates << QDate(2010, 1, 20)
2584+ << QDate(2011, 2, 21)
2585+ << QDate(2012, 3, 22);
2586+
2587+ rec.setRecurrenceDates(rDates.toSet());
2588+
2589+ QList<QDate> rExeptDates;
2590+ rExeptDates << QDate(2013, 4, 23)
2591+ << QDate(2014, 5, 24)
2592+ << QDate(2015, 6, 25);
2593+ rec.setExceptionDates(rExeptDates.toSet());
2594+
2595+ QOrganizerRecurrenceRule dailyRule;
2596+ QList<QOrganizerRecurrenceRule> rrules;
2597+
2598+ dailyRule.setFrequency(QOrganizerRecurrenceRule::Daily);
2599+ dailyRule.setLimit(1000);
2600+ rrules << dailyRule;
2601+
2602+ QOrganizerRecurrenceRule weeklyRule;
2603+ weeklyRule.setFrequency(QOrganizerRecurrenceRule::Weekly);
2604+ weeklyRule.setLimit(1001);
2605+ QList<Qt::DayOfWeek> daysOfWeek;
2606+ daysOfWeek << Qt::Monday
2607+ << Qt::Tuesday
2608+ << Qt::Wednesday
2609+ << Qt::Thursday
2610+ << Qt::Friday;
2611+ weeklyRule.setDaysOfWeek(daysOfWeek.toSet());
2612+ weeklyRule.setFirstDayOfWeek(Qt::Sunday);
2613+ rrules << weeklyRule;
2614+
2615+ QOrganizerRecurrenceRule monthlyRule;
2616+ monthlyRule.setFrequency(QOrganizerRecurrenceRule::Monthly);
2617+ monthlyRule.setLimit(1002);
2618+
2619+ QList<int> daysOfMonth;
2620+ daysOfMonth << 1
2621+ << 15
2622+ << 30;
2623+ monthlyRule.setDaysOfMonth(daysOfMonth.toSet());
2624+ rrules << monthlyRule;
2625+
2626+ QOrganizerRecurrenceRule yearlyRule;
2627+ yearlyRule.setFrequency(QOrganizerRecurrenceRule::Yearly);
2628+ yearlyRule.setLimit(1003);
2629+ QList<int> daysOfYear;
2630+ daysOfYear << 1
2631+ << 10
2632+ << 20
2633+ << 50
2634+ << 300;
2635+ yearlyRule.setDaysOfYear(daysOfYear.toSet());
2636+
2637+
2638+ QList<QOrganizerRecurrenceRule::Month> monthsOfYear;
2639+ monthsOfYear << QOrganizerRecurrenceRule::January
2640+ << QOrganizerRecurrenceRule::March
2641+ << QOrganizerRecurrenceRule::December;
2642+ yearlyRule.setMonthsOfYear(monthsOfYear.toSet());
2643+ rrules << yearlyRule;
2644+
2645+ rec.setRecurrenceRules(rrules.toSet());
2646+
2647+ // save recurrence
2648+ event.saveDetail(&rec);
2649+
2650+ ECalComponent *comp = e_cal_component_new();
2651+ e_cal_component_set_new_vtype(comp, E_CAL_COMPONENT_EVENT);
2652+ QOrganizerEDSEngine::parseRecurrence(event, comp);
2653+
2654+ // recurrence dates
2655+ GSList *periodList = 0;
2656+ e_cal_component_get_rdate_list(comp, &periodList);
2657+
2658+ QCOMPARE(g_slist_length(periodList), (guint)3);
2659+
2660+ for(GSList *pIter = periodList; pIter != 0; pIter = pIter->next) {
2661+ ECalComponentPeriod *period = static_cast<ECalComponentPeriod*>(pIter->data);
2662+ QDate periodDate = QDateTime::fromTime_t(icaltime_as_timet(period->start)).date();
2663+
2664+ QVERIFY(rDates.contains(periodDate));
2665+ }
2666+ e_cal_component_free_period_list(periodList);
2667+
2668+ // exception dates
2669+ GSList *exDateList = 0;
2670+ e_cal_component_get_exdate_list(comp, &exDateList);
2671+ for(GSList *pIter = exDateList; pIter != 0; pIter = pIter->next) {
2672+ ECalComponentDateTime *exDate = static_cast<ECalComponentDateTime*>(pIter->data);
2673+ QDate exDateValue = QDateTime::fromTime_t(icaltime_as_timet(*exDate->value)).date();
2674+ QVERIFY(rExeptDates.contains(exDateValue));
2675+ }
2676+ e_cal_component_free_exdate_list(exDateList);
2677+
2678+
2679+ // rules
2680+ GSList *recurList = 0;
2681+ e_cal_component_get_rrule_list(comp, &recurList);
2682+ QCOMPARE(g_slist_length(recurList), (guint) rrules.count());
2683+
2684+ for(GSList *recurListIter = recurList; recurListIter != 0; recurListIter = recurListIter->next) {
2685+ struct icalrecurrencetype *rule = static_cast<struct icalrecurrencetype*>(recurListIter->data);
2686+
2687+ switch(rule->freq)
2688+ {
2689+ case ICAL_DAILY_RECURRENCE:
2690+ QCOMPARE(rule->count, dailyRule.limitCount());
2691+ break;
2692+ case ICAL_WEEKLY_RECURRENCE:
2693+ QCOMPARE(rule->count, weeklyRule.limitCount());
2694+ for (int d = Qt::Monday; d <= Qt::Sunday; d++) {
2695+ if (daysOfWeek.contains(static_cast<Qt::DayOfWeek>(d))) {
2696+ QVERIFY(rule->by_day[(d-1)] != ICAL_RECURRENCE_ARRAY_MAX);
2697+ } else {
2698+ QVERIFY(rule->by_day[d-1] == ICAL_RECURRENCE_ARRAY_MAX);
2699+ }
2700+ }
2701+ break;
2702+ case ICAL_MONTHLY_RECURRENCE:
2703+ {
2704+ QCOMPARE(rule->count, monthlyRule.limitCount());
2705+
2706+ QList<int> ruleDays;
2707+ for (int d=0; d < ICAL_BY_MONTHDAY_SIZE; d++) {
2708+ if (rule->by_month_day[d] != ICAL_RECURRENCE_ARRAY_MAX) {
2709+ ruleDays << rule->by_month_day[d];
2710+ }
2711+ }
2712+ QCOMPARE(ruleDays.count(), daysOfMonth.count());
2713+ Q_FOREACH(int day, ruleDays) {
2714+ QVERIFY(daysOfMonth.contains(day));
2715+ }
2716+ break;
2717+ }
2718+ case ICAL_YEARLY_RECURRENCE:
2719+ {
2720+ QCOMPARE(rule->count, yearlyRule.limitCount());
2721+ QList<int> ruleDays;
2722+
2723+ for (int d=0; d < ICAL_BY_YEARDAY_SIZE; d++) {
2724+ if (rule->by_year_day[d] != ICAL_RECURRENCE_ARRAY_MAX) {
2725+
2726+ ruleDays << rule->by_year_day[d];
2727+ }
2728+ }
2729+ QCOMPARE(ruleDays.count(), daysOfYear.count());
2730+ Q_FOREACH(int day, ruleDays) {
2731+ QVERIFY(daysOfYear.contains(day));
2732+ }
2733+
2734+ QList<int> ruleMonths;
2735+ for (int d=0; d < ICAL_BY_MONTH_SIZE; d++) {
2736+ if (rule->by_month[d] != ICAL_RECURRENCE_ARRAY_MAX) {
2737+ ruleMonths << rule->by_month[d];
2738+ }
2739+ }
2740+ QCOMPARE(ruleMonths.count(), monthsOfYear.count());
2741+ Q_FOREACH(int month, ruleMonths) {
2742+ QVERIFY(monthsOfYear.contains(static_cast<QOrganizerRecurrenceRule::Month>(month)));
2743+ }
2744+ }
2745+ default:
2746+ break;
2747+ }
2748+ }
2749+
2750+ // invert
2751+ QOrganizerEvent event2;
2752+ QOrganizerEDSEngine::parseRecurrence(comp, &event2);
2753+
2754+ QCOMPARE(event2.recurrenceDates(), event.recurrenceDates());
2755+ QCOMPARE(event2.exceptionDates(), event.exceptionDates());
2756+
2757+ QList<QOrganizerRecurrenceRule> rrules2 = event2.recurrenceRules().toList();
2758+ QCOMPARE(rrules2.count(), rrules.count());
2759+
2760+ Q_FOREACH(QOrganizerRecurrenceRule rule2, rrules2) {
2761+ switch(rule2.frequency()) {
2762+ case QOrganizerRecurrenceRule::Daily:
2763+ QCOMPARE(rule2.limitCount(), dailyRule.limitCount());
2764+ break;
2765+ case QOrganizerRecurrenceRule::Weekly:
2766+ {
2767+ QCOMPARE(rule2.limitCount(), weeklyRule.limitCount());
2768+ QList<Qt::DayOfWeek> daysOfWeek2 = rule2.daysOfWeek().toList();
2769+ qSort(daysOfWeek2);
2770+ QCOMPARE(daysOfWeek2, daysOfWeek);
2771+ break;
2772+ }
2773+ case QOrganizerRecurrenceRule::Monthly:
2774+ {
2775+ QCOMPARE(rule2.limitCount(), monthlyRule.limitCount());
2776+ QList<int> daysOfMonth2 = rule2.daysOfMonth().toList();
2777+ qSort(daysOfMonth2);
2778+ QCOMPARE(daysOfMonth2, daysOfMonth);
2779+ break;
2780+ }
2781+ case QOrganizerRecurrenceRule::Yearly:
2782+ {
2783+ QCOMPARE(rule2.limitCount(), yearlyRule.limitCount());
2784+ QList<int> daysOfYear2 = rule2.daysOfYear().toList();
2785+ qSort(daysOfYear2);
2786+ QCOMPARE(daysOfYear2, daysOfYear);
2787+
2788+ QList<QOrganizerRecurrenceRule::Month> monthsOfYear2 = rule2.monthsOfYear().toList();
2789+ qSort(monthsOfYear2);
2790+ QCOMPARE(monthsOfYear2, monthsOfYear);
2791+ break;
2792+ }
2793+ default:
2794+ QVERIFY(false);
2795+ }
2796+ }
2797+
2798+ g_object_unref(comp);
2799+ }
2800+};
2801+
2802+QTEST_MAIN(ParseEcalTest)
2803+
2804+#include "parseecal-test.moc"
2805
2806=== added file 'tests/unittest/parseitem-test.cpp'

Subscribers

People subscribed via source and target branches