Akonadi Mime

standardmailactionmanager.cpp
1/*
2 This file is part of Akonadi Contact.
3
4 Copyright (c) 2009 - 2010 Tobias Koenig <tokoe@kde.org>
5 SPDX-FileCopyrightText: 2010 Klarälvdalens Datakonsult AB, a KDAB Group company, <info@kdab.com>
6 SPDX-FileCopyrightText: 2010 Andras Mantia <andras@kdab.com>
7
8 SPDX-License-Identifier: LGPL-2.0-or-later
9*/
10
11#include "standardmailactionmanager.h"
12
13#include "akonadi_mime_debug.h"
14#include "emptytrashcommand.h"
15#include "markascommand.h"
16#include "movetotrashcommand.h"
17#include "removeduplicatesjob.h"
18#include "specialmailcollections.h"
19#include "util_p.h"
20
21#include <Akonadi/AgentFilterProxyModel>
22#include <Akonadi/AgentInstance>
23#include <Akonadi/AgentInstanceCreateJob>
24#include <Akonadi/AgentManager>
25#include <Akonadi/AgentTypeDialog>
26#include <Akonadi/CollectionStatistics>
27#include <Akonadi/EntityTreeModel>
28#include <Akonadi/MimeTypeChecker>
29#include <Akonadi/SubscriptionDialog>
30
31#include "messagestatus.h"
32#include <KMime/KMimeMessage>
33
34#include <KActionCollection>
35#include <QAction>
36
37#include <KLocalizedString>
38
39#include <QItemSelectionModel>
40
41using namespace Akonadi;
42
43class Akonadi::StandardMailActionManagerPrivate
44{
45public:
46 StandardMailActionManagerPrivate(KActionCollection *actionCollection, QWidget *parentWidget, StandardMailActionManager *parent)
47 : mActionCollection(actionCollection)
48 , mParentWidget(parentWidget)
49 , mParent(parent)
50 {
51 mGenericManager = new StandardActionManager(actionCollection, parentWidget);
52
54 mGenericManager,
56 mParent,
57 [this](const Collection::List &selectedCollections, const Collection::List &selectedFavoriteCollections, const Item::List &selectedItems) {
58 // Optimization: pass along the lists to avoid recalculating them here
59 updateActions(selectedCollections, selectedFavoriteCollections, selectedItems);
60 });
61
63
65 mGenericManager->setCapabilityFilter(QStringList() << QStringLiteral("Resource"));
66 }
67
68 ~StandardMailActionManagerPrivate()
69 {
70 delete mGenericManager;
71 }
72
73 void updateGenericAllActions()
74 {
75 updateGenericAction(StandardActionManager::CreateCollection);
76 updateGenericAction(StandardActionManager::CopyCollections);
80 updateGenericAction(StandardActionManager::CopyItems);
81 updateGenericAction(StandardActionManager::Paste);
82 updateGenericAction(StandardActionManager::DeleteItems);
88 updateGenericAction(StandardActionManager::CopyItemToMenu);
89 updateGenericAction(StandardActionManager::MoveItemToMenu);
91 updateGenericAction(StandardActionManager::CutItems);
92 updateGenericAction(StandardActionManager::CutCollections);
93 updateGenericAction(StandardActionManager::CreateResource);
94 updateGenericAction(StandardActionManager::DeleteResources);
100 updateGenericAction(StandardActionManager::CopyItemToDialog);
101 updateGenericAction(StandardActionManager::MoveItemToDialog);
104 updateGenericAction(StandardActionManager::MoveItemsToTrash);
112 }
113
114 void updateGenericAction(StandardActionManager::Type type)
115 {
116 switch (type) {
119 act->setText(i18n("Add Folder..."));
120 act->setWhatsThis(i18n("Add a new folder to the currently selected account."));
121 setHelpText(act, i18n("Add a new folder to the currently selected account."));
122
124
127 ki18n("Could not create folder: %1"));
128
130 break;
131 }
133 mGenericManager->setActionText(Akonadi::StandardActionManager::CopyCollections, ki18np("Copy Folder", "Copy %1 Folders"));
134 mGenericManager->action(Akonadi::StandardActionManager::CopyCollections)->setWhatsThis(i18n("Copy the selected folders to the clipboard."));
135 setHelpText(mGenericManager->action(Akonadi::StandardActionManager::CopyCollections), i18n("Copy the selected folders to the clipboard."));
138 ki18nc("@title:window", "Properties of Folder %1"));
139 break;
141 mGenericManager->setActionText(Akonadi::StandardActionManager::DeleteCollections, ki18np("Delete Folder", "Delete %1 Folders"));
142 mGenericManager->action(Akonadi::StandardActionManager::DeleteCollections)->setWhatsThis(i18n("Delete the selected folders from the account."));
143 setHelpText(mGenericManager->action(Akonadi::StandardActionManager::DeleteCollections), i18n("Delete the selected folders from the account."));
146 ki18np("Do you really want to delete this folder and all its sub-folders?",
147 "Do you really want to delete %1 folders and all their sub-folders?"));
148
151 ki18ncp("@title:window", "Delete folder?", "Delete folders?"));
152
155 ki18n("Could not delete folder: %1"));
156
158
159 break;
161 mGenericManager->setActionText(Akonadi::StandardActionManager::SynchronizeCollections, ki18np("Update Folder", "Update Folders"));
162
163 mGenericManager->action(Akonadi::StandardActionManager::SynchronizeCollections)->setWhatsThis(i18n("Update the contents of the selected folders."));
164 setHelpText(mGenericManager->action(Akonadi::StandardActionManager::SynchronizeCollections), i18n("Update the contents of the selected folders."));
165 break;
167 mGenericManager->setActionText(Akonadi::StandardActionManager::CutCollections, ki18np("Cut Folder", "Cut %1 Folders"));
168 mGenericManager->action(Akonadi::StandardActionManager::CutCollections)->setWhatsThis(i18n("Cut the selected folders from the account."));
169 setHelpText(mGenericManager->action(Akonadi::StandardActionManager::CutCollections), i18n("Cut the selected folders from the account."));
170 break;
172 mGenericManager->action(Akonadi::StandardActionManager::CollectionProperties)->setText(i18n("Folder Properties"));
174 ->setWhatsThis(i18n("Open a dialog to edit the properties of the selected folder."));
176 i18n("Open a dialog to edit the properties of the selected folder."));
177 break;
179 mGenericManager->setActionText(Akonadi::StandardActionManager::CopyItems, ki18np("Copy Message", "Copy %1 Messages"));
180 mGenericManager->action(Akonadi::StandardActionManager::CopyItems)->setWhatsThis(i18n("Copy the selected messages to the clipboard."));
181 setHelpText(mGenericManager->action(Akonadi::StandardActionManager::CopyItems), i18n("Copy the selected messages to the clipboard."));
182 break;
184 mGenericManager->setActionText(Akonadi::StandardActionManager::DeleteItems, ki18np("Delete Message", "Delete %1 Messages"));
185 mGenericManager->action(Akonadi::StandardActionManager::DeleteItems)->setWhatsThis(i18n("Delete the selected messages from the folder."));
186 setHelpText(mGenericManager->action(Akonadi::StandardActionManager::DeleteItems), i18n("Delete the selected messages from the folder."));
189 ki18np("Do you really want to delete the selected message?", "Do you really want to delete %1 messages?"));
190
193 ki18ncp("@title:window", "Delete Message?", "Delete Messages?"));
194
196
198 break;
200 mGenericManager->setActionText(Akonadi::StandardActionManager::CutItems, ki18np("Cut Message", "Cut %1 Messages"));
201 mGenericManager->action(Akonadi::StandardActionManager::CutItems)->setWhatsThis(i18n("Cut the selected message from the folder."));
202 setHelpText(mGenericManager->action(Akonadi::StandardActionManager::CutItems), i18n("Cut the selected message from the folder."));
203 break;
205 mGenericManager->action(Akonadi::StandardActionManager::CreateResource)->setText(i18n("Add &Account..."));
207 ->setWhatsThis(i18n("Add a new account<p>"
208 "You will be presented with a dialog where you can select "
209 "the type of the account that shall be added.</p>"));
210 mGenericManager->setContextText(StandardActionManager::CreateResource, StandardActionManager::DialogTitle, i18nc("@title:window", "Add Account"));
211
214 ki18n("Could not create account: %1"));
215
217 break;
219 mGenericManager->setActionText(Akonadi::StandardActionManager::DeleteResources, ki18np("&Delete Account", "&Delete %1 Accounts"));
221 ->setWhatsThis(i18n("Delete the selected accounts<p>"
222 "The currently selected accounts will be deleted, "
223 "along with all the messages they contain.</p>"));
226 ki18np("Do you really want to delete this account?", "Do you really want to delete %1 accounts?"));
227
230 ki18ncp("@title:window", "Delete Account?", "Delete Accounts?"));
231 break;
233 mGenericManager->action(Akonadi::StandardActionManager::ResourceProperties)->setText(i18n("Account Properties..."));
235 ->setWhatsThis(i18n("Open a dialog to edit properties of the selected account."));
236 break;
238 mGenericManager->setActionText(Akonadi::StandardActionManager::SynchronizeResources, ki18np("Update Account", "Update %1 Accounts"));
240 ->setWhatsThis(i18n("Updates the content of all folders of the selected accounts."));
241 break;
244 ki18np("Update This Folder and All Its Subfolders", "Update These Folders and All Their Subfolders"));
245
247 ->setWhatsThis(i18n("Update the contents of the selected folders and all their subfolders."));
249 i18n("Update the contents of the selected folders and all their subfolders."));
250 break;
252 mGenericManager->setContextText(StandardActionManager::Paste, StandardActionManager::ErrorMessageText, ki18n("Could not paste message: %1"));
253
255 break;
256 default:
257 break;
258 }
259 }
260
261 void setHelpText(QAction *act, const QString &text)
262 {
263 act->setStatusTip(text);
264 act->setToolTip(text);
265 if (act->whatsThis().isEmpty()) {
266 act->setWhatsThis(text);
267 }
268 }
269
270 void updateActions()
271 {
272 const Akonadi::Item::List selectedItems = mGenericManager->selectedItems();
273 const Akonadi::Collection::List selectedCollections = mGenericManager->selectedCollections();
274 updateActions(selectedCollections, {}, selectedItems);
275 }
276
277 void updateActionsFromSelectedItems(const Item::List &selectedItems)
278 {
279 const bool itemIsSelected = !selectedItems.isEmpty();
280 if (itemIsSelected) {
281 bool allMarkedAsImportant = true;
282 bool allMarkedAsRead = true;
283 bool allMarkedAsUnread = true;
284 bool allMarkedAsActionItem = true;
285
286 for (const Akonadi::Item &item : selectedItems) {
288 status.setStatusFromFlags(item.flags());
289 if (!status.isImportant()) {
290 allMarkedAsImportant = false;
291 }
292 if (!status.isRead()) {
293 allMarkedAsRead = false;
294 } else {
295 allMarkedAsUnread = false;
296 }
297 if (!status.isToAct()) {
298 allMarkedAsActionItem = false;
299 }
300 }
301
303 if (action) {
304 updateMarkAction(action, allMarkedAsRead);
305 action->setEnabled(!allMarkedAsRead);
306 }
307
309 if (action) {
310 updateMarkAction(action, allMarkedAsUnread);
311 action->setEnabled(!allMarkedAsUnread);
312 }
313
315 if (action) {
316 action->setCheckable(true);
317 updateMarkAction(action, allMarkedAsImportant);
318 action->setChecked(allMarkedAsImportant);
319 if (allMarkedAsImportant) {
320 action->setText(i18n("Remove Important Mark"));
321 } else {
322 action->setText(i18n("&Mark Message as Important"));
323 }
324 action->setEnabled(true);
325 }
326
328 if (action) {
329 action->setCheckable(true);
330 updateMarkAction(action, allMarkedAsActionItem);
331 action->setChecked(allMarkedAsActionItem);
332 if (allMarkedAsActionItem) {
333 action->setText(i18n("Remove Action Item Mark"));
334 } else {
335 action->setText(i18n("&Mark Message as Action Item"));
336 }
337 action->setEnabled(true);
338 }
339 } else {
341 if (action) {
342 action->setEnabled(false);
343 }
344
346 if (action) {
347 action->setEnabled(false);
348 }
349
351 if (action) {
352 action->setEnabled(false);
353 }
354 }
355 }
356
357 void updateActions(const Collection::List &selectedCollections, const Collection::List &selectedFavoriteCollections, const Item::List &selectedItems)
358 {
359 Q_UNUSED(selectedFavoriteCollections)
360 const bool itemIsSelected = !selectedItems.isEmpty();
361 const bool collectionIsSelected = !selectedCollections.isEmpty();
362 updateActionsFromSelectedItems(selectedItems);
363
364 bool enableMarkAllAsRead = false;
365 bool enableMarkAllAsUnread = false;
366 bool canDeleteItem = true;
367 bool isSystemFolder = false;
368 if (collectionIsSelected) {
369 for (const Collection &collection : std::as_const(selectedCollections)) {
370 if (collection.isValid()) {
371 const Akonadi::CollectionStatistics stats = collection.statistics();
372 if (!enableMarkAllAsRead) {
373 enableMarkAllAsRead = (stats.unreadCount() > 0);
374 }
375 if (!enableMarkAllAsUnread) {
376 enableMarkAllAsUnread = (stats.count() != stats.unreadCount());
377 }
378 if (canDeleteItem) {
379 canDeleteItem = collection.rights() & Akonadi::Collection::CanDeleteItem;
380 }
381 if (!isSystemFolder) {
388 }
389 // We will not change after that.
390 if (enableMarkAllAsRead && enableMarkAllAsUnread && !canDeleteItem && isSystemFolder) {
391 break;
392 }
393 }
394 }
395 }
396 QAction *action = nullptr;
397 if (isSystemFolder) {
398 action = mGenericManager->action(StandardActionManager::DeleteCollections);
399 if (action) {
400 action->setEnabled(false);
401 }
402 }
403
405 if (action) {
406 action->setEnabled(itemIsSelected && canDeleteItem);
407 }
409 if (action) {
410 action->setEnabled(canDeleteItem);
411 }
412
414 if (action) {
415 action->setEnabled(enableMarkAllAsRead);
416 }
417
419 if (action) {
420 action->setEnabled(enableMarkAllAsUnread);
421 }
422
423 Q_EMIT mParent->actionStateUpdated();
424 }
425
426 void updateMarkAction(QAction *action, bool allMarked)
427 {
428 QByteArray data = action->data().toByteArray();
429 if (allMarked) {
430 if (!data.startsWith('!')) {
431 data.prepend('!');
432 }
433 } else {
434 if (data.startsWith('!')) {
435 data.remove(0, 1);
436 }
437 }
438 action->setData(data);
439 }
440
441 void markItemsAs(QByteArray typeStr, const Akonadi::Item::List &items, bool checkIntercept = true)
442 {
443 qCDebug(AKONADIMIME_LOG) << "Mark mail as: " << typeStr;
444
445 bool invert = false;
446 if (typeStr.startsWith('!')) {
447 invert = true;
448 typeStr.remove(0, 1);
449 }
450
451 Akonadi::MessageStatus targetStatus;
452 targetStatus.setStatusFromStr(QLatin1StringView(typeStr));
453
455 if (typeStr == "U") {
457 targetStatus.setRead(true);
458 invert = true;
459 } else if (typeStr == "K") {
461 } else if (typeStr == "G") {
463 }
464
465 if (mInterceptedActions.contains(type) && checkIntercept) {
466 return;
467 }
468
469 auto command = new MarkAsCommand(targetStatus, items, invert, mParent);
470 command->execute();
471 }
472
473 void slotMarkAs()
474 {
475 const Akonadi::Item::List items = mGenericManager->selectedItems();
476 if (items.isEmpty()) {
477 return;
478 }
479 const QAction *action = qobject_cast<QAction *>(mParent->sender());
480 Q_ASSERT(action);
481
482 const QByteArray typeStr = action->data().toByteArray();
483
484 markItemsAs(typeStr, items, true);
485 }
486
487 void markAllItemsAs(QByteArray typeStr, const Akonadi::Collection::List &collections, bool checkIntercept = true)
488 {
489 qCDebug(AKONADIMIME_LOG) << "Mark all as: " << typeStr;
490
491 Akonadi::MessageStatus targetStatus;
492 targetStatus.setStatusFromStr(QLatin1StringView(typeStr));
493
494 bool invert = false;
495 if (typeStr.startsWith('!')) {
496 invert = true;
497 typeStr.remove(0, 1);
498 }
499 bool recursive = false;
500 if (typeStr.startsWith(':')) {
501 recursive = true;
502 typeStr.remove(0, 1);
503 }
504
506 if (typeStr == "U") {
508 targetStatus.setRead(true);
509 invert = true;
510 } else if (typeStr == "K") {
512 } else if (typeStr == "G") {
514 }
515
516 if (mInterceptedActions.contains(type) && checkIntercept) {
517 return;
518 }
519
520 auto command = new MarkAsCommand(targetStatus, collections, invert, recursive, mParent);
521 command->execute();
522 }
523
524 void slotMarkAllAs()
525 {
526 const Akonadi::Collection::List collections = mGenericManager->selectedCollections();
527 if (collections.isEmpty()) {
528 return;
529 }
530
531 const QAction *action = qobject_cast<QAction *>(mParent->sender());
532 Q_ASSERT(action);
533 const QByteArray typeStr = action->data().toByteArray();
534 markAllItemsAs(typeStr, collections, true);
535 }
536
537 void slotMoveToTrash()
538 {
539 if (mInterceptedActions.contains(StandardMailActionManager::MoveToTrash)) {
540 return;
541 }
542
543 if (mCollectionSelectionModel->selection().indexes().isEmpty()) {
544 return;
545 }
546
547 const Item::List items = mGenericManager->selectedItems();
548 if (items.isEmpty()) {
549 return;
550 }
551
552 auto command = new MoveToTrashCommand(mCollectionSelectionModel->model(), items, mParent);
553 command->execute();
554 }
555
556 void slotMoveAllToTrash()
557 {
558 if (mInterceptedActions.contains(StandardMailActionManager::MoveAllToTrash)) {
559 return;
560 }
561
562 if (mCollectionSelectionModel->selection().indexes().isEmpty()) {
563 return;
564 }
565
566 const Collection::List collections = mGenericManager->selectedCollections();
567 if (collections.isEmpty()) {
568 return;
569 }
570
571 auto command = new MoveToTrashCommand(mCollectionSelectionModel->model(), collections, mParent);
572 command->execute();
573 }
574
575 void slotRemoveDuplicates()
576 {
577 if (mInterceptedActions.contains(StandardMailActionManager::RemoveDuplicates)) {
578 return;
579 }
580
581 const Collection::List collections = mGenericManager->selectedCollections();
582 if (collections.isEmpty()) {
583 return;
584 }
585
586 auto job = new RemoveDuplicatesJob(collections, mParent);
587 QObject::connect(job, &RemoveDuplicatesJob::finished, mParent, [this](KJob *job) {
588 slotJobFinished(job);
589 });
590 }
591
592 void slotJobFinished(KJob *job)
593 {
594 if (job->error()) {
595 Util::showJobError(job);
596 }
597 }
598
599 void slotEmptyAllTrash()
600 {
601 if (mInterceptedActions.contains(StandardMailActionManager::EmptyAllTrash)) {
602 return;
603 }
604
605 auto command = new EmptyTrashCommand(const_cast<QAbstractItemModel *>(mCollectionSelectionModel->model()), mParent);
606 command->execute();
607 }
608
609 void slotEmptyTrash()
610 {
611 if (mInterceptedActions.contains(StandardMailActionManager::EmptyTrash)) {
612 return;
613 }
614
615 if (mCollectionSelectionModel->selection().indexes().isEmpty()) {
616 return;
617 }
618
619 const Collection::List collections = mGenericManager->selectedCollections();
620 if (collections.count() != 1) {
621 return;
622 }
623
624 auto command = new EmptyTrashCommand(collections.first(), mParent);
625 command->execute();
626 }
627
628 KActionCollection *const mActionCollection;
629 QWidget *const mParentWidget;
630 StandardActionManager *mGenericManager = nullptr;
631 QItemSelectionModel *mCollectionSelectionModel = nullptr;
632 QItemSelectionModel *mItemSelectionModel = nullptr;
634 QSet<StandardMailActionManager::Type> mInterceptedActions;
635 StandardMailActionManager *const mParent;
636};
637
639 : QObject(parent)
640 , d(new StandardMailActionManagerPrivate(actionCollection, parent, this))
641{
642}
643
645
647{
648 d->mCollectionSelectionModel = selectionModel;
649 d->mGenericManager->setCollectionSelectionModel(selectionModel);
650
651 connect(selectionModel->model(), &QAbstractItemModel::rowsInserted, this, [this]() {
652 d->updateActions();
653 });
654 connect(selectionModel->model(), &QAbstractItemModel::rowsRemoved, this, [this]() {
655 d->updateActions();
656 });
657 // connecting to QItemSelectionModel::selectionChanged is done by mGenericManager
658
659 d->updateActions();
660}
661
662void StandardMailActionManager::setItems(const Item::List &selectedItems)
663{
664 d->updateActionsFromSelectedItems(selectedItems);
665}
666
668{
669 d->mItemSelectionModel = selectionModel;
670 d->mGenericManager->setItemSelectionModel(selectionModel);
671
672 // connecting to QItemSelectionModel::selectionChanged is done by mGenericManager
673
674 // to catch item modifications, listen to the model's dataChanged signal as well
675 connect(selectionModel->model(), &QAbstractItemModel::dataChanged, this, [this]() {
676 d->updateActions();
677 });
678
679 d->updateActions();
680}
681
683{
684 if (d->mActions.contains(type)) {
685 return d->mActions.value(type);
686 }
687
688 QAction *action = nullptr;
689
690 switch (type) {
691 case MarkMailAsRead:
692 action = new QAction(d->mParentWidget);
693 action->setIcon(QIcon::fromTheme(QStringLiteral("mail-mark-read")));
694 action->setText(i18n("&Mark Message as Read"));
695 action->setIconText(i18n("Mark as Read"));
696 d->setHelpText(action, i18n("Mark selected messages as read."));
697 action->setWhatsThis(i18n("Mark selected messages as read."));
698 d->mActions.insert(MarkMailAsRead, action);
699 d->mActionCollection->addAction(QStringLiteral("akonadi_mark_as_read"), action);
701 d->mActionCollection->setDefaultShortcut(action, QKeySequence(Qt::CTRL | Qt::Key_R));
702 connect(action, &QAction::triggered, this, [this]() {
703 d->slotMarkAs();
704 });
705 break;
706 case MarkMailAsUnread:
707 action = new QAction(d->mParentWidget);
708 action->setIcon(QIcon::fromTheme(QStringLiteral("mail-mark-unread")));
709 action->setText(i18n("&Mark Message as Unread"));
710 action->setIconText(i18n("Mark as Unread"));
711 d->setHelpText(action, i18n("Mark selected messages as unread."));
712 action->setWhatsThis(i18n("Mark selected messages as unread."));
713 d->mActions.insert(MarkMailAsUnread, action);
714 d->mActionCollection->addAction(QStringLiteral("akonadi_mark_as_unread"), action);
715 d->mActionCollection->setDefaultShortcut(action, QKeySequence(Qt::CTRL | Qt::Key_U));
717 connect(action, &QAction::triggered, this, [this]() {
718 d->slotMarkAs();
719 });
720 break;
722 action = new QAction(d->mParentWidget);
723 action->setIcon(QIcon::fromTheme(QStringLiteral("mail-mark-important")));
724 action->setText(i18n("&Mark Message as Important"));
725 action->setIconText(i18n("Mark as Important"));
726 d->setHelpText(action, i18n("Mark selected messages as important."));
727
728 d->mActions.insert(MarkMailAsImportant, action);
729 d->mActionCollection->addAction(QStringLiteral("akonadi_mark_as_important"), action);
731 connect(action, &QAction::triggered, this, [this]() {
732 d->slotMarkAs();
733 });
734 break;
736 action = new QAction(d->mParentWidget);
737 action->setIcon(QIcon::fromTheme(QStringLiteral("mail-mark-task")));
738 action->setText(i18n("&Mark Message as Action Item"));
739 action->setIconText(i18n("Mark as Action Item"));
740 d->setHelpText(action, i18n("Mark selected messages as action items."));
741 action->setWhatsThis(i18n("Mark selected messages as action items."));
742 d->mActions.insert(MarkMailAsActionItem, action);
743 d->mActionCollection->addAction(QStringLiteral("akonadi_mark_as_action_item"), action);
745 connect(action, &QAction::triggered, this, [this]() {
746 d->slotMarkAs();
747 });
748 break;
750 action = new QAction(d->mParentWidget);
751 action->setIcon(QIcon::fromTheme(QStringLiteral("mail-mark-read")));
752 action->setText(i18n("Mark &All Messages as Read"));
753 action->setIconText(i18n("Mark All as Read"));
754 d->setHelpText(action, i18n("Mark all messages as read."));
755 action->setWhatsThis(i18n("Mark all messages as read."));
756 d->mActions.insert(MarkAllMailAsRead, action);
757 d->mActionCollection->addAction(QStringLiteral("akonadi_mark_all_as_read"), action);
759 connect(action, &QAction::triggered, this, [this]() {
760 d->slotMarkAllAs();
761 });
762 break;
764 action = new QAction(d->mParentWidget);
765 action->setIcon(QIcon::fromTheme(QStringLiteral("mail-mark-read")));
766 action->setText(i18n("Mark &All Messages as Read Recursively"));
767 action->setIconText(i18n("Mark All as Read Recursively"));
768 d->setHelpText(action, i18n("Mark all messages as read recursively."));
769 action->setWhatsThis(i18n("Mark all messages as read recursively."));
770 d->mActions.insert(MarkAllMailAsReadRecursive, action);
771 d->mActionCollection->addAction(QStringLiteral("akonadi_mark_all_as_read_recursive"), action);
772 action->setData(QByteArray(":R"));
773 connect(action, &QAction::triggered, this, [this]() {
774 d->slotMarkAllAs();
775 });
776 break;
778 action = new QAction(d->mParentWidget);
779 action->setIcon(QIcon::fromTheme(QStringLiteral("mail-mark-unread")));
780 action->setText(i18n("Mark &All Messages as Unread"));
781 action->setIconText(i18n("Mark All as Unread"));
782 d->setHelpText(action, i18n("Mark all messages as unread."));
783 action->setWhatsThis(i18n("Mark all messages as unread."));
784 d->mActions.insert(MarkAllMailAsUnread, action);
785 d->mActionCollection->addAction(QStringLiteral("akonadi_mark_all_as_unread"), action);
787 connect(action, &QAction::triggered, this, [this]() {
788 d->slotMarkAllAs();
789 });
790 break;
792 action = new QAction(d->mParentWidget);
793 action->setIcon(QIcon::fromTheme(QStringLiteral("mail-mark-important")));
794 action->setText(i18n("Mark &All Messages as Important"));
795 action->setIconText(i18n("Mark All as Important"));
796 d->setHelpText(action, i18n("Mark all messages as important."));
797 action->setWhatsThis(i18n("Mark all messages as important."));
798 d->mActions.insert(MarkAllMailAsImportant, action);
799 d->mActionCollection->addAction(QStringLiteral("akonadi_mark_all_as_important"), action);
801 connect(action, &QAction::triggered, this, [this]() {
802 d->slotMarkAllAs();
803 });
804 break;
806 action = new QAction(d->mParentWidget);
807 action->setIconText(i18n("Mark All as Action Item"));
808 action->setText(i18n("Mark &All Messages as Action Item"));
809 action->setIcon(QIcon::fromTheme(QStringLiteral("mail-mark-task")));
810 d->setHelpText(action, i18n("Mark all messages as action items."));
811 action->setWhatsThis(i18n("Mark all messages as action items."));
812 d->mActions.insert(MarkAllMailAsActionItem, action);
813 d->mActionCollection->addAction(QStringLiteral("akonadi_mark_all_as_action_item"), action);
815 connect(action, &QAction::triggered, this, [this]() {
816 d->slotMarkAllAs();
817 });
818 break;
819 case MoveToTrash:
820 action = new QAction(d->mParentWidget);
821 action->setIcon(QIcon::fromTheme(QStringLiteral("user-trash")));
822 action->setText(i18n("Move to &Trash"));
823 d->mActionCollection->setDefaultShortcut(action, QKeySequence(Qt::Key_Delete));
824 d->setHelpText(action, i18n("Move selected messages to the trash folder."));
825 action->setWhatsThis(i18n("Move selected messages to the trash folder."));
826 d->mActions.insert(MoveToTrash, action);
827 d->mActionCollection->addAction(QStringLiteral("akonadi_move_to_trash"), action);
828 connect(action, &QAction::triggered, this, [this]() {
829 d->slotMoveToTrash();
830 });
831 break;
832 case MoveAllToTrash:
833 action = new QAction(d->mParentWidget);
834 action->setIcon(QIcon::fromTheme(QStringLiteral("user-trash")));
835 action->setText(i18n("Move All to &Trash"));
836 d->setHelpText(action, i18n("Move all messages to the trash folder."));
837 action->setWhatsThis(i18n("Move all messages to the trash folder."));
838 d->mActions.insert(MoveAllToTrash, action);
839 d->mActionCollection->addAction(QStringLiteral("akonadi_move_all_to_trash"), action);
840 connect(action, &QAction::triggered, this, [this]() {
841 d->slotMoveAllToTrash();
842 });
843 break;
844 case RemoveDuplicates:
845 action = new QAction(d->mParentWidget);
846 action->setText(i18n("Remove &Duplicate Messages"));
847 d->setHelpText(action, i18n("Remove duplicate messages."));
848 action->setWhatsThis(i18n("Remove duplicate messages."));
849 d->mActionCollection->setDefaultShortcut(action, QKeySequence(Qt::CTRL | Qt::Key_Asterisk));
850 d->mActions.insert(RemoveDuplicates, action);
851 d->mActionCollection->addAction(QStringLiteral("akonadi_remove_duplicates"), action);
852 connect(action, &QAction::triggered, this, [this]() {
853 d->slotRemoveDuplicates();
854 });
855 break;
856 case EmptyAllTrash:
857 action = new QAction(d->mParentWidget);
858 action->setText(i18n("Empty All &Trash Folders"));
859 d->setHelpText(action, i18n("Permanently delete all messages from all trash folders."));
860 action->setWhatsThis(i18n("Permanently delete all messages from all trash folders."));
861 d->mActions.insert(EmptyAllTrash, action);
862 d->mActionCollection->addAction(QStringLiteral("akonadi_empty_all_trash"), action);
863 connect(action, &QAction::triggered, this, [this]() {
864 d->slotEmptyAllTrash();
865 });
866 break;
867 case EmptyTrash:
868 action = new QAction(d->mParentWidget);
869 action->setText(i18n("E&mpty Trash"));
870 d->setHelpText(action, i18n("Permanently delete all messages from the trash folder."));
871 action->setWhatsThis(i18n("Permanently delete all messages from the trash folder."));
872 d->mActions.insert(EmptyTrash, action);
873 d->mActionCollection->addAction(QStringLiteral("akonadi_empty_trash"), action);
874 connect(action, &QAction::triggered, this, [this]() {
875 d->slotEmptyTrash();
876 });
877 break;
878 default:
879 Q_ASSERT(false); // should never happen
880 break;
881 }
882
883 return action;
884}
885
887{
888 QAction *act = d->mGenericManager->action(type);
889 if (!act) {
890 act = d->mGenericManager->createAction(type);
891 }
892 d->updateGenericAction(type);
893 return act;
894}
895
918
920{
921 return d->mActions.value(type);
922}
923
925{
926 return d->mGenericManager->action(type);
927}
928
930{
931 d->mGenericManager->setActionText(type, text);
932}
933
935{
936 if (intercept) {
937 d->mInterceptedActions.insert(type);
938 } else {
939 d->mInterceptedActions.remove(type);
940 }
941}
942
944{
945 d->mGenericManager->interceptAction(type, intercept);
946}
947
949{
950 return d->mGenericManager->selectedCollections();
951}
952
954{
955 return d->mGenericManager->selectedItems();
956}
957
959{
960 d->mGenericManager->setFavoriteCollectionsModel(favoritesModel);
961}
962
964{
965 d->mGenericManager->setFavoriteSelectionModel(selectionModel);
966}
967
968void StandardMailActionManager::setCollectionPropertiesPageNames(const QStringList &names)
969{
970 d->mGenericManager->setCollectionPropertiesPageNames(names);
971}
972
973Akonadi::StandardActionManager *StandardMailActionManager::standardActionManager() const
974{
975 return d->mGenericManager;
976}
977
978void StandardMailActionManager::markItemsAs(const QByteArray &typeStr, const Item::List &items, bool checkIntercept)
979{
980 d->markItemsAs(typeStr, items, checkIntercept);
981}
982
983void StandardMailActionManager::markAllItemsAs(const QByteArray &typeStr, const Collection::List &collections, bool checkIntercept)
984{
985 d->markAllItemsAs(typeStr, collections, checkIntercept);
986}
987
988#include "moc_standardmailactionmanager.cpp"
Akonadi KMime Message Status.
void setRead(bool read=true)
Set the status to read.
void setStatusFromFlags(const QSet< QByteArray > &flags)
Set the status as a whole e.g.
void setStatusFromStr(const QString &aStr)
Set the status based on a string representation.
Job that finds and removes duplicate messages in given collection.
@ SentMail
The sent-mail collection.
@ Templates
The templates collection.
static SpecialMailCollections * self()
Returns the global SpecialMailCollections instance.
Akonadi::Collection defaultCollection(Type type) const
Returns the special mail collection of given type in the default resource, or an invalid collection i...
void setActionText(Type type, const KLocalizedString &text)
Akonadi::Item::List selectedItems() const
void setCapabilityFilter(const QStringList &capabilities)
void setMimeTypeFilter(const QStringList &mimeTypes)
void setContextText(Type type, TextContext context, const KLocalizedString &text)
Akonadi::Collection::List selectedCollections() const
QAction * action(Type type) const
void selectionsChanged(const Collection::List &selectedCollectionsList, const Collection::List &selectedFavoriteCollectionsList, const Item::List &selectedItems)
Manages emails specific actions for collection and item views.
void setFavoriteCollectionsModel(FavoriteCollectionsModel *favoritesModel)
Sets the favorite collections model based on which the collection relatedactions should operate.
StandardMailActionManager(KActionCollection *actionCollection, QWidget *parent=nullptr)
Creates a new standard mail action manager.
~StandardMailActionManager() override
Destroys the standard mail action manager.
void setActionText(StandardActionManager::Type type, const KLocalizedString &text)
Sets the label of the action type to text, which is used during updating the action state and substit...
void setItemSelectionModel(QItemSelectionModel *selectionModel)
Sets the item selection model based on which the item related actions should operate.
QAction * createAction(Type type)
Creates the action of the given type and adds it to the action collection specified in the constructo...
void setFavoriteSelectionModel(QItemSelectionModel *selectionModel)
Sets the favorite collection selection model based on which the favorite collection related actions s...
void createAllActions()
Convenience method to create all standard actions.
Akonadi::Item::List selectedItems() const
Returns the list of items that are currently selected.
Type
Describes the supported actions.
@ RemoveDuplicates
Removes all duplicated messages.
@ MoveToTrash
Move all selected messages and folders to trash.
@ EmptyTrash
Empties the trash folder, if a trash folder was selected.
@ MarkAllMailAsReadRecursive
Marks all mails in a folder and its subfolders as read.
@ MarkMailAsActionItem
Marks a mail as action item.
@ MarkAllMailAsActionItem
Marks all mails in a folder as action item.
@ EmptyAllTrash
Empties trash folders on all accounts.
@ MoveAllToTrash
Move all messages of the current folder to trash.
@ MarkAllMailAsImportant
Marks all mails in a folder as important.
@ MarkAllMailAsRead
Marks all mails in a folder as read.
@ MarkMailAsImportant
Marks a mail as important.
@ MarkAllMailAsUnread
Marks all mails in a folder as unread.
Akonadi::Collection::List selectedCollections() const
Returns the list of collections that are currently selected.
void interceptAction(Type type, bool intercept=true)
Sets whether the default implementation for the given action type shall be executed when the action i...
void actionStateUpdated()
This signal is emitted whenever the action state has been updated.
void setCollectionSelectionModel(QItemSelectionModel *selectionModel)
Sets the collection selection model based on which the collection related actions should operate.
QAction * action(Type type) const
Returns the action of the given type, 0 if it has not been created (yet).
int error() const
void finished(KJob *job)
static QString mimeType()
Q_SCRIPTABLE CaptureState status()
KLocalizedString KI18N_EXPORT ki18np(const char *singular, const char *plural)
KLocalizedString KI18N_EXPORT ki18n(const char *text)
QString i18nc(const char *context, const char *text, const TYPE &arg...)
KLocalizedString KI18N_EXPORT ki18ncp(const char *context, const char *singular, const char *plural)
KLocalizedString KI18N_EXPORT ki18nc(const char *context, const char *text)
QString i18n(const char *text, const TYPE &arg...)
Type type(const QSqlDatabase &db)
void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QList< int > &roles)
void rowsInserted(const QModelIndex &parent, int first, int last)
void rowsRemoved(const QModelIndex &parent, int first, int last)
void setCheckable(bool)
void setChecked(bool)
QVariant data() const const
void setEnabled(bool)
void setIcon(const QIcon &icon)
void setIconText(const QString &text)
void setData(const QVariant &data)
void setStatusTip(const QString &statusTip)
void setText(const QString &text)
void setToolTip(const QString &tip)
void triggered(bool checked)
void setWhatsThis(const QString &what)
QByteArray & prepend(QByteArrayView ba)
QByteArray & remove(qsizetype pos, qsizetype len)
bool startsWith(QByteArrayView bv) const const
T value(const Key &key) const const
QIcon fromTheme(const QString &name)
QModelIndexList indexes() const const
QAbstractItemModel * model()
const QItemSelection selection() const const
qsizetype count() const const
T & first()
bool isEmpty() const const
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
QObject * sender() const const
bool contains(const QSet< T > &other) const const
QByteArray toByteArray() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:21:09 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.