diff options
author | Tero Ahola <tero.ahola@digia.com> | 2010-09-17 13:05:50 +0300 |
---|---|---|
committer | Tero Ahola <tero.ahola@digia.com> | 2010-09-17 19:05:12 +0300 |
commit | 597c19c6cead71b24c0f5ce9feff547e09b57496 (patch) | |
tree | 2a035271e6b839e2b6a6cbd2ff5f949ba58b066c | |
parent | b54394a65628dbe22f31bb44070b91154479aae4 (diff) |
Symbian: Implemented multical item instance fetch and modify
Also refactored completely the item instance fetch related functions.
This was needed because the previous implementation had a lot of
memory leak and readability issues.
12 files changed, 380 insertions, 255 deletions
diff --git a/plugins/organizer/symbian/organizeritemtransform.cpp b/plugins/organizer/symbian/organizeritemtransform.cpp index 02634108ed..93ece58f01 100644 --- a/plugins/organizer/symbian/organizeritemtransform.cpp +++ b/plugins/organizer/symbian/organizeritemtransform.cpp @@ -193,7 +193,9 @@ void OrganizerItemTransform::toItemPostSaveL(const CCalEntry &entry, QOrganizerI item->setId(itemId); } -void OrganizerItemTransform::toItemInstanceL(const CCalInstance &instance, QOrganizerItem *itemInstance) const +void OrganizerItemTransform::toItemInstanceL( + const CCalInstance &instance, + QOrganizerItem *itemInstance) const { //debugInstanceL(instance); diff --git a/plugins/organizer/symbian/organizeritemtransform.h b/plugins/organizer/symbian/organizeritemtransform.h index 8191aa0561..9e3ed4135d 100644 --- a/plugins/organizer/symbian/organizeritemtransform.h +++ b/plugins/organizer/symbian/organizeritemtransform.h @@ -67,7 +67,7 @@ public: void toItemL(const CCalEntry &entry, QOrganizerItem *item) const; void toItemPostSaveL(const CCalEntry &entry, QOrganizerItem *item, QString managerUri) const; void toItemInstanceL(const CCalInstance &instance, QOrganizerItem *itemInstance) const; - + private: QList<OrganizerItemDetailTransform *> m_detailTransforms; }; diff --git a/plugins/organizer/symbian/organizersymbiancollection.cpp b/plugins/organizer/symbian/organizersymbiancollection.cpp index a5dfd01320..c59ee052c2 100644 --- a/plugins/organizer/symbian/organizersymbiancollection.cpp +++ b/plugins/organizer/symbian/organizersymbiancollection.cpp @@ -43,6 +43,7 @@ #include <QDebug> #include <calsession.h> #include <calentryview.h> +#include <calinstanceview.h> #include "organizersymbianutils.h" #include "qorganizeritemchangeset.h" #include "qorganizeritemmanagerengine.h" @@ -54,6 +55,7 @@ OrganizerSymbianCollectionPrivate::OrganizerSymbianCollectionPrivate() m_engine(0), m_calSession(0), m_calEntryView(0), + m_calInstanceView(0), m_calCollectionId(0), m_error(0) { @@ -65,6 +67,7 @@ OrganizerSymbianCollectionPrivate::~OrganizerSymbianCollectionPrivate() if (m_calSession) m_calSession->StopChangeNotification(); delete m_calEntryView; + delete m_calInstanceView; delete m_calSession; delete m_activeSchedulerWait; } @@ -164,6 +167,8 @@ void OrganizerSymbianCollection::openL(const TDesC &fileName) d->m_calSession->StopChangeNotification(); delete d->m_calEntryView; d->m_calEntryView = 0; + delete d->m_calInstanceView; + d->m_calInstanceView = 0; delete d->m_calSession; d->m_calSession = 0; @@ -226,12 +231,17 @@ void OrganizerSymbianCollection::openL(const TDesC &fileName) delete filter; } -void OrganizerSymbianCollection::createEntryViewL() +void OrganizerSymbianCollection::createViewsL() { // Create an entry view d->m_calEntryView = CCalEntryView::NewL(*d->m_calSession, *d); d->m_activeSchedulerWait->Start(); // stopped at Completed() User::LeaveIfError(d->m_error); + + // Create an instance view + d->m_calInstanceView = CCalInstanceView::NewL(*d->m_calSession, *d); + d->m_activeSchedulerWait->Start(); + User::LeaveIfError(d->m_error); } QOrganizerCollectionId OrganizerSymbianCollection::id() const @@ -259,6 +269,11 @@ CCalEntryView *OrganizerSymbianCollection::calEntryView() const return d->m_calEntryView; } +CCalInstanceView *OrganizerSymbianCollection::calInstanceView() const +{ + return d->m_calInstanceView; +} + QString OrganizerSymbianCollection::fileName() const { return d->m_fileName; diff --git a/plugins/organizer/symbian/organizersymbiancollection.h b/plugins/organizer/symbian/organizersymbiancollection.h index 6aeb9ef42d..1822a3b37b 100644 --- a/plugins/organizer/symbian/organizersymbiancollection.h +++ b/plugins/organizer/symbian/organizersymbiancollection.h @@ -52,6 +52,7 @@ class QOrganizerItemManagerEngine; QTM_END_NAMESPACE class CCalSession; class CCalEntryView; +class CCalInstanceView; class CCalCalendarInfo; class OrganizerSymbianCollectionPrivate : public QSharedData, @@ -70,6 +71,7 @@ public: QOrganizerItemManagerEngine *m_engine; CCalSession *m_calSession; CCalEntryView *m_calEntryView; + CCalInstanceView *m_calInstanceView; QOrganizerCollectionId m_id; quint32 m_calCollectionId; CActiveSchedulerWait *m_activeSchedulerWait; @@ -89,12 +91,13 @@ public: #else void openL(const TDesC &fileName); #endif - void createEntryViewL(); + void createViewsL(); QOrganizerCollectionId id() const; QOrganizerCollectionLocalId localId() const; quint32 calCollectionId() const; CCalSession *calSession() const; CCalEntryView *calEntryView() const; + CCalInstanceView *calInstanceView() const; QString fileName() const; bool isValid() const; bool isMarkedForDeletionL() const; diff --git a/plugins/organizer/symbian/qorganizersymbian.cpp b/plugins/organizer/symbian/qorganizersymbian.cpp index f8ecf11286..44fa91178c 100644 --- a/plugins/organizer/symbian/qorganizersymbian.cpp +++ b/plugins/organizer/symbian/qorganizersymbian.cpp @@ -62,6 +62,7 @@ #include "organizeritemguidtransform.h" #include "qorganizeritemrequestqueue.h" #include "organizersymbianutils.h" +#include "resetanddestroy.h" using namespace OrganizerSymbianUtils; @@ -233,6 +234,7 @@ uint QOrganizerCollectionSymbianEngineLocalId::hash() const // valid. The error code is not expected to clash with any symbian calendar // API errors. const TInt KErrInvalidOccurrence(-32768); +const TInt KErrInvalidItemType(-32769); QOrganizerItemManagerEngine* QOrganizerItemSymbianFactory::engine( const QMap<QString, QString>& parameters, @@ -275,8 +277,7 @@ Q_EXPORT_PLUGIN2(qtorganizer_symbian, QOrganizerItemSymbianFactory); QOrganizerItemSymbianEngine::QOrganizerItemSymbianEngine() : QOrganizerItemManagerEngine(), - m_defaultCollection(this), - m_activeSchedulerWait(0) + m_defaultCollection(this) { } @@ -285,9 +286,9 @@ void QOrganizerItemSymbianEngine::initializeL() { // Open the default collection m_defaultCollection.openL(KNullDesC); - m_collections.insert(m_defaultCollection.localId(), m_defaultCollection); - m_defaultCollection.createEntryViewL(); - + m_collections.insert(m_defaultCollection.localId(), m_defaultCollection); + m_defaultCollection.createViewsL(); + #ifdef SYMBIAN_CALENDAR_V2 // Start listening to calendar file changes m_defaultCollection.calSession()->StartFileChangeNotificationL(*this); @@ -318,20 +319,12 @@ void QOrganizerItemSymbianEngine::initializeL() OrganizerSymbianCollection collection(this); collection.openL(calInfo->FileNameL()); m_collections.insert(collection.localId(), collection); - collection.createEntryViewL(); - + collection.createViewsL(); + CleanupStack::PopAndDestroy(calInfo); } CleanupStack::PopAndDestroy(iterator); #endif - - m_instanceView = CCalInstanceView::NewL(*m_defaultCollection.calSession(), *this); - // TODO: multical instance view(s) - // TODO: The calendar session may take some time to initialize which would - // make an UI app using symbian backend freeze. To be refactored. - m_activeSchedulerWait = new CActiveSchedulerWait(); - m_activeSchedulerWait->Start(); - // Create request queue for asynch requests m_requestServiceProviderQueue = QOrganizerItemRequestQueue::instance(*this); } @@ -342,8 +335,6 @@ QOrganizerItemSymbianEngine::~QOrganizerItemSymbianEngine() m_defaultCollection.calSession()->StopFileChangeNotification(); #endif delete m_requestServiceProviderQueue; - delete m_activeSchedulerWait; - delete m_instanceView; } QString QOrganizerItemSymbianEngine::managerName() const @@ -364,186 +355,163 @@ int QOrganizerItemSymbianEngine::managerVersion() const } QList<QOrganizerItem> QOrganizerItemSymbianEngine::itemInstances( - const QOrganizerItem& generator, const QDateTime& periodStart, - const QDateTime& periodEnd, int maxCount, + const QOrganizerItem& generator, + const QDateTime& periodStart, + const QDateTime& periodEnd, + int maxCount, QOrganizerItemManager::Error* error) const { - QList<QOrganizerItem> occurrenceList; + QList<QOrganizerItem> itemInstances; + TRAPD(err, itemInstancesL(itemInstances, generator, periodStart, periodEnd, maxCount)); + if (err != KErrNone) { + transformError(err, error); + return QList<QOrganizerItem>(); + } + return itemInstances; +} - quint32 defaultCollectionLocalIdValue = 0; - QOrganizerCollectionSymbianEngineLocalId* idPtr = static_cast<QOrganizerCollectionSymbianEngineLocalId*>(QOrganizerItemManagerEngine::engineLocalCollectionId(m_defaultCollection.localId())); - if (idPtr != 0) - defaultCollectionLocalIdValue = idPtr->m_localCollectionId; - - // Parent item should be an Event or a Todo - if (!((generator.type()== QOrganizerItemType::TypeEvent) ||(generator.type()== QOrganizerItemType::TypeTodo))) { - *error = QOrganizerItemManager::InvalidItemTypeError; - return occurrenceList; +void QOrganizerItemSymbianEngine::itemInstancesL( + QList<QOrganizerItem> &itemInstances, + const QOrganizerItem &generator, + const QDateTime &periodStart, + const QDateTime &periodEnd, + int maxCount) const +{ + // Check parameters + if (periodStart.isValid() && periodEnd.isValid() && periodEnd < periodStart) { + User::Leave(KErrArgument); } - //check for valid periodStart - if (periodStart.isValid()&&(periodEnd.isValid() || (maxCount > 0))) { - - // End period should be greater than start period. - if (periodEnd.isValid() && (periodEnd < periodStart)) { - *error = QOrganizerItemManager::BadArgumentError; - return occurrenceList; - } - RPointerArray<CCalInstance> instanceList; - QDateTime endDateTime(periodEnd); - CalCommon::TCalViewFilter filter(0); - //use maximum end date if only count is present. - if ((!periodEnd.isValid()) && (maxCount > 0)) { - TCalTime endTime; - endTime.SetTimeUtcL(TCalTime::MaxTime()); - endDateTime = toQDateTimeL(endTime); - } - - if (generator.type() == QOrganizerItemType::TypeEvent) { - filter = CalCommon::EIncludeAppts; - } else if (generator.type() == QOrganizerItemType::TypeTodo) { - filter = (CalCommon::EIncludeCompletedTodos | - CalCommon::EIncludeIncompletedTodos); - } - #ifdef SYMBIAN_CALENDAR_V2 - CCalInstanceIterator *iterator(NULL); - CCalFindInstanceSettings *findIntanceSettings = CCalFindInstanceSettings::NewL(filter, - CalCommon::TCalTimeRange(toTCalTimeL(periodStart), - toTCalTimeL(endDateTime))); - CleanupStack::PushL(findIntanceSettings); - - TRAPD(err,iterator = m_instanceView->FindInstanceL(*findIntanceSettings)); - CleanupStack::PopAndDestroy(findIntanceSettings); - CleanupStack::PushL(iterator); - #else - - TRAPD(err, m_instanceView->FindInstanceL(instanceList,filter, - CalCommon::TCalTimeRange( - toTCalTimeL(periodStart), - toTCalTimeL(endDateTime)) - )); - #endif - transformError(err, error); - - if (*error == QOrganizerItemManager::NoError) { - #ifdef SYMBIAN_CALENDAR_V2 - int count(iterator->Count()); - #else - int count(instanceList.Count()); - #endif - // Convert calninstance list to QOrganizerEventOccurrence and add to QOrganizerItem list - for( int index=0; index < count;index++ ) { - QOrganizerItem itemInstance; - CCalInstance* calInstance(NULL); - #ifdef SYMBIAN_CALENDAR_V2 - calInstance = iterator->NextL(); - #else - calInstance = (instanceList)[index]; - #endif - CleanupStack::PushL(calInstance); - - if (QOrganizerItemType::TypeEvent == generator.type()) - itemInstance.setType(QOrganizerItemType::TypeEventOccurrence); - else if (QOrganizerItemType::TypeTodo == generator.type()) - itemInstance.setType(QOrganizerItemType::TypeTodoOccurrence); - else - User::Leave(KErrNotSupported); - - TRAPD(err, m_itemTransform.toItemInstanceL(*calInstance, &itemInstance)); - transformError(err, error); - if ((*error == QOrganizerItemManager::NoError)&&(generator.guid() == itemInstance.guid())) { - if ((periodEnd.isValid()&& (maxCount < 0))||(maxCount > 0) && (index < maxCount)) { - QOrganizerItemId id; - id.setManagerUri(this->managerUri()); - // The instance might be modified. Then it will not point to the parent entry. - // In this case local id must be set. Otherwise it should be zero. - QOrganizerItemLocalId instanceEntryId(new QOrganizerItemSymbianEngineLocalId(defaultCollectionLocalIdValue, calInstance->Entry().LocalUidL())); - if (instanceEntryId != generator.localId()) - id.setLocalId(instanceEntryId); - itemInstance.setId(id); - occurrenceList.append(itemInstance); - } - } - CleanupStack::PopAndDestroy(calInstance); - } - } - #ifdef SYMBIAN_CALENDAR_V2 - CleanupStack::PopAndDestroy(iterator); - #else - instanceList.Close(); - #endif - + // Set cal view filter based on the item type + // TODO: move to transform classes? + CalCommon::TCalViewFilter filter(0); + QString itemType; + if (generator.type() == QOrganizerItemType::TypeEvent) { + itemType = QOrganizerItemType::TypeEventOccurrence.latin1(); + filter = CalCommon::EIncludeAppts | CalCommon::EIncludeEvents; + } else if (generator.type() == QOrganizerItemType::TypeTodo) { + itemType = QOrganizerItemType::TypeTodoOccurrence.latin1(); + filter = (CalCommon::EIncludeCompletedTodos | CalCommon::EIncludeIncompletedTodos); } else { - *error = QOrganizerItemManager::BadArgumentError; + User::Leave(KErrInvalidItemType); + } + + // If start time is not defined, use minimum start date + TCalTime startTime; + startTime.SetTimeUtcL(TCalTime::MinTime()); + if (periodStart.isValid()) + startTime.SetTimeUtcL(toTTime(periodStart, Qt::UTC)); + + // If end date is not defined, use maximum end date + TCalTime endTime; + endTime.SetTimeUtcL(TCalTime::MaxTime()); + if (periodEnd.isValid()) + endTime.SetTimeUtcL(toTTime(periodEnd, Qt::UTC)); + + // Loop through all the instance views and fetch the item instances + foreach(QOrganizerCollectionLocalId collectionId, m_collections.keys()) { + RPointerArray<CCalInstance> instanceList; + CleanupResetAndDestroyPushL(instanceList); + instanceViewL(collectionId)->FindInstanceL(instanceList, filter, + CalCommon::TCalTimeRange(startTime, endTime)); + // Transform CCalInstances to QOrganizerItems + toItemInstancesL(instanceList, generator, maxCount, collectionId, itemInstances); + CleanupStack::PopAndDestroy(&instanceList); } - - return occurrenceList; } + QList<QOrganizerItem> QOrganizerItemSymbianEngine::itemInstances( - const QOrganizerItemFilter& filter, - const QList<QOrganizerItemSortOrder>& sortOrders, + const QOrganizerItemFilter& filter, + const QList<QOrganizerItemSortOrder>& sortOrders, const QOrganizerItemFetchHint& fetchHint, QOrganizerItemManager::Error* error) const { + QList<QOrganizerItem> itemInstances; + TRAPD(err, itemInstancesL(itemInstances, filter, sortOrders, fetchHint)); + if (err != KErrNone) { + transformError(err, error); + return QList<QOrganizerItem>(); + } + return itemInstances; +} + +QList<QOrganizerItem> QOrganizerItemSymbianEngine::itemInstancesL( + QList<QOrganizerItem> &itemInstances, + const QOrganizerItemFilter &filter, + const QList<QOrganizerItemSortOrder> &sortOrders, + const QOrganizerItemFetchHint &fetchHint) const +{ + // TODO: It might be possible to optimize by using fetch hint Q_UNUSED(fetchHint); - QList<QOrganizerItem> occurrenceList; + TCalTime startTime; startTime.SetTimeUtcL(TCalTime::MinTime()); - TCalTime endTime; endTime.SetTimeUtcL(TCalTime::MaxTime()); - RPointerArray<CCalInstance> instanceList; - TRAPD(err, m_instanceView->FindInstanceL(instanceList,CalCommon::EIncludeAll, - CalCommon::TCalTimeRange(startTime,endTime))); + // Loop through all the instance views and fetch the item instances + foreach(QOrganizerCollectionLocalId collectionId, m_collections.keys()) { + RPointerArray<CCalInstance> instanceList; + CleanupResetAndDestroyPushL(instanceList); + instanceViewL(collectionId)->FindInstanceL( + instanceList, CalCommon::EIncludeAll, + CalCommon::TCalTimeRange(startTime, endTime)); + // Transform CCalInstances to QOrganizerItems + toItemInstancesL(instanceList, QOrganizerItem(), -1, collectionId, itemInstances); + CleanupStack::PopAndDestroy(&instanceList); + } + + // Use the general implementation to filter and sort items + itemInstances = slowFilter(itemInstances, filter, sortOrders); + return itemInstances; +} + +void QOrganizerItemSymbianEngine::toItemInstancesL( + const RPointerArray<CCalInstance> &calInstanceList, + QOrganizerItem generator, + const int maxCount, + QOrganizerCollectionLocalId collectionLocalId, + QList<QOrganizerItem> &itemInstances) const +{ // find the default collection local id value quint32 defaultCollectionLocalIdValue = 0; QOrganizerCollectionSymbianEngineLocalId* idPtr = static_cast<QOrganizerCollectionSymbianEngineLocalId*>(QOrganizerItemManagerEngine::engineLocalCollectionId(m_defaultCollection.localId())); if (idPtr != 0) defaultCollectionLocalIdValue = idPtr->m_localCollectionId; - - transformError(err, error); - //Convert instance list to list of QOrganizerItem - if (*error == QOrganizerItemManager::NoError) { - int count(instanceList.Count()); - // Convert calninstance list to QOrganizerEventOccurrence and add to QOrganizerItem list - for( int index=0; index < count;index++ ) { - QOrganizerItem itemInstance; - CCalInstance* calInstance = (instanceList)[index]; - - TRAPD(err, m_itemTransform.toItemInstanceL(*calInstance, &itemInstance)); - transformError(err, error); - if (*error == QOrganizerItemManager::NoError) { - QOrganizerItemId id; - id.setManagerUri(this->managerUri()); - - // The instance might be modified. Then it will not point to the parent entry. - // In this case local id must be set. Otherwise it should be zero. - if (calInstance->Entry().RecurrenceIdL().TimeUtcL() != Time::NullTTime()) { - QOrganizerItemLocalId instanceEntryId(new QOrganizerItemSymbianEngineLocalId(defaultCollectionLocalIdValue, calInstance->Entry().LocalUidL())); - id.setLocalId(instanceEntryId); - itemInstance.setId(id); - } - occurrenceList.append(itemInstance); - } - } - } else { - instanceList.ResetAndDestroy(); - return occurrenceList; + + // Transform all the instances to QOrganizerItems + for(int i(0); i < calInstanceList.Count(); i++) { + QOrganizerItem itemInstance; + CCalInstance* calInstance = calInstanceList[i]; + m_itemTransform.toItemInstanceL(*calInstance, &itemInstance); + + // Optimization: if a generator instance is defined, skip the instances that do not match + if (!generator.isEmpty() && generator.guid() != itemInstance.guid()) + continue; + + // Check if maxCount limit is reached + if(maxCount > 0 && i >= maxCount) + break; + + // Set item id + QOrganizerItemId id; + id.setManagerUri(managerUri()); + // Set local id if this is an exceptional item + if (calInstance->Entry().RecurrenceIdL().TimeUtcL() != Time::NullTTime()) { + QOrganizerItemLocalId instanceEntryId(new QOrganizerItemSymbianEngineLocalId(defaultCollectionLocalIdValue, calInstance->Entry().LocalUidL())); + id.setLocalId(instanceEntryId); + } + itemInstance.setId(id); + + // Set collection id + QOrganizerCollectionId cid; + cid.setLocalId(collectionLocalId); + cid.setManagerUri(managerUri()); + setItemCollectionId(&itemInstance, cid); + + itemInstances.append(itemInstance); } - instanceList.ResetAndDestroy(); - - //Check whether no filtering and sorting needed.Return complete list. - if (filter == QOrganizerItemInvalidFilter() && sortOrders.count() == 0) - return occurrenceList; - - // Use the general implementation to filter and sort items - QList<QOrganizerItem> filteredAndSortedItemList = slowFilter(occurrenceList, filter, sortOrders); - occurrenceList.clear(); - occurrenceList.append(filteredAndSortedItemList); - - return occurrenceList; } QList<QOrganizerItemLocalId> QOrganizerItemSymbianEngine::itemIds(const QOrganizerItemFilter& filter, const QList<QOrganizerItemSortOrder>& sortOrders, QOrganizerItemManager::Error* error) const @@ -704,14 +672,14 @@ void QOrganizerItemSymbianEngine::itemL(const QOrganizerItemLocalId& itemId, itemLocalIdValue = idPtr->m_localItemId; // Fetch item - TCalLocalUid uid(itemLocalIdValue); + TCalLocalUid localId(itemLocalIdValue); CCalEntry *calEntry(0); QOrganizerCollectionLocalId collectionLocalId(new QOrganizerCollectionSymbianEngineLocalId(0)); foreach (const OrganizerSymbianCollection &collection, m_collections) { // TODO: instead of looping through entry views, get the collection id from // local id? (not certain that is the correct way, because the Qt API for // collections is still under development) - calEntry = collection.calEntryView()->FetchL(uid); + calEntry = collection.calEntryView()->FetchL(localId); if (calEntry) { collectionLocalId = collection.localId(); break; @@ -820,9 +788,9 @@ void QOrganizerItemSymbianEngine::saveItemL(QOrganizerItem *item, bool isNewEntry(false); if(item->type()== QOrganizerItemType::TypeEventOccurrence || item->type()== QOrganizerItemType::TypeTodoOccurrence) { - entry = entryForItemOccurrenceL(collectionId, item, isNewEntry); + entry = entryForItemOccurrenceL(collectionLocalId, item, isNewEntry); } else { - entry = entryForItemL(collectionId, item, isNewEntry); + entry = entryForItemL(collectionLocalId, item, isNewEntry); } CleanupStack::PushL(entry); @@ -834,7 +802,7 @@ void QOrganizerItemSymbianEngine::saveItemL(QOrganizerItem *item, CleanupClosePushL(entries); entries.AppendL(entry); TInt count(0); - entryViewL(collectionId)->StoreL(entries, count); + entryViewL(collectionLocalId)->StoreL(entries, count); if (count != entries.Count()) { // The documentation states about count "On return, this // contains the number of entries which were successfully stored". @@ -848,7 +816,7 @@ void QOrganizerItemSymbianEngine::saveItemL(QOrganizerItem *item, // Set collection id QOrganizerCollectionId cid; - cid.setLocalId(collectionLocalIdL(*item, collectionId)); + cid.setLocalId(collectionLocalId); cid.setManagerUri(managerUri()); setItemCollectionId(item, cid); @@ -874,7 +842,7 @@ CCalEntryView* QOrganizerItemSymbianEngine::entryViewL( { QOrganizerCollectionLocalId tempCollectionId = collectionId; - // 0 is interpreted as the default collection + // Null is interpreted as the default collection if (tempCollectionId.isNull()) tempCollectionId = m_defaultCollection.localId(); @@ -885,6 +853,24 @@ CCalEntryView* QOrganizerItemSymbianEngine::entryViewL( } /*! + * Retrieves the instance view for the collection. Leaves with KErrArgument if + * not found. + */ +CCalInstanceView* QOrganizerItemSymbianEngine::instanceViewL(const QOrganizerCollectionLocalId& collectionId) const +{ + QOrganizerCollectionLocalId tempCollectionId = collectionId; + + // Null is interpreted as the default collection + if (tempCollectionId.isNull()) + tempCollectionId = m_defaultCollection.localId(); + + if (!m_collections.contains(tempCollectionId)) + User::Leave(KErrArgument); + + return m_collections[tempCollectionId].calInstanceView(); +} + +/*! * Returns item's collection id if it is valid. If not returns collectionId * given as a parameter if it is valid. Fallback is to return the default * session's collection id. @@ -924,7 +910,7 @@ CCalEntry* QOrganizerItemSymbianEngine::entryForItemOccurrenceL( User::Leave(KErrInvalidOccurrence); // Fetch the item (will return NULL if the localid is not found) - entry = entryViewL(collectionLocalIdL(*item))->FetchL(toTCalLocalUid(item->localId())); + entry = entryViewL(collectionId)->FetchL(toTCalLocalUid(item->localId())); if (!entry) User::Leave(KErrInvalidOccurrence); return entry; @@ -1158,7 +1144,11 @@ QList<QOrganizerItem> QOrganizerItemSymbianEngine::slowFilter( const QList<QOrganizerItemSortOrder>& sortOrders) const { QList<QOrganizerItem> filteredAndSorted; - + + // TODO: should we return the complete list in case of invalid filter? + if (filter == QOrganizerItemInvalidFilter() && sortOrders.count() == 0) + return items; + if (filter != QOrganizerItemInvalidFilter()) { foreach(const QOrganizerItem& item, items) { if (QOrganizerItemManagerEngine::testFilter(filter, item)) @@ -1263,8 +1253,8 @@ bool QOrganizerItemSymbianEngine::saveCollection( if (*error == QOrganizerItemManager::NoError) { if (isNewCollection) - emit collectionsAdded(QList<QOrganizerCollectionLocalId>() << - collection->id().localId()); + emit collectionsAdded(QList<QOrganizerCollectionLocalId>() + << collection->id().localId()); // NOTE: collectionsChanged signal will be emitted from // CalendarInfoChangeNotificationL } @@ -1312,7 +1302,7 @@ void QOrganizerItemSymbianEngine::saveCollectionL( // Create a new collection symbianCollection.openL(toPtrC16(fileName), calInfo); m_collections.insert(symbianCollection.localId(), symbianCollection); - symbianCollection.createEntryViewL(); + symbianCollection.createViewsL(); } else { // Cannot allow changing the filename for an existing collection @@ -1572,35 +1562,6 @@ QStringList QOrganizerItemSymbianEngine::supportedItemTypes() const return ret; } -/*! - * From MCalProgressCallBack - */ -void QOrganizerItemSymbianEngine::Progress(TInt /*aPercentageCompleted*/) -{ -} - -/*! - * From MCalProgressCallBack - */ -void QOrganizerItemSymbianEngine::Completed(TInt aError) -{ - Q_UNUSED(aError) - // TODO: How to handle aError? The client should be informed that the - // initialization failed - - // Let's continue the operation that started the calendar operation - m_activeSchedulerWait->AsyncStop(); -} - -/*! - * From MCalProgressCallBack - */ -TBool QOrganizerItemSymbianEngine::NotifyProgress() -{ - // No - return EFalse; -} - #ifdef SYMBIAN_CALENDAR_V2 void QOrganizerItemSymbianEngine::CalendarInfoChangeNotificationL( RPointerArray<CCalFileChangeInfo>& aCalendarInfoChangeEntries) @@ -1633,7 +1594,7 @@ void QOrganizerItemSymbianEngine::CalendarInfoChangeNotificationL( // instance. collection.openL(fileName); m_collections.insert(collection.localId(), collection); - collection.createEntryViewL(); + collection.createViewsL(); collectionsAdded << collection.localId(); } break; @@ -1666,7 +1627,7 @@ void QOrganizerItemSymbianEngine::CalendarInfoChangeNotificationL( } else { // Calendar file has been modified but we do not have a session // to it. - collection.openL(fileName); + collection.openL(fileName); // Is it marked for deletion? if (collection.isMarkedForDeletionL()) { @@ -1676,7 +1637,7 @@ void QOrganizerItemSymbianEngine::CalendarInfoChangeNotificationL( // A calendar file which was marked for deletion has been // taken into use again. m_collections.insert(collection.localId(), collection); - collection.createEntryViewL(); + collection.createViewsL(); collectionsAdded << collection.localId(); } } @@ -1759,6 +1720,11 @@ bool QOrganizerItemSymbianEngine::transformError(TInt symbianError, QOrganizerIt *qtError = QOrganizerItemManager::InvalidOccurrenceError; break; } + case KErrInvalidItemType: + { + *qtError = QOrganizerItemManager::InvalidItemTypeError; + break; + } default: { *qtError = QOrganizerItemManager::UnspecifiedError; diff --git a/plugins/organizer/symbian/qorganizersymbian_p.h b/plugins/organizer/symbian/qorganizersymbian_p.h index 7f10871c07..471f503992 100644 --- a/plugins/organizer/symbian/qorganizersymbian_p.h +++ b/plugins/organizer/symbian/qorganizersymbian_p.h @@ -193,8 +193,8 @@ class QOrganizerItemRequestQueue; class CCalCalendarInfo; #endif -class QOrganizerItemSymbianEngine : public QOrganizerItemManagerEngine, - public MCalProgressCallBack +class QOrganizerItemSymbianEngine : public QOrganizerItemManagerEngine + #ifdef SYMBIAN_CALENDAR_V2 ,public MCalFileChangeObserver #endif @@ -307,11 +307,28 @@ public: /* Util functions */ static bool transformError(TInt symbianError, QOrganizerItemManager::Error* qtError); - void saveItemL(QOrganizerItem *item, - const QOrganizerCollectionLocalId& collectionId, - QOrganizerItemChangeSet *changeSet); + void itemInstancesL( + QList<QOrganizerItem> &itemInstances, + const QOrganizerItem &generator, + const QDateTime &periodStart, + const QDateTime &periodEnd, + int maxCount) const; + QList<QOrganizerItem> itemInstancesL( + QList<QOrganizerItem> &itemInstances, + const QOrganizerItemFilter &filter, + const QList<QOrganizerItemSortOrder> &sortOrders, + const QOrganizerItemFetchHint &fetchHint) const; + void toItemInstancesL( + const RPointerArray<CCalInstance> &calInstanceList, + QOrganizerItem generator, + const int maxCount, + QOrganizerCollectionLocalId collectionLocalId, + QList<QOrganizerItem> &itemInstances) const; void itemL(const QOrganizerItemLocalId& itemId, QOrganizerItem *item, const QOrganizerItemFetchHint& fetchHint) const; + void saveItemL(QOrganizerItem *item, + const QOrganizerCollectionLocalId& collectionId, + QOrganizerItemChangeSet *changeSet); void removeItemL(const QOrganizerItemLocalId& organizeritemId); QList<QOrganizerItem> slowFilter(const QList<QOrganizerItem> &items, const QOrganizerItemFilter& filter, @@ -327,8 +344,8 @@ public: #endif private: - CCalEntryView* entryViewL( - const QOrganizerCollectionLocalId& collectionId) const; + CCalEntryView* entryViewL(const QOrganizerCollectionLocalId& collectionId) const; + CCalInstanceView* instanceViewL(const QOrganizerCollectionLocalId& collectionId) const; QOrganizerCollectionLocalId collectionLocalIdL(QOrganizerItem item, const QOrganizerCollectionLocalId& collectionId = QOrganizerCollectionLocalId()) const; CCalEntry* entryForItemOccurrenceL( @@ -348,8 +365,6 @@ private: OrganizerSymbianCollection m_defaultCollection; QMap<QOrganizerCollectionLocalId, OrganizerSymbianCollection> m_collections; - CCalInstanceView *m_instanceView; - CActiveSchedulerWait *m_activeSchedulerWait; QOrganizerItemRequestQueue* m_requestServiceProviderQueue; OrganizerItemTransform m_itemTransform; mutable QMap<QString, QMap<QString, QOrganizerItemDetailDefinition> > m_definition; diff --git a/plugins/organizer/symbian/resetanddestroy.h b/plugins/organizer/symbian/resetanddestroy.h new file mode 100644 index 0000000000..f7dcba88b4 --- /dev/null +++ b/plugins/organizer/symbian/resetanddestroy.h @@ -0,0 +1,76 @@ +/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+//system includes
+
+#ifndef CLEANUPRESETANDDESTROY_H
+#define CLEANUPRESETANDDESTROY_H
+
+template <class T>
+
+/*!
+ * A helper class for pushing a pointer array into cleanup stack + */
+class CleanupResetAndDestroy
+{
+public:
+ inline static void PushL(T &obj);
+private:
+ static void ResetAndDestroy(TAny *obj);
+};
+
+template <class T> inline void CleanupResetAndDestroyPushL(T &obj);
+
+template <class T> inline void CleanupResetAndDestroy<T>::PushL(T &obj)
+{
+ CleanupStack::PushL(TCleanupItem(&ResetAndDestroy, &obj));
+}
+
+template <class T> void CleanupResetAndDestroy<T>::ResetAndDestroy(TAny *obj)
+{
+ static_cast<T*>(obj)->ResetAndDestroy();
+}
+
+template <class T> inline void CleanupResetAndDestroyPushL(T &obj)
+{
+ CleanupResetAndDestroy<T>::PushL(obj);
+}
+
+#endif // CLEANUPRESETANDDESTROY_H
diff --git a/plugins/organizer/symbian/symbian.pro b/plugins/organizer/symbian/symbian.pro index edabee6a16..105f14da18 100644 --- a/plugins/organizer/symbian/symbian.pro +++ b/plugins/organizer/symbian/symbian.pro @@ -36,6 +36,7 @@ symbian: { organizersymbiancollection.h \ organizersymbianutils.h \ organizeritemtransform.h \ + resetanddestroy.h \ transform/organizeritemdetailtransform.h \ transform/organizereventtimerangetransform.h \ transform/organizeritemdescriptiontransform.h \ @@ -50,7 +51,8 @@ symbian: { transform/organizerjournaltimerangetransform.h \ transform/organizertodoprogresstransform.h \ transform/organizertodotimerangetransform.h \ - transform/organizeritemremindertransform.h + transform/organizeritemremindertransform.h + SOURCES += \ qorganizeritemrequestqueue.cpp \ organizeritemrequestserviceprovider.cpp \ @@ -72,7 +74,7 @@ symbian: { transform/organizerjournaltimerangetransform.cpp \ transform/organizertodoprogresstransform.cpp \ transform/organizertodotimerangetransform.cpp \ - transform/organizeritemremindertransform.cpp + transform/organizeritemremindertransform.cpp LIBS += -lcalinterimapi diff --git a/plugins/organizer/symbian/transform/organizeritemtypetransform.cpp b/plugins/organizer/symbian/transform/organizeritemtypetransform.cpp index 7a6ebc6232..7e0b46d6f5 100644 --- a/plugins/organizer/symbian/transform/organizeritemtypetransform.cpp +++ b/plugins/organizer/symbian/transform/organizeritemtypetransform.cpp @@ -77,8 +77,6 @@ void OrganizerItemTypeTransform::transformToDetailL(const CCalEntry& entry, QOrg else User::Leave(KErrUnknown); // unknown type - // TODO: CCalEntry::EReminder - item->setType(itemType); } @@ -98,8 +96,6 @@ void OrganizerItemTypeTransform::transformToDetailL(const CCalInstance& instance else User::Leave(KErrUnknown); // unknown type - // TODO: CCalEntry::EReminder - itemInstance->setType(itemType); } diff --git a/plugins/organizer/symbian/tsrc/tst_itemoccurrence/tst_itemoccurrence.cpp b/plugins/organizer/symbian/tsrc/tst_itemoccurrence/tst_itemoccurrence.cpp index 632a282f1c..a96f86d1e0 100644 --- a/plugins/organizer/symbian/tsrc/tst_itemoccurrence/tst_itemoccurrence.cpp +++ b/plugins/organizer/symbian/tsrc/tst_itemoccurrence/tst_itemoccurrence.cpp @@ -265,6 +265,7 @@ void tst_ItemOccurrence::fetchOccurrenceByFilterSort() //fetch instances and modify displaylabel for second and third instance QList<QOrganizerItem> instanceList; instanceList = m_om->itemInstances(item,startTime,QDateTime(),10); + QCOMPARE(instanceList.count(), 3); instanceList[1].setDisplayLabel(modifiedLabel); instanceList[2].setDisplayLabel(modifiedLabel); QVERIFY(m_om->saveItem(&instanceList[1])); @@ -754,17 +755,20 @@ void tst_ItemOccurrence::fetchNegative() instanceList = m_om->itemInstances(invalidItem,startTime,endTime); QCOMPARE(m_om->error(), QOrganizerItemManager::InvalidItemTypeError); - // Fetch the item instance with invalid count - instanceList = m_om->itemInstances(item,startTime,QDateTime(),-2); - QCOMPARE(m_om->error(), QOrganizerItemManager::BadArgumentError); - - // Fetch the item instance with invalid starttime - instanceList = m_om->itemInstances(item,QDateTime(),endTime); - QCOMPARE(m_om->error(), QOrganizerItemManager::BadArgumentError); - - // Fetch the item instance with invalid endtime - instanceList = m_om->itemInstances(item,startTime,QDateTime()); - QCOMPARE(m_om->error(), QOrganizerItemManager::BadArgumentError); + // Fetch the item instance with negative count + instanceList = m_om->itemInstances(item, startTime, QDateTime(), -2); + QCOMPARE(m_om->error(), QOrganizerItemManager::NoError); + QCOMPARE(instanceList.count(), 1); + + // Fetch the item instance with undefined starttime + instanceList = m_om->itemInstances(item, QDateTime(), endTime); + QCOMPARE(m_om->error(), QOrganizerItemManager::NoError); + QCOMPARE(instanceList.count(), 1); + + // Fetch the item instance with undefined endtime + instanceList = m_om->itemInstances(item, startTime, QDateTime()); + QCOMPARE(m_om->error(), QOrganizerItemManager::NoError); + QCOMPARE(instanceList.count(), 1); } void tst_ItemOccurrence::daylightSavingTime() diff --git a/plugins/organizer/symbian/tsrc/tst_symbianom/tst_symbianom.cpp b/plugins/organizer/symbian/tsrc/tst_symbianom/tst_symbianom.cpp index a26a44eddb..9338d940c3 100644 --- a/plugins/organizer/symbian/tsrc/tst_symbianom/tst_symbianom.cpp +++ b/plugins/organizer/symbian/tsrc/tst_symbianom/tst_symbianom.cpp @@ -717,12 +717,11 @@ void tst_SymbianOm::addReminderToSingleInstance() instance1 = m_om->item(instance1.localId()); rptReminder = instance1.detail<QOrganizerItemReminder>(); QVERIFY(!rptReminder.isEmpty()); - + // Verify that the other instances have not been modified - itemInstances = m_om->itemInstances(repeatingEvent, QDateTime::currentDateTime(), QDateTime(), 3); - instance1 = itemInstances.at(1); - rptReminder = instance1.detail<QOrganizerItemReminder>(); - QVERIFY(rptReminder.isEmpty()); + itemInstances = m_om->itemInstances(repeatingEvent, QDateTime::currentDateTime(), QDateTime(), 3); + QCOMPARE(itemInstances.count(), 3); + QVERIFY(itemInstances.at(1).detail<QOrganizerItemReminder>().isEmpty()); } /*! @@ -776,9 +775,8 @@ void tst_SymbianOm::removeReminderFromSingleInstance() // Check if the other instances are intact itemInstances = m_om->itemInstances(repeatingEvent, QDateTime::currentDateTime(), QDateTime(), 3); - instance1 = itemInstances.at(1); - rptReminder = instance1.detail<QOrganizerItemReminder>(); - QVERIFY(!rptReminder.isEmpty()); + QCOMPARE(itemInstances.count(), 3); + QVERIFY(!itemInstances.at(1).detail<QOrganizerItemReminder>().isEmpty()); } void tst_SymbianOm::timezone() diff --git a/plugins/organizer/symbian/tsrc/tst_symbianomcollections/tst_symbianomcollections.cpp b/plugins/organizer/symbian/tsrc/tst_symbianomcollections/tst_symbianomcollections.cpp index 8b42a6c0cd..1cc38eb0da 100644 --- a/plugins/organizer/symbian/tsrc/tst_symbianomcollections/tst_symbianomcollections.cpp +++ b/plugins/organizer/symbian/tsrc/tst_symbianomcollections/tst_symbianomcollections.cpp @@ -131,6 +131,9 @@ private slots: // Test cases void fetchItemInstance_data(){ addManagers(); }; void fetchItemInstance(); + void modifyItemInstance_data(){ addManagers(); }; + void modifyItemInstance(); + // TODO: test all known properties //void collectionProperties_data(); //void collectionProperties(); @@ -654,9 +657,54 @@ void tst_symbianomcollections::fetchItemInstance() QVERIFY(m_om->saveItem(&item, c.id().localId())); // Verify - QCOMPARE(m_om->itemInstances().count(), 5); QCOMPARE(m_om->items().count(), 1); QCOMPARE(m_om->items().at(0).collectionId(), c.id()); + QCOMPARE(m_om->itemInstances().count(), 5); + QVERIFY(m_om->itemInstances().at(0).localId() == 0); + QVERIFY(m_om->itemInstances().at(1).localId() == 0); + QCOMPARE(m_om->itemInstances().at(0).type(), QLatin1String(QOrganizerItemType::TypeEventOccurrence)); + QCOMPARE(m_om->itemInstances().at(1).type(), QLatin1String(QOrganizerItemType::TypeEventOccurrence)); +} + +void tst_symbianomcollections::modifyItemInstance() +{ + // Save a collection + QOrganizerCollection c; + c.setMetaData("Name", "modifyItemInstance"); + c.setMetaData("FileName", "c:modifyiteminstance"); + QVERIFY(m_om->saveCollection(&c)); + + // Save a weekly recurring item + QOrganizerItem item = createItem(QOrganizerItemType::TypeEvent, + QString("modifyiteminstance"), + QDateTime::currentDateTime().addMSecs(3600)); + QOrganizerItemRecurrenceRule rrule; + rrule.setFrequency(QOrganizerItemRecurrenceRule::Weekly); + rrule.setCount(5); + QList<QOrganizerItemRecurrenceRule> rrules; + rrules.append(rrule); + QOrganizerItemRecurrence recurrence; + recurrence.setRecurrenceRules(rrules); + QVERIFY(item.saveDetail(&recurrence)); + QVERIFY(m_om->saveItem(&item, c.id().localId())); + QCOMPARE(m_om->itemInstances().count(), 5); + + // Modify the second instance + QOrganizerItem secondInstance = m_om->itemInstances().at(1); + secondInstance.setDisplayLabel("secondinstance"); + QVERIFY(m_om->saveItem(&secondInstance)); + + // Verify + QCOMPARE(m_om->itemInstances().count(), 5); + QCOMPARE(m_om->itemInstances().at(0).collectionId(), c.id()); + QCOMPARE(m_om->itemInstances().at(1).collectionId(), c.id()); + QCOMPARE(m_om->itemInstances().at(2).collectionId(), c.id()); + QVERIFY(m_om->itemInstances().at(0).localId() == 0); + QVERIFY(m_om->itemInstances().at(1).localId() != 0); + QVERIFY(m_om->itemInstances().at(2).localId() == 0); + QCOMPARE(m_om->itemInstances().at(0).displayLabel(), QString("modifyiteminstance")); + QCOMPARE(m_om->itemInstances().at(1).displayLabel(), QString("secondinstance")); + QCOMPARE(m_om->itemInstances().at(2).displayLabel(), QString("modifyiteminstance")); } /*! |