| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287 |
- #include "vstyleparser.h"
- #include <QFont>
- #include <QFontDatabase>
- #include <QPalette>
- #include <QTextEdit>
- #include <QColor>
- #include <QBrush>
- #include <QVector>
- #include <QtDebug>
- #include <QStringList>
- 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;
- qWarning() << "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:
- {
- QString familyList(attrs->value->font_family);
- QString finalFamily = filterAvailableFontFamily(familyList);
- if (!finalFamily.isEmpty()) {
- format.setFontFamily(finalFamily);
- }
- 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() << "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;
- for (int i = 0; i < pmh_NUM_LANG_TYPES; ++i) {
- pmh_style_attribute *attr = markdownStyles->element_styles[i];
- if (!attr) {
- continue;
- }
- HighlightingStyle style;
- style.type = attr->lang_element_type;
- style.format = QTextCharFormatFromAttrs(attr, baseFont);
- styles.append(style);
- }
- return styles;
- }
- QMap<QString, QTextCharFormat> VStyleParser::fetchCodeBlockStyles(const QFont & p_baseFont) const
- {
- QMap<QString, QTextCharFormat> styles;
- pmh_style_attribute *attrs = markdownStyles->element_styles[pmh_VERBATIM];
- // First set up the base format.
- QTextCharFormat baseFormat = QTextCharFormatFromAttrs(attrs, p_baseFont);
- while (attrs) {
- switch (attrs->type) {
- case pmh_attr_type_other:
- {
- QString attrName(attrs->name);
- QString attrValue(attrs->value->string);
- QTextCharFormat format;
- format.setFontFamily(baseFormat.fontFamily());
- QStringList items = attrValue.split(',', QString::SkipEmptyParts);
- for (auto const &item : items) {
- QString val = item.trimmed().toLower();
- if (val == "bold") {
- format.setFontWeight(QFont::Bold);
- } else if (val == "italic") {
- format.setFontItalic(true);
- } else if (val == "underlined") {
- format.setFontUnderline(true);
- } else {
- // Treat it as the color RGB value string without '#'.
- QColor color("#" + val);
- if (color.isValid()) {
- format.setForeground(QBrush(color));
- }
- }
- }
- if (format.isValid()) {
- styles[attrName] = format;
- }
- break;
- }
- default:
- // We just only handle custom attribute here.
- break;
- }
- attrs = attrs->next;
- }
- return styles;
- }
- void VStyleParser::fetchMarkdownEditorStyles(QPalette &palette, QFont &font,
- QMap<QString, QMap<QString, QString>> &styles) const
- {
- QString ruleKey;
- // 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;
- case pmh_attr_type_font_family:
- {
- QString familyList(editorStyles->value->font_family);
- QString finalFamily = filterAvailableFontFamily(familyList);
- if (!finalFamily.isEmpty()) {
- font.setFamily(finalFamily);
- }
- break;
- }
- default:
- qWarning() << "unimplemented editor attr type:" << editorStyles->type;
- }
- editorStyles = editorStyles->next;
- }
- // editor-current-line
- pmh_style_attribute *curLineStyles = markdownStyles->editor_current_line_styles;
- ruleKey = "editor-current-line";
- while (curLineStyles) {
- switch (curLineStyles->type) {
- case pmh_attr_type_background_color:
- {
- QString attrName(curLineStyles->name);
- QString value = QColorFromPmhAttr(curLineStyles->value->argb_color).name();
- styles[ruleKey][attrName] = value;
- break;
- }
- case pmh_attr_type_other:
- {
- QString attrName(curLineStyles->name);
- QString value(curLineStyles->value->string);
- styles[ruleKey][attrName] = value;
- break;
- }
- default:
- qWarning() << "unimplemented current line attr type:" << curLineStyles->type;
- }
- curLineStyles = curLineStyles->next;
- }
- // 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() << "unimplemented selection attr type:" << selStyles->type;
- }
- selStyles = selStyles->next;
- }
- }
- // @familyList is a comma separated string
- QString VStyleParser::filterAvailableFontFamily(const QString &familyList) const
- {
- QStringList families = familyList.split(',', QString::SkipEmptyParts);
- QStringList availFamilies = QFontDatabase().families();
- qDebug() << "family:" << familyList;
- for (int i = 0; i < families.size(); ++i) {
- QString family = families[i].trimmed().toLower();
- for (int j = 0; j < availFamilies.size(); ++j) {
- QString availFamily = availFamilies[j];
- availFamily.remove(QRegExp("\\[.*\\]"));
- if (family == availFamily.trimmed().toLower()) {
- qDebug() << "matched family:" << availFamilies[j];
- return availFamilies[j];
- }
- }
- }
- return QString();
- }
|