support custom CSS styles

VNote will find CSS files in the "styles" folder under the config folder.
This commit is contained in:
Le Tan 2017-04-22 15:39:12 +08:00
parent c642d60757
commit d0d4e1443d
8 changed files with 173 additions and 15 deletions

View File

@ -1,6 +1,6 @@
[global]
welcome_page_path=:/resources/welcome.html
template_css_url=qrc:/resources/markdown.css
template_css=default
current_notebook=0
tab_stop_width=4
is_expand_tab=true

View File

@ -10,11 +10,13 @@
#include "utils/vutils.h"
#include "vstyleparser.h"
const QString VConfigManager::orgName = QString("tamlok");
const QString VConfigManager::orgName = QString("vnote");
const QString VConfigManager::appName = QString("vnote");
const QString VConfigManager::c_version = QString("1.2");
const QString VConfigManager::dirConfigFileName = QString(".vnote.json");
const QString VConfigManager::defaultConfigFilePath = QString(":/resources/vnote.ini");
const QString VConfigManager::c_styleConfigFolder = QString("styles");
const QString VConfigManager::c_defaultCssFile = QString(":/resources/styles/default.css");
VConfigManager::VConfigManager()
: userSettings(NULL), defaultSettings(NULL)
@ -31,11 +33,24 @@ VConfigManager::~VConfigManager()
}
}
void VConfigManager::migrateIniFile()
{
const QString originalFolder = "tamlok";
const QString newFolder = orgName;
QString configFolder = getConfigFolder();
QDir dir(configFolder);
dir.cdUp();
dir.rename(originalFolder, newFolder);
}
void VConfigManager::initialize()
{
userSettings = new QSettings(QSettings::IniFormat, QSettings::UserScope, orgName, appName);
userSettings = new QSettings(QSettings::IniFormat, QSettings::UserScope,
orgName, appName);
defaultSettings = new QSettings(defaultConfigFilePath, QSettings::IniFormat);
migrateIniFile();
m_editorFontSize = getConfigFromSettings("global", "editor_font_size").toInt();
if (m_editorFontSize <= 0) {
m_editorFontSize = 12;
@ -44,7 +59,7 @@ void VConfigManager::initialize()
baseEditPalette = QTextEdit().palette();
welcomePagePath = getConfigFromSettings("global", "welcome_page_path").toString();
templateCssUrl = getConfigFromSettings("global", "template_css_url").toString();
m_templateCss = getConfigFromSettings("global", "template_css").toString();
curNotebookIndex = getConfigFromSettings("global", "current_notebook").toInt();
markdownExtensions = hoedown_extensions(HOEDOWN_EXT_TABLES | HOEDOWN_EXT_FENCED_CODE |
@ -311,3 +326,84 @@ void VConfigManager::setWebZoomFactor(qreal p_factor)
setConfigToSettings("global", "web_zoom_factor", m_webZoomFactor);
}
QString VConfigManager::getConfigFolder() const
{
V_ASSERT(userSettings);
QString iniPath = userSettings->fileName();
return VUtils::basePathFromPath(iniPath);
}
QString VConfigManager::getStyleConfigFolder() const
{
return getConfigFolder() + QDir::separator() + c_styleConfigFolder;
}
QVector<QString> VConfigManager::getCssStyles() const
{
QVector<QString> res;
QDir dir(getStyleConfigFolder());
if (!dir.exists()) {
// Output pre-defined css styles to this folder.
outputDefaultCssStyle();
}
// Get all the .css files in the folder.
dir.setFilter(QDir::Files | QDir::NoSymLinks);
dir.setNameFilters(QStringList("*.css"));
QStringList files = dir.entryList();
res.reserve(files.size());
for (auto const &item : files) {
res.push_back(item.left(item.size() - 4));
}
return res;
}
bool VConfigManager::outputDefaultCssStyle() const
{
// Make sure the styles folder exists.
QDir dir(getConfigFolder());
if (!dir.exists(c_styleConfigFolder)) {
if (!dir.mkdir(c_styleConfigFolder)) {
return false;
}
}
return VUtils::copyFile(c_defaultCssFile,
getStyleConfigFolder() + QDir::separator() + "default.css",
false);
}
QString VConfigManager::getTemplateCssUrl()
{
QString cssPath = getStyleConfigFolder() + QDir::separator() + m_templateCss + ".css";
if (!QFile::exists(cssPath)) {
// Specified css not exists.
if (m_templateCss == "default") {
bool ret = outputDefaultCssStyle();
if (!ret) {
// Use embedded file.
cssPath = "qrc" + c_defaultCssFile;
}
} else {
setTemplateCss("default");
return getTemplateCssUrl();
}
}
qDebug() << "use template css:" << cssPath;
return cssPath;
}
const QString &VConfigManager::getTemplateCss() const
{
return m_templateCss;
}
void VConfigManager::setTemplateCss(const QString &p_css)
{
if (m_templateCss == p_css) {
return;
}
m_templateCss = p_css;
setConfigToSettings("global", "template_css", m_templateCss);
}

View File

@ -54,7 +54,10 @@ public:
inline QString getWelcomePagePath() const;
inline QString getTemplateCssUrl() const;
QString getTemplateCssUrl();
const QString &getTemplateCss() const;
void setTemplateCss(const QString &p_css);
inline QFont getBaseEditFont() const;
inline QPalette getBaseEditPalette() const;
@ -140,6 +143,15 @@ public:
inline bool getEnableCodeBlockHighlight() const;
inline void setEnableCodeBlockHighlight(bool p_enabled);
// Get the folder the ini file exists.
QString getConfigFolder() const;
// Get the folder c_styleConfigFolder in the config folder.
QString getStyleConfigFolder() const;
// Read all available css files in c_styleConfigFolder.
QVector<QString> getCssStyles() const;
private:
void updateMarkdownEditStyle();
QVariant getConfigFromSettings(const QString &section, const QString &key);
@ -150,6 +162,12 @@ private:
// Update baseEditPalette according to curBackgroundColor
void updatePaletteColor();
// Migrate ini file from tamlok/vnote.ini to vnote/vnote.ini.
// This is for the change of org name.
void migrateIniFile();
bool outputDefaultCssStyle() const;
int m_editorFontSize;
QFont baseEditFont;
QPalette baseEditPalette;
@ -158,7 +176,7 @@ private:
QVector<HighlightingStyle> mdHighlightingStyles;
QMap<QString, QTextCharFormat> m_codeBlockStyles;
QString welcomePagePath;
QString templateCssUrl;
QString m_templateCss;
int curNotebookIndex;
// Markdown Converter
@ -230,6 +248,9 @@ private:
QSettings *userSettings;
// Qsettings for @defaultConfigFileName
QSettings *defaultSettings;
// The folder name of style files.
static const QString c_styleConfigFolder;
static const QString c_defaultCssFile;
};
@ -258,11 +279,6 @@ inline QString VConfigManager::getWelcomePagePath() const
return welcomePagePath;
}
inline QString VConfigManager::getTemplateCssUrl() const
{
return templateCssUrl;
}
inline QFont VConfigManager::getBaseEditFont() const
{
return baseEditFont;

View File

@ -348,8 +348,12 @@ void VMainWindow::initMarkdownMenu()
Q_ASSERT(false);
}
initRenderStyleMenu(markdownMenu);
initRenderBackgroundMenu(markdownMenu);
markdownMenu->addSeparator();
QAction *mermaidAct = new QAction(tr("&Mermaid Diagram"), this);
mermaidAct->setToolTip(tr("Enable Mermaid for graph and diagram"));
mermaidAct->setCheckable(true);
@ -359,8 +363,8 @@ void VMainWindow::initMarkdownMenu()
mermaidAct->setChecked(vconfig.getEnableMermaid());
QAction *mathjaxAct = new QAction(tr("Math&jax"), this);
mathjaxAct->setToolTip(tr("Enable Mathjax for math support in Markdown"));
QAction *mathjaxAct = new QAction(tr("Math&Jax"), this);
mathjaxAct->setToolTip(tr("Enable MathJax for math support in Markdown"));
mathjaxAct->setCheckable(true);
connect(mathjaxAct, &QAction::triggered,
this, &VMainWindow::enableMathjax);
@ -767,6 +771,37 @@ void VMainWindow::initRenderBackgroundMenu(QMenu *menu)
}
}
void VMainWindow::initRenderStyleMenu(QMenu *p_menu)
{
QMenu *styleMenu = p_menu->addMenu(tr("Rendering &Style"));
styleMenu->setToolTipsVisible(true);
QActionGroup *styleAct = new QActionGroup(this);
connect(styleAct, &QActionGroup::triggered,
this, &VMainWindow::setRenderStyle);
bool foundCurrentCss = false;
QVector<QString> styles = vconfig.getCssStyles();
for (auto const &style : styles) {
QAction *act = new QAction(style, styleAct);
act->setToolTip(tr("Set as the CSS style for Markdown rendering"));
act->setCheckable(true);
act->setData(style);
if (vconfig.getTemplateCss() == style) {
act->setChecked(true);
foundCurrentCss = true;
}
}
if (!foundCurrentCss && styles.isEmpty()) {
delete styleAct;
return;
}
styleMenu->addActions(styleAct->actions());
}
void VMainWindow::initEditorBackgroundMenu(QMenu *menu)
{
QMenu *backgroundColorMenu = menu->addMenu(tr("&Background Color"));
@ -810,6 +845,15 @@ void VMainWindow::setRenderBackgroundColor(QAction *action)
vnote->updateTemplate();
}
void VMainWindow::setRenderStyle(QAction *p_action)
{
if (!p_action) {
return;
}
vconfig.setTemplateCss(p_action->data().toString());
vnote->updateTemplate();
}
void VMainWindow::updateActionStateFromTabStatusChange(const VFile *p_file,
bool p_editMode)
{

View File

@ -52,6 +52,7 @@ private slots:
void setTabStopWidth(QAction *action);
void setEditorBackgroundColor(QAction *action);
void setRenderBackgroundColor(QAction *action);
void setRenderStyle(QAction *p_action);
void changeHighlightCursorLine(bool p_checked);
void changeHighlightSelectedWord(bool p_checked);
void changeHighlightSearchedWord(bool p_checked);
@ -97,6 +98,7 @@ private:
void initAvatar();
void initPredefinedColorPixmaps();
void initRenderBackgroundMenu(QMenu *menu);
void initRenderStyleMenu(QMenu *p_menu);
void initEditorBackgroundMenu(QMenu *menu);
void changeSplitterView(int nrPanel);
void updateWindowTitle(const QString &str);

View File

@ -157,7 +157,7 @@ void VNote::updateTemplate()
}
QString cssStyle;
if (!rgb.isEmpty()) {
cssStyle = "body { background-color: #" + rgb + "; }";
cssStyle = "body { background-color: #" + rgb + " !important; }";
}
QString styleHolder("<!-- BACKGROUND_PLACE_HOLDER -->");
QString cssHolder("CSS_PLACE_HOLDER");

View File

@ -2,7 +2,6 @@
<qresource prefix="/">
<file>resources/welcome.html</file>
<file>resources/qwebchannel.js</file>
<file>resources/markdown.css</file>
<file>utils/marked/marked.min.js</file>
<file>utils/highlightjs/highlight.pack.js</file>
<file>utils/highlightjs/styles/androidstudio.css</file>
@ -99,5 +98,6 @@
<file>resources/icons/float.svg</file>
<file>resources/docs/shortcuts_en.md</file>
<file>resources/docs/shortcuts_zh.md</file>
<file>resources/styles/default.css</file>
</qresource>
</RCC>