vmdeditor.h 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380
  1. #ifndef VMDEDITOR_H
  2. #define VMDEDITOR_H
  3. #include <QVector>
  4. #include <QString>
  5. #include <QClipboard>
  6. #include <QImage>
  7. #include <QUrl>
  8. #include <QTemporaryFile>
  9. #include <QSharedPointer>
  10. #include "vtextedit.h"
  11. #include "veditor.h"
  12. #include "vconfigmanager.h"
  13. #include "vtableofcontent.h"
  14. #include "vconfigmanager.h"
  15. #include "utils/vutils.h"
  16. class PegMarkdownHighlighter;
  17. class VCodeBlockHighlightHelper;
  18. class VDocument;
  19. class VPreviewManager;
  20. class VCopyTextAsHtmlDialog;
  21. class VEditTab;
  22. class VTableHelper;
  23. class VMdEditor : public VTextEdit, public VEditor
  24. {
  25. Q_OBJECT
  26. public:
  27. VMdEditor(VFile *p_file,
  28. VDocument *p_doc,
  29. MarkdownConverterType p_type,
  30. const QSharedPointer<VTextEditCompleter> &p_completer,
  31. QWidget *p_parent = nullptr);
  32. void beginEdit() Q_DECL_OVERRIDE;
  33. void endEdit() Q_DECL_OVERRIDE;
  34. void saveFile() Q_DECL_OVERRIDE;
  35. void reloadFile() Q_DECL_OVERRIDE;
  36. bool scrollToBlock(int p_blockNumber) Q_DECL_OVERRIDE;
  37. void makeBlockVisible(const QTextBlock &p_block) Q_DECL_OVERRIDE;
  38. QVariant inputMethodQuery(Qt::InputMethodQuery p_query) const Q_DECL_OVERRIDE;
  39. bool isBlockVisible(const QTextBlock &p_block) Q_DECL_OVERRIDE;
  40. // An image has been inserted. The image is relative.
  41. // @p_path is the absolute path of the inserted image.
  42. // @p_url is the URL text within ().
  43. void imageInserted(const QString &p_path, const QString &p_url);
  44. // Scroll to header @p_blockNumber.
  45. // Return true if @p_blockNumber is valid to scroll to.
  46. bool scrollToHeader(int p_blockNumber);
  47. void scrollBlockInPage(int p_blockNum, int p_dest, int p_margin = 0) Q_DECL_OVERRIDE;
  48. void updateConfig() Q_DECL_OVERRIDE;
  49. QString getContent() const Q_DECL_OVERRIDE;
  50. void setContent(const QString &p_content, bool p_modified = false) Q_DECL_OVERRIDE;
  51. void refreshPreview();
  52. // Update m_initImages and m_insertedImages to handle the change of the note path.
  53. void updateInitAndInsertedImages(bool p_fileChanged, UpdateAction p_act);
  54. VWordCountInfo fetchWordCountInfo() const Q_DECL_OVERRIDE;
  55. void setEditTab(VEditTab *p_editTab);
  56. PegMarkdownHighlighter *getMarkdownHighlighter() const;
  57. VPreviewManager *getPreviewManager() const;
  58. void updateHeaderSequenceByConfigChange();
  59. void updateFontAndPalette() Q_DECL_OVERRIDE;
  60. void insertTable() Q_DECL_OVERRIDE;
  61. public slots:
  62. bool jumpTitle(bool p_forward, int p_relativeLevel, int p_repeat) Q_DECL_OVERRIDE;
  63. void textToHtmlFinished(int p_id, int p_timeStamp, const QUrl &p_baseUrl, const QString &p_html);
  64. void htmlToTextFinished(int p_id, int p_timeStamp, const QString &p_html);
  65. void parseAndPaste();
  66. // Wrapper functions for QPlainTextEdit/QTextEdit.
  67. public:
  68. void setExtraSelectionsW(const QList<QTextEdit::ExtraSelection> &p_selections) Q_DECL_OVERRIDE
  69. {
  70. setExtraSelections(p_selections);
  71. }
  72. QTextDocument *documentW() const Q_DECL_OVERRIDE
  73. {
  74. return document();
  75. }
  76. int tabStopWidthW() const Q_DECL_OVERRIDE
  77. {
  78. return tabStopWidth();
  79. }
  80. void setTabStopWidthW(int p_width) Q_DECL_OVERRIDE
  81. {
  82. setTabStopWidth(p_width);
  83. }
  84. QTextCursor textCursorW() const Q_DECL_OVERRIDE
  85. {
  86. return textCursor();
  87. }
  88. void moveCursorW(QTextCursor::MoveOperation p_operation,
  89. QTextCursor::MoveMode p_mode) Q_DECL_OVERRIDE
  90. {
  91. moveCursor(p_operation, p_mode);
  92. }
  93. QScrollBar *verticalScrollBarW() const Q_DECL_OVERRIDE
  94. {
  95. return verticalScrollBar();
  96. }
  97. QScrollBar *horizontalScrollBarW() const Q_DECL_OVERRIDE
  98. {
  99. return horizontalScrollBar();
  100. }
  101. void setTextCursorW(const QTextCursor &p_cursor) Q_DECL_OVERRIDE
  102. {
  103. setTextCursor(p_cursor);
  104. }
  105. bool findW(const QString &p_exp,
  106. QTextDocument::FindFlags p_options = QTextDocument::FindFlags()) Q_DECL_OVERRIDE
  107. {
  108. return find(p_exp, p_options);
  109. }
  110. bool findW(const QRegExp &p_exp,
  111. QTextDocument::FindFlags p_options = QTextDocument::FindFlags()) Q_DECL_OVERRIDE
  112. {
  113. return find(p_exp, p_options);
  114. }
  115. bool isReadOnlyW() const Q_DECL_OVERRIDE
  116. {
  117. return isReadOnly();
  118. }
  119. void setReadOnlyW(bool p_ro) Q_DECL_OVERRIDE
  120. {
  121. setReadOnly(p_ro);
  122. }
  123. QWidget *viewportW() const Q_DECL_OVERRIDE
  124. {
  125. return viewport();
  126. }
  127. void insertPlainTextW(const QString &p_text) Q_DECL_OVERRIDE
  128. {
  129. insertPlainText(p_text);
  130. }
  131. void undoW() Q_DECL_OVERRIDE
  132. {
  133. undo();
  134. }
  135. void redoW() Q_DECL_OVERRIDE
  136. {
  137. redo();
  138. }
  139. // Whether display cursor as block.
  140. void setCursorBlockModeW(CursorBlock p_mode) Q_DECL_OVERRIDE
  141. {
  142. setCursorBlockMode(p_mode);
  143. }
  144. void zoomInW(int p_range = 1) Q_DECL_OVERRIDE
  145. {
  146. zoomPage(true, p_range);
  147. }
  148. void zoomOutW(int p_range = 1) Q_DECL_OVERRIDE
  149. {
  150. zoomPage(false, p_range);
  151. }
  152. void ensureCursorVisibleW() Q_DECL_OVERRIDE
  153. {
  154. ensureCursorVisible();
  155. }
  156. QRect cursorRectW() Q_DECL_OVERRIDE
  157. {
  158. return cursorRect();
  159. }
  160. QRect cursorRectW(const QTextCursor &p_cursor) Q_DECL_OVERRIDE
  161. {
  162. return cursorRect(p_cursor);
  163. }
  164. signals:
  165. // Signal when headers change.
  166. void headersChanged(const QVector<VTableOfContentItem> &p_headers);
  167. // Signal when current header change.
  168. void currentHeaderChanged(int p_blockNumber);
  169. // Signal when the status of VMdEdit changed.
  170. // Will be emitted by VImagePreviewer for now.
  171. void statusChanged();
  172. // Request to convert @p_text to Html.
  173. void requestTextToHtml(const QString &p_text, int p_id, int p_timeStamp);
  174. // Request to convert @p_html to Markdown text.
  175. void requestHtmlToText(const QString &p_html, int p_id, int p_timeStamp);
  176. void requestUploadImageToGithub();
  177. void requestUploadImageToGitee();
  178. void requestUploadImageToWechat();
  179. void requestUploadImageToTencent();
  180. protected:
  181. void contextMenuEvent(QContextMenuEvent *p_event) Q_DECL_OVERRIDE;
  182. // Used to implement dragging mouse with Ctrl and left button pressed to scroll.
  183. void mousePressEvent(QMouseEvent *p_event) Q_DECL_OVERRIDE;
  184. void mouseReleaseEvent(QMouseEvent *p_event) Q_DECL_OVERRIDE;
  185. void mouseMoveEvent(QMouseEvent *p_event) Q_DECL_OVERRIDE;
  186. void mouseDoubleClickEvent(QMouseEvent *p_event) Q_DECL_OVERRIDE;
  187. void keyPressEvent(QKeyEvent *p_event) Q_DECL_OVERRIDE;
  188. bool canInsertFromMimeData(const QMimeData *p_source) const Q_DECL_OVERRIDE;
  189. void insertFromMimeData(const QMimeData *p_source) Q_DECL_OVERRIDE;
  190. void wheelEvent(QWheelEvent *p_event) Q_DECL_OVERRIDE;
  191. int lineNumberAreaWidth() const Q_DECL_OVERRIDE;
  192. private slots:
  193. // Update m_headers according to elements.
  194. void updateHeaders(const QVector<VElementRegion> &p_headerRegions);
  195. // Update current header according to cursor position.
  196. // When there is no header in current cursor, will signal an invalid header.
  197. void updateCurrentHeader();
  198. // Copy selected text as HTML.
  199. void handleCopyAsAction(QAction *p_act);
  200. void handleLinkToAttachmentAction(QAction *p_act);
  201. private:
  202. void updateHeadersHelper(const QVector<VElementRegion> &p_headerRegions, bool p_configChanged);
  203. // Update the config of VTextEdit according to global configurations.
  204. void updateTextEditConfig();
  205. // Get the initial images from file before edit.
  206. void initInitImages();
  207. // Clear two kind of images according to initial images and current images:
  208. // 1. Newly inserted images which are deleted later;
  209. // 2. Initial images which are deleted;
  210. void clearUnusedImages();
  211. // Index in m_headers of current header which contains the cursor.
  212. int indexOfCurrentHeader() const;
  213. // Zoom in/out.
  214. // We need to maintain the styles font size.
  215. void zoomPage(bool p_zoomIn, int p_range = 1);
  216. QAction *initCopyAsMenu(QAction *p_after, QMenu *p_menu);
  217. QAction *initPasteAsBlockQuoteMenu(QAction *p_after, QMenu *p_menu);
  218. QAction *initPasteAfterParseMenu(QAction *p_after, QMenu *p_menu);
  219. void initLinkAndPreviewMenu(QAction *p_before, QMenu *p_menu, const QPoint &p_pos);
  220. bool initInPlacePreviewMenu(QAction *p_before,
  221. QMenu *p_menu,
  222. const QTextBlock &p_block,
  223. int p_pos);
  224. bool initExportAndCopyMenu(QAction *p_before,
  225. QMenu *p_menu,
  226. const QTextBlock &p_block,
  227. int p_pos);
  228. void initAttachmentMenu(QMenu *p_menu);
  229. void initImageHostingMenu(QMenu *p_menu);
  230. void insertImageLink(const QString &p_text, const QString &p_url);
  231. void setFontPointSizeByStyleSheet(int p_ptSize);
  232. void setFontAndPaletteByStyleSheet(const QFont &p_font, const QPalette &p_palette);
  233. void exportGraphAndCopy(const QString &p_lang,
  234. const QString &p_text,
  235. const QString &p_format);
  236. bool processHtmlFromMimeData(const QMimeData *p_source);
  237. bool processImageFromMimeData(const QMimeData *p_source);
  238. bool processUrlFromMimeData(const QMimeData *p_source);
  239. void replaceTextWithLocalImages(QString &p_text);
  240. PegMarkdownHighlighter *m_pegHighlighter;
  241. VCodeBlockHighlightHelper *m_cbHighlighter;
  242. VPreviewManager *m_previewMgr;
  243. VTableHelper *m_tableHelper;
  244. // Image links inserted while editing.
  245. QVector<ImageLink> m_insertedImages;
  246. // Image links right at the beginning of the edit.
  247. QVector<ImageLink> m_initImages;
  248. // Mainly used for title jump.
  249. QVector<VTableOfContentItem> m_headers;
  250. bool m_freshEdit;
  251. VCopyTextAsHtmlDialog *m_textToHtmlDialog;
  252. int m_zoomDelta;
  253. VEditTab *m_editTab;
  254. int m_copyTimeStamp;
  255. // Temp file used for ExportAndCopy.
  256. QSharedPointer<QTemporaryFile> m_exportTempFile;
  257. };
  258. inline PegMarkdownHighlighter *VMdEditor::getMarkdownHighlighter() const
  259. {
  260. return m_pegHighlighter;
  261. }
  262. inline VPreviewManager *VMdEditor::getPreviewManager() const
  263. {
  264. return m_previewMgr;
  265. }
  266. #endif // VMDEDITOR_H