void CollectionTest::testBuildCollection() { QDomDocument mDocument; mDocument.setContent(collection1, true, 0); Collection::List colist = XmlReader::readCollections(mDocument.documentElement()); QStringList mimeType; mimeType << QStringLiteral("inode/directory") << QStringLiteral("message/rfc822"); QCOMPARE(colist.size(), 1); verifyCollection(colist, 0, QStringLiteral("c11"), QStringLiteral("Inbox"), mimeType); mDocument.setContent(collection2, true, 0); colist = XmlReader::readCollections(mDocument.documentElement()); QCOMPARE(colist.size(), 3); verifyCollection(colist, 0, QStringLiteral("c11"), QStringLiteral("Inbox"), mimeType); verifyCollection(colist, 1, QStringLiteral("c111"), QStringLiteral("KDE PIM"), mimeType); verifyCollection(colist, 2, QStringLiteral("c112"), QStringLiteral("Akonadi"), mimeType); QVERIFY(colist.at(0).hasAttribute<EntityDisplayAttribute>()); EntityDisplayAttribute *attr = colist.at(0).attribute<EntityDisplayAttribute>(); QCOMPARE(attr->displayName(), QStringLiteral("Posteingang")); }
Collection HandlerHelper::collectionFromIdOrName(const QByteArray &id) { // id is a number bool ok = false; qint64 collectionId = id.toLongLong(&ok); if (ok) { return Collection::retrieveById(collectionId); } // id is a path QString path = QString::fromUtf8(id); // ### should be UTF-7 for real IMAP compatibility const QStringList pathParts = path.split(QLatin1Char('/'), QString::SkipEmptyParts); Collection col; for (const QString &part : pathParts) { SelectQueryBuilder<Collection> qb; qb.addValueCondition(Collection::nameColumn(), Query::Equals, part); if (col.isValid()) { qb.addValueCondition(Collection::parentIdColumn(), Query::Equals, col.id()); } else { qb.addValueCondition(Collection::parentIdColumn(), Query::Is, QVariant()); } if (!qb.exec()) { return Collection(); } Collection::List list = qb.result(); if (list.count() != 1) { return Collection(); } col = list.first(); } return col; }
QList<FakeJobResponse *> FakeJobResponse::parseTreeString( FakeServerData *fakeServerData, const QString& treeString) { int depth = 0; QList<FakeJobResponse *> collectionResponseList; QHash<Collection::Id, FakeJobResponse *> itemResponseMap; Collection::List recentCollections; recentCollections.append( Collection::root() ); QList<Token> tokens = tokenize( treeString ); while(!tokens.isEmpty()) { Token token = tokens.takeFirst(); if (token.type == Token::Branch) { ++depth; continue; } Q_ASSERT(token.type == Token::Leaf); parseEntityString( collectionResponseList, itemResponseMap, recentCollections, fakeServerData, token.content, depth ); depth = 0; } return collectionResponseList; }
void RecursiveMover::collectionListResult( KJob *job ) { Q_ASSERT( m_pendingCollections.isEmpty() ); --m_runningJobs; if ( job->error() ) return; // error handling is in the base class // build a parent -> children map for the following topological sorting // while we are iterating anyway, also fill m_collections here CollectionFetchJob *fetchJob = qobject_cast<CollectionFetchJob*>( job ); QHash<Collection::Id, Collection::List> colTree; foreach ( const Collection &col, fetchJob->collections() ) { colTree[col.parentCollection().id()] << col; m_collections.insert( col.id(), col ); } // topological sort; BFS traversal of the tree m_pendingCollections.push_back( m_movedCollection ); QQueue<Collection> toBeProcessed; toBeProcessed.enqueue( m_movedCollection ); while ( !toBeProcessed.isEmpty() ) { const Collection col = toBeProcessed.dequeue(); const Collection::List children = colTree.value( col.id() ); if ( children.isEmpty() ) continue; m_pendingCollections.append( children ); foreach ( const Collection &child, children ) toBeProcessed.enqueue( child ); } replayNextCollection(); }
void CollectionTest::verifyCollection(const Collection::List &colist, int listPosition, const QString &remoteId, const QString &name, const QStringList &mimeType) { QVERIFY(colist.at(listPosition).name() == name); QVERIFY(colist.at(listPosition).remoteId() == remoteId); QVERIFY(colist.at(listPosition).contentMimeTypes() == mimeType); }
void CalendarBaseTest::fetchCollection() { CollectionFetchJob *job = new CollectionFetchJob(Collection::root(), CollectionFetchJob::Recursive, this); // Get list of collections job->fetchScope().setContentMimeTypes(QStringList() << QStringLiteral("application/x-vnd.akonadi.calendar.event")); AKVERIFYEXEC(job); // Find our collection Collection::List collections = job->collections(); QVERIFY(!collections.isEmpty()); mCollection = collections.first(); QVERIFY(mCollection.isValid()); }
void ActionStateManager::updateState(const Collection::List &collections, const Item::List &items) { const int collectionCount = collections.count(); const bool singleCollectionSelected = (collectionCount == 1); const bool multipleCollectionsSelected = (collectionCount > 1); const bool atLeastOneCollectionSelected = (singleCollectionSelected || multipleCollectionsSelected); const int itemCount = items.count(); const bool singleItemSelected = (itemCount == 1); const bool multipleItemsSelected = (itemCount > 1); const bool atLeastOneItemSelected = (singleItemSelected || multipleItemsSelected); const bool listOfCollectionNotEmpty = collections.isEmpty() ? false : true; bool canDeleteCollections = listOfCollectionNotEmpty; if (canDeleteCollections) { foreach (const Collection &collection, collections) { // do we have the necessary rights? if (!(collection.rights() &Collection::CanDeleteCollection)) { canDeleteCollections = false; break; } if (isRootCollection(collection)) { canDeleteCollections = false; break; } if (isResourceCollection(collection)) { canDeleteCollections = false; break; } } } bool canCutCollections = canDeleteCollections; // we must be able to delete for cutting foreach (const Collection &collection, collections) { if (isSpecialCollection(collection)) { canCutCollections = false; break; } if (!isFolderCollection(collection)) { canCutCollections = false; break; } } const bool canMoveCollections = canCutCollections; // we must be able to cut for moving bool canCopyCollections = listOfCollectionNotEmpty; if (canCopyCollections) { foreach (const Collection &collection, collections) { if (isRootCollection(collection)) { canCopyCollections = false; break; } if (!isFolderCollection(collection)) { canCopyCollections = false; break; } } } bool canAddToFavoriteCollections = listOfCollectionNotEmpty; if (canAddToFavoriteCollections) { foreach (const Collection &collection, collections) { if (isRootCollection(collection)) { canAddToFavoriteCollections = false; break; } if (isFavoriteCollection(collection)) { canAddToFavoriteCollections = false; break; } if (!isFolderCollection(collection)) { canAddToFavoriteCollections = false; break; } if (!canContainItems(collection)) { canAddToFavoriteCollections = false; break; } } } bool canRemoveFromFavoriteCollections = listOfCollectionNotEmpty; foreach (const Collection &collection, collections) { if (!isFavoriteCollection(collection)) { canRemoveFromFavoriteCollections = false; break; } } bool collectionsAreFolders = listOfCollectionNotEmpty; foreach (const Collection &collection, collections) { if (!isFolderCollection(collection)) { collectionsAreFolders = false; break; } } bool collectionsAreInTrash = false; foreach (const Collection &collection, collections) { if (collection.hasAttribute<EntityDeletedAttribute>()) { collectionsAreInTrash = true; break; } } bool atLeastOneCollectionCanHaveItems = false; foreach (const Collection &collection, collections) { if (collectionCanHaveItems(collection)) { atLeastOneCollectionCanHaveItems = true; break; } } const Collection collection = (!collections.isEmpty() ? collections.first() : Collection()); // collection specific actions enableAction(StandardActionManager::CreateCollection, singleCollectionSelected && // we can create only inside one collection canCreateSubCollection(collection)); // we need the necessary rights enableAction(StandardActionManager::DeleteCollections, canDeleteCollections); enableAction(StandardActionManager::CopyCollections, canCopyCollections); enableAction(StandardActionManager::CutCollections, canCutCollections); enableAction(StandardActionManager::CopyCollectionToMenu, canCopyCollections); enableAction(StandardActionManager::MoveCollectionToMenu, canMoveCollections); enableAction(StandardActionManager::MoveCollectionsToTrash, atLeastOneCollectionSelected && canMoveCollections && !collectionsAreInTrash); enableAction(StandardActionManager::RestoreCollectionsFromTrash, atLeastOneCollectionSelected && canMoveCollections && collectionsAreInTrash); enableAction(StandardActionManager::CopyCollectionToDialog, canCopyCollections); enableAction(StandardActionManager::MoveCollectionToDialog, canMoveCollections); enableAction(StandardActionManager::CollectionProperties, singleCollectionSelected && // we can only configure one collection at a time !isRootCollection(collection)); // we can not configure the root collection enableAction(StandardActionManager::SynchronizeCollections, atLeastOneCollectionCanHaveItems); // it must be a valid folder collection enableAction(StandardActionManager::SynchronizeCollectionsRecursive, atLeastOneCollectionSelected && collectionsAreFolders); // it must be a valid folder collection #ifndef QT_NO_CLIPBOARD enableAction(StandardActionManager::Paste, singleCollectionSelected && // we can paste only into a single collection PasteHelper::canPaste(QApplication::clipboard()->mimeData(), collection)); // there must be data on the clipboard #else enableAction(StandardActionManager::Paste, false); // no support for clipboard -> no paste #endif // favorite collections specific actions enableAction(StandardActionManager::AddToFavoriteCollections, canAddToFavoriteCollections); enableAction(StandardActionManager::RemoveFromFavoriteCollections, canRemoveFromFavoriteCollections); enableAction(StandardActionManager::RenameFavoriteCollection, singleCollectionSelected && // we can rename only one collection at a time isFavoriteCollection(collection)); // it must be a favorite collection already // resource specific actions int resourceCollectionCount = 0; bool canDeleteResources = true; bool canConfigureResource = true; bool canSynchronizeResources = true; foreach (const Collection &collection, collections) { if (isResourceCollection(collection)) { resourceCollectionCount++; // check that the 'NoConfig' flag is not set for the resource if (hasResourceCapability(collection, QStringLiteral("NoConfig"))) { canConfigureResource = false; } } else { // we selected a non-resource collection canDeleteResources = false; canConfigureResource = false; canSynchronizeResources = false; } } if (resourceCollectionCount == 0) { // not a single resource collection has been selected canDeleteResources = false; canConfigureResource = false; canSynchronizeResources = false; } enableAction(StandardActionManager::CreateResource, true); enableAction(StandardActionManager::DeleteResources, canDeleteResources); enableAction(StandardActionManager::ResourceProperties, canConfigureResource); enableAction(StandardActionManager::SynchronizeResources, canSynchronizeResources); enableAction(StandardActionManager::SynchronizeCollectionTree, canSynchronizeResources); if (collectionsAreInTrash) { updateAlternatingAction(StandardActionManager::MoveToTrashRestoreCollectionAlternative); //updatePluralLabel( StandardActionManager::MoveToTrashRestoreCollectionAlternative, collectionCount ); } else { updateAlternatingAction(StandardActionManager::MoveToTrashRestoreCollection); } enableAction(StandardActionManager::MoveToTrashRestoreCollection, atLeastOneCollectionSelected && canMoveCollections); // item specific actions bool canDeleteItems = (!items.isEmpty()); //TODO: fixme foreach (const Item &item, items) { const Collection parentCollection = item.parentCollection(); if (!parentCollection.isValid()) { continue; } canDeleteItems = canDeleteItems && (parentCollection.rights() &Collection::CanDeleteItem); } bool itemsAreInTrash = false; foreach (const Item &item, items) { if (item.hasAttribute<EntityDeletedAttribute>()) { itemsAreInTrash = true; break; } } enableAction(StandardActionManager::CopyItems, atLeastOneItemSelected); // we need items to work with enableAction(StandardActionManager::CutItems, atLeastOneItemSelected && // we need items to work with canDeleteItems); // we need the necessary rights enableAction(StandardActionManager::DeleteItems, atLeastOneItemSelected && // we need items to work with canDeleteItems); // we need the necessary rights enableAction(StandardActionManager::CopyItemToMenu, atLeastOneItemSelected); // we need items to work with enableAction(StandardActionManager::MoveItemToMenu, atLeastOneItemSelected && // we need items to work with canDeleteItems); // we need the necessary rights enableAction(StandardActionManager::MoveItemsToTrash, atLeastOneItemSelected && canDeleteItems && !itemsAreInTrash); enableAction(StandardActionManager::RestoreItemsFromTrash, atLeastOneItemSelected && itemsAreInTrash); enableAction(StandardActionManager::CopyItemToDialog, atLeastOneItemSelected); // we need items to work with enableAction(StandardActionManager::MoveItemToDialog, atLeastOneItemSelected && // we need items to work with canDeleteItems); // we need the necessary rights if (itemsAreInTrash) { updateAlternatingAction(StandardActionManager::MoveToTrashRestoreItemAlternative); //updatePluralLabel( StandardActionManager::MoveToTrashRestoreItemAlternative, itemCount ); } else { updateAlternatingAction(StandardActionManager::MoveToTrashRestoreItem); } enableAction(StandardActionManager::MoveToTrashRestoreItem, atLeastOneItemSelected && // we need items to work with canDeleteItems); // we need the necessary rights // update the texts of the actions updatePluralLabel(StandardActionManager::CopyCollections, collectionCount); updatePluralLabel(StandardActionManager::CopyItems, itemCount); updatePluralLabel(StandardActionManager::DeleteItems, itemCount); updatePluralLabel(StandardActionManager::CutItems, itemCount); updatePluralLabel(StandardActionManager::CutCollections, collectionCount); updatePluralLabel(StandardActionManager::DeleteCollections, collectionCount); updatePluralLabel(StandardActionManager::SynchronizeCollections, collectionCount); updatePluralLabel(StandardActionManager::SynchronizeCollectionsRecursive, collectionCount); updatePluralLabel(StandardActionManager::DeleteResources, resourceCollectionCount); updatePluralLabel(StandardActionManager::SynchronizeResources, resourceCollectionCount); updatePluralLabel(StandardActionManager::SynchronizeCollectionTree, resourceCollectionCount); }
void FakeJobResponse::parseEntityString( QList<FakeJobResponse *> &collectionResponseList, QHash<Collection::Id, FakeJobResponse *> &itemResponseMap, Collection::List &recentCollections, FakeServerData *fakeServerData, const QString& _entityString, int depth ) { QString entityString = _entityString; if ( entityString.startsWith( 'C' ) ) { Collection collection; entityString.remove( 0, 2 ); Q_ASSERT( entityString.startsWith( '(' ) ); entityString.remove( 0, 1 ); QStringList parts = entityString.split( ')' ); if ( !parts.first().isEmpty() ) { QString typesString = parts.takeFirst(); QStringList types = typesString.split(','); types.replaceInStrings(" ", ""); collection.setContentMimeTypes( types ); } else { parts.removeFirst(); } collection.setId( fakeServerData->nextCollectionId() ); collection.setName( QString("Collection %1").arg( collection.id() ) ); collection.setRemoteId( QString( "remoteId %1" ).arg( collection.id() ) ); if ( depth == 0 ) collection.setParentCollection( Collection::root() ); else collection.setParentCollection( recentCollections.at( depth ) ); if ( recentCollections.size() == ( depth + 1) ) recentCollections.append( collection ); else recentCollections[ depth + 1 ] = collection; int order = 0; if ( !parts.first().isEmpty() ) { QString displayName; QString optionalSection = parts.first().trimmed(); if ( optionalSection.startsWith( QLatin1Char( '\'' ) ) ) { optionalSection.remove( 0, 1 ); QStringList optionalParts = optionalSection.split( QLatin1Char( '\'' ) ); displayName = optionalParts.takeFirst(); EntityDisplayAttribute *eda = new EntityDisplayAttribute(); eda->setDisplayName( displayName ); collection.addAttribute( eda ); optionalSection = optionalParts.first(); } QString orderString = optionalSection.trimmed(); if ( !orderString.isEmpty() ) { bool ok; order = orderString.toInt(&ok); Q_ASSERT(ok); } } else { order = 1; } while ( collectionResponseList.size() < order ) { collectionResponseList.append( new FakeJobResponse( recentCollections[ depth ], FakeJobResponse::RespondToCollectionFetch, fakeServerData ) ); } collectionResponseList[ order - 1 ]->appendCollection( collection ); } if ( entityString.startsWith( 'I' ) ) { Item item; entityString.remove( 0, 2 ); entityString = entityString.trimmed(); QString type; int order = 0; int iFirstSpace = entityString.indexOf( QLatin1Char( ' ' ) ); type = entityString.left( iFirstSpace ); entityString = entityString.remove( 0, iFirstSpace + 1 ).trimmed(); if ( iFirstSpace > 0 && !entityString.isEmpty() ) { QString displayName; QString optionalSection = entityString; if ( optionalSection.startsWith( QLatin1Char( '\'' ) ) ) { optionalSection.remove( 0, 1 ); QStringList optionalParts = optionalSection.split( QLatin1Char( '\'' ) ); displayName = optionalParts.takeFirst(); EntityDisplayAttribute *eda = new EntityDisplayAttribute(); eda->setDisplayName( displayName ); item.addAttribute( eda ); optionalSection = optionalParts.first(); } QString orderString = optionalSection.trimmed(); if ( !orderString.isEmpty() ) { bool ok; order = orderString.toInt( &ok ); Q_ASSERT( ok ); } } else type = entityString; item.setMimeType( type ); item.setId( fakeServerData->nextItemId() ); item.setRemoteId( QString( "RId_%1 %2" ).arg( item.id() ).arg(type) ); item.setParentCollection( recentCollections.at( depth ) ); Collection::Id colId = recentCollections[ depth ].id(); if ( !itemResponseMap.contains( colId ) ) { FakeJobResponse *newResponse = new FakeJobResponse( recentCollections[ depth ], FakeJobResponse::RespondToItemFetch, fakeServerData ); itemResponseMap.insert( colId, newResponse ); collectionResponseList.append( newResponse ); } itemResponseMap[ colId ]->appendItem( item ); } }
void IncidenceChanger::Private::onCollectionsLoaded(KJob *job) { Q_ASSERT(!mPendingCreations.isEmpty()); if (job->error() != 0 || !m_collectionFetchJob) { qCritical() << "Error loading collections:" << job->errorString(); return; } Q_ASSERT(job == m_collectionFetchJob); Akonadi::Collection::List allCollections; foreach (const Akonadi::Collection &collection, m_collectionFetchJob->collections()) { if (collection.rights() & Akonadi::Collection::CanCreateItem) { allCollections << collection; } } m_collectionFetchJob = Q_NULLPTR; bool canceled = false; // These two will never be true, maybe even assert bool noAcl = false; bool invalidCollection = false; Collection collectionToUse; foreach (const Change::Ptr &change, mPendingCreations) { mPendingCreations.removeAll(change); if (canceled) { change->resultCode = ResultCodeUserCanceled; continue; } if (noAcl) { change->resultCode = ResultCodePermissions; continue; } if (invalidCollection) { change->resultCode = ResultCodeInvalidUserCollection; continue; } if (collectionToUse.isValid()) { // We don't show the dialog multiple times step2CreateIncidence(change, collectionToUse); continue; } KCalCore::Incidence::Ptr incidence = CalendarUtils::incidence(change->newItem); Collection::List candidateCollections = collectionsForMimeType(incidence->mimeType(), allCollections); if (candidateCollections.count() == 1 && candidateCollections.first().isValid()) { // We only have 1 writable collection, don't bother the user with a dialog collectionToUse = candidateCollections.first(); qCDebug(AKONADICALENDAR_LOG) << "Only one collection exists, will not show collection dialog: " << collectionToUse.displayName(); step2CreateIncidence(change, collectionToUse); continue; } // Lets ask the user which collection to use: int dialogCode; QWidget *parent = change->parentWidget; const QStringList mimeTypes(incidence->mimeType()); collectionToUse = CalendarUtils::selectCollection(parent, /*by-ref*/dialogCode, mimeTypes, mDefaultCollection); if (dialogCode != QDialog::Accepted) { qCDebug(AKONADICALENDAR_LOG) << "User canceled collection choosing"; change->resultCode = ResultCodeUserCanceled; canceled = true; cancelTransaction(); continue; } if (collectionToUse.isValid() && !hasRights(collectionToUse, ChangeTypeCreate)) { qCWarning(AKONADICALENDAR_LOG) << "No ACLs for incidence creation"; const QString errorMessage = showErrorDialog(ResultCodePermissions, parent); change->resultCode = ResultCodePermissions; change->errorString = errorMessage; noAcl = true; cancelTransaction(); continue; } // TODO: add unit test for these two situations after reviewing API if (!collectionToUse.isValid()) { qCritical() << "Invalid collection selected. Can't create incidence."; change->resultCode = ResultCodeInvalidUserCollection; const QString errorString = showErrorDialog(ResultCodeInvalidUserCollection, parent); change->errorString = errorString; invalidCollection = true; cancelTransaction(); continue; } step2CreateIncidence(change, collectionToUse); }
/****************************************************************************** * Called when a collection fetch job has completed. * Obtains the collection handled by the agent, and configures it. */ void CalendarCreator::collectionFetchResult(KJob* j) { kDebug() << mName; if (j->error()) { mErrorMessage = j->errorString(); kError() << "CollectionFetchJob error: " << mErrorMessage; finish(true); return; } CollectionFetchJob* job = static_cast<CollectionFetchJob*>(j); Collection::List collections = job->collections(); if (collections.isEmpty()) { if (++mCollectionFetchRetryCount >= 10) { mErrorMessage = i18nc("@info/plain", "New configuration timed out"); kError() << "Timeout fetching collection for resource"; finish(true); return; } // Need to wait a bit longer until the resource has initialised and // created its collection. Retry after 200ms. kDebug() << "Retrying"; QTimer::singleShot(200, this, SLOT(fetchCollection())); return; } if (collections.count() > 1) { mErrorMessage = i18nc("@info/plain", "New configuration was corrupt"); kError() << "Wrong number of collections for this resource:" << collections.count(); finish(true); return; } // Set Akonadi Collection attributes Collection collection = collections[0]; collection.setContentMimeTypes(CalEvent::mimeTypes(mAlarmType)); EntityDisplayAttribute* dattr = collection.attribute<EntityDisplayAttribute>(Collection::AddIfMissing); dattr->setIconName("kalarm"); CollectionAttribute* attr = collection.attribute<CollectionAttribute>(Entity::AddIfMissing); attr->setEnabled(mEnabled ? mAlarmType : CalEvent::EMPTY); if (mStandard) attr->setStandard(mAlarmType); if (mColour.isValid()) attr->setBackgroundColor(mColour); // Update the calendar to the current KAlarm format if necessary, // and if the user agrees. bool dirResource = false; switch (mResourceType) { case LocalFile: case RemoteFile: break; case LocalDir: dirResource = true; break; default: Q_ASSERT(0); // Invalid resource type break; } //FIXME: port away of calendarupdater bool keep = true; bool duplicate = false; if (!mReadOnly) { /* CalendarUpdater* updater = new CalendarUpdater(collection, dirResource, false, true, this); duplicate = updater->isDuplicate(); keep = !updater->update(); // note that 'updater' will auto-delete when finished*/ } if (!duplicate) { // Record the user's choice of whether to update the calendar attr->setKeepFormat(keep); } // Update the collection's CollectionAttribute value in the Akonadi database. // Note that we can't supply 'collection' to CollectionModifyJob since // that also contains the CompatibilityAttribute value, which is read-only // for applications. So create a new Collection instance and only set a // value for CollectionAttribute. Collection c(collection.id()); CollectionAttribute* att = c.attribute<CollectionAttribute>(Entity::AddIfMissing); *att = *attr; CollectionModifyJob* cmjob = new CollectionModifyJob(c, this); connect(cmjob, SIGNAL(result(KJob*)), this, SLOT(modifyCollectionJobDone(KJob*))); }
// TODO: test signals void testMove() { QFETCH( Collection, source ); QFETCH( Collection, destination ); QFETCH( bool, crossResource ); QVERIFY( source.isValid() ); QVERIFY( destination.isValid() ); CollectionFetchJob *fetch = new CollectionFetchJob( source, CollectionFetchJob::Base, this ); AKVERIFYEXEC( fetch ); QCOMPARE( fetch->collections().count(), 1 ); source = fetch->collections().first(); // obtain reference listing fetch = new CollectionFetchJob( source, CollectionFetchJob::Recursive ); AKVERIFYEXEC( fetch ); QHash<Collection, Item::List> referenceData; foreach ( const Collection &c, fetch->collections() ) { ItemFetchJob *job = new ItemFetchJob( c, this ); AKVERIFYEXEC( job ); referenceData.insert( c, job->items() ); } // move collection CollectionMoveJob *mod = new CollectionMoveJob( source, destination, this ); AKVERIFYEXEC( mod ); // check if source was modified correctly CollectionFetchJob *ljob = new CollectionFetchJob( source, CollectionFetchJob::Base ); AKVERIFYEXEC( ljob ); Collection::List list = ljob->collections(); QCOMPARE( list.count(), 1 ); Collection col = list.first(); QCOMPARE( col.name(), source.name() ); QCOMPARE( col.parentCollection(), destination ); // list destination and check if everything is still there ljob = new CollectionFetchJob( destination, CollectionFetchJob::Recursive ); AKVERIFYEXEC( ljob ); list = ljob->collections(); QVERIFY( list.count() >= referenceData.count() ); for ( QHash<Collection, Item::List>::ConstIterator it = referenceData.constBegin(); it != referenceData.constEnd(); ++it ) { QVERIFY( list.contains( it.key() ) ); if ( crossResource ) { QVERIFY( list[ list.indexOf( it.key() ) ].resource() != it.key().resource() ); } else { QCOMPARE( list[ list.indexOf( it.key() ) ].resource(), it.key().resource() ); } ItemFetchJob *job = new ItemFetchJob( it.key(), this ); job->fetchScope().fetchFullPayload(); AKVERIFYEXEC( job ); QCOMPARE( job->items().count(), it.value().count() ); foreach ( const Item &item, job->items() ) { QVERIFY( it.value().contains( item ) ); QVERIFY( item.hasPayload() ); } } // cleanup mod = new CollectionMoveJob( col, source.parentCollection(), this ); AKVERIFYEXEC( mod ); }