File indexing completed on 2025-03-09 04:54:44

0001 /*
0002   SPDX-FileCopyrightText: 1997 Markus Wuebben <markus.wuebben@kde.org>
0003   SPDX-FileCopyrightText: 2009 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.net
0004   SPDX-FileCopyrightText: 2009 Andras Mantia <andras@kdab.net>
0005 
0006   SPDX-License-Identifier: GPL-2.0-or-later
0007 */
0008 
0009 #pragma once
0010 
0011 #include "csshelper.h"
0012 #include "messageviewer/viewerplugininterface.h"
0013 #include "messageviewer_private_export.h"
0014 #include "viewer.h" //not so nice, it is actually for the enums from MailViewer
0015 #include "widgets/opensavedfilefolderwidget.h"
0016 #include <Akonadi/Item>
0017 #include <Akonadi/Monitor>
0018 #include <Akonadi/Session>
0019 #include <KMime/MDN>
0020 #include <KMime/Message>
0021 #include <KService>
0022 #include <MessageViewer/MDNWarningWidget>
0023 #include <PimCommon/ShareServiceUrlManager>
0024 #include <QList>
0025 #include <QPointer>
0026 #include <QStringDecoder>
0027 #include <QUrl>
0028 #include <WebEngineViewer/CheckPhishingUrlUtil>
0029 
0030 #include <QObject>
0031 #include <QTimer>
0032 namespace KIO
0033 {
0034 class Job;
0035 }
0036 
0037 class QAction;
0038 class KActionCollection;
0039 class KSelectAction;
0040 class KToggleAction;
0041 class QMenu;
0042 class KActionMenu;
0043 
0044 class QPoint;
0045 class QSplitter;
0046 class QModelIndex;
0047 class QVBoxLayout;
0048 
0049 namespace PimCommon
0050 {
0051 class PurposeMenuMessageWidget;
0052 }
0053 
0054 namespace KIdentityManagementCore
0055 {
0056 class IdentityManager;
0057 }
0058 
0059 namespace TextAddonsWidgets
0060 {
0061 class SlideContainer;
0062 }
0063 #ifdef HAVE_KTEXTADDONS_TEXT_TO_SPEECH_SUPPORT
0064 namespace TextEditTextToSpeech
0065 {
0066 class TextToSpeechContainerWidget;
0067 }
0068 #endif
0069 
0070 namespace MimeTreeParser
0071 {
0072 class ObjectTreeParser;
0073 class NodeHelper;
0074 }
0075 namespace MessageViewer
0076 {
0077 class DKIMWidgetInfo;
0078 class DKIMViewerMenu;
0079 }
0080 namespace WebEngineViewer
0081 {
0082 class WebHitTestResult;
0083 class FindBarWebEngineView;
0084 class ZoomActionMenu;
0085 class LocalDataBaseManager;
0086 class TrackingWarningWidget;
0087 class DeveloperToolDialog;
0088 class SubmittedFormWarningWidget;
0089 }
0090 namespace MessageViewer
0091 {
0092 class AttachmentStrategy;
0093 class HeaderStylePlugin;
0094 class HtmlWriter;
0095 class CSSHelper;
0096 class MessageViewerRenderer;
0097 class MailWebEngineView;
0098 class WebEnginePartHtmlWriter;
0099 class HtmlStatusBar;
0100 class ScamDetectionWarningWidget;
0101 class MimePartTreeView;
0102 class HeaderStyleMenuManager;
0103 class ViewerPluginToolManager;
0104 class MailSourceWebEngineViewer;
0105 class ShowNextMessageWidget;
0106 class RemoteContentMenu;
0107 class MDNWarningWidget;
0108 /**
0109 \brief Private class for the Viewer, the main widget in the messageviewer library.
0110 
0111 This class creates all subwidgets, like the MailWebView, the HtmlStatusBar and the FindBarMailWebView.
0112 
0113 Also, ViewerPrivate creates and exposes all actions.
0114 
0115 \par Displaying a message
0116 
0117 Before displaying a message, a message needs to be set. This can be done in two ways, with
0118 setMessageItem() and with setMessage(). setMessageItem() is the preferred way, as the viewer can
0119 then remember the Akonadi::Item belonging to the message. The Akonadi::Item is needed when modifying
0120 the message, for example when editing or deleting an attachment.
0121 Sometimes passing an Akonadi::Item to the viewer is not possible, for example when double-clicking
0122 an attached message, in which case a new KMime::Message is constructed out of the attachment, and a
0123 separate window is opened for it. In this case, the KMime::Message has no associated Akonadi::Item.
0124 If there is an Akonadi::Item available, it will be monitored for changes and the viewer
0125 automatically updated on external changes.
0126 
0127 Once a message is set, update() is called. update() can also be called after the message has already
0128 been displayed. As an example, this is the case when the user decides to decrypt the message. The
0129 decryption can happen async, and once the decryption is finished, update() is called to display the
0130 now decrypted content. See the documentation of MimeTreeParser::ObjectTreeParser on how exactly decryption is
0131 handled.
0132 update() is just a thin wrapper that calls updateReaderWin(). The only difference is that update()
0133 has a timer that prevents too many slow calls to updateReaderWin() in a short time frame.
0134 updateReaderWin() again is only a thin wrapper that resets some state and then calls
0135 displayMessage().
0136 displayMessage() itself is again a thin wrapper, which starts the HtmlWriter and then calls
0137 parseMsg().
0138 Finally, parseMsg() does the real work. It uses MimeTreeParser::ObjectTreeParser parseObjectTree() to let the
0139 MimeTreeParser::ObjectTreeParser parse the message and generate the HTML code for it.
0140 As mentioned before, it can happen that the MimeTreeParser::ObjectTreeParser needs to do some operation that happens
0141 async, for example decrypting. In this case, the MimeTreeParser::ObjectTreeParser will create a BodyPartMemento,
0142 which basically is a wrapper around the job that does the async operation. Once the async operation
0143 is finished. the BodyPartMemento will trigger an update() of ViewerPrivate, so that
0144 MimeTreeParser::ObjectTreeParser parseObjectTree() gets called again and the MimeTreeParser::ObjectTreeParser then can generate
0145 HTML which has the decrypted content of the message. Again, see the documentation of MimeTreeParser::ObjectTreeParser for the details.
0146 Additionally, parseMsg() does some evil hack for saving unencrypted messages should the config
0147 option for that be set.
0148 
0149 \par Displaying a MIME part of the message
0150 
0151 The viewer can show only a part of the message, for example by clicking on a MIME part in the
0152 message structure viewer or by double-clicking an attached message. In this case, setMessagePart()
0153 is called. There are two of these functions. One even has special handling for images, special
0154 handling for binary attachments and special handling of attached messages. In the last case, a new
0155 KMime::Message is constructed and set as the main message with setMessage().
0156 
0157 \par Attachment Handling
0158 
0159 Some of those actions are actions that operate on a single attachment. For those, there is usually
0160 a slot, like slotAttachmentCopy(). These actions are triggered from the attachment context menu,
0161 which is shown in showAttachmentPopup(). The actions are connected to slotHandleAttachment() when
0162 they are activated.
0163 The action to edit an attachment uses the EditorWatcher to detect when editing with an external
0164 editor is finished. Upon finishing, slotAttachmentEditDone() is called, which then creates an
0165 ItemModifyJob to store the changes of the attachment. A map of currently active EditorWatcher and
0166 their KMime::Content is available in mEditorWatchers.
0167 For most attachment actions, the attachment is first written to a temp file. The action is then
0168 executed on this temp file. Writing the attachment to a temp file is done with
0169 MimeTreeParser::NodeHelper::writeNodeToTempFile(). This method is called before opening or copying an attachment or
0170 when rendering the attachment list. The MimeTreeParser::ObjectTreeParser also calls MimeTreeParser::NodeHelper::writeNodeToTempFile()
0171 in some places. Once the temp file is written, MimeTreeParser::NodeHelper::tempFileUrlFromNode() can be used to get
0172 the file name of the temp file for a specific MIME part. This is for example used by the handler for
0173 'attachment:' URLs, AttachmentURLHandler.
0174 
0175 Since URLs for attachments are in the "attachment:" scheme, dragging them as-is to outside applications
0176 wouldn't work, since other applications don't understand this scheme. Therefore, the viewer has
0177 special handling for dragging URLs: In eventFilter(), drags are detected, and the URL handler is
0178 called to deal with the drag. The attachment URL handler then starts a drag with the file:// URL
0179 of the temp file of the attachment, which it gets with MimeTreeParser::NodeHelper::tempFileUrlFromNode().
0180 
0181 TODO: How are attachment handled that are loaded on demand? How does prepareHandleAttachment() work?
0182 TODO: This temp file handling is a big mess and could use a rewrite, especially in the face of load
0183       on demand. There shouldn't be the need to write out tempfiles until really needed.
0184 
0185 Some header styles display an attachment list in the header. The HTML code for the attachment list
0186 cannot be generated by the HeaderStyle itself, since that does not know about all attachments.
0187 Therefore, the attachment list needs to be created by ViewerPrivate. For this, the HeaderStyle
0188 writes out a placeholder for the attachment list when it creates the HTML for the header. Once the
0189 MimeTreeParser::ObjectTreeParser is finished with the message, injectAttachments() is called. injectAttachments()
0190 searches for the placeholder and replaces that with the real HTML code for the attachments.
0191 
0192 One of the attachment actions is to scroll to the attachment. That action is only available when
0193 right-clicking the header. The action scrolls to the attachment in the body and draws a yellow frame
0194 around the attachment. This is done in scrollToAttachment(). The attachment in the body and the div
0195 which is used for the colored frame are both created by the MimeTreeParser::ObjectTreeParser .
0196 
0197 \par Misc
0198 
0199 ViewerPrivate holds the MimeTreeParser::NodeHelper, which is passed on to the MimeTreeParser::ObjectTreeParser when it needs it.
0200 It also holds the HeaderStyle, HeaderStrategy, MimeTreeParser::AttachmentStrategy, CSSHelper, HtmlWriter and more,
0201 some of them again passed to the MimeTreeParser::ObjectTreeParser when it needs it.
0202 
0203 @author andras@kdab.net
0204  */
0205 class MESSAGEVIEWER_TESTS_EXPORT ViewerPrivate : public QObject
0206 {
0207     Q_OBJECT
0208 public:
0209     ViewerPrivate(Viewer *aParent, QWidget *mainWindow, KActionCollection *actionCollection);
0210 
0211     ~ViewerPrivate() override;
0212 
0213     /** Returns message part from given URL or null if invalid. The URL's path is a KMime::ContentIndex path, or an index for the extra nodes,
0214     followed by : and the ContentIndex path. */
0215     [[nodiscard]] KMime::Content *nodeFromUrl(const QUrl &url) const;
0216 
0217     /** Open the attachment pointed to the node.
0218      * @param node the node
0219      * @param url - if not empty, use this file to load the attachment content
0220      */
0221     void openAttachment(KMime::Content *node, const QUrl &url);
0222 
0223     /** Delete the attachment the @p node points to. Returns false if the user
0224     cancelled the deletion, true in all other cases (including failure to delete
0225     the attachment!)
0226     * @param node the node
0227     * @param showWarning whether some warning should be shown
0228     */
0229     [[nodiscard]] bool deleteAttachment(KMime::Content *node, bool showWarning = true);
0230 
0231     void attachmentProperties(KMime::Content *node);
0232     void attachmentCopy(const KMime::Content::List &contents);
0233 
0234     void scrollToAnchor(const QString &anchor);
0235 
0236     void showAttachmentPopup(KMime::Content *node, const QString &name, const QPoint &p);
0237 
0238     /**
0239      * Sets the current attachment ID and the current attachment temporary filename
0240      * to the given values.
0241      * Call this so that slotHandleAttachment() knows which attachment to handle.
0242      */
0243     void prepareHandleAttachment(KMime::Content *node);
0244 
0245     [[nodiscard]] KService::Ptr getServiceOffer(KMime::Content *content);
0246     [[nodiscard]] KMime::Content::List selectedContents() const;
0247     void attachmentOpenWith(KMime::Content *node, const KService::Ptr &offer = KService::Ptr());
0248     void attachmentOpen(KMime::Content *node);
0249 
0250     /** Return the HtmlWriter connected to the MailWebView we use */
0251     HtmlWriter *htmlWriter() const;
0252 
0253     HeaderStylePlugin *headerStylePlugin() const;
0254 
0255     CSSHelper *cssHelper() const;
0256 
0257     MimeTreeParser::NodeHelper *nodeHelper() const;
0258 
0259     Viewer *viewer() const;
0260 
0261     [[nodiscard]] Akonadi::Item messageItem() const;
0262 
0263     [[nodiscard]] KMime::Message::Ptr message() const;
0264 
0265     /** Returns whether the message should be decrypted. */
0266     [[nodiscard]] bool decryptMessage() const;
0267 
0268     /** Display a generic HTML splash page instead of a message. */
0269     void displaySplashPage(const QString &templateName, const QVariantHash &data, const QByteArray &domain = QByteArray());
0270 
0271     void displaySplashPage(const QString &message);
0272 
0273     /** Enable the displaying of messages again after an splash (or other) page was displayed */
0274     void enableMessageDisplay();
0275 
0276     /** Feeds the HTML viewer with the contents of the given message.
0277     HTML begin/end parts are written around the message. */
0278     void displayMessage();
0279 
0280     /** Parse the given content and generate HTML out of it for display */
0281     void parseContent(KMime::Content *content);
0282 
0283     /** Creates a nice mail header depending on the current selected
0284     header style. */
0285     [[nodiscard]] QString writeMessageHeader(KMime::Message *aMsg, KMime::Content *vCardNode, bool topLevel);
0286 
0287     void saveMainFrameScreenshotInFile(const QString &filename);
0288 
0289     void exportToPdf(const QString &fileName);
0290 
0291 private:
0292     /** HTML initialization. */
0293     void initHtmlWidget();
0294     void createOpenWithMenu(QMenu *topMenu, const QString &contentTypeStr, bool fromCurrentContent);
0295 
0296 public:
0297     void updatePalette();
0298 
0299     void itemFetchResult(KJob *job);
0300 
0301     /** Read settings from app's config file. */
0302     void readConfig();
0303 
0304     /** Write settings to app's config file. Calls sync() if withSync is true. */
0305     void writeConfig(bool withSync = true);
0306 
0307     /** Get/set the message attachment strategy. */
0308     const AttachmentStrategy *attachmentStrategy() const;
0309     void setAttachmentStrategy(const AttachmentStrategy *strategy);
0310 
0311     /** Get selected override character encoding.
0312       @return The encoding selected by the user or an empty string if auto-detection
0313       is selected. */
0314     [[nodiscard]] QString overrideEncoding() const;
0315 
0316     /** Set the override character encoding. */
0317     void setOverrideEncoding(const QString &encoding);
0318 
0319     /** Set printing mode */
0320     void setPrinting(bool enable);
0321     [[nodiscard]] bool printingMode() const;
0322 
0323     /** Print message. */
0324     void printMessage(const Akonadi::Item &msg);
0325     void printPreviewMessage(const Akonadi::Item &message);
0326 
0327     void resetStateForNewMessage();
0328 
0329     void setMessageInternal(const KMime::Message::Ptr &message, MimeTreeParser::UpdateMode updateMode);
0330 
0331     /** Set the Akonadi item that will be displayed.
0332      *  @param item - the Akonadi item to be displayed. If it doesn't hold a mail (KMime::Message::Ptr as payload data),
0333      *                an empty page is shown.
0334      *  @param updateMode - update the display immediately or not. See MailViewer::UpdateMode.
0335      */
0336     void setMessageItem(const Akonadi::Item &item, MimeTreeParser::UpdateMode updateMode = MimeTreeParser::Delayed, bool forceHtmlLoadExtOverride = false);
0337 
0338     /** Set the message that shall be shown.
0339      * @param msg - the message to be shown. If 0, an empty page is displayed.
0340      * @param updateMode - update the display immediately or not. See MailViewer::UpdateMode.
0341      */
0342     void setMessage(const KMime::Message::Ptr &msg, MimeTreeParser::UpdateMode updateMode = MimeTreeParser::Delayed);
0343 
0344     /** Instead of settings a message to be shown sets a message part
0345       to be shown */
0346     void setMessagePart(KMime::Content *node);
0347 
0348     /** Show or hide the Mime Tree Viewer if configuration
0349       is set to smart mode.  */
0350     void showHideMimeTree();
0351 
0352     /** View message part of type message/RFC822 in extra viewer window. */
0353     void attachmentViewMessage(const KMime::Message::Ptr &message);
0354 
0355     void adjustLayout();
0356     void createWidgets();
0357     void createActions();
0358 
0359     void showContextMenu(KMime::Content *content, const QPoint &point);
0360 
0361     KToggleAction *actionForAttachmentStrategy(const AttachmentStrategy *);
0362     /** Read override codec from configuration */
0363     void readGlobalOverrideCodec();
0364 
0365     /** Get codec corresponding to the currently selected override character encoding.
0366       @return The override codec or 0 if auto-detection is selected. */
0367     [[nodiscard]] QByteArray overrideCodecName() const;
0368 
0369     [[nodiscard]] QString renderAttachments(KMime::Content *node, const QColor &bgColor) const;
0370 
0371     KMime::Content *findContentByType(KMime::Content *content, const QByteArray &type); // TODO(Andras) move to MimeTreeParser::NodeHelper
0372 
0373     /** Saves the relative position of the scroll view. Call this before calling update()
0374       if you want to preserve the current view. */
0375     void saveRelativePosition();
0376 
0377     [[nodiscard]] bool htmlMail() const;
0378     [[nodiscard]] bool htmlLoadExternal() const;
0379 
0380     [[nodiscard]] bool htmlMailGlobalSetting() const;
0381 
0382     /** Get the html override setting */
0383     [[nodiscard]] Viewer::DisplayFormatMessage displayFormatMessageOverwrite() const;
0384 
0385     /** Override default html mail setting */
0386     void setDisplayFormatMessageOverwrite(Viewer::DisplayFormatMessage format);
0387 
0388     /** Get the load external references override setting */
0389     [[nodiscard]] bool htmlLoadExtOverride() const;
0390 
0391     /** Default behavior for loading external references.
0392      *  Use this for specifying the external reference loading behavior as
0393      *  specified in the user settings.
0394      *  @see setHtmlLoadExtOverride
0395      */
0396     void setHtmlLoadExtDefault(bool loadExtDefault);
0397 
0398     /** Override default load external references setting
0399      *  @warning This must only be called when the user has explicitly
0400      *  been asked to retrieve external references!
0401      *  @see setHtmlLoadExtDefault
0402      */
0403     void setHtmlLoadExtOverride(bool loadExtOverride);
0404 
0405     /** Enforce message decryption. */
0406     void setDecryptMessageOverwrite(bool overwrite = true);
0407 
0408     /** Show signature details. */
0409     [[nodiscard]] bool showSignatureDetails() const;
0410 
0411     /** Show signature details. */
0412     void setShowSignatureDetails(bool showDetails = true);
0413 
0414     /* show or hide encryption details */
0415     void setShowEncryptionDetails(bool showEncDetails);
0416 
0417     [[nodiscard]] bool showEncryptionDetails() const;
0418 
0419     void scrollToAttachment(KMime::Content *node);
0420     void setUseFixedFont(bool useFixedFont);
0421 
0422     void attachmentView(KMime::Content *atmNode);
0423 
0424     void setZoomFactor(qreal zoomFactor);
0425 
0426     void goOnline();
0427     void goResourceOnline();
0428 
0429     void showSavedFileFolderWidget(const QList<QUrl> &urls, MessageViewer::OpenSavedFileFolderWidget::FileType fileType);
0430 
0431     [[nodiscard]] bool mimePartTreeIsEmpty() const;
0432 
0433     void setPluginName(const QString &pluginName);
0434 
0435     [[nodiscard]] QList<QAction *> viewerPluginActionList(MessageViewer::ViewerPluginInterface::SpecificFeatureTypes features);
0436     [[nodiscard]] QList<QAction *> interceptorUrlActions(const WebEngineViewer::WebHitTestResult &result) const;
0437 
0438     void setPrintElementBackground(bool printElementBackground);
0439     [[nodiscard]] bool showEmoticons() const;
0440     void checkPhishingUrl();
0441     void executeRunner(const QUrl &url);
0442     [[nodiscard]] QUrl imageUrl() const;
0443     [[nodiscard]] qreal webViewZoomFactor() const;
0444     void setWebViewZoomFactor(qreal factor);
0445     void recreateCssHelper();
0446     void hasMultiMessages(bool messages);
0447     void updateShowMultiMessagesButton(bool enablePreviousButton, bool enableNextButton);
0448     MessageViewer::DKIMViewerMenu *dkimViewerMenu();
0449 
0450     [[nodiscard]] bool isAutocryptEnabled(KMime::Message *message);
0451     void setIdentityManager(KIdentityManagementCore::IdentityManager *ident);
0452     void setFolderIdentity(uint folderIdentity);
0453 
0454     [[nodiscard]] RemoteContentMenu *remoteContentMenu() const;
0455     void showMdnInformations(const QPair<QString, bool> &mdnInfo);
0456     void mdnWarningAnimatedHide();
0457 
0458 private Q_SLOTS:
0459     void slotActivatePlugin(MessageViewer::ViewerPluginInterface *interface);
0460     void slotModifyItemDone(KJob *job);
0461     void slotMessageMayBeAScam();
0462     void slotMessageIsNotAScam();
0463     void slotAddToWhiteList();
0464     void slotItemChanged(const Akonadi::Item &item, const QSet<QByteArray> &partIdentifiers);
0465     void slotItemMoved(const Akonadi::Item &, const Akonadi::Collection &, const Akonadi::Collection &);
0466 
0467     void itemModifiedResult(KJob *job);
0468 
0469     void slotClear();
0470 
0471     void slotMessageRendered();
0472 
0473     void slotOpenWithAction(QAction *act);
0474 
0475     void slotOpenWithActionCurrentContent(QAction *act);
0476 
0477     void slotOpenWithDialog();
0478 
0479     void slotOpenWithDialogCurrentContent();
0480 
0481     void saveSplitterSizes() const;
0482 
0483     void slotRefreshMessage(const Akonadi::Item &item);
0484     void slotServiceUrlSelected(PimCommon::ShareServiceUrlManager::ServiceType serviceType);
0485     void slotStyleChanged(MessageViewer::HeaderStylePlugin *plugin);
0486     void slotStyleUpdated();
0487     void slotWheelZoomChanged(int numSteps);
0488     void slotOpenInBrowser();
0489     void slotExportHtmlPageFailed();
0490     void slotExportHtmlPageSuccess(const QString &filename);
0491     void slotToggleEmoticons();
0492 
0493 public Q_SLOTS:
0494     /** An URL has been activate with a click. */
0495     void slotUrlOpen(const QUrl &url = QUrl());
0496     void slotOpenUrl();
0497 
0498     /** The mouse has moved on or off an URL. */
0499     void slotUrlOn(const QString &link);
0500 
0501     /** The user presses the right mouse button on an URL. */
0502     void slotUrlPopup(const WebEngineViewer::WebHitTestResult &result);
0503 
0504     /** The user selected "Find" from the menu. */
0505     void slotFind();
0506 
0507     /** The user toggled the "Fixed Font" flag from the view menu. */
0508     void slotToggleFixedFont();
0509     void slotToggleMimePartTree();
0510 
0511     /** Show the message source */
0512     void slotShowMessageSource();
0513 
0514     /** Refresh the reader window */
0515     void updateReaderWin();
0516 
0517     void slotMimePartSelected(const QModelIndex &index);
0518 
0519     void slotIconicAttachments();
0520     void slotSmartAttachments();
0521     void slotInlineAttachments();
0522     void slotHideAttachments();
0523     void slotHeaderOnlyAttachments();
0524 
0525     /** Some attachment operations. */
0526     void slotDelayedResize();
0527 
0528     /** Print message. Called on as a response of finished() signal of mPartHtmlWriter
0529       after rendering is finished.
0530       In the very end it deletes the KMReaderWin window that was created
0531       for the purpose of rendering. */
0532     void slotPrintMessage();
0533     void slotPrintPreview();
0534 
0535     void slotSetEncoding();
0536     void executeCustomScriptsAfterLoading();
0537     void slotSettingsChanged();
0538     void slotMimeTreeContextMenuRequested(const QPoint &pos);
0539     void slotAttachmentOpenWith();
0540     void slotAttachmentOpen();
0541     void slotAttachmentSaveAs();
0542     void slotAttachmentSaveAll();
0543     void slotAttachmentView();
0544     void slotAttachmentProperties();
0545     void slotAttachmentCopy();
0546     void slotAttachmentDelete();
0547     void slotLevelQuote(int l);
0548 
0549     /** Toggle display mode between HTML and plain text. */
0550     void slotToggleHtmlMode();
0551     void slotLoadExternalReference();
0552 
0553     /**
0554      * Does an action for the current attachment.
0555      * The action is defined by the KMHandleAttachmentCommand::AttachmentAction
0556      * enum.
0557      * prepareHandleAttachment() needs to be called before calling this to set the
0558      * correct attachment ID.
0559      */
0560     void slotHandleAttachment(int action);
0561     /** Copy the selected text to the clipboard */
0562     void slotCopySelectedText();
0563 
0564     void viewerSelectionChanged();
0565 
0566     /** Select message body. */
0567     void selectAll();
0568 
0569     /** Copy URL in mUrlCurrent to clipboard. Removes "mailto:" at
0570       beginning of URL before copying. */
0571     void slotUrlCopy();
0572     void slotSaveMessage();
0573     /** Re-parse the current message. */
0574     void update(MimeTreeParser::UpdateMode updateMode = MimeTreeParser::Delayed);
0575 
0576     void slotSpeakText();
0577     void slotCopyImageLocation();
0578     void slotSaveMessageDisplayFormat();
0579     void slotResetMessageDisplayFormat();
0580 
0581     void slotGeneralFontChanged();
0582     void slotShowDevelopmentTools();
0583 
0584 Q_SIGNALS:
0585     void showStatusBarMessage(const QString &message);
0586     void popupMenu(const Akonadi::Item &msg, const QUrl &url, const QUrl &imageUrl, const QPoint &mousePos);
0587     void displayPopupMenu(const Akonadi::Item &msg, const WebEngineViewer::WebHitTestResult &result, const QPoint &mousePos);
0588 
0589     void urlClicked(const Akonadi::Item &msg, const QUrl &url);
0590     void requestConfigSync();
0591     void showReader(KMime::Content *aMsgPart, bool aHTML, const QString &encoding);
0592     void showMessage(const KMime::Message::Ptr &message, const QString &encoding);
0593     void replyMessageTo(const KMime::Message::Ptr &message, bool replyToAll);
0594     void itemRemoved();
0595     void makeResourceOnline(MessageViewer::Viewer::ResourceOnlineMode mode);
0596 
0597     void changeDisplayMail(Viewer::DisplayFormatMessage, bool);
0598     void moveMessageToTrash();
0599     void pageIsScrolledToBottom(bool);
0600     void printingFinished();
0601     void zoomChanged(qreal zoomFactor);
0602     void showNextMessage();
0603     void showPreviousMessage();
0604     void sendResponse(MessageViewer::MDNWarningWidget::ResponseType type, KMime::MDN::SendingMode sendingMode);
0605 
0606 private:
0607     [[nodiscard]] QString attachmentHtml();
0608     void initializeColorFromScheme();
0609 
0610     void replyMessageToAuthor(KMime::Content *atmNode);
0611     void replyMessageToAll(KMime::Content *atmNode);
0612     void replyMessage(KMime::Content *atmNode, bool replyToAll);
0613     [[nodiscard]] bool urlIsAMalwareButContinue();
0614     [[nodiscard]] bool messageIsInSpecialFolder() const;
0615 
0616     void slotCheckedUrlFinished(const QUrl &url, WebEngineViewer::CheckPhishingUrlUtil::UrlStatus status);
0617 
0618     void adaptHtmlHeadSettings();
0619     void slotDelayPrintPreview();
0620     void applyZoomValue(qreal factor, bool saveConfig = true);
0621     void slotZoomChanged(qreal zoom);
0622     void assignMessageItem(const Akonadi::Item &item);
0623     void slotUrlBlocked(const QUrl &url);
0624     void updateColorFromScheme();
0625     void updateMessageAfterDeletingAttachments(KMime::Message::Ptr &message);
0626     void createSubmittedFormWarning();
0627     void createPurposeMenuMessageWidget();
0628     void createOpenSavedFileFolderWidget();
0629     void createTrackingWarningWidget();
0630     void createShowNextMessageWidget();
0631     void createMdnWarningWidget();
0632     void createScamDetectionWarningWidget();
0633 
0634     MimeTreeParser::NodeHelper *mNodeHelper = nullptr;
0635     bool mHtmlMailGlobalSetting = false;
0636     bool mHtmlLoadExternalDefaultSetting = false;
0637     bool mHtmlLoadExtOverride = false;
0638 
0639 public:
0640     KMime::Message::Ptr mMessage; // the current message, if it was set manually
0641     Akonadi::Item mMessageItem; // the message item from Akonadi
0642     // widgets:
0643     QSplitter *mSplitter = nullptr;
0644     QWidget *mBox = nullptr;
0645     HtmlStatusBar *mColorBar = nullptr;
0646     MimePartTreeView *mMimePartTree = nullptr;
0647     MailWebEngineView *mViewer = nullptr;
0648     WebEngineViewer::FindBarWebEngineView *mFindBar = nullptr;
0649 
0650     const AttachmentStrategy *mAttachmentStrategy = nullptr;
0651     QTimer mUpdateReaderWinTimer;
0652     QTimer mResizeTimer;
0653     QString mOverrideEncoding;
0654     QString mOldGlobalOverrideEncoding; // used to detect changes of the global override character encoding
0655 
0656     /// This is true if the viewer currently is displaying a message. Can be false, for example when
0657     /// the splash/busy page is displayed.
0658     bool mMsgDisplay = true;
0659 
0660     CSSHelperBase::HtmlHeadSettings mHtmlHeadSettings;
0661     bool mPrinting = false;
0662     QWidget *mMainWindow = nullptr;
0663     KActionCollection *const mActionCollection;
0664     QAction *mCopyAction = nullptr;
0665     QAction *mCopyURLAction = nullptr;
0666     QAction *mUrlOpenAction = nullptr;
0667     QAction *mSelectAllAction = nullptr;
0668     QAction *mScrollUpAction = nullptr;
0669     QAction *mScrollDownAction = nullptr;
0670     QAction *mScrollUpMoreAction = nullptr;
0671     QAction *mScrollDownMoreAction = nullptr;
0672     QAction *mViewSourceAction = nullptr;
0673     QAction *mSaveMessageAction = nullptr;
0674     QAction *mFindInMessageAction = nullptr;
0675     QAction *mSaveMessageDisplayFormat = nullptr;
0676     QAction *mResetMessageDisplayFormat = nullptr;
0677     KToggleAction *mDisableEmoticonAction = nullptr;
0678     KToggleAction *mHeaderOnlyAttachmentsAction = nullptr;
0679     KSelectAction *mSelectEncodingAction = nullptr;
0680     KToggleAction *mToggleFixFontAction = nullptr;
0681     KToggleAction *mToggleDisplayModeAction = nullptr;
0682     KToggleAction *mToggleMimePartTreeAction = nullptr;
0683     QAction *mDevelopmentToolsAction = nullptr;
0684     QAction *mSpeakTextAction = nullptr;
0685     QAction *mCopyImageLocation = nullptr;
0686     QAction *mShareTextAction = nullptr;
0687     QUrl mClickedUrl;
0688     QUrl mImageUrl;
0689     HtmlWriter *mHtmlWriter = nullptr;
0690     /** Used only to be able to connect and disconnect finished() signal
0691       in printMsg() and slotPrintMsg() since mHtmlWriter points only to abstract non-QObject class. */
0692     QPointer<WebEnginePartHtmlWriter> mPartHtmlWriter;
0693     QPointer<WebEngineViewer::DeveloperToolDialog> mDeveloperToolDialog;
0694 
0695     int mLevelQuote;
0696     bool mDecrytMessageOverwrite = false;
0697     bool mShowSignatureDetails = false;
0698     bool mShowEncryptionDetails = false;
0699     bool mForceEmoticons = true;
0700     int mRecursionCountForDisplayMessage = 0;
0701     uint mFolderIdentity = 0;
0702     KMime::Content *mCurrentContent = nullptr;
0703     KMime::Content *mMessagePartNode = nullptr;
0704     QString mMessagePath;
0705 
0706     QColor mForegroundError;
0707     QColor mBackgroundError;
0708     QColor mBackgroundAttachment;
0709 
0710     Viewer *const q;
0711     Akonadi::Session *mSession = nullptr;
0712     Akonadi::Monitor mMonitor;
0713     QSet<AbstractMessageLoadedHandler *> mMessageLoadedHandlers;
0714     Akonadi::Item::Id mPreviouslyViewedItemId = -1;
0715 
0716     MessageViewer::ScamDetectionWarningWidget *mScamDetectionWarning = nullptr;
0717     MessageViewer::OpenSavedFileFolderWidget *mOpenSavedFileFolderWidget = nullptr;
0718     WebEngineViewer::SubmittedFormWarningWidget *mSubmittedFormWarning = nullptr;
0719     WebEngineViewer::TrackingWarningWidget *mMailTrackingWarning = nullptr;
0720 #ifdef HAVE_KTEXTADDONS_TEXT_TO_SPEECH_SUPPORT
0721     TextEditTextToSpeech::TextToSpeechContainerWidget *mTextToSpeechContainerWidget = nullptr;
0722 #endif
0723     Viewer::DisplayFormatMessage mDisplayFormatMessageOverwrite;
0724     TextAddonsWidgets::SlideContainer *mSliderContainer = nullptr;
0725     PimCommon::ShareServiceUrlManager *mShareServiceManager = nullptr;
0726     KActionMenu *mShareServiceUrlMenu = nullptr;
0727     MessageViewer::HeaderStylePlugin *mHeaderStylePlugin = nullptr;
0728     MessageViewer::HeaderStyleMenuManager *mHeaderStyleMenuManager = nullptr;
0729     MessageViewer::ViewerPluginToolManager *mViewerPluginToolManager = nullptr;
0730     WebEngineViewer::ZoomActionMenu *mZoomActionMenu = nullptr;
0731     QList<QPointer<MessageViewer::MailSourceWebEngineViewer>> mListMailSourceViewer;
0732     WebEngineViewer::LocalDataBaseManager *mPhishingDatabase = nullptr;
0733     MessageViewer::ShowNextMessageWidget *mShowNextMessageWidget = nullptr;
0734     MessageViewer::DKIMWidgetInfo *mDkimWidgetInfo = nullptr;
0735     MessageViewer::DKIMViewerMenu *mDkimViewerMenu = nullptr;
0736     MessageViewer::MessageViewerRenderer *mMessageViewerRenderer = nullptr;
0737     KIdentityManagementCore::IdentityManager *mIdentityManager = nullptr;
0738     RemoteContentMenu *mRemoteContentMenu = nullptr;
0739     MessageViewer::MDNWarningWidget *mMdnWarning = nullptr;
0740     PimCommon::PurposeMenuMessageWidget *mPurposeMenuMessageWidget = nullptr;
0741     QVBoxLayout *mReaderBoxVBoxLayout = nullptr;
0742     QWidget *mReaderBox = nullptr;
0743 };
0744 }