veditor.cpp 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. #include <QtWidgets>
  2. #include <QTextBrowser>
  3. #include <QWebChannel>
  4. #include <QWebEngineView>
  5. #include "veditor.h"
  6. #include "vedit.h"
  7. #include "vdocument.h"
  8. #include "vnote.h"
  9. #include "utils/vutils.h"
  10. #include "vpreviewpage.h"
  11. #include "hgmarkdownhighlighter.h"
  12. #include "vconfigmanager.h"
  13. VEditor::VEditor(const QString &path, const QString &name, bool modifiable,
  14. QWidget *parent)
  15. : QStackedWidget(parent)
  16. {
  17. DocType docType = isMarkdown(name) ? DocType::Markdown : DocType::Html;
  18. QString fileText = VUtils::readFileFromDisk(QDir(path).filePath(name));
  19. noteFile = new VNoteFile(path, name, fileText, docType, modifiable);
  20. isEditMode = false;
  21. mdHighlighter = NULL;
  22. setupUI();
  23. showFileReadMode();
  24. }
  25. VEditor::~VEditor()
  26. {
  27. if (noteFile) {
  28. delete noteFile;
  29. }
  30. }
  31. void VEditor::setupUI()
  32. {
  33. textEditor = new VEdit(noteFile);
  34. addWidget(textEditor);
  35. switch (noteFile->docType) {
  36. case DocType::Markdown:
  37. setupMarkdownPreview();
  38. textBrowser = NULL;
  39. mdHighlighter = new HGMarkdownHighlighter(VConfigInst->mdHighlightingStyles,
  40. textEditor->document(), 500);
  41. break;
  42. case DocType::Html:
  43. textBrowser = new QTextBrowser();
  44. addWidget(textBrowser);
  45. textBrowser->setFont(VConfigInst->baseEditFont);
  46. webPreviewer = NULL;
  47. break;
  48. default:
  49. qWarning() << "error: unknown doc type" << int(noteFile->docType);
  50. }
  51. }
  52. bool VEditor::isMarkdown(const QString &name)
  53. {
  54. const QVector<QString> mdPostfix({"md", "markdown", "mkd"});
  55. QStringList list = name.split('.', QString::SkipEmptyParts);
  56. if (list.isEmpty()) {
  57. return false;
  58. }
  59. const QString &postfix = list.last();
  60. for (int i = 0; i < mdPostfix.size(); ++i) {
  61. if (postfix == mdPostfix[i]) {
  62. return true;
  63. }
  64. }
  65. return false;
  66. }
  67. void VEditor::showFileReadMode()
  68. {
  69. isEditMode = false;
  70. switch (noteFile->docType) {
  71. case DocType::Html:
  72. textBrowser->setHtml(noteFile->content);
  73. setCurrentWidget(textBrowser);
  74. break;
  75. case DocType::Markdown:
  76. document.setText(noteFile->content);
  77. setCurrentWidget(webPreviewer);
  78. break;
  79. default:
  80. qWarning() << "error: unknown doc type" << int(noteFile->docType);
  81. }
  82. }
  83. void VEditor::showFileEditMode()
  84. {
  85. isEditMode = true;
  86. textEditor->beginEdit();
  87. setCurrentWidget(textEditor);
  88. }
  89. bool VEditor::requestClose()
  90. {
  91. readFile();
  92. return !isEditMode;
  93. }
  94. void VEditor::editFile()
  95. {
  96. if (isEditMode || !noteFile->modifiable) {
  97. return;
  98. }
  99. showFileEditMode();
  100. }
  101. void VEditor::readFile()
  102. {
  103. if (!isEditMode) {
  104. return;
  105. }
  106. bool canExit = textEditor->tryEndEdit();
  107. if (!canExit) {
  108. // Need to save the changes
  109. QMessageBox msgBox;
  110. msgBox.setText("The note has been modified.");
  111. msgBox.setInformativeText("Do you want to save your changes?");
  112. msgBox.setIcon(QMessageBox::Information);
  113. msgBox.setStandardButtons(QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel);
  114. msgBox.setDefaultButton(QMessageBox::Save);
  115. int ret = msgBox.exec();
  116. switch (ret) {
  117. case QMessageBox::Save:
  118. saveFile();
  119. // Fall through
  120. case QMessageBox::Discard:
  121. textEditor->reloadFile();
  122. break;
  123. case QMessageBox::Cancel:
  124. // Nothing to do if user cancel this action
  125. return;
  126. default:
  127. qWarning() << "error: wrong return value from QMessageBox:" << ret;
  128. return;
  129. }
  130. }
  131. textEditor->setReadOnly(true);
  132. showFileReadMode();
  133. }
  134. bool VEditor::saveFile()
  135. {
  136. if (!isEditMode || !noteFile->modifiable) {
  137. return true;
  138. }
  139. textEditor->beginSave();
  140. bool ret = VUtils::writeFileToDisk(QDir(noteFile->path).filePath(noteFile->name),
  141. noteFile->content);
  142. if (!ret) {
  143. QMessageBox msgBox(QMessageBox::Warning, tr("Fail to save to file"),
  144. QString("Fail to write to disk when saving a note. Please try it again."));
  145. msgBox.setStandardButtons(QMessageBox::Ok);
  146. msgBox.setDefaultButton(QMessageBox::Ok);
  147. msgBox.exec();
  148. return false;
  149. }
  150. textEditor->endSave();
  151. return true;
  152. }
  153. void VEditor::setupMarkdownPreview()
  154. {
  155. webPreviewer = new QWebEngineView(this);
  156. VPreviewPage *page = new VPreviewPage(this);
  157. webPreviewer->setPage(page);
  158. QWebChannel *channel = new QWebChannel(this);
  159. channel->registerObject(QStringLiteral("content"), &document);
  160. page->setWebChannel(channel);
  161. webPreviewer->setHtml(VNote::templateHtml, QUrl::fromLocalFile(noteFile->path + QDir::separator()));
  162. addWidget(webPreviewer);
  163. }