예제 #1
0
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();
}
예제 #2
0
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());
}
예제 #3
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);

}
/******************************************************************************
* 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*)));
}