kde-playground/kdepimlibs/akonadi/actionstatemanager.cpp
2015-04-14 21:49:29 +00:00

422 lines
16 KiB
C++

/*
Copyright (c) 2010 Tobias Koenig <tokoe@kde.org>
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 <akonadi/entitydeletedattribute.h>
#include <QApplication>
#include <QClipboard>
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<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, 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<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);
}
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<SpecialCollectionAttribute>();
}
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));
}