akonadi
actionstatemanager.cpp
00001 /* 00002 Copyright (c) 2010 Tobias Koenig <tokoe@kde.org> 00003 00004 This library is free software; you can redistribute it and/or modify it 00005 under the terms of the GNU Library General Public License as published by 00006 the Free Software Foundation; either version 2 of the License, or (at your 00007 option) any later version. 00008 00009 This library is distributed in the hope that it will be useful, but WITHOUT 00010 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 00011 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public 00012 License for more details. 00013 00014 You should have received a copy of the GNU Library General Public License 00015 along with this library; see the file COPYING.LIB. If not, write to the 00016 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 00017 02110-1301, USA. 00018 */ 00019 00020 #include "actionstatemanager_p.h" 00021 00022 #include "agentmanager.h" 00023 #include "collectionutils_p.h" 00024 #include "pastehelper_p.h" 00025 #include "specialcollectionattribute_p.h" 00026 #include "standardactionmanager.h" 00027 00028 #include <akonadi/entitydeletedattribute.h> 00029 00030 #include <QtGui/QApplication> 00031 #include <QtGui/QClipboard> 00032 00033 using namespace Akonadi; 00034 00035 static bool canCreateSubCollection( const Collection &collection ) 00036 { 00037 if ( !( collection.rights() & Collection::CanCreateCollection ) ) 00038 return false; 00039 00040 if ( !collection.contentMimeTypes().contains( Collection::mimeType() ) ) 00041 return false; 00042 00043 return true; 00044 } 00045 00046 static inline bool canContainItems( const Collection &collection ) 00047 { 00048 if ( collection.contentMimeTypes().isEmpty() ) 00049 return false; 00050 00051 if ( (collection.contentMimeTypes().count() == 1) && 00052 (collection.contentMimeTypes().first() == Collection::mimeType()) ) 00053 return false; 00054 00055 return true; 00056 } 00057 00058 ActionStateManager::ActionStateManager() 00059 : mReceiver( 0 ) 00060 { 00061 } 00062 00063 ActionStateManager::~ActionStateManager() 00064 { 00065 } 00066 00067 void ActionStateManager::setReceiver( QObject *object ) 00068 { 00069 mReceiver = object; 00070 } 00071 00072 void ActionStateManager::updateState( const Collection::List &collections, const Item::List &items ) 00073 { 00074 const int collectionCount = collections.count(); 00075 const bool singleCollectionSelected = (collectionCount == 1); 00076 const bool multipleCollectionsSelected = (collectionCount > 1); 00077 const bool atLeastOneCollectionSelected = (singleCollectionSelected || multipleCollectionsSelected); 00078 00079 const int itemCount = items.count(); 00080 const bool singleItemSelected = (itemCount == 1); 00081 const bool multipleItemsSelected = (itemCount > 1); 00082 const bool atLeastOneItemSelected = (singleItemSelected || multipleItemsSelected); 00083 00084 const bool listOfCollectionNotEmpty = collections.isEmpty() ? false : true; 00085 bool canDeleteCollections = listOfCollectionNotEmpty; 00086 if ( canDeleteCollections ) 00087 { 00088 foreach ( const Collection &collection, collections ) { 00089 // do we have the necessary rights? 00090 if ( !(collection.rights() & Collection::CanDeleteCollection) ) { 00091 canDeleteCollections = false; 00092 break; 00093 } 00094 00095 if ( isRootCollection( collection ) ) { 00096 canDeleteCollections = false; 00097 break; 00098 } 00099 00100 if ( isResourceCollection( collection ) ) { 00101 canDeleteCollections = false; 00102 break; 00103 } 00104 } 00105 } 00106 00107 bool canCutCollections = canDeleteCollections; // we must be able to delete for cutting 00108 foreach ( const Collection &collection, collections ) { 00109 if ( isSpecialCollection( collection ) ) { 00110 canCutCollections = false; 00111 break; 00112 } 00113 00114 if ( !isFolderCollection( collection ) ) { 00115 canCutCollections = false; 00116 break; 00117 } 00118 } 00119 00120 const bool canMoveCollections = canCutCollections; // we must be able to cut for moving 00121 00122 bool canCopyCollections = listOfCollectionNotEmpty; 00123 if ( canCopyCollections ) { 00124 foreach ( const Collection &collection, collections ) { 00125 if ( isRootCollection( collection ) ) { 00126 canCopyCollections = false; 00127 break; 00128 } 00129 00130 if ( !isFolderCollection( collection ) ) { 00131 canCopyCollections = false; 00132 break; 00133 } 00134 } 00135 } 00136 bool canAddToFavoriteCollections = listOfCollectionNotEmpty; 00137 if ( canAddToFavoriteCollections ) { 00138 foreach ( const Collection &collection, collections ) { 00139 if ( isRootCollection( collection ) ) { 00140 canAddToFavoriteCollections = false; 00141 break; 00142 } 00143 00144 if ( isFavoriteCollection( collection ) ) { 00145 canAddToFavoriteCollections = false; 00146 break; 00147 } 00148 00149 if ( !isFolderCollection( collection ) ) { 00150 canAddToFavoriteCollections = false; 00151 break; 00152 } 00153 00154 if ( !canContainItems( collection ) ) { 00155 canAddToFavoriteCollections = false; 00156 break; 00157 } 00158 } 00159 } 00160 bool canRemoveFromFavoriteCollections = listOfCollectionNotEmpty; 00161 foreach ( const Collection &collection, collections ) { 00162 if ( !isFavoriteCollection( collection ) ) { 00163 canRemoveFromFavoriteCollections = false; 00164 break; 00165 } 00166 } 00167 00168 bool collectionsAreFolders = listOfCollectionNotEmpty; 00169 00170 foreach ( const Collection &collection, collections ) { 00171 if ( !isFolderCollection( collection ) ) { 00172 collectionsAreFolders = false; 00173 break; 00174 } 00175 } 00176 00177 bool collectionsAreInTrash = false; 00178 foreach ( const Collection &collection, collections ) { 00179 if ( collection.hasAttribute<EntityDeletedAttribute>() ) { 00180 collectionsAreInTrash = true; 00181 break; 00182 } 00183 } 00184 00185 bool atLeastOneCollectionCanHaveItems = false; 00186 foreach ( const Collection &collection, collections ) { 00187 if ( collectionCanHaveItems( collection ) ) { 00188 atLeastOneCollectionCanHaveItems = true; 00189 break; 00190 } 00191 } 00192 00193 const Collection collection = (!collections.isEmpty() ? collections.first() : Collection()); 00194 00195 // collection specific actions 00196 enableAction( StandardActionManager::CreateCollection, singleCollectionSelected && // we can create only inside one collection 00197 canCreateSubCollection( collection ) ); // we need the necessary rights 00198 00199 enableAction( StandardActionManager::DeleteCollections, canDeleteCollections ); 00200 00201 enableAction( StandardActionManager::CopyCollections, canCopyCollections ); 00202 00203 enableAction( StandardActionManager::CutCollections, canCutCollections ); 00204 00205 enableAction( StandardActionManager::CopyCollectionToMenu, canCopyCollections ); 00206 00207 enableAction( StandardActionManager::MoveCollectionToMenu, canMoveCollections ); 00208 00209 enableAction( StandardActionManager::MoveCollectionsToTrash, atLeastOneCollectionSelected && canMoveCollections && !collectionsAreInTrash ); 00210 00211 enableAction( StandardActionManager::RestoreCollectionsFromTrash, atLeastOneCollectionSelected && canMoveCollections && collectionsAreInTrash ); 00212 00213 enableAction( StandardActionManager::CopyCollectionToDialog, canCopyCollections ); 00214 00215 enableAction( StandardActionManager::MoveCollectionToDialog, canMoveCollections ); 00216 00217 enableAction( StandardActionManager::CollectionProperties, singleCollectionSelected && // we can only configure one collection at a time 00218 !isRootCollection( collection ) ); // we can not configure the root collection 00219 00220 enableAction( StandardActionManager::SynchronizeCollections, atLeastOneCollectionCanHaveItems ); // it must be a valid folder collection 00221 00222 enableAction( StandardActionManager::SynchronizeCollectionsRecursive, atLeastOneCollectionSelected && 00223 collectionsAreFolders ); // it must be a valid folder collection 00224 #ifndef QT_NO_CLIPBOARD 00225 enableAction( StandardActionManager::Paste, singleCollectionSelected && // we can paste only into a single collection 00226 PasteHelper::canPaste( QApplication::clipboard()->mimeData(), collection ) ); // there must be data on the clipboard 00227 #else 00228 enableAction( StandardActionManager::Paste, false ); // no support for clipboard -> no paste 00229 #endif 00230 00231 // favorite collections specific actions 00232 enableAction( StandardActionManager::AddToFavoriteCollections, canAddToFavoriteCollections ); 00233 00234 enableAction( StandardActionManager::RemoveFromFavoriteCollections, canRemoveFromFavoriteCollections ); 00235 00236 enableAction( StandardActionManager::RenameFavoriteCollection, singleCollectionSelected && // we can rename only one collection at a time 00237 isFavoriteCollection( collection ) ); // it must be a favorite collection already 00238 00239 // resource specific actions 00240 int resourceCollectionCount = 0; 00241 bool canDeleteResources = true; 00242 bool canConfigureResource = true; 00243 bool canSynchronizeResources = true; 00244 foreach ( const Collection &collection, collections ) { 00245 if ( isResourceCollection( collection ) ) { 00246 resourceCollectionCount++; 00247 00248 // check that the 'NoConfig' flag is not set for the resource 00249 if ( hasResourceCapability( collection, QLatin1String( "NoConfig" ) ) ) 00250 canConfigureResource = false; 00251 00252 } else { 00253 // we selected a non-resource collection 00254 canDeleteResources = false; 00255 canConfigureResource = false; 00256 canSynchronizeResources = false; 00257 } 00258 } 00259 00260 if ( resourceCollectionCount == 0 ) { 00261 // not a single resource collection has been selected 00262 canDeleteResources = false; 00263 canConfigureResource = false; 00264 canSynchronizeResources = false; 00265 } 00266 00267 enableAction( StandardActionManager::CreateResource, true ); 00268 enableAction( StandardActionManager::DeleteResources, canDeleteResources ); 00269 enableAction( StandardActionManager::ResourceProperties, canConfigureResource ); 00270 enableAction( StandardActionManager::SynchronizeResources, canSynchronizeResources ); 00271 00272 if (collectionsAreInTrash) { 00273 updateAlternatingAction( StandardActionManager::MoveToTrashRestoreCollectionAlternative ); 00274 //updatePluralLabel( StandardActionManager::MoveToTrashRestoreCollectionAlternative, collectionCount ); 00275 } else { 00276 updateAlternatingAction( StandardActionManager::MoveToTrashRestoreCollection ); 00277 } 00278 enableAction( StandardActionManager::MoveToTrashRestoreCollection, atLeastOneCollectionSelected && canMoveCollections ); 00279 00280 // item specific actions 00281 bool canDeleteItems = (items.count() > 0); //TODO: fixme 00282 foreach ( const Item &item, items ) { 00283 const Collection parentCollection = item.parentCollection(); 00284 if ( !parentCollection.isValid() ) 00285 continue; 00286 00287 canDeleteItems = canDeleteItems && (parentCollection.rights() & Collection::CanDeleteItem); 00288 } 00289 00290 bool itemsAreInTrash = false; 00291 foreach ( const Item &item, items ) { 00292 if ( item.hasAttribute<EntityDeletedAttribute>() ) { 00293 itemsAreInTrash = true; 00294 break; 00295 } 00296 } 00297 00298 enableAction( StandardActionManager::CopyItems, atLeastOneItemSelected ); // we need items to work with 00299 00300 enableAction( StandardActionManager::CutItems, atLeastOneItemSelected && // we need items to work with 00301 canDeleteItems ); // we need the necessary rights 00302 00303 enableAction( StandardActionManager::DeleteItems, atLeastOneItemSelected && // we need items to work with 00304 canDeleteItems ); // we need the necessary rights 00305 00306 enableAction( StandardActionManager::CopyItemToMenu, atLeastOneItemSelected ); // we need items to work with 00307 00308 enableAction( StandardActionManager::MoveItemToMenu, atLeastOneItemSelected && // we need items to work with 00309 canDeleteItems ); // we need the necessary rights 00310 00311 enableAction( StandardActionManager::MoveItemsToTrash, atLeastOneItemSelected && canDeleteItems && !itemsAreInTrash ); 00312 00313 enableAction( StandardActionManager::RestoreItemsFromTrash, atLeastOneItemSelected && itemsAreInTrash ); 00314 00315 enableAction( StandardActionManager::CopyItemToDialog, atLeastOneItemSelected ); // we need items to work with 00316 00317 enableAction( StandardActionManager::MoveItemToDialog, atLeastOneItemSelected && // we need items to work with 00318 canDeleteItems ); // we need the necessary rights 00319 00320 if (itemsAreInTrash) { 00321 updateAlternatingAction( StandardActionManager::MoveToTrashRestoreItemAlternative ); 00322 //updatePluralLabel( StandardActionManager::MoveToTrashRestoreItemAlternative, itemCount ); 00323 } else { 00324 updateAlternatingAction( StandardActionManager::MoveToTrashRestoreItem ); 00325 } 00326 enableAction( StandardActionManager::MoveToTrashRestoreItem, atLeastOneItemSelected && // we need items to work with 00327 canDeleteItems ); // we need the necessary rights 00328 00329 // update the texts of the actions 00330 updatePluralLabel( StandardActionManager::CopyCollections, collectionCount ); 00331 updatePluralLabel( StandardActionManager::CopyItems, itemCount ); 00332 updatePluralLabel( StandardActionManager::DeleteItems, itemCount ); 00333 updatePluralLabel( StandardActionManager::CutItems, itemCount ); 00334 updatePluralLabel( StandardActionManager::CutCollections, collectionCount ); 00335 updatePluralLabel( StandardActionManager::DeleteCollections, collectionCount ); 00336 updatePluralLabel( StandardActionManager::SynchronizeCollections, collectionCount ); 00337 updatePluralLabel( StandardActionManager::SynchronizeCollectionsRecursive, collectionCount ); 00338 updatePluralLabel( StandardActionManager::DeleteResources, resourceCollectionCount ); 00339 updatePluralLabel( StandardActionManager::SynchronizeResources, resourceCollectionCount ); 00340 00341 } 00342 00343 bool ActionStateManager::isRootCollection( const Collection &collection ) const 00344 { 00345 return CollectionUtils::isRoot( collection ); 00346 } 00347 00348 bool ActionStateManager::isResourceCollection( const Collection &collection ) const 00349 { 00350 return CollectionUtils::isResource( collection ); 00351 } 00352 00353 bool ActionStateManager::isFolderCollection( const Collection &collection ) const 00354 { 00355 return (CollectionUtils::isFolder( collection ) || 00356 CollectionUtils::isResource( collection ) || 00357 CollectionUtils::isStructural( collection )); 00358 } 00359 00360 bool ActionStateManager::isSpecialCollection( const Collection &collection ) const 00361 { 00362 return collection.hasAttribute<SpecialCollectionAttribute>(); 00363 } 00364 00365 bool ActionStateManager::isFavoriteCollection( const Collection &collection ) const 00366 { 00367 if ( !mReceiver ) 00368 return false; 00369 00370 bool result = false; 00371 QMetaObject::invokeMethod( mReceiver, "isFavoriteCollection", Qt::DirectConnection, 00372 Q_RETURN_ARG( bool, result ), Q_ARG( Akonadi::Collection, collection ) ); 00373 00374 return result; 00375 } 00376 00377 bool ActionStateManager::hasResourceCapability( const Collection &collection, const QString &capability ) const 00378 { 00379 const Akonadi::AgentInstance instance = AgentManager::self()->instance( collection.resource() ); 00380 00381 return instance.type().capabilities().contains( capability ); 00382 } 00383 00384 bool ActionStateManager::collectionCanHaveItems( const Collection &collection ) const 00385 { 00386 return !( collection.contentMimeTypes() == ( QStringList() << QLatin1String( "inode/directory" ) ) || 00387 CollectionUtils::isStructural( collection ) ); 00388 } 00389 00390 void ActionStateManager::enableAction( int action, bool state ) 00391 { 00392 if ( !mReceiver ) 00393 return; 00394 00395 QMetaObject::invokeMethod( mReceiver, "enableAction", Qt::DirectConnection, Q_ARG( int, action ), Q_ARG( bool, state ) ); 00396 } 00397 00398 void ActionStateManager::updatePluralLabel( int action, int count ) 00399 { 00400 if ( !mReceiver ) 00401 return; 00402 00403 QMetaObject::invokeMethod( mReceiver, "updatePluralLabel", Qt::DirectConnection, Q_ARG( int, action ), Q_ARG( int, count ) ); 00404 } 00405 00406 void ActionStateManager::updateAlternatingAction( int action ) 00407 { 00408 if ( !mReceiver ) 00409 return; 00410 00411 QMetaObject::invokeMethod( mReceiver, "updateAlternatingAction", Qt::DirectConnection, Q_ARG( int, action )); 00412 }
This file is part of the KDE documentation.
Documentation copyright © 1996-2012 The KDE developers.
Generated on Thu Aug 2 2012 15:25:17 by doxygen 1.7.5 written by Dimitri van Heesch, © 1997-2006
Documentation copyright © 1996-2012 The KDE developers.
Generated on Thu Aug 2 2012 15:25:17 by doxygen 1.7.5 written by Dimitri van Heesch, © 1997-2006
KDE's Doxygen guidelines are available online.