void RetrieveItemsJob::Private::akonadiFetchResult(KJob *job) { if (job->error() != 0) { return; // handled by base class } ItemFetchJob *itemFetch = qobject_cast<ItemFetchJob *>(job); Q_ASSERT(itemFetch != 0); Item::List items = itemFetch->items(); itemFetch->clearItems(); // save memory qCDebug(MIXEDMAILDIR_LOG) << "Akonadi fetch got" << items.count() << "items"; mServerItemsByRemoteId.reserve(items.size()); for (int i = 0; i < items.count(); ++i) { Item &item = items[i]; // items without remoteId have not been written to the resource yet if (!item.remoteId().isEmpty()) { // set the parent collection (with all ancestors) in every item item.setParentCollection(mCollection); mServerItemsByRemoteId.insert(item.remoteId(), item); } } qCDebug(MIXEDMAILDIR_LOG) << "of which" << mServerItemsByRemoteId.count() << "have remoteId"; FileStore::ItemFetchJob *storeFetch = mStore->fetchItems(mCollection); // just basic items, no data connect(storeFetch, SIGNAL(result(KJob*)), q, SLOT(storeListResult(KJob*))); }
Item::Iterator::Ptr CardinalityVerifier::evaluateSequence(const DynamicContext::Ptr &context) const { const Item::Iterator::Ptr it(m_operand->evaluateSequence(context)); const Item next(it->next()); if(next) { const Item next2(it->next()); if(next2) { if(m_reqCard.allowsMany()) { Item::List start; start.append(next); start.append(next2); return Item::Iterator::Ptr(new InsertionIterator(it, 1, makeListIterator(start))); } else { context->error(wrongCardinality(m_reqCard, Cardinality::twoOrMore()), m_errorCode, this); return CommonValues::emptyIterator; } } else { /* We might be instantiated for the empty sequence. */ if(m_reqCard.isEmpty()) { context->error(wrongCardinality(m_reqCard, Cardinality::twoOrMore()), m_errorCode, this); return CommonValues::emptyIterator; } else return makeSingletonIterator(next); } } else { if(m_reqCard.allowsEmpty()) return CommonValues::emptyIterator; else { context->error(wrongCardinality(m_reqCard, Cardinality::twoOrMore()), m_errorCode, this); return CommonValues::emptyIterator; } } }
Item::Iterator::Ptr Path::evaluateSequence(const DynamicContext::Ptr &context) const { /* Note, we use the old context for m_operand1. */ const Item::Iterator::Ptr source(m_operand1->evaluateSequence(context)); const DynamicContext::Ptr focus(context->createFocus()); focus->setFocusIterator(source); const Item::Iterator::Ptr result(makeSequenceMappingIterator<Item>(ConstPtr(this), source, focus)); if(m_checkXPTY0018) { /* This is an expensive code path, but it should happen very rarely. */ enum FoundItem { FoundNone, FoundNode, FoundAtomicValue } hasFound = FoundNone; Item::List whenChecked; Item next(result->next()); while(next) { const FoundItem found = next.isAtomicValue() ? FoundAtomicValue : FoundNode; if(hasFound != FoundNone && hasFound != found) { /* It's an atomic value and we've already found a node. Mixed content. */ context->error(QtXmlPatterns::tr("The last step in a path must contain either nodes " "or atomic values. It cannot be a mixture between the two."), ReportContext::XPTY0018, this); } else hasFound = found; whenChecked.append(next); next = result->next(); } return makeListIterator(whenChecked); } else return result; }
bool GeneralComparison::evaluateEBV(const DynamicContext::Ptr &context) const { const Item::Iterator::Ptr it1(m_operand1->evaluateSequence(context)); Item item1(it1->next()); if(!item1) return false; const Item::Iterator::Ptr it2(m_operand2->evaluateSequence(context)); Item::List cache; Item item2; while(true) { item2 = it2->next(); if(!item2) break; if(generalCompare(item1, item2, context)) return true; cache.append(item2); } while(true) { item1 = it1->next(); if(!item1) return false; const Item::List::const_iterator end(cache.constEnd()); Item::List::const_iterator it(cache.constBegin()); for(; it != end; ++it) if(generalCompare(item1, *it, context)) return true; } Q_ASSERT(false); return false; }
void InfoCommand::onItemsFetched(KJob *job) { if (job->error() != 0) { emit error(job->errorString()); emit finished(RuntimeError); return; } ItemFetchJob *fetchJob = qobject_cast<ItemFetchJob *>(job); Q_ASSERT(fetchJob!=0); Item::List items = fetchJob->items(); if (items.count()<1) { emit error(i18nc("@info:shell", "Cannot find '%1' as a collection or item", mEntityArg)); emit finished(RuntimeError); return; } mInfoItem = new Item(items.first()); fetchParentPath(mInfoItem->parentCollection()); }
Expression::Ptr Expression::constantPropagate(const StaticContext::Ptr &context) const { Q_ASSERT(context); /* Optimization: We rewrite literals to literals here, which is pointless. * Maybe we should have a property which says "doesn't disable elimination * but don't eliminate me." */ if(staticType()->cardinality().allowsMany()) { Item::Iterator::Ptr it(evaluateSequence(context->dynamicContext())); Item::List result; Item item(it->next()); while(item) { result.append(item); item = it->next(); } switch(result.count()) { case 0: return EmptySequence::create(this, context); case 1: return rewrite(Expression::Ptr(new Literal(result.first())), context); default: return rewrite(Expression::Ptr(new LiteralSequence(result)), context); } } else { const Item item(evaluateSingleton(context->dynamicContext())); if(item) return rewrite(Expression::Ptr(new Literal(item)), context); else return EmptySequence::create(this, context); } }
LiteralSequence::LiteralSequence(const Item::List &list) : m_list(list) { Q_ASSERT(list.size() >= 2); }
void testLink() { SearchCreateJob *create = new SearchCreateJob( "linkTestFolder", "dummy query", this ); AKVERIFYEXEC( create ); CollectionFetchJob *list = new CollectionFetchJob( Collection( 1 ), CollectionFetchJob::Recursive, this ); AKVERIFYEXEC( list ); Collection col; foreach ( const Collection &c, list->collections() ) { if ( c.name() == "linkTestFolder" ) { col = c; } } QVERIFY( col.isValid() ); Item::List items; items << Item( 3 ) << Item( 4 ) << Item( 6 ); Monitor *monitor = new Monitor( this ); monitor->setCollectionMonitored( col ); monitor->itemFetchScope().fetchFullPayload(); qRegisterMetaType<Akonadi::Collection>(); qRegisterMetaType<Akonadi::Item>(); QSignalSpy lspy( monitor, SIGNAL(itemLinked(Akonadi::Item,Akonadi::Collection)) ); QSignalSpy uspy( monitor, SIGNAL(itemUnlinked(Akonadi::Item,Akonadi::Collection)) ); QVERIFY( lspy.isValid() ); QVERIFY( uspy.isValid() ); LinkJob *link = new LinkJob( col, items, this ); AKVERIFYEXEC( link ); QTest::qWait( 1000 ); QVERIFY( uspy.isEmpty() ); QCOMPARE( lspy.count(), 3 ); QList<QVariant> arg = lspy.takeFirst(); Item item = arg.at( 0 ).value<Item>(); QCOMPARE( item.mimeType(), QString::fromLatin1( "application/octet-stream" ) ); QVERIFY( item.hasPayload<QByteArray>() ); lspy.clear(); ItemFetchJob *fetch = new ItemFetchJob( col ); AKVERIFYEXEC( fetch ); QCOMPARE( fetch->items().count(), 3 ); foreach ( const Item &item, fetch->items() ) { QVERIFY( items.contains( item ) ); } UnlinkJob *unlink = new UnlinkJob( col, items, this ); AKVERIFYEXEC( unlink ); QTest::qWait( 1000 ); QVERIFY( lspy.isEmpty() ); QCOMPARE( uspy.count(), 3 ); fetch = new ItemFetchJob( col ); AKVERIFYEXEC( fetch ); QCOMPARE( fetch->items().count(), 0 ); }
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 RetrieveItemsJob::Private::storeListResult(KJob *job) { qCDebug(MIXEDMAILDIRRESOURCE_LOG) << "storeList->error=" << job->error(); FileStore::ItemFetchJob *storeList = qobject_cast<FileStore::ItemFetchJob *>(job); Q_ASSERT(storeList != 0); if (storeList->error() != 0) { q->setError(storeList->error()); q->setErrorText(storeList->errorText()); q->emitResult(); return; } // if some items have tags, we need to complete the retrieval and schedule tagging // to a later time so we can then fetch the items to get their Akonadi URLs // forward the property to this instance so the resource can take care of that const QVariant var = storeList->property("remoteIdToTagList"); if (var.isValid()) { q->setProperty("remoteIdToTagList", var); } const qint64 collectionTimestamp = mCollection.remoteRevision().toLongLong(); const Item::List storedItems = storeList->items(); for (const Item &item : storedItems) { // messages marked as deleted have been deleted from mbox files but never got purged Akonadi::MessageStatus status; status.setStatusFromFlags(item.flags()); if (status.isDeleted()) { mItemsMarkedAsDeleted << item; continue; } mAvailableItems << item; const QHash<QString, Item>::iterator it = mServerItemsByRemoteId.find(item.remoteId()); if (it == mServerItemsByRemoteId.end()) { // item not in server items -> new mNewItems << item; } else { // item both on server and in store, check modification time const QDateTime modTime = item.modificationTime(); if (!modTime.isValid() || modTime.toMSecsSinceEpoch() > collectionTimestamp) { mChangedItems << it.value(); } // remove from hash so only no longer existing items remain mServerItemsByRemoteId.erase(it); } } qCDebug(MIXEDMAILDIR_LOG) << "Store fetch got" << storedItems.count() << "items" << "of which" << mNewItems.count() << "are new and" << mChangedItems.count() << "are changed and" << mServerItemsByRemoteId.count() << "need to be removed"; // all items remaining in mServerItemsByRemoteId are no longer in the store if (!mServerItemsByRemoteId.isEmpty()) { ItemDeleteJob *deleteJob = new ItemDeleteJob(Akonadi::valuesToVector(mServerItemsByRemoteId), transaction()); transaction()->setIgnoreJobFailure(deleteJob); } processNewItem(); }
void DupeTest::testDupes() { QFETCH(QString, message); QFETCH(int, count); QFETCH(int, delay); // clean sink ItemFetchJob *fjob = new ItemFetchJob(sink, this); AKVERIFYEXEC(fjob); if (fjob->items().count() > 0) { // this test is needed because ItemDeleteJob gives error if no items are found ItemDeleteJob *djob = new ItemDeleteJob(sink, this); AKVERIFYEXEC(djob); } fjob = new ItemFetchJob(sink, this); AKVERIFYEXEC(fjob); QCOMPARE(fjob->items().count(), 0); // queue messages Q_ASSERT(monitor); QSignalSpy *addSpy = new QSignalSpy(monitor, SIGNAL(itemAdded(Akonadi::Item,Akonadi::Collection))); qDebug() << "Queuing" << count << "messages..."; for (int i = 0; i < count; i++) { //qDebug() << "Queuing message" << i + 1 << "of" << count; Message::Ptr msg = Message::Ptr(new Message); msg->setContent(QStringLiteral("%1-msg%2\n").arg(message).arg(i + 1, 2, 10, QLatin1Char('0')).toLatin1()); MessageQueueJob *job = new MessageQueueJob(this); job->setMessage(msg); job->transportAttribute().setTransportId(TransportManager::self()->defaultTransportId()); // default dispatch mode // default sent-mail collection job->addressAttribute().setFrom(QStringLiteral("naiba")); job->addressAttribute().setTo(QStringList() << QStringLiteral("dracu")); //AKVERIFYEXEC( job ); job->start(); QTest::qWait(delay); } qDebug() << "Queued" << count << "messages."; // wait for the MDA to send them int seconds = 0; while (true) { seconds++; QTest::qWait(1000); qDebug() << seconds << "seconds elapsed." << addSpy->count() << "messages got to sink."; if (addSpy->count() >= count) { break; } #if 0 if (seconds >= TIMEOUT_SECONDS) { qDebug() << "Timeout, gdb master!"; QTest::qWait(1000 * 1000); } #endif QVERIFY2(seconds < TIMEOUT_SECONDS, "Timeout"); } // TODO I should verify that the MDA has actually finished its work and has an empty queue QTest::qWait(2000); // verify what has been sent fjob = new ItemFetchJob(sink, this); fjob->fetchScope().fetchFullPayload(); AKVERIFYEXEC(fjob); const Item::List items = fjob->items(); int found[ MAXCOUNT ]; for (int i = 0; i < count; i++) { found[i] = 0; } for (int i = 0; i < items.count(); i++) { QVERIFY(items[i].hasPayload<Message::Ptr>()); Message::Ptr msg = items[i].payload<Message::Ptr>(); const QByteArray content = msg->encodedContent(); //qDebug() << "i" << i << "content" << content; int loc = content.indexOf("-msg"); QVERIFY(loc >= 0); bool ok; int who = content.mid(loc + 4, 2).toInt(&ok); QVERIFY(ok); //qDebug() << "identified msg" << who; QVERIFY(who > 0 && who <= count); found[ who - 1 ]++; } for (int i = 0; i < count; i++) { if (found[i] > 1) { qDebug() << "found duplicate message" << i + 1 << "(" << found[i] << "times )"; } else if (found[i] < 1) { qDebug() << "didn't find message" << i + 1; } QCOMPARE(found[i], 1); } QCOMPARE(addSpy->count(), count); QCOMPARE(items.count(), count); }