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 }