mirror of
https://bitbucket.org/smil3y/kde-playground.git
synced 2025-02-23 10:22:50 +00:00
422 lines
16 KiB
C++
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));
|
|
}
|