File indexing completed on 2024-05-12 05:20:39
0001 // 0002 0003 #pragma once 0004 0005 #include "kmail_private_export.h" 0006 0007 #include <MailCommon/SearchPattern> 0008 #include <MessageComposer/MessageFactoryNG> 0009 #include <MessageList/View> 0010 #include <MessageViewer/Viewer> 0011 0012 #include <Akonadi/MessageStatus> 0013 #include <KIO/TransferJob> 0014 #include <KMime/KMimeMessage> 0015 0016 #include <Akonadi/Collection> 0017 #include <Akonadi/Item> 0018 #include <Akonadi/ItemFetchScope> 0019 #include <QList> 0020 #include <QPointer> 0021 #include <QUrl> 0022 0023 namespace Akonadi 0024 { 0025 class Tag; 0026 } 0027 0028 namespace KPIM 0029 { 0030 class ProgressItem; 0031 } 0032 0033 using Akonadi::MessageStatus; 0034 0035 class QProgressDialog; 0036 class KMMainWidget; 0037 class KMReaderMainWin; 0038 0039 namespace MessageViewer 0040 { 0041 class HeaderStyle; 0042 class AttachmentStrategy; 0043 } 0044 0045 namespace KIO 0046 { 0047 class Job; 0048 } 0049 namespace KMail 0050 { 0051 class Composer; 0052 } 0053 using PartNodeMessageMap = QMap<KMime::Content *, Akonadi::Item>; 0054 /// Small helper structure which encapsulates the KMMessage created when creating a reply, and 0055 0056 class KMAILTESTS_TESTS_EXPORT KMCommand : public QObject 0057 { 0058 Q_OBJECT 0059 0060 public: 0061 enum Result { 0062 Undefined, 0063 OK, 0064 Canceled, 0065 Failed, 0066 }; 0067 0068 // Trivial constructor, don't retrieve any messages 0069 explicit KMCommand(QWidget *parent = nullptr); 0070 KMCommand(QWidget *parent, const Akonadi::Item &); 0071 // Retrieve all messages in msgList when start is called. 0072 KMCommand(QWidget *parent, const Akonadi::Item::List &msgList); 0073 // Retrieve the single message msgBase when start is called. 0074 ~KMCommand() override; 0075 0076 /** Returns the result of the command. Only call this method from the slot 0077 connected to completed(). 0078 */ 0079 [[nodiscard]] Result result() const; 0080 0081 public Q_SLOTS: 0082 // Retrieve messages then calls execute 0083 void start(); 0084 0085 Q_SIGNALS: 0086 0087 /// @param result The status of the command. 0088 void messagesTransfered(KMCommand::Result result); 0089 0090 /// Emitted when the command has completed. 0091 void completed(KMCommand *command); 0092 0093 protected: 0094 virtual Akonadi::ItemFetchJob *createFetchJob(const Akonadi::Item::List &items); 0095 0096 /** Allows to configure how much data should be retrieved of the messages. */ 0097 [[nodiscard]] Akonadi::ItemFetchScope &fetchScope() 0098 { 0099 return mFetchScope; 0100 } 0101 0102 // Returns list of messages retrieved 0103 [[nodiscard]] const Akonadi::Item::List retrievedMsgs() const; 0104 // Returns the single message retrieved 0105 [[nodiscard]] Akonadi::Item retrievedMessage() const; 0106 // Returns the parent widget 0107 QWidget *parentWidget() const; 0108 0109 [[nodiscard]] bool deletesItself() const; 0110 /** Specify whether the subclass takes care of the deletion of the object. 0111 By default the base class will delete the object. 0112 @param deletesItself true if the subclass takes care of deletion, false 0113 if the base class should take care of deletion 0114 */ 0115 void setDeletesItself(bool deletesItself); 0116 0117 [[nodiscard]] bool emitsCompletedItself() const; 0118 /** Specify whether the subclass takes care of emitting the completed() 0119 signal. By default the base class will Q_EMIT this signal. 0120 @param emitsCompletedItself true if the subclass emits the completed 0121 signal, false if the base class should Q_EMIT 0122 the signal 0123 */ 0124 void setEmitsCompletedItself(bool emitsCompletedItself); 0125 0126 /** Use this to set the result of the command. 0127 @param result The result of the command. 0128 */ 0129 void setResult(Result result); 0130 0131 private: 0132 Q_DISABLE_COPY(KMCommand) 0133 // execute should be implemented by derived classes 0134 virtual Result execute() = 0; 0135 0136 /** transfers the list of (imap)-messages 0137 * this is a necessary preparation for e.g. forwarding */ 0138 void transferSelectedMsgs(); 0139 0140 private Q_SLOTS: 0141 void slotPostTransfer(KMCommand::Result result); 0142 /** the msg has been transferred */ 0143 void slotMsgTransfered(const Akonadi::Item::List &msgs); 0144 /** the KMImapJob is finished */ 0145 void slotJobFinished(); 0146 /** the transfer was canceled */ 0147 void slotTransferCancelled(); 0148 0149 protected: 0150 Akonadi::Item::List mRetrievedMsgs; 0151 0152 private: 0153 void fetchMessages(const Akonadi::Item::List &ids); 0154 // ProgressDialog for transferring messages 0155 QPointer<QProgressDialog> mProgressDialog; 0156 // Currently only one async command allowed at a time 0157 static int mCountJobs; 0158 int mCountMsgs = 0; 0159 Result mResult = Undefined; 0160 bool mDeletesItself : 1; 0161 bool mEmitsCompletedItself : 1; 0162 0163 QWidget *const mParent; 0164 Akonadi::Item::List mMsgList; 0165 Akonadi::ItemFetchScope mFetchScope; 0166 0167 // grant super power to test cases 0168 friend class KMCommandsTest; 0169 }; 0170 0171 class KMAILTESTS_TESTS_EXPORT KMMailtoComposeCommand : public KMCommand 0172 { 0173 Q_OBJECT 0174 0175 public: 0176 explicit KMMailtoComposeCommand(const QUrl &url, const Akonadi::Item &msg = Akonadi::Item()); 0177 0178 private: 0179 [[nodiscard]] Result execute() override; 0180 0181 QUrl mUrl; 0182 Akonadi::Item mMessage; 0183 }; 0184 0185 class KMAILTESTS_TESTS_EXPORT KMMailtoReplyCommand : public KMCommand 0186 { 0187 Q_OBJECT 0188 0189 public: 0190 KMMailtoReplyCommand(QWidget *parent, const QUrl &url, const Akonadi::Item &msg, const QString &selection); 0191 0192 [[nodiscard]] bool replyAsHtml() const; 0193 void setReplyAsHtml(bool replyAsHtml); 0194 0195 private: 0196 [[nodiscard]] Result execute() override; 0197 0198 QUrl mUrl; 0199 QString mSelection; 0200 bool mReplyAsHtml = false; 0201 }; 0202 0203 class KMAILTESTS_TESTS_EXPORT KMMailtoForwardCommand : public KMCommand 0204 { 0205 Q_OBJECT 0206 0207 public: 0208 KMMailtoForwardCommand(QWidget *parent, const QUrl &url, const Akonadi::Item &msg); 0209 0210 private: 0211 [[nodiscard]] Result execute() override; 0212 QUrl mUrl; 0213 }; 0214 0215 class KMAILTESTS_TESTS_EXPORT KMAddBookmarksCommand : public KMCommand 0216 { 0217 Q_OBJECT 0218 0219 public: 0220 KMAddBookmarksCommand(const QUrl &url, QWidget *parent); 0221 0222 private: 0223 [[nodiscard]] Result execute() override; 0224 0225 QUrl mUrl; 0226 }; 0227 0228 class KMAILTESTS_TESTS_EXPORT KMUrlSaveCommand : public KMCommand 0229 { 0230 Q_OBJECT 0231 0232 public: 0233 KMUrlSaveCommand(const QUrl &url, QWidget *parent); 0234 0235 private Q_SLOTS: 0236 void slotUrlSaveResult(KJob *job); 0237 0238 private: 0239 [[nodiscard]] Result execute() override; 0240 0241 QUrl mUrl; 0242 }; 0243 0244 class KMAILTESTS_TESTS_EXPORT KMEditItemCommand : public KMCommand 0245 { 0246 Q_OBJECT 0247 0248 public: 0249 explicit KMEditItemCommand(QWidget *parent, const Akonadi::Item &msg, bool deleteFromSource = true); 0250 ~KMEditItemCommand() override; 0251 private Q_SLOTS: 0252 void slotDeleteItem(KJob *job); 0253 0254 private: 0255 [[nodiscard]] Result execute() override; 0256 bool mDeleteFromSource = false; 0257 }; 0258 0259 class KMAILTESTS_TESTS_EXPORT KMEditMessageCommand : public KMCommand 0260 { 0261 Q_OBJECT 0262 0263 public: 0264 explicit KMEditMessageCommand(QWidget *parent, const KMime::Message::Ptr &msg); 0265 0266 private: 0267 [[nodiscard]] Result execute() override; 0268 KMime::Message::Ptr mMessage; 0269 }; 0270 0271 class KMAILTESTS_TESTS_EXPORT KMUseTemplateCommand : public KMCommand 0272 { 0273 Q_OBJECT 0274 0275 public: 0276 KMUseTemplateCommand(QWidget *parent, const Akonadi::Item &msg); 0277 0278 private: 0279 [[nodiscard]] Result execute() override; 0280 }; 0281 0282 class KMAILTESTS_TESTS_EXPORT KMSaveMsgCommand : public KMCommand 0283 { 0284 Q_OBJECT 0285 0286 public: 0287 KMSaveMsgCommand(QWidget *parent, const Akonadi::Item::List &msgList); 0288 0289 private: 0290 [[nodiscard]] Result execute() override; 0291 }; 0292 0293 class KMAILTESTS_TESTS_EXPORT KMOpenMsgCommand : public KMCommand 0294 { 0295 Q_OBJECT 0296 0297 public: 0298 explicit KMOpenMsgCommand(QWidget *parent, const QUrl &url = QUrl(), const QString &encoding = QString(), KMMainWidget *main = nullptr); 0299 0300 private: 0301 [[nodiscard]] Result execute() override; 0302 0303 private Q_SLOTS: 0304 void slotDataArrived(KIO::Job *job, const QByteArray &data); 0305 void slotResult(KJob *job); 0306 0307 private: 0308 void doesNotContainMessage(); 0309 static const int MAX_CHUNK_SIZE = 64 * 1024; 0310 QUrl mUrl; 0311 QByteArray mMsgString; 0312 KIO::TransferJob *mJob = nullptr; 0313 const QString mEncoding; 0314 KMMainWidget *mMainWidget = nullptr; 0315 }; 0316 0317 class KMAILTESTS_TESTS_EXPORT KMSaveAttachmentsCommand : public KMCommand 0318 { 0319 Q_OBJECT 0320 public: 0321 /** Use this to save all attachments of the given message. 0322 @param parent The parent widget of the command used for message boxes. 0323 @param msg The message of which the attachments should be saved. 0324 @param viewer The message viewer. 0325 */ 0326 KMSaveAttachmentsCommand(QWidget *parent, const Akonadi::Item &msg, MessageViewer::Viewer *viewer); 0327 /** Use this to save all attachments of the given messages. 0328 @param parent The parent widget of the command used for message boxes. 0329 @param msgs The messages of which the attachments should be saved. 0330 */ 0331 KMSaveAttachmentsCommand(QWidget *parent, const Akonadi::Item::List &msgs, MessageViewer::Viewer *viewer); 0332 0333 private: 0334 Result execute() override; 0335 MessageViewer::Viewer *mViewer = nullptr; 0336 }; 0337 0338 class KMAILTESTS_TESTS_EXPORT KMDeleteAttachmentsCommand : public KMCommand 0339 { 0340 Q_OBJECT 0341 public: 0342 KMDeleteAttachmentsCommand(QWidget *parent, const Akonadi::Item::List &msgs); 0343 0344 private Q_SLOTS: 0345 void slotUpdateResult(KJob *job); 0346 void slotCanceled(); 0347 0348 private: 0349 [[nodiscard]] Result execute() override; 0350 void complete(KMCommand::Result result); 0351 0352 KPIM::ProgressItem *mProgressItem = nullptr; 0353 QList<KJob *> mRunningJobs; 0354 }; 0355 0356 class KMAILTESTS_TESTS_EXPORT KMReplyCommand : public KMCommand 0357 { 0358 Q_OBJECT 0359 public: 0360 KMReplyCommand(QWidget *parent, 0361 const Akonadi::Item &msg, 0362 MessageComposer::ReplyStrategy replyStrategy, 0363 const QString &selection = QString(), 0364 bool noquote = false, 0365 const QString &templateName = QString()); 0366 [[nodiscard]] bool replyAsHtml() const; 0367 void setReplyAsHtml(bool replyAsHtml); 0368 0369 private: 0370 [[nodiscard]] Result execute() override; 0371 0372 private: 0373 QString mSelection; 0374 QString mTemplate; 0375 MessageComposer::ReplyStrategy m_replyStrategy; 0376 bool mNoQuote = false; 0377 bool mReplyAsHtml = false; 0378 }; 0379 0380 class KMAILTESTS_TESTS_EXPORT KMForwardCommand : public KMCommand 0381 { 0382 Q_OBJECT 0383 0384 public: 0385 KMForwardCommand(QWidget *parent, 0386 const Akonadi::Item::List &msgList, 0387 uint identity = 0, 0388 const QString &templateName = QString(), 0389 const QString &selection = QString()); 0390 KMForwardCommand(QWidget *parent, 0391 const Akonadi::Item &msg, 0392 uint identity = 0, 0393 const QString &templateName = QString(), 0394 const QString &selection = QString()); 0395 0396 private: 0397 [[nodiscard]] KMCommand::Result createComposer(const Akonadi::Item &item); 0398 Result execute() override; 0399 0400 private: 0401 uint mIdentity; 0402 QString mTemplate; 0403 QString mSelection; 0404 }; 0405 0406 class KMAILTESTS_TESTS_EXPORT KMForwardAttachedCommand : public KMCommand 0407 { 0408 Q_OBJECT 0409 0410 public: 0411 KMForwardAttachedCommand(QWidget *parent, const Akonadi::Item::List &msgList, uint identity = 0, KMail::Composer *win = nullptr); 0412 KMForwardAttachedCommand(QWidget *parent, const Akonadi::Item &msg, uint identity = 0, KMail::Composer *win = nullptr); 0413 0414 private: 0415 Result execute() override; 0416 0417 uint mIdentity; 0418 QPointer<KMail::Composer> mWin; 0419 }; 0420 0421 class KMAILTESTS_TESTS_EXPORT KMRedirectCommand : public KMCommand 0422 { 0423 Q_OBJECT 0424 0425 public: 0426 KMRedirectCommand(QWidget *parent, const Akonadi::Item &msg); 0427 KMRedirectCommand(QWidget *parent, const Akonadi::Item::List &msgList); 0428 0429 private: 0430 [[nodiscard]] Result execute() override; 0431 }; 0432 0433 struct KMAILTESTS_TESTS_EXPORT KMPrintCommandInfo { 0434 Akonadi::Item mMsg; 0435 QFont mOverrideFont; 0436 QString mEncoding; 0437 MessageViewer::Viewer::DisplayFormatMessage mFormat = MessageViewer::Viewer::UseGlobalSetting; 0438 const MessageViewer::AttachmentStrategy *mAttachmentStrategy = nullptr; 0439 MessageViewer::HeaderStylePlugin *mHeaderStylePlugin = nullptr; 0440 bool mHtmlLoadExtOverride = false; 0441 bool mUseFixedFont = false; 0442 bool mPrintPreview = false; 0443 bool mShowSignatureDetails = false; 0444 bool mShowEncryptionDetails = false; 0445 }; 0446 0447 QDebug operator<<(QDebug d, const KMPrintCommandInfo &t); 0448 0449 class KMAILTESTS_TESTS_EXPORT KMPrintCommand : public KMCommand 0450 { 0451 Q_OBJECT 0452 0453 public: 0454 KMPrintCommand(QWidget *parent, const KMPrintCommandInfo &commandInfo); 0455 0456 private: 0457 [[nodiscard]] Result execute() override; 0458 0459 KMPrintCommandInfo mPrintCommandInfo; 0460 }; 0461 0462 class KMAILTESTS_TESTS_EXPORT KMSetStatusCommand : public KMCommand 0463 { 0464 Q_OBJECT 0465 0466 public: 0467 // Serial numbers 0468 KMSetStatusCommand(const MessageStatus &status, const Akonadi::Item::List &items, bool invert = false); 0469 0470 protected Q_SLOTS: 0471 void slotModifyItemDone(KJob *job); 0472 0473 private: 0474 [[nodiscard]] Result execute() override; 0475 MessageStatus mStatus; 0476 bool mInvertMark = false; 0477 }; 0478 0479 /** This command is used to set or toggle a tag for a list of messages. If toggle is 0480 true then the tag is deleted if it is already applied. 0481 */ 0482 class KMAILTESTS_TESTS_EXPORT KMSetTagCommand : public KMCommand 0483 { 0484 Q_OBJECT 0485 0486 public: 0487 enum SetTagMode { 0488 AddIfNotExisting, 0489 Toggle, 0490 CleanExistingAndAddNew, 0491 }; 0492 0493 KMSetTagCommand(const Akonadi::Tag::List &tags, const Akonadi::Item::List &item, SetTagMode mode = AddIfNotExisting); 0494 0495 protected Q_SLOTS: 0496 void slotModifyItemDone(KJob *job); 0497 0498 private: 0499 [[nodiscard]] Result execute() override; 0500 void setTags(); 0501 0502 Akonadi::Tag::List mTags; 0503 Akonadi::Tag::List mCreatedTags; 0504 Akonadi::Item::List mItem; 0505 SetTagMode mMode; 0506 }; 0507 0508 /* This command is used to apply a single filter (AKA ad-hoc filter) 0509 to a set of messages */ 0510 class KMAILTESTS_TESTS_EXPORT KMFilterActionCommand : public KMCommand 0511 { 0512 Q_OBJECT 0513 0514 public: 0515 KMFilterActionCommand(QWidget *parent, const QList<qlonglong> &msgListId, const QString &filterId); 0516 0517 private: 0518 [[nodiscard]] Result execute() override; 0519 QList<qlonglong> mMsgListId; 0520 QString mFilterId; 0521 }; 0522 0523 class KMAILTESTS_TESTS_EXPORT KMMetaFilterActionCommand : public QObject 0524 { 0525 Q_OBJECT 0526 0527 public: 0528 KMMetaFilterActionCommand(const QString &filterId, KMMainWidget *main); 0529 0530 public Q_SLOTS: 0531 void start(); 0532 0533 private: 0534 QString mFilterId; 0535 KMMainWidget *mMainWidget = nullptr; 0536 }; 0537 0538 class KMAILTESTS_TESTS_EXPORT KMMailingListFilterCommand : public KMCommand 0539 { 0540 Q_OBJECT 0541 0542 public: 0543 KMMailingListFilterCommand(QWidget *parent, const Akonadi::Item &msg); 0544 0545 private: 0546 [[nodiscard]] Result execute() override; 0547 }; 0548 0549 class KMAILTESTS_TESTS_EXPORT KMCopyCommand : public KMCommand 0550 { 0551 Q_OBJECT 0552 0553 public: 0554 KMCopyCommand(const Akonadi::Collection &destFolder, const Akonadi::Item::List &msgList); 0555 KMCopyCommand(const Akonadi::Collection &destFolder, const Akonadi::Item &msg); 0556 0557 protected Q_SLOTS: 0558 void slotCopyResult(KJob *job); 0559 0560 private: 0561 [[nodiscard]] Result execute() override; 0562 0563 Akonadi::Collection mDestFolder; 0564 }; 0565 0566 class KMAILTESTS_TESTS_EXPORT KMCopyDecryptedCommand : public KMCommand 0567 { 0568 Q_OBJECT 0569 public: 0570 KMCopyDecryptedCommand(const Akonadi::Collection &destFolder, const Akonadi::Item::List &msgList); 0571 KMCopyDecryptedCommand(const Akonadi::Collection &destFolder, const Akonadi::Item &msg); 0572 0573 protected Q_SLOTS: 0574 void slotAppendResult(KJob *job); 0575 0576 private: 0577 [[nodiscard]] Result execute() override; 0578 0579 Akonadi::Collection mDestFolder; 0580 QList<KJob *> mPendingJobs; 0581 }; 0582 0583 class KMAILTESTS_TESTS_EXPORT KMMoveCommand : public KMCommand 0584 { 0585 Q_OBJECT 0586 0587 public: 0588 KMMoveCommand(const Akonadi::Collection &destFolder, const Akonadi::Item::List &msgList, MessageList::Core::MessageItemSetReference ref); 0589 KMMoveCommand(const Akonadi::Collection &destFolder, 0590 const Akonadi::Item &msg, 0591 MessageList::Core::MessageItemSetReference ref = MessageList::Core::MessageItemSetReference()); 0592 [[nodiscard]] Akonadi::Collection destFolder() const 0593 { 0594 return mDestFolder; 0595 } 0596 0597 [[nodiscard]] MessageList::Core::MessageItemSetReference refSet() const 0598 { 0599 return mRef; 0600 } 0601 0602 public Q_SLOTS: 0603 void slotMoveCanceled(); 0604 void slotMoveResult(KJob *job); 0605 0606 protected: 0607 void setDestFolder(const Akonadi::Collection &folder) 0608 { 0609 mDestFolder = folder; 0610 } 0611 0612 Q_SIGNALS: 0613 void moveDone(KMMoveCommand *); 0614 0615 private: 0616 [[nodiscard]] Result execute() override; 0617 void completeMove(Result result); 0618 0619 Akonadi::Collection mDestFolder; 0620 KPIM::ProgressItem *mProgressItem = nullptr; 0621 MessageList::Core::MessageItemSetReference mRef; 0622 }; 0623 0624 class KMAILTESTS_TESTS_EXPORT KMTrashMsgCommand final : public KMCommand 0625 { 0626 Q_OBJECT 0627 0628 public: 0629 enum TrashOperation { 0630 Unknown, 0631 MoveToTrash, 0632 Delete, 0633 Both, 0634 }; 0635 0636 KMTrashMsgCommand(const Akonadi::Collection &srcFolder, const Akonadi::Item::List &msgList, MessageList::Core::MessageItemSetReference ref); 0637 KMTrashMsgCommand(const Akonadi::Collection &srcFolder, const Akonadi::Item &msg, MessageList::Core::MessageItemSetReference ref); 0638 [[nodiscard]] MessageList::Core::MessageItemSetReference refSet() const 0639 { 0640 return mRef; 0641 } 0642 0643 TrashOperation operation() const; 0644 0645 public Q_SLOTS: 0646 void slotMoveCanceled(); 0647 0648 private Q_SLOTS: 0649 void slotMoveResult(KJob *job); 0650 void slotDeleteResult(KJob *job); 0651 Q_SIGNALS: 0652 void moveDone(KMTrashMsgCommand *); 0653 0654 private: 0655 [[nodiscard]] Result execute() override; 0656 void completeMove(Result result); 0657 0658 [[nodiscard]] static Akonadi::Collection findTrashFolder(const Akonadi::Collection &srcFolder); 0659 0660 QMap<Akonadi::Collection, Akonadi::Item::List> mTrashFolders; 0661 KPIM::ProgressItem *mMoveProgress = nullptr; 0662 KPIM::ProgressItem *mDeleteProgress = nullptr; 0663 MessageList::Core::MessageItemSetReference mRef; 0664 QList<KJob *> mPendingMoves; 0665 QList<KJob *> mPendingDeletes; 0666 }; 0667 0668 class KMAILTESTS_TESTS_EXPORT KMResendMessageCommand : public KMCommand 0669 { 0670 Q_OBJECT 0671 0672 public: 0673 explicit KMResendMessageCommand(QWidget *parent, const Akonadi::Item &msg = Akonadi::Item()); 0674 0675 private: 0676 [[nodiscard]] Result execute() override; 0677 }; 0678 0679 class KMAILTESTS_TESTS_EXPORT KMShareImageCommand : public KMCommand 0680 { 0681 Q_OBJECT 0682 0683 public: 0684 explicit KMShareImageCommand(const QUrl &url, QWidget *parent); 0685 0686 private: 0687 [[nodiscard]] Result execute() override; 0688 QUrl mUrl; 0689 }; 0690 0691 class KMAILTESTS_TESTS_EXPORT KMFetchMessageCommand : public KMCommand 0692 { 0693 Q_OBJECT 0694 public: 0695 explicit KMFetchMessageCommand(QWidget *parent, const Akonadi::Item &item, MessageViewer::Viewer *viewer, KMReaderMainWin *win = nullptr); 0696 0697 [[nodiscard]] Akonadi::Item item() const; 0698 0699 KMReaderMainWin *readerMainWin() const; 0700 0701 private: 0702 Akonadi::ItemFetchJob *createFetchJob(const Akonadi::Item::List &items) override; 0703 [[nodiscard]] Result execute() override; 0704 0705 Akonadi::Item mItem; 0706 MessageViewer::Viewer *mViewer = nullptr; 0707 KMReaderMainWin *mReaderMainWin = nullptr; 0708 };