/* Copyright (c) 2010 Tobias Koenig This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "actionstatemanager_p.h" #include "agentmanager.h" #include "collectionutils_p.h" #include "pastehelper_p.h" #include "specialcollectionattribute_p.h" #include "standardactionmanager.h" #include #include #include using namespace Akonadi; static bool canCreateSubCollection(const Collection &collection) { if (!(collection.rights() & Collection::CanCreateCollection)) { return false; } if (!collection.contentMimeTypes().contains(Collection::mimeType()) && !collection.contentMimeTypes().contains(Collection::virtualMimeType())) { return false; } return true; } static inline bool canContainItems(const Collection &collection) { if (collection.contentMimeTypes().isEmpty()) { return false; } if ((collection.contentMimeTypes().count() == 1) && ((collection.contentMimeTypes().first() == Collection::mimeType()) || (collection.contentMimeTypes().first() == Collection::virtualMimeType()))) { return false; } return true; } ActionStateManager::ActionStateManager() : mReceiver(0) { } ActionStateManager::~ActionStateManager() { } void ActionStateManager::setReceiver(QObject *object) { mReceiver = object; } 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()) { 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, QLatin1String("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); if (collectionsAreInTrash) { updateAlternatingAction(StandardActionManager::MoveToTrashRestoreCollectionAlternative); //updatePluralLabel( StandardActionManager::MoveToTrashRestoreCollectionAlternative, collectionCount ); } else { updateAlternatingAction(StandardActionManager::MoveToTrashRestoreCollection); } enableAction(StandardActionManager::MoveToTrashRestoreCollection, atLeastOneCollectionSelected && canMoveCollections); // item specific actions bool canDeleteItems = (items.count() > 0); //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()) { 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); } bool ActionStateManager::isRootCollection(const Collection &collection) const { return CollectionUtils::isRoot(collection); } bool ActionStateManager::isResourceCollection(const Collection &collection) const { return CollectionUtils::isResource(collection); } bool ActionStateManager::isFolderCollection(const Collection &collection) const { return (CollectionUtils::isFolder(collection) || CollectionUtils::isResource(collection) || CollectionUtils::isStructural(collection)); } bool ActionStateManager::isSpecialCollection(const Collection &collection) const { return collection.hasAttribute(); } bool ActionStateManager::isFavoriteCollection(const Collection &collection) const { if (!mReceiver) { return false; } bool result = false; QMetaObject::invokeMethod(mReceiver, "isFavoriteCollection", Qt::DirectConnection, Q_RETURN_ARG(bool, result), Q_ARG(Akonadi::Collection, collection)); return result; } bool ActionStateManager::hasResourceCapability(const Collection &collection, const QString &capability) const { const Akonadi::AgentInstance instance = AgentManager::self()->instance(collection.resource()); return instance.type().capabilities().contains(capability); } bool ActionStateManager::collectionCanHaveItems(const Collection &collection) const { return !(collection.contentMimeTypes() == (QStringList() << QLatin1String("inode/directory")) || CollectionUtils::isStructural(collection)); } void ActionStateManager::enableAction(int action, bool state) { if (!mReceiver) { return; } QMetaObject::invokeMethod(mReceiver, "enableAction", Qt::DirectConnection, Q_ARG(int, action), Q_ARG(bool, state)); } void ActionStateManager::updatePluralLabel(int action, int count) { if (!mReceiver) { return; } QMetaObject::invokeMethod(mReceiver, "updatePluralLabel", Qt::DirectConnection, Q_ARG(int, action), Q_ARG(int, count)); } void ActionStateManager::updateAlternatingAction(int action) { if (!mReceiver) { return; } QMetaObject::invokeMethod(mReceiver, "updateAlternatingAction", Qt::DirectConnection, Q_ARG(int, action)); }