Merge lp:~renatofilho/qtorganizer5-eds/fix-1426519 into lp:qtorganizer5-eds

Proposed by Renato Araujo Oliveira Filho
Status: Merged
Approved by: Charles Kerr
Approved revision: 76
Merged at revision: 80
Proposed branch: lp:~renatofilho/qtorganizer5-eds/fix-1426519
Merge into: lp:qtorganizer5-eds
Diff against target: 331 lines (+124/-16)
8 files modified
CMakeLists.txt (+1/-0)
organizer/qorganizer-eds-engine.cpp (+43/-7)
organizer/qorganizer-eds-engine.h (+3/-1)
organizer/qorganizer-eds-requestdata.cpp (+16/-4)
organizer/qorganizer-eds-requestdata.h (+1/-1)
tests/unittest/CMakeLists.txt (+0/-1)
tests/unittest/event-test.cpp (+59/-1)
tests/unittest/run-eds-test.sh (+1/-1)
To merge this branch: bzr merge lp:~renatofilho/qtorganizer5-eds/fix-1426519
Reviewer Review Type Date Requested Status
Charles Kerr (community) Approve
PS Jenkins bot continuous-integration Needs Fixing
Review via email: mp+253985@code.launchpad.net

Commit message

Implemented support for extended details.

Now you can set extended details (X-*, properties) for calendar items.

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
Charles Kerr (charlesk) wrote :

Looks good to me. Thanks for the fast work, Renato!

Revision history for this message
Charles Kerr (charlesk) :
review: Approve
77. By Renato Araujo Oliveira Filho

Fixed wait function to not block glib.
Fixed source creation process to avoid return unready sources.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'CMakeLists.txt'
--- CMakeLists.txt 2014-09-22 13:18:51 +0000
+++ CMakeLists.txt 2015-03-30 17:59:30 +0000
@@ -9,6 +9,7 @@
99
10find_package(Qt5Core REQUIRED)10find_package(Qt5Core REQUIRED)
11add_definitions(-DQT_NO_KEYWORDS)11add_definitions(-DQT_NO_KEYWORDS)
12add_definitions(-std=c++11)
1213
13pkg_check_modules(GLIB REQUIRED glib-2.0>=2.32)14pkg_check_modules(GLIB REQUIRED glib-2.0>=2.32)
14pkg_check_modules(GIO REQUIRED gio-2.0>=2.32)15pkg_check_modules(GIO REQUIRED gio-2.0>=2.32)
1516
=== modified file 'organizer/qorganizer-eds-engine.cpp'
--- organizer/qorganizer-eds-engine.cpp 2015-03-24 17:56:44 +0000
+++ organizer/qorganizer-eds-engine.cpp 2015-03-30 17:59:30 +0000
@@ -61,6 +61,7 @@
61#include <QtOrganizer/QOrganizerEventOccurrence>61#include <QtOrganizer/QOrganizerEventOccurrence>
62#include <QtOrganizer/QOrganizerTodoOccurrence>62#include <QtOrganizer/QOrganizerTodoOccurrence>
63#include <QtOrganizer/QOrganizerItemParent>63#include <QtOrganizer/QOrganizerItemParent>
64#include <QtOrganizer/QOrganizerItemExtendedDetail>
6465
65#include <glib.h>66#include <glib.h>
66#include <libecal/libecal.h>67#include <libecal/libecal.h>
@@ -863,7 +864,7 @@
863 requestData);864 requestData);
864 } else {865 } else {
865 requestData->prepareToUpdate();866 requestData->prepareToUpdate();
866 saveCollectionUpdateAsyncStart(requestData);867 g_idle_add((GSourceFunc) saveCollectionUpdateAsyncStart, requestData);
867 }868 }
868}869}
869870
@@ -884,16 +885,16 @@
884 } else if (data->isLive()) {885 } else if (data->isLive()) {
885 data->commitSourceCreated();886 data->commitSourceCreated();
886 data->prepareToUpdate();887 data->prepareToUpdate();
887 saveCollectionUpdateAsyncStart(data);888 g_idle_add((GSourceFunc) saveCollectionUpdateAsyncStart, data);
888 }889 }
889}890}
890891
891void QOrganizerEDSEngine::saveCollectionUpdateAsyncStart(SaveCollectionRequestData *data)892gboolean QOrganizerEDSEngine::saveCollectionUpdateAsyncStart(SaveCollectionRequestData *data)
892{893{
893 // check if request was destroyed by the caller894 // check if request was destroyed by the caller
894 if (!data->isLive()) {895 if (!data->isLive()) {
895 releaseRequestData(data);896 releaseRequestData(data);
896 return;897 return FALSE;
897 }898 }
898899
899 ESource *source = data->nextSourceToUpdate();900 ESource *source = data->nextSourceToUpdate();
@@ -906,6 +907,7 @@
906 data->finish();907 data->finish();
907 releaseRequestData(data);908 releaseRequestData(data);
908 }909 }
910 return FALSE;
909}911}
910912
911void QOrganizerEDSEngine::saveCollectionUpdateAsynCommited(ESource *source,913void QOrganizerEDSEngine::saveCollectionUpdateAsynCommited(ESource *source,
@@ -926,7 +928,7 @@
926 }928 }
927929
928 if (data->isLive()) {930 if (data->isLive()) {
929 saveCollectionUpdateAsyncStart(data);931 g_idle_add((GSourceFunc) saveCollectionUpdateAsyncStart, data);
930 } else {932 } else {
931 releaseRequestData(data);933 releaseRequestData(data);
932 }934 }
@@ -1081,11 +1083,10 @@
1081bool QOrganizerEDSEngine::waitForRequestFinished(QOrganizerAbstractRequest* req, int msecs)1083bool QOrganizerEDSEngine::waitForRequestFinished(QOrganizerAbstractRequest* req, int msecs)
1082{1084{
1083 Q_ASSERT(req);1085 Q_ASSERT(req);
1084 Q_UNUSED(msecs);
10851086
1086 RequestData *data = m_runningRequests.value(req);1087 RequestData *data = m_runningRequests.value(req);
1087 if (data) {1088 if (data) {
1088 data->wait();1089 data->wait(msecs);
1089 // We can delete the operation already finished1090 // We can delete the operation already finished
1090 data->deleteLater();1091 data->deleteLater();
1091 }1092 }
@@ -1619,6 +1620,20 @@
1619 e_cal_component_free_attendee_list(attendeeList);1620 e_cal_component_free_attendee_list(attendeeList);
1620}1621}
16211622
1623void QOrganizerEDSEngine::parseExtendedDetails(ECalComponent *comp, QOrganizerItem *item)
1624{
1625 icalcomponent *icalcomp = e_cal_component_get_icalcomponent(comp);
1626 for (icalproperty *prop = icalcomponent_get_first_property(icalcomp, ICAL_X_PROPERTY);
1627 prop != NULL;
1628 prop = icalcomponent_get_next_property (icalcomp, ICAL_X_PROPERTY)) {
1629
1630 QOrganizerItemExtendedDetail ex;
1631 ex.setName(QString::fromUtf8(icalproperty_get_x_name(prop)));
1632 ex.setData(QByteArray(icalproperty_get_x(prop)));
1633 item->saveDetail(&ex);
1634 }
1635}
1636
1622QOrganizerItem *QOrganizerEDSEngine::parseEvent(ECalComponent *comp)1637QOrganizerItem *QOrganizerEDSEngine::parseEvent(ECalComponent *comp)
1623{1638{
1624 QOrganizerItem *event;1639 QOrganizerItem *event;
@@ -1841,6 +1856,7 @@
1841 parseTags(comp, item);1856 parseTags(comp, item);
1842 parseReminders(comp, item);1857 parseReminders(comp, item);
1843 parseAttendeeList(comp, item);1858 parseAttendeeList(comp, item);
1859 parseExtendedDetails(comp, item);
18441860
1845 items << *item;1861 items << *item;
1846 delete item;1862 delete item;
@@ -2160,6 +2176,25 @@
2160 e_cal_component_free_attendee_list(attendeeList);2176 e_cal_component_free_attendee_list(attendeeList);
2161}2177}
21622178
2179void QOrganizerEDSEngine::parseExtendedDetails(const QOrganizerItem &item, ECalComponent *comp)
2180{
2181 icalcomponent *icalcomp = e_cal_component_get_icalcomponent(comp);
2182 Q_FOREACH(const QOrganizerItemExtendedDetail &ex, item.details(QOrganizerItemDetail::TypeExtendedDetail)) {
2183 // We only support QByteArray.
2184 // We could use QStream serialization but it will make it impossible to read it from glib side, for example indicators.
2185 QByteArray data = ex.data().toByteArray();
2186 if (data.isEmpty()) {
2187 qWarning() << "Invalid value for property" << ex.name()
2188 <<". EDS only supports QByteArray values for extended properties";
2189 continue;
2190 }
2191
2192 icalproperty *xProp = icalproperty_new_x(data.constData());
2193 icalproperty_set_x_name(xProp, ex.name().toUtf8().constData());
2194 icalcomponent_add_property(icalcomp, xProp);
2195 }
2196}
2197
2163bool QOrganizerEDSEngine::hasRecurrence(ECalComponent *comp)2198bool QOrganizerEDSEngine::hasRecurrence(ECalComponent *comp)
2164{2199{
2165 char *rid = e_cal_component_get_recurid_as_string(comp);2200 char *rid = e_cal_component_get_recurid_as_string(comp);
@@ -2433,6 +2468,7 @@
2433 parseTags(item, comp);2468 parseTags(item, comp);
2434 parseReminders(item, comp);2469 parseReminders(item, comp);
2435 parseAttendeeList(item, comp);2470 parseAttendeeList(item, comp);
2471 parseExtendedDetails(item, comp);
24362472
2437 if (!item.id().isNull()) {2473 if (!item.id().isNull()) {
2438 e_cal_component_commit_sequence(comp);2474 e_cal_component_commit_sequence(comp);
24392475
=== modified file 'organizer/qorganizer-eds-engine.h'
--- organizer/qorganizer-eds-engine.h 2015-03-24 17:56:44 +0000
+++ organizer/qorganizer-eds-engine.h 2015-03-30 17:59:30 +0000
@@ -168,6 +168,7 @@
168 static void parseProgress(const QtOrganizer::QOrganizerItem &item, ECalComponent *comp);168 static void parseProgress(const QtOrganizer::QOrganizerItem &item, ECalComponent *comp);
169 static void parseStatus(const QtOrganizer::QOrganizerItem &item, ECalComponent *comp);169 static void parseStatus(const QtOrganizer::QOrganizerItem &item, ECalComponent *comp);
170 static void parseAttendeeList(const QtOrganizer::QOrganizerItem &item, ECalComponent *comp);170 static void parseAttendeeList(const QtOrganizer::QOrganizerItem &item, ECalComponent *comp);
171 static void parseExtendedDetails(const QtOrganizer::QOrganizerItem &item, ECalComponent *comp);
171172
172 // ECalComponent -> QOrganizerItem173 // ECalComponent -> QOrganizerItem
173 static bool hasRecurrence(ECalComponent *comp);174 static bool hasRecurrence(ECalComponent *comp);
@@ -193,6 +194,7 @@
193 static void parseProgress(ECalComponent *comp, QtOrganizer::QOrganizerItem *item);194 static void parseProgress(ECalComponent *comp, QtOrganizer::QOrganizerItem *item);
194 static void parseStatus(ECalComponent *comp, QtOrganizer::QOrganizerItem *item);195 static void parseStatus(ECalComponent *comp, QtOrganizer::QOrganizerItem *item);
195 static void parseAttendeeList(ECalComponent *comp, QtOrganizer::QOrganizerItem *item);196 static void parseAttendeeList(ECalComponent *comp, QtOrganizer::QOrganizerItem *item);
197 static void parseExtendedDetails(ECalComponent *comp, QtOrganizer::QOrganizerItem *item);
196198
197 static QDateTime fromIcalTime(struct icaltimetype value, const char *tzId);199 static QDateTime fromIcalTime(struct icaltimetype value, const char *tzId);
198 static icaltimetype fromQDateTime(const QDateTime &dateTime, bool allDay, QByteArray *tzId);200 static icaltimetype fromQDateTime(const QDateTime &dateTime, bool allDay, QByteArray *tzId);
@@ -234,7 +236,7 @@
234 static void removeItemsAsyncStart(RemoveRequestData *data);236 static void removeItemsAsyncStart(RemoveRequestData *data);
235237
236 void saveCollectionAsync(QtOrganizer::QOrganizerCollectionSaveRequest *req);238 void saveCollectionAsync(QtOrganizer::QOrganizerCollectionSaveRequest *req);
237 static void saveCollectionUpdateAsyncStart(SaveCollectionRequestData *data);239 static gboolean saveCollectionUpdateAsyncStart(SaveCollectionRequestData *data);
238 static void saveCollectionAsyncCommited(ESourceRegistry *registry, GAsyncResult *res, SaveCollectionRequestData *data);240 static void saveCollectionAsyncCommited(ESourceRegistry *registry, GAsyncResult *res, SaveCollectionRequestData *data);
239 static void saveCollectionUpdateAsynCommited(ESource *source, GAsyncResult *res, SaveCollectionRequestData *data);241 static void saveCollectionUpdateAsynCommited(ESource *source, GAsyncResult *res, SaveCollectionRequestData *data);
240242
241243
=== modified file 'organizer/qorganizer-eds-requestdata.cpp'
--- organizer/qorganizer-eds-requestdata.cpp 2015-03-06 22:47:19 +0000
+++ organizer/qorganizer-eds-requestdata.cpp 2015-03-30 17:59:30 +0000
@@ -19,7 +19,7 @@
19#include "qorganizer-eds-requestdata.h"19#include "qorganizer-eds-requestdata.h"
2020
21#include <QtCore/QDebug>21#include <QtCore/QDebug>
22#include <QtCore/QCoreApplication>22#include <QtCore/QTimer>
2323
24#include <QtOrganizer/QOrganizerAbstractRequest>24#include <QtOrganizer/QOrganizerAbstractRequest>
25#include <QtOrganizer/QOrganizerManagerEngine>25#include <QtOrganizer/QOrganizerManagerEngine>
@@ -81,12 +81,24 @@
81 }81 }
82}82}
8383
84void RequestData::wait()84void RequestData::wait(int msec)
85{85{
86 QMutexLocker locker(&m_waiting);86 QMutexLocker locker(&m_waiting);
87 while(!m_finished) {87 QEventLoop *loop = new QEventLoop;
88 QCoreApplication::processEvents(QEventLoop::AllEvents, 100);88 QOrganizerAbstractRequest *req = m_req.data();
89 QObject::connect(req, &QOrganizerAbstractRequest::stateChanged, [req, loop](QOrganizerAbstractRequest::State newState) {
90 if (newState != QOrganizerAbstractRequest::ActiveState) {
91 loop->quit();
92 }
93 });
94 QTimer timeout;
95 if (msec > 0) {
96 timeout.setInterval(msec);
97 timeout.setSingleShot(true);
98 timeout.start();
89 }99 }
100 loop->exec(QEventLoop::AllEvents|QEventLoop::WaitForMoreEvents);
101 delete loop;
90}102}
91103
92bool RequestData::isWaiting()104bool RequestData::isWaiting()
93105
=== modified file 'organizer/qorganizer-eds-requestdata.h'
--- organizer/qorganizer-eds-requestdata.h 2015-03-06 22:47:19 +0000
+++ organizer/qorganizer-eds-requestdata.h 2015-03-30 17:59:30 +0000
@@ -42,7 +42,7 @@
42 virtual void cancel();42 virtual void cancel();
43 void deleteLater();43 void deleteLater();
44 virtual void finish(QtOrganizer::QOrganizerManager::Error error, QtOrganizer::QOrganizerAbstractRequest::State state) = 0;44 virtual void finish(QtOrganizer::QOrganizerManager::Error error, QtOrganizer::QOrganizerAbstractRequest::State state) = 0;
45 void wait();45 void wait(int msec = 0);
46 bool isWaiting();46 bool isWaiting();
4747
48 template<class T>48 template<class T>
4949
=== modified file 'tests/unittest/CMakeLists.txt'
--- tests/unittest/CMakeLists.txt 2015-03-24 17:56:44 +0000
+++ tests/unittest/CMakeLists.txt 2015-03-30 17:59:30 +0000
@@ -38,7 +38,6 @@
38)38)
3939
40add_definitions(-DTEST_SUITE)40add_definitions(-DTEST_SUITE)
41add_definitions(-std=c++11)
4241
43declare_test(itemid-test)42declare_test(itemid-test)
44declare_test(parseecal-test)43declare_test(parseecal-test)
4544
=== modified file 'tests/unittest/event-test.cpp'
--- tests/unittest/event-test.cpp 2014-10-29 14:19:47 +0000
+++ tests/unittest/event-test.cpp 2015-03-30 17:59:30 +0000
@@ -806,7 +806,6 @@
806 QList<QOrganizerItemId> ids;806 QList<QOrganizerItemId> ids;
807 QOrganizerItemFetchHint hint;807 QOrganizerItemFetchHint hint;
808 ids << items[0].id();808 ids << items[0].id();
809 qDebug() << "Find for id" << ids;
810 QList<QOrganizerItem> newItems = m_engine->items(ids, hint, &errorMap, &error);809 QList<QOrganizerItem> newItems = m_engine->items(ids, hint, &errorMap, &error);
811 QCOMPARE(newItems.size(), 1);810 QCOMPARE(newItems.size(), 1);
812811
@@ -819,6 +818,65 @@
819 QCOMPARE(newAttendee.participationRole(), attendee.participationRole());818 QCOMPARE(newAttendee.participationRole(), attendee.participationRole());
820 QCOMPARE(newAttendee.participationStatus(), attendee.participationStatus());819 QCOMPARE(newAttendee.participationStatus(), attendee.participationStatus());
821 }820 }
821
822 void testExtendedProperties()
823 {
824 static QString displayLabelValue = QStringLiteral("event with collection attendee");
825 static QString descriptionValue = QStringLiteral("event without collection");
826 QOrganizerItemId itemId;
827 QDateTime currentTime = QDateTime::currentDateTime();
828
829 {
830 // create a item with X-URL
831 QOrganizerEvent event;
832 event.setStartDateTime(currentTime);
833 event.setEndDateTime(currentTime.addSecs(60 * 30));
834 event.setDisplayLabel(displayLabelValue);
835 event.setDescription(descriptionValue);
836
837 QOrganizerItemExtendedDetail ex;
838 ex.setName(QStringLiteral("X-URL"));
839 ex.setData(QByteArray("http://canonical.com"));
840 event.saveDetail(&ex);
841
842 // save the new item
843 QtOrganizer::QOrganizerManager::Error error;
844 QMap<int, QtOrganizer::QOrganizerManager::Error> errorMap;
845 QList<QOrganizerItem> items;
846 QSignalSpy createdItem(m_engine, SIGNAL(itemsAdded(QList<QOrganizerItemId>)));
847 items << event;
848 bool saveResult = m_engine->saveItems(&items,
849 QList<QtOrganizer::QOrganizerItemDetail::DetailType>(),
850 &errorMap,
851 &error);
852 QTRY_COMPARE(createdItem.count(), 1);
853 QVERIFY(saveResult);
854 QCOMPARE(error, QOrganizerManager::NoError);
855 QCOMPARE(items.size(), 1);
856 QVERIFY(errorMap.isEmpty());
857 QVERIFY(!items[0].id().isNull());
858 QCOMPARE(items[0].details(QOrganizerItemDetail::TypeExtendedDetail).size(), 1);
859 itemId = items[0].id();
860 }
861
862 // fetch for the item
863 {
864 QtOrganizer::QOrganizerManager::Error error;
865 QMap<int, QtOrganizer::QOrganizerManager::Error> errorMap;
866 QList<QOrganizerItemId> ids;
867 QOrganizerItemFetchHint hint;
868 ids << itemId;
869 QList<QOrganizerItem> items = m_engine->items(ids, hint, &errorMap, &error);
870 QCOMPARE(items.size(), 1);
871
872 QList<QOrganizerItemDetail> exs = items[0].details(QOrganizerItemDetail::TypeExtendedDetail);
873 QCOMPARE(exs.size(), 1);
874 QCOMPARE(exs[0].value(QOrganizerItemExtendedDetail::FieldName).toString(),
875 QStringLiteral("X-URL"));
876 QCOMPARE(exs[0].value(QOrganizerItemExtendedDetail::FieldData).toByteArray(),
877 QByteArray("http://canonical.com"));
878 }
879 }
822};880};
823881
824const QString EventTest::collectionTypePropertyName = QStringLiteral("collection-type");882const QString EventTest::collectionTypePropertyName = QStringLiteral("collection-type");
825883
=== modified file 'tests/unittest/run-eds-test.sh'
--- tests/unittest/run-eds-test.sh 2014-10-28 20:54:11 +0000
+++ tests/unittest/run-eds-test.sh 2015-03-30 17:59:30 +0000
@@ -12,7 +12,7 @@
12export QT_QPA_PLATFORM=minimal12export QT_QPA_PLATFORM=minimal
13export HOME=$TEST_TMP_DIR13export HOME=$TEST_TMP_DIR
14export XDG_RUNTIME_DIR=$TEST_TMP_DIR14export XDG_RUNTIME_DIR=$TEST_TMP_DIR
15export XDG_CACHE_HOME=$TEST_TMP_DIR}/.cache15export XDG_CACHE_HOME=$TEST_TMP_DIR/.cache
16export XDG_CONFIG_HOME=$TEST_TMP_DIR/.config16export XDG_CONFIG_HOME=$TEST_TMP_DIR/.config
17export XDG_DATA_HOME=$TEST_TMP_DIR/.local/share17export XDG_DATA_HOME=$TEST_TMP_DIR/.local/share
18export XDG_DESKTOP_DIR=$TEST_TMP_DIR18export XDG_DESKTOP_DIR=$TEST_TMP_DIR

Subscribers

People subscribed via source and target branches