24 #include "standardmailactionmanager.h"
26 #include "emptytrashcommand_p.h"
27 #include "markascommand_p.h"
28 #include "movetotrashcommand_p.h"
29 #include "specialmailcollections.h"
30 #include "removeduplicatesjob.h"
32 #include "akonadi/agentfilterproxymodel.h"
33 #include "akonadi/agentinstance.h"
34 #include "akonadi/agentinstancecreatejob.h"
35 #include "akonadi/agentmanager.h"
36 #include "akonadi/agenttypedialog.h"
37 #include "akonadi/collectionstatistics.h"
38 #include "akonadi/entitytreemodel.h"
39 #include "akonadi/kmime/messagestatus.h"
41 #include "akonadi/mimetypechecker.h"
42 #include "akonadi/subscriptiondialog_p.h"
45 #include <kactioncollection.h>
47 #include <klocalizedstring.h>
48 #include <kmessagebox.h>
49 #include <kmime/kmime_message.h>
51 #include <QtCore/QPointer>
52 #include <QItemSelectionModel>
54 using namespace Akonadi;
56 class StandardMailActionManager::Private
60 : mActionCollection( actionCollection ),
61 mParentWidget( parentWidget ),
62 mCollectionSelectionModel( 0 ),
63 mItemSelectionModel( 0 ),
72 mGenericManager->setMimeTypeFilter( QStringList() << KMime::Message::mimeType() );
73 mGenericManager->setCapabilityFilter( QStringList() << QLatin1String(
"Resource" ) );
78 delete mGenericManager;
81 void updateGenericAllActions()
126 i18n(
"Add Folder..." ) );
128 i18n(
"Add a new folder to the currently selected account." ) );
130 i18n(
"Add a new folder to the currently selected account." ) );
132 mGenericManager->setContextText(
134 i18nc(
"@title:window",
"New Folder" ) );
136 mGenericManager->setContextText(
138 ki18n(
"Could not create folder: %1" ) );
140 mGenericManager->setContextText(
142 i18n(
"Folder creation failed" ) );
147 ki18np(
"Copy Folder",
"Copy %1 Folders" ) );
149 i18n(
"Copy the selected folders to the clipboard." ) );
151 i18n(
"Copy the selected folders to the clipboard." ) );
152 mGenericManager->setContextText(
154 ki18nc(
"@title:window",
"Properties of Folder %1" ) );
159 ki18np(
"Delete Folder",
"Delete %1 Folders" ) );
161 i18n(
"Delete the selected folders from the account." ) );
163 i18n(
"Delete the selected folders from the account." ) );
164 mGenericManager->setContextText(
166 ki18np(
"Do you really want to delete this folder and all its sub-folders?",
167 "Do you really want to delete %1 folders and all their sub-folders?" ) );
169 mGenericManager->setContextText(
171 ki18ncp(
"@title:window",
"Delete folder?",
"Delete folders?" ) );
173 mGenericManager->setContextText(
175 ki18n(
"Could not delete folder: %1" ) );
177 mGenericManager->setContextText(
179 i18n(
"Folder deletion failed" ) );
184 ki18np(
"Update Folder",
"Update Folders" ) );
187 i18n(
"Update the contents of the selected folders." ) );
189 i18n(
"Update the contents of the selected folders." ) );
193 ki18np(
"Cut Folder",
"Cut %1 Folders" ) );
195 i18n(
"Cut the selected folders from the account." ) );
197 i18n(
"Cut the selected folders from the account." ) );
201 i18n(
"Folder Properties..." ) );
203 i18n(
"Open a dialog to edit the properties of the selected folder." ) );
205 i18n(
"Open a dialog to edit the properties of the selected folder." ) );
209 ki18np(
"Copy Message",
"Copy %1 Messages" ) );
211 i18n(
"Copy the selected messages to the clipboard." ) );
213 i18n(
"Copy the selected messages to the clipboard." ) );
217 ki18np(
"Delete Message",
"Delete %1 Messages" ) );
219 i18n(
"Delete the selected messages from the folder." ) );
221 i18n(
"Delete the selected messages from the folder." ) );
222 mGenericManager->setContextText(
224 ki18np(
"Do you really want to delete the selected message?",
225 "Do you really want to delete %1 messages?" ) );
227 mGenericManager->setContextText(
229 ki18ncp(
"@title:window",
"Delete Message?",
"Delete Messages?" ) );
231 mGenericManager->setContextText(
233 ki18n(
"Could not delete message: %1" ) );
235 mGenericManager->setContextText(
237 i18n(
"Message deletion failed" ) );
241 ki18np(
"Cut Message",
"Cut %1 Messages" ) );
243 i18n(
"Cut the selected message from the folder." ) );
245 i18n(
"Cut the selected message from the folder." ) );
249 i18n(
"Add &Account..." ) );
251 i18n(
"Add a new account<p>"
252 "You will be presented with a dialog where you can select "
253 "the type of the account that shall be added.</p>" ) );
254 mGenericManager->setContextText(
256 i18nc(
"@title:window",
"Add Account" ) );
258 mGenericManager->setContextText(
260 ki18n(
"Could not create account: %1" ) );
262 mGenericManager->setContextText(
264 i18n(
"Account creation failed" ) );
268 ki18np(
"&Delete Account",
"&Delete %1 Accounts" ) );
270 i18n(
"Delete the selected accounts<p>"
271 "The currently selected accounts will be deleted, "
272 "along with all the messages they contain.</p>" ) );
273 mGenericManager->setContextText(
275 ki18np(
"Do you really want to delete this account?",
276 "Do you really want to delete %1 accounts?" ) );
278 mGenericManager->setContextText(
280 ki18ncp(
"@title:window",
"Delete Account?",
"Delete Accounts?" ) );
284 i18n(
"Account Properties..." ) );
286 i18n(
"Open a dialog to edit properties of the selected account." ) );
290 ki18np(
"Update Account",
"Update %1 Accounts" ) );
292 i18n(
"Updates the content of all folders of the selected accounts." ) );
298 ki18np(
"Update This Folder and All Its Subfolders",
299 "Update These Folders and All Their Subfolders" ));
302 i18n(
"Update the contents of the selected folders and all their subfolders." ) );
304 i18n(
"Update the contents of the selected folders and all their subfolders." ) );
307 mGenericManager->setContextText(
309 ki18n(
"Could not paste message: %1" ) );
311 mGenericManager->setContextText(
313 i18n(
"Paste failed" ) );
326 bool itemIsSelected = !selectedItems.isEmpty();
327 bool collectionIsSelected = !selectedCollections.isEmpty();
329 if ( itemIsSelected ) {
330 bool allMarkedAsImportant =
true;
331 bool allMarkedAsRead =
true;
332 bool allMarkedAsUnread =
true;
333 bool allMarkedAsActionItem =
true;
339 allMarkedAsImportant =
false;
342 allMarkedAsRead=
false;
344 allMarkedAsUnread =
false;
347 allMarkedAsActionItem =
false;
353 updateMarkAction( action, allMarkedAsRead );
354 if ( allMarkedAsRead ) {
355 action->setEnabled(
false );
357 action->setEnabled(
true );
363 updateMarkAction( action, allMarkedAsUnread );
364 if ( allMarkedAsUnread ) {
365 action->setEnabled(
false );
367 action->setEnabled(
true );
373 updateMarkAction( action, allMarkedAsImportant );
374 if ( allMarkedAsImportant ) {
375 action->setText( i18n(
"Remove Important Mark" ) );
377 action->setText( i18n(
"&Mark Mail as Important" ) );
379 action->setEnabled(
true );
384 updateMarkAction( action, allMarkedAsActionItem );
385 if ( allMarkedAsActionItem ) {
386 action->setText( i18n(
"Remove Action Item Mark" ) );
388 action->setText( i18n(
"&Mark Mail as Action Item" ) );
390 action->setEnabled(
true );
395 action->setEnabled(
false );
400 action->setEnabled(
false );
405 action->setEnabled(
false );
409 bool enableMarkAllAsRead =
false;
410 bool enableMarkAllAsUnread =
false;
411 bool canDeleteItem =
true;
412 bool isSystemFolder =
false;
413 if ( collectionIsSelected ) {
414 foreach (
const Collection &collection, selectedCollections ) {
417 if ( !enableMarkAllAsRead ) {
420 if ( !enableMarkAllAsUnread ) {
423 if ( canDeleteItem ) {
426 if ( !isSystemFolder ) {
435 if ( enableMarkAllAsRead && enableMarkAllAsUnread && !canDeleteItem && isSystemFolder ) {
441 if ( isSystemFolder ) {
456 action->setEnabled( enableMarkAllAsRead );
461 action->setEnabled( enableMarkAllAsUnread );
464 emit mParent->actionStateUpdated();
467 void updateMarkAction( QAction* action,
bool allMarked )
469 QByteArray data = action->data().toByteArray();
471 if ( !data.startsWith(
'!' ) ) {
475 if ( data.startsWith(
'!' ) ) {
476 data = data.mid( 1 );
479 action->setData( data );
484 const QAction *action = qobject_cast<QAction*>( mParent->sender() );
488 if ( items.isEmpty() ) {
492 QByteArray typeStr = action->data().toByteArray();
493 kDebug() <<
"Mark mail as: " << typeStr;
496 if ( typeStr.startsWith(
'!' ) ) {
498 typeStr = typeStr.mid( 1 );
505 if ( typeStr ==
"U" ) {
509 }
else if ( typeStr ==
"K" ) {
511 }
else if ( typeStr ==
"G" ) {
515 if ( mInterceptedActions.contains( type ) ) {
519 MarkAsCommand *command =
new MarkAsCommand( targetStatus, items, invert, mParent );
525 const QAction *action = qobject_cast<QAction*>( mParent->sender() );
528 QByteArray typeStr = action->data().toByteArray();
529 kDebug() <<
"Mark all as: " << typeStr;
532 if ( collections.isEmpty() ) {
540 if ( typeStr.startsWith(
'!' ) ) {
542 typeStr = typeStr.mid( 1 );
546 if ( typeStr ==
"U" ) {
550 }
else if ( typeStr ==
"K" ) {
552 }
else if ( typeStr ==
"G" ) {
556 if ( mInterceptedActions.contains( type ) ) {
560 MarkAsCommand *command =
new MarkAsCommand( targetStatus, collections, invert, mParent );
564 void slotMoveToTrash()
570 if ( mCollectionSelectionModel->selection().indexes().isEmpty() ) {
574 const Item::List items = mGenericManager->selectedItems();
575 if ( items.isEmpty() ) {
579 MoveToTrashCommand *command =
new MoveToTrashCommand( mCollectionSelectionModel->model(), items, mParent );
583 void slotMoveAllToTrash()
589 if ( mCollectionSelectionModel->selection().indexes().isEmpty() ) {
593 const Collection::List collections = mGenericManager->selectedCollections();
594 if ( collections.isEmpty() ) {
598 MoveToTrashCommand *command =
new MoveToTrashCommand( mCollectionSelectionModel->model(), collections, mParent );
602 void slotRemoveDuplicates()
608 const Collection::List collections = mGenericManager->selectedCollections();
609 if ( collections.isEmpty() ) {
614 connect( job, SIGNAL(finished(KJob*)), mParent, SLOT(slotJobFinished(KJob*)) );
617 void slotJobFinished( KJob *job )
619 if ( job->error() ) {
620 Util::showJobError( job );
624 void slotEmptyAllTrash()
630 EmptyTrashCommand *command =
new EmptyTrashCommand( const_cast<QAbstractItemModel*>( mCollectionSelectionModel->model() ), mParent );
634 void slotEmptyTrash()
640 if ( mCollectionSelectionModel->selection().indexes().isEmpty() ) {
644 const Collection::List collections = mGenericManager->selectedCollections();
645 if ( collections.count() != 1 ) {
649 EmptyTrashCommand *command =
new EmptyTrashCommand( collections.first(), mParent );
653 KActionCollection *mActionCollection;
654 QWidget *mParentWidget;
656 QItemSelectionModel *mCollectionSelectionModel;
657 QItemSelectionModel *mItemSelectionModel;
658 QHash<StandardMailActionManager::Type, KAction*> mActions;
659 QSet<StandardMailActionManager::Type> mInterceptedActions;
665 : QObject( parent ), d( new Private( actionCollection, parent, this ) )
676 d->mCollectionSelectionModel = selectionModel;
677 d->mGenericManager->setCollectionSelectionModel( selectionModel );
679 connect( selectionModel->model(), SIGNAL(rowsInserted(QModelIndex,
int,
int)),
680 SLOT(updateActions()) );
681 connect( selectionModel->model(), SIGNAL(rowsRemoved(QModelIndex,
int,
int)),
682 SLOT(updateActions()) );
683 connect( selectionModel, SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
684 SLOT(updateActions()) );
691 d->mItemSelectionModel = selectionModel;
692 d->mGenericManager->setItemSelectionModel( selectionModel );
694 connect( selectionModel, SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
695 SLOT(updateActions()) );
698 connect( selectionModel->model(), SIGNAL(dataChanged(QModelIndex,QModelIndex)),
699 SLOT(updateActions()) );
706 if ( d->mActions.contains( type ) ) {
707 return d->mActions.value( type );
714 action =
new KAction( d->mParentWidget );
715 action->setIcon( KIcon( QLatin1String(
"mail-mark-read" ) ) );
716 action->setText( i18n(
"&Mark Message as Read" ) );
717 action->setIconText( i18n(
"Mark as Read" ) );
718 action->setHelpText( i18n(
"Mark selected messages as read." ) );
719 action->setWhatsThis( i18n(
"Mark selected messages as read." ) );
721 d->mActionCollection->addAction( QString::fromLatin1(
"akonadi_mark_as_read" ), action );
722 action->setData( QByteArray(
"R" ) );
723 action->setShortcut( Qt::CTRL+Qt::Key_R );
724 connect( action, SIGNAL(triggered(
bool)),
this, SLOT(slotMarkAs()) );
727 action =
new KAction( d->mParentWidget );
728 action->setIcon( KIcon( QLatin1String(
"mail-mark-unread" ) ) );
729 action->setText( i18n(
"&Mark Message as Unread" ) );
730 action->setIconText( i18n(
"Mark as Unread" ) );
731 action->setHelpText( i18n(
"Mark selected messages as unread." ) );
732 action->setWhatsThis( i18n(
"Mark selected messages as unread." ) );
734 d->mActionCollection->addAction( QString::fromLatin1(
"akonadi_mark_as_unread" ), action );
735 action->setShortcut( Qt::CTRL+Qt::Key_U );
736 action->setData( QByteArray(
"U" ) );
737 connect( action, SIGNAL(triggered(
bool)),
this, SLOT(slotMarkAs()) );
740 action =
new KAction( d->mParentWidget );
741 action->setIcon( KIcon( QLatin1String(
"mail-mark-important" ) ) );
742 action->setText( i18n(
"&Mark Message as Important" ) );
743 action->setIconText( i18n(
"Mark as Important" ) );
744 action->setHelpText( i18n(
"Mark selected messages as important." ) );
747 d->mActionCollection->addAction( QString::fromLatin1(
"akonadi_mark_as_important" ), action );
748 action->setData( QByteArray(
"G" ) );
749 connect( action, SIGNAL(triggered(
bool)),
this, SLOT(slotMarkAs()) );
752 action =
new KAction( d->mParentWidget );
753 action->setIcon( KIcon( QLatin1String(
"mail-mark-task" ) ) );
754 action->setText( i18n(
"&Mark Message as Action Item" ) );
755 action->setIconText( i18n(
"Mark as Action Item" ) );
756 action->setHelpText( i18n(
"Mark selected messages as action items." ) );
757 action->setWhatsThis( i18n(
"Mark selected messages as action items." ) );
759 d->mActionCollection->addAction( QString::fromLatin1(
"akonadi_mark_as_action_item" ), action );
760 action->setData( QByteArray(
"K" ) );
761 connect( action, SIGNAL(triggered(
bool)),
this, SLOT(slotMarkAs()) );
764 action =
new KAction( d->mParentWidget );
765 action->setIcon( KIcon( QLatin1String(
"mail-mark-read" ) ) );
766 action->setText( i18n(
"Mark &All Messages as Read" ) );
767 action->setIconText( i18n(
"Mark All as Read" ) );
768 action->setHelpText( i18n(
"Mark all messages as read." ) );
769 action->setWhatsThis( i18n(
"Mark all messages as read." ) );
771 d->mActionCollection->addAction( QString::fromLatin1(
"akonadi_mark_all_as_read" ), action );
772 action->setData( QByteArray(
"R" ) );
773 connect( action, SIGNAL(triggered(
bool)),
this, SLOT(slotMarkAllAs()) );
776 action =
new KAction( d->mParentWidget );
777 action->setIcon( KIcon( QLatin1String(
"mail-mark-unread" ) ) );
778 action->setText( i18n(
"Mark &All Messages as Unread" ) );
779 action->setIconText( i18n(
"Mark All as Unread" ) );
780 action->setHelpText( i18n(
"Mark all messages as unread." ) );
781 action->setWhatsThis( i18n(
"Mark all messages as unread." ) );
783 d->mActionCollection->addAction( QString::fromLatin1(
"akonadi_mark_all_as_unread" ), action );
784 action->setData( QByteArray(
"U" ) );
785 connect( action, SIGNAL(triggered(
bool)),
this, SLOT(slotMarkAllAs()) );
788 action =
new KAction( d->mParentWidget );
789 action->setIcon( KIcon( QLatin1String(
"mail-mark-important" ) ) );
790 action->setText( i18n(
"Mark &All Messages as Important" ) );
791 action->setIconText( i18n(
"Mark All as Important" ) );
792 action->setHelpText( i18n(
"Mark all messages as important." ) );
793 action->setWhatsThis( i18n(
"Mark all messages as important." ) );
795 d->mActionCollection->addAction( QString::fromLatin1(
"akonadi_mark_all_as_important" ), action );
796 action->setData( QByteArray(
"G" ) );
797 connect( action, SIGNAL(triggered(
bool)),
this, SLOT(slotMarkAllAs()) );
800 action =
new KAction( d->mParentWidget );
801 action->setIconText( i18n(
"Mark All as Action Item" ) );
802 action->setText( i18n(
"Mark &All Messages as Action Item" ) );
803 action->setIcon( KIcon( QLatin1String(
"mail-mark-task" ) ) );
804 action->setHelpText( i18n(
"Mark all messages as action items." ) );
805 action->setWhatsThis( i18n(
"Mark all messages as action items." ) );
807 d->mActionCollection->addAction( QString::fromLatin1(
"akonadi_mark_all_as_action_item" ), action );
808 action->setData( QByteArray(
"K" ) );
809 connect( action, SIGNAL(triggered(
bool)),
this, SLOT(slotMarkAllAs()) );
812 action =
new KAction( d->mParentWidget );
813 action->setIcon( KIcon( QLatin1String(
"user-trash" ) ) );
814 action->setText( i18n(
"Move to &Trash" ) );
815 action->setShortcut( QKeySequence( Qt::Key_Delete ) );
816 action->setHelpText( i18n(
"Move selected messages to the trash folder." ) );
817 action->setWhatsThis( i18n(
"Move selected messages to the trash folder." ) );
819 d->mActionCollection->addAction( QString::fromLatin1(
"akonadi_move_to_trash" ), action );
820 connect( action, SIGNAL(triggered(
bool)),
this, SLOT(slotMoveToTrash()) );
823 action =
new KAction( d->mParentWidget );
824 action->setIcon( KIcon( QLatin1String(
"user-trash" ) ) );
825 action->setText( i18n(
"Move All to &Trash" ) );
826 action->setHelpText( i18n(
"Move all messages to the trash folder." ) );
827 action->setWhatsThis( i18n(
"Move all messages to the trash folder." ) );
829 d->mActionCollection->addAction( QString::fromLatin1(
"akonadi_move_all_to_trash" ), action );
830 connect( action, SIGNAL(triggered(
bool)),
this, SLOT(slotMoveAllToTrash()) );
833 action =
new KAction( d->mParentWidget );
834 action->setText( i18n(
"Remove &Duplicate Messages" ) );
835 action->setHelpText( i18n(
"Remove duplicate messages." ) );
836 action->setWhatsThis( i18n(
"Remove duplicate messages." ) );
837 action->setShortcut( QKeySequence( Qt::CTRL + Qt::Key_Asterisk ) );
839 d->mActionCollection->addAction( QString::fromLatin1(
"akonadi_remove_duplicates" ), action );
840 connect( action, SIGNAL(triggered(
bool)),
this, SLOT(slotRemoveDuplicates()) );
843 action =
new KAction( d->mParentWidget );
844 action->setText( i18n(
"Empty All &Trash Folders" ) );
845 action->setHelpText( i18n(
"Permanently delete all messages from all trash folders." ) );
846 action->setWhatsThis( i18n(
"Permanently delete all messages from all trash folders." ) );
848 d->mActionCollection->addAction( QString::fromLatin1(
"akonadi_empty_all_trash" ), action );
849 connect( action, SIGNAL(triggered(
bool)),
this, SLOT(slotEmptyAllTrash()) );
852 action =
new KAction( d->mParentWidget );
853 action->setText( i18n(
"E&mpty Trash" ) );
854 action->setHelpText( i18n(
"Permanently delete all messages from the trash folder." ) );
855 action->setWhatsThis( i18n(
"Permanently delete all messages from the trash folder." ) );
857 d->mActionCollection->addAction( QString::fromLatin1(
"akonadi_empty_trash" ), action );
858 connect( action, SIGNAL(triggered(
bool)),
this, SLOT(slotEmptyTrash()) );
870 KAction *act = d->mGenericManager->action(type);
872 act = d->mGenericManager->createAction( type );
873 d->updateGenericAction(type);
893 d->mGenericManager->createAllActions();
894 d->updateGenericAllActions();
901 if ( d->mActions.contains( type ) ) {
902 return d->mActions.value( type );
910 return d->mGenericManager->action( type );
915 d->mGenericManager->setActionText( type, text );
921 d->mInterceptedActions.insert( type );
923 d->mInterceptedActions.remove( type );
929 d->mGenericManager->interceptAction( type, intercept );
934 return d->mGenericManager->selectedCollections();
939 return d->mGenericManager->selectedItems();
944 d->mGenericManager->setFavoriteCollectionsModel( favoritesModel );
949 d->mGenericManager->setFavoriteSelectionModel( selectionModel );
952 void StandardMailActionManager::setCollectionPropertiesPageNames(
const QStringList &names )
954 d->mGenericManager->setCollectionPropertiesPageNames( names );
959 return d->mGenericManager;
962 #include "moc_standardmailactionmanager.cpp"