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