add VStyleParser as a wrapper of pmh_styleparser

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

Signed-off-by: Le Tan <tamlokveer@gmail.com>
This commit is contained in:
Le Tan 2016-10-12 22:52:58 +08:00
parent 33f62915e1
commit d22f0124d3
16 changed files with 532 additions and 74 deletions

View File

@ -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

View File

@ -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();

View File

@ -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

View File

@ -0,0 +1,79 @@
# This is the default markdown styles used for Peg-Markdown-Highlight
# Created by Le Tan (tamlokveer@gmail.com)
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

View File

@ -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

View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -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()

View File

@ -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:

View File

@ -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();

View File

@ -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()

View File

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

View File

@ -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
vstyleparser.cpp Normal file
View File

@ -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
vstyleparser.h Normal file
View File

@ -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