فهرست منبع

add VStyleParser as a wrapper of pmh_styleparser

Use VStyleParser to read .mdhl style file for markdown highlighting.

Signed-off-by: Le Tan <[email protected]>
Le Tan 9 سال پیش
والد
کامیت
d22f0124d3
16فایلهای تغییر یافته به همراه532 افزوده شده و 74 حذف شده
  1. 6 2
      VNote.pro
  2. 8 62
      hgmarkdownhighlighter.cpp
  3. 2 2
      hgmarkdownhighlighter.h
  4. 79 0
      resources/styles/default.mdhl
  5. 79 0
      resources/styles/solarized-dark.mdhl
  6. 80 0
      resources/styles/solarized-light.mdhl
  7. 37 0
      vconfigmanager.cpp
  8. 19 2
      vconfigmanager.h
  9. 5 1
      vedit.cpp
  10. 4 2
      veditor.cpp
  11. 2 0
      vmainwindow.cpp
  12. 0 2
      vnote.cpp
  13. 0 1
      vnote.h
  14. 3 0
      vnote.qrc
  15. 174 0
      vstyleparser.cpp
  16. 34 0
      vstyleparser.h

+ 6 - 2
VNote.pro

@@ -29,7 +29,9 @@ SOURCES += main.cpp\
     utils/vutils.cpp \
     vpreviewpage.cpp \
     utils/peg-highlight/pmh_parser.c \
-    hgmarkdownhighlighter.cpp
+    hgmarkdownhighlighter.cpp \
+    vstyleparser.cpp \
+    utils/peg-highlight/pmh_styleparser.c
 
 HEADERS  += vmainwindow.h \
     vdirectorytree.h \
@@ -49,7 +51,9 @@ HEADERS  += vmainwindow.h \
     vpreviewpage.h \
     utils/peg-highlight/pmh_parser.h \
     hgmarkdownhighlighter.h \
-    utils/peg-highlight/pmh_definitions.h
+    utils/peg-highlight/pmh_definitions.h \
+    vstyleparser.h \
+    utils/peg-highlight/pmh_styleparser.h
 
 RESOURCES += \
     vnote.qrc

+ 8 - 62
hgmarkdownhighlighter.cpp

@@ -18,8 +18,7 @@
 const int WorkerThread::initCapacity = 1024;
 
 WorkerThread::WorkerThread()
-    : QThread(NULL), content(NULL), result(NULL),
-      capacity(0)
+    : QThread(NULL), content(NULL), capacity(0), result(NULL)
 {
     resizeBuffer(initCapacity);
 }
@@ -86,12 +85,14 @@ void WorkerThread::run()
 }
 
 // Will be freeed by parent automatically
-HGMarkdownHighlighter::HGMarkdownHighlighter(QTextDocument *parent,
+HGMarkdownHighlighter::HGMarkdownHighlighter(const QVector<HighlightingStyle> &styles,
+                                             QTextDocument *parent,
                                              int aWaitInterval) : QObject(parent)
 {
     workerThread = new WorkerThread();
     cached_elements = NULL;
     waitInterval = aWaitInterval;
+    setStyles(styles);
     timer = new QTimer(this);
     timer->setSingleShot(true);
     timer->setInterval(aWaitInterval);
@@ -123,63 +124,6 @@ void HGMarkdownHighlighter::setStyles(const QVector<HighlightingStyle> &styles)
     this->highlightingStyles = styles;
 }
 
-#define STY(type, format) styles.append({type, format})
-
-void HGMarkdownHighlighter::setDefaultStyles()
-{
-    QVector<HighlightingStyle> &styles = this->highlightingStyles;
-    styles.clear();
-
-    QTextCharFormat headers; headers.setForeground(QBrush(Qt::darkBlue));
-    headers.setBackground(QBrush(QColor(230,230,240)));
-    STY(pmh_H1, headers);
-    STY(pmh_H2, headers);
-    STY(pmh_H3, headers);
-    STY(pmh_H4, headers);
-    STY(pmh_H5, headers);
-    STY(pmh_H6, headers);
-
-    QTextCharFormat hrule; hrule.setForeground(QBrush(Qt::darkGray));
-    hrule.setBackground(QBrush(Qt::lightGray));
-    STY(pmh_HRULE, hrule);
-
-    QTextCharFormat list; list.setForeground(QBrush(Qt::magenta));
-    STY(pmh_LIST_BULLET, list);
-    STY(pmh_LIST_ENUMERATOR, list);
-
-    QTextCharFormat link; link.setForeground(QBrush(Qt::darkCyan));
-    link.setBackground(QBrush(QColor(205,240,240)));
-    STY(pmh_LINK, link);
-    STY(pmh_AUTO_LINK_URL, link);
-    STY(pmh_AUTO_LINK_EMAIL, link);
-
-    QTextCharFormat image; image.setForeground(QBrush(Qt::darkCyan));
-    image.setBackground(QBrush(Qt::cyan));
-    STY(pmh_IMAGE, image);
-
-    QTextCharFormat ref; ref.setForeground(QBrush(QColor(213,178,178)));
-    STY(pmh_REFERENCE, ref);
-
-    QTextCharFormat code; code.setForeground(QBrush(Qt::darkGreen));
-    code.setBackground(QBrush(QColor(217,231,217)));
-    STY(pmh_CODE, code);
-    STY(pmh_VERBATIM, code);
-
-    QTextCharFormat emph; emph.setForeground(QBrush(Qt::darkYellow));
-    emph.setFontItalic(true);
-    STY(pmh_EMPH, emph);
-
-    QTextCharFormat strong; strong.setForeground(QBrush(Qt::magenta));
-    strong.setFontWeight(QFont::Bold);
-    STY(pmh_STRONG, strong);
-
-    QTextCharFormat comment; comment.setForeground(QBrush(Qt::gray));
-    STY(pmh_COMMENT, comment);
-
-    QTextCharFormat blockquote; blockquote.setForeground(QBrush(Qt::darkRed));
-    STY(pmh_BLOCKQUOTE, blockquote);
-}
-
 void HGMarkdownHighlighter::clearFormatting()
 {
     QTextBlock block = document->firstBlock();
@@ -195,8 +139,10 @@ void HGMarkdownHighlighter::highlight()
         return;
     }
 
-    if (highlightingStyles.isEmpty())
-        this->setDefaultStyles();
+    if (highlightingStyles.isEmpty()) {
+        qWarning() << "error: HighlightingStyles is not set";
+        return;
+    }
 
     this->clearFormatting();
 

+ 2 - 2
hgmarkdownhighlighter.h

@@ -52,7 +52,8 @@ class HGMarkdownHighlighter : public QObject
     Q_OBJECT
 
 public:
-    HGMarkdownHighlighter(QTextDocument *parent = 0, int aWaitInterval = 2000);
+    HGMarkdownHighlighter(const QVector<HighlightingStyle> &styles,
+                          QTextDocument *parent = 0, int aWaitInterval = 2000);
     ~HGMarkdownHighlighter();
     void setStyles(const QVector<HighlightingStyle> &styles);
     int waitInterval;
@@ -73,7 +74,6 @@ private:
     void clearFormatting();
     void highlight();
     void parse();
-    void setDefaultStyles();
 };
 
 #endif

+ 79 - 0
resources/styles/default.mdhl

@@ -0,0 +1,79 @@
+# This is the default markdown styles used for Peg-Markdown-Highlight
+# Created by Le Tan ([email protected])
+
+H1
+foreground: 111111
+font-style: bold
+font-size: +12
+
+H2
+foreground: 111111
+font-style: bold
+font-size: +10
+
+H3
+foreground: 111111
+font-style: bold
+font-size: +8
+
+H4
+foreground: 111111
+font-size: +6
+
+H5
+foreground: 111111
+font-size: +4
+
+H6
+foreground: 111111
+font-size: +2
+
+HRULE
+foreground: 586e75
+
+LIST_BULLET
+foreground: d33682
+font-style: bold
+font-size: +2
+
+LIST_ENUMERATOR
+foreground: 0000ff
+
+LINK
+foreground: 2aa198
+
+AUTO_LINK_URL
+foreground: 2aa198
+
+AUTO_LINK_EMAIL
+foreground: 2aa198
+
+IMAGE
+foreground: d33682
+
+REFERENCE
+foreground: b58900
+
+CODE
+foreground: 5f00ff
+
+EMPH
+font-style: italic
+
+STRONG
+font-style: bold
+
+HTML_ENTITY
+foreground: 6c71c4
+
+COMMENT
+foreground: 93a1a1
+
+VERBATIM
+foreground: 859900
+
+BLOCKQUOTE
+foreground: 00af00
+
+STRIKE
+strike-color: 586e75

+ 79 - 0
resources/styles/solarized-dark.mdhl

@@ -0,0 +1,79 @@
+# Styles using 'Solarized' color scheme
+# by Ethan Schoonover: http://ethanschoonover.com/solarized
+# 
+# (dark background version)
+
+editor
+foreground: 93a1a1 # base1
+background: 002b36 # base03
+caret: ffffff
+
+H1
+foreground: 6c71c4 # violet
+font-style: bold
+
+H2
+foreground: 6c71c4 # violet
+font-style: bold
+
+H3
+foreground: 6c71c4 # violet
+
+H4
+foreground: 268bd2 # blue
+
+H5
+foreground: 268bd2 # blue
+
+H6
+foreground: 268bd2 # blue
+
+HRULE
+foreground: 586e75 # base01
+
+LIST_BULLET
+foreground: b58900 # yellow
+
+LIST_ENUMERATOR
+foreground: b58900 # yellow
+
+LINK
+foreground: 2aa198 # cyan
+
+AUTO_LINK_URL
+foreground: 2aa198 # cyan
+
+AUTO_LINK_EMAIL
+foreground: 2aa198 # cyan
+
+IMAGE
+foreground: d33682 # magenta
+
+REFERENCE
+foreground: 80b58900 # yellow, reduced alpha
+
+CODE
+foreground: 859900 # green
+
+EMPH
+foreground: cb4b16 # orange
+font-style: italic
+
+STRONG
+foreground: dc322f # red
+font-style: bold
+
+HTML_ENTITY
+foreground: 6c71c4 # violet
+
+COMMENT
+foreground: 93a1a1 # base1
+
+VERBATIM
+foreground: 859900 # green
+
+BLOCKQUOTE
+foreground: d33682 # magenta
+
+STRIKE
+strike-color: 93a1a1 # base1

+ 80 - 0
resources/styles/solarized-light.mdhl

@@ -0,0 +1,80 @@
+# Styles using 'Solarized' color scheme
+# by Ethan Schoonover: http://ethanschoonover.com/solarized
+# 
+# (light background version)
+
+editor
+foreground: 586e75 # base01
+background: fdf6e3 # base3
+caret: 000000
+
+H1
+foreground: 6c71c4 # violet
+font-style: bold
+
+H2
+foreground: 6c71c4 # violet
+font-style: bold
+
+H3
+foreground: 6c71c4 # violet
+
+H4
+foreground: 268bd2 # blue
+
+H5
+foreground: 268bd2 # blue
+
+H6
+foreground: 268bd2 # blue
+
+HRULE
+foreground: 586e75 # base01
+
+LIST_BULLET
+foreground: b58900 # yellow
+
+LIST_ENUMERATOR
+foreground: b58900 # yellow
+
+LINK
+foreground: 2aa198 # cyan
+
+AUTO_LINK_URL
+foreground: 2aa198 # cyan
+
+AUTO_LINK_EMAIL
+foreground: 2aa198 # cyan
+
+IMAGE
+foreground: d33682 # magenta
+
+REFERENCE
+foreground: 80b58900 # yellow, reduced alpha
+
+CODE
+foreground: 859900 # green
+
+EMPH
+foreground: cb4b16 # orange
+font-style: italic
+
+STRONG
+foreground: dc322f # red
+font-style: bold
+
+HTML_ENTITY
+foreground: 6c71c4 # violet
+
+COMMENT
+foreground: 93a1a1 # base1
+
+VERBATIM
+foreground: 859900 # green
+
+BLOCKQUOTE
+foreground: d33682 # magenta
+
+STRIKE
+strike-color: 586e75 # base01
+

+ 37 - 0
vconfigmanager.cpp

@@ -6,12 +6,33 @@
 #include <QJsonObject>
 #include <QJsonDocument>
 #include <QtDebug>
+#include <QTextEdit>
+#include "utils/vutils.h"
+#include "vstyleparser.h"
 
 const QString VConfigManager::dirConfigFileName = QString(".vnote.json");
+VConfigManager* VConfigManager::instance = NULL;
 
 VConfigManager::VConfigManager()
+    : baseEditFont(QFont())
 {
+}
+
+VConfigManager* VConfigManager::getInst()
+{
+    if (!instance) {
+        instance = new VConfigManager();
+        instance->initialize();
+    }
+    return instance;
+}
+
+void VConfigManager::initialize()
+{
+    baseEditFont.setPointSize(11);
+    baseEditPalette = QTextEdit().palette();
 
+    updateMarkdownEditStyle();
 }
 
 QJsonObject VConfigManager::readDirectoryConfig(const QString &path)
@@ -60,3 +81,19 @@ bool VConfigManager::deleteDirectoryConfig(const QString &path)
     qDebug() << "delete config file:" << configFile;
     return true;
 }
+
+void VConfigManager::updateMarkdownEditStyle()
+{
+    // Read style file .mdhl
+    QString file(":/resources/styles/default.mdhl");
+
+    QString styleStr = VUtils::readFileFromDisk(file);
+    if (styleStr.isEmpty()) {
+        return;
+    }
+
+    VStyleParser parser;
+    parser.parseMarkdownStyle(styleStr);
+    mdHighlightingStyles = parser.fetchMarkdownStyles(baseEditFont);
+    mdEditPalette = parser.fetchMarkdownEditorStyles(baseEditPalette);
+}

+ 19 - 2
vconfigmanager.h

@@ -1,22 +1,39 @@
 #ifndef VCONFIGMANAGER_H
 #define VCONFIGMANAGER_H
 
+#include <QFont>
+#include <QPalette>
+#include <QVector>
+
+#include "hgmarkdownhighlighter.h"
+
 class QJsonObject;
 class QString;
 
+#define VConfigInst VConfigManager::getInst()
+
 class VConfigManager
 {
 public:
-    VConfigManager();
-
+    static VConfigManager *getInst();
     // Read config from the directory config json file into a QJsonObject
     static QJsonObject readDirectoryConfig(const QString &path);
     static bool writeDirectoryConfig(const QString &path, const QJsonObject &configJson);
     static bool deleteDirectoryConfig(const QString &path);
 
+    void updateMarkdownEditStyle();
+
+    QFont baseEditFont;
+    QPalette baseEditPalette;
+    QPalette mdEditPalette;
+    QVector<HighlightingStyle> mdHighlightingStyles;
+
 private:
+    VConfigManager();
+    void initialize();
     // The name of the config file in each directory
     static const QString dirConfigFileName;
+    static VConfigManager *instance;
 };
 
 #endif // VCONFIGMANAGER_H

+ 5 - 1
vedit.cpp

@@ -1,11 +1,15 @@
 #include <QtWidgets>
 #include "vedit.h"
 #include "vnote.h"
+#include "vconfigmanager.h"
 
 VEdit::VEdit(VNoteFile *noteFile, QWidget *parent)
     : QTextEdit(parent), noteFile(noteFile)
 {
-    setFont(VNote::editorAndBrowserFont);
+    setFont(VConfigInst->baseEditFont);
+    if (noteFile->docType == DocType::Markdown) {
+        setPalette(VConfigInst->mdEditPalette);
+    }
 }
 
 void VEdit::beginEdit()

+ 4 - 2
veditor.cpp

@@ -9,6 +9,7 @@
 #include "utils/vutils.h"
 #include "vpreviewpage.h"
 #include "hgmarkdownhighlighter.h"
+#include "vconfigmanager.h"
 
 VEditor::VEditor(const QString &path, const QString &name, bool modifiable,
                  QWidget *parent)
@@ -43,13 +44,14 @@ void VEditor::setupUI()
         setupMarkdownPreview();
         textBrowser = NULL;
 
-        mdHighlighter = new HGMarkdownHighlighter(textEditor->document(), 500);
+        mdHighlighter = new HGMarkdownHighlighter(VConfigInst->mdHighlightingStyles,
+                                                  textEditor->document(), 500);
         break;
 
     case DocType::Html:
         textBrowser = new QTextBrowser();
         addWidget(textBrowser);
-        textBrowser->setFont(VNote::editorAndBrowserFont);
+        textBrowser->setFont(VConfigInst->baseEditFont);
         webPreviewer = NULL;
         break;
     default:

+ 2 - 0
vmainwindow.cpp

@@ -4,10 +4,12 @@
 #include "vnote.h"
 #include "vfilelist.h"
 #include "vtabwidget.h"
+#include "vconfigmanager.h"
 
 VMainWindow::VMainWindow(QWidget *parent)
     : QMainWindow(parent)
 {
+    VConfigInst;
     setupUI();
     initActions();
     initToolBar();

+ 0 - 2
vnote.cpp

@@ -13,13 +13,11 @@ const QString VNote::defaultCssUrl = QString("qrc:/resources/markdown.css");
 
 QString VNote::templateHtml;
 QString VNote::cssUrl = VNote::defaultCssUrl;
-QFont VNote::editorAndBrowserFont;
 
 VNote::VNote()
     : curNotebookIndex(0)
 {
     decorateTemplate();
-    editorAndBrowserFont.setPointSize(11);
 }
 
 void VNote::decorateTemplate()

+ 0 - 1
vnote.h

@@ -26,7 +26,6 @@ public:
     static const QString templatePath;
 
     static QString templateHtml;
-    static QFont editorAndBrowserFont;
 
 private:
     // Write notebooks section of global config

+ 3 - 0
vnote.qrc

@@ -32,5 +32,8 @@
         <file>utils/highlightjs/styles/tomorrow-night-eighties.css</file>
         <file>utils/highlightjs/styles/tomorrow-night.css</file>
         <file>utils/highlightjs/styles/tomorrow.css</file>
+        <file>resources/styles/default.mdhl</file>
+        <file>resources/styles/solarized-light.mdhl</file>
+        <file>resources/styles/solarized-dark.mdhl</file>
     </qresource>
 </RCC>

+ 174 - 0
vstyleparser.cpp

@@ -0,0 +1,174 @@
+#include "vstyleparser.h"
+
+#include <QFont>
+#include <QPalette>
+#include <QTextEdit>
+#include <QColor>
+#include <QBrush>
+#include <QVector>
+#include <QtDebug>
+
+VStyleParser::VStyleParser()
+{
+    markdownStyles = NULL;
+}
+
+VStyleParser::~VStyleParser()
+{
+    if (markdownStyles) {
+        pmh_free_style_collection(markdownStyles);
+    }
+}
+
+QColor VStyleParser::QColorFromPmhAttr(pmh_attr_argb_color *attr) const
+{
+    return QColor(attr->red, attr->green, attr->blue, attr->alpha);
+}
+
+QBrush VStyleParser::QBrushFromPmhAttr(pmh_attr_argb_color *attr) const
+{
+    return QBrush(QColorFromPmhAttr(attr));
+}
+
+void markdownStyleErrorCB(char *errMsg, int lineNr, void *context)
+{
+    (void)context;
+    qDebug() << "parser error:" << errMsg << lineNr;
+}
+
+QTextCharFormat VStyleParser::QTextCharFormatFromAttrs(pmh_style_attribute *attrs,
+                                                       const QFont &baseFont) const
+{
+    QTextCharFormat format;
+    while (attrs) {
+        switch (attrs->type) {
+        case pmh_attr_type_foreground_color:
+            format.setForeground(QBrushFromPmhAttr(attrs->value->argb_color));
+            break;
+
+        case pmh_attr_type_background_color:
+            format.setBackground(QBrushFromPmhAttr(attrs->value->argb_color));
+            break;
+
+        case pmh_attr_type_font_size_pt:
+        {
+            pmh_attr_font_size *fontSize = attrs->value->font_size;
+            int ptSize = fontSize->size_pt;
+            if (fontSize->is_relative) {
+                int basePtSize = baseFont.pointSize();
+                if (basePtSize == -1) {
+                    // In pixel. Use default font configuration.
+                    basePtSize = 11;
+                }
+                ptSize += basePtSize;
+            }
+            if (ptSize > 0) {
+                format.setFontPointSize(ptSize);
+            }
+            break;
+        }
+
+        case pmh_attr_type_font_family:
+            // TODO
+            break;
+
+        case pmh_attr_type_font_style:
+        {
+            pmh_attr_font_styles *fontStyle = attrs->value->font_styles;
+            if (fontStyle->italic) {
+                format.setFontItalic(true);
+            }
+            if (fontStyle->bold) {
+                format.setFontWeight(QFont::Bold);
+            }
+            if (fontStyle->underlined) {
+                format.setFontUnderline(true);
+            }
+            break;
+        }
+
+        default:
+            qWarning() << "warning: unimplemented format attr type:" << attrs->type;
+            break;
+        }
+        attrs = attrs->next;
+    }
+    return format;
+}
+
+void VStyleParser::parseMarkdownStyle(const QString &styleStr)
+{
+    if (markdownStyles) {
+        pmh_free_style_collection(markdownStyles);
+    }
+    markdownStyles = pmh_parse_styles(styleStr.toLocal8Bit().data(),
+                                      &markdownStyleErrorCB, this);
+}
+
+QVector<HighlightingStyle> VStyleParser::fetchMarkdownStyles(const QFont &baseFont) const
+{
+    QVector<HighlightingStyle> styles(pmh_NUM_LANG_TYPES);
+
+    for (int i = 0; i < pmh_NUM_LANG_TYPES; ++i) {
+        pmh_style_attribute *attr = markdownStyles->element_styles[i];
+        if (!attr) {
+            continue;
+        }
+        styles[i].type = attr->lang_element_type;
+        styles[i].format = QTextCharFormatFromAttrs(attr, baseFont);
+    }
+    return styles;
+}
+
+QPalette VStyleParser::fetchMarkdownEditorStyles(const QPalette &basePalette) const
+{
+    QPalette palette(basePalette);
+
+    // editor
+    pmh_style_attribute *editorStyles = markdownStyles->editor_styles;
+    while (editorStyles) {
+        switch (editorStyles->type) {
+        case pmh_attr_type_foreground_color:
+            palette.setColor(QPalette::Text,
+                             QColorFromPmhAttr(editorStyles->value->argb_color));
+            break;
+
+        case pmh_attr_type_background_color:
+            palette.setColor(QPalette::Base,
+                             QColorFromPmhAttr(editorStyles->value->argb_color));
+            break;
+
+        default:
+                qWarning() << "warning: unimplemented editor attr type:" << editorStyles->type;
+        }
+        editorStyles = editorStyles->next;
+    }
+
+    // editor-current-line
+    pmh_style_attribute *curLineStyles = markdownStyles->editor_current_line_styles;
+    if (curLineStyles) {
+        qDebug() << "editor-current-line style is not supported";
+    }
+
+    // editor-selection
+    pmh_style_attribute *selStyles = markdownStyles->editor_selection_styles;
+    while (selStyles) {
+        switch (selStyles->type) {
+        case pmh_attr_type_foreground_color:
+            palette.setColor(QPalette::HighlightedText,
+                             QColorFromPmhAttr(selStyles->value->argb_color));
+            break;
+
+        case pmh_attr_type_background_color:
+            palette.setColor(QPalette::Highlight,
+                             QColorFromPmhAttr(selStyles->value->argb_color));
+            break;
+
+        default:
+            qWarning() << "warning: unimplemented selection attr type:" << selStyles->type;
+        }
+        selStyles = selStyles->next;
+    }
+
+    return palette;
+}

+ 34 - 0
vstyleparser.h

@@ -0,0 +1,34 @@
+#ifndef VSTYLEPARSER_H
+#define VSTYLEPARSER_H
+
+#include <QPalette>
+#include <QVector>
+#include "hgmarkdownhighlighter.h"
+
+extern "C" {
+#include "utils/peg-highlight/pmh_definitions.h"
+#include "utils/peg-highlight/pmh_styleparser.h"
+}
+
+class QColor;
+class QBrush;
+
+class VStyleParser
+{
+public:
+    VStyleParser();
+    ~VStyleParser();
+
+    void parseMarkdownStyle(const QString &styleStr);
+    QVector<HighlightingStyle> fetchMarkdownStyles(const QFont &baseFont) const;
+    QPalette fetchMarkdownEditorStyles(const QPalette &basePalette) const;
+
+private:
+    QColor QColorFromPmhAttr(pmh_attr_argb_color *attr) const;
+    QBrush QBrushFromPmhAttr(pmh_attr_argb_color *attr) const;
+    QTextCharFormat QTextCharFormatFromAttrs(pmh_style_attribute *attrs,
+                                             const QFont &baseFont) const;
+    pmh_style_collection *markdownStyles;
+};
+
+#endif // VSTYLEPARSER_H