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 <QtGui/QApplication> 00029 #include <QtGui/QClipboard> 00030 00031 using namespace Akonadi; 00032 00033 static bool canCreateSubCollection( const Collection &collection ) 00034 { 00035 if ( !( collection.rights() & Collection::CanCreateCollection ) ) 00036 return false; 00037 00038 if ( !collection.contentMimeTypes().contains( Collection::mimeType() ) ) 00039 return false; 00040 00041 return true; 00042 } 00043 00044 static inline bool canContainItems( const Collection &collection ) 00045 { 00046 if ( collection.contentMimeTypes().isEmpty() ) 00047 return false; 00048 00049 if ( (collection.contentMimeTypes().count() == 1) && 00050 (collection.contentMimeTypes().first() == Collection::mimeType()) ) 00051 return false; 00052 00053 return true; 00054 } 00055 00056 ActionStateManager::ActionStateManager() 00057 : mReceiver( 0 ) 00058 { 00059 } 00060 00061 ActionStateManager::~ActionStateManager() 00062 { 00063 } 00064 00065 void ActionStateManager::setReceiver( QObject *object ) 00066 { 00067 mReceiver = object; 00068 } 00069 00070 void ActionStateManager::updateState( const Collection::List &collections, const Item::List &items ) 00071 { 00072 const bool singleCollectionSelected = (collections.count() == 1); 00073 const bool multipleCollectionsSelected = (collections.count() > 1); 00074 const bool atLeastOneCollectionSelected = (singleCollectionSelected || multipleCollectionsSelected); 00075 const int collectionCount = collections.count(); 00076 00077 const bool singleItemSelected = (items.count() == 1); 00078 const bool multipleItemsSelected = (items.count() > 1); 00079 const bool atLeastOneItemSelected = (singleItemSelected || multipleItemsSelected); 00080 const int itemCount = items.count(); 00081 00082 bool canDeleteCollections = (collections.count() > 0); 00083 foreach ( const Collection &collection, collections ) { 00084 // do we have the necessary rights? 00085 if ( !(collection.rights() & Collection::CanDeleteCollection) ) 00086 canDeleteCollections = false; 00087 00088 if ( isRootCollection( collection ) ) 00089 canDeleteCollections = false; 00090 00091 if ( isResourceCollection( collection ) ) 00092 canDeleteCollections = false; 00093 } 00094 00095 bool canCutCollections = canDeleteCollections; // we must be able to delete for cutting 00096 foreach ( const Collection &collection, collections ) { 00097 if ( isSpecialCollection( collection ) ) 00098 canCutCollections = false; 00099 00100 if ( !isFolderCollection( collection ) ) 00101 canCutCollections = false; 00102 } 00103 00104 const bool canMoveCollections = canCutCollections; // we must be able to cut for moving 00105 00106 bool canCopyCollections = (collections.count() > 0); 00107 foreach ( const Collection &collection, collections ) { 00108 if ( isRootCollection( collection ) ) 00109 canCopyCollections = false; 00110 00111 if ( !isFolderCollection( collection ) ) 00112 canCopyCollections = false; 00113 } 00114 00115 bool canAddToFavoriteCollections = (collections.count() > 0); 00116 foreach ( const Collection &collection, collections ) { 00117 if ( isRootCollection( collection ) ) 00118 canAddToFavoriteCollections = false; 00119 00120 if ( isFavoriteCollection( collection ) ) 00121 canAddToFavoriteCollections = false; 00122 00123 if ( !isFolderCollection( collection ) ) 00124 canAddToFavoriteCollections = false; 00125 00126 if ( !canContainItems( collection ) ) 00127 canAddToFavoriteCollections = false; 00128 } 00129 00130 bool canRemoveFromFavoriteCollections = (collections.count() > 0); 00131 foreach ( const Collection &collection, collections ) { 00132 if ( !isFavoriteCollection( collection ) ) 00133 canRemoveFromFavoriteCollections = false; 00134 } 00135 00136 bool collectionsAreFolders = (!collections.isEmpty() ? true : false); 00137 00138 foreach ( Collection collection, collections ) { 00139 if ( !isFolderCollection( collection ) ) { 00140 collectionsAreFolders = false; 00141 break; 00142 } 00143 } 00144 00145 const Collection collection = (!collections.isEmpty() ? collections.first() : Collection()); 00146 00147 // collection specific actions 00148 enableAction( StandardActionManager::CreateCollection, singleCollectionSelected && // we can create only inside one collection 00149 canCreateSubCollection( collection ) ); // we need the necessary rights 00150 00151 enableAction( StandardActionManager::DeleteCollections, canDeleteCollections ); 00152 00153 enableAction( StandardActionManager::CopyCollections, canCopyCollections ); 00154 00155 enableAction( StandardActionManager::CutCollections, canCutCollections ); 00156 00157 enableAction( StandardActionManager::CopyCollectionToMenu, canCopyCollections ); 00158 00159 enableAction( StandardActionManager::MoveCollectionToMenu, canMoveCollections ); 00160 00161 enableAction( StandardActionManager::CopyCollectionToDialog, canCopyCollections ); 00162 00163 enableAction( StandardActionManager::MoveCollectionToDialog, canMoveCollections ); 00164 00165 enableAction( StandardActionManager::CollectionProperties, singleCollectionSelected && // we can only configure one collection at a time 00166 !isRootCollection( collection ) ); // we can not configure the root collection 00167 00168 enableAction( StandardActionManager::SynchronizeCollections, atLeastOneCollectionSelected && 00169 collectionsAreFolders ); // it must be a valid folder collection 00170 00171 enableAction( StandardActionManager::SynchronizeCollectionsRecursive, atLeastOneCollectionSelected && 00172 collectionsAreFolders ); // it must be a valid folder collection 00173 #ifndef QT_NO_CLIPBOARD 00174 enableAction( StandardActionManager::Paste, singleCollectionSelected && // we can paste only into a single collection 00175 PasteHelper::canPaste( QApplication::clipboard()->mimeData(), collection ) ); // there must be data on the clipboard 00176 #else 00177 enableAction( StandardActionManager::Paste, false ); // no support for clipboard -> no paste 00178 #endif 00179 00180 // favorite collections specific actions 00181 enableAction( StandardActionManager::AddToFavoriteCollections, canAddToFavoriteCollections ); 00182 00183 enableAction( StandardActionManager::RemoveFromFavoriteCollections, canRemoveFromFavoriteCollections ); 00184 00185 enableAction( StandardActionManager::RenameFavoriteCollection, singleCollectionSelected && // we can rename only one collection at a time 00186 isFavoriteCollection( collection ) ); // it must be a favorite collection already 00187 00188 // resource specific actions 00189 int resourceCollectionCount = 0; 00190 bool canDeleteResources = true; 00191 bool canConfigureResource = true; 00192 bool canSynchronizeResources = true; 00193 foreach ( const Collection &collection, collections ) { 00194 if ( isResourceCollection( collection ) ) { 00195 resourceCollectionCount++; 00196 00197 // check that the 'NoConfig' flag is not set for the resource 00198 if ( hasResourceCapability( collection, QLatin1String( "NoConfig" ) ) ) 00199 canConfigureResource = false; 00200 00201 } else { 00202 // we selected a non-resource collection 00203 canDeleteResources = false; 00204 canConfigureResource = false; 00205 canSynchronizeResources = false; 00206 } 00207 } 00208 00209 if ( resourceCollectionCount == 0 ) { 00210 // not a single resource collection has been selected 00211 canDeleteResources = false; 00212 canConfigureResource = false; 00213 canSynchronizeResources = false; 00214 } 00215 00216 enableAction( StandardActionManager::CreateResource, true ); 00217 enableAction( StandardActionManager::DeleteResources, canDeleteResources ); 00218 enableAction( StandardActionManager::ResourceProperties, canConfigureResource ); 00219 enableAction( StandardActionManager::SynchronizeResources, canSynchronizeResources ); 00220 00221 // item specific actions 00222 bool canDeleteItems = (items.count() > 0); //TODO: fixme 00223 foreach ( const Item &item, items ) { 00224 const Collection parentCollection = item.parentCollection(); 00225 if ( !parentCollection.isValid() ) 00226 continue; 00227 00228 canDeleteItems = canDeleteItems && (parentCollection.rights() & Collection::CanDeleteItem); 00229 } 00230 00231 enableAction( StandardActionManager::CopyItems, atLeastOneItemSelected ); // we need items to work with 00232 00233 enableAction( StandardActionManager::CutItems, atLeastOneItemSelected && // we need items to work with 00234 canDeleteItems ); // we need the necessary rights 00235 00236 enableAction( StandardActionManager::DeleteItems, atLeastOneItemSelected && // we need items to work with 00237 canDeleteItems ); // we need the necessary rights 00238 00239 enableAction( StandardActionManager::CopyItemToMenu, atLeastOneItemSelected ); // we need items to work with 00240 00241 enableAction( StandardActionManager::MoveItemToMenu, atLeastOneItemSelected && // we need items to work with 00242 canDeleteItems ); // we need the necessary rights 00243 00244 enableAction( StandardActionManager::CopyItemToDialog, atLeastOneItemSelected ); // we need items to work with 00245 00246 enableAction( StandardActionManager::MoveItemToDialog, atLeastOneItemSelected && // we need items to work with 00247 canDeleteItems ); // we need the necessary rights 00248 00249 // update the texts of the actions 00250 updatePluralLabel( StandardActionManager::CopyCollections, collectionCount ); 00251 updatePluralLabel( StandardActionManager::CopyItems, itemCount ); 00252 updatePluralLabel( StandardActionManager::DeleteItems, itemCount ); 00253 updatePluralLabel( StandardActionManager::CutItems, itemCount ); 00254 updatePluralLabel( StandardActionManager::CutCollections, collectionCount ); 00255 updatePluralLabel( StandardActionManager::DeleteCollections, collectionCount ); 00256 updatePluralLabel( StandardActionManager::SynchronizeCollections, collectionCount ); 00257 updatePluralLabel( StandardActionManager::SynchronizeCollectionsRecursive, collectionCount ); 00258 updatePluralLabel( StandardActionManager::DeleteResources, resourceCollectionCount ); 00259 updatePluralLabel( StandardActionManager::SynchronizeResources, resourceCollectionCount ); 00260 } 00261 00262 bool ActionStateManager::isRootCollection( const Collection &collection ) const 00263 { 00264 return CollectionUtils::isRoot( collection ); 00265 } 00266 00267 bool ActionStateManager::isResourceCollection( const Collection &collection ) const 00268 { 00269 return CollectionUtils::isResource( collection ); 00270 } 00271 00272 bool ActionStateManager::isFolderCollection( const Collection &collection ) const 00273 { 00274 return (CollectionUtils::isFolder( collection ) || 00275 CollectionUtils::isResource( collection ) || 00276 CollectionUtils::isStructural( collection )); 00277 } 00278 00279 bool ActionStateManager::isSpecialCollection( const Collection &collection ) const 00280 { 00281 return collection.hasAttribute<SpecialCollectionAttribute>(); 00282 } 00283 00284 bool ActionStateManager::isFavoriteCollection( const Collection &collection ) const 00285 { 00286 if ( !mReceiver ) 00287 return false; 00288 00289 bool result = false; 00290 QMetaObject::invokeMethod( mReceiver, "isFavoriteCollection", Qt::DirectConnection, 00291 Q_RETURN_ARG( bool, result ), Q_ARG( Akonadi::Collection, collection ) ); 00292 00293 return result; 00294 } 00295 00296 bool ActionStateManager::hasResourceCapability( const Collection &collection, const QString &capability ) const 00297 { 00298 const Akonadi::AgentInstance instance = AgentManager::self()->instance( collection.resource() ); 00299 00300 return instance.type().capabilities().contains( capability ); 00301 } 00302 00303 void ActionStateManager::enableAction( int action, bool state ) 00304 { 00305 if ( !mReceiver ) 00306 return; 00307 00308 QMetaObject::invokeMethod( mReceiver, "enableAction", Qt::DirectConnection, Q_ARG( int, action ), Q_ARG( bool, state ) ); 00309 } 00310 00311 void ActionStateManager::updatePluralLabel( int action, int count ) 00312 { 00313 if ( !mReceiver ) 00314 return; 00315 00316 QMetaObject::invokeMethod( mReceiver, "updatePluralLabel", Qt::DirectConnection, Q_ARG( int, action ), Q_ARG( int, count ) ); 00317 }