• Skip to content
  • Skip to link menu
  • KDE API Reference
  • kdepimlibs-4.9.3 API Reference
  • KDE Home
  • Contact Us
 

akonadi

  • akonadi
actionstatemanager.cpp
1 /*
2  Copyright (c) 2010 Tobias Koenig <tokoe@kde.org>
3 
4  This library is free software; you can redistribute it and/or modify it
5  under the terms of the GNU Library General Public License as published by
6  the Free Software Foundation; either version 2 of the License, or (at your
7  option) any later version.
8 
9  This library is distributed in the hope that it will be useful, but WITHOUT
10  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
12  License for more details.
13 
14  You should have received a copy of the GNU Library General Public License
15  along with this library; see the file COPYING.LIB. If not, write to the
16  Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17  02110-1301, USA.
18 */
19 
20 #include "actionstatemanager_p.h"
21 
22 #include "agentmanager.h"
23 #include "collectionutils_p.h"
24 #include "pastehelper_p.h"
25 #include "specialcollectionattribute_p.h"
26 #include "standardactionmanager.h"
27 
28 #include <akonadi/entitydeletedattribute.h>
29 
30 #include <QtGui/QApplication>
31 #include <QtGui/QClipboard>
32 
33 using namespace Akonadi;
34 
35 static bool canCreateSubCollection( const Collection &collection )
36 {
37  if ( !( collection.rights() & Collection::CanCreateCollection ) )
38  return false;
39 
40  if ( !collection.contentMimeTypes().contains( Collection::mimeType() ) )
41  return false;
42 
43  return true;
44 }
45 
46 static inline bool canContainItems( const Collection &collection )
47 {
48  if ( collection.contentMimeTypes().isEmpty() )
49  return false;
50 
51  if ( (collection.contentMimeTypes().count() == 1) &&
52  (collection.contentMimeTypes().first() == Collection::mimeType()) )
53  return false;
54 
55  return true;
56 }
57 
58 ActionStateManager::ActionStateManager()
59  : mReceiver( 0 )
60 {
61 }
62 
63 ActionStateManager::~ActionStateManager()
64 {
65 }
66 
67 void ActionStateManager::setReceiver( QObject *object )
68 {
69  mReceiver = object;
70 }
71 
72 void ActionStateManager::updateState( const Collection::List &collections, const Item::List &items )
73 {
74  const int collectionCount = collections.count();
75  const bool singleCollectionSelected = (collectionCount == 1);
76  const bool multipleCollectionsSelected = (collectionCount > 1);
77  const bool atLeastOneCollectionSelected = (singleCollectionSelected || multipleCollectionsSelected);
78 
79  const int itemCount = items.count();
80  const bool singleItemSelected = (itemCount == 1);
81  const bool multipleItemsSelected = (itemCount > 1);
82  const bool atLeastOneItemSelected = (singleItemSelected || multipleItemsSelected);
83 
84  const bool listOfCollectionNotEmpty = collections.isEmpty() ? false : true;
85  bool canDeleteCollections = listOfCollectionNotEmpty;
86  if ( canDeleteCollections )
87  {
88  foreach ( const Collection &collection, collections ) {
89  // do we have the necessary rights?
90  if ( !(collection.rights() & Collection::CanDeleteCollection) ) {
91  canDeleteCollections = false;
92  break;
93  }
94 
95  if ( isRootCollection( collection ) ) {
96  canDeleteCollections = false;
97  break;
98  }
99 
100  if ( isResourceCollection( collection ) ) {
101  canDeleteCollections = false;
102  break;
103  }
104  }
105  }
106 
107  bool canCutCollections = canDeleteCollections; // we must be able to delete for cutting
108  foreach ( const Collection &collection, collections ) {
109  if ( isSpecialCollection( collection ) ) {
110  canCutCollections = false;
111  break;
112  }
113 
114  if ( !isFolderCollection( collection ) ) {
115  canCutCollections = false;
116  break;
117  }
118  }
119 
120  const bool canMoveCollections = canCutCollections; // we must be able to cut for moving
121 
122  bool canCopyCollections = listOfCollectionNotEmpty;
123  if ( canCopyCollections ) {
124  foreach ( const Collection &collection, collections ) {
125  if ( isRootCollection( collection ) ) {
126  canCopyCollections = false;
127  break;
128  }
129 
130  if ( !isFolderCollection( collection ) ) {
131  canCopyCollections = false;
132  break;
133  }
134  }
135  }
136  bool canAddToFavoriteCollections = listOfCollectionNotEmpty;
137  if ( canAddToFavoriteCollections ) {
138  foreach ( const Collection &collection, collections ) {
139  if ( isRootCollection( collection ) ) {
140  canAddToFavoriteCollections = false;
141  break;
142  }
143 
144  if ( isFavoriteCollection( collection ) ) {
145  canAddToFavoriteCollections = false;
146  break;
147  }
148 
149  if ( !isFolderCollection( collection ) ) {
150  canAddToFavoriteCollections = false;
151  break;
152  }
153 
154  if ( !canContainItems( collection ) ) {
155  canAddToFavoriteCollections = false;
156  break;
157  }
158  }
159  }
160  bool canRemoveFromFavoriteCollections = listOfCollectionNotEmpty;
161  foreach ( const Collection &collection, collections ) {
162  if ( !isFavoriteCollection( collection ) ) {
163  canRemoveFromFavoriteCollections = false;
164  break;
165  }
166  }
167 
168  bool collectionsAreFolders = listOfCollectionNotEmpty;
169 
170  foreach ( const Collection &collection, collections ) {
171  if ( !isFolderCollection( collection ) ) {
172  collectionsAreFolders = false;
173  break;
174  }
175  }
176 
177  bool collectionsAreInTrash = false;
178  foreach ( const Collection &collection, collections ) {
179  if ( collection.hasAttribute<EntityDeletedAttribute>() ) {
180  collectionsAreInTrash = true;
181  break;
182  }
183  }
184 
185  bool atLeastOneCollectionCanHaveItems = false;
186  foreach ( const Collection &collection, collections ) {
187  if ( collectionCanHaveItems( collection ) ) {
188  atLeastOneCollectionCanHaveItems = true;
189  break;
190  }
191  }
192 
193  const Collection collection = (!collections.isEmpty() ? collections.first() : Collection());
194 
195  // collection specific actions
196  enableAction( StandardActionManager::CreateCollection, singleCollectionSelected && // we can create only inside one collection
197  canCreateSubCollection( collection ) ); // we need the necessary rights
198 
199  enableAction( StandardActionManager::DeleteCollections, canDeleteCollections );
200 
201  enableAction( StandardActionManager::CopyCollections, canCopyCollections );
202 
203  enableAction( StandardActionManager::CutCollections, canCutCollections );
204 
205  enableAction( StandardActionManager::CopyCollectionToMenu, canCopyCollections );
206 
207  enableAction( StandardActionManager::MoveCollectionToMenu, canMoveCollections );
208 
209  enableAction( StandardActionManager::MoveCollectionsToTrash, atLeastOneCollectionSelected && canMoveCollections && !collectionsAreInTrash );
210 
211  enableAction( StandardActionManager::RestoreCollectionsFromTrash, atLeastOneCollectionSelected && canMoveCollections && collectionsAreInTrash );
212 
213  enableAction( StandardActionManager::CopyCollectionToDialog, canCopyCollections );
214 
215  enableAction( StandardActionManager::MoveCollectionToDialog, canMoveCollections );
216 
217  enableAction( StandardActionManager::CollectionProperties, singleCollectionSelected && // we can only configure one collection at a time
218  !isRootCollection( collection ) ); // we can not configure the root collection
219 
220  enableAction( StandardActionManager::SynchronizeCollections, atLeastOneCollectionCanHaveItems ); // it must be a valid folder collection
221 
222  enableAction( StandardActionManager::SynchronizeCollectionsRecursive, atLeastOneCollectionSelected &&
223  collectionsAreFolders ); // it must be a valid folder collection
224 #ifndef QT_NO_CLIPBOARD
225  enableAction( StandardActionManager::Paste, singleCollectionSelected && // we can paste only into a single collection
226  PasteHelper::canPaste( QApplication::clipboard()->mimeData(), collection ) ); // there must be data on the clipboard
227 #else
228  enableAction( StandardActionManager::Paste, false ); // no support for clipboard -> no paste
229 #endif
230 
231  // favorite collections specific actions
232  enableAction( StandardActionManager::AddToFavoriteCollections, canAddToFavoriteCollections );
233 
234  enableAction( StandardActionManager::RemoveFromFavoriteCollections, canRemoveFromFavoriteCollections );
235 
236  enableAction( StandardActionManager::RenameFavoriteCollection, singleCollectionSelected && // we can rename only one collection at a time
237  isFavoriteCollection( collection ) ); // it must be a favorite collection already
238 
239  // resource specific actions
240  int resourceCollectionCount = 0;
241  bool canDeleteResources = true;
242  bool canConfigureResource = true;
243  bool canSynchronizeResources = true;
244  foreach ( const Collection &collection, collections ) {
245  if ( isResourceCollection( collection ) ) {
246  resourceCollectionCount++;
247 
248  // check that the 'NoConfig' flag is not set for the resource
249  if ( hasResourceCapability( collection, QLatin1String( "NoConfig" ) ) )
250  canConfigureResource = false;
251 
252  } else {
253  // we selected a non-resource collection
254  canDeleteResources = false;
255  canConfigureResource = false;
256  canSynchronizeResources = false;
257  }
258  }
259 
260  if ( resourceCollectionCount == 0 ) {
261  // not a single resource collection has been selected
262  canDeleteResources = false;
263  canConfigureResource = false;
264  canSynchronizeResources = false;
265  }
266 
267  enableAction( StandardActionManager::CreateResource, true );
268  enableAction( StandardActionManager::DeleteResources, canDeleteResources );
269  enableAction( StandardActionManager::ResourceProperties, canConfigureResource );
270  enableAction( StandardActionManager::SynchronizeResources, canSynchronizeResources );
271 
272  if (collectionsAreInTrash) {
273  updateAlternatingAction( StandardActionManager::MoveToTrashRestoreCollectionAlternative );
274  //updatePluralLabel( StandardActionManager::MoveToTrashRestoreCollectionAlternative, collectionCount );
275  } else {
276  updateAlternatingAction( StandardActionManager::MoveToTrashRestoreCollection );
277  }
278  enableAction( StandardActionManager::MoveToTrashRestoreCollection, atLeastOneCollectionSelected && canMoveCollections );
279 
280  // item specific actions
281  bool canDeleteItems = (items.count() > 0); //TODO: fixme
282  foreach ( const Item &item, items ) {
283  const Collection parentCollection = item.parentCollection();
284  if ( !parentCollection.isValid() )
285  continue;
286 
287  canDeleteItems = canDeleteItems && (parentCollection.rights() & Collection::CanDeleteItem);
288  }
289 
290  bool itemsAreInTrash = false;
291  foreach ( const Item &item, items ) {
292  if ( item.hasAttribute<EntityDeletedAttribute>() ) {
293  itemsAreInTrash = true;
294  break;
295  }
296  }
297 
298  enableAction( StandardActionManager::CopyItems, atLeastOneItemSelected ); // we need items to work with
299 
300  enableAction( StandardActionManager::CutItems, atLeastOneItemSelected && // we need items to work with
301  canDeleteItems ); // we need the necessary rights
302 
303  enableAction( StandardActionManager::DeleteItems, atLeastOneItemSelected && // we need items to work with
304  canDeleteItems ); // we need the necessary rights
305 
306  enableAction( StandardActionManager::CopyItemToMenu, atLeastOneItemSelected ); // we need items to work with
307 
308  enableAction( StandardActionManager::MoveItemToMenu, atLeastOneItemSelected && // we need items to work with
309  canDeleteItems ); // we need the necessary rights
310 
311  enableAction( StandardActionManager::MoveItemsToTrash, atLeastOneItemSelected && canDeleteItems && !itemsAreInTrash );
312 
313  enableAction( StandardActionManager::RestoreItemsFromTrash, atLeastOneItemSelected && itemsAreInTrash );
314 
315  enableAction( StandardActionManager::CopyItemToDialog, atLeastOneItemSelected ); // we need items to work with
316 
317  enableAction( StandardActionManager::MoveItemToDialog, atLeastOneItemSelected && // we need items to work with
318  canDeleteItems ); // we need the necessary rights
319 
320  if (itemsAreInTrash) {
321  updateAlternatingAction( StandardActionManager::MoveToTrashRestoreItemAlternative );
322  //updatePluralLabel( StandardActionManager::MoveToTrashRestoreItemAlternative, itemCount );
323  } else {
324  updateAlternatingAction( StandardActionManager::MoveToTrashRestoreItem );
325  }
326  enableAction( StandardActionManager::MoveToTrashRestoreItem, atLeastOneItemSelected && // we need items to work with
327  canDeleteItems ); // we need the necessary rights
328 
329  // update the texts of the actions
330  updatePluralLabel( StandardActionManager::CopyCollections, collectionCount );
331  updatePluralLabel( StandardActionManager::CopyItems, itemCount );
332  updatePluralLabel( StandardActionManager::DeleteItems, itemCount );
333  updatePluralLabel( StandardActionManager::CutItems, itemCount );
334  updatePluralLabel( StandardActionManager::CutCollections, collectionCount );
335  updatePluralLabel( StandardActionManager::DeleteCollections, collectionCount );
336  updatePluralLabel( StandardActionManager::SynchronizeCollections, collectionCount );
337  updatePluralLabel( StandardActionManager::SynchronizeCollectionsRecursive, collectionCount );
338  updatePluralLabel( StandardActionManager::DeleteResources, resourceCollectionCount );
339  updatePluralLabel( StandardActionManager::SynchronizeResources, resourceCollectionCount );
340 
341 }
342 
343 bool ActionStateManager::isRootCollection( const Collection &collection ) const
344 {
345  return CollectionUtils::isRoot( collection );
346 }
347 
348 bool ActionStateManager::isResourceCollection( const Collection &collection ) const
349 {
350  return CollectionUtils::isResource( collection );
351 }
352 
353 bool ActionStateManager::isFolderCollection( const Collection &collection ) const
354 {
355  return (CollectionUtils::isFolder( collection ) ||
356  CollectionUtils::isResource( collection ) ||
357  CollectionUtils::isStructural( collection ));
358 }
359 
360 bool ActionStateManager::isSpecialCollection( const Collection &collection ) const
361 {
362  return collection.hasAttribute<SpecialCollectionAttribute>();
363 }
364 
365 bool ActionStateManager::isFavoriteCollection( const Collection &collection ) const
366 {
367  if ( !mReceiver )
368  return false;
369 
370  bool result = false;
371  QMetaObject::invokeMethod( mReceiver, "isFavoriteCollection", Qt::DirectConnection,
372  Q_RETURN_ARG( bool, result ), Q_ARG( Akonadi::Collection, collection ) );
373 
374  return result;
375 }
376 
377 bool ActionStateManager::hasResourceCapability( const Collection &collection, const QString &capability ) const
378 {
379  const Akonadi::AgentInstance instance = AgentManager::self()->instance( collection.resource() );
380 
381  return instance.type().capabilities().contains( capability );
382 }
383 
384 bool ActionStateManager::collectionCanHaveItems( const Collection &collection ) const
385 {
386  return !( collection.contentMimeTypes() == ( QStringList() << QLatin1String( "inode/directory" ) ) ||
387  CollectionUtils::isStructural( collection ) );
388 }
389 
390 void ActionStateManager::enableAction( int action, bool state )
391 {
392  if ( !mReceiver )
393  return;
394 
395  QMetaObject::invokeMethod( mReceiver, "enableAction", Qt::DirectConnection, Q_ARG( int, action ), Q_ARG( bool, state ) );
396 }
397 
398 void ActionStateManager::updatePluralLabel( int action, int count )
399 {
400  if ( !mReceiver )
401  return;
402 
403  QMetaObject::invokeMethod( mReceiver, "updatePluralLabel", Qt::DirectConnection, Q_ARG( int, action ), Q_ARG( int, count ) );
404 }
405 
406 void ActionStateManager::updateAlternatingAction( int action )
407 {
408  if ( !mReceiver )
409  return;
410 
411  QMetaObject::invokeMethod( mReceiver, "updateAlternatingAction", Qt::DirectConnection, Q_ARG( int, action ));
412 }
This file is part of the KDE documentation.
Documentation copyright © 1996-2012 The KDE developers.
Generated on Wed Nov 28 2012 21:51:20 by doxygen 1.8.1.2 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

akonadi

Skip menu "akonadi"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • Modules
  • Related Pages

kdepimlibs-4.9.3 API Reference

Skip menu "kdepimlibs-4.9.3 API Reference"
  • akonadi
  •   contact
  •   kmime
  • kabc
  • kalarmcal
  • kblog
  • kcal
  • kcalcore
  • kcalutils
  • kholidays
  • kimap
  • kioslave
  •   imap4
  •   mbox
  •   nntp
  • kldap
  • kmbox
  • kmime
  • kontactinterface
  • kpimidentities
  • kpimtextedit
  •   richtextbuilders
  • kpimutils
  • kresources
  • ktnef
  • kxmlrpcclient
  • mailtransport
  • microblog
  • qgpgme
  • syndication
  •   atom
  •   rdf
  •   rss2
Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal