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 };