veditor.cpp 4.5 KB

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