vnote.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. #include <QSettings>
  2. #include <QDebug>
  3. #include <QJsonObject>
  4. #include <QJsonArray>
  5. #include <QDir>
  6. #include <QFont>
  7. #include <QFontMetrics>
  8. #include <QStringList>
  9. #include <QFontDatabase>
  10. #include "vnote.h"
  11. #include "utils/vutils.h"
  12. #include "vconfigmanager.h"
  13. #include "vmainwindow.h"
  14. #include "vorphanfile.h"
  15. extern VConfigManager vconfig;
  16. QString VNote::s_markdownTemplate;
  17. const QString VNote::c_hoedownJsFile = ":/resources/hoedown.js";
  18. const QString VNote::c_markedJsFile = ":/resources/marked.js";
  19. const QString VNote::c_markedExtraFile = ":/utils/marked/marked.min.js";
  20. const QString VNote::c_markdownitJsFile = ":/resources/markdown-it.js";
  21. const QString VNote::c_markdownitExtraFile = ":/utils/markdown-it/markdown-it.min.js";
  22. const QString VNote::c_markdownitAnchorExtraFile = ":/utils/markdown-it/markdown-it-headinganchor.js";
  23. const QString VNote::c_markdownitTaskListExtraFile = ":/utils/markdown-it/markdown-it-task-lists.min.js";
  24. const QString VNote::c_mermaidApiJsFile = ":/utils/mermaid/mermaidAPI.min.js";
  25. const QString VNote::c_mermaidCssFile = ":/utils/mermaid/mermaid.css";
  26. const QString VNote::c_mermaidDarkCssFile = ":/utils/mermaid/mermaid.dark.css";
  27. const QString VNote::c_mermaidForestCssFile = ":/utils/mermaid/mermaid.forest.css";
  28. const QString VNote::c_mathjaxJsFile = "https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-MML-AM_CHTML";
  29. const QString VNote::c_shortcutsDocFile_en = ":/resources/docs/shortcuts_en.md";
  30. const QString VNote::c_shortcutsDocFile_zh = ":/resources/docs/shortcuts_zh.md";
  31. VNote::VNote(QObject *parent)
  32. : QObject(parent), m_mainWindow(dynamic_cast<VMainWindow *>(parent))
  33. {
  34. initTemplate();
  35. vconfig.getNotebooks(m_notebooks, this);
  36. }
  37. void VNote::initPalette(QPalette palette)
  38. {
  39. m_palette.clear();
  40. m_palette.append(QPair<QString, QString>("base-background",
  41. palette.background().color().name()));
  42. m_palette.append(QPair<QString, QString>("base-foreground",
  43. palette.background().color().name()));
  44. m_palette.append(QPair<QString, QString>("hover-color", "#42A5F5"));
  45. m_palette.append(QPair<QString, QString>("base-color", "#BDBDBD"));
  46. m_palette.append(QPair<QString, QString>("focus-color", "#75C5B5"));
  47. m_palette.append(QPair<QString, QString>("logo-base", "#D6EACE"));
  48. m_palette.append(QPair<QString, QString>("logo-max", "#15AE67"));
  49. m_palette.append(QPair<QString, QString>("logo-min", "#75C5B5"));
  50. // Material Design Colors
  51. m_palette.append(QPair<QString, QString>("Teal0", "#E0F2F1"));
  52. m_palette.append(QPair<QString, QString>("Teal1", "#B2DFDB"));
  53. m_palette.append(QPair<QString, QString>("Teal2", "#80CBC4"));
  54. m_palette.append(QPair<QString, QString>("Teal3", "#4DB6AC"));
  55. m_palette.append(QPair<QString, QString>("Teal4", "#26A69A"));
  56. m_palette.append(QPair<QString, QString>("Teal5", "#009688"));
  57. m_palette.append(QPair<QString, QString>("Indigo0", "#E8EAF6"));
  58. m_palette.append(QPair<QString, QString>("Indigo1", "#C5CAE9"));
  59. m_palette.append(QPair<QString, QString>("Indigo2", "#9FA8DA"));
  60. m_palette.append(QPair<QString, QString>("Indigo3", "#7986CB"));
  61. m_palette.append(QPair<QString, QString>("Indigo4", "#5C6BC0"));
  62. m_palette.append(QPair<QString, QString>("Grey0", "#FAFAFA"));
  63. m_palette.append(QPair<QString, QString>("Grey1", "#F5F5F5"));
  64. m_palette.append(QPair<QString, QString>("Grey2", "#EEEEEE"));
  65. m_palette.append(QPair<QString, QString>("Grey3", "#E0E0E0"));
  66. m_palette.append(QPair<QString, QString>("Grey4", "#BDBDBD"));
  67. m_palette.append(QPair<QString, QString>("Grey5", "#9E9E9E"));
  68. m_palette.append(QPair<QString, QString>("Grey6", "#757575"));
  69. m_palette.append(QPair<QString, QString>("Grey7", "#616161"));
  70. m_palette.append(QPair<QString, QString>("Grey8", "#424242"));
  71. m_palette.append(QPair<QString, QString>("Green0", "#E8F5E9"));
  72. m_palette.append(QPair<QString, QString>("Green1", "#C8E6C9"));
  73. m_palette.append(QPair<QString, QString>("Green2", "#A5D6A7"));
  74. m_palette.append(QPair<QString, QString>("Green3", "#81C784"));
  75. m_palette.append(QPair<QString, QString>("Green4", "#66BB6A"));
  76. m_palette.append(QPair<QString, QString>("Green5", "#4CAF50"));
  77. m_palette.append(QPair<QString, QString>("Green6", "#43A047"));
  78. m_palette.append(QPair<QString, QString>("Green7", "#388E3C"));
  79. m_palette.append(QPair<QString, QString>("Green8", "#2E7D32"));
  80. m_palette.append(QPair<QString, QString>("Green9", "#1B5E20"));
  81. m_palette.append(QPair<QString, QString>("DeepPurple0", "#EDE7F6"));
  82. m_palette.append(QPair<QString, QString>("DeepPurple1", "#D1C4E9"));
  83. m_palette.append(QPair<QString, QString>("DeepPurple2", "#B39DDB"));
  84. m_palette.append(QPair<QString, QString>("DeepPurple3", "#9575CD"));
  85. m_palette.append(QPair<QString, QString>("DeepPurple4", "#7E57C2"));
  86. m_palette.append(QPair<QString, QString>("DeepPurple5", "#673AB7"));
  87. m_palette.append(QPair<QString, QString>("DeepPurple6", "#5E35B1"));
  88. m_palette.append(QPair<QString, QString>("DeepPurple7", "#512DA8"));
  89. m_palette.append(QPair<QString, QString>("DeepPurple8", "#4527A0"));
  90. m_palette.append(QPair<QString, QString>("DeepPurple9", "#311B92"));
  91. m_palette.append(QPair<QString, QString>("Purple0", "#F3E5F5"));
  92. m_palette.append(QPair<QString, QString>("Purple1", "#E1BEE7"));
  93. m_palette.append(QPair<QString, QString>("Purple2", "#CE93D8"));
  94. m_palette.append(QPair<QString, QString>("Purple3", "#BA68C8"));
  95. m_palette.append(QPair<QString, QString>("Purple4", "#AB47BC"));
  96. m_palette.append(QPair<QString, QString>("Purple5", "#9C27B0"));
  97. m_palette.append(QPair<QString, QString>("Purple6", "#8E24AA"));
  98. m_palette.append(QPair<QString, QString>("Purple7", "#7B1FA2"));
  99. m_palette.append(QPair<QString, QString>("Purple8", "#6A1B9A"));
  100. m_palette.append(QPair<QString, QString>("Purple9", "#4A148C"));
  101. m_palette.append(QPair<QString, QString>("Red0", "#FFEBEE"));
  102. m_palette.append(QPair<QString, QString>("Red1", "#FFCDD2"));
  103. m_palette.append(QPair<QString, QString>("Red2", "#EF9A9A"));
  104. m_palette.append(QPair<QString, QString>("Red3", "#E57373"));
  105. m_palette.append(QPair<QString, QString>("Red4", "#EF5350"));
  106. m_palette.append(QPair<QString, QString>("Red5", "#F44336"));
  107. m_palette.append(QPair<QString, QString>("Red6", "#E53935"));
  108. m_palette.append(QPair<QString, QString>("Red7", "#D32F2F"));
  109. m_palette.append(QPair<QString, QString>("Red8", "#C62828"));
  110. m_palette.append(QPair<QString, QString>("Red9", "#B71C1C"));
  111. }
  112. QString VNote::getColorFromPalette(const QString &p_name) const
  113. {
  114. for (int i = 0; i < m_palette.size(); ++i) {
  115. if (m_palette[i].first == p_name) {
  116. return m_palette[i].second;
  117. }
  118. }
  119. return "White";
  120. }
  121. void VNote::initTemplate()
  122. {
  123. if (s_markdownTemplate.isEmpty()) {
  124. updateTemplate();
  125. }
  126. }
  127. void VNote::updateTemplate()
  128. {
  129. const QString c_markdownTemplatePath(":/resources/markdown_template.html");
  130. // Get background color
  131. QString rgb;
  132. const QString &curRenderBg = vconfig.getCurRenderBackgroundColor();
  133. const QVector<VColor> &predefinedColors = vconfig.getPredefinedColors();
  134. if (curRenderBg != "System") {
  135. for (int i = 0; i < predefinedColors.size(); ++i) {
  136. if (predefinedColors[i].name == curRenderBg) {
  137. rgb = predefinedColors[i].rgb;
  138. break;
  139. }
  140. }
  141. }
  142. QString cssStyle;
  143. if (!rgb.isEmpty()) {
  144. cssStyle += "body { background-color: #" + rgb + " !important; }\n";
  145. }
  146. if (vconfig.getEnableImageConstraint()) {
  147. // Constain the image width.
  148. cssStyle += "img { max-width: 100% !important; height: auto !important; }\n";
  149. }
  150. QString styleHolder("<!-- BACKGROUND_PLACE_HOLDER -->");
  151. QString cssHolder("CSS_PLACE_HOLDER");
  152. s_markdownTemplate = VUtils::readFileFromDisk(c_markdownTemplatePath);
  153. s_markdownTemplate.replace(cssHolder, vconfig.getTemplateCssUrl());
  154. if (!cssStyle.isEmpty()) {
  155. s_markdownTemplate.replace(styleHolder, cssStyle);
  156. }
  157. }
  158. const QVector<VNotebook *> &VNote::getNotebooks() const
  159. {
  160. return m_notebooks;
  161. }
  162. QVector<VNotebook *> &VNote::getNotebooks()
  163. {
  164. return m_notebooks;
  165. }
  166. QString VNote::getNavigationLabelStyle(const QString &p_str) const
  167. {
  168. static int lastLen = -1;
  169. static int pxWidth = 24;
  170. int fontPt = 15;
  171. QString fontFamily = getMonospacedFont();
  172. if (p_str.size() != lastLen) {
  173. QFont font(fontFamily, fontPt);
  174. font.setBold(true);
  175. QFontMetrics fm(font);
  176. pxWidth = fm.width(p_str);
  177. lastLen = p_str.size();
  178. }
  179. return QString("background-color: %1;"
  180. "color: %2;"
  181. "font-size: %3pt;"
  182. "font: bold;"
  183. "font-family: %4;"
  184. "border-radius: 3px;"
  185. "min-width: %5px;"
  186. "max-width: %5px;")
  187. .arg(getColorFromPalette("logo-base"))
  188. .arg(getColorFromPalette("logo-max"))
  189. .arg(fontPt)
  190. .arg(fontFamily)
  191. .arg(pxWidth);
  192. }
  193. const QString &VNote::getMonospacedFont() const
  194. {
  195. static QString font;
  196. if (font.isNull()) {
  197. QStringList candidates;
  198. candidates << "Consolas" << "Monaco" << "Andale Mono" << "Monospace" << "Courier New";
  199. QStringList availFamilies = QFontDatabase().families();
  200. for (int i = 0; i < candidates.size(); ++i) {
  201. QString family = candidates[i].trimmed().toLower();
  202. for (int j = 0; j < availFamilies.size(); ++j) {
  203. QString availFamily = availFamilies[j];
  204. availFamily.remove(QRegExp("\\[.*\\]"));
  205. if (family == availFamily.trimmed().toLower()) {
  206. font = availFamily;
  207. return font;
  208. }
  209. }
  210. }
  211. // Fallback to current font.
  212. font = QFont().family();
  213. }
  214. return font;
  215. }
  216. VFile *VNote::getOrphanFile(const QString &p_path)
  217. {
  218. if (p_path.isEmpty()) {
  219. return NULL;
  220. }
  221. // See if the file has already been opened before.
  222. for (auto const &file : m_externalFiles) {
  223. if (file->getType() == FileType::Orphan && file->retrivePath() == p_path) {
  224. qDebug() << "find a VFile for path" << p_path;
  225. return file;
  226. }
  227. }
  228. // TODO: Clean up unopened file here.
  229. // Create a VOrphanFile for p_path.
  230. VOrphanFile *file = new VOrphanFile(p_path, this);
  231. m_externalFiles.append(file);
  232. return file;
  233. }