#include #include #include #include #include #include #include #include #include #include "vnote.h" #include "utils/vutils.h" #include "vconfigmanager.h" #include "vmainwindow.h" #include "vorphanfile.h" #include "vnotefile.h" extern VConfigManager *g_config; QString VNote::s_markdownTemplate; QString VNote::s_markdownTemplatePDF; const QString VNote::c_hoedownJsFile = ":/resources/hoedown.js"; const QString VNote::c_markedJsFile = ":/resources/marked.js"; const QString VNote::c_markedExtraFile = ":/utils/marked/marked.min.js"; const QString VNote::c_markdownitJsFile = ":/resources/markdown-it.js"; const QString VNote::c_markdownitExtraFile = ":/utils/markdown-it/markdown-it.min.js"; const QString VNote::c_markdownitAnchorExtraFile = ":/utils/markdown-it/markdown-it-headinganchor.js"; const QString VNote::c_markdownitTaskListExtraFile = ":/utils/markdown-it/markdown-it-task-lists.min.js"; const QString VNote::c_markdownitSubExtraFile = ":/utils/markdown-it/markdown-it-sub.min.js"; const QString VNote::c_markdownitSupExtraFile = ":/utils/markdown-it/markdown-it-sup.min.js"; const QString VNote::c_markdownitFootnoteExtraFile = ":/utils/markdown-it/markdown-it-footnote.min.js"; const QString VNote::c_showdownJsFile = ":/resources/showdown.js"; const QString VNote::c_showdownExtraFile = ":/utils/showdown/showdown.min.js"; const QString VNote::c_showdownAnchorExtraFile = ":/utils/showdown/showdown-headinganchor.js"; const QString VNote::c_mermaidApiJsFile = ":/utils/mermaid/mermaidAPI.min.js"; const QString VNote::c_mermaidCssFile = ":/utils/mermaid/mermaid.css"; const QString VNote::c_mermaidDarkCssFile = ":/utils/mermaid/mermaid.dark.css"; const QString VNote::c_mermaidForestCssFile = ":/utils/mermaid/mermaid.forest.css"; const QString VNote::c_flowchartJsFile = ":/utils/flowchart.js/flowchart.min.js"; const QString VNote::c_raphaelJsFile = ":/utils/flowchart.js/raphael.min.js"; const QString VNote::c_highlightjsLineNumberExtraFile = ":/utils/highlightjs/highlightjs-line-numbers.min.js"; const QString VNote::c_shortcutsDocFile_en = ":/resources/docs/shortcuts_en.md"; const QString VNote::c_shortcutsDocFile_zh = ":/resources/docs/shortcuts_zh.md"; const QString VNote::c_markdownGuideDocFile_en = ":/resources/docs/markdown_guide_en.md"; const QString VNote::c_markdownGuideDocFile_zh = ":/resources/docs/markdown_guide_zh.md"; VNote::VNote(QObject *parent) : QObject(parent), m_mainWindow(dynamic_cast(parent)) { initTemplate(); g_config->getNotebooks(m_notebooks, this); } void VNote::initPalette(QPalette palette) { m_palette.clear(); m_palette.append(QPair("base-background", palette.background().color().name())); m_palette.append(QPair("base-foreground", palette.background().color().name())); m_palette.append(QPair("hover-color", "#42A5F5")); m_palette.append(QPair("base-color", "#BDBDBD")); m_palette.append(QPair("focus-color", "#75C5B5")); m_palette.append(QPair("logo-base", "#D6EACE")); m_palette.append(QPair("logo-max", "#15AE67")); m_palette.append(QPair("logo-min", "#75C5B5")); // Material Design Colors m_palette.append(QPair("Teal0", "#E0F2F1")); m_palette.append(QPair("Teal1", "#B2DFDB")); m_palette.append(QPair("Teal2", "#80CBC4")); m_palette.append(QPair("Teal3", "#4DB6AC")); m_palette.append(QPair("Teal4", "#26A69A")); m_palette.append(QPair("Teal5", "#009688")); m_palette.append(QPair("Teal6", "#00897B")); m_palette.append(QPair("Teal7", "#00796B")); m_palette.append(QPair("Teal8", "#00695C")); m_palette.append(QPair("Teal9", "#004D40")); m_palette.append(QPair("Indigo0", "#E8EAF6")); m_palette.append(QPair("Indigo1", "#C5CAE9")); m_palette.append(QPair("Indigo2", "#9FA8DA")); m_palette.append(QPair("Indigo3", "#7986CB")); m_palette.append(QPair("Indigo4", "#5C6BC0")); m_palette.append(QPair("Grey0", "#FAFAFA")); m_palette.append(QPair("Grey1", "#F5F5F5")); m_palette.append(QPair("Grey2", "#EEEEEE")); m_palette.append(QPair("Grey3", "#E0E0E0")); m_palette.append(QPair("Grey4", "#BDBDBD")); m_palette.append(QPair("Grey5", "#9E9E9E")); m_palette.append(QPair("Grey6", "#757575")); m_palette.append(QPair("Grey7", "#616161")); m_palette.append(QPair("Grey8", "#424242")); m_palette.append(QPair("Green0", "#E8F5E9")); m_palette.append(QPair("Green1", "#C8E6C9")); m_palette.append(QPair("Green2", "#A5D6A7")); m_palette.append(QPair("Green3", "#81C784")); m_palette.append(QPair("Green4", "#66BB6A")); m_palette.append(QPair("Green5", "#4CAF50")); m_palette.append(QPair("Green6", "#43A047")); m_palette.append(QPair("Green7", "#388E3C")); m_palette.append(QPair("Green8", "#2E7D32")); m_palette.append(QPair("Green9", "#1B5E20")); m_palette.append(QPair("DeepPurple0", "#EDE7F6")); m_palette.append(QPair("DeepPurple1", "#D1C4E9")); m_palette.append(QPair("DeepPurple2", "#B39DDB")); m_palette.append(QPair("DeepPurple3", "#9575CD")); m_palette.append(QPair("DeepPurple4", "#7E57C2")); m_palette.append(QPair("DeepPurple5", "#673AB7")); m_palette.append(QPair("DeepPurple6", "#5E35B1")); m_palette.append(QPair("DeepPurple7", "#512DA8")); m_palette.append(QPair("DeepPurple8", "#4527A0")); m_palette.append(QPair("DeepPurple9", "#311B92")); m_palette.append(QPair("Purple0", "#F3E5F5")); m_palette.append(QPair("Purple1", "#E1BEE7")); m_palette.append(QPair("Purple2", "#CE93D8")); m_palette.append(QPair("Purple3", "#BA68C8")); m_palette.append(QPair("Purple4", "#AB47BC")); m_palette.append(QPair("Purple5", "#9C27B0")); m_palette.append(QPair("Purple6", "#8E24AA")); m_palette.append(QPair("Purple7", "#7B1FA2")); m_palette.append(QPair("Purple8", "#6A1B9A")); m_palette.append(QPair("Purple9", "#4A148C")); m_palette.append(QPair("Red0", "#FFEBEE")); m_palette.append(QPair("Red1", "#FFCDD2")); m_palette.append(QPair("Red2", "#EF9A9A")); m_palette.append(QPair("Red3", "#E57373")); m_palette.append(QPair("Red4", "#EF5350")); m_palette.append(QPair("Red5", "#F44336")); m_palette.append(QPair("Red6", "#E53935")); m_palette.append(QPair("Red7", "#D32F2F")); m_palette.append(QPair("Red8", "#C62828")); m_palette.append(QPair("Red9", "#B71C1C")); } QString VNote::getColorFromPalette(const QString &p_name) const { for (int i = 0; i < m_palette.size(); ++i) { if (m_palette[i].first == p_name) { return m_palette[i].second; } } return "White"; } void VNote::initTemplate() { if (s_markdownTemplate.isEmpty()) { updateTemplate(); } } void VNote::updateTemplate() { const QString c_markdownTemplatePath(":/resources/markdown_template.html"); // Get background color QString rgb; const QString &curRenderBg = g_config->getCurRenderBackgroundColor(); const QVector &predefinedColors = g_config->getPredefinedColors(); if (curRenderBg != "System") { for (int i = 0; i < predefinedColors.size(); ++i) { if (predefinedColors[i].name == curRenderBg) { rgb = predefinedColors[i].rgb; break; } } } QString cssStyle; if (!rgb.isEmpty()) { cssStyle += "body { background-color: #" + rgb + " !important; }\n"; } if (g_config->getEnableImageConstraint()) { // Constain the image width. cssStyle += "img { max-width: 100% !important; height: auto !important; }\n"; } const QString styleHolder(""); const QString cssHolder("CSS_PLACE_HOLDER"); s_markdownTemplate = VUtils::readFileFromDisk(c_markdownTemplatePath); s_markdownTemplate.replace(cssHolder, g_config->getTemplateCssUrl()); s_markdownTemplatePDF = s_markdownTemplate; if (!cssStyle.isEmpty()) { s_markdownTemplate.replace(styleHolder, cssStyle); } // Shoudl not display scrollbar in PDF. cssStyle += "pre code { white-space: pre-wrap !important; " "word-break: break-all !important; }\n"; if (!g_config->getEnableImageConstraint()) { // Constain the image width by force in PDF, otherwise, the PDF will // be cut off. cssStyle += "img { max-width: 100% !important; height: auto !important; }\n"; } s_markdownTemplatePDF.replace(styleHolder, cssStyle); } const QVector &VNote::getNotebooks() const { return m_notebooks; } QVector &VNote::getNotebooks() { return m_notebooks; } QString VNote::getNavigationLabelStyle(const QString &p_str) const { static int lastLen = -1; static int pxWidth = 24; int fontPt = 15; QString fontFamily = getMonospacedFont(); if (p_str.size() != lastLen) { QFont font(fontFamily, fontPt); font.setBold(true); QFontMetrics fm(font); pxWidth = fm.width(p_str); lastLen = p_str.size(); } return QString("background-color: %1;" "color: %2;" "font-size: %3pt;" "font: bold;" "font-family: %4;" "border-radius: 3px;" "min-width: %5px;" "max-width: %5px;") .arg(getColorFromPalette("logo-base")) .arg(getColorFromPalette("logo-max")) .arg(fontPt) .arg(fontFamily) .arg(pxWidth); } const QString &VNote::getMonospacedFont() const { static QString font; if (font.isNull()) { QStringList candidates; candidates << "Consolas" << "Monaco" << "Andale Mono" << "Monospace" << "Courier New"; QStringList availFamilies = QFontDatabase().families(); for (int i = 0; i < candidates.size(); ++i) { QString family = candidates[i].trimmed().toLower(); for (int j = 0; j < availFamilies.size(); ++j) { QString availFamily = availFamilies[j]; availFamily.remove(QRegExp("\\[.*\\]")); if (family == availFamily.trimmed().toLower()) { font = availFamily; return font; } } } // Fallback to current font. font = QFont().family(); } return font; } VOrphanFile *VNote::getOrphanFile(const QString &p_path, bool p_modifiable, bool p_systemFile) { if (p_path.isEmpty()) { return NULL; } QString path = QDir::cleanPath(p_path); // See if the file has already been opened before. for (auto const &file : m_externalFiles) { if (VUtils::equalPath(QDir::cleanPath(file->fetchPath()), path)) { Q_ASSERT(file->isModifiable() == p_modifiable); Q_ASSERT(file->isSystemFile() == p_systemFile); return file; } } for (int i = 0; i < m_externalFiles.size(); ++i) { VOrphanFile *file = m_externalFiles[i]; if (!file->isOpened()) { qDebug() << "release orphan file" << file; m_externalFiles.removeAt(i); delete file; --i; } } // Create a VOrphanFile for path. VOrphanFile *file = new VOrphanFile(this, path, p_modifiable, p_systemFile); m_externalFiles.append(file); return file; } VNoteFile *VNote::getInternalFile(const QString &p_path) { VNoteFile *file = NULL; for (auto & nb : m_notebooks) { file = nb->tryLoadFile(p_path); if (file) { break; } } return file; }