• Skip to content
  • Skip to link menu
  • KDE API Reference
  • kdepimlibs-4.10.5 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 <QApplication>
31 #include <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 
41  if ( !collection.contentMimeTypes().contains( Collection::mimeType() ) ) {
42  return false;
43  }
44 
45  return true;
46 }
47 
48 static inline bool canContainItems( const Collection &collection )
49 {
50  if ( collection.contentMimeTypes().isEmpty() ) {
51  return false;
52  }
53 
54  if ( ( collection.contentMimeTypes().count() == 1 ) &&
55  ( collection.contentMimeTypes().first() == Collection::mimeType() ) ) {
56  return false;
57  }
58 
59  return true;
60 }
61 
62 ActionStateManager::ActionStateManager()
63  : mReceiver( 0 )
64 {
65 }
66 
67 ActionStateManager::~ActionStateManager()
68 {
69 }
70 
71 void ActionStateManager::setReceiver( QObject *object )
72 {
73  mReceiver = object;
74 }
75 
76 void ActionStateManager::updateState( const Collection::List &collections, const Item::List &items )
77 {
78  const int collectionCount = collections.count();
79  const bool singleCollectionSelected = ( collectionCount == 1 );
80  const bool multipleCollectionsSelected = ( collectionCount > 1 );
81  const bool atLeastOneCollectionSelected = ( singleCollectionSelected || multipleCollectionsSelected );
82 
83  const int itemCount = items.count();
84  const bool singleItemSelected = ( itemCount == 1 );
85  const bool multipleItemsSelected = ( itemCount > 1 );
86  const bool atLeastOneItemSelected = ( singleItemSelected || multipleItemsSelected );
87 
88  const bool listOfCollectionNotEmpty = collections.isEmpty() ? false : true;
89  bool canDeleteCollections = listOfCollectionNotEmpty;
90  if ( canDeleteCollections ) {
91  foreach ( const Collection &collection, collections ) {
92  // do we have the necessary rights?
93  if ( !( collection.rights() & Collection::CanDeleteCollection ) ) {
94  canDeleteCollections = false;
95  break;
96  }
97 
98  if ( isRootCollection( collection ) ) {
99  canDeleteCollections = false;
100  break;
101  }
102 
103  if ( isResourceCollection( collection ) ) {
104  canDeleteCollections = false;
105  break;
106  }
107  }
108  }
109 
110  bool canCutCollections = canDeleteCollections; // we must be able to delete for cutting
111  foreach ( const Collection &collection, collections ) {
112  if ( isSpecialCollection( collection ) ) {
113  canCutCollections = false;
114  break;
115  }
116 
117  if ( !isFolderCollection( collection ) ) {
118  canCutCollections = false;
119  break;
120  }
121  }
122 
123  const bool canMoveCollections = canCutCollections; // we must be able to cut for moving
124 
125  bool canCopyCollections = listOfCollectionNotEmpty;
126  if ( canCopyCollections ) {
127  foreach ( const Collection &collection, collections ) {
128  if ( isRootCollection( collection ) ) {
129  canCopyCollections = false;
130  break;
131  }
132 
133  if ( !isFolderCollection( collection ) ) {
134  canCopyCollections = false;
135  break;
136  }
137  }
138  }
139  bool canAddToFavoriteCollections = listOfCollectionNotEmpty;
140  if ( canAddToFavoriteCollections ) {
141  foreach ( const Collection &collection, collections ) {
142  if ( isRootCollection( collection ) ) {
143  canAddToFavoriteCollections = false;
144  break;
145  }
146 
147  if ( isFavoriteCollection( collection ) ) {
148  canAddToFavoriteCollections = false;
149  break;
150  }
151 
152  if ( !isFolderCollection( collection ) ) {
153  canAddToFavoriteCollections = false;
154  break;
155  }
156 
157  if ( !canContainItems( collection ) ) {
158  canAddToFavoriteCollections = false;
159  break;
160  }
161  }
162  }
163  bool canRemoveFromFavoriteCollections = listOfCollectionNotEmpty;
164  foreach ( const Collection &collection, collections ) {
165  if ( !isFavoriteCollection( collection ) ) {
166  canRemoveFromFavoriteCollections = false;
167  break;
168  }
169  }
170 
171  bool collectionsAreFolders = listOfCollectionNotEmpty;
172 
173  foreach ( const Collection &collection, collections ) {
174  if ( !isFolderCollection( collection ) ) {
175  collectionsAreFolders = false;
176  break;
177  }
178  }
179 
180  bool collectionsAreInTrash = false;
181  foreach ( const Collection &collection, collections ) {
182  if ( collection.hasAttribute<EntityDeletedAttribute>() ) {
183  collectionsAreInTrash = true;
184  break;
185  }
186  }
187 
188  bool atLeastOneCollectionCanHaveItems = false;
189  foreach ( const Collection &collection, collections ) {
190  if ( collectionCanHaveItems( collection ) ) {
191  atLeastOneCollectionCanHaveItems = true;
192  break;
193  }
194  }
195 
196  const Collection collection = ( !collections.isEmpty() ? collections.first() : Collection() );
197 
198  // collection specific actions
199  enableAction( StandardActionManager::CreateCollection, singleCollectionSelected && // we can create only inside one collection
200  canCreateSubCollection( collection ) ); // we need the necessary rights
201 
202  enableAction( StandardActionManager::DeleteCollections, canDeleteCollections );
203 
204  enableAction( StandardActionManager::CopyCollections, canCopyCollections );
205 
206  enableAction( StandardActionManager::CutCollections, canCutCollections );
207 
208  enableAction( StandardActionManager::CopyCollectionToMenu, canCopyCollections );
209 
210  enableAction( StandardActionManager::MoveCollectionToMenu, canMoveCollections );
211 
212  enableAction( StandardActionManager::MoveCollectionsToTrash, atLeastOneCollectionSelected && canMoveCollections && !collectionsAreInTrash );
213 
214  enableAction( StandardActionManager::RestoreCollectionsFromTrash, atLeastOneCollectionSelected && canMoveCollections && collectionsAreInTrash );
215 
216  enableAction( StandardActionManager::CopyCollectionToDialog, canCopyCollections );
217 
218  enableAction( StandardActionManager::MoveCollectionToDialog, canMoveCollections );
219 
220  enableAction( StandardActionManager::CollectionProperties, singleCollectionSelected && // we can only configure one collection at a time
221  !isRootCollection( collection ) ); // we can not configure the root collection
222 
223  enableAction( StandardActionManager::SynchronizeCollections, atLeastOneCollectionCanHaveItems ); // it must be a valid folder collection
224 
225  enableAction( StandardActionManager::SynchronizeCollectionsRecursive, atLeastOneCollectionSelected &&
226  collectionsAreFolders ); // it must be a valid folder collection
227 #ifndef QT_NO_CLIPBOARD
228  enableAction( StandardActionManager::Paste, singleCollectionSelected && // we can paste only into a single collection
229  PasteHelper::canPaste( QApplication::clipboard()->mimeData(), collection ) ); // there must be data on the clipboard
230 #else
231  enableAction( StandardActionManager::Paste, false ); // no support for clipboard -> no paste
232 #endif
233 
234  // favorite collections specific actions
235  enableAction( StandardActionManager::AddToFavoriteCollections, canAddToFavoriteCollections );
236 
237  enableAction( StandardActionManager::RemoveFromFavoriteCollections, canRemoveFromFavoriteCollections );
238 
239  enableAction( StandardActionManager::RenameFavoriteCollection, singleCollectionSelected && // we can rename only one collection at a time
240  isFavoriteCollection( collection ) ); // it must be a favorite collection already
241 
242  // resource specific actions
243  int resourceCollectionCount = 0;
244  bool canDeleteResources = true;
245  bool canConfigureResource = true;
246  bool canSynchronizeResources = true;
247  foreach ( const Collection &collection, collections ) {
248  if ( isResourceCollection( collection ) ) {
249  resourceCollectionCount++;
250 
251  // check that the 'NoConfig' flag is not set for the resource
252  if ( hasResourceCapability( collection, QLatin1String( "NoConfig" ) ) ) {
253  canConfigureResource = false;
254  }
255  } else {
256  // we selected a non-resource collection
257  canDeleteResources = false;
258  canConfigureResource = false;
259  canSynchronizeResources = false;
260  }
261  }
262 
263  if ( resourceCollectionCount == 0 ) {
264  // not a single resource collection has been selected
265  canDeleteResources = false;
266  canConfigureResource = false;
267  canSynchronizeResources = false;
268  }
269 
270  enableAction( StandardActionManager::CreateResource, true );
271  enableAction( StandardActionManager::DeleteResources, canDeleteResources );
272  enableAction( StandardActionManager::ResourceProperties, canConfigureResource );
273  enableAction( StandardActionManager::SynchronizeResources, canSynchronizeResources );
274 
275  if ( collectionsAreInTrash ) {
276  updateAlternatingAction( StandardActionManager::MoveToTrashRestoreCollectionAlternative );
277  //updatePluralLabel( StandardActionManager::MoveToTrashRestoreCollectionAlternative, collectionCount );
278  } else {
279  updateAlternatingAction( StandardActionManager::MoveToTrashRestoreCollection );
280  }
281  enableAction( StandardActionManager::MoveToTrashRestoreCollection, atLeastOneCollectionSelected && canMoveCollections );
282 
283  // item specific actions
284  bool canDeleteItems = ( items.count() > 0 ); //TODO: fixme
285  foreach ( const Item &item, items ) {
286  const Collection parentCollection = item.parentCollection();
287  if ( !parentCollection.isValid() ) {
288  continue;
289  }
290 
291  canDeleteItems = canDeleteItems && ( parentCollection.rights() & Collection::CanDeleteItem );
292  }
293 
294  bool itemsAreInTrash = false;
295  foreach ( const Item &item, items ) {
296  if ( item.hasAttribute<EntityDeletedAttribute>() ) {
297  itemsAreInTrash = true;
298  break;
299  }
300  }
301 
302  enableAction( StandardActionManager::CopyItems, atLeastOneItemSelected ); // we need items to work with
303 
304  enableAction( StandardActionManager::CutItems, atLeastOneItemSelected && // we need items to work with
305  canDeleteItems ); // we need the necessary rights
306 
307  enableAction( StandardActionManager::DeleteItems, atLeastOneItemSelected && // we need items to work with
308  canDeleteItems ); // we need the necessary rights
309 
310  enableAction( StandardActionManager::CopyItemToMenu, atLeastOneItemSelected ); // we need items to work with
311 
312  enableAction( StandardActionManager::MoveItemToMenu, atLeastOneItemSelected && // we need items to work with
313  canDeleteItems ); // we need the necessary rights
314 
315  enableAction( StandardActionManager::MoveItemsToTrash, atLeastOneItemSelected && canDeleteItems && !itemsAreInTrash );
316 
317  enableAction( StandardActionManager::RestoreItemsFromTrash, atLeastOneItemSelected && itemsAreInTrash );
318 
319  enableAction( StandardActionManager::CopyItemToDialog, atLeastOneItemSelected ); // we need items to work with
320 
321  enableAction( StandardActionManager::MoveItemToDialog, atLeastOneItemSelected && // we need items to work with
322  canDeleteItems ); // we need the necessary rights
323 
324  if ( itemsAreInTrash ) {
325  updateAlternatingAction( StandardActionManager::MoveToTrashRestoreItemAlternative );
326  //updatePluralLabel( StandardActionManager::MoveToTrashRestoreItemAlternative, itemCount );
327  } else {
328  updateAlternatingAction( StandardActionManager::MoveToTrashRestoreItem );
329  }
330  enableAction( StandardActionManager::MoveToTrashRestoreItem, atLeastOneItemSelected && // we need items to work with
331  canDeleteItems ); // we need the necessary rights
332 
333  // update the texts of the actions
334  updatePluralLabel( StandardActionManager::CopyCollections, collectionCount );
335  updatePluralLabel( StandardActionManager::CopyItems, itemCount );
336  updatePluralLabel( StandardActionManager::DeleteItems, itemCount );
337  updatePluralLabel( StandardActionManager::CutItems, itemCount );
338  updatePluralLabel( StandardActionManager::CutCollections, collectionCount );
339  updatePluralLabel( StandardActionManager::DeleteCollections, collectionCount );
340  updatePluralLabel( StandardActionManager::SynchronizeCollections, collectionCount );
341  updatePluralLabel( StandardActionManager::SynchronizeCollectionsRecursive, collectionCount );
342  updatePluralLabel( StandardActionManager::DeleteResources, resourceCollectionCount );
343  updatePluralLabel( StandardActionManager::SynchronizeResources, resourceCollectionCount );
344 
345 }
346 
347 bool ActionStateManager::isRootCollection( const Collection &collection ) const
348 {
349  return CollectionUtils::isRoot( collection );
350 }
351 
352 bool ActionStateManager::isResourceCollection( const Collection &collection ) const
353 {
354  return CollectionUtils::isResource( collection );
355 }
356 
357 bool ActionStateManager::isFolderCollection( const Collection &collection ) const
358 {
359  return ( CollectionUtils::isFolder( collection ) ||
360  CollectionUtils::isResource( collection ) ||
361  CollectionUtils::isStructural( collection ) );
362 }
363 
364 bool ActionStateManager::isSpecialCollection( const Collection &collection ) const
365 {
366  return collection.hasAttribute<SpecialCollectionAttribute>();
367 }
368 
369 bool ActionStateManager::isFavoriteCollection( const Collection &collection ) const
370 {
371  if ( !mReceiver ) {
372  return false;
373  }
374 
375  bool result = false;
376  QMetaObject::invokeMethod( mReceiver, "isFavoriteCollection", Qt::DirectConnection,
377  Q_RETURN_ARG( bool, result ), Q_ARG( Akonadi::Collection, collection ) );
378 
379  return result;
380 }
381 
382 bool ActionStateManager::hasResourceCapability( const Collection &collection, const QString &capability ) const
383 {
384  const Akonadi::AgentInstance instance = AgentManager::self()->instance( collection.resource() );
385 
386  return instance.type().capabilities().contains( capability );
387 }
388 
389 bool ActionStateManager::collectionCanHaveItems( const Collection &collection ) const
390 {
391  return !( collection.contentMimeTypes() == ( QStringList() << QLatin1String( "inode/directory" ) ) ||
392  CollectionUtils::isStructural( collection ) );
393 }
394 
395 void ActionStateManager::enableAction( int action, bool state )
396 {
397  if ( !mReceiver ) {
398  return;
399  }
400 
401  QMetaObject::invokeMethod( mReceiver, "enableAction", Qt::DirectConnection, Q_ARG( int, action ), Q_ARG( bool, state ) );
402 }
403 
404 void ActionStateManager::updatePluralLabel( int action, int count )
405 {
406  if ( !mReceiver ) {
407  return;
408  }
409 
410  QMetaObject::invokeMethod( mReceiver, "updatePluralLabel", Qt::DirectConnection, Q_ARG( int, action ), Q_ARG( int, count ) );
411 }
412 
413 void ActionStateManager::updateAlternatingAction( int action )
414 {
415  if ( !mReceiver ) {
416  return;
417  }
418 
419  QMetaObject::invokeMethod( mReceiver, "updateAlternatingAction", Qt::DirectConnection, Q_ARG( int, action ) );
420 }
This file is part of the KDE documentation.
Documentation copyright © 1996-2013 The KDE developers.
Generated on Sat Jul 13 2013 01:27:30 by doxygen 1.8.3.1 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.10.5 API Reference

Skip menu "kdepimlibs-4.10.5 API Reference"
  • akonadi
  •   contact
  •   kmime
  •   socialutils
  • kabc
  • kalarmcal
  • kblog
  • kcal
  • kcalcore
  • kcalutils
  • kholidays
  • kimap
  • kioslave
  •   imap4
  •   mbox
  •   nntp
  • kldap
  • kmbox
  • kmime
  • kontactinterface
  • kpimidentities
  • kpimtextedit
  • 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