1 /* 2 This file is part of KMail, the KDE mail client. 3 SPDX-FileCopyrightText: 1997 Markus Wuebben <markus.wuebben@kde.org> 4 SPDX-FileCopyrightText: 2009 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.net 5 SPDX-FileCopyrightText: 2009 Andras Mantia <andras@kdab.net> 6 7 SPDX-License-Identifier: GPL-2.0-or-later 8 */ 9 10 #pragma once 11 12 #include "config-messageviewer.h" 13 #include "messageviewer/viewerplugininterface.h" 14 #include "messageviewer_export.h" 15 #include <MimeTreeParser/Enums> 16 17 #include <KMime/Message> 18 19 #include <QWidget> 20 #include <memory> 21 22 namespace Akonadi 23 { 24 class Item; 25 class ItemFetchJob; 26 } 27 28 namespace KIdentityManagement 29 { 30 class IdentityManager; 31 } 32 33 class KActionCollection; 34 class QAction; 35 class KToggleAction; 36 class KActionMenu; 37 38 class QAbstractItemModel; 39 class QCloseEvent; 40 class QEvent; 41 class QResizeEvent; 42 43 namespace WebEngineViewer 44 { 45 class WebHitTestResult; 46 } 47 48 namespace MessageViewer 49 { 50 class WebHitTestResult; 51 class DKIMWidgetInfo; 52 class DKIMViewerMenu; 53 class AttachmentStrategy; 54 class HeaderStylePlugin; 55 class CSSHelper; 56 class ViewerPrivate; 57 class Viewer; 58 class RemoteContentMenu; 59 60 /** 61 * An interface to plug in a handler that is called when 62 * an message item has been loaded into the view. 63 */ 64 class MESSAGEVIEWER_EXPORT AbstractMessageLoadedHandler 65 { 66 public: 67 AbstractMessageLoadedHandler(); 68 virtual ~AbstractMessageLoadedHandler(); 69 70 /** 71 * This method is called whenever a message item has been loaded 72 * into the view. 73 * 74 * @param item The message item that has been loaded. 75 */ 76 virtual void setItem(const Akonadi::Item &item) = 0; 77 78 protected: 79 Akonadi::Session *session() const; 80 81 private: 82 void setSession(Akonadi::Session *session); 83 84 friend class Viewer; 85 class AbstractMessageLoadedHandlerPrivate; 86 std::unique_ptr<AbstractMessageLoadedHandlerPrivate> const d; 87 }; 88 89 /** 90 * This is the main widget for the viewer. 91 * See the documentation of ViewerPrivate for implementation details. 92 * See Mainpage.dox for an overview of the classes in the messageviewer library. 93 */ 94 class MESSAGEVIEWER_EXPORT Viewer : public QWidget 95 { 96 Q_OBJECT 97 98 Q_DECLARE_PRIVATE(Viewer) 99 100 public: 101 /** 102 * Create a mail viewer widget 103 * @param parent parent widget 104 * @param widget the application's main widget 105 * @param actionCollection the action collection where the widget's actions will belong to 106 */ 107 explicit Viewer(QWidget *parent, QWidget *widget = nullptr, KActionCollection *actionCollection = nullptr); 108 ~Viewer() override; 109 110 /** 111 * Returns the current message displayed in the viewer. 112 */ 113 Q_REQUIRED_RESULT KMime::Message::Ptr message() const; 114 115 /** 116 * Returns the current message item displayed in the viewer. 117 */ 118 Q_REQUIRED_RESULT Akonadi::Item messageItem() const; 119 120 enum DisplayFormatMessage { UseGlobalSetting = 0, Text = 1, Html = 2, Unknown = 3, ICal = 4 }; 121 122 enum AttachmentAction { Open = 1, OpenWith, View, Save, Properties, Delete, Copy, ScrollTo, ReplyMessageToAuthor, ReplyMessageToAll }; 123 124 enum ResourceOnlineMode { AllResources = 0, SelectedResource = 1 }; 125 126 /** 127 * Set the message that shall be shown. 128 * @param message - the message to be shown. If 0, an empty page is displayed. 129 * @param updateMode - update the display immediately or not. See UpdateMode. 130 */ 131 void setMessage(const KMime::Message::Ptr &message, MimeTreeParser::UpdateMode updateMode = MimeTreeParser::Delayed); 132 133 /** 134 * Set the Akonadi item that will be displayed. 135 * @param item - the Akonadi item to be displayed. If it doesn't hold a mail (KMime::Message::Ptr as payload data), 136 * an empty page is shown. 137 * @param updateMode - update the display immediately or not. See UpdateMode. 138 */ 139 void setMessageItem(const Akonadi::Item &item, MimeTreeParser::UpdateMode updateMode = MimeTreeParser::Delayed); 140 141 /** 142 * The path to the message in terms of Akonadi collection hierarchy. 143 */ 144 Q_REQUIRED_RESULT QString messagePath() const; 145 146 /** 147 * Set the path to the message in terms of Akonadi collection hierarchy. 148 */ 149 void setMessagePath(const QString &path); 150 151 /** 152 * Instead of settings a message to be shown sets a message part 153 * to be shown 154 */ 155 void setMessagePart(KMime::Content *aMsgPart); 156 157 /** 158 * Convenience method to clear the reader and discard the current message. Sets the internal message pointer 159 * returned by message() to 0. 160 * @param updateMode - update the display immediately or not. See UpdateMode. 161 */ 162 void clear(MimeTreeParser::UpdateMode updateMode = MimeTreeParser::Delayed); 163 164 void update(MimeTreeParser::UpdateMode updateMode = MimeTreeParser::Delayed); 165 166 /** 167 * Sets a message as the current one and print it immediately. 168 * @param msg the message to display and print 169 */ 170 void printMessage(const Akonadi::Item &msg); 171 172 void printPreviewMessage(const Akonadi::Item &message); 173 174 /** Print the currently displayed message */ 175 void print(); 176 void printPreview(); 177 178 /** Get the html override setting */ 179 Q_REQUIRED_RESULT Viewer::DisplayFormatMessage displayFormatMessageOverwrite() const; 180 181 /** Override default html mail setting */ 182 void setDisplayFormatMessageOverwrite(Viewer::DisplayFormatMessage format); 183 184 /** Get the load external references override setting */ 185 bool htmlLoadExtOverride() const; 186 187 /** Default behavior for loading external references. 188 * Use this for specifying the external reference loading behavior as 189 * specified in the user settings. 190 * @see setHtmlLoadExtOverride 191 */ 192 void setHtmlLoadExtDefault(bool loadExtDefault); 193 194 /** Override default load external references setting 195 * @warning This must only be called when the user has explicitly 196 * been asked to retrieve external references! 197 * @see setHtmlLoadExtDefault 198 */ 199 void setHtmlLoadExtOverride(bool loadExtOverride); 200 201 /** Is html mail to be supported? Takes into account override */ 202 Q_REQUIRED_RESULT bool htmlMail() const; 203 204 /** Is loading ext. references to be supported? Takes into account override */ 205 Q_REQUIRED_RESULT bool htmlLoadExternal() const; 206 207 /** 208 * Display a generic HTML splash page instead of a message. 209 * @param templateName - the template to be loaded 210 * @param data - data for the template 211 * @param domain the domain. 212 */ 213 void displaySplashPage(const QString &templateName, const QVariantHash &data, const QByteArray &domain = QByteArray()); 214 215 /** Enable the displaying of messages again after an splash (or other) page was displayed */ 216 void enableMessageDisplay(); 217 218 /** Returns true if the message view is scrolled to the bottom. */ 219 void atBottom(); 220 221 Q_REQUIRED_RESULT bool isFixedFont() const; 222 void setUseFixedFont(bool useFixedFont); 223 224 Q_REQUIRED_RESULT QWidget *mainWindow(); 225 226 /** Enforce message decryption. */ 227 void setDecryptMessageOverwrite(bool overwrite = true); 228 229 /** 230 * Initiates a delete, by sending a signal to delete the message item */ 231 void deleteMessage(); 232 233 Q_REQUIRED_RESULT const AttachmentStrategy *attachmentStrategy() const; 234 void setAttachmentStrategy(const AttachmentStrategy *strategy); 235 236 Q_REQUIRED_RESULT QString overrideEncoding() const; 237 void setOverrideEncoding(const QString &encoding); 238 Q_REQUIRED_RESULT CSSHelper *cssHelper() const; 239 void setPrinting(bool enable); 240 241 void selectAll(); 242 void copySelectionToClipboard(); 243 244 void setZoomFactor(qreal zoomFactor); 245 246 Q_REQUIRED_RESULT KToggleAction *toggleFixFontAction() const; 247 248 Q_REQUIRED_RESULT KToggleAction *toggleMimePartTreeAction() const; 249 250 Q_REQUIRED_RESULT QAction *selectAllAction() const; 251 Q_REQUIRED_RESULT QAction *copyURLAction() const; 252 Q_REQUIRED_RESULT QAction *copyAction() const; 253 Q_REQUIRED_RESULT QAction *urlOpenAction() const; 254 Q_REQUIRED_RESULT QAction *speakTextAction() const; 255 Q_REQUIRED_RESULT QAction *copyImageLocation() const; 256 Q_REQUIRED_RESULT QAction *viewSourceAction() const; 257 Q_REQUIRED_RESULT QAction *findInMessageAction() const; 258 Q_REQUIRED_RESULT QAction *saveAsAction() const; 259 Q_REQUIRED_RESULT QAction *saveMessageDisplayFormatAction() const; 260 Q_REQUIRED_RESULT QAction *resetMessageDisplayFormatAction() const; 261 Q_REQUIRED_RESULT QAction *shareTextAction() const; 262 263 Q_REQUIRED_RESULT QAction *developmentToolsAction() const; 264 Q_REQUIRED_RESULT KToggleAction *disableEmoticonAction() const; 265 Q_REQUIRED_RESULT KActionMenu *shareServiceUrlMenu() const; 266 Q_REQUIRED_RESULT HeaderStylePlugin *headerStylePlugin() const; 267 Q_REQUIRED_RESULT MessageViewer::DKIMViewerMenu *dkimViewerMenu(); 268 269 Q_REQUIRED_RESULT MessageViewer::RemoteContentMenu *remoteContentMenu() const; 270 271 void setPluginName(const QString &pluginName); 272 273 void writeConfig(bool withSync = true); 274 275 Q_REQUIRED_RESULT QUrl urlClicked() const; 276 Q_REQUIRED_RESULT QUrl imageUrlClicked() const; 277 278 void readConfig(); 279 280 /** A QAIM tree model of the message structure. */ 281 QAbstractItemModel *messageTreeModel() const; 282 283 /** 284 * Create an item fetch job that is suitable for using to fetch the message item that will 285 * be displayed on this viewer. 286 * It will set the correct fetch scope. 287 * You still need to connect to the job's result signal. 288 */ 289 Akonadi::ItemFetchJob *createFetchJob(const Akonadi::Item &item); 290 291 /** 292 * Adds a @p handler for actions that will be executed when the message 293 * has been loaded into the view. 294 */ 295 void addMessageLoadedHandler(AbstractMessageLoadedHandler *handler); 296 297 /** 298 * Removes the @p handler for actions that will be executed when the message 299 * has been loaded into the view. 300 */ 301 void removeMessageLoadedHandler(AbstractMessageLoadedHandler *handler); 302 303 Q_REQUIRED_RESULT QString selectedText() const; 304 305 void saveMainFrameScreenshotInFile(const QString &filename); 306 bool mimePartTreeIsEmpty() const; 307 308 void showOpenAttachmentFolderWidget(const QList<QUrl> &urls); 309 Q_REQUIRED_RESULT QList<QAction *> viewerPluginActionList(MessageViewer::ViewerPluginInterface::SpecificFeatureTypes features); 310 Q_REQUIRED_RESULT QList<QAction *> interceptorUrlActions(const WebEngineViewer::WebHitTestResult &result) const; 311 312 void runJavaScript(const QString &code); 313 void setPrintElementBackground(bool printElementBackground); 314 315 Q_REQUIRED_RESULT bool printingMode() const; 316 317 Q_REQUIRED_RESULT bool showSignatureDetails() const; 318 void setShowSignatureDetails(bool showDetails); 319 320 Q_REQUIRED_RESULT qreal webViewZoomFactor() const; 321 void setWebViewZoomFactor(qreal factor); 322 323 Q_REQUIRED_RESULT bool showEncryptionDetails() const; 324 void setShowEncryptionDetails(bool showDetails); 325 326 void hasMultiMessages(bool messages); 327 void updateShowMultiMessagesButton(bool enablePreviousButton, bool enableNextButton); 328 Q_REQUIRED_RESULT MessageViewer::DKIMWidgetInfo *dkimWidgetInfo(); 329 330 void exportToPdf(const QString &fileName); 331 332 void showDevelopmentTools(); 333 334 void setIdentityManager(KIdentityManagement::IdentityManager *ident); 335 void setFolderIdentity(uint folderIdentity); 336 Q_SIGNALS: 337 void moveMessageToTrash(); 338 void pageIsScrolledToBottom(bool); 339 340 /** 341 * Emitted when a status bar message is shown. Note that the status bar message is also set to 342 * KPIM::BroadcastStatus in addition. 343 */ 344 void showStatusBarMessage(const QString &message); 345 346 /** The user presses the right mouse button. 'url' may be 0. */ 347 void popupMenu(const Akonadi::Item &msg, const QUrl &url, const QUrl &imageUrl, const QPoint &mousePos); 348 void displayPopupMenu(const Akonadi::Item &msg, const WebEngineViewer::WebHitTestResult &result, const QPoint &mousePos); 349 /** 350 * The message viewer handles some types of urls itself, most notably http(s) 351 * and ftp(s). When it can't handle the url it will Q_EMIT this signal. 352 */ 353 void urlClicked(const Akonadi::Item &, const QUrl &); 354 355 void requestConfigSync(); 356 357 /// Emitted when the content should be shown in a separate window 358 void showReader(KMime::Content *aMsgPart, bool aHTML, const QString &encoding); 359 360 /// Emitted when the message should be shown in a separate window 361 void showMessage(const KMime::Message::Ptr &message, const QString &encoding); 362 363 void replyMessageTo(const KMime::Message::Ptr &message, bool replyToAll); 364 365 void deleteMessage(const Akonadi::Item &); 366 367 /// Emitted when the item, previously set with setMessageItem, has been removed. 368 void itemRemoved(); 369 370 void makeResourceOnline(MessageViewer::Viewer::ResourceOnlineMode mode); 371 372 void printingFinished(); 373 void zoomChanged(qreal zoomFactor); 374 void showNextMessage(); 375 void showPreviousMessage(); 376 377 private: 378 void initialize(); 379 380 public Q_SLOTS: 381 382 /** 383 * HTML Widget scrollbar and layout handling. 384 * 385 * Scrolling always happens in the direction of the slot that is called. I.e. 386 * the methods take the absolute value of 387 */ 388 void slotScrollUp(); 389 void slotScrollDown(); 390 void slotScrollPrior(); 391 void slotScrollNext(); 392 void slotJumpDown(); 393 void slotFind(); 394 void slotSaveMessage(); 395 void slotAttachmentSaveAs(); 396 void slotAttachmentSaveAll(); 397 void slotShowMessageSource(); 398 void slotZoomIn(); 399 void slotZoomOut(); 400 void slotZoomReset(); 401 void slotChangeDisplayMail(Viewer::DisplayFormatMessage, bool); 402 403 protected: 404 /** Some necessary event handling. */ 405 void closeEvent(QCloseEvent *) override; 406 void resizeEvent(QResizeEvent *) override; 407 /** Watch for palette changes */ 408 Q_REQUIRED_RESULT bool event(QEvent *e) override; 409 void changeEvent(QEvent *event) override; 410 411 ViewerPrivate *const d_ptr; 412 }; 413 } 414 415