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

akonadi

  • akonadi
standardactionmanager.cpp
1 /*
2  Copyright (c) 2008 Volker Krause <vkrause@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 "standardactionmanager.h"
21 
22 #include "actionstatemanager_p.h"
23 #include "agentfilterproxymodel.h"
24 #include "agentinstancecreatejob.h"
25 #include "agentmanager.h"
26 #include "agenttypedialog.h"
27 #include "collectioncreatejob.h"
28 #include "collectiondeletejob.h"
29 #include "collectiondialog.h"
30 #include "collectionmodel.h"
31 #include "collectionutils_p.h"
32 #include "entitytreemodel.h"
33 #include "favoritecollectionsmodel.h"
34 #include "itemdeletejob.h"
35 #include "itemmodel.h"
36 #include "metatypes.h"
37 #include "pastehelper_p.h"
38 #include "specialcollectionattribute_p.h"
39 #include "collectionpropertiesdialog.h"
40 #include "subscriptiondialog_p.h"
41 #include "renamefavoritedialog.h"
42 #include "trashjob.h"
43 #include "trashrestorejob.h"
44 #include "entitydeletedattribute.h"
45 #include "recentcollectionaction_p.h"
46 
47 #include <KAction>
48 #include <KActionCollection>
49 #include <KActionMenu>
50 #include <KDebug>
51 #include <KInputDialog>
52 #include <KLocale>
53 #include <KMenu>
54 #include <KMessageBox>
55 #include <KToggleAction>
56 
57 #include <QtCore/QMimeData>
58 #include <QApplication>
59 #include <QClipboard>
60 #include <QItemSelectionModel>
61 #include <QWeakPointer>
62 
63 #include <boost/static_assert.hpp>
64 
65 using namespace Akonadi;
66 
67 //@cond PRIVATE
68 
69 enum ActionType
70 {
71  NormalAction,
72  ActionWithAlternative, //Normal action, but with an alternative state
73  ActionAlternative, //Alternative state of the ActionWithAlternative
74  MenuAction,
75  ToggleAction
76 };
77 
78 static const struct {
79  const char *name;
80  const char *label;
81  const char *iconLabel;
82  const char *icon;
83  int shortcut;
84  const char* slot;
85  ActionType actionType;
86 } standardActionData[] = {
87  { "akonadi_collection_create", I18N_NOOP( "&New Folder..." ), I18N_NOOP( "New" ), "folder-new", 0, SLOT(slotCreateCollection()), NormalAction },
88  { "akonadi_collection_copy", 0, 0, "edit-copy", 0, SLOT(slotCopyCollections()), NormalAction },
89  { "akonadi_collection_delete", I18N_NOOP( "&Delete Folder" ), I18N_NOOP( "Delete" ), "edit-delete", 0, SLOT(slotDeleteCollection()), NormalAction },
90  { "akonadi_collection_sync", I18N_NOOP( "&Synchronize Folder" ), I18N_NOOP( "Synchronize" ), "view-refresh", Qt::Key_F5, SLOT(slotSynchronizeCollection()), NormalAction },
91  { "akonadi_collection_properties", I18N_NOOP( "Folder &Properties" ), I18N_NOOP( "Properties" ), "configure", 0, SLOT(slotCollectionProperties()), NormalAction },
92  { "akonadi_item_copy", 0, 0, "edit-copy", 0, SLOT(slotCopyItems()), NormalAction },
93  { "akonadi_paste", I18N_NOOP( "&Paste" ), I18N_NOOP( "Paste" ), "edit-paste", Qt::CTRL + Qt::Key_V, SLOT(slotPaste()), NormalAction },
94  { "akonadi_item_delete", 0, 0, "edit-delete", Qt::Key_Delete, SLOT(slotDeleteItems()), NormalAction },
95  { "akonadi_manage_local_subscriptions", I18N_NOOP( "Manage Local &Subscriptions..." ), I18N_NOOP( "Manage Local Subscriptions" ), "folder-bookmarks", 0, SLOT(slotLocalSubscription()), NormalAction },
96  { "akonadi_collection_add_to_favorites", I18N_NOOP( "Add to Favorite Folders" ), I18N_NOOP( "Add to Favorite" ), "bookmark-new", 0, SLOT(slotAddToFavorites()), NormalAction },
97  { "akonadi_collection_remove_from_favorites", I18N_NOOP( "Remove from Favorite Folders" ), I18N_NOOP( "Remove from Favorite" ), "edit-delete", 0, SLOT(slotRemoveFromFavorites()), NormalAction },
98  { "akonadi_collection_rename_favorite", I18N_NOOP( "Rename Favorite..." ), I18N_NOOP( "Rename" ), "edit-rename", 0, SLOT(slotRenameFavorite()), NormalAction },
99  { "akonadi_collection_copy_to_menu", I18N_NOOP( "Copy Folder To..." ), I18N_NOOP( "Copy To" ), "edit-copy", 0, SLOT(slotCopyCollectionTo(QAction*)), MenuAction },
100  { "akonadi_item_copy_to_menu", I18N_NOOP( "Copy Item To..." ), I18N_NOOP( "Copy To" ), "edit-copy", 0, SLOT(slotCopyItemTo(QAction*)), MenuAction },
101  { "akonadi_item_move_to_menu", I18N_NOOP( "Move Item To..." ), I18N_NOOP( "Move To" ), "go-jump", 0, SLOT(slotMoveItemTo(QAction*)), MenuAction },
102  { "akonadi_collection_move_to_menu", I18N_NOOP( "Move Folder To..." ), I18N_NOOP( "Move To" ), "go-jump", 0, SLOT(slotMoveCollectionTo(QAction*)), MenuAction },
103  { "akonadi_item_cut", I18N_NOOP( "&Cut Item" ), I18N_NOOP( "Cut" ), "edit-cut", Qt::CTRL + Qt::Key_X, SLOT(slotCutItems()), NormalAction },
104  { "akonadi_collection_cut", I18N_NOOP( "&Cut Folder" ), I18N_NOOP( "Cut" ), "edit-cut", Qt::CTRL + Qt::Key_X, SLOT(slotCutCollections()), NormalAction },
105  { "akonadi_resource_create", I18N_NOOP( "Create Resource" ), 0, "folder-new", 0, SLOT(slotCreateResource()), NormalAction },
106  { "akonadi_resource_delete", I18N_NOOP( "Delete Resource" ), 0, "edit-delete", 0, SLOT(slotDeleteResource()), NormalAction },
107  { "akonadi_resource_properties", I18N_NOOP( "&Resource Properties" ), I18N_NOOP( "Properties" ), "configure", 0, SLOT(slotResourceProperties()), NormalAction },
108  { "akonadi_resource_synchronize", I18N_NOOP( "Synchronize Resource" ), I18N_NOOP( "Synchronize" ), "view-refresh", 0, SLOT(slotSynchronizeResource()), NormalAction },
109  { "akonadi_work_offline", I18N_NOOP( "Work Offline" ), 0, "user-offline", 0, SLOT(slotToggleWorkOffline(bool)), ToggleAction },
110  { "akonadi_collection_copy_to_dialog", I18N_NOOP( "Copy Folder To..." ), I18N_NOOP( "Copy To" ), "edit-copy", 0, SLOT(slotCopyCollectionTo()), NormalAction },
111  { "akonadi_collection_move_to_dialog", I18N_NOOP( "Move Folder To..." ), I18N_NOOP( "Move To" ), "go-jump", 0, SLOT(slotMoveCollectionTo()), NormalAction },
112  { "akonadi_item_copy_to_dialog", I18N_NOOP( "Copy Item To..." ), I18N_NOOP( "Copy To" ), "edit-copy", 0, SLOT(slotCopyItemTo()), NormalAction },
113  { "akonadi_item_move_to_dialog", I18N_NOOP( "Move Item To..." ), I18N_NOOP( "Move To" ), "go-jump", 0, SLOT(slotMoveItemTo()), NormalAction },
114  { "akonadi_collection_sync_recursive", I18N_NOOP( "&Synchronize Folder Recursively" ), I18N_NOOP( "Synchronize Recursively" ), "view-refresh", Qt::CTRL + Qt::Key_F5, SLOT(slotSynchronizeCollectionRecursive()), NormalAction },
115  { "akonadi_move_collection_to_trash", I18N_NOOP( "&Move Folder To Trash" ), I18N_NOOP( "Move Folder To Trash" ), "user-trash", 0, SLOT(slotMoveCollectionToTrash()), NormalAction },
116  { "akonadi_move_item_to_trash", I18N_NOOP( "&Move Item To Trash" ), I18N_NOOP( "Move Item To Trash" ), "user-trash", 0, SLOT(slotMoveItemToTrash()), NormalAction },
117  { "akonadi_restore_collection_from_trash", I18N_NOOP( "&Restore Folder From Trash" ), I18N_NOOP( "Restore Folder From Trash" ), "view-refresh", 0, SLOT(slotRestoreCollectionFromTrash()), NormalAction },
118  { "akonadi_restore_item_from_trash", I18N_NOOP( "&Restore Item From Trash" ), I18N_NOOP( "Restore Item From Trash" ), "view-refresh", 0, SLOT(slotRestoreItemFromTrash()), NormalAction },
119  { "akonadi_collection_trash_restore", I18N_NOOP( "&Restore Folder From Trash" ), I18N_NOOP( "Restore Folder From Trash" ), "user-trash", 0, SLOT(slotTrashRestoreCollection()), ActionWithAlternative },
120  { 0, I18N_NOOP( "&Restore Collection From Trash" ), I18N_NOOP( "Restore Collection From Trash" ), "view-refresh", 0, 0, ActionAlternative },
121  { "akonadi_item_trash_restore", I18N_NOOP( "&Restore Item From Trash" ), I18N_NOOP( "Restore Item From Trash" ), "user-trash", 0, SLOT(slotTrashRestoreItem()), ActionWithAlternative },
122  { 0, I18N_NOOP( "&Restore Item From Trash" ), I18N_NOOP( "Restore Item From Trash" ), "view-refresh", 0, 0, ActionAlternative },
123  { "akonadi_collection_sync_favorite_folders", I18N_NOOP( "&Synchronize Favorite Folders" ), I18N_NOOP( "Synchronize Favorite Folders" ), "view-refresh", Qt::CTRL+Qt::SHIFT+Qt::Key_L , SLOT(slotSynchronizeFavoriteCollections()), NormalAction }
124 
125 };
126 static const int numStandardActionData = sizeof standardActionData / sizeof *standardActionData;
127 
128 BOOST_STATIC_ASSERT( numStandardActionData == StandardActionManager::LastType );
129 
130 static bool canCreateCollection( const Akonadi::Collection &collection )
131 {
132  if ( !( collection.rights() & Akonadi::Collection::CanCreateCollection ) )
133  return false;
134 
135  if ( !collection.contentMimeTypes().contains( Akonadi::Collection::mimeType() ) )
136  return false;
137 
138  return true;
139 }
140 
141 static inline bool isRootCollection( const Akonadi::Collection &collection )
142 {
143  return (collection == Akonadi::Collection::root());
144 }
145 
146 static void setWorkOffline( bool offline )
147 {
148  KConfig config( QLatin1String( "akonadikderc" ) );
149  KConfigGroup group( &config, QLatin1String( "Actions" ) );
150 
151  group.writeEntry( "WorkOffline", offline );
152 }
153 
154 static bool workOffline()
155 {
156  KConfig config( QLatin1String( "akonadikderc" ) );
157  const KConfigGroup group( &config, QLatin1String( "Actions" ) );
158 
159  return group.readEntry( "WorkOffline", false );
160 }
161 
162 static QModelIndexList safeSelectedRows( QItemSelectionModel *selectionModel )
163 {
164  QModelIndexList selectedRows = selectionModel->selectedRows();
165  if (!selectedRows.isEmpty())
166  return selectedRows;
167 
168  // try harder for selected rows that don't span the full row for some reason (e.g. due to buggy column adding proxy models etc)
169  foreach ( const QItemSelectionRange &range, selectionModel->selection() ) {
170  if ( !range.isValid() || range.isEmpty() )
171  continue;
172  const QModelIndex parent = range.parent();
173  for ( int row = range.top(); row <= range.bottom(); ++row ) {
174  const QModelIndex index = range.model()->index( row, range.left(), parent );
175  const Qt::ItemFlags flags = range.model()->flags( index );
176  if ( (flags & Qt::ItemIsSelectable) && (flags & Qt::ItemIsEnabled) )
177  selectedRows.push_back( index );
178  }
179  }
180 
181  return selectedRows;
182 }
183 
184 
188 class StandardActionManager::Private
189 {
190  public:
191  Private( StandardActionManager *parent ) :
192  q( parent ),
193  actionCollection( 0 ),
194  parentWidget( 0 ),
195  collectionSelectionModel( 0 ),
196  itemSelectionModel( 0 ),
197  favoritesModel( 0 ),
198  favoriteSelectionModel( 0 ),
199  insideSelectionSlot( false )
200  {
201  actions.fill( 0, StandardActionManager::LastType );
202 
203  pluralLabels.insert( StandardActionManager::CopyCollections,
204  ki18np( "&Copy Folder", "&Copy %1 Folders" ) );
205  pluralLabels.insert( StandardActionManager::CopyItems,
206  ki18np( "&Copy Item", "&Copy %1 Items" ) );
207  pluralLabels.insert( StandardActionManager::CutItems,
208  ki18np( "&Cut Item", "&Cut %1 Items" ) );
209  pluralLabels.insert( StandardActionManager::CutCollections,
210  ki18np( "&Cut Folder", "&Cut %1 Folders" ) );
211  pluralLabels.insert( StandardActionManager::DeleteItems,
212  ki18np( "&Delete Item", "&Delete %1 Items" ) );
213  pluralLabels.insert( StandardActionManager::DeleteCollections,
214  ki18np( "&Delete Folder", "&Delete %1 Folders" ) );
215  pluralLabels.insert( StandardActionManager::SynchronizeCollections,
216  ki18np( "&Synchronize Folder", "&Synchronize %1 Folders" ) );
217  pluralLabels.insert( StandardActionManager::DeleteResources,
218  ki18np( "&Delete Resource", "&Delete %1 Resources" ) );
219  pluralLabels.insert( StandardActionManager::SynchronizeResources,
220  ki18np( "&Synchronize Resource", "&Synchronize %1 Resources" ) );
221 
222 
223  pluralIconLabels.insert( StandardActionManager::CopyCollections,
224  ki18np( "Copy Folder", "Copy %1 Folders" ) );
225  pluralIconLabels.insert( StandardActionManager::CopyItems,
226  ki18np( "Copy Item", "Copy %1 Items" ) );
227  pluralIconLabels.insert( StandardActionManager::CutItems,
228  ki18np( "Cut Item", "Cut %1 Items" ) );
229  pluralIconLabels.insert( StandardActionManager::CutCollections,
230  ki18np( "Cut Folder", "Cut %1 Folders" ) );
231  pluralIconLabels.insert( StandardActionManager::DeleteItems,
232  ki18np( "Delete Item", "Delete %1 Items" ) );
233  pluralIconLabels.insert( StandardActionManager::DeleteCollections,
234  ki18np( "Delete Folder", "Delete %1 Folders" ) );
235  pluralIconLabels.insert( StandardActionManager::SynchronizeCollections,
236  ki18np( "Synchronize Folder", "Synchronize %1 Folders" ) );
237  pluralIconLabels.insert( StandardActionManager::DeleteResources,
238  ki18np( "Delete Resource", "Delete %1 Resources" ) );
239  pluralIconLabels.insert( StandardActionManager::SynchronizeResources,
240  ki18np( "Synchronize Resource", "Synchronize %1 Resources" ) );
241 
242  setContextText( StandardActionManager::CreateCollection, StandardActionManager::DialogTitle,
243  i18nc( "@title:window", "New Folder" ) );
244  setContextText( StandardActionManager::CreateCollection, StandardActionManager::DialogText,
245  i18nc( "@label:textbox name of a thing", "Name" ) );
246  setContextText( StandardActionManager::CreateCollection, StandardActionManager::ErrorMessageText,
247  ki18n( "Could not create folder: %1" ) );
248  setContextText( StandardActionManager::CreateCollection, StandardActionManager::ErrorMessageTitle,
249  i18n( "Folder creation failed" ) );
250 
251  setContextText( StandardActionManager::DeleteCollections, StandardActionManager::MessageBoxText,
252  ki18np( "Do you really want to delete this folder and all its sub-folders?",
253  "Do you really want to delete %1 folders and all their sub-folders?" ) );
254  setContextText( StandardActionManager::DeleteCollections, StandardActionManager::MessageBoxTitle,
255  ki18ncp( "@title:window", "Delete folder?", "Delete folders?" ) );
256  setContextText( StandardActionManager::DeleteCollections, StandardActionManager::ErrorMessageText,
257  ki18n( "Could not delete folder: %1" ) );
258  setContextText( StandardActionManager::DeleteCollections, StandardActionManager::ErrorMessageTitle,
259  i18n( "Folder deletion failed" ) );
260 
261  setContextText( StandardActionManager::CollectionProperties, StandardActionManager::DialogTitle,
262  ki18nc( "@title:window", "Properties of Folder %1" ) );
263 
264  setContextText( StandardActionManager::DeleteItems, StandardActionManager::MessageBoxText,
265  ki18np( "Do you really want to delete the selected item?",
266  "Do you really want to delete %1 items?" ) );
267  setContextText( StandardActionManager::DeleteItems, StandardActionManager::MessageBoxTitle,
268  ki18ncp( "@title:window", "Delete item?", "Delete items?" ) );
269  setContextText( StandardActionManager::DeleteItems, StandardActionManager::ErrorMessageText,
270  ki18n( "Could not delete item: %1" ) );
271  setContextText( StandardActionManager::DeleteItems, StandardActionManager::ErrorMessageTitle,
272  i18n( "Item deletion failed" ) );
273 
274  setContextText( StandardActionManager::RenameFavoriteCollection, StandardActionManager::DialogTitle,
275  i18nc( "@title:window", "Rename Favorite" ) );
276  setContextText( StandardActionManager::RenameFavoriteCollection, StandardActionManager::DialogText,
277  i18nc( "@label:textbox name of the folder", "Name:" ) );
278 
279  setContextText( StandardActionManager::CreateResource, StandardActionManager::DialogTitle,
280  i18nc( "@title:window", "New Resource" ) );
281  setContextText( StandardActionManager::CreateResource, StandardActionManager::ErrorMessageText,
282  ki18n( "Could not create resource: %1" ) );
283  setContextText( StandardActionManager::CreateResource, StandardActionManager::ErrorMessageTitle,
284  i18n( "Resource creation failed" ) );
285 
286  setContextText( StandardActionManager::DeleteResources, StandardActionManager::MessageBoxText,
287  ki18np( "Do you really want to delete this resource?",
288  "Do you really want to delete %1 resources?" ) );
289  setContextText( StandardActionManager::DeleteResources, StandardActionManager::MessageBoxTitle,
290  ki18ncp( "@title:window", "Delete Resource?", "Delete Resources?" ) );
291 
292  setContextText( StandardActionManager::Paste, StandardActionManager::ErrorMessageText,
293  ki18n( "Could not paste data: %1" ) );
294  setContextText( StandardActionManager::Paste, StandardActionManager::ErrorMessageTitle,
295  i18n( "Paste failed" ) );
296 
297  qRegisterMetaType<Akonadi::Item::List>("Akonadi::Item::List");
298  }
299  void enableAction( int type, bool enable )
300  {
301  enableAction( static_cast<StandardActionManager::Type>( type ), enable );
302  }
303 
304  void enableAction( StandardActionManager::Type type, bool enable )
305  {
306  Q_ASSERT( type < StandardActionManager::LastType );
307  if ( actions[type] )
308  actions[type]->setEnabled( enable );
309 
310  // Update the action menu
311  KActionMenu *actionMenu = qobject_cast<KActionMenu*>( actions[type] );
312  if ( actionMenu ) {
313  //get rid of the submenus, they are re-created in enableAction. clear() is not enough, doesn't remove the submenu object instances.
314  KMenu *menu = actionMenu->menu();
315  //Not necessary to delete and recreate menu when it was not created
316  if ( menu->property( "actionType" ).isValid() && menu->isEmpty() )
317  return;
318  mRecentCollectionsMenu.remove(type);
319  delete menu;
320  menu = new KMenu();
321 
322  menu->setProperty( "actionType", static_cast<int>( type ) );
323  q->connect( menu, SIGNAL(aboutToShow()), SLOT(aboutToShowMenu()) );
324  q->connect( menu, SIGNAL(triggered(QAction*)), standardActionData[ type ].slot );
325  actionMenu->setMenu( menu );
326  }
327  }
328 
329  void aboutToShowMenu()
330  {
331  QMenu *menu = qobject_cast<QMenu*>( q->sender() );
332  if ( !menu )
333  return;
334 
335  if ( !menu->isEmpty() )
336  return;
337  // collect all selected collections
338  const Akonadi::Collection::List selectedCollectionsList = selectedCollections();
339  const StandardActionManager::Type type = static_cast<StandardActionManager::Type>( menu->property( "actionType" ).toInt() );
340 
341  QWeakPointer<RecentCollectionAction> recentCollection = new RecentCollectionAction( collectionSelectionModel->model(), menu );
342  mRecentCollectionsMenu.insert( type, recentCollection );
343  const QSet<QString> mimeTypes = mimeTypesOfSelection( type );
344  fillFoldersMenu( selectedCollectionsList,
345  mimeTypes,
346  type,
347  menu,
348  collectionSelectionModel->model(),
349  QModelIndex() );
350  }
351 
352  void createActionFolderMenu(QMenu *menu, StandardActionManager::Type type)
353  {
354  if ( type == CopyCollectionToMenu ||
355  type == CopyItemToMenu ||
356  type == MoveItemToMenu ||
357  type ==MoveCollectionToMenu )
358  {
359 
360  QWeakPointer<RecentCollectionAction> recentCollection = new RecentCollectionAction( collectionSelectionModel->model(), menu );
361  Collection::List selectedCollectionsList = selectedCollections();
362  const QSet<QString> mimeTypes = mimeTypesOfSelection( type );
363  fillFoldersMenu( selectedCollectionsList,
364  mimeTypes,
365  type,
366  menu,
367  collectionSelectionModel->model(),
368  QModelIndex() );
369  }
370  }
371 
372 
373  void updateAlternatingAction( int type )
374  {
375  updateAlternatingAction( static_cast<StandardActionManager::Type>( type ) );
376  }
377 
378  void updateAlternatingAction( StandardActionManager::Type type )
379  {
380  Q_ASSERT( type < StandardActionManager::LastType );
381  if (!actions[type]) {
382  return;
383  }
384 
385  /*
386  * The same action is stored at the ActionWithAlternative indexes as well as the corresponding ActionAlternative indexes in the actions array.
387  * The following simply changes the standardActionData
388  */
389  if ( ( standardActionData[type].actionType == ActionWithAlternative ) || ( standardActionData[type].actionType == ActionAlternative ) ) {
390  actions[type]->setText( i18n ( standardActionData[type].label ) );
391  actions[type]->setIcon( KIcon( QString::fromLatin1( standardActionData[type].icon ) ) );
392 
393  if ( pluralLabels.contains( type ) && !pluralLabels.value( type ).isEmpty() )
394  actions[type]->setText( pluralLabels.value( type ).subs( 1 ).toString() );
395  else if ( standardActionData[type].label )
396  actions[type]->setText( i18n( standardActionData[type].label ) );
397 
398  if ( pluralIconLabels.contains( type ) && !pluralIconLabels.value( type ).isEmpty() )
399  actions[type]->setIconText( pluralIconLabels.value( type ).subs( 1 ).toString() );
400  else if ( standardActionData[type].iconLabel )
401  actions[type]->setIconText( i18n( standardActionData[type].iconLabel ) );
402 
403  if ( standardActionData[type].icon )
404  actions[type]->setIcon( KIcon( QString::fromLatin1( standardActionData[type].icon ) ) );
405 
406  //actions[type]->setShortcut( standardActionData[type].shortcut );
407 
408  /*if ( standardActionData[type].slot ) {
409  switch ( standardActionData[type].actionType ) {
410  case NormalAction:
411  case ActionWithAlternative:
412  connect( action, SIGNAL(triggered()), standardActionData[type].slot );
413  break;
414  }
415  }*/
416  }
417  }
418 
419  void updatePluralLabel( int type, int count )
420  {
421  updatePluralLabel( static_cast<StandardActionManager::Type>( type ), count );
422  }
423 
424  void updatePluralLabel( StandardActionManager::Type type, int count )
425  {
426  Q_ASSERT( type < StandardActionManager::LastType );
427  if ( actions[type] && pluralLabels.contains( type ) && !pluralLabels.value( type ).isEmpty() ) {
428  actions[type]->setText( pluralLabels.value( type ).subs( qMax( count, 1 ) ).toString() );
429  }
430  }
431 
432  bool isFavoriteCollection( const Akonadi::Collection &collection )
433  {
434  if ( !favoritesModel )
435  return false;
436 
437  return favoritesModel->collectionIds().contains( collection.id() );
438  }
439 
440  void encodeToClipboard( QItemSelectionModel* selectionModel, bool cut = false )
441  {
442  Q_ASSERT( selectionModel );
443  if ( safeSelectedRows( selectionModel ).count() <= 0 )
444  return;
445 
446 #ifndef QT_NO_CLIPBOARD
447  QMimeData *mimeData = selectionModel->model()->mimeData( safeSelectedRows( selectionModel ) );
448  markCutAction( mimeData, cut );
449  QApplication::clipboard()->setMimeData( mimeData );
450 
451  QAbstractItemModel *model = const_cast<QAbstractItemModel *>( selectionModel->model() );
452 
453  foreach ( const QModelIndex &index, safeSelectedRows( selectionModel ) )
454  model->setData( index, true, EntityTreeModel::PendingCutRole );
455 #endif
456  }
457 
458  void updateActions()
459  {
460  // collect all selected collections
461  Collection::List selectedCollectionsList;
462  if ( collectionSelectionModel ) {
463  const QModelIndexList rows = safeSelectedRows( collectionSelectionModel );
464  foreach ( const QModelIndex &index, rows ) {
465  Collection collection = index.data( EntityTreeModel::CollectionRole ).value<Collection>();
466  if ( !collection.isValid() )
467  continue;
468 
469  const Collection parentCollection = index.data( EntityTreeModel::ParentCollectionRole ).value<Collection>();
470  collection.setParentCollection( parentCollection );
471 
472  selectedCollectionsList << collection;
473  }
474  }
475 
476  // collect all selected items
477  Item::List selectedItems;
478  if ( itemSelectionModel ) {
479  const QModelIndexList rows = safeSelectedRows( itemSelectionModel );
480  foreach ( const QModelIndex &index, rows ) {
481  Item item = index.data( EntityTreeModel::ItemRole ).value<Item>();
482  if ( !item.isValid() )
483  continue;
484 
485  const Collection parentCollection = index.data( EntityTreeModel::ParentCollectionRole ).value<Collection>();
486  item.setParentCollection( parentCollection );
487 
488  selectedItems << item;
489  }
490  }
491 
492  mActionStateManager.updateState( selectedCollectionsList, selectedItems );
493  if( favoritesModel)
494  enableAction( StandardActionManager::SynchronizeFavoriteCollections, (favoritesModel->rowCount() > 0));
495  emit q->actionStateUpdated();
496  }
497 
498 #ifndef QT_NO_CLIPBOARD
499  void clipboardChanged( QClipboard::Mode mode )
500  {
501  if ( mode == QClipboard::Clipboard )
502  updateActions();
503  }
504 #endif
505 
506  QItemSelection mapToEntityTreeModel( const QAbstractItemModel *model, const QItemSelection &selection ) const
507  {
508  const QAbstractProxyModel *proxy = qobject_cast<const QAbstractProxyModel*>( model );
509  if ( proxy ) {
510  return mapToEntityTreeModel( proxy->sourceModel(), proxy->mapSelectionToSource( selection ) );
511  } else {
512  return selection;
513  }
514  }
515 
516  QItemSelection mapFromEntityTreeModel( const QAbstractItemModel *model, const QItemSelection &selection ) const
517  {
518  const QAbstractProxyModel *proxy = qobject_cast<const QAbstractProxyModel*>( model );
519  if ( proxy ) {
520  const QItemSelection select = mapFromEntityTreeModel( proxy->sourceModel(), selection );
521  return proxy->mapSelectionFromSource( select );
522  } else {
523  return selection;
524  }
525  }
526 
527  // RAII class for setting insideSelectionSlot to true on entering, and false on exiting, the two slots below.
528  class InsideSelectionSlotBlocker {
529  public:
530  InsideSelectionSlotBlocker( Private *p ) : _p( p ) {
531  Q_ASSERT( !p->insideSelectionSlot );
532  p->insideSelectionSlot = true;
533  }
534  ~InsideSelectionSlotBlocker() {
535  Q_ASSERT( _p->insideSelectionSlot );
536  _p->insideSelectionSlot = false;
537  }
538  private:
539  Private *_p;
540  };
541 
542  void collectionSelectionChanged()
543  {
544  if ( insideSelectionSlot )
545  return;
546  InsideSelectionSlotBlocker block( this );
547  QItemSelection selection = collectionSelectionModel->selection();
548  selection = mapToEntityTreeModel( collectionSelectionModel->model(), selection );
549  selection = mapFromEntityTreeModel( favoritesModel, selection );
550 
551  if ( favoriteSelectionModel ) {
552  favoriteSelectionModel->select( selection, QItemSelectionModel::ClearAndSelect );
553  }
554 
555  updateActions();
556  }
557 
558  void favoriteSelectionChanged()
559  {
560  if ( insideSelectionSlot )
561  return;
562  QItemSelection selection = favoriteSelectionModel->selection();
563  if ( selection.isEmpty() )
564  return;
565 
566  selection = mapToEntityTreeModel( favoritesModel, selection );
567  selection = mapFromEntityTreeModel( collectionSelectionModel->model(), selection );
568 
569  InsideSelectionSlotBlocker block( this );
570  collectionSelectionModel->select( selection, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows );
571 
572  // Also set the current index. This will trigger KMMainWidget::slotFolderChanged in kmail, which we want.
573  collectionSelectionModel->setCurrentIndex( selection.indexes().first(), QItemSelectionModel::NoUpdate );
574 
575  updateActions();
576  }
577 
578  void slotCreateCollection()
579  {
580  Q_ASSERT( collectionSelectionModel );
581  if ( collectionSelectionModel->selection().indexes().isEmpty() )
582  return;
583 
584  const QModelIndex index = collectionSelectionModel->selection().indexes().at( 0 );
585  Q_ASSERT( index.isValid() );
586  const Collection parentCollection = index.data( CollectionModel::CollectionRole ).value<Collection>();
587  Q_ASSERT( parentCollection.isValid() );
588 
589  if ( !canCreateCollection( parentCollection ) )
590  return;
591 
592  QString name = KInputDialog::getText( contextText( StandardActionManager::CreateCollection, StandardActionManager::DialogTitle ),
593  contextText( StandardActionManager::CreateCollection, StandardActionManager::DialogText ),
594  QString(), 0, parentWidget );
595  name = name.trimmed();
596  if ( name.isEmpty() )
597  return;
598 
599  if ( name.contains( QLatin1Char( '/' ) ) ) {
600  KMessageBox::error( parentWidget,
601  i18n( "We can not add \"/\" in folder name." ),
602  i18n( "Create new folder error" ) );
603  return;
604  }
605  if ( name.startsWith( QLatin1Char('.') ) ||
606  name.endsWith( QLatin1Char('.') ) ) {
607  KMessageBox::error( parentWidget,
608  i18n( "We can not add \".\" at begin or end of folder name." ),
609  i18n( "Create new folder error" ) );
610  return;
611  }
612 
613  Collection collection;
614  collection.setName( name );
615  collection.setParentCollection( parentCollection );
616  if ( actions[StandardActionManager::CreateCollection] ) {
617  const QStringList mts = actions[StandardActionManager::CreateCollection]->property( "ContentMimeTypes" ).toStringList();
618  if ( !mts.isEmpty() )
619  collection.setContentMimeTypes( mts );
620  }
621  CollectionCreateJob *job = new CollectionCreateJob( collection );
622  q->connect( job, SIGNAL(result(KJob*)), q, SLOT(collectionCreationResult(KJob*)) );
623  }
624 
625  void slotCopyCollections()
626  {
627  encodeToClipboard( collectionSelectionModel );
628  }
629 
630  void slotCutCollections()
631  {
632  encodeToClipboard( collectionSelectionModel, true );
633  }
634 
635  Collection::List selectedCollections()
636  {
637  Collection::List collections;
638 
639  Q_ASSERT( collectionSelectionModel );
640 
641  foreach ( const QModelIndex &index, safeSelectedRows( collectionSelectionModel ) ) {
642  Q_ASSERT( index.isValid() );
643  const Collection collection = index.data( CollectionModel::CollectionRole ).value<Collection>();
644  Q_ASSERT( collection.isValid() );
645 
646  collections << collection;
647  }
648 
649  return collections;
650  }
651 
652  void slotDeleteCollection()
653  {
654  const Collection::List collections = selectedCollections();
655  if ( collections.isEmpty() )
656  return;
657 
658  const QString collectionName = collections.first().name();
659  const QString text = contextText( StandardActionManager::DeleteCollections, StandardActionManager::MessageBoxText,
660  collections.count(), collectionName );
661 
662  if ( KMessageBox::questionYesNo( parentWidget, text,
663  contextText( StandardActionManager::DeleteCollections, StandardActionManager::MessageBoxTitle, collections.count(), collectionName ),
664  KStandardGuiItem::del(), KStandardGuiItem::cancel(),
665  QString(), KMessageBox::Dangerous ) != KMessageBox::Yes )
666  return;
667 
668  foreach ( const Collection &collection, collections ) {
669  CollectionDeleteJob *job = new CollectionDeleteJob( collection, q );
670  q->connect( job, SIGNAL(result(KJob*)), q, SLOT(collectionDeletionResult(KJob*)) );
671  }
672  }
673 
674  void slotMoveCollectionToTrash()
675  {
676  const Collection::List collections = selectedCollections();
677  if ( collections.isEmpty() )
678  return;
679 
680  foreach ( const Collection &collection, collections ) {
681  TrashJob *job = new TrashJob( collection, q );
682  q->connect( job, SIGNAL(result(KJob*)), q, SLOT(moveCollectionToTrashResult(KJob*)) );
683  }
684  }
685 
686  void slotRestoreCollectionFromTrash()
687  {
688  const Collection::List collections = selectedCollections();
689  if ( collections.isEmpty() )
690  return;
691 
692  foreach ( const Collection &collection, collections ) {
693  TrashRestoreJob *job = new TrashRestoreJob( collection, q );
694  q->connect( job, SIGNAL(result(KJob*)), q, SLOT(moveCollectionToTrashResult(KJob*)) );
695  }
696  }
697 
698  Item::List selectedItems() const
699  {
700  Item::List items;
701 
702  Q_ASSERT( itemSelectionModel );
703 
704  foreach ( const QModelIndex &index, safeSelectedRows( itemSelectionModel ) ) {
705  Q_ASSERT( index.isValid() );
706  const Item item = index.data( ItemModel::ItemRole ).value<Item>();
707  Q_ASSERT( item.isValid() );
708 
709  items << item;
710  }
711 
712  return items;
713  }
714 
715  void slotMoveItemToTrash()
716  {
717  const Item::List items = selectedItems();
718  if ( items.isEmpty() )
719  return;
720 
721  TrashJob *job = new TrashJob( items, q );
722  q->connect( job, SIGNAL(result(KJob*)), q, SLOT(moveItemToTrashResult(KJob*)) );
723  }
724 
725  void slotRestoreItemFromTrash()
726  {
727  const Item::List items = selectedItems();
728  if ( items.isEmpty() )
729  return;
730 
731  TrashRestoreJob *job = new TrashRestoreJob( items, q );
732  q->connect( job, SIGNAL(result(KJob*)), q, SLOT(moveItemToTrashResult(KJob*)) );
733  }
734 
735  void slotTrashRestoreCollection()
736  {
737  const Collection::List collections = selectedCollections();
738  if ( collections.isEmpty() )
739  return;
740 
741  bool collectionsAreInTrash = false;
742  foreach ( const Collection &collection, collections ) {
743  if ( collection.hasAttribute<EntityDeletedAttribute>() ) {
744  collectionsAreInTrash = true;
745  break;
746  }
747  }
748 
749  if (collectionsAreInTrash) {
750  slotRestoreCollectionFromTrash();
751  } else {
752  slotMoveCollectionToTrash();
753  }
754  }
755 
756  void slotTrashRestoreItem()
757  {
758  const Item::List items = selectedItems();
759  if ( items.isEmpty() )
760  return;
761 
762  bool itemsAreInTrash = false;
763  foreach ( const Item &item, items ) {
764  if ( item.hasAttribute<EntityDeletedAttribute>() ) {
765  itemsAreInTrash = true;
766  break;
767  }
768  }
769 
770  if (itemsAreInTrash) {
771  slotRestoreItemFromTrash();
772  } else {
773  slotMoveItemToTrash();
774  }
775  }
776 
777  void slotSynchronizeCollection()
778  {
779  Q_ASSERT( collectionSelectionModel );
780  const QModelIndexList list = safeSelectedRows( collectionSelectionModel );
781  if ( list.isEmpty() )
782  return;
783 
784  const Collection::List collections = selectedCollections();
785  if ( collections.isEmpty() )
786  return;
787 
788  foreach( const Collection &collection, collections ) {
789  if ( !testAndSetOnlineResources(collection) )
790  break;
791  AgentManager::self()->synchronizeCollection( collection, false );
792  }
793  }
794 
795  bool testAndSetOnlineResources(const Akonadi::Collection& collection)
796  {
797  Akonadi::AgentInstance instance = Akonadi::AgentManager::self()->instance( collection.resource() );
798  if ( !instance.isOnline() ) {
799  if ( KMessageBox::questionYesNo( parentWidget, i18n( "Before syncing folder \"%1\" it is necessary to have the resource online. Do you want to make it online?" , collection.name() ), i18n( "Account \"%1\" is offline", instance.name() ) ) != KMessageBox::Yes )
800  return false;
801  instance.setIsOnline( true );
802  }
803  return true;
804  }
805 
806  void slotSynchronizeCollectionRecursive()
807  {
808  Q_ASSERT( collectionSelectionModel );
809  const QModelIndexList list = safeSelectedRows( collectionSelectionModel );
810  if ( list.isEmpty() )
811  return;
812 
813  const Collection::List collections = selectedCollections();
814  if ( collections.isEmpty() )
815  return;
816 
817  foreach( const Collection &collection, collections ) {
818  if ( !testAndSetOnlineResources(collection) )
819  break;
820  AgentManager::self()->synchronizeCollection( collection, true );
821  }
822  }
823 
824  void slotCollectionProperties()
825  {
826  const QModelIndexList list = safeSelectedRows( collectionSelectionModel );
827  if ( list.isEmpty() )
828  return;
829 
830  const QModelIndex index = list.first();
831  Q_ASSERT( index.isValid() );
832 
833  const Collection collection = index.data( CollectionModel::CollectionRole ).value<Collection>();
834  Q_ASSERT( collection.isValid() );
835 
836  const QString displayName = collection.hasAttribute<EntityDisplayAttribute>() ? collection.attribute<EntityDisplayAttribute>()->displayName()
837  : collection.name();
838 
839  CollectionPropertiesDialog* dlg = new CollectionPropertiesDialog( collection, mCollectionPropertiesPageNames, parentWidget );
840  dlg->setCaption( contextText( StandardActionManager::CollectionProperties, StandardActionManager::DialogTitle,displayName ) );
841  dlg->show();
842  }
843 
844  void slotCopyItems()
845  {
846  encodeToClipboard( itemSelectionModel );
847  }
848 
849  void slotCutItems()
850  {
851  encodeToClipboard( itemSelectionModel, true );
852  }
853 
854  void slotPaste()
855  {
856  Q_ASSERT( collectionSelectionModel );
857 
858  const QModelIndexList list = safeSelectedRows( collectionSelectionModel );
859  if ( list.isEmpty() )
860  return;
861 
862  const QModelIndex index = list.first();
863  Q_ASSERT( index.isValid() );
864 
865 #ifndef QT_NO_CLIPBOARD
866  // TODO: Copy or move? We can't seem to cut yet
867  QAbstractItemModel *model = const_cast<QAbstractItemModel *>( collectionSelectionModel->model() );
868  const QMimeData *mimeData = QApplication::clipboard()->mimeData();
869  model->dropMimeData( mimeData, isCutAction( mimeData ) ? Qt::MoveAction : Qt::CopyAction, -1, -1, index );
870  model->setData( QModelIndex(), false, EntityTreeModel::PendingCutRole );
871  QApplication::clipboard()->clear();
872 #endif
873  }
874 
875  void slotDeleteItems()
876  {
877  Q_ASSERT( itemSelectionModel );
878 
879  Item::List items;
880  foreach ( const QModelIndex &index, safeSelectedRows( itemSelectionModel ) ) {
881  bool ok;
882  const qlonglong id = index.data( ItemModel::IdRole ).toLongLong( &ok );
883  Q_ASSERT( ok );
884  items << Item( id );
885  }
886 
887  if ( items.isEmpty() )
888  return;
889 
890  QMetaObject::invokeMethod(q, "slotDeleteItemsDeferred",
891  Qt::QueuedConnection,
892  Q_ARG(Akonadi::Item::List, items));
893  }
894 
895  void slotDeleteItemsDeferred(const Akonadi::Item::List &items)
896  {
897  Q_ASSERT( itemSelectionModel );
898 
899  if ( KMessageBox::questionYesNo( parentWidget,
900  contextText( StandardActionManager::DeleteItems, StandardActionManager::MessageBoxText, items.count(), QString() ),
901  contextText( StandardActionManager::DeleteItems, StandardActionManager::MessageBoxTitle, items.count(), QString() ),
902  KStandardGuiItem::del(), KStandardGuiItem::cancel(),
903  QString(), KMessageBox::Dangerous ) != KMessageBox::Yes )
904  return;
905 
906  ItemDeleteJob *job = new ItemDeleteJob( items, q );
907  q->connect( job, SIGNAL(result(KJob*)), q, SLOT(itemDeletionResult(KJob*)) );
908  }
909 
910  void slotLocalSubscription()
911  {
912  SubscriptionDialog* dlg = new SubscriptionDialog( mMimeTypeFilter, parentWidget );
913  dlg->showHiddenCollection(true);
914  dlg->show();
915  }
916 
917  void slotAddToFavorites()
918  {
919  Q_ASSERT( collectionSelectionModel );
920  Q_ASSERT( favoritesModel );
921  const QModelIndexList list = safeSelectedRows( collectionSelectionModel );
922  if ( list.isEmpty() )
923  return;
924 
925  foreach ( const QModelIndex &index, list ) {
926  Q_ASSERT( index.isValid() );
927  const Collection collection = index.data( CollectionModel::CollectionRole ).value<Collection>();
928  Q_ASSERT( collection.isValid() );
929 
930  favoritesModel->addCollection( collection );
931  }
932 
933  updateActions();
934  }
935 
936  void slotRemoveFromFavorites()
937  {
938  Q_ASSERT( collectionSelectionModel );
939  Q_ASSERT( favoritesModel );
940  const QModelIndexList list = safeSelectedRows( collectionSelectionModel );
941  if ( list.isEmpty() )
942  return;
943 
944  foreach ( const QModelIndex &index, list ) {
945  Q_ASSERT( index.isValid() );
946  const Collection collection = index.data( CollectionModel::CollectionRole ).value<Collection>();
947  Q_ASSERT( collection.isValid() );
948 
949  favoritesModel->removeCollection( collection );
950  }
951 
952  updateActions();
953  }
954 
955  void slotRenameFavorite()
956  {
957  Q_ASSERT( collectionSelectionModel );
958  Q_ASSERT( favoritesModel );
959  const QModelIndexList list = safeSelectedRows( collectionSelectionModel );
960  if ( list.isEmpty() )
961  return;
962  const QModelIndex index = list.first();
963  Q_ASSERT( index.isValid() );
964  const Collection collection = index.data( CollectionModel::CollectionRole ).value<Collection>();
965  Q_ASSERT( collection.isValid() );
966 
967  const QString displayName = collection.hasAttribute<EntityDisplayAttribute>() ? collection.attribute<EntityDisplayAttribute>()->displayName() : collection.name();
968 
969  RenameFavoriteDialog dlg(contextText( StandardActionManager::RenameFavoriteCollection, StandardActionManager::DialogTitle ),contextText( StandardActionManager::RenameFavoriteCollection, StandardActionManager::DialogText ) , favoritesModel->favoriteLabel( collection ), displayName, parentWidget );
970  if ( dlg.exec() )
971  {
972  favoritesModel->setFavoriteLabel( collection, dlg.newName() );
973  }
974  }
975 
976  void slotSynchronizeFavoriteCollections()
977  {
978  Q_ASSERT( favoritesModel );
979  foreach( const Collection& collection, favoritesModel->collections() ) {
980  // there might be virtual collections in favorites which cannot be checked
981  // so let's be safe here, agentmanager asserts otherwise
982  if ( !collection.resource().isEmpty() ) {
983  AgentManager::self()->synchronizeCollection( collection, false );
984  }
985  }
986  }
987 
988  void slotCopyCollectionTo()
989  {
990  pasteTo( collectionSelectionModel, collectionSelectionModel->model(), CopyCollectionToMenu, Qt::CopyAction );
991  }
992 
993  void slotCopyItemTo()
994  {
995  pasteTo( itemSelectionModel, collectionSelectionModel->model(), CopyItemToMenu, Qt::CopyAction );
996  }
997 
998  void slotMoveCollectionTo()
999  {
1000  pasteTo( collectionSelectionModel, collectionSelectionModel->model(), MoveCollectionToMenu, Qt::MoveAction );
1001  }
1002 
1003  void slotMoveItemTo()
1004  {
1005  pasteTo( itemSelectionModel, collectionSelectionModel->model(), MoveItemToMenu, Qt::MoveAction );
1006  }
1007 
1008  void slotCopyCollectionTo( QAction *action )
1009  {
1010  pasteTo( collectionSelectionModel, action, Qt::CopyAction );
1011  }
1012 
1013  void slotCopyItemTo( QAction *action )
1014  {
1015  pasteTo( itemSelectionModel, action, Qt::CopyAction );
1016  }
1017 
1018  void slotMoveCollectionTo( QAction *action )
1019  {
1020  pasteTo( collectionSelectionModel, action, Qt::MoveAction );
1021  }
1022 
1023  void slotMoveItemTo( QAction *action )
1024  {
1025  pasteTo( itemSelectionModel, action, Qt::MoveAction );
1026  }
1027 
1028  AgentInstance::List selectedAgentInstances() const
1029  {
1030  AgentInstance::List instances;
1031 
1032  Q_ASSERT( collectionSelectionModel );
1033  if ( collectionSelectionModel->selection().indexes().isEmpty() )
1034  return instances;
1035 
1036  foreach ( const QModelIndex &index, collectionSelectionModel->selection().indexes() ) {
1037  Q_ASSERT( index.isValid() );
1038  const Collection collection = index.data( CollectionModel::CollectionRole ).value<Collection>();
1039  Q_ASSERT( collection.isValid() );
1040 
1041  if ( collection.isValid() ) {
1042  const QString identifier = collection.resource();
1043  instances << AgentManager::self()->instance( identifier );
1044  }
1045  }
1046 
1047  return instances;
1048  }
1049 
1050  AgentInstance selectedAgentInstance() const
1051  {
1052  const AgentInstance::List instances = selectedAgentInstances();
1053 
1054  if ( instances.isEmpty() )
1055  return AgentInstance();
1056 
1057  return instances.first();
1058  }
1059 
1060  void slotCreateResource()
1061  {
1062  Akonadi::AgentTypeDialog dlg( parentWidget );
1063  dlg.setCaption( contextText( StandardActionManager::CreateResource, StandardActionManager::DialogTitle ) );
1064 
1065  foreach ( const QString &mimeType, mMimeTypeFilter )
1066  dlg.agentFilterProxyModel()->addMimeTypeFilter( mimeType );
1067 
1068  foreach ( const QString &capability, mCapabilityFilter )
1069  dlg.agentFilterProxyModel()->addCapabilityFilter( capability );
1070 
1071  if ( dlg.exec() ) {
1072  const AgentType agentType = dlg.agentType();
1073 
1074  if ( agentType.isValid() ) {
1075  AgentInstanceCreateJob *job = new AgentInstanceCreateJob( agentType, q );
1076  q->connect( job, SIGNAL(result(KJob*)), SLOT(resourceCreationResult(KJob*)) );
1077  job->configure( parentWidget );
1078  job->start();
1079  }
1080  }
1081  }
1082 
1083  void slotDeleteResource()
1084  {
1085  const AgentInstance::List instances = selectedAgentInstances();
1086  if ( instances.isEmpty() )
1087  return;
1088 
1089  if ( KMessageBox::questionYesNo( parentWidget,
1090  contextText( StandardActionManager::DeleteResources, StandardActionManager::MessageBoxText, instances.count(), instances.first().name() ),
1091  contextText( StandardActionManager::DeleteResources, StandardActionManager::MessageBoxTitle, instances.count(), instances.first().name() ),
1092  KStandardGuiItem::del(), KStandardGuiItem::cancel(),
1093  QString(), KMessageBox::Dangerous ) != KMessageBox::Yes )
1094  return;
1095 
1096  foreach ( const AgentInstance &instance, instances )
1097  AgentManager::self()->removeInstance( instance );
1098  }
1099 
1100  void slotSynchronizeResource()
1101  {
1102  const AgentInstance::List instances = selectedAgentInstances();
1103  if ( instances.isEmpty() )
1104  return;
1105 
1106  foreach ( AgentInstance instance, instances ) { //krazy:exclude=foreach
1107  instance.synchronize();
1108  }
1109  }
1110 
1111  void slotResourceProperties()
1112  {
1113  AgentInstance instance = selectedAgentInstance();
1114  if ( !instance.isValid() )
1115  return;
1116 
1117  instance.configure( parentWidget );
1118  }
1119 
1120  void slotToggleWorkOffline( bool offline )
1121  {
1122  setWorkOffline( offline );
1123 
1124  AgentInstance::List instances = AgentManager::self()->instances();
1125  foreach ( AgentInstance instance, instances ) { //krazy:exclude=foreach
1126  instance.setIsOnline( !offline );
1127  }
1128  }
1129 
1130  void pasteTo( QItemSelectionModel *selectionModel, const QAbstractItemModel *model, StandardActionManager::Type type, Qt::DropAction dropAction )
1131  {
1132  const QSet<QString> mimeTypes = mimeTypesOfSelection( type );
1133 
1134  CollectionDialog dlg( const_cast<QAbstractItemModel*>( model ) );
1135  dlg.setMimeTypeFilter( mimeTypes.toList() );
1136 
1137  if ( type == CopyItemToMenu || type == MoveItemToMenu )
1138  dlg.setAccessRightsFilter( Collection::CanCreateItem );
1139  else if ( type == CopyCollectionToMenu || type == MoveCollectionToMenu )
1140  dlg.setAccessRightsFilter( Collection::CanCreateCollection );
1141 
1142  if ( dlg.exec() ) {
1143  const QModelIndex index = EntityTreeModel::modelIndexForCollection( collectionSelectionModel->model(), dlg.selectedCollection() );
1144  if ( !index.isValid() )
1145  return;
1146 
1147  const QMimeData *mimeData = selectionModel->model()->mimeData( safeSelectedRows( selectionModel ) );
1148 
1149  QAbstractItemModel *model = const_cast<QAbstractItemModel *>( index.model() );
1150  model->dropMimeData( mimeData, dropAction, -1, -1, index );
1151  }
1152  }
1153 
1154  void pasteTo( QItemSelectionModel *selectionModel, QAction *action, Qt::DropAction dropAction )
1155  {
1156  Q_ASSERT( selectionModel );
1157  Q_ASSERT( action );
1158 
1159  if ( safeSelectedRows( selectionModel ).count() <= 0 )
1160  return;
1161 
1162  const QMimeData *mimeData = selectionModel->model()->mimeData( selectionModel->selectedRows() );
1163 
1164  const QModelIndex index = action->data().value<QModelIndex>();
1165  Q_ASSERT( index.isValid() );
1166 
1167  QAbstractItemModel *model = const_cast<QAbstractItemModel *>( index.model() );
1168  const Collection collection = index.data( EntityTreeModel::CollectionRole ).value<Collection>();
1169  addRecentCollection( collection.id() );
1170  model->dropMimeData( mimeData, dropAction, -1, -1, index );
1171  }
1172 
1173  void addRecentCollection( Akonadi::Collection::Id id )
1174  {
1175  QMapIterator<StandardActionManager::Type, QWeakPointer<RecentCollectionAction> > item(mRecentCollectionsMenu);
1176  while (item.hasNext()) {
1177  item.next();
1178  if ( item.value().data() ) {
1179  item.value().data()->addRecentCollection( id );
1180  }
1181  }
1182  }
1183 
1184  void collectionCreationResult( KJob *job )
1185  {
1186  if ( job->error() ) {
1187  KMessageBox::error( parentWidget,
1188  contextText( StandardActionManager::CreateCollection, StandardActionManager::ErrorMessageText, job->errorString() ),
1189  contextText( StandardActionManager::CreateCollection, StandardActionManager::ErrorMessageTitle ) );
1190  }
1191  }
1192 
1193  void collectionDeletionResult( KJob *job )
1194  {
1195  if ( job->error() ) {
1196  KMessageBox::error( parentWidget,
1197  contextText( StandardActionManager::DeleteCollections, StandardActionManager::ErrorMessageText, job->errorString() ),
1198  contextText( StandardActionManager::DeleteCollections, StandardActionManager::ErrorMessageTitle ) );
1199  }
1200  }
1201 
1202  void moveCollectionToTrashResult( KJob *job )
1203  {
1204  if ( job->error() ) {
1205  KMessageBox::error( parentWidget,
1206  contextText( StandardActionManager::MoveCollectionsToTrash, StandardActionManager::ErrorMessageText, job->errorString() ),
1207  contextText( StandardActionManager::MoveCollectionsToTrash, StandardActionManager::ErrorMessageTitle ) );
1208  }
1209  }
1210 
1211  void moveItemToTrashResult( KJob *job )
1212  {
1213  if ( job->error() ) {
1214  KMessageBox::error( parentWidget,
1215  contextText( StandardActionManager::MoveItemsToTrash, StandardActionManager::ErrorMessageText, job->errorString() ),
1216  contextText( StandardActionManager::MoveItemsToTrash, StandardActionManager::ErrorMessageTitle ) );
1217  }
1218  }
1219 
1220  void itemDeletionResult( KJob *job )
1221  {
1222  if ( job->error() ) {
1223  KMessageBox::error( parentWidget,
1224  contextText( StandardActionManager::DeleteItems, StandardActionManager::ErrorMessageText, job->errorString() ),
1225  contextText( StandardActionManager::DeleteItems, StandardActionManager::ErrorMessageTitle ) );
1226  }
1227  }
1228 
1229  void resourceCreationResult( KJob *job )
1230  {
1231  if ( job->error() ) {
1232  KMessageBox::error( parentWidget,
1233  contextText( StandardActionManager::CreateResource, StandardActionManager::ErrorMessageText, job->errorString() ),
1234  contextText( StandardActionManager::CreateResource, StandardActionManager::ErrorMessageTitle ) );
1235  }
1236  }
1237 
1238  void pasteResult( KJob *job )
1239  {
1240  if ( job->error() ) {
1241  KMessageBox::error( parentWidget,
1242  contextText( StandardActionManager::Paste, StandardActionManager::ErrorMessageText, job->errorString() ),
1243  contextText( StandardActionManager::Paste, StandardActionManager::ErrorMessageTitle ) );
1244  }
1245  }
1246 
1250  QSet<QString> mimeTypesOfSelection( StandardActionManager::Type type ) const
1251  {
1252  QModelIndexList list;
1253  QSet<QString> mimeTypes;
1254 
1255  const bool isItemAction = ( type == CopyItemToMenu || type == MoveItemToMenu );
1256  const bool isCollectionAction = ( type == CopyCollectionToMenu || type == MoveCollectionToMenu );
1257 
1258  if ( isItemAction ) {
1259  list = safeSelectedRows( itemSelectionModel );
1260  foreach ( const QModelIndex &index, list )
1261  mimeTypes << index.data( EntityTreeModel::MimeTypeRole ).toString();
1262  }
1263 
1264  if ( isCollectionAction ) {
1265  list = safeSelectedRows( collectionSelectionModel );
1266  foreach ( const QModelIndex &index, list ) {
1267  const Collection collection = index.data( EntityTreeModel::CollectionRole ).value<Collection>();
1268 
1269  // The mimetypes that the selected collection can possibly contain
1270  mimeTypes = AgentManager::self()->instance( collection.resource() ).type().mimeTypes().toSet();
1271  }
1272  }
1273 
1274  return mimeTypes;
1275  }
1276 
1280  bool isWritableTargetCollectionForMimeTypes( const Collection &collection, const QSet<QString> &mimeTypes, StandardActionManager::Type type ) const
1281  {
1282  if ( collection.isVirtual() )
1283  return false;
1284 
1285  const bool isItemAction = ( type == CopyItemToMenu || type == MoveItemToMenu );
1286  const bool isCollectionAction = ( type == CopyCollectionToMenu || type == MoveCollectionToMenu );
1287 
1288  const bool canContainRequiredMimeTypes = !collection.contentMimeTypes().toSet().intersect( mimeTypes ).isEmpty();
1289  const bool canCreateNewItems = (collection.rights() & Collection::CanCreateItem);
1290 
1291  const bool canCreateNewCollections = (collection.rights() & Collection::CanCreateCollection);
1292  const bool canContainCollections = collection.contentMimeTypes().contains( Collection::mimeType() );
1293  const bool resourceAllowsRequiredMimeTypes = AgentManager::self()->instance( collection.resource() ).type().mimeTypes().toSet().contains( mimeTypes );
1294 
1295  const bool isReadOnlyForItems = (isItemAction && (!canCreateNewItems || !canContainRequiredMimeTypes));
1296  const bool isReadOnlyForCollections = (isCollectionAction && (!canCreateNewCollections || !canContainCollections || !resourceAllowsRequiredMimeTypes));
1297 
1298  return !(CollectionUtils::isStructural( collection ) || isReadOnlyForItems || isReadOnlyForCollections);
1299  }
1300 
1301  void fillFoldersMenu( const Akonadi::Collection::List& selectedCollectionsList, const QSet<QString>& mimeTypes, StandardActionManager::Type type, QMenu *menu,
1302  const QAbstractItemModel *model, QModelIndex parentIndex )
1303  {
1304  const int rowCount = model->rowCount( parentIndex );
1305 
1306  for ( int row = 0; row < rowCount; ++row ) {
1307  const QModelIndex index = model->index( row, 0, parentIndex );
1308  const Collection collection = model->data( index, CollectionModel::CollectionRole ).value<Collection>();
1309 
1310  if ( collection.isVirtual() )
1311  continue;
1312 
1313  const bool readOnly = !isWritableTargetCollectionForMimeTypes( collection, mimeTypes, type );
1314  const bool collectionIsSelected = selectedCollectionsList.contains( collection );
1315 
1316  QString label = model->data( index ).toString();
1317  label.replace( QLatin1String( "&" ), QLatin1String( "&&" ) );
1318 
1319  const QIcon icon = model->data( index, Qt::DecorationRole ).value<QIcon>();
1320 
1321  if ( model->rowCount( index ) > 0 ) {
1322  // new level
1323  QMenu* popup = new QMenu( menu );
1324  const bool moveAction = (type == MoveCollectionToMenu || type == MoveItemToMenu);
1325  popup->setObjectName( QString::fromUtf8( "subMenu" ) );
1326  popup->setTitle( label );
1327  popup->setIcon( icon );
1328 
1329  fillFoldersMenu( selectedCollectionsList, mimeTypes, type, popup, model, index );
1330 
1331  if ( !readOnly ) {
1332  popup->addSeparator();
1333 
1334  QAction *action = popup->addAction( moveAction ? i18n( "Move to This Folder" ) : i18n( "Copy to This Folder" ) );
1335  action->setData( QVariant::fromValue<QModelIndex>( index ) );
1336  }
1337 
1338  menu->addMenu( popup );
1339 
1340  } else {
1341  // insert an item
1342  QAction* action = menu->addAction( icon, label );
1343  action->setData( QVariant::fromValue<QModelIndex>( index ) );
1344  action->setEnabled( !readOnly && !collectionIsSelected );
1345  }
1346  }
1347  }
1348 
1349  void checkModelsConsistency()
1350  {
1351  if ( favoritesModel == 0 || favoriteSelectionModel == 0 ) {
1352  // No need to check when the favorite collections feature is not used
1353  return;
1354  }
1355 
1356  // find the base ETM of the favourites view
1357  const QAbstractItemModel *favModel = favoritesModel;
1358  while ( const QAbstractProxyModel *proxy = qobject_cast<const QAbstractProxyModel*>( favModel ) ) {
1359  favModel = proxy->sourceModel();
1360  }
1361 
1362  // Check that the collection selection model maps to the same
1363  // EntityTreeModel than favoritesModel
1364  if ( collectionSelectionModel != 0 ) {
1365  const QAbstractItemModel *model = collectionSelectionModel->model();
1366  while ( const QAbstractProxyModel *proxy = qobject_cast<const QAbstractProxyModel*>( model ) ) {
1367  model = proxy->sourceModel();
1368  }
1369 
1370  Q_ASSERT( model == favModel );
1371  }
1372 
1373  // Check that the favorite selection model maps to favoritesModel
1374  const QAbstractItemModel *model = favoriteSelectionModel->model();
1375  while ( const QAbstractProxyModel *proxy = qobject_cast<const QAbstractProxyModel*>( model ) ) {
1376  model = proxy->sourceModel();
1377  }
1378  Q_ASSERT( model == favModel );
1379  }
1380 
1381  void markCutAction( QMimeData *mimeData, bool cut ) const
1382  {
1383  if ( !cut )
1384  return;
1385 
1386  const QByteArray cutSelectionData = "1"; //krazy:exclude=doublequote_chars
1387  mimeData->setData( QLatin1String( "application/x-kde.akonadi-cutselection" ), cutSelectionData);
1388  }
1389 
1390  bool isCutAction( const QMimeData *mimeData ) const
1391  {
1392  const QByteArray data = mimeData->data( QLatin1String( "application/x-kde.akonadi-cutselection" ) );
1393  if ( data.isEmpty() )
1394  return false;
1395  else
1396  return (data.at( 0 ) == '1'); // true if 1
1397  }
1398 
1399  void setContextText( StandardActionManager::Type type, StandardActionManager::TextContext context, const QString &data )
1400  {
1401  ContextTextEntry entry;
1402  entry.text = data;
1403 
1404  contextTexts[ type ].insert( context, entry );
1405  }
1406 
1407  void setContextText( StandardActionManager::Type type, StandardActionManager::TextContext context, const KLocalizedString &data )
1408  {
1409  ContextTextEntry entry;
1410  entry.localizedText = data;
1411 
1412  contextTexts[ type ].insert( context, entry );
1413  }
1414 
1415  QString contextText( StandardActionManager::Type type, StandardActionManager::TextContext context ) const
1416  {
1417  return contextTexts[ type ].value( context ).text;
1418  }
1419 
1420  QString contextText( StandardActionManager::Type type, StandardActionManager::TextContext context, const QString& value ) const
1421  {
1422  KLocalizedString text = contextTexts[ type ].value( context ).localizedText;
1423  if ( text.isEmpty() )
1424  return contextTexts[ type ].value( context ).text;
1425 
1426  return text.subs( value ).toString();
1427  }
1428 
1429 
1430  QString contextText( StandardActionManager::Type type, StandardActionManager::TextContext context, int count, const QString &value ) const
1431  {
1432  KLocalizedString text = contextTexts[ type ].value( context ).localizedText;
1433  if ( text.isEmpty() )
1434  return contextTexts[ type ].value( context ).text;
1435 
1436  const QString str = text.subs( count ).toString();
1437  const int argCount = str.count( QRegExp( QLatin1String( "%[0-9]" ) ) );
1438  if ( argCount > 0 ) {
1439  return text.subs( count ).subs( value ).toString();
1440  } else {
1441  return text.subs( count ).toString();
1442  }
1443  }
1444 
1445  StandardActionManager *q;
1446  KActionCollection *actionCollection;
1447  QWidget *parentWidget;
1448  QItemSelectionModel *collectionSelectionModel;
1449  QItemSelectionModel *itemSelectionModel;
1450  FavoriteCollectionsModel *favoritesModel;
1451  QItemSelectionModel *favoriteSelectionModel;
1452  bool insideSelectionSlot;
1453  QVector<KAction*> actions;
1454  QHash<StandardActionManager::Type, KLocalizedString> pluralLabels;
1455  QHash<StandardActionManager::Type, KLocalizedString> pluralIconLabels;
1456 
1457  struct ContextTextEntry
1458  {
1459  QString text;
1460  KLocalizedString localizedText;
1461  bool isLocalized;
1462  };
1463 
1464  typedef QHash<StandardActionManager::TextContext, ContextTextEntry> ContextTexts;
1465  QHash<StandardActionManager::Type, ContextTexts> contextTexts;
1466 
1467  ActionStateManager mActionStateManager;
1468 
1469  QStringList mMimeTypeFilter;
1470  QStringList mCapabilityFilter;
1471  QStringList mCollectionPropertiesPageNames;
1472  QMap<StandardActionManager::Type, QWeakPointer<RecentCollectionAction> > mRecentCollectionsMenu;
1473 };
1474 
1475 //@endcond
1476 
1477 StandardActionManager::StandardActionManager( KActionCollection * actionCollection,
1478  QWidget * parent) :
1479  QObject( parent ),
1480  d( new Private( this ) )
1481 {
1482  d->parentWidget = parent;
1483  d->actionCollection = actionCollection;
1484  d->mActionStateManager.setReceiver( this );
1485 #ifndef QT_NO_CLIPBOARD
1486  connect( QApplication::clipboard(), SIGNAL(changed(QClipboard::Mode)), SLOT(clipboardChanged(QClipboard::Mode)) );
1487 #endif
1488 }
1489 
1490 StandardActionManager::~ StandardActionManager()
1491 {
1492  delete d;
1493 }
1494 
1495 void StandardActionManager::setCollectionSelectionModel( QItemSelectionModel * selectionModel )
1496 {
1497  d->collectionSelectionModel = selectionModel;
1498  connect( selectionModel, SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
1499  SLOT(collectionSelectionChanged()) );
1500 
1501  d->checkModelsConsistency();
1502 }
1503 
1504 void StandardActionManager::setItemSelectionModel( QItemSelectionModel * selectionModel )
1505 {
1506  d->itemSelectionModel = selectionModel;
1507  connect( selectionModel, SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
1508  SLOT(updateActions()) );
1509 }
1510 
1511 void StandardActionManager::setFavoriteCollectionsModel( FavoriteCollectionsModel *favoritesModel )
1512 {
1513  d->favoritesModel = favoritesModel;
1514  d->checkModelsConsistency();
1515 }
1516 
1517 void StandardActionManager::setFavoriteSelectionModel( QItemSelectionModel *selectionModel )
1518 {
1519  d->favoriteSelectionModel = selectionModel;
1520  connect( selectionModel, SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
1521  SLOT(favoriteSelectionChanged()) );
1522  d->checkModelsConsistency();
1523 }
1524 
1525 KAction* StandardActionManager::createAction( Type type )
1526 {
1527  Q_ASSERT( type < LastType );
1528  if ( d->actions[type] )
1529  return d->actions[type];
1530  KAction *action = 0;
1531  switch ( standardActionData[type].actionType ) {
1532  case NormalAction:
1533  case ActionWithAlternative:
1534  action = new KAction( d->parentWidget );
1535  break;
1536  case ActionAlternative:
1537  d->actions[type] = d->actions[type-1];
1538  Q_ASSERT( d->actions[type] );
1539  if ( (LastType > type+1) && (standardActionData[type+1].actionType == ActionAlternative) ) {
1540  createAction(static_cast<Type>(type+1)); //ensure that alternative actions are initialized when not created by createAllActions
1541  }
1542  return d->actions[type];
1543  case MenuAction:
1544  action = new KActionMenu( d->parentWidget );
1545  break;
1546  case ToggleAction:
1547  action = new KToggleAction( d->parentWidget );
1548  break;
1549  }
1550 
1551  if ( d->pluralLabels.contains( type ) && !d->pluralLabels.value( type ).isEmpty() )
1552  action->setText( d->pluralLabels.value( type ).subs( 1 ).toString() );
1553  else if ( standardActionData[type].label )
1554  action->setText( i18n( standardActionData[type].label ) );
1555 
1556  if ( d->pluralIconLabels.contains( type ) && !d->pluralIconLabels.value( type ).isEmpty() )
1557  action->setIconText( d->pluralIconLabels.value( type ).subs( 1 ).toString() );
1558  else if ( standardActionData[type].iconLabel )
1559  action->setIconText( i18n( standardActionData[type].iconLabel ) );
1560 
1561  if ( standardActionData[type].icon )
1562  action->setIcon( KIcon( QString::fromLatin1( standardActionData[type].icon ) ) );
1563 
1564  action->setShortcut( standardActionData[type].shortcut );
1565 
1566  if ( standardActionData[type].slot ) {
1567  switch ( standardActionData[type].actionType ) {
1568  case NormalAction:
1569  case ActionWithAlternative:
1570  connect( action, SIGNAL(triggered()), standardActionData[type].slot );
1571  break;
1572  case MenuAction:
1573  {
1574  KActionMenu *actionMenu = qobject_cast<KActionMenu*>( action );
1575  connect( actionMenu->menu(), SIGNAL(triggered(QAction*)), standardActionData[type].slot );
1576  }
1577  break;
1578  case ToggleAction:
1579  {
1580  connect( action, SIGNAL(triggered(bool)), standardActionData[type].slot );
1581  }
1582  break;
1583  case ActionAlternative:
1584  Q_ASSERT(0);
1585  }
1586  }
1587 
1588  if ( type == ToggleWorkOffline ) {
1589  // inititalize the action state with information from config file
1590  disconnect( action, SIGNAL(triggered(bool)), this, standardActionData[type].slot );
1591  action->setChecked( workOffline() );
1592  connect( action, SIGNAL(triggered(bool)), this, standardActionData[type].slot );
1593 
1594  //TODO: find a way to check for updates to the config file
1595  }
1596 
1597  Q_ASSERT( standardActionData[type].name );
1598  d->actionCollection->addAction( QString::fromLatin1(standardActionData[type].name), action );
1599  d->actions[type] = action;
1600  if ( ( standardActionData[type].actionType == ActionWithAlternative ) && (standardActionData[type+1].actionType == ActionAlternative)) {
1601  createAction(static_cast<Type>(type+1)); //ensure that alternative actions are initialized when not created by createAllActions
1602  }
1603  d->updateActions();
1604  return action;
1605 }
1606 
1607 void StandardActionManager::createAllActions()
1608 {
1609  for ( uint i = 0; i < LastType; ++i )
1610  createAction( (Type)i );
1611 }
1612 
1613 KAction * StandardActionManager::action( Type type ) const
1614 {
1615  Q_ASSERT( type < LastType );
1616  return d->actions[type];
1617 }
1618 
1619 void StandardActionManager::setActionText( Type type, const KLocalizedString & text )
1620 {
1621  Q_ASSERT( type < LastType );
1622  d->pluralLabels.insert( type, text );
1623  d->updateActions();
1624 }
1625 
1626 void StandardActionManager::interceptAction( Type type, bool intercept )
1627 {
1628  Q_ASSERT( type < LastType );
1629 
1630  const KAction *action = d->actions[type];
1631 
1632  if ( !action )
1633  return;
1634 
1635  if ( intercept )
1636  disconnect( action, SIGNAL(triggered()), this, standardActionData[type].slot );
1637  else
1638  connect( action, SIGNAL(triggered()), standardActionData[type].slot );
1639 }
1640 
1641 Akonadi::Collection::List StandardActionManager::selectedCollections() const
1642 {
1643  Collection::List collections;
1644 
1645  if ( !d->collectionSelectionModel )
1646  return collections;
1647 
1648  foreach ( const QModelIndex &index, safeSelectedRows( d->collectionSelectionModel ) ) {
1649  const Collection collection = index.data( EntityTreeModel::CollectionRole ).value<Collection>();
1650  if ( collection.isValid() )
1651  collections << collection;
1652  }
1653 
1654  return collections;
1655 }
1656 
1657 Item::List StandardActionManager::selectedItems() const
1658 {
1659  Item::List items;
1660 
1661  if ( !d->itemSelectionModel )
1662  return items;
1663 
1664  foreach ( const QModelIndex &index, safeSelectedRows( d->itemSelectionModel ) ) {
1665  const Item item = index.data( EntityTreeModel::ItemRole ).value<Item>();
1666  if ( item.isValid() )
1667  items << item;
1668  }
1669 
1670  return items;
1671 }
1672 
1673 void StandardActionManager::setContextText( Type type, TextContext context, const QString &text )
1674 {
1675  d->setContextText( type, context, text );
1676 }
1677 
1678 void StandardActionManager::setContextText( Type type, TextContext context, const KLocalizedString &text )
1679 {
1680  d->setContextText( type, context, text );
1681 }
1682 
1683 void StandardActionManager::setMimeTypeFilter( const QStringList &mimeTypes )
1684 {
1685  d->mMimeTypeFilter = mimeTypes;
1686 }
1687 
1688 void StandardActionManager::setCapabilityFilter( const QStringList &capabilities )
1689 {
1690  d->mCapabilityFilter = capabilities;
1691 }
1692 
1693 void StandardActionManager::setCollectionPropertiesPageNames( const QStringList &names )
1694 {
1695  d->mCollectionPropertiesPageNames = names;
1696 }
1697 
1698 void StandardActionManager::createActionFolderMenu(QMenu *menu, Type type)
1699 {
1700  d->createActionFolderMenu( menu, type );
1701 }
1702 
1703 
1704 
1705 #include "moc_standardactionmanager.cpp"
This file is part of the KDE documentation.
Documentation copyright © 1996-2013 The KDE developers.
Generated on Sat Jul 13 2013 01:27:42 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