1 /*
2   SPDX-FileCopyrightText: 1997 Markus Wuebben <markus.wuebben@kde.org>
3   SPDX-FileCopyrightText: 2009 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.net
4   SPDX-FileCopyrightText: 2009 Andras Mantia <andras@kdab.net>
5 
6   SPDX-License-Identifier: GPL-2.0-or-later
7 */
8 
9 #pragma once
10 
11 #include "config-messageviewer.h"
12 #include "messageviewer/viewerplugininterface.h"
13 #include "messageviewer_private_export.h"
14 #include "viewer.h" //not so nice, it is actually for the enums from MailViewer
15 #include "widgets/opensavedfilefolderwidget.h"
16 #include <PimCommon/ShareServiceUrlManager>
17 #include <WebEngineViewer/CheckPhishingUrlUtil>
18 
19 #include <Akonadi/Item>
20 #include <Akonadi/Monitor>
21 #include <Akonadi/Session>
22 #include <KIO/Job>
23 #include <KMime/Message>
24 #include <KService>
25 #include <QPointer>
26 #include <QUrl>
27 #include <QVector>
28 
29 #include <QObject>
30 #include <QTimer>
31 
32 namespace KIO
33 {
34 class Job;
35 }
36 
37 class QAction;
38 class KActionCollection;
39 class KSelectAction;
40 class KToggleAction;
41 class QMenu;
42 class KActionMenu;
43 
44 class QPoint;
45 class QSplitter;
46 class QModelIndex;
47 class QPrinter;
48 
49 namespace KIdentityManagement
50 {
51 class IdentityManager;
52 }
53 
54 namespace KPIMTextEdit
55 {
56 class SlideContainer;
57 class TextToSpeechWidget;
58 }
59 
60 namespace MimeTreeParser
61 {
62 class ObjectTreeParser;
63 class NodeHelper;
64 }
65 namespace MessageViewer
66 {
67 class DKIMWidgetInfo;
68 class DKIMViewerMenu;
69 }
70 namespace WebEngineViewer
71 {
72 class WebHitTestResult;
73 class FindBarWebEngineView;
74 class ZoomActionMenu;
75 class LocalDataBaseManager;
76 class TrackingWarningWidget;
77 class DeveloperToolDialog;
78 class SubmittedFormWarningWidget;
79 }
80 namespace MessageViewer
81 {
82 class AttachmentStrategy;
83 class HeaderStylePlugin;
84 class HtmlWriter;
85 class CSSHelper;
86 class MessageViewerRenderer;
87 class MailWebEngineView;
88 class WebEnginePartHtmlWriter;
89 class HtmlStatusBar;
90 class ScamDetectionWarningWidget;
91 class MimePartTreeView;
92 class HeaderStyleMenuManager;
93 class ViewerPluginToolManager;
94 class MailSourceWebEngineViewer;
95 class ShowNextMessageWidget;
96 class RemoteContentMenu;
97 /**
98 \brief Private class for the Viewer, the main widget in the messageviewer library.
99 
100 This class creates all subwidgets, like the MailWebView, the HtmlStatusBar and the FindBarMailWebView.
101 
102 Also, ViewerPrivate creates and exposes all actions.
103 
104 \par Displaying a message
105 
106 Before displaying a message, a message needs to be set. This can be done in two ways, with
107 setMessageItem() and with setMessage(). setMessageItem() is the preferred way, as the viewer can
108 then remember the Akonadi::Item belonging to the message. The Akonadi::Item is needed when modifying
109 the message, for example when editing or deleting an attachment.
110 Sometimes passing an Akonadi::Item to the viewer is not possible, for example when double-clicking
111 an attached message, in which case a new KMime::Message is constructed out of the attachment, and a
112 separate window is opened for it. In this case, the KMime::Message has no associated Akonadi::Item.
113 If there is an Akonadi::Item available, it will be monitored for changes and the viewer
114 automatically updated on external changes.
115 
116 Once a message is set, update() is called. update() can also be called after the message has already
117 been displayed. As an example, this is the case when the user decides to decrypt the message. The
118 decryption can happen async, and once the decryption is finished, update() is called to display the
119 now decrypted content. See the documentation of MimeTreeParser::ObjectTreeParser on how exactly decryption is
120 handled.
121 update() is just a thin wrapper that calls updateReaderWin(). The only difference is that update()
122 has a timer that prevents too many slow calls to updateReaderWin() in a short time frame.
123 updateReaderWin() again is only a thin wrapper that resets some state and then calls
124 displayMessage().
125 displayMessage() itself is again a thin wrapper, which starts the HtmlWriter and then calls
126 parseMsg().
127 Finally, parseMsg() does the real work. It uses MimeTreeParser::ObjectTreeParser parseObjectTree() to let the
128 MimeTreeParser::ObjectTreeParser parse the message and generate the HTML code for it.
129 As mentioned before, it can happen that the MimeTreeParser::ObjectTreeParser needs to do some operation that happens
130 async, for example decrypting. In this case, the MimeTreeParser::ObjectTreeParser will create a BodyPartMemento,
131 which basically is a wrapper around the job that does the async operation. Once the async operation
132 is finished. the BodyPartMemento will trigger an update() of ViewerPrivate, so that
133 MimeTreeParser::ObjectTreeParser parseObjectTree() gets called again and the MimeTreeParser::ObjectTreeParser then can generate
134 HTML which has the decrypted content of the message. Again, see the documentation of MimeTreeParser::ObjectTreeParser for the details.
135 Additionally, parseMsg() does some evil hack for saving unencrypted messages should the config
136 option for that be set.
137 
138 \par Displaying a MIME part of the message
139 
140 The viewer can show only a part of the message, for example by clicking on a MIME part in the
141 message structure viewer or by double-clicking an attached message. In this case, setMessagePart()
142 is called. There are two of these functions. One even has special handling for images, special
143 handling for binary attachments and special handling of attached messages. In the last case, a new
144 KMime::Message is constructed and set as the main message with setMessage().
145 
146 \par Attachment Handling
147 
148 Some of those actions are actions that operate on a single attachment. For those, there is usually
149 a slot, like slotAttachmentCopy(). These actions are triggered from the attachment context menu,
150 which is shown in showAttachmentPopup(). The actions are connected to slotHandleAttachment() when
151 they are activated.
152 The action to edit an attachment uses the EditorWatcher to detect when editing with an external
153 editor is finished. Upon finishing, slotAttachmentEditDone() is called, which then creates an
154 ItemModifyJob to store the changes of the attachment. A map of currently active EditorWatcher and
155 their KMime::Content is available in mEditorWatchers.
156 For most attachment actions, the attachment is first written to a temp file. The action is then
157 executed on this temp file. Writing the attachment to a temp file is done with
158 MimeTreeParser::NodeHelper::writeNodeToTempFile(). This method is called before opening or copying an attachment or
159 when rendering the attachment list. The MimeTreeParser::ObjectTreeParser also calls MimeTreeParser::NodeHelper::writeNodeToTempFile()
160 in some places. Once the temp file is written, MimeTreeParser::NodeHelper::tempFileUrlFromNode() can be used to get
161 the file name of the temp file for a specific MIME part. This is for example used by the handler for
162 'attachment:' URLs, AttachmentURLHandler.
163 
164 Since URLs for attachments are in the "attachment:" scheme, dragging them as-is to outside applications
165 wouldn't work, since other applications don't understand this scheme. Therefore, the viewer has
166 special handling for dragging URLs: In eventFilter(), drags are detected, and the URL handler is
167 called to deal with the drag. The attachment URL handler then starts a drag with the file:// URL
168 of the temp file of the attachment, which it gets with MimeTreeParser::NodeHelper::tempFileUrlFromNode().
169 
170 TODO: How are attachment handled that are loaded on demand? How does prepareHandleAttachment() work?
171 TODO: This temp file handling is a big mess and could use a rewrite, especially in the face of load
172       on demand. There shouldn't be the need to write out tempfiles until really needed.
173 
174 Some header styles display an attachment list in the header. The HTML code for the attachment list
175 cannot be generated by the HeaderStyle itself, since that does not know about all attachments.
176 Therefore, the attachment list needs to be created by ViewerPrivate. For this, the HeaderStyle
177 writes out a placeholder for the attachment list when it creates the HTML for the header. Once the
178 MimeTreeParser::ObjectTreeParser is finished with the message, injectAttachments() is called. injectAttachments()
179 searches for the placeholder and replaces that with the real HTML code for the attachments.
180 
181 One of the attachment actions is to scroll to the attachment. That action is only available when
182 right-clicking the header. The action scrolls to the attachment in the body and draws a yellow frame
183 around the attachment. This is done in scrollToAttachment(). The attachment in the body and the div
184 which is used for the colored frame are both created by the MimeTreeParser::ObjectTreeParser .
185 
186 \par Misc
187 
188 ViewerPrivate holds the MimeTreeParser::NodeHelper, which is passed on to the MimeTreeParser::ObjectTreeParser when it needs it.
189 It also holds the HeaderStyle, HeaderStrategy, MimeTreeParser::AttachmentStrategy, CSSHelper, HtmlWriter and more,
190 some of them again passed to the MimeTreeParser::ObjectTreeParser when it needs it.
191 
192 @author andras@kdab.net
193  */
194 class MESSAGEVIEWER_TESTS_EXPORT ViewerPrivate : public QObject
195 {
196     Q_OBJECT
197 public:
198     ViewerPrivate(Viewer *aParent, QWidget *mainWindow, KActionCollection *actionCollection);
199 
200     ~ViewerPrivate() override;
201 
202     /** 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,
203     followed by : and the ContentIndex path. */
204     Q_REQUIRED_RESULT KMime::Content *nodeFromUrl(const QUrl &url) const;
205 
206     /** Open the attachment pointed to the node.
207      * @param node the node
208      * @param url - if not empty, use this file to load the attachment content
209      */
210     void openAttachment(KMime::Content *node, const QUrl &url);
211 
212     /** Delete the attachment the @p node points to. Returns false if the user
213     cancelled the deletion, true in all other cases (including failure to delete
214     the attachment!)
215     * @param node the node
216     * @param showWarning whether some warning should be shown
217     */
218     Q_REQUIRED_RESULT bool deleteAttachment(KMime::Content *node, bool showWarning = true);
219 
220     void attachmentProperties(KMime::Content *node);
221     void attachmentCopy(const KMime::Content::List &contents);
222 
223     void scrollToAnchor(const QString &anchor);
224 
225     void showAttachmentPopup(KMime::Content *node, const QString &name, const QPoint &p);
226 
227     /**
228      * Sets the current attachment ID and the current attachment temporary filename
229      * to the given values.
230      * Call this so that slotHandleAttachment() knows which attachment to handle.
231      */
232     void prepareHandleAttachment(KMime::Content *node);
233 
234     Q_REQUIRED_RESULT KService::Ptr getServiceOffer(KMime::Content *content);
235     Q_REQUIRED_RESULT KMime::Content::List selectedContents() const;
236     void attachmentOpenWith(KMime::Content *node, const KService::Ptr &offer = KService::Ptr());
237     void attachmentOpen(KMime::Content *node);
238 
239     /** Return the HtmlWriter connected to the MailWebView we use */
240     HtmlWriter *htmlWriter() const;
241 
242     HeaderStylePlugin *headerStylePlugin() const;
243 
244     CSSHelper *cssHelper() const;
245 
246     MimeTreeParser::NodeHelper *nodeHelper() const;
247 
248     Viewer *viewer() const;
249 
250     Q_REQUIRED_RESULT Akonadi::Item messageItem() const;
251 
252     Q_REQUIRED_RESULT KMime::Message::Ptr message() const;
253 
254     /** Returns whether the message should be decrypted. */
255     Q_REQUIRED_RESULT bool decryptMessage() const;
256 
257     /** Display a generic HTML splash page instead of a message. */
258     void displaySplashPage(const QString &templateName, const QVariantHash &data, const QByteArray &domain = QByteArray());
259 
260     void displaySplashPage(const QString &message);
261 
262     /** Enable the displaying of messages again after an splash (or other) page was displayed */
263     void enableMessageDisplay();
264 
265     /** Feeds the HTML viewer with the contents of the given message.
266     HTML begin/end parts are written around the message. */
267     void displayMessage();
268 
269     /** Parse the given content and generate HTML out of it for display */
270     void parseContent(KMime::Content *content);
271 
272     /** Creates a nice mail header depending on the current selected
273     header style. */
274     Q_REQUIRED_RESULT QString writeMessageHeader(KMime::Message *aMsg, KMime::Content *vCardNode, bool topLevel);
275 
276     /** show window containing information about a vCard. */
277     void showVCard(KMime::Content *msgPart);
278 
279     void saveMainFrameScreenshotInFile(const QString &filename);
280 
281     void exportToPdf(const QString &fileName);
282 
283 private:
284     /** HTML initialization. */
285     void initHtmlWidget();
286     void createOpenWithMenu(QMenu *topMenu, const QString &contentTypeStr, bool fromCurrentContent);
287 
288 public:
289     void itemFetchResult(KJob *job);
290 
291     /** Read settings from app's config file. */
292     void readConfig();
293 
294     /** Write settings to app's config file. Calls sync() if withSync is true. */
295     void writeConfig(bool withSync = true);
296 
297     /** Get/set the message attachment strategy. */
298     const AttachmentStrategy *attachmentStrategy() const;
299     void setAttachmentStrategy(const AttachmentStrategy *strategy);
300 
301     /** Get selected override character encoding.
302       @return The encoding selected by the user or an empty string if auto-detection
303       is selected. */
304     Q_REQUIRED_RESULT QString overrideEncoding() const;
305 
306     /** Set the override character encoding. */
307     void setOverrideEncoding(const QString &encoding);
308 
309     /** Set printing mode */
310     void setPrinting(bool enable);
311     Q_REQUIRED_RESULT bool printingMode() const;
312 
313     /** Print message. */
314     void printMessage(const Akonadi::Item &msg);
315     void printPreviewMessage(const Akonadi::Item &message);
316 
317     void resetStateForNewMessage();
318 
319     void setMessageInternal(const KMime::Message::Ptr &message, MimeTreeParser::UpdateMode updateMode);
320 
321     /** Set the Akonadi item that will be displayed.
322      *  @param item - the Akonadi item to be displayed. If it doesn't hold a mail (KMime::Message::Ptr as payload data),
323      *                an empty page is shown.
324      *  @param updateMode - update the display immediately or not. See MailViewer::UpdateMode.
325      */
326     void setMessageItem(const Akonadi::Item &item, MimeTreeParser::UpdateMode updateMode = MimeTreeParser::Delayed, bool forceHtmlLoadExtOverride = false);
327 
328     /** Set the message that shall be shown.
329      * @param msg - the message to be shown. If 0, an empty page is displayed.
330      * @param updateMode - update the display immediately or not. See MailViewer::UpdateMode.
331      */
332     void setMessage(const KMime::Message::Ptr &msg, MimeTreeParser::UpdateMode updateMode = MimeTreeParser::Delayed);
333 
334     /** Instead of settings a message to be shown sets a message part
335       to be shown */
336     void setMessagePart(KMime::Content *node);
337 
338     /** Show or hide the Mime Tree Viewer if configuration
339       is set to smart mode.  */
340     void showHideMimeTree();
341 
342     /** View message part of type message/RFC822 in extra viewer window. */
343     void attachmentViewMessage(const KMime::Message::Ptr &message);
344 
345     void adjustLayout();
346     void createWidgets();
347     void createActions();
348 
349     void showContextMenu(KMime::Content *content, const QPoint &point);
350 
351     KToggleAction *actionForAttachmentStrategy(const AttachmentStrategy *);
352     /** Read override codec from configuration */
353     void readGlobalOverrideCodec();
354 
355     /** Get codec corresponding to the currently selected override character encoding.
356       @return The override codec or 0 if auto-detection is selected. */
357     const QTextCodec *overrideCodec() const;
358 
359     Q_REQUIRED_RESULT QString renderAttachments(KMime::Content *node, const QColor &bgColor) const;
360 
361     KMime::Content *findContentByType(KMime::Content *content, const QByteArray &type); // TODO(Andras) move to MimeTreeParser::NodeHelper
362 
363     /** Saves the relative position of the scroll view. Call this before calling update()
364       if you want to preserve the current view. */
365     void saveRelativePosition();
366 
367     Q_REQUIRED_RESULT bool htmlMail() const;
368     Q_REQUIRED_RESULT bool htmlLoadExternal() const;
369 
370     Q_REQUIRED_RESULT bool htmlMailGlobalSetting() const;
371 
372     /** Get the html override setting */
373     Q_REQUIRED_RESULT Viewer::DisplayFormatMessage displayFormatMessageOverwrite() const;
374 
375     /** Override default html mail setting */
376     void setDisplayFormatMessageOverwrite(Viewer::DisplayFormatMessage format);
377 
378     /** Get the load external references override setting */
379     Q_REQUIRED_RESULT bool htmlLoadExtOverride() const;
380 
381     /** Default behavior for loading external references.
382      *  Use this for specifying the external reference loading behavior as
383      *  specified in the user settings.
384      *  @see setHtmlLoadExtOverride
385      */
386     void setHtmlLoadExtDefault(bool loadExtDefault);
387 
388     /** Override default load external references setting
389      *  @warning This must only be called when the user has explicitly
390      *  been asked to retrieve external references!
391      *  @see setHtmlLoadExtDefault
392      */
393     void setHtmlLoadExtOverride(bool loadExtOverride);
394 
395     /** Enforce message decryption. */
396     void setDecryptMessageOverwrite(bool overwrite = true);
397 
398     /** Show signature details. */
399     Q_REQUIRED_RESULT bool showSignatureDetails() const;
400 
401     /** Show signature details. */
402     void setShowSignatureDetails(bool showDetails = true);
403 
404     /* show or hide encryption details */
405     void setShowEncryptionDetails(bool showEncDetails);
406 
407     Q_REQUIRED_RESULT bool showEncryptionDetails() const;
408 
409     void scrollToAttachment(KMime::Content *node);
410     void setUseFixedFont(bool useFixedFont);
411 
412     void attachmentView(KMime::Content *atmNode);
413 
414     void setZoomFactor(qreal zoomFactor);
415 
416     void goOnline();
417     void goResourceOnline();
418 
419     void showSavedFileFolderWidget(const QList<QUrl> &urls, MessageViewer::OpenSavedFileFolderWidget::FileType fileType);
420 
421     Q_REQUIRED_RESULT bool mimePartTreeIsEmpty() const;
422 
423     void setPluginName(const QString &pluginName);
424 
425     Q_REQUIRED_RESULT QList<QAction *> viewerPluginActionList(MessageViewer::ViewerPluginInterface::SpecificFeatureTypes features);
426     Q_REQUIRED_RESULT QList<QAction *> interceptorUrlActions(const WebEngineViewer::WebHitTestResult &result) const;
427 
428     void setPrintElementBackground(bool printElementBackground);
429     Q_REQUIRED_RESULT bool showEmoticons() const;
430     void checkPhishingUrl();
431     void executeRunner(const QUrl &url);
432     Q_REQUIRED_RESULT QUrl imageUrl() const;
433     Q_REQUIRED_RESULT qreal webViewZoomFactor() const;
434     void setWebViewZoomFactor(qreal factor);
435     void recreateCssHelper();
436     void hasMultiMessages(bool messages);
437     void updateShowMultiMessagesButton(bool enablePreviousButton, bool enableNextButton);
438     MessageViewer::DKIMViewerMenu *dkimViewerMenu();
439 
440     Q_REQUIRED_RESULT bool isAutocryptEnabled(KMime::Message *message);
441     void setIdentityManager(KIdentityManagement::IdentityManager *ident);
442     void setFolderIdentity(uint folderIdentity);
443 
444     RemoteContentMenu *remoteContentMenu() const;
445 
446 private Q_SLOTS:
447     void slotActivatePlugin(MessageViewer::ViewerPluginInterface *interface);
448     void slotModifyItemDone(KJob *job);
449     void slotMessageMayBeAScam();
450     void slotMessageIsNotAScam();
451     void slotAddToWhiteList();
452     void slotItemChanged(const Akonadi::Item &item, const QSet<QByteArray> &partIdentifiers);
453     void slotItemMoved(const Akonadi::Item &, const Akonadi::Collection &, const Akonadi::Collection &);
454 
455     void itemModifiedResult(KJob *job);
456 
457     void slotClear();
458 
459     void slotMessageRendered();
460 
461     void slotOpenWithAction(QAction *act);
462 
463     void slotOpenWithActionCurrentContent(QAction *act);
464 
465     void slotOpenWithDialog();
466 
467     void slotOpenWithDialogCurrentContent();
468 
469     void saveSplitterSizes() const;
470 
471     void slotRefreshMessage(const Akonadi::Item &item);
472     void slotServiceUrlSelected(PimCommon::ShareServiceUrlManager::ServiceType serviceType);
473     void slotStyleChanged(MessageViewer::HeaderStylePlugin *plugin);
474     void slotStyleUpdated();
475     void slotWheelZoomChanged(int numSteps);
476     void slotOpenInBrowser();
477     void slotExportHtmlPageFailed();
478     void slotExportHtmlPageSuccess(const QString &filename);
479     void slotHandlePagePrinted(bool result);
480     void slotToggleEmoticons();
481 
482 public Q_SLOTS:
483     /** An URL has been activate with a click. */
484     void slotUrlOpen(const QUrl &url = QUrl());
485     void slotOpenUrl();
486 
487     /** The mouse has moved on or off an URL. */
488     void slotUrlOn(const QString &link);
489 
490     /** The user presses the right mouse button on an URL. */
491     void slotUrlPopup(const WebEngineViewer::WebHitTestResult &result);
492 
493     /** The user selected "Find" from the menu. */
494     void slotFind();
495 
496     /** The user toggled the "Fixed Font" flag from the view menu. */
497     void slotToggleFixedFont();
498     void slotToggleMimePartTree();
499 
500     /** Show the message source */
501     void slotShowMessageSource();
502 
503     /** Refresh the reader window */
504     void updateReaderWin();
505 
506     void slotMimePartSelected(const QModelIndex &index);
507 
508     void slotIconicAttachments();
509     void slotSmartAttachments();
510     void slotInlineAttachments();
511     void slotHideAttachments();
512     void slotHeaderOnlyAttachments();
513 
514     /** Some attachment operations. */
515     void slotDelayedResize();
516 
517     /** Print message. Called on as a response of finished() signal of mPartHtmlWriter
518       after rendering is finished.
519       In the very end it deletes the KMReaderWin window that was created
520       for the purpose of rendering. */
521     void slotPrintMessage();
522     void slotPrintPreview();
523 
524     void slotSetEncoding();
525     void executeCustomScriptsAfterLoading();
526     void slotSettingsChanged();
527     void slotMimeTreeContextMenuRequested(const QPoint &pos);
528     void slotAttachmentOpenWith();
529     void slotAttachmentOpen();
530     void slotAttachmentSaveAs();
531     void slotAttachmentSaveAll();
532     void slotAttachmentView();
533     void slotAttachmentProperties();
534     void slotAttachmentCopy();
535     void slotAttachmentDelete();
536     void slotLevelQuote(int l);
537 
538     /** Toggle display mode between HTML and plain text. */
539     void slotToggleHtmlMode();
540     void slotLoadExternalReference();
541 
542     /**
543      * Does an action for the current attachment.
544      * The action is defined by the KMHandleAttachmentCommand::AttachmentAction
545      * enum.
546      * prepareHandleAttachment() needs to be called before calling this to set the
547      * correct attachment ID.
548      */
549     void slotHandleAttachment(int action);
550     /** Copy the selected text to the clipboard */
551     void slotCopySelectedText();
552 
553     void viewerSelectionChanged();
554 
555     /** Select message body. */
556     void selectAll();
557 
558     /** Copy URL in mUrlCurrent to clipboard. Removes "mailto:" at
559       beginning of URL before copying. */
560     void slotUrlCopy();
561     void slotSaveMessage();
562     /** Re-parse the current message. */
563     void update(MimeTreeParser::UpdateMode updateMode = MimeTreeParser::Delayed);
564 
565     void slotSpeakText();
566     void slotCopyImageLocation();
567     void slotSaveMessageDisplayFormat();
568     void slotResetMessageDisplayFormat();
569 
570     void slotGeneralFontChanged();
571     void slotShowDevelopmentTools();
572 
573 Q_SIGNALS:
574     void showStatusBarMessage(const QString &message);
575     void popupMenu(const Akonadi::Item &msg, const QUrl &url, const QUrl &imageUrl, const QPoint &mousePos);
576     void displayPopupMenu(const Akonadi::Item &msg, const WebEngineViewer::WebHitTestResult &result, const QPoint &mousePos);
577 
578     void urlClicked(const Akonadi::Item &msg, const QUrl &url);
579     void requestConfigSync();
580     void showReader(KMime::Content *aMsgPart, bool aHTML, const QString &encoding);
581     void showMessage(const KMime::Message::Ptr &message, const QString &encoding);
582     void replyMessageTo(const KMime::Message::Ptr &message, bool replyToAll);
583     void itemRemoved();
584     void makeResourceOnline(MessageViewer::Viewer::ResourceOnlineMode mode);
585 
586     void changeDisplayMail(Viewer::DisplayFormatMessage, bool);
587     void moveMessageToTrash();
588     void pageIsScrolledToBottom(bool);
589     void printingFinished();
590     void zoomChanged(qreal zoomFactor);
591     void showNextMessage();
592     void showPreviousMessage();
593 
594 private:
595     Q_REQUIRED_RESULT QString attachmentHtml();
596     void initializeColorFromScheme();
597 
598     void replyMessageToAuthor(KMime::Content *atmNode);
599     void replyMessageToAll(KMime::Content *atmNode);
600     void replyMessage(KMime::Content *atmNode, bool replyToAll);
601     Q_REQUIRED_RESULT bool urlIsAMalwareButContinue();
602     Q_REQUIRED_RESULT bool messageIsInSpecialFolder() const;
603 
604     void slotCheckedUrlFinished(const QUrl &url, WebEngineViewer::CheckPhishingUrlUtil::UrlStatus status);
605 
606     void slotDelayPrintPreview();
607     void applyZoomValue(qreal factor, bool saveConfig = true);
608     void slotZoomChanged(qreal zoom);
609     void assignMessageItem(const Akonadi::Item &item);
610     void slotPdfPrintingFinished(const QString &filePath, bool success);
611     MimeTreeParser::NodeHelper *mNodeHelper = nullptr;
612     bool mHtmlMailGlobalSetting = false;
613     bool mHtmlLoadExternalDefaultSetting = false;
614     bool mHtmlLoadExtOverride = false;
615     void slotUrlBlocked(const QUrl &url);
616 
617 public:
618     KMime::Message::Ptr mMessage; // the current message, if it was set manually
619     Akonadi::Item mMessageItem; // the message item from Akonadi
620     // widgets:
621     QSplitter *mSplitter = nullptr;
622     QWidget *mBox = nullptr;
623     HtmlStatusBar *mColorBar = nullptr;
624     MimePartTreeView *mMimePartTree = nullptr;
625     MailWebEngineView *mViewer = nullptr;
626     WebEngineViewer::FindBarWebEngineView *mFindBar = nullptr;
627 
628     const AttachmentStrategy *mAttachmentStrategy = nullptr;
629     QTimer mUpdateReaderWinTimer;
630     QTimer mResizeTimer;
631     QString mOverrideEncoding;
632     QString mOldGlobalOverrideEncoding; // used to detect changes of the global override character encoding
633 
634     /// This is true if the viewer currently is displaying a message. Can be false, for example when
635     /// the splash/busy page is displayed.
636     bool mMsgDisplay = true;
637 
638     bool mUseFixedFont = false;
639     bool mPrinting = false;
640     QWidget *mMainWindow = nullptr;
641     KActionCollection *const mActionCollection;
642     QAction *mCopyAction = nullptr;
643     QAction *mCopyURLAction = nullptr;
644     QAction *mUrlOpenAction = nullptr;
645     QAction *mSelectAllAction = nullptr;
646     QAction *mScrollUpAction = nullptr;
647     QAction *mScrollDownAction = nullptr;
648     QAction *mScrollUpMoreAction = nullptr;
649     QAction *mScrollDownMoreAction = nullptr;
650     QAction *mViewSourceAction = nullptr;
651     QAction *mSaveMessageAction = nullptr;
652     QAction *mFindInMessageAction = nullptr;
653     QAction *mSaveMessageDisplayFormat = nullptr;
654     QAction *mResetMessageDisplayFormat = nullptr;
655     KToggleAction *mDisableEmoticonAction = nullptr;
656     KToggleAction *mHeaderOnlyAttachmentsAction = nullptr;
657     KSelectAction *mSelectEncodingAction = nullptr;
658     KToggleAction *mToggleFixFontAction = nullptr;
659     KToggleAction *mToggleDisplayModeAction = nullptr;
660     KToggleAction *mToggleMimePartTreeAction = nullptr;
661     QAction *mDevelopmentToolsAction = nullptr;
662     QAction *mSpeakTextAction = nullptr;
663     QAction *mCopyImageLocation = nullptr;
664     QAction *mShareTextAction = nullptr;
665     QUrl mClickedUrl;
666     QUrl mImageUrl;
667     HtmlWriter *mHtmlWriter = nullptr;
668     /** Used only to be able to connect and disconnect finished() signal
669       in printMsg() and slotPrintMsg() since mHtmlWriter points only to abstract non-QObject class. */
670     QPointer<WebEnginePartHtmlWriter> mPartHtmlWriter;
671     QPointer<WebEngineViewer::DeveloperToolDialog> mDeveloperToolDialog;
672 
673     int mLevelQuote;
674     bool mDecrytMessageOverwrite = false;
675     bool mShowSignatureDetails = false;
676     bool mShowEncryptionDetails = false;
677     bool mForceEmoticons = true;
678     int mRecursionCountForDisplayMessage = 0;
679     uint mFolderIdentity = 0;
680     KMime::Content *mCurrentContent = nullptr;
681     KMime::Content *mMessagePartNode = nullptr;
682     QString mMessagePath;
683 
684     QColor mForegroundError;
685     QColor mBackgroundError;
686     QColor mBackgroundAttachment;
687 
688     Viewer *const q;
689     Akonadi::Session *mSession = nullptr;
690     Akonadi::Monitor mMonitor;
691     QSet<AbstractMessageLoadedHandler *> mMessageLoadedHandlers;
692     Akonadi::Item::Id mPreviouslyViewedItemId = -1;
693 
694     MessageViewer::ScamDetectionWarningWidget *mScamDetectionWarning = nullptr;
695     MessageViewer::OpenSavedFileFolderWidget *mOpenSavedFileFolderWidget = nullptr;
696     WebEngineViewer::SubmittedFormWarningWidget *mSubmittedFormWarning = nullptr;
697     WebEngineViewer::TrackingWarningWidget *mMailTrackingWarning = nullptr;
698     KPIMTextEdit::TextToSpeechWidget *mTextToSpeechWidget = nullptr;
699     Viewer::DisplayFormatMessage mDisplayFormatMessageOverwrite;
700     KPIMTextEdit::SlideContainer *mSliderContainer = nullptr;
701     PimCommon::ShareServiceUrlManager *mShareServiceManager = nullptr;
702     KActionMenu *mShareServiceUrlMenu = nullptr;
703     MessageViewer::HeaderStylePlugin *mHeaderStylePlugin = nullptr;
704     MessageViewer::HeaderStyleMenuManager *mHeaderStyleMenuManager = nullptr;
705     MessageViewer::ViewerPluginToolManager *mViewerPluginToolManager = nullptr;
706     WebEngineViewer::ZoomActionMenu *mZoomActionMenu = nullptr;
707     QPrinter *mCurrentPrinter = nullptr;
708     QVector<QPointer<MessageViewer::MailSourceWebEngineViewer>> mListMailSourceViewer;
709     WebEngineViewer::LocalDataBaseManager *mPhishingDatabase = nullptr;
710     MessageViewer::ShowNextMessageWidget *mShowNextMessageWidget = nullptr;
711     MessageViewer::DKIMWidgetInfo *mDkimWidgetInfo = nullptr;
712     MessageViewer::DKIMViewerMenu *mDkimViewerMenu = nullptr;
713     MessageViewer::MessageViewerRenderer *mMessageViewerRenderer = nullptr;
714     KIdentityManagement::IdentityManager *mIdentityManager = nullptr;
715     RemoteContentMenu *mRemoteContentMenu = nullptr;
716 };
717 }
718 
719