20 #include "standardactionmanager.h"
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"
43 #include "trashrestorejob.h"
44 #include "entitydeletedattribute.h"
45 #include "recentcollectionaction_p.h"
48 #include <KActionCollection>
49 #include <KActionMenu>
51 #include <KInputDialog>
54 #include <KMessageBox>
55 #include <KToggleAction>
57 #include <QtCore/QMimeData>
58 #include <QtGui/QApplication>
59 #include <QtGui/QClipboard>
60 #include <QtGui/QItemSelectionModel>
61 #include <QWeakPointer>
63 #include <boost/static_assert.hpp>
65 using namespace Akonadi;
72 ActionWithAlternative,
81 const char *iconLabel;
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 }
126 static const int numStandardActionData =
sizeof standardActionData /
sizeof *standardActionData;
128 BOOST_STATIC_ASSERT( numStandardActionData == StandardActionManager::LastType );
130 static bool canCreateCollection(
const Akonadi::Collection &collection )
135 if ( !collection.contentMimeTypes().contains( Akonadi::Collection::mimeType() ) )
141 static inline bool isRootCollection(
const Akonadi::Collection &collection )
143 return (collection == Akonadi::Collection::root());
146 static void setWorkOffline(
bool offline )
148 KConfig config( QLatin1String(
"akonadikderc" ) );
149 KConfigGroup group( &config, QLatin1String(
"Actions" ) );
151 group.writeEntry(
"WorkOffline", offline );
154 static bool workOffline()
156 KConfig config( QLatin1String(
"akonadikderc" ) );
157 const KConfigGroup group( &config, QLatin1String(
"Actions" ) );
159 return group.readEntry(
"WorkOffline",
false );
162 static QModelIndexList safeSelectedRows( QItemSelectionModel *selectionModel )
164 QModelIndexList selectedRows = selectionModel->selectedRows();
165 if (!selectedRows.isEmpty())
169 foreach (
const QItemSelectionRange &range, selectionModel->selection() ) {
170 if ( !range.isValid() || range.isEmpty() )
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 );
188 class StandardActionManager::Private
191 Private( StandardActionManager *parent ) :
193 collectionSelectionModel( 0 ),
194 itemSelectionModel( 0 ),
196 favoriteSelectionModel( 0 )
198 actions.fill( 0, StandardActionManager::LastType );
200 pluralLabels.insert( StandardActionManager::CopyCollections,
201 ki18np(
"&Copy Folder",
"&Copy %1 Folders" ) );
202 pluralLabels.insert( StandardActionManager::CopyItems,
203 ki18np(
"&Copy Item",
"&Copy %1 Items" ) );
204 pluralLabels.insert( StandardActionManager::CutItems,
205 ki18np(
"&Cut Item",
"&Cut %1 Items" ) );
206 pluralLabels.insert( StandardActionManager::CutCollections,
207 ki18np(
"&Cut Folder",
"&Cut %1 Folders" ) );
208 pluralLabels.insert( StandardActionManager::DeleteItems,
209 ki18np(
"&Delete Item",
"&Delete %1 Items" ) );
210 pluralLabels.insert( StandardActionManager::DeleteCollections,
211 ki18np(
"&Delete Folder",
"&Delete %1 Folders" ) );
212 pluralLabels.insert( StandardActionManager::SynchronizeCollections,
213 ki18np(
"&Synchronize Folder",
"&Synchronize %1 Folders" ) );
214 pluralLabels.insert( StandardActionManager::DeleteResources,
215 ki18np(
"&Delete Resource",
"&Delete %1 Resources" ) );
216 pluralLabels.insert( StandardActionManager::SynchronizeResources,
217 ki18np(
"&Synchronize Resource",
"&Synchronize %1 Resources" ) );
220 pluralIconLabels.insert( StandardActionManager::CopyCollections,
221 ki18np(
"Copy Folder",
"Copy %1 Folders" ) );
222 pluralIconLabels.insert( StandardActionManager::CopyItems,
223 ki18np(
"Copy Item",
"Copy %1 Items" ) );
224 pluralIconLabels.insert( StandardActionManager::CutItems,
225 ki18np(
"Cut Item",
"Cut %1 Items" ) );
226 pluralIconLabels.insert( StandardActionManager::CutCollections,
227 ki18np(
"Cut Folder",
"Cut %1 Folders" ) );
228 pluralIconLabels.insert( StandardActionManager::DeleteItems,
229 ki18np(
"Delete Item",
"Delete %1 Items" ) );
230 pluralIconLabels.insert( StandardActionManager::DeleteCollections,
231 ki18np(
"Delete Folder",
"Delete %1 Folders" ) );
232 pluralIconLabels.insert( StandardActionManager::SynchronizeCollections,
233 ki18np(
"Synchronize Folder",
"Synchronize %1 Folders" ) );
234 pluralIconLabels.insert( StandardActionManager::DeleteResources,
235 ki18np(
"Delete Resource",
"Delete %1 Resources" ) );
236 pluralIconLabels.insert( StandardActionManager::SynchronizeResources,
237 ki18np(
"Synchronize Resource",
"Synchronize %1 Resources" ) );
239 setContextText( StandardActionManager::CreateCollection, StandardActionManager::DialogTitle,
240 i18nc(
"@title:window",
"New Folder" ) );
241 setContextText( StandardActionManager::CreateCollection, StandardActionManager::DialogText,
242 i18nc(
"@label:textbox name of a thing",
"Name" ) );
243 setContextText( StandardActionManager::CreateCollection, StandardActionManager::ErrorMessageText,
244 ki18n(
"Could not create folder: %1" ) );
245 setContextText( StandardActionManager::CreateCollection, StandardActionManager::ErrorMessageTitle,
246 i18n(
"Folder creation failed" ) );
248 setContextText( StandardActionManager::DeleteCollections, StandardActionManager::MessageBoxText,
249 ki18np(
"Do you really want to delete this folder and all its sub-folders?",
250 "Do you really want to delete %1 folders and all their sub-folders?" ) );
251 setContextText( StandardActionManager::DeleteCollections, StandardActionManager::MessageBoxTitle,
252 ki18ncp(
"@title:window",
"Delete folder?",
"Delete folders?" ) );
253 setContextText( StandardActionManager::DeleteCollections, StandardActionManager::ErrorMessageText,
254 ki18n(
"Could not delete folder: %1" ) );
255 setContextText( StandardActionManager::DeleteCollections, StandardActionManager::ErrorMessageTitle,
256 i18n(
"Folder deletion failed" ) );
258 setContextText( StandardActionManager::CollectionProperties, StandardActionManager::DialogTitle,
259 ki18nc(
"@title:window",
"Properties of Folder %1" ) );
261 setContextText( StandardActionManager::DeleteItems, StandardActionManager::MessageBoxText,
262 ki18np(
"Do you really want to delete the selected item?",
263 "Do you really want to delete %1 items?" ) );
264 setContextText( StandardActionManager::DeleteItems, StandardActionManager::MessageBoxTitle,
265 ki18ncp(
"@title:window",
"Delete item?",
"Delete items?" ) );
266 setContextText( StandardActionManager::DeleteItems, StandardActionManager::ErrorMessageText,
267 ki18n(
"Could not delete item: %1" ) );
268 setContextText( StandardActionManager::DeleteItems, StandardActionManager::ErrorMessageTitle,
269 i18n(
"Item deletion failed" ) );
271 setContextText( StandardActionManager::RenameFavoriteCollection, StandardActionManager::DialogTitle,
272 i18nc(
"@title:window",
"Rename Favorite" ) );
273 setContextText( StandardActionManager::RenameFavoriteCollection, StandardActionManager::DialogText,
274 i18nc(
"@label:textbox name of the folder",
"Name:" ) );
276 setContextText( StandardActionManager::CreateResource, StandardActionManager::DialogTitle,
277 i18nc(
"@title:window",
"New Resource" ) );
278 setContextText( StandardActionManager::CreateResource, StandardActionManager::ErrorMessageText,
279 ki18n(
"Could not create resource: %1" ) );
280 setContextText( StandardActionManager::CreateResource, StandardActionManager::ErrorMessageTitle,
281 i18n(
"Resource creation failed" ) );
283 setContextText( StandardActionManager::DeleteResources, StandardActionManager::MessageBoxText,
284 ki18np(
"Do you really want to delete this resource?",
285 "Do you really want to delete %1 resources?" ) );
286 setContextText( StandardActionManager::DeleteResources, StandardActionManager::MessageBoxTitle,
287 ki18ncp(
"@title:window",
"Delete Resource?",
"Delete Resources?" ) );
289 setContextText( StandardActionManager::Paste, StandardActionManager::ErrorMessageText,
290 ki18n(
"Could not paste data: %1" ) );
291 setContextText( StandardActionManager::Paste, StandardActionManager::ErrorMessageTitle,
292 i18n(
"Paste failed" ) );
294 qRegisterMetaType<Akonadi::Item::List>(
"Akonadi::Item::List");
297 void enableAction(
int type,
bool enable )
299 enableAction( static_cast<StandardActionManager::Type>( type ), enable );
302 void enableAction( StandardActionManager::Type type,
bool enable )
304 Q_ASSERT( type < StandardActionManager::LastType );
306 actions[type]->setEnabled( enable );
309 KActionMenu *actionMenu = qobject_cast<KActionMenu*>( actions[type] );
312 KMenu *menu = actionMenu->menu();
314 if ( menu->property(
"actionType" ).isValid() && menu->isEmpty() )
319 menu->setProperty(
"actionType", static_cast<int>( type ) );
320 q->connect( menu, SIGNAL(aboutToShow()), SLOT(aboutToShowMenu()) );
321 q->connect( menu, SIGNAL(triggered(QAction*)), standardActionData[ type ].slot );
322 actionMenu->setMenu( menu );
326 void aboutToShowMenu()
328 QMenu *menu = qobject_cast<QMenu*>( q->sender() );
332 if ( !menu->isEmpty() )
336 const StandardActionManager::Type type =
static_cast<StandardActionManager::Type
>( menu->property(
"actionType" ).toInt() );
338 QWeakPointer<RecentCollectionAction> recentCollection =
new RecentCollectionAction( collectionSelectionModel->model(), menu );
339 mRecentCollectionsMenu.insert( type, recentCollection );
340 const QSet<QString> mimeTypes = mimeTypesOfSelection( type );
341 fillFoldersMenu( selectedCollectionsList,
345 collectionSelectionModel->model(),
349 void createActionFolderMenu(QMenu *menu, StandardActionManager::Type type)
351 if ( type == CopyCollectionToMenu ||
352 type == CopyItemToMenu ||
353 type == MoveItemToMenu ||
354 type ==MoveCollectionToMenu )
357 QWeakPointer<RecentCollectionAction> recentCollection =
new RecentCollectionAction( collectionSelectionModel->model(), menu );
358 Collection::List selectedCollectionsList = selectedCollections();
359 const QSet<QString> mimeTypes = mimeTypesOfSelection( type );
360 fillFoldersMenu( selectedCollectionsList,
364 collectionSelectionModel->model(),
370 void updateAlternatingAction(
int type )
372 updateAlternatingAction( static_cast<StandardActionManager::Type>( type ) );
375 void updateAlternatingAction( StandardActionManager::Type type )
377 Q_ASSERT( type < StandardActionManager::LastType );
378 if (!actions[type]) {
386 if ( ( standardActionData[type].actionType == ActionWithAlternative ) || ( standardActionData[type].actionType == ActionAlternative ) ) {
387 actions[type]->setText( i18n ( standardActionData[type].label ) );
388 actions[type]->setIcon( KIcon( QString::fromLatin1( standardActionData[type].icon ) ) );
390 if ( pluralLabels.contains( type ) && !pluralLabels.value( type ).isEmpty() )
391 actions[type]->setText( pluralLabels.value( type ).subs( 1 ).toString() );
392 else if ( standardActionData[type].label )
393 actions[type]->setText( i18n( standardActionData[type].label ) );
395 if ( pluralIconLabels.contains( type ) && !pluralIconLabels.value( type ).isEmpty() )
396 actions[type]->setIconText( pluralIconLabels.value( type ).subs( 1 ).toString() );
397 else if ( standardActionData[type].iconLabel )
398 actions[type]->setIconText( i18n( standardActionData[type].iconLabel ) );
400 if ( standardActionData[type].icon )
401 actions[type]->setIcon( KIcon( QString::fromLatin1( standardActionData[type].icon ) ) );
416 void updatePluralLabel(
int type,
int count )
418 updatePluralLabel( static_cast<StandardActionManager::Type>( type ), count );
421 void updatePluralLabel( StandardActionManager::Type type,
int count )
423 Q_ASSERT( type < StandardActionManager::LastType );
424 if ( actions[type] && pluralLabels.contains( type ) && !pluralLabels.value( type ).isEmpty() ) {
425 actions[type]->setText( pluralLabels.value( type ).subs( qMax( count, 1 ) ).toString() );
429 bool isFavoriteCollection(
const Akonadi::Collection &collection )
431 if ( !favoritesModel )
434 return favoritesModel->collections().contains( collection );
437 void encodeToClipboard( QItemSelectionModel* selectionModel,
bool cut =
false )
439 Q_ASSERT( selectionModel );
440 if ( safeSelectedRows( selectionModel ).count() <= 0 )
443 #ifndef QT_NO_CLIPBOARD
444 QMimeData *mimeData = selectionModel->model()->mimeData( safeSelectedRows( selectionModel ) );
445 markCutAction( mimeData, cut );
446 QApplication::clipboard()->setMimeData( mimeData );
448 QAbstractItemModel *model =
const_cast<QAbstractItemModel *
>( selectionModel->model() );
450 foreach (
const QModelIndex &index, safeSelectedRows( selectionModel ) )
451 model->setData( index,
true, EntityTreeModel::PendingCutRole );
458 Collection::List selectedCollectionsList;
459 if ( collectionSelectionModel ) {
460 const QModelIndexList rows = safeSelectedRows( collectionSelectionModel );
461 foreach (
const QModelIndex &index, rows ) {
462 Collection collection = index.data( EntityTreeModel::CollectionRole ).value<Collection>();
463 if ( !collection.isValid() )
466 const Collection parentCollection = index.data( EntityTreeModel::ParentCollectionRole ).value<Collection>();
467 collection.setParentCollection( parentCollection );
469 selectedCollectionsList << collection;
474 Item::List selectedItems;
475 if ( itemSelectionModel ) {
476 const QModelIndexList rows = safeSelectedRows( itemSelectionModel );
477 foreach (
const QModelIndex &index, rows ) {
478 Item item = index.data( EntityTreeModel::ItemRole ).value<Item>();
479 if ( !item.isValid() )
482 const Collection parentCollection = index.data( EntityTreeModel::ParentCollectionRole ).value<Collection>();
483 item.setParentCollection( parentCollection );
485 selectedItems << item;
489 mActionStateManager.updateState( selectedCollectionsList, selectedItems );
491 enableAction( StandardActionManager::SynchronizeFavoriteCollections, (favoritesModel->rowCount() > 0));
492 emit q->actionStateUpdated();
495 #ifndef QT_NO_CLIPBOARD
496 void clipboardChanged( QClipboard::Mode mode )
498 if ( mode == QClipboard::Clipboard )
503 QItemSelection mapToEntityTreeModel(
const QAbstractItemModel *model,
const QItemSelection &selection )
const
505 const QAbstractProxyModel *proxy = qobject_cast<
const QAbstractProxyModel*>( model );
507 return mapToEntityTreeModel( proxy->sourceModel(), proxy->mapSelectionToSource( selection ) );
513 QItemSelection mapFromEntityTreeModel(
const QAbstractItemModel *model,
const QItemSelection &selection )
const
515 const QAbstractProxyModel *proxy = qobject_cast<
const QAbstractProxyModel*>( model );
517 const QItemSelection select = mapFromEntityTreeModel( proxy->sourceModel(), selection );
518 return proxy->mapSelectionFromSource( select );
524 void collectionSelectionChanged()
526 q->blockSignals(
true );
528 QItemSelection selection = collectionSelectionModel->selection();
529 selection = mapToEntityTreeModel( collectionSelectionModel->model(), selection );
530 selection = mapFromEntityTreeModel( favoritesModel, selection );
532 if ( favoriteSelectionModel )
533 favoriteSelectionModel->select( selection, QItemSelectionModel::ClearAndSelect );
535 q->blockSignals(
false );
540 void favoriteSelectionChanged()
542 q->blockSignals(
true );
544 QItemSelection selection = favoriteSelectionModel->selection();
545 if ( selection.indexes().isEmpty() )
548 selection = mapToEntityTreeModel( favoritesModel, selection );
549 selection = mapFromEntityTreeModel( collectionSelectionModel->model(), selection );
551 collectionSelectionModel->select( selection, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows );
552 q->blockSignals(
false );
557 void slotCreateCollection()
559 Q_ASSERT( collectionSelectionModel );
560 if ( collectionSelectionModel->selection().indexes().isEmpty() )
563 const QModelIndex index = collectionSelectionModel->selection().indexes().at( 0 );
564 Q_ASSERT( index.isValid() );
565 const Collection parentCollection = index.data( CollectionModel::CollectionRole ).value<Collection>();
566 Q_ASSERT( parentCollection.isValid() );
568 if ( !canCreateCollection( parentCollection ) )
571 QString name = KInputDialog::getText( contextText( StandardActionManager::CreateCollection, StandardActionManager::DialogTitle ),
572 contextText( StandardActionManager::CreateCollection, StandardActionManager::DialogText ),
573 QString(), 0, parentWidget );
574 name = name.trimmed();
575 if ( name.isEmpty() )
578 if ( name.contains( QLatin1Char(
'/' ) ) ) {
579 KMessageBox::error( parentWidget,
580 i18n(
"We can not add \"/\" in folder name." ),
581 i18n(
"Create new folder error" ) );
584 if ( name.startsWith( QLatin1Char(
'.') ) ||
585 name.endsWith( QLatin1Char(
'.') ) ) {
586 kDebug()<<
" We can not add \".\" at begin or end of folder name ";
590 Collection collection;
591 collection.setName( name );
592 collection.setParentCollection( parentCollection );
593 if ( actions[StandardActionManager::CreateCollection] ) {
594 const QStringList mts = actions[StandardActionManager::CreateCollection]->property(
"ContentMimeTypes" ).toStringList();
595 if ( !mts.isEmpty() )
596 collection.setContentMimeTypes( mts );
598 CollectionCreateJob *job =
new CollectionCreateJob( collection );
599 q->connect( job, SIGNAL(result(KJob*)), q, SLOT(collectionCreationResult(KJob*)) );
602 void slotCopyCollections()
604 encodeToClipboard( collectionSelectionModel );
607 void slotCutCollections()
609 encodeToClipboard( collectionSelectionModel,
true );
612 Collection::List selectedCollections()
614 Collection::List collections;
616 Q_ASSERT( collectionSelectionModel );
618 foreach (
const QModelIndex &index, safeSelectedRows( collectionSelectionModel ) ) {
619 Q_ASSERT( index.isValid() );
620 const Collection collection = index.data( CollectionModel::CollectionRole ).value<Collection>();
621 Q_ASSERT( collection.isValid() );
623 collections << collection;
629 void slotDeleteCollection()
631 const Collection::List collections = selectedCollections();
632 if ( collections.isEmpty() )
635 const QString collectionName = collections.first().name();
636 const QString text = contextText( StandardActionManager::DeleteCollections, StandardActionManager::MessageBoxText,
637 collections.count(), collectionName );
639 if ( KMessageBox::questionYesNo( parentWidget, text,
640 contextText( StandardActionManager::DeleteCollections, StandardActionManager::MessageBoxTitle, collections.count(), collectionName ),
641 KStandardGuiItem::del(), KStandardGuiItem::cancel(),
642 QString(), KMessageBox::Dangerous ) != KMessageBox::Yes )
645 foreach (
const Collection &collection, collections ) {
646 CollectionDeleteJob *job =
new CollectionDeleteJob( collection, q );
647 q->connect( job, SIGNAL(result(KJob*)), q, SLOT(collectionDeletionResult(KJob*)) );
651 void slotMoveCollectionToTrash()
653 const Collection::List collections = selectedCollections();
654 if ( collections.isEmpty() )
657 foreach (
const Collection &collection, collections ) {
658 TrashJob *job =
new TrashJob( collection, q );
659 q->connect( job, SIGNAL(result(KJob*)), q, SLOT(moveCollectionToTrashResult(KJob*)) );
663 void slotRestoreCollectionFromTrash()
665 const Collection::List collections = selectedCollections();
666 if ( collections.isEmpty() )
669 foreach (
const Collection &collection, collections ) {
670 TrashRestoreJob *job =
new TrashRestoreJob( collection, q );
671 q->connect( job, SIGNAL(result(KJob*)), q, SLOT(moveCollectionToTrashResult(KJob*)) );
675 Item::List selectedItems()
const
679 Q_ASSERT( itemSelectionModel );
681 foreach (
const QModelIndex &index, safeSelectedRows( itemSelectionModel ) ) {
682 Q_ASSERT( index.isValid() );
683 const Item item = index.data( ItemModel::ItemRole ).value<Item>();
684 Q_ASSERT( item.isValid() );
692 void slotMoveItemToTrash()
694 const Item::List items = selectedItems();
695 if ( items.isEmpty() )
698 TrashJob *job =
new TrashJob( items, q );
699 q->connect( job, SIGNAL(result(KJob*)), q, SLOT(moveItemToTrashResult(KJob*)) );
702 void slotRestoreItemFromTrash()
704 const Item::List items = selectedItems();
705 if ( items.isEmpty() )
708 TrashRestoreJob *job =
new TrashRestoreJob( items, q );
709 q->connect( job, SIGNAL(result(KJob*)), q, SLOT(moveItemToTrashResult(KJob*)) );
712 void slotTrashRestoreCollection()
714 const Collection::List collections = selectedCollections();
715 if ( collections.isEmpty() )
718 bool collectionsAreInTrash =
false;
719 foreach (
const Collection &collection, collections ) {
720 if ( collection.hasAttribute<EntityDeletedAttribute>() ) {
721 collectionsAreInTrash =
true;
726 if (collectionsAreInTrash) {
727 slotRestoreCollectionFromTrash();
729 slotMoveCollectionToTrash();
733 void slotTrashRestoreItem()
735 const Item::List items = selectedItems();
736 if ( items.isEmpty() )
739 bool itemsAreInTrash =
false;
740 foreach (
const Item &item, items ) {
741 if ( item.hasAttribute<EntityDeletedAttribute>() ) {
742 itemsAreInTrash =
true;
747 if (itemsAreInTrash) {
748 slotRestoreItemFromTrash();
750 slotMoveItemToTrash();
754 void slotSynchronizeCollection()
756 Q_ASSERT( collectionSelectionModel );
757 const QModelIndexList list = safeSelectedRows( collectionSelectionModel );
758 if ( list.isEmpty() )
761 const Collection::List collections = selectedCollections();
762 if ( collections.isEmpty() )
765 foreach(
const Collection &collection, collections ) {
766 if ( !testAndSetOnlineResources(collection) )
772 bool testAndSetOnlineResources(
const Akonadi::Collection& collection)
776 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 )
783 void slotSynchronizeCollectionRecursive()
785 Q_ASSERT( collectionSelectionModel );
786 const QModelIndexList list = safeSelectedRows( collectionSelectionModel );
787 if ( list.isEmpty() )
790 const Collection::List collections = selectedCollections();
791 if ( collections.isEmpty() )
794 foreach(
const Collection &collection, collections ) {
795 if ( !testAndSetOnlineResources(collection) )
801 void slotCollectionProperties()
803 const QModelIndexList list = safeSelectedRows( collectionSelectionModel );
804 if ( list.isEmpty() )
807 const QModelIndex index = list.first();
808 Q_ASSERT( index.isValid() );
810 const Collection collection = index.data( CollectionModel::CollectionRole ).value<Collection>();
811 Q_ASSERT( collection.isValid() );
813 const QString displayName = collection.hasAttribute<EntityDisplayAttribute>() ? collection.attribute<EntityDisplayAttribute>()->displayName()
816 CollectionPropertiesDialog* dlg =
new CollectionPropertiesDialog( collection, mCollectionPropertiesPageNames, parentWidget );
817 dlg->setCaption( contextText( StandardActionManager::CollectionProperties, StandardActionManager::DialogTitle ).arg( displayName ) );
823 encodeToClipboard( itemSelectionModel );
828 encodeToClipboard( itemSelectionModel,
true );
833 Q_ASSERT( collectionSelectionModel );
835 const QModelIndexList list = safeSelectedRows( collectionSelectionModel );
836 if ( list.isEmpty() )
839 const QModelIndex index = list.first();
840 Q_ASSERT( index.isValid() );
842 #ifndef QT_NO_CLIPBOARD
844 QAbstractItemModel *model =
const_cast<QAbstractItemModel *
>( collectionSelectionModel->model() );
845 const QMimeData *mimeData = QApplication::clipboard()->mimeData();
846 model->dropMimeData( mimeData, isCutAction( mimeData ) ? Qt::MoveAction : Qt::CopyAction, -1, -1, index );
847 model->setData( QModelIndex(),
false, EntityTreeModel::PendingCutRole );
848 QApplication::clipboard()->clear();
852 void slotDeleteItems()
854 Q_ASSERT( itemSelectionModel );
857 foreach (
const QModelIndex &index, safeSelectedRows( itemSelectionModel ) ) {
859 const qlonglong
id = index.data( ItemModel::IdRole ).toLongLong( &ok );
864 if ( items.isEmpty() )
867 QMetaObject::invokeMethod(q,
"slotDeleteItemsDeferred",
868 Qt::QueuedConnection,
869 Q_ARG(Akonadi::Item::List, items));
872 void slotDeleteItemsDeferred(
const Akonadi::Item::List &items)
874 Q_ASSERT( itemSelectionModel );
876 if ( KMessageBox::questionYesNo( parentWidget,
877 contextText( StandardActionManager::DeleteItems, StandardActionManager::MessageBoxText, items.count(), QString() ),
878 contextText( StandardActionManager::DeleteItems, StandardActionManager::MessageBoxTitle, items.count(), QString() ),
879 KStandardGuiItem::del(), KStandardGuiItem::cancel(),
880 QString(), KMessageBox::Dangerous ) != KMessageBox::Yes )
883 ItemDeleteJob *job =
new ItemDeleteJob( items, q );
884 q->connect( job, SIGNAL(result(KJob*)), q, SLOT(itemDeletionResult(KJob*)) );
887 void slotLocalSubscription()
889 SubscriptionDialog* dlg =
new SubscriptionDialog( mMimeTypeFilter, parentWidget );
890 dlg->showHiddenCollection(
true);
894 void slotAddToFavorites()
896 Q_ASSERT( collectionSelectionModel );
897 Q_ASSERT( favoritesModel );
898 const QModelIndexList list = safeSelectedRows( collectionSelectionModel );
899 if ( list.isEmpty() )
902 foreach (
const QModelIndex &index, list ) {
903 Q_ASSERT( index.isValid() );
904 const Collection collection = index.data( CollectionModel::CollectionRole ).value<Collection>();
905 Q_ASSERT( collection.isValid() );
907 favoritesModel->addCollection( collection );
913 void slotRemoveFromFavorites()
915 Q_ASSERT( collectionSelectionModel );
916 Q_ASSERT( favoritesModel );
917 const QModelIndexList list = safeSelectedRows( collectionSelectionModel );
918 if ( list.isEmpty() )
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() );
926 favoritesModel->removeCollection( collection );
932 void slotRenameFavorite()
934 Q_ASSERT( collectionSelectionModel );
935 Q_ASSERT( favoritesModel );
936 const QModelIndexList list = safeSelectedRows( collectionSelectionModel );
937 if ( list.isEmpty() )
939 const QModelIndex index = list.first();
940 Q_ASSERT( index.isValid() );
941 const Collection collection = index.data( CollectionModel::CollectionRole ).value<Collection>();
942 Q_ASSERT( collection.isValid() );
944 const QString displayName = collection.hasAttribute<EntityDisplayAttribute>() ? collection.attribute<EntityDisplayAttribute>()->displayName() : collection.name();
946 RenameFavoriteDialog dlg(contextText( StandardActionManager::RenameFavoriteCollection, StandardActionManager::DialogTitle ),contextText( StandardActionManager::RenameFavoriteCollection, StandardActionManager::DialogText ) , favoritesModel->favoriteLabel( collection ), displayName, parentWidget );
949 favoritesModel->setFavoriteLabel( collection, dlg.newName() );
953 void slotSynchronizeFavoriteCollections()
955 Q_ASSERT( favoritesModel );
956 foreach(
const Collection& collection, favoritesModel->collections() ) {
959 if ( !collection.resource().isEmpty() ) {
965 void slotCopyCollectionTo()
967 pasteTo( collectionSelectionModel, collectionSelectionModel->model(), CopyCollectionToMenu, Qt::CopyAction );
970 void slotCopyItemTo()
972 pasteTo( itemSelectionModel, collectionSelectionModel->model(), CopyItemToMenu, Qt::CopyAction );
975 void slotMoveCollectionTo()
977 pasteTo( collectionSelectionModel, collectionSelectionModel->model(), MoveCollectionToMenu, Qt::MoveAction );
980 void slotMoveItemTo()
982 pasteTo( itemSelectionModel, collectionSelectionModel->model(), MoveItemToMenu, Qt::MoveAction );
985 void slotCopyCollectionTo( QAction *action )
987 pasteTo( collectionSelectionModel, action, Qt::CopyAction );
990 void slotCopyItemTo( QAction *action )
992 pasteTo( itemSelectionModel, action, Qt::CopyAction );
995 void slotMoveCollectionTo( QAction *action )
997 pasteTo( collectionSelectionModel, action, Qt::MoveAction );
1000 void slotMoveItemTo( QAction *action )
1002 pasteTo( itemSelectionModel, action, Qt::MoveAction );
1009 Q_ASSERT( collectionSelectionModel );
1010 if ( collectionSelectionModel->selection().indexes().isEmpty() )
1013 foreach (
const QModelIndex &index, collectionSelectionModel->selection().indexes() ) {
1014 Q_ASSERT( index.isValid() );
1015 const Collection collection = index.data( CollectionModel::CollectionRole ).value<Collection>();
1016 Q_ASSERT( collection.isValid() );
1018 if ( collection.isValid() ) {
1019 const QString identifier = collection.resource();
1031 if ( instances.isEmpty() )
1034 return instances.first();
1037 void slotCreateResource()
1040 dlg.setCaption( contextText( StandardActionManager::CreateResource, StandardActionManager::DialogTitle ) );
1042 foreach (
const QString &mimeType, mMimeTypeFilter )
1043 dlg.agentFilterProxyModel()->addMimeTypeFilter( mimeType );
1045 foreach (
const QString &capability, mCapabilityFilter )
1046 dlg.agentFilterProxyModel()->addCapabilityFilter( capability );
1049 const AgentType agentType = dlg.agentType();
1053 q->connect( job, SIGNAL(result(KJob*)), SLOT(resourceCreationResult(KJob*)) );
1060 void slotDeleteResource()
1063 if ( instances.isEmpty() )
1066 if ( KMessageBox::questionYesNo( parentWidget,
1067 contextText( StandardActionManager::DeleteResources, StandardActionManager::MessageBoxText, instances.count(), instances.first().name() ),
1068 contextText( StandardActionManager::DeleteResources, StandardActionManager::MessageBoxTitle, instances.count(), instances.first().name() ),
1069 KStandardGuiItem::del(), KStandardGuiItem::cancel(),
1070 QString(), KMessageBox::Dangerous ) != KMessageBox::Yes )
1077 void slotSynchronizeResource()
1080 if ( instances.isEmpty() )
1088 void slotResourceProperties()
1097 void slotToggleWorkOffline(
bool offline )
1099 setWorkOffline( offline );
1107 void pasteTo( QItemSelectionModel *selectionModel,
const QAbstractItemModel *model, StandardActionManager::Type type, Qt::DropAction dropAction )
1109 const QSet<QString> mimeTypes = mimeTypesOfSelection( type );
1111 CollectionDialog dlg( const_cast<QAbstractItemModel*>( model ) );
1112 dlg.setMimeTypeFilter( mimeTypes.toList() );
1114 if ( type == CopyItemToMenu || type == MoveItemToMenu )
1115 dlg.setAccessRightsFilter( Collection::CanCreateItem );
1116 else if ( type == CopyCollectionToMenu || type == MoveCollectionToMenu )
1117 dlg.setAccessRightsFilter( Collection::CanCreateCollection );
1120 const QModelIndex index = EntityTreeModel::modelIndexForCollection( collectionSelectionModel->model(), dlg.selectedCollection() );
1121 if ( !index.isValid() )
1124 const QMimeData *mimeData = selectionModel->model()->mimeData( safeSelectedRows( selectionModel ) );
1126 QAbstractItemModel *model =
const_cast<QAbstractItemModel *
>( index.model() );
1127 model->dropMimeData( mimeData, dropAction, -1, -1, index );
1131 void pasteTo( QItemSelectionModel *selectionModel, QAction *action, Qt::DropAction dropAction )
1133 Q_ASSERT( selectionModel );
1136 if ( safeSelectedRows( selectionModel ).count() <= 0 )
1139 const QMimeData *mimeData = selectionModel->model()->mimeData( selectionModel->selectedRows() );
1141 const QModelIndex index = action->data().value<QModelIndex>();
1142 Q_ASSERT( index.isValid() );
1144 QAbstractItemModel *model =
const_cast<QAbstractItemModel *
>( index.model() );
1145 const Collection collection = index.data( EntityTreeModel::CollectionRole ).value<Collection>();
1146 addRecentCollection( collection.id() );
1147 model->dropMimeData( mimeData, dropAction, -1, -1, index );
1150 void addRecentCollection( Akonadi::Collection::Id
id )
1152 QMapIterator<StandardActionManager::Type, QWeakPointer<RecentCollectionAction> > item(mRecentCollectionsMenu);
1153 while (item.hasNext()) {
1155 if ( item.value().data() ) {
1156 item.value().data()->addRecentCollection(
id );
1161 void collectionCreationResult( KJob *job )
1163 if ( job->error() ) {
1164 KMessageBox::error( parentWidget,
1165 contextText( StandardActionManager::CreateCollection, StandardActionManager::ErrorMessageText ).arg( job->errorString() ),
1166 contextText( StandardActionManager::CreateCollection, StandardActionManager::ErrorMessageTitle ) );
1170 void collectionDeletionResult( KJob *job )
1172 if ( job->error() ) {
1173 KMessageBox::error( parentWidget,
1174 contextText( StandardActionManager::DeleteCollections, StandardActionManager::ErrorMessageText ).arg( job->errorString() ),
1175 contextText( StandardActionManager::DeleteCollections, StandardActionManager::ErrorMessageTitle ) );
1179 void moveCollectionToTrashResult( KJob *job )
1181 if ( job->error() ) {
1182 KMessageBox::error( parentWidget,
1183 contextText( StandardActionManager::MoveCollectionsToTrash, StandardActionManager::ErrorMessageText ).arg( job->errorString() ),
1184 contextText( StandardActionManager::MoveCollectionsToTrash, StandardActionManager::ErrorMessageTitle ) );
1188 void moveItemToTrashResult( KJob *job )
1190 if ( job->error() ) {
1191 KMessageBox::error( parentWidget,
1192 contextText( StandardActionManager::MoveItemsToTrash, StandardActionManager::ErrorMessageText ).arg( job->errorString() ),
1193 contextText( StandardActionManager::MoveItemsToTrash, StandardActionManager::ErrorMessageTitle ) );
1197 void itemDeletionResult( KJob *job )
1199 if ( job->error() ) {
1200 KMessageBox::error( parentWidget,
1201 contextText( StandardActionManager::DeleteItems, StandardActionManager::ErrorMessageText ).arg( job->errorString() ),
1202 contextText( StandardActionManager::DeleteItems, StandardActionManager::ErrorMessageTitle ) );
1206 void resourceCreationResult( KJob *job )
1208 if ( job->error() ) {
1209 KMessageBox::error( parentWidget,
1210 contextText( StandardActionManager::CreateResource, StandardActionManager::ErrorMessageText ).arg( job->errorString() ),
1211 contextText( StandardActionManager::CreateResource, StandardActionManager::ErrorMessageTitle ) );
1215 void pasteResult( KJob *job )
1217 if ( job->error() ) {
1218 KMessageBox::error( parentWidget,
1219 contextText( StandardActionManager::Paste, StandardActionManager::ErrorMessageText ).arg( job->errorString() ),
1220 contextText( StandardActionManager::Paste, StandardActionManager::ErrorMessageTitle ) );
1227 QSet<QString> mimeTypesOfSelection( StandardActionManager::Type type )
const
1229 QModelIndexList list;
1230 QSet<QString> mimeTypes;
1232 const bool isItemAction = ( type == CopyItemToMenu || type == MoveItemToMenu );
1233 const bool isCollectionAction = ( type == CopyCollectionToMenu || type == MoveCollectionToMenu );
1235 if ( isItemAction ) {
1236 list = safeSelectedRows( itemSelectionModel );
1237 foreach (
const QModelIndex &index, list )
1238 mimeTypes << index.data( EntityTreeModel::MimeTypeRole ).toString();
1241 if ( isCollectionAction ) {
1242 list = safeSelectedRows( collectionSelectionModel );
1243 foreach (
const QModelIndex &index, list ) {
1244 const Collection collection = index.data( EntityTreeModel::CollectionRole ).value<Collection>();
1257 bool isWritableTargetCollectionForMimeTypes(
const Collection &collection,
const QSet<QString> &mimeTypes, StandardActionManager::Type type )
const
1259 if ( CollectionUtils::isVirtual( collection ) )
1262 const bool isItemAction = ( type == CopyItemToMenu || type == MoveItemToMenu );
1263 const bool isCollectionAction = ( type == CopyCollectionToMenu || type == MoveCollectionToMenu );
1265 const bool canContainRequiredMimeTypes = !collection.contentMimeTypes().toSet().intersect( mimeTypes ).isEmpty();
1266 const bool canCreateNewItems = (collection.rights() & Collection::CanCreateItem);
1268 const bool canCreateNewCollections = (collection.rights() & Collection::CanCreateCollection);
1269 const bool canContainCollections = collection.contentMimeTypes().contains( Collection::mimeType() );
1270 const bool resourceAllowsRequiredMimeTypes =
AgentManager::self()->
instance( collection.resource() ).type().mimeTypes().toSet().contains( mimeTypes );
1272 const bool isReadOnlyForItems = (isItemAction && (!canCreateNewItems || !canContainRequiredMimeTypes));
1273 const bool isReadOnlyForCollections = (isCollectionAction && (!canCreateNewCollections || !canContainCollections || !resourceAllowsRequiredMimeTypes));
1275 return !(CollectionUtils::isStructural( collection ) || isReadOnlyForItems || isReadOnlyForCollections);
1278 void fillFoldersMenu(
const Akonadi::Collection::List& selectedCollectionsList,
const QSet<QString>& mimeTypes, StandardActionManager::Type type, QMenu *menu,
1279 const QAbstractItemModel *model, QModelIndex parentIndex )
1281 const int rowCount = model->rowCount( parentIndex );
1283 for (
int row = 0; row < rowCount; ++row ) {
1284 const QModelIndex index = model->index( row, 0, parentIndex );
1285 const Collection collection = model->data( index, CollectionModel::CollectionRole ).value<Collection>();
1287 if ( CollectionUtils::isVirtual( collection ) )
1290 const bool readOnly = !isWritableTargetCollectionForMimeTypes( collection, mimeTypes, type );
1291 const bool collectionIsSelected = selectedCollectionsList.contains( collection );
1293 QString label = model->data( index ).toString();
1294 label.replace( QLatin1String(
"&" ), QLatin1String(
"&&" ) );
1296 const QIcon icon = model->data( index, Qt::DecorationRole ).value<QIcon>();
1298 if ( model->rowCount( index ) > 0 ) {
1300 QMenu* popup =
new QMenu( menu );
1301 const bool moveAction = (type == MoveCollectionToMenu || type == MoveItemToMenu);
1302 popup->setObjectName( QString::fromUtf8(
"subMenu" ) );
1303 popup->setTitle( label );
1304 popup->setIcon( icon );
1306 fillFoldersMenu( selectedCollectionsList, mimeTypes, type, popup, model, index );
1309 popup->addSeparator();
1311 QAction *action = popup->addAction( moveAction ? i18n(
"Move to This Folder" ) : i18n(
"Copy to This Folder" ) );
1312 action->setData( QVariant::fromValue<QModelIndex>( index ) );
1315 menu->addMenu( popup );
1319 QAction* action = menu->addAction( icon, label );
1320 action->setData( QVariant::fromValue<QModelIndex>( index ) );
1321 action->setEnabled( !readOnly && !collectionIsSelected );
1326 void checkModelsConsistency()
1328 if ( favoritesModel == 0 || favoriteSelectionModel == 0 ) {
1334 const QAbstractItemModel *favModel = favoritesModel;
1335 while (
const QAbstractProxyModel *proxy = qobject_cast<const QAbstractProxyModel*>( favModel ) ) {
1336 favModel = proxy->sourceModel();
1341 if ( collectionSelectionModel != 0 ) {
1342 const QAbstractItemModel *model = collectionSelectionModel->model();
1343 while (
const QAbstractProxyModel *proxy = qobject_cast<const QAbstractProxyModel*>( model ) ) {
1344 model = proxy->sourceModel();
1347 Q_ASSERT( model == favModel );
1351 const QAbstractItemModel *model = favoriteSelectionModel->model();
1352 while (
const QAbstractProxyModel *proxy = qobject_cast<const QAbstractProxyModel*>( model ) ) {
1353 model = proxy->sourceModel();
1355 Q_ASSERT( model == favModel );
1358 void markCutAction( QMimeData *mimeData,
bool cut )
const
1363 const QByteArray cutSelectionData =
"1";
1364 mimeData->setData( QLatin1String(
"application/x-kde.akonadi-cutselection" ), cutSelectionData);
1367 bool isCutAction(
const QMimeData *mimeData )
const
1369 const QByteArray data = mimeData->data( QLatin1String(
"application/x-kde.akonadi-cutselection" ) );
1370 if ( data.isEmpty() )
1373 return (data.at( 0 ) ==
'1');
1376 void setContextText( StandardActionManager::Type type, StandardActionManager::TextContext context,
const QString &data )
1378 ContextTextEntry entry;
1381 contextTexts[ type ].insert( context, entry );
1384 void setContextText( StandardActionManager::Type type, StandardActionManager::TextContext context,
const KLocalizedString &data )
1386 ContextTextEntry entry;
1387 entry.localizedText = data;
1389 contextTexts[ type ].insert( context, entry );
1392 QString contextText( StandardActionManager::Type type, StandardActionManager::TextContext context )
const
1394 return contextTexts[ type ].value( context ).text;
1397 QString contextText( StandardActionManager::Type type, StandardActionManager::TextContext context,
int count,
const QString &value )
const
1399 if ( contextTexts[ type ].value( context ).localizedText.isEmpty() )
1400 return contextTexts[ type ].value( context ).text;
1402 KLocalizedString text = contextTexts[ type ].value( context ).localizedText;
1403 const QString str = text.subs( count ).toString();
1404 const int argCount = str.count( QRegExp( QLatin1String(
"%[0-9]" ) ) );
1405 if ( argCount > 0 ) {
1406 return text.subs( count ).subs( value ).toString();
1408 return text.subs( count ).toString();
1412 StandardActionManager *q;
1413 KActionCollection *actionCollection;
1414 QWidget *parentWidget;
1415 QItemSelectionModel *collectionSelectionModel;
1416 QItemSelectionModel *itemSelectionModel;
1417 FavoriteCollectionsModel *favoritesModel;
1418 QItemSelectionModel *favoriteSelectionModel;
1419 QVector<KAction*> actions;
1420 QHash<StandardActionManager::Type, KLocalizedString> pluralLabels;
1421 QHash<StandardActionManager::Type, KLocalizedString> pluralIconLabels;
1423 struct ContextTextEntry
1426 KLocalizedString localizedText;
1430 typedef QHash<StandardActionManager::TextContext, ContextTextEntry> ContextTexts;
1431 QHash<StandardActionManager::Type, ContextTexts> contextTexts;
1435 QStringList mMimeTypeFilter;
1436 QStringList mCapabilityFilter;
1437 QStringList mCollectionPropertiesPageNames;
1438 QMap<StandardActionManager::Type, QWeakPointer<RecentCollectionAction> > mRecentCollectionsMenu;
1443 StandardActionManager::StandardActionManager( KActionCollection * actionCollection,
1446 d( new Private( this ) )
1448 d->parentWidget = parent;
1449 d->actionCollection = actionCollection;
1450 d->mActionStateManager.setReceiver(
this );
1451 #ifndef QT_NO_CLIPBOARD
1452 connect( QApplication::clipboard(), SIGNAL(changed(QClipboard::Mode)), SLOT(clipboardChanged(QClipboard::Mode)) );
1456 StandardActionManager::~ StandardActionManager()
1461 void StandardActionManager::setCollectionSelectionModel( QItemSelectionModel * selectionModel )
1463 d->collectionSelectionModel = selectionModel;
1464 connect( selectionModel, SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
1465 SLOT(collectionSelectionChanged()) );
1467 d->checkModelsConsistency();
1470 void StandardActionManager::setItemSelectionModel( QItemSelectionModel * selectionModel )
1472 d->itemSelectionModel = selectionModel;
1473 connect( selectionModel, SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
1474 SLOT(updateActions()) );
1479 d->favoritesModel = favoritesModel;
1480 d->checkModelsConsistency();
1483 void StandardActionManager::setFavoriteSelectionModel( QItemSelectionModel *selectionModel )
1485 d->favoriteSelectionModel = selectionModel;
1486 connect( selectionModel, SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
1487 SLOT(favoriteSelectionChanged()) );
1488 d->checkModelsConsistency();
1491 KAction* StandardActionManager::createAction(
Type type )
1493 Q_ASSERT( type < LastType );
1494 if ( d->actions[type] )
1495 return d->actions[type];
1496 KAction *action = 0;
1497 switch ( standardActionData[type].actionType ) {
1499 case ActionWithAlternative:
1500 action =
new KAction( d->parentWidget );
1502 case ActionAlternative:
1503 d->actions[type] = d->actions[type-1];
1504 Q_ASSERT( d->actions[type] );
1505 if ( (LastType > type+1) && (standardActionData[type+1].actionType == ActionAlternative) ) {
1506 createAction(static_cast<Type>(type+1));
1508 return d->actions[type];
1510 action =
new KActionMenu( d->parentWidget );
1513 action =
new KToggleAction( d->parentWidget );
1517 if ( d->pluralLabels.contains( type ) && !d->pluralLabels.value( type ).isEmpty() )
1518 action->setText( d->pluralLabels.value( type ).subs( 1 ).toString() );
1519 else if ( standardActionData[type].label )
1520 action->setText( i18n( standardActionData[type].label ) );
1522 if ( d->pluralIconLabels.contains( type ) && !d->pluralIconLabels.value( type ).isEmpty() )
1523 action->setIconText( d->pluralIconLabels.value( type ).subs( 1 ).toString() );
1524 else if ( standardActionData[type].iconLabel )
1525 action->setIconText( i18n( standardActionData[type].iconLabel ) );
1527 if ( standardActionData[type].icon )
1528 action->setIcon( KIcon( QString::fromLatin1( standardActionData[type].icon ) ) );
1530 action->setShortcut( standardActionData[type].shortcut );
1532 if ( standardActionData[type].slot ) {
1533 switch ( standardActionData[type].actionType ) {
1535 case ActionWithAlternative:
1536 connect( action, SIGNAL(triggered()), standardActionData[type].slot );
1540 KActionMenu *actionMenu = qobject_cast<KActionMenu*>( action );
1541 connect( actionMenu->menu(), SIGNAL(triggered(QAction*)), standardActionData[type].slot );
1546 connect( action, SIGNAL(triggered(
bool)), standardActionData[type].slot );
1549 case ActionAlternative:
1554 if ( type == ToggleWorkOffline ) {
1556 disconnect( action, SIGNAL(triggered(
bool)),
this, standardActionData[type].slot );
1557 action->setChecked( workOffline() );
1558 connect( action, SIGNAL(triggered(
bool)),
this, standardActionData[type].slot );
1563 Q_ASSERT( standardActionData[type].name );
1564 d->actionCollection->addAction( QString::fromLatin1(standardActionData[type].name), action );
1565 d->actions[type] = action;
1566 if ( ( standardActionData[type].actionType == ActionWithAlternative ) && (standardActionData[type+1].actionType == ActionAlternative)) {
1567 createAction(static_cast<Type>(type+1));
1573 void StandardActionManager::createAllActions()
1575 for ( uint i = 0; i < LastType; ++i )
1576 createAction( (
Type)i );
1579 KAction * StandardActionManager::action(
Type type )
const
1581 Q_ASSERT( type < LastType );
1582 return d->actions[type];
1585 void StandardActionManager::setActionText(
Type type,
const KLocalizedString & text )
1587 Q_ASSERT( type < LastType );
1588 d->pluralLabels.insert( type, text );
1592 void StandardActionManager::interceptAction(
Type type,
bool intercept )
1594 Q_ASSERT( type < LastType );
1596 const KAction *action = d->actions[type];
1602 disconnect( action, SIGNAL(triggered()),
this, standardActionData[type].slot );
1604 connect( action, SIGNAL(triggered()), standardActionData[type].slot );
1607 Akonadi::Collection::List StandardActionManager::selectedCollections()
const
1611 if ( !d->collectionSelectionModel )
1614 foreach (
const QModelIndex &index, safeSelectedRows( d->collectionSelectionModel ) ) {
1615 const Collection collection = index.data( EntityTreeModel::CollectionRole ).value<
Collection>();
1617 collections << collection;
1627 if ( !d->itemSelectionModel )
1630 foreach (
const QModelIndex &index, safeSelectedRows( d->itemSelectionModel ) ) {
1631 const Item item = index.data( EntityTreeModel::ItemRole ).value<
Item>();
1639 void StandardActionManager::setContextText(
Type type,
TextContext context,
const QString &text )
1641 d->setContextText( type, context, text );
1644 void StandardActionManager::setContextText(
Type type,
TextContext context,
const KLocalizedString &text )
1646 d->setContextText( type, context, text );
1649 void StandardActionManager::setMimeTypeFilter(
const QStringList &mimeTypes )
1651 d->mMimeTypeFilter = mimeTypes;
1654 void StandardActionManager::setCapabilityFilter(
const QStringList &capabilities )
1656 d->mCapabilityFilter = capabilities;
1659 void StandardActionManager::setCollectionPropertiesPageNames(
const QStringList &names )
1661 d->mCollectionPropertiesPageNames = names;
1664 void StandardActionManager::createActionFolderMenu(QMenu *menu,
Type type)
1666 d->createActionFolderMenu( menu, type );
1671 #include "standardactionmanager.moc"