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/Message>
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) {
389 }
390 // We will not change after that.
391 if (enableMarkAllAsRead && enableMarkAllAsUnread && !canDeleteItem && isSystemFolder) {
392 break;
393 }
394 }
395 }
396 }
397 QAction *action = nullptr;
398 if (isSystemFolder) {
399 action = mGenericManager->action(StandardActionManager::DeleteCollections);
400 if (action) {
401 action->setEnabled(false);
402 }
403 }
404
406 if (action) {
407 action->setEnabled(itemIsSelected && canDeleteItem);
408 }
410 if (action) {
411 action->setEnabled(canDeleteItem);
412 }
413
415 if (action) {
416 action->setEnabled(enableMarkAllAsRead);
417 }
418
420 if (action) {
421 action->setEnabled(enableMarkAllAsUnread);
422 }
423
424 Q_EMIT mParent->actionStateUpdated();
425 }
426
427 void updateMarkAction(QAction *action, bool allMarked)
428 {
429 QByteArray data = action->data().toByteArray();
430 if (allMarked) {
431 if (!data.startsWith('!')) {
432 data.prepend('!');
433 }
434 } else {
435 if (data.startsWith('!')) {
436 data.remove(0, 1);
437 }
438 }
439 action->setData(data);
440 }
441
442 void markItemsAs(QByteArray typeStr, const Akonadi::Item::List &items, bool checkIntercept = true)
443 {
444 qCDebug(AKONADIMIME_LOG) << "Mark mail as: " << typeStr;
445
446 bool invert = false;
447 if (typeStr.startsWith('!')) {
448 invert = true;
449 typeStr.remove(0, 1);
450 }
451
452 Akonadi::MessageStatus targetStatus;
453 targetStatus.setStatusFromStr(QLatin1StringView(typeStr));
454
456 if (typeStr == "U") {
458 targetStatus.setRead(true);
459 invert = true;
460 } else if (typeStr == "K") {
462 } else if (typeStr == "G") {
464 }
465
466 if (mInterceptedActions.contains(type) && checkIntercept) {
467 return;
468 }
469
470 auto command = new MarkAsCommand(targetStatus, items, invert, mParent);
471 command->execute();
472 }
473
474 void slotMarkAs()
475 {
476 const Akonadi::Item::List items = mGenericManager->selectedItems();
477 if (items.isEmpty()) {
478 return;
479 }
480 const QAction *action = qobject_cast<QAction *>(mParent->sender());
481 Q_ASSERT(action);
482
483 const QByteArray typeStr = action->data().toByteArray();
484
485 markItemsAs(typeStr, items, true);
486 }
487
488 void markAllItemsAs(QByteArray typeStr, const Akonadi::Collection::List &collections, bool checkIntercept = true)
489 {
490 qCDebug(AKONADIMIME_LOG) << "Mark all as: " << typeStr;
491
492 Akonadi::MessageStatus targetStatus;
493 targetStatus.setStatusFromStr(QLatin1StringView(typeStr));
494
495 bool invert = false;
496 if (typeStr.startsWith('!')) {
497 invert = true;
498 typeStr.remove(0, 1);
499 }
500 bool recursive = false;
501 if (typeStr.startsWith(':')) {
502 recursive = true;
503 typeStr.remove(0, 1);
504 }
505
507 if (typeStr == "U") {
509 targetStatus.setRead(true);
510 invert = true;
511 } else if (typeStr == "K") {
513 } else if (typeStr == "G") {
515 }
516
517 if (mInterceptedActions.contains(type) && checkIntercept) {
518 return;
519 }
520
521 auto command = new MarkAsCommand(targetStatus, collections, invert, recursive, mParent);
522 command->execute();
523 }
524
525 void slotMarkAllAs()
526 {
527 const Akonadi::Collection::List collections = mGenericManager->selectedCollections();
528 if (collections.isEmpty()) {
529 return;
530 }
531
532 const QAction *action = qobject_cast<QAction *>(mParent->sender());
533 Q_ASSERT(action);
534 const QByteArray typeStr = action->data().toByteArray();
535 markAllItemsAs(typeStr, collections, true);
536 }
537
538 void slotMoveToTrash()
539 {
540 if (mInterceptedActions.contains(StandardMailActionManager::MoveToTrash)) {
541 return;
542 }
543
544 if (mCollectionSelectionModel->selection().indexes().isEmpty()) {
545 return;
546 }
547
548 const Item::List items = mGenericManager->selectedItems();
549 if (items.isEmpty()) {
550 return;
551 }
552
553 auto command = new MoveToTrashCommand(mCollectionSelectionModel->model(), items, mParent);
554 command->execute();
555 }
556
557 void slotMoveAllToTrash()
558 {
559 if (mInterceptedActions.contains(StandardMailActionManager::MoveAllToTrash)) {
560 return;
561 }
562
563 if (mCollectionSelectionModel->selection().indexes().isEmpty()) {
564 return;
565 }
566
567 const Collection::List collections = mGenericManager->selectedCollections();
568 if (collections.isEmpty()) {
569 return;
570 }
571
572 auto command = new MoveToTrashCommand(mCollectionSelectionModel->model(), collections, mParent);
573 command->execute();
574 }
575
576 void slotRemoveDuplicates()
577 {
578 if (mInterceptedActions.contains(StandardMailActionManager::RemoveDuplicates)) {
579 return;
580 }
581
582 const Collection::List collections = mGenericManager->selectedCollections();
583 if (collections.isEmpty()) {
584 return;
585 }
586
587 auto job = new RemoveDuplicatesJob(collections, mParent);
588 QObject::connect(job, &RemoveDuplicatesJob::finished, mParent, [this](KJob *job) {
589 slotJobFinished(job);
590 });
591 }
592
593 void slotJobFinished(KJob *job)
594 {
595 if (job->error()) {
596 Util::showJobError(job);
597 }
598 }
599
600 void slotEmptyAllTrash()
601 {
602 if (mInterceptedActions.contains(StandardMailActionManager::EmptyAllTrash)) {
603 return;
604 }
605
606 auto command = new EmptyTrashCommand(const_cast<QAbstractItemModel *>(mCollectionSelectionModel->model()), mParent);
607 command->execute();
608 }
609
610 void slotEmptyTrash()
611 {
612 if (mInterceptedActions.contains(StandardMailActionManager::EmptyTrash)) {
613 return;
614 }
615
616 if (mCollectionSelectionModel->selection().indexes().isEmpty()) {
617 return;
618 }
619
620 const Collection::List collections = mGenericManager->selectedCollections();
621 if (collections.count() != 1) {
622 return;
623 }
624
625 auto command = new EmptyTrashCommand(collections.first(), mParent);
626 command->execute();
627 }
628
629 KActionCollection *const mActionCollection;
630 QWidget *const mParentWidget;
631 StandardActionManager *mGenericManager = nullptr;
632 QItemSelectionModel *mCollectionSelectionModel = nullptr;
633 QItemSelectionModel *mItemSelectionModel = nullptr;
635 QSet<StandardMailActionManager::Type> mInterceptedActions;
636 StandardMailActionManager *const mParent;
637};
638
640 : QObject(parent)
641 , d(new StandardMailActionManagerPrivate(actionCollection, parent, this))
642{
643}
644
646
648{
649 d->mCollectionSelectionModel = selectionModel;
650 d->mGenericManager->setCollectionSelectionModel(selectionModel);
651
652 connect(selectionModel->model(), &QAbstractItemModel::rowsInserted, this, [this]() {
653 d->updateActions();
654 });
655 connect(selectionModel->model(), &QAbstractItemModel::rowsRemoved, this, [this]() {
656 d->updateActions();
657 });
658 // connecting to QItemSelectionModel::selectionChanged is done by mGenericManager
659
660 d->updateActions();
661}
662
663void StandardMailActionManager::setItems(const Item::List &selectedItems)
664{
665 d->updateActionsFromSelectedItems(selectedItems);
666}
667
669{
670 d->mItemSelectionModel = selectionModel;
671 d->mGenericManager->setItemSelectionModel(selectionModel);
672
673 // connecting to QItemSelectionModel::selectionChanged is done by mGenericManager
674
675 // to catch item modifications, listen to the model's dataChanged signal as well
676 connect(selectionModel->model(), &QAbstractItemModel::dataChanged, this, [this]() {
677 d->updateActions();
678 });
679
680 d->updateActions();
681}
682
684{
685 if (d->mActions.contains(type)) {
686 return d->mActions.value(type);
687 }
688
689 QAction *action = nullptr;
690
691 switch (type) {
692 case MarkMailAsRead:
693 action = new QAction(d->mParentWidget);
694 action->setIcon(QIcon::fromTheme(QStringLiteral("mail-mark-read")));
695 action->setText(i18n("&Mark Message as Read"));
696 action->setIconText(i18n("Mark as Read"));
697 d->setHelpText(action, i18n("Mark selected messages as read."));
698 action->setWhatsThis(i18n("Mark selected messages as read."));
699 d->mActions.insert(MarkMailAsRead, action);
700 d->mActionCollection->addAction(QStringLiteral("akonadi_mark_as_read"), action);
702 d->mActionCollection->setDefaultShortcut(action, QKeySequence(Qt::CTRL | Qt::Key_R));
703 connect(action, &QAction::triggered, this, [this]() {
704 d->slotMarkAs();
705 });
706 break;
707 case MarkMailAsUnread:
708 action = new QAction(d->mParentWidget);
709 action->setIcon(QIcon::fromTheme(QStringLiteral("mail-mark-unread")));
710 action->setText(i18n("&Mark Message as Unread"));
711 action->setIconText(i18n("Mark as Unread"));
712 d->setHelpText(action, i18n("Mark selected messages as unread."));
713 action->setWhatsThis(i18n("Mark selected messages as unread."));
714 d->mActions.insert(MarkMailAsUnread, action);
715 d->mActionCollection->addAction(QStringLiteral("akonadi_mark_as_unread"), action);
716 d->mActionCollection->setDefaultShortcut(action, QKeySequence(Qt::CTRL | Qt::Key_U));
718 connect(action, &QAction::triggered, this, [this]() {
719 d->slotMarkAs();
720 });
721 break;
723 action = new QAction(d->mParentWidget);
724 action->setIcon(QIcon::fromTheme(QStringLiteral("mail-mark-important")));
725 action->setText(i18n("&Mark Message as Important"));
726 action->setIconText(i18n("Mark as Important"));
727 d->setHelpText(action, i18n("Mark selected messages as important."));
728
729 d->mActions.insert(MarkMailAsImportant, action);
730 d->mActionCollection->addAction(QStringLiteral("akonadi_mark_as_important"), action);
732 connect(action, &QAction::triggered, this, [this]() {
733 d->slotMarkAs();
734 });
735 break;
737 action = new QAction(d->mParentWidget);
738 action->setIcon(QIcon::fromTheme(QStringLiteral("mail-mark-task")));
739 action->setText(i18n("&Mark Message as Action Item"));
740 action->setIconText(i18n("Mark as Action Item"));
741 d->setHelpText(action, i18n("Mark selected messages as action items."));
742 action->setWhatsThis(i18n("Mark selected messages as action items."));
743 d->mActions.insert(MarkMailAsActionItem, action);
744 d->mActionCollection->addAction(QStringLiteral("akonadi_mark_as_action_item"), action);
746 connect(action, &QAction::triggered, this, [this]() {
747 d->slotMarkAs();
748 });
749 break;
751 action = new QAction(d->mParentWidget);
752 action->setIcon(QIcon::fromTheme(QStringLiteral("mail-mark-read")));
753 action->setText(i18n("Mark &All Messages as Read"));
754 action->setIconText(i18n("Mark All as Read"));
755 d->setHelpText(action, i18n("Mark all messages as read."));
756 action->setWhatsThis(i18n("Mark all messages as read."));
757 d->mActions.insert(MarkAllMailAsRead, action);
758 d->mActionCollection->addAction(QStringLiteral("akonadi_mark_all_as_read"), action);
760 connect(action, &QAction::triggered, this, [this]() {
761 d->slotMarkAllAs();
762 });
763 break;
765 action = new QAction(d->mParentWidget);
766 action->setIcon(QIcon::fromTheme(QStringLiteral("mail-mark-read")));
767 action->setText(i18n("Mark &All Messages as Read Recursively"));
768 action->setIconText(i18n("Mark All as Read Recursively"));
769 d->setHelpText(action, i18n("Mark all messages as read recursively."));
770 action->setWhatsThis(i18n("Mark all messages as read recursively."));
771 d->mActions.insert(MarkAllMailAsReadRecursive, action);
772 d->mActionCollection->addAction(QStringLiteral("akonadi_mark_all_as_read_recursive"), action);
773 action->setData(QByteArray(":R"));
774 connect(action, &QAction::triggered, this, [this]() {
775 d->slotMarkAllAs();
776 });
777 break;
779 action = new QAction(d->mParentWidget);
780 action->setIcon(QIcon::fromTheme(QStringLiteral("mail-mark-unread")));
781 action->setText(i18n("Mark &All Messages as Unread"));
782 action->setIconText(i18n("Mark All as Unread"));
783 d->setHelpText(action, i18n("Mark all messages as unread."));
784 action->setWhatsThis(i18n("Mark all messages as unread."));
785 d->mActions.insert(MarkAllMailAsUnread, action);
786 d->mActionCollection->addAction(QStringLiteral("akonadi_mark_all_as_unread"), action);
788 connect(action, &QAction::triggered, this, [this]() {
789 d->slotMarkAllAs();
790 });
791 break;
793 action = new QAction(d->mParentWidget);
794 action->setIcon(QIcon::fromTheme(QStringLiteral("mail-mark-important")));
795 action->setText(i18n("Mark &All Messages as Important"));
796 action->setIconText(i18n("Mark All as Important"));
797 d->setHelpText(action, i18n("Mark all messages as important."));
798 action->setWhatsThis(i18n("Mark all messages as important."));
799 d->mActions.insert(MarkAllMailAsImportant, action);
800 d->mActionCollection->addAction(QStringLiteral("akonadi_mark_all_as_important"), action);
802 connect(action, &QAction::triggered, this, [this]() {
803 d->slotMarkAllAs();
804 });
805 break;
807 action = new QAction(d->mParentWidget);
808 action->setIconText(i18n("Mark All as Action Item"));
809 action->setText(i18n("Mark &All Messages as Action Item"));
810 action->setIcon(QIcon::fromTheme(QStringLiteral("mail-mark-task")));
811 d->setHelpText(action, i18n("Mark all messages as action items."));
812 action->setWhatsThis(i18n("Mark all messages as action items."));
813 d->mActions.insert(MarkAllMailAsActionItem, action);
814 d->mActionCollection->addAction(QStringLiteral("akonadi_mark_all_as_action_item"), action);
816 connect(action, &QAction::triggered, this, [this]() {
817 d->slotMarkAllAs();
818 });
819 break;
820 case MoveToTrash:
821 action = new QAction(d->mParentWidget);
822 action->setIcon(QIcon::fromTheme(QStringLiteral("user-trash")));
823 action->setText(i18n("Move to &Trash"));
824 d->mActionCollection->setDefaultShortcut(action, QKeySequence(Qt::Key_Delete));
825 d->setHelpText(action, i18n("Move selected messages to the trash folder."));
826 action->setWhatsThis(i18n("Move selected messages to the trash folder."));
827 d->mActions.insert(MoveToTrash, action);
828 d->mActionCollection->addAction(QStringLiteral("akonadi_move_to_trash"), action);
829 connect(action, &QAction::triggered, this, [this]() {
830 d->slotMoveToTrash();
831 });
832 break;
833 case MoveAllToTrash:
834 action = new QAction(d->mParentWidget);
835 action->setIcon(QIcon::fromTheme(QStringLiteral("user-trash")));
836 action->setText(i18n("Move All to &Trash"));
837 d->setHelpText(action, i18n("Move all messages to the trash folder."));
838 action->setWhatsThis(i18n("Move all messages to the trash folder."));
839 d->mActions.insert(MoveAllToTrash, action);
840 d->mActionCollection->addAction(QStringLiteral("akonadi_move_all_to_trash"), action);
841 connect(action, &QAction::triggered, this, [this]() {
842 d->slotMoveAllToTrash();
843 });
844 break;
845 case RemoveDuplicates:
846 action = new QAction(d->mParentWidget);
847 action->setText(i18n("Remove &Duplicate Messages"));
848 d->setHelpText(action, i18n("Remove duplicate messages."));
849 action->setWhatsThis(i18n("Remove duplicate messages."));
850 d->mActionCollection->setDefaultShortcut(action, QKeySequence(Qt::CTRL | Qt::Key_Asterisk));
851 d->mActions.insert(RemoveDuplicates, action);
852 d->mActionCollection->addAction(QStringLiteral("akonadi_remove_duplicates"), action);
853 connect(action, &QAction::triggered, this, [this]() {
854 d->slotRemoveDuplicates();
855 });
856 break;
857 case EmptyAllTrash:
858 action = new QAction(d->mParentWidget);
859 action->setText(i18n("Empty All &Trash Folders"));
860 d->setHelpText(action, i18n("Permanently delete all messages from all trash folders."));
861 action->setWhatsThis(i18n("Permanently delete all messages from all trash folders."));
862 d->mActions.insert(EmptyAllTrash, action);
863 d->mActionCollection->addAction(QStringLiteral("akonadi_empty_all_trash"), action);
864 connect(action, &QAction::triggered, this, [this]() {
865 d->slotEmptyAllTrash();
866 });
867 break;
868 case EmptyTrash:
869 action = new QAction(d->mParentWidget);
870 action->setText(i18n("E&mpty Trash"));
871 d->setHelpText(action, i18n("Permanently delete all messages from the trash folder."));
872 action->setWhatsThis(i18n("Permanently delete all messages from the trash folder."));
873 d->mActions.insert(EmptyTrash, action);
874 d->mActionCollection->addAction(QStringLiteral("akonadi_empty_trash"), action);
875 connect(action, &QAction::triggered, this, [this]() {
876 d->slotEmptyTrash();
877 });
878 break;
879 default:
880 Q_ASSERT(false); // should never happen
881 break;
882 }
883
884 return action;
885}
886
888{
889 QAction *act = d->mGenericManager->action(type);
890 if (!act) {
891 act = d->mGenericManager->createAction(type);
892 }
893 d->updateGenericAction(type);
894 return act;
895}
896
919
921{
922 return d->mActions.value(type);
923}
924
926{
927 return d->mGenericManager->action(type);
928}
929
931{
932 d->mGenericManager->setActionText(type, text);
933}
934
936{
937 if (intercept) {
938 d->mInterceptedActions.insert(type);
939 } else {
940 d->mInterceptedActions.remove(type);
941 }
942}
943
945{
946 d->mGenericManager->interceptAction(type, intercept);
947}
948
950{
951 return d->mGenericManager->selectedCollections();
952}
953
955{
956 return d->mGenericManager->selectedItems();
957}
958
960{
961 d->mGenericManager->setFavoriteCollectionsModel(favoritesModel);
962}
963
965{
966 d->mGenericManager->setFavoriteSelectionModel(selectionModel);
967}
968
969void StandardMailActionManager::setCollectionPropertiesPageNames(const QStringList &names)
970{
971 d->mGenericManager->setCollectionPropertiesPageNames(names);
972}
973
974Akonadi::StandardActionManager *StandardMailActionManager::standardActionManager() const
975{
976 return d->mGenericManager;
977}
978
979void StandardMailActionManager::markItemsAs(const QByteArray &typeStr, const Item::List &items, bool checkIntercept)
980{
981 d->markItemsAs(typeStr, items, checkIntercept);
982}
983
984void StandardMailActionManager::markAllItemsAs(const QByteArray &typeStr, const Collection::List &collections, bool checkIntercept)
985{
986 d->markAllItemsAs(typeStr, collections, checkIntercept);
987}
988
989#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 Sat Dec 21 2024 17:05:31 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.