support themes

This commit is contained in:
Le Tan 2017-11-30 21:26:37 +08:00
parent 6fea8bf7dc
commit 262c6acfd9
25 changed files with 1145 additions and 66 deletions

View File

@ -39,7 +39,7 @@ void VEditSnippetDialog::setupUI(const QString &p_title, const QString &p_info)
m_nameEdit->setValidator(validator); m_nameEdit->setValidator(validator);
// Type. // Type.
m_typeCB = new QComboBox(); m_typeCB = VUtils::getComboBox();
for (int i = 0; i < VSnippet::Type::Invalid; ++i) { for (int i = 0; i < VSnippet::Type::Invalid; ++i) {
m_typeCB->addItem(VSnippet::typeStr(static_cast<VSnippet::Type>(i)), i); m_typeCB->addItem(VSnippet::typeStr(static_cast<VSnippet::Type>(i)), i);
} }
@ -49,7 +49,7 @@ void VEditSnippetDialog::setupUI(const QString &p_title, const QString &p_info)
m_typeCB->setCurrentIndex(typeIdx); m_typeCB->setCurrentIndex(typeIdx);
// Shortcut. // Shortcut.
m_shortcutCB = new QComboBox(); m_shortcutCB = VUtils::getComboBox();
m_shortcutCB->addItem(tr("None"), QChar()); m_shortcutCB->addItem(tr("None"), QChar());
auto shortcuts = getAvailableShortcuts(); auto shortcuts = getAvailableShortcuts();
for (auto it : shortcuts) { for (auto it : shortcuts) {

View File

@ -52,7 +52,7 @@ void VNewFileDialog::setupUI(const QString &p_title,
m_nameEdit->setSelection(0, (dotIndex == -1) ? p_defaultName.size() : dotIndex); m_nameEdit->setSelection(0, (dotIndex == -1) ? p_defaultName.size() : dotIndex);
// Template. // Template.
m_templateCB = new QComboBox(); m_templateCB = VUtils::getComboBox();
m_templateCB->setToolTip(tr("Choose a template (magic word supported)")); m_templateCB->setToolTip(tr("Choose a template (magic word supported)"));
m_templateCB->setSizeAdjustPolicy(QComboBox::AdjustToContents); m_templateCB->setSizeAdjustPolicy(QComboBox::AdjustToContents);

View File

@ -161,7 +161,7 @@ VGeneralTab::VGeneralTab(QWidget *p_parent)
: QWidget(p_parent) : QWidget(p_parent)
{ {
// Language combo. // Language combo.
m_langCombo = new QComboBox(this); m_langCombo = VUtils::getComboBox(this);
m_langCombo->setToolTip(tr("Choose the language of VNote interface")); m_langCombo->setToolTip(tr("Choose the language of VNote interface"));
m_langCombo->addItem(tr("System"), "System"); m_langCombo->addItem(tr("System"), "System");
auto langs = VUtils::getAvailableLanguages(); auto langs = VUtils::getAvailableLanguages();
@ -194,7 +194,7 @@ VGeneralTab::VGeneralTab(QWidget *p_parent)
QLayout *VGeneralTab::setupStartupPagesLayout() QLayout *VGeneralTab::setupStartupPagesLayout()
{ {
m_startupPageTypeCombo = new QComboBox(this); m_startupPageTypeCombo = VUtils::getComboBox(this);
m_startupPageTypeCombo->setToolTip(tr("Restore tabs or open specific notes on startup")); m_startupPageTypeCombo->setToolTip(tr("Restore tabs or open specific notes on startup"));
m_startupPageTypeCombo->addItem(tr("None"), (int)StartupPageType::None); m_startupPageTypeCombo->addItem(tr("None"), (int)StartupPageType::None);
m_startupPageTypeCombo->addItem(tr("Continue where you left off"), (int)StartupPageType::ContinueLeftOff); m_startupPageTypeCombo->addItem(tr("Continue where you left off"), (int)StartupPageType::ContinueLeftOff);
@ -598,19 +598,19 @@ VMarkdownTab::VMarkdownTab(QWidget *p_parent)
: QWidget(p_parent) : QWidget(p_parent)
{ {
// Default note open mode. // Default note open mode.
m_openModeCombo = new QComboBox(); m_openModeCombo = VUtils::getComboBox();
m_openModeCombo->setToolTip(tr("Default mode to open a note")); m_openModeCombo->setToolTip(tr("Default mode to open a note"));
m_openModeCombo->addItem(tr("Read Mode"), (int)OpenFileMode::Read); m_openModeCombo->addItem(tr("Read Mode"), (int)OpenFileMode::Read);
m_openModeCombo->addItem(tr("Edit Mode"), (int)OpenFileMode::Edit); m_openModeCombo->addItem(tr("Edit Mode"), (int)OpenFileMode::Edit);
// Heading sequence. // Heading sequence.
m_headingSequenceTypeCombo = new QComboBox(); m_headingSequenceTypeCombo = VUtils::getComboBox();
m_headingSequenceTypeCombo->setToolTip(tr("Enable auto sequence for all headings (in the form like 1.2.3.4.)")); m_headingSequenceTypeCombo->setToolTip(tr("Enable auto sequence for all headings (in the form like 1.2.3.4.)"));
m_headingSequenceTypeCombo->addItem(tr("Disabled"), (int)HeadingSequenceType::Disabled); m_headingSequenceTypeCombo->addItem(tr("Disabled"), (int)HeadingSequenceType::Disabled);
m_headingSequenceTypeCombo->addItem(tr("Enabled"), (int)HeadingSequenceType::Enabled); m_headingSequenceTypeCombo->addItem(tr("Enabled"), (int)HeadingSequenceType::Enabled);
m_headingSequenceTypeCombo->addItem(tr("Enabled for notes only"), (int)HeadingSequenceType::EnabledNoteOnly); m_headingSequenceTypeCombo->addItem(tr("Enabled for notes only"), (int)HeadingSequenceType::EnabledNoteOnly);
m_headingSequenceLevelCombo = new QComboBox(); m_headingSequenceLevelCombo = VUtils::getComboBox();
m_headingSequenceLevelCombo->setToolTip(tr("Base level to start heading sequence")); m_headingSequenceLevelCombo->setToolTip(tr("Base level to start heading sequence"));
m_headingSequenceLevelCombo->addItem(tr("1"), 1); m_headingSequenceLevelCombo->addItem(tr("1"), 1);
m_headingSequenceLevelCombo->addItem(tr("2"), 2); m_headingSequenceLevelCombo->addItem(tr("2"), 2);

View File

@ -12,9 +12,12 @@
#include "utils/vutils.h" #include "utils/vutils.h"
#include "vsingleinstanceguard.h" #include "vsingleinstanceguard.h"
#include "vconfigmanager.h" #include "vconfigmanager.h"
#include "vpalette.h"
VConfigManager *g_config; VConfigManager *g_config;
VPalette *g_palette;
#if defined(QT_NO_DEBUG) #if defined(QT_NO_DEBUG)
// 5MB log size. // 5MB log size.
#define MAX_LOG_SIZE 5 * 1024 * 1024 #define MAX_LOG_SIZE 5 * 1024 * 1024
@ -164,10 +167,12 @@ int main(int argc, char *argv[])
app.installTranslator(&translator); app.installTranslator(&translator);
} }
VPalette palette(g_config->getThemeFile());
g_palette = &palette;
VMainWindow w(&guard); VMainWindow w(&guard);
QString style = VUtils::readFileFromDisk(":/resources/vnote.qss"); QString style = palette.fetchQtStyleSheet();
if (!style.isEmpty()) { if (!style.isEmpty()) {
VUtils::processStyle(style, w.getPalette());
app.setStyleSheet(style); app.setStyleSheet(style);
} }

View File

@ -1,9 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
<g>
<polygon points="128,320 256,192 384,320 "/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 542 B

View File

@ -1,9 +1,9 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> <!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve"> width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
<g> <g>
<polygon points="128,192 256,320 384,192 "/> <polygon points="128,192 256,320 384,192 "/>
</g> </g>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 542 B

After

Width:  |  Height:  |  Size: 533 B

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
<path d="M443.6,387.1L312.4,255.4l131.5-130c5.4-5.4,5.4-14.2,0-19.6l-37.4-37.6c-2.6-2.6-6.1-4-9.8-4c-3.7,0-7.2,1.5-9.8,4
L256,197.8L124.9,68.3c-2.6-2.6-6.1-4-9.8-4c-3.7,0-7.2,1.5-9.8,4L68,105.9c-5.4,5.4-5.4,14.2,0,19.6l131.5,130L68.4,387.1
c-2.6,2.6-4.1,6.1-4.1,9.8c0,3.7,1.4,7.2,4.1,9.8l37.4,37.6c2.7,2.7,6.2,4.1,9.8,4.1c3.5,0,7.1-1.3,9.8-4.1L256,313.1l130.7,131.1
c2.7,2.7,6.2,4.1,9.8,4.1c3.5,0,7.1-1.3,9.8-4.1l37.4-37.6c2.6-2.6,4.1-6.1,4.1-9.8C447.7,393.2,446.2,389.7,443.6,387.1z"/>
</svg>

After

Width:  |  Height:  |  Size: 974 B

View File

@ -1,10 +1,10 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> <!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve"> width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
<path style="fill:#BDBDBD" d="M443.6,387.1L312.4,255.4l131.5-130c5.4-5.4,5.4-14.2,0-19.6l-37.4-37.6c-2.6-2.6-6.1-4-9.8-4c-3.7,0-7.2,1.5-9.8,4 <path style="fill:#9E9E9E" d="M443.6,387.1L312.4,255.4l131.5-130c5.4-5.4,5.4-14.2,0-19.6l-37.4-37.6c-2.6-2.6-6.1-4-9.8-4c-3.7,0-7.2,1.5-9.8,4
L256,197.8L124.9,68.3c-2.6-2.6-6.1-4-9.8-4c-3.7,0-7.2,1.5-9.8,4L68,105.9c-5.4,5.4-5.4,14.2,0,19.6l131.5,130L68.4,387.1 L256,197.8L124.9,68.3c-2.6-2.6-6.1-4-9.8-4c-3.7,0-7.2,1.5-9.8,4L68,105.9c-5.4,5.4-5.4,14.2,0,19.6l131.5,130L68.4,387.1
c-2.6,2.6-4.1,6.1-4.1,9.8c0,3.7,1.4,7.2,4.1,9.8l37.4,37.6c2.7,2.7,6.2,4.1,9.8,4.1c3.5,0,7.1-1.3,9.8-4.1L256,313.1l130.7,131.1 c-2.6,2.6-4.1,6.1-4.1,9.8c0,3.7,1.4,7.2,4.1,9.8l37.4,37.6c2.7,2.7,6.2,4.1,9.8,4.1c3.5,0,7.1-1.3,9.8-4.1L256,313.1l130.7,131.1
c2.7,2.7,6.2,4.1,9.8,4.1c3.5,0,7.1-1.3,9.8-4.1l37.4-37.6c2.6-2.6,4.1-6.1,4.1-9.8C447.7,393.2,446.2,389.7,443.6,387.1z"/> c2.7,2.7,6.2,4.1,9.8,4.1c3.5,0,7.1-1.3,9.8-4.1l37.4-37.6c2.6-2.6,4.1-6.1,4.1-9.8C447.7,393.2,446.2,389.7,443.6,387.1z"/>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 1005 B

After

Width:  |  Height:  |  Size: 995 B

View File

@ -1,12 +1,12 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> <!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve"> width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
<g> <g>
<path d="M64,144v304h303.9V144H64z M351.9,432H80V160h271.9V432z"/> <path d="M64,144v304h303.9V144H64z M351.9,432H80V160h271.9V432z"/>
<g> <g>
<polygon points="448,64 144,64 144,128 160,128 160,80 432,80 432,352 384,352 384,368 448,368 "/> <polygon points="448,64 144,64 144,128 160,128 160,80 432,80 432,352 384,352 384,368 448,368 "/>
</g> </g>
</g> </g>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 685 B

After

Width:  |  Height:  |  Size: 673 B

View File

@ -0,0 +1,171 @@
; File path could be absolute path or relative path (related to this file).
; Use @color_tag to reference a style.
[metadata]
qss_file=v_white.qss
[phony]
; Abstract color attributes.
base_fg=#000000
base_color_1=#EEEEEE
hover_color_1=#C4C4C4
selected_color_1=#BEBEBE
base_color_2=#E0E0E0
separator_color=#E0E0E0
border_color=#9E9E9E
focus_color=#BDBDBD
content_color=#FAFAFA
selection_color=#64B5F6
[widgets]
; Widget color attributes.
; QWidget.
widget_fg=@base_fg
; Separator of dock widgets.
dock_separator_bg=@base_color_2
dock_separator_hover_bg=@base_color_2
; Menubar.
menubar_bg=@base_color_1
menubar_fg=@base_fg
menubar_item_selected_bg=@selected_color_1
; Menu.
menu_bg=@base_color_1
menu_fg=@base_fg
menu_item_selected_bg=@selected_color_1
menu_separator_bg=@separator_color
; Tooltip.
tooltip_border=@base_color_2
tooltip_bg=@base_color_1
tooltip_fg=@base_fg
; Toolbar.
toolbar_bg=@base_color_1
toolbutton_hover_bg=@hover_color_1
toolbutton_pressed_bg=@selected_color_1
; Dockwidget.
dockwidget_title_bg=@base_color_2
dockwidget_button_hover_bg=@hover_color_1
; PushButton.
pushbutton_fg=@base_fg
pushbutton_bg=transparent
pushbutton_border=@border_color
pushbutton_pressed_bg=@selected_color_1
pushbutton_hover_bg=@hover_color_1
pushbutton_default_border=#424242
pushbutton_cornerbtn_hover_bg=@hover_color_1
pushbutton_cornerbtn_focus_bg=@focus_color
pushbutton_statusbtn_hover_bg=@hover_color_1
pushbutton_statusbtn_focus_bg=@focus_color
pushbutton_flatbtn_hover_bg=@hover_color_1
pushbutton_flatbtn_focus_bg=@focus_color
pushbutton_selectionbtn_hover_bg=@hover_color_1
pushbutton_selectionbtn_focus_bg=@focus_color
pushbutton_titlebtn_bg=@base_color_2
pushbutton_titlebtn_hover_bg=@hover_color_1
pushbutton_titlebtn_focus_bg=@focus_color
pushbutton_dangerbtn_fg=#FFF
pushbutton_dangerbtn_border=#D43F3A
pushbutton_dangerbtn_bg=#D9534F
pushbutton_dangerbtn_hover_fg=#FFF
pushbutton_dangerbtn_hover_bg=#C9302C
pushbutton_dangerbtn_hover_border=#AC2925
; ComboBox.
combobox_border=@border_color
combobox_fg=@base_fg
combobox_bg=@content_color
combobox_view_border=@border_color
combobox_view_selected_bg=@selected_color_1
combobox_view_selected_fg=@base_fg
combobox_view_item_hover_fg=@base_fg
combobox_view_item_hover_bg=@hover_color_1
combobox_focus_bg=@focus_color
; Label.
label_fg=@base_fg
label_titlelabel_fg=@base_fg
label_titlelabel_bg=@base_color_2
; LineEdit.
lineedit_border=@border_color
lineedit_fg=@base_fg
lineedit_bg=@content_color
lineedit_selection_fg=@base_fg
lineedit_selection_bg=@selection_color
; TabWidget.
tabwidget_pane_border=@selected_color_1
; TabBar.
tabbar_fg=@base_fg
tabbar_bg=@base_color_1
tabbar_border=@border_color
tabbar_selected_fg=@base_fg
tabbar_selected_bg=@selected_color_1
tabbar_selected_border=@border_color
tabbar_hover_fg=@base_fg
tabbar_hover_bg=@hover_color_1
tabbar_hover_border=@border_color
tabbar_closebutton_hover_bg=@hover_color_1
tabbar_clostbutton_focus_bg=@focus_color
; SelectorItem.
selectoritem_border=@base_fg
selectoritem_fg=@base_fg
selectoritem_bg=@base_color_1
; InsertSelector.
insertselector_bg=@base_color_1
; TreeView.
treeview_fg=@base_fg
treeview_bg=@content_color
treeview_item_hover_fg=@base_fg
treeview_item_hover_bg=@hover_color_1
treeview_item_selected_fg=@base_fg
treeview_item_selected_bg=@selected_color_1
treeview_item_selected_avtive_fg=@base_fg
treeview_item_selected_avtive_bg=@selected_color_1
treeview_item_selected_inactive_fg=@base_fg
treeview_item_selected_inactive_bg=#D0D0D0
; ListView.
listview_fg=@base_fg
listview_bg=@content_color
listview_item_hover_fg=@base_fg
listview_item_hover_bg=@hover_color_1
listview_item_selected_fg=@base_fg
listview_item_selected_bg=@selected_color_1
listview_item_selected_avtive_fg=@base_fg
listview_item_selected_avtive_bg=@selected_color_1
listview_item_selected_inactive_fg=@base_fg
listview_item_selected_inactive_bg=#D0D0D0
; Splitter.
splitter_handle_bg=@base_color_2
splitter_mainsplitter_border=@base_color_2
; StatusBar.
statusbar_fg=@base_fg
statusbar_bg=@base_color_1
; ScrollBar.
scrollbar_bg=#EEEEEE
scrollbar_handle_bg=#D0D0D0
scrollbar_addline_bg=#E0E0E0

View File

@ -0,0 +1,561 @@
QToolTip
{
border: 1px solid @tooltip_border;
background: @tooltip_bg;
color: @tooltip_fg;
padding: 5px;
}
/* QWidget */
QWidget
{
color: @widget_fg;
}
QWidget[NotebookPanel="true"] {
padding-left: 3px;
}
/* End QWidget */
QMainWindow::separator {
background: @dock_separator_bg;
width: 2px;
height: 2px;
}
QMainWindow::separator:hover {
background: @dock_separator_hover_bg;
}
QMenuBar {
border: none;
background: @menubar_bg;
color: @menubar_fg;
}
QMenuBar::item:selected {
background: @menubar_item_selected_bg;
}
QMenu {
background: @menu_bg;
color: @menu_fg;
margin: 2px;
}
QMenu::icon {
margin: 5px;
}
QMenu::item {
padding: 5px 30px 5px 30px;
background: 1px solid transparent;
}
QMenu::item:selected {
background: @menu_item_selected_bg;
}
QMenu::icon:checked { /* appearance of a 'checked' icon */
border: 2px solid @menu_item_selected_bg;
}
QMenu::separator {
height: 2px;
background: @menu_separator_bg;
margin-left: 10px;
margin-right: 5px;
}
QMenu::indicator {
width: 20px;
height: 20px;
}
QToolBar {
border: none;
background: @toolbar_bg;
}
QToolButton {
border: none;
background: transparent;
margin: 1px 3px 1px 3px;
padding: 0px;
}
QToolButton[popupMode="1"] { /* only for MenuButtonPopup */
padding-right: 16px; /* make way for the popup button */
}
QToolButton[popupMode="2"] { /* only for InstantPopup */
padding-right: 10px; /* make way for the popup button */
}
QToolButton:hover {
border:none;
background: @toolbutton_hover_bg;
}
QToolButton::pressed {
background: @toolbutton_pressed_bg;
}
/* the subcontrols below are used only in the MenuButtonPopup mode */
QToolButton::menu-button {
border: none;
width: 16px;
}
/* DockWidget */
QDockWidget {
titlebar-close-icon: url(close.svg);
titlebar-normal-icon: url(float.svg);
}
QDockWidget::Title {
background: @dockwidget_title_bg;
text-align: center left;
}
QDockWidget::close-button, QDockWidget::float-button {
border: none;
}
QDockWidget::close-button:hover, QDockWidget::float-button:hover {
background: @dockwidget_button_hover_bg;
}
/* End DockWidget */
/* QPushButton */
QPushButton {
color: @pushbutton_fg;
background: @pushbutton_bg;
border: 1px solid @pushbutton_border;
padding: 3px;
min-width: 80px;
}
QPushButton:pressed {
background-color: @pushbutton_pressed_bg;
}
QPushButton:hover {
background-color: @pushbutton_hover_bg;
}
QPushButton:flat {
border: none;
}
QPushButton::default {
border-color: @pushbutton_default_border;
}
QPushButton[CornerBtn="true"] {
padding: 4px -2px 4px -2px;
margin: 0px;
border: none;
background-color: transparent;
min-width: -1;
}
QPushButton[CornerBtn="true"]::menu-indicator {
image: none;
}
QPushButton[CornerBtn="true"]:hover {
background-color: @pushbutton_cornerbtn_hover_bg;
}
QPushButton[CornerBtn="true"]:focus {
background-color: @pushbutton_cornerbtn_focus_bg;
}
QPushButton[StatusBtn="true"] {
font: bold;
padding: 0px 2px 0px 2px;
margin: 0px;
border: none;
background-color: transparent;
min-width: -1;
}
QPushButton[StatusBtn="true"]:hover {
background-color: @pushbutton_statusbtn_hover_bg;
}
QPushButton[StatusBtn="true"]:focus {
background-color: @pushbutton_statusbtn_focus_bg;;
}
QPushButton[FlatBtn="true"] {
padding: 4px;
margin: 0px;
border: none;
background-color: transparent;
min-width: -1;
}
QPushButton[FlatBtn="true"]:hover {
background-color: @pushbutton_flatbtn_hover_bg;
}
QPushButton[FlatBtn="true"]:focus {
background-color: @pushbutton_flatbtn_focus_bg;
}
QPushButton[SelectionBtn="true"] {
padding: 4px 10px 4px 10px;
border: none;
background-color: transparent;
font-size: 15pt;
text-align: left;
min-width: -1;
}
QPushButton[SelectionBtn="true"]:hover {
background-color: @pushbutton_selectionbtn_hover_bg;
}
QPushButton[SelectionBtn="true"]:focus {
background-color: @pushbutton_selectionbtn_focus_bg;
}
QPushButton[TitleBtn="true"] {
padding: 4px;
margin: 0px;
border: none;
background-color: @pushbutton_titlebtn_bg;
min-width: -1;
}
QPushButton[TitleBtn="true"]:hover {
background-color: @pushbutton_titlebtn_hover_bg;
}
QPushButton[TitleBtn="true"]:focus {
background-color: @pushbutton_titlebtn_focus_bg;
}
QPushButton[DangerBtn="true"] {
color: @pushbutton_dangerbtn_fg;
border-color: @pushbutton_dangerbtn_border;
background-color: @pushbutton_dangerbtn_bg;
min-width: -1;
}
QPushButton[DangerBtn="true"]:hover {
color: @pushbutton_dangerbtn_hover_fg;
border-color: @pushbutton_dangerbtn_hover_border;
background-color: @pushbutton_dangerbtn_hover_bg;
}
/* End QPushButton*/
/* QComboBox */
QComboBox {
padding: 3px;
color: @combobox_fg;
background: @combobox_bg;
border: 1px solid @combobox_border;
}
QComboBox:focus {
background-color: @combobox_focus_bg;
}
QComboBox::drop-down {
subcontrol-origin: padding;
subcontrol-position: top right;
width: 20px;
border: none;
background: transparent;
}
QComboBox::down-arrow {
image: url(arrow_dropdown.svg);
width: 20px;
height: 20px;
}
QComboBox QAbstractItemView {
padding: 2px;
border: 1px solid @combobox_view_border;
background: @combobox_bg;
selection-color: @combobox_view_selected_fg;
selection-background-color: @combobox_view_selected_bg;
}
QComboBox QAbstractItemView::item {
background: transparent;
padding: 3px;
}
QComboBox QAbstractItemView::item:hover {
color: @combobox_view_item_hover_fg;
background: @combobox_view_item_hover_bg;
}
QComboBox#NotebookSelector {
border: none;
font-size: 13pt;
padding-top: 3px;
padding-bottom: 3px;
icon-size: 30px;
}
QComboBox#NotebookSelector QListWidget {
border: 1px solid @combobox_view_border;
background-color: @combobox_bg;
font-size: 13pt;
icon-size: 30px;
}
QComboBox#NotebookSelector QListWidget::item {
padding-top: 10px;
padding-bottom: 10px;
}
QComboBox#NotebookSelector QListWidget::item:hover {
color: @combobox_view_item_hover_fg;
background-color: @combobox_view_item_hover_bg;
}
/* End QComboBox */
/* QLabel */
QLabel {
border: none;
color: @label_fg;
background: transparent;
}
QLabel[TitleLabel="true"] {
padding-top: 5px;
padding-bottom: 5px;
color: @label_titlelabel_fg;
background-color: @label_titlelabel_bg;
}
QLabel[ColorRedLabel="true"] {
padding-left: 5px;
padding-right: 5px;
font: bold;
color: white;
border-radius: 2px;
background-color: #D32F2F;
}
QLabel[ColorGreenLabel="true"] {
padding-left: 5px;
padding-right: 5px;
font: bold;
color: white;
border-radius: 2px;
background-color: #388E3C;
}
QLabel[ColorGreyLabel="true"] {
padding-left: 5px;
padding-right: 5px;
font: bold;
color: white;
border-radius: 2px;
background-color: #616161;
}
QLabel[ColorTealLabel="true"] {
padding-left: 5px;
padding-right: 5px;
font: bold;
color: white;
border-radius: 2px;
background-color: #00796B;
}
/* End QLabel */
/* QLineEdit */
QLineEdit {
border: 1px solid @lineedit_border;
padding: 3px;
color: @lineedit_fg;
background: @lineedit_bg;
selection-color: @lineedit_selection_fg;
selection-background-color: @lineedit_selection_bg;
}
QLineEdit[VimCommandLine="true"] {
padding: 0px;
margin: 0px;
border: none;
}
/* End QLineEdit */
/* QTabWidget */
QTabWidget {
border: none;
}
QTabWidget::pane {
border: none;
border-top: 3px solid @tabwidget_pane_border;
}
/* End QTabWidget */
/* QTabBar */
QTabBar::tab {
color: @tabbar_fg;
background: @tabbar_bg;
border: 1px solid @tabbar_border;
border-bottom: none;
padding: 2px;
}
QTabBar::tab:selected {
color: @tabbar_selected_fg;
background: @tabbar_selected_bg;
border: 1px solid @tabbar_selected_border;
border-bottom: none;
}
QTabBar::tab:hover {
color: @tabbar_hover_fg;
background: @tabbar_hover_bg;
border: 1px solid @tabbar_hover_border;
border-bottom: none;
}
QTabBar::tab:!selected {
margin-top: 2px; /* make non-selected tabs look smaller */
}
QTabBar::close-button {
image: url(close_grey.svg);
}
QTabBar::close-button:hover {
image: url(close.svg);
background-color: @tabbar_closebutton_hover_bg;
}
QTabBar::close-button:focus {
image: url(close.svg);
background-color: @tabbar_clostbutton_focus_bg;
}
/* End QTabBar */
VSelectorItemWidget QLabel[SelectorItemShortcutLabel="true"] {
font: bold;
border: 2px solid @selectoritem_border;
padding: 3px;
border-radius: 5px;
background-color: @selectoritem_bg;
color: @selectoritem_fg;
}
VInsertSelector {
border: none;
background: @insertselector_bg;
}
/* QTreeView */
QTreeView {
color: @treeview_fg;
background: @treeview_bg;
show-decoration-selected: 1;
padding-top: 3px;
border: none;
}
QTreeView::item {
padding-top: 5px;
padding-bottom: 5px;
}
QTreeView::item:hover {
color: @treeview_item_hover_fg;
background: @treeview_item_hover_bg;
}
QTreeView::item:selected {
color: @treeview_item_selected_fg;
background: @treeview_item_selected_bg;
}
QTreeView::item:selected:active {
color: @treeview_item_selected_active_fg;
background: @treeview_item_selected_active_bg;
}
QTreeView::item:selected:!active {
color: @treeview_item_selected_inactive_fg;
background: @treeview_item_selected_inactive_bg;
}
/* End QTreeView */
/* QListView */
QListView {
color: @listview_fg;
background: @listview_bg;
show-decoration-selected: 1;
padding-top: 3px;
border: none;
}
QListView::item {
padding-top: 5px;
padding-bottom: 5px;
}
QListView::item:hover {
color: @listview_item_hover_fg;
background: @listview_item_hover_bg;
}
QListView::item:selected {
color: @listview_item_selected_fg;
background: @listview_item_selected_bg;
}
QListView::item:selected:active {
color: @listview_item_selected_active_fg;
background: @listview_item_selected_active_bg;
}
QListView::item:selected:!active {
color: @listview_item_selected_inactive_fg;
background: @listview_item_selected_inactive_bg;
}
/* End QListView */
/* QSplitter */
QSplitter {
border: none;
}
QSplitter::handle {
background-color: @splitter_handle_bg;
}
QSplitter::handle:vertical {
height: 2px;
}
QSplitter::handle:horizontal {
width: 2px;
}
QSplitter#MainSplitter {
border-top: 2px solid @splitter_mainsplitter_border;
}
/* End QSplitter */
/* QStatusBar */
QStatusBar {
color: @statusbar_fg;
background: @statusbar_bg;
}
/* End QStatusBar */
QWidget[MainEditor="true"] {
border: none;
}

View File

@ -1,4 +1,7 @@
[global] [global]
; Theme name
theme=v_white
welcome_page_path=:/resources/welcome.html welcome_page_path=:/resources/welcome.html
; CSS style for Markdown template ; CSS style for Markdown template

View File

@ -98,7 +98,8 @@ SOURCES += main.cpp\
utils/vimnavigationforwidget.cpp \ utils/vimnavigationforwidget.cpp \
vtoolbox.cpp \ vtoolbox.cpp \
vinsertselector.cpp \ vinsertselector.cpp \
utils/vclipboardutils.cpp utils/vclipboardutils.cpp \
vpalette.cpp
HEADERS += vmainwindow.h \ HEADERS += vmainwindow.h \
vdirectorytree.h \ vdirectorytree.h \
@ -183,7 +184,8 @@ HEADERS += vmainwindow.h \
utils/vimnavigationforwidget.h \ utils/vimnavigationforwidget.h \
vtoolbox.h \ vtoolbox.h \
vinsertselector.h \ vinsertselector.h \
utils/vclipboardutils.h utils/vclipboardutils.h \
vpalette.h
RESOURCES += \ RESOURCES += \
vnote.qrc \ vnote.qrc \

View File

@ -21,6 +21,8 @@
#include <QRegExpValidator> #include <QRegExpValidator>
#include <QRegExp> #include <QRegExp>
#include <QKeySequence> #include <QKeySequence>
#include <QComboBox>
#include <QStyledItemDelegate>
#include "vorphanfile.h" #include "vorphanfile.h"
#include "vnote.h" #include "vnote.h"
@ -1074,3 +1076,12 @@ bool VUtils::isMetaKey(int p_key)
|| p_key == Qt::Key_Meta || p_key == Qt::Key_Meta
|| p_key == Qt::Key_Alt; || p_key == Qt::Key_Alt;
} }
QComboBox *VUtils::getComboBox(QWidget *p_parent)
{
QComboBox *box = new QComboBox(p_parent);
QStyledItemDelegate *itemDelegate = new QStyledItemDelegate(box);
box->setItemDelegate(itemDelegate);
return box;
}

View File

@ -15,6 +15,8 @@ class QKeyEvent;
class VFile; class VFile;
class VOrphanFile; class VOrphanFile;
class VNotebook; class VNotebook;
class QWidget;
class QComboBox;
#if !defined(V_ASSERT) #if !defined(V_ASSERT)
#define V_ASSERT(cond) ((!(cond)) ? qt_assert(#cond, __FILE__, __LINE__) : qt_noop()) #define V_ASSERT(cond) ((!(cond)) ? qt_assert(#cond, __FILE__, __LINE__) : qt_noop())
@ -261,6 +263,9 @@ public:
// Ctrl, Meta, Shift, Alt. // Ctrl, Meta, Shift, Alt.
static bool isMetaKey(int p_key); static bool isMetaKey(int p_key);
// Create and return a QComboBox.
static QComboBox *getComboBox(QWidget *p_parent = nullptr);
// Regular expression for image link. // Regular expression for image link.
// ![image title]( http://github.com/tamlok/vnote.jpg "alt \" text" ) // ![image title]( http://github.com/tamlok/vnote.jpg "alt \" text" )
// Captured texts (need to be trimmed): // Captured texts (need to be trimmed):

View File

@ -32,6 +32,8 @@ const QString VConfigManager::c_snippetConfigFile = QString("snippet.json");
const QString VConfigManager::c_styleConfigFolder = QString("styles"); const QString VConfigManager::c_styleConfigFolder = QString("styles");
const QString VConfigManager::c_themeConfigFolder = QString("themes");
const QString VConfigManager::c_codeBlockStyleConfigFolder = QString("codeblock_styles"); const QString VConfigManager::c_codeBlockStyleConfigFolder = QString("codeblock_styles");
const QString VConfigManager::c_templateConfigFolder = QString("templates"); const QString VConfigManager::c_templateConfigFolder = QString("templates");
@ -74,6 +76,8 @@ void VConfigManager::initialize()
outputDefaultCodeBlockCssStyle(); outputDefaultCodeBlockCssStyle();
outputDefaultEditorStyle(); outputDefaultEditorStyle();
initThemes();
m_defaultEditPalette = QTextEdit().palette(); m_defaultEditPalette = QTextEdit().palette();
m_editorStyle = getConfigFromSettings("global", "editor_style").toString(); m_editorStyle = getConfigFromSettings("global", "editor_style").toString();
@ -283,6 +287,9 @@ void VConfigManager::initialize()
m_vimExemptionKeys = getConfigFromSettings("global", m_vimExemptionKeys = getConfigFromSettings("global",
"vim_exemption_keys").toString(); "vim_exemption_keys").toString();
m_theme = getConfigFromSettings("global",
"theme").toString();
} }
void VConfigManager::initSettings() void VConfigManager::initSettings()
@ -783,36 +790,53 @@ QString VConfigManager::getConfigFilePath() const
return userSettings->fileName(); return userSettings->fileName();
} }
QString VConfigManager::getStyleConfigFolder() const const QString &VConfigManager::getStyleConfigFolder() const
{ {
static QString path = QDir(getConfigFolder()).filePath(c_styleConfigFolder); static QString path = QDir(getConfigFolder()).filePath(c_styleConfigFolder);
return path; return path;
} }
QString VConfigManager::getCodeBlockStyleConfigFolder() const const QString &VConfigManager::getThemeConfigFolder() const
{
static QString path = QDir(getConfigFolder()).filePath(c_themeConfigFolder);
return path;
}
const QString &VConfigManager::getCodeBlockStyleConfigFolder() const
{ {
static QString path = QDir(getStyleConfigFolder()).filePath(c_codeBlockStyleConfigFolder); static QString path = QDir(getStyleConfigFolder()).filePath(c_codeBlockStyleConfigFolder);
return path; return path;
} }
QString VConfigManager::getTemplateConfigFolder() const const QString &VConfigManager::getTemplateConfigFolder() const
{ {
static QString path = QDir(getConfigFolder()).filePath(c_templateConfigFolder); static QString path = QDir(getConfigFolder()).filePath(c_templateConfigFolder);
return path; return path;
} }
QString VConfigManager::getSnippetConfigFolder() const const QString &VConfigManager::getSnippetConfigFolder() const
{ {
static QString path = QDir(getConfigFolder()).filePath(c_snippetConfigFolder); static QString path = QDir(getConfigFolder()).filePath(c_snippetConfigFolder);
return path; return path;
} }
QString VConfigManager::getSnippetConfigFilePath() const const QString &VConfigManager::getSnippetConfigFilePath() const
{ {
static QString path = QDir(getSnippetConfigFolder()).filePath(c_snippetConfigFile); static QString path = QDir(getSnippetConfigFolder()).filePath(c_snippetConfigFile);
return path; return path;
} }
QString VConfigManager::getThemeFile() const
{
QString file;
auto it = m_themes.find(m_theme);
if (it != m_themes.end()) {
file = QDir(getThemeConfigFolder()).filePath(it.value());
}
return file;
}
QVector<QString> VConfigManager::getCssStyles() const QVector<QString> VConfigManager::getCssStyles() const
{ {
QVector<QString> res; QVector<QString> res;
@ -1368,3 +1392,31 @@ const QString &VConfigManager::getFlashPage() const
return m_flashPage; return m_flashPage;
} }
void VConfigManager::initThemes()
{
m_themes.clear();
// Built-in.
m_themes.insert(tr("v_white"), ":/resources/themes/v_white/v_white.palette");
// User theme folder.
QDir dir(getThemeConfigFolder());
if (!dir.exists()) {
dir.mkpath(getThemeConfigFolder());
return;
}
dir.setFilter(QDir::Dirs | QDir::NoDotAndDotDot | QDir::NoSymLinks);
QStringList dirs = dir.entryList();
for (auto const &item : dirs) {
QDir themeDir(dir.filePath(item));
QStringList files = themeDir.entryList(QStringList() << "*.palette");
if (files.size() != 1) {
continue;
}
QFileInfo fi(files[0]);
m_themes.insert(fi.completeBaseName(), themeDir.filePath(files[0]));
}
}

View File

@ -353,15 +353,20 @@ public:
QString getConfigFilePath() const; QString getConfigFilePath() const;
// Get the folder c_styleConfigFolder in the config folder. // Get the folder c_styleConfigFolder in the config folder.
QString getStyleConfigFolder() const; const QString &getStyleConfigFolder() const;
// Get the folder c_templateConfigFolder in the config folder. // Get the folder c_templateConfigFolder in the config folder.
QString getTemplateConfigFolder() const; const QString &getTemplateConfigFolder() const;
// Get the folder c_themeConfigFolder in the config folder.
const QString &getThemeConfigFolder() const;
// Get the folder c_snippetConfigFolder in the config folder. // Get the folder c_snippetConfigFolder in the config folder.
QString getSnippetConfigFolder() const; const QString &getSnippetConfigFolder() const;
QString getSnippetConfigFilePath() const; const QString &getSnippetConfigFilePath() const;
QString getThemeFile() const;
// Read all available css files in c_styleConfigFolder. // Read all available css files in c_styleConfigFolder.
QVector<QString> getCssStyles() const; QVector<QString> getCssStyles() const;
@ -370,7 +375,7 @@ public:
QVector<QString> getNoteTemplates(DocType p_type = DocType::Unknown) const; QVector<QString> getNoteTemplates(DocType p_type = DocType::Unknown) const;
// Get the folder c_codeBlockStyleConfigFolder in the config folder. // Get the folder c_codeBlockStyleConfigFolder in the config folder.
QString getCodeBlockStyleConfigFolder() const; const QString &getCodeBlockStyleConfigFolder() const;
// Read all available css files in c_codeBlockStyleConfigFolder. // Read all available css files in c_codeBlockStyleConfigFolder.
QVector<QString> getCodeBlockCssStyles() const; QVector<QString> getCodeBlockCssStyles() const;
@ -397,6 +402,14 @@ public:
const QString &getFlashPage() const; const QString &getFlashPage() const;
// All the themes.
QList<QString> getThemes() const;
// Return current theme name.
const QString &getTheme() const;
void setTheme(const QString &p_theme);
private: private:
// Look up a config from user and default settings. // Look up a config from user and default settings.
QVariant getConfigFromSettings(const QString &section, const QString &key) const; QVariant getConfigFromSettings(const QString &section, const QString &key) const;
@ -474,6 +487,9 @@ private:
// Whether @p_seq is a valid key sequence for shortcuts. // Whether @p_seq is a valid key sequence for shortcuts.
bool isValidKeySequence(const QString &p_seq); bool isValidKeySequence(const QString &p_seq);
// Init the themes name-file mappings.
void initThemes();
// Default font and palette. // Default font and palette.
QFont m_defaultEditFont; QFont m_defaultEditFont;
QPalette m_defaultEditPalette; QPalette m_defaultEditPalette;
@ -760,6 +776,13 @@ private:
// Absolute path of flash page. // Absolute path of flash page.
QString m_flashPage; QString m_flashPage;
// The theme name.
QString m_theme;
// All the themes.
// [name] -> [file path].
QMap<QString, QString> m_themes;
// The name of the config file in each directory, obsolete. // The name of the config file in each directory, obsolete.
// Use c_dirConfigFile instead. // Use c_dirConfigFile instead.
static const QString c_obsoleteDirConfigFile; static const QString c_obsoleteDirConfigFile;
@ -792,6 +815,9 @@ private:
// The folder name of style files. // The folder name of style files.
static const QString c_styleConfigFolder; static const QString c_styleConfigFolder;
// The folder name of theme files.
static const QString c_themeConfigFolder;
// The folder name of code block style files. // The folder name of code block style files.
static const QString c_codeBlockStyleConfigFolder; static const QString c_codeBlockStyleConfigFolder;
@ -1881,4 +1907,24 @@ inline const QString &VConfigManager::getVimExemptionKeys() const
return m_vimExemptionKeys; return m_vimExemptionKeys;
} }
inline QList<QString> VConfigManager::getThemes() const
{
return m_themes.keys();
}
inline const QString &VConfigManager::getTheme() const
{
return m_theme;
}
inline void VConfigManager::setTheme(const QString &p_theme)
{
if (p_theme == m_theme) {
return;
}
m_theme = p_theme;
setConfigToSettings("global", "theme", m_theme);
}
#endif // VCONFIGMANAGER_H #endif // VCONFIGMANAGER_H

View File

@ -111,3 +111,13 @@ void VInsertSelector::showEvent(QShowEvent *p_event)
setFocus(); setFocus();
} }
} }
void VInsertSelector::paintEvent(QPaintEvent *p_event)
{
QStyleOption opt;
opt.init(this);
QPainter p(this);
style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
QWidget::paintEvent(p_event);
}

View File

@ -7,6 +7,7 @@
class QPushButton; class QPushButton;
class QKeyEvent; class QKeyEvent;
class QShowEvent; class QShowEvent;
class QPaintEvent;
struct VInsertSelectorItem struct VInsertSelectorItem
{ {
@ -64,6 +65,8 @@ protected:
void showEvent(QShowEvent *p_event) Q_DECL_OVERRIDE; void showEvent(QShowEvent *p_event) Q_DECL_OVERRIDE;
void paintEvent(QPaintEvent *p_event) Q_DECL_OVERRIDE;
private slots: private slots:
void itemClicked(const QString &p_name); void itemClicked(const QString &p_name);

View File

@ -925,6 +925,9 @@ void VMainWindow::initFileMenu()
this, &VMainWindow::printNote); this, &VMainWindow::printNote);
m_printAct->setEnabled(false); m_printAct->setEnabled(false);
// Themes.
initThemeMenu(fileMenu);
// Settings. // Settings.
QAction *settingsAct = newAction(QIcon(":/resources/icons/settings.svg"), QAction *settingsAct = newAction(QIcon(":/resources/icons/settings.svg"),
tr("&Settings"), this); tr("&Settings"), this);
@ -2775,3 +2778,36 @@ void VMainWindow::initHeadingButton(QToolBar *p_tb)
m_headingBtn->setMenu(menu); m_headingBtn->setMenu(menu);
p_tb->addWidget(m_headingBtn); p_tb->addWidget(m_headingBtn);
} }
void VMainWindow::initThemeMenu(QMenu *p_menu)
{
QMenu *themeMenu = p_menu->addMenu(tr("Theme"));
themeMenu->setToolTipsVisible(true);
QActionGroup *ag = new QActionGroup(this);
connect(ag, &QActionGroup::triggered,
this, [this](QAction *p_action) {
if (!p_action) {
return;
}
QString data = p_action->data().toString();
g_config->setTheme(data);
});
QList<QString> themes = g_config->getThemes();
QString theme = g_config->getTheme();
for (auto const &item : themes) {
QAction *act = new QAction(item, ag);
act->setToolTip(tr("Set as the theme of VNote (restart VNote to make it work)"));
act->setCheckable(true);
act->setData(item);
// Add it to the menu.
themeMenu->addAction(act);
if (theme == item) {
act->setChecked(true);
}
}
}

View File

@ -263,6 +263,8 @@ private:
void initHeadingButton(QToolBar *p_tb); void initHeadingButton(QToolBar *p_tb);
void initThemeMenu(QMenu *p_emnu);
// Captain mode functions. // Captain mode functions.
// Popup the attachment list if it is enabled. // Popup the attachment list if it is enabled.

View File

@ -413,6 +413,7 @@ void VMdTab::setupMarkdownEditor()
Q_ASSERT(!m_editor); Q_ASSERT(!m_editor);
m_editor = new VMdEditor(m_file, m_document, m_mdConType, this); m_editor = new VMdEditor(m_file, m_document, m_mdConType, this);
m_editor->setProperty("MainEditor", true);
connect(m_editor, &VMdEditor::headersChanged, connect(m_editor, &VMdEditor::headersChanged,
this, &VMdTab::updateOutlineFromHeaders); this, &VMdTab::updateOutlineFromHeaders);
connect(m_editor, SIGNAL(currentHeaderChanged(int)), connect(m_editor, SIGNAL(currentHeaderChanged(int)),

View File

@ -65,7 +65,6 @@
<file>resources/icons/paste.svg</file> <file>resources/icons/paste.svg</file>
<file>resources/icons/dir_item.svg</file> <file>resources/icons/dir_item.svg</file>
<file>resources/icons/notebook_item.svg</file> <file>resources/icons/notebook_item.svg</file>
<file>resources/icons/arrow_dropdown.svg</file>
<file>resources/icons/vnote.png</file> <file>resources/icons/vnote.png</file>
<file>resources/icons/insert_image.svg</file> <file>resources/icons/insert_image.svg</file>
<file>resources/icons/import_note.svg</file> <file>resources/icons/import_note.svg</file>
@ -93,8 +92,6 @@
<file>utils/mermaid/mermaid.forest.css</file> <file>utils/mermaid/mermaid.forest.css</file>
<file>utils/mermaid/mermaidAPI.min.js</file> <file>utils/mermaid/mermaidAPI.min.js</file>
<file>resources/icons/close_red.svg</file> <file>resources/icons/close_red.svg</file>
<file>resources/icons/close_grey.svg</file>
<file>resources/icons/float.svg</file>
<file>resources/docs/shortcuts_en.md</file> <file>resources/docs/shortcuts_en.md</file>
<file>resources/docs/shortcuts_zh.md</file> <file>resources/docs/shortcuts_zh.md</file>
<file>resources/styles/default.css</file> <file>resources/styles/default.css</file>
@ -107,7 +104,6 @@
<file>utils/markdown-it/markdown-it-sub.min.js</file> <file>utils/markdown-it/markdown-it-sub.min.js</file>
<file>utils/markdown-it/markdown-it-sup.min.js</file> <file>utils/markdown-it/markdown-it-sup.min.js</file>
<file>utils/markdown-it/markdown-it-footnote.min.js</file> <file>utils/markdown-it/markdown-it-footnote.min.js</file>
<file>resources/icons/arrow_dropup.svg</file>
<file>resources/icons/vnote_update.svg</file> <file>resources/icons/vnote_update.svg</file>
<file>utils/flowchart.js/flowchart.min.js</file> <file>utils/flowchart.js/flowchart.min.js</file>
<file>utils/flowchart.js/raphael.min.js</file> <file>utils/flowchart.js/raphael.min.js</file>
@ -144,5 +140,11 @@
<file>resources/icons/reading_modified.svg</file> <file>resources/icons/reading_modified.svg</file>
<file>resources/icons/flash_page.svg</file> <file>resources/icons/flash_page.svg</file>
<file>resources/icons/heading.svg</file> <file>resources/icons/heading.svg</file>
<file>resources/themes/v_white/arrow_dropdown.svg</file>
<file>resources/themes/v_white/close.svg</file>
<file>resources/themes/v_white/close_grey.svg</file>
<file>resources/themes/v_white/float.svg</file>
<file>resources/themes/v_white/v_white.palette</file>
<file>resources/themes/v_white/v_white.qss</file>
</qresource> </qresource>
</RCC> </RCC>

129
src/vpalette.cpp Normal file
View File

@ -0,0 +1,129 @@
#include "vpalette.h"
#include <QSettings>
#include <QRegExp>
#include <QFileInfo>
#include <QDir>
#include <QDebug>
#include "utils/vutils.h"
VPalette::VPalette(const QString &p_file)
{
init(p_file);
}
void VPalette::init(const QString &p_file)
{
m_file = QFileInfo(p_file).absoluteFilePath();
QSettings settings(p_file, QSettings::IniFormat);
initMetaData(&settings, "metadata");
initPaleteFromSettings(&settings, "phony");
initPaleteFromSettings(&settings, "widgets");
}
void VPalette::initMetaData(QSettings *p_settings, const QString &p_group)
{
p_settings->beginGroup(p_group);
// Qss file.
QString val = p_settings->value("qss_file").toString();
if (!val.isEmpty()) {
m_qssFile = QDir(VUtils::basePathFromPath(m_file)).filePath(val);
qDebug() << "theme file" << m_file << "qss file" << m_qssFile;
}
p_settings->endGroup();
}
void VPalette::initPaleteFromSettings(QSettings *p_settings, const QString &p_group)
{
QRegExp reg("@(\\w+)");
p_settings->beginGroup(p_group);
QStringList keys = p_settings->childKeys();
for (auto const & key : keys) {
if (key.isEmpty()) {
continue;
}
QString val = p_settings->value(key).toString();
if (reg.exactMatch(val)) {
auto it = m_palette.find(reg.cap(1));
if (it != m_palette.end()) {
val = it.value();
} else {
qWarning() << "non-defined reference attribute" << key << "in palette" << p_settings->fileName();
val.clear();
}
}
m_palette.insert(key, val);
}
p_settings->endGroup();
}
QString VPalette::color(const QString &p_name) const
{
auto it = m_palette.find(p_name);
if (it != m_palette.end()) {
return it.value();
}
return QString();
}
void VPalette::fillStyle(QString &p_style) const
{
// Cap(2) is the string to be replaced.
QRegExp reg("(\\s|:)@(\\w+)(?=\\W)");
int pos = 0;
while (pos < p_style.size()) {
int idx = p_style.indexOf(reg, pos);
if (idx == -1) {
break;
}
QString name = reg.cap(2);
QString val = color(name);
if (val.isEmpty()) {
pos = idx + reg.matchedLength();
} else {
pos = idx + reg.matchedLength() + val.size() - name.size() - 1;
p_style.replace(idx + reg.cap(1).size(), name.size() + 1, val);
}
}
}
QString VPalette::fetchQtStyleSheet() const
{
QString style = VUtils::readFileFromDisk(m_qssFile);
fillStyle(style);
fillAbsoluteUrl(style);
return style;
}
void VPalette::fillAbsoluteUrl(QString &p_style) const
{
// Cap(2) is the string to be replaced.
QRegExp reg("(\\s|:)url\\(([^\\(\\)]+)\\)(?=\\W)");
int literalSize = QString("url(").size();
QDir dir(VUtils::basePathFromPath(m_file));
int pos = 0;
while (pos < p_style.size()) {
int idx = p_style.indexOf(reg, pos);
if (idx == -1) {
break;
}
QString url = reg.cap(2);
QString abUrl = dir.filePath(url);
pos = idx + reg.matchedLength() + abUrl.size() - url.size();
p_style.replace(idx + reg.cap(1).size() + literalSize, url.size(), abUrl);
}
}

39
src/vpalette.h Normal file
View File

@ -0,0 +1,39 @@
#ifndef VPALETTE_H
#define VPALETTE_H
#include <QString>
#include <QHash>
class QSettings;
class VPalette
{
public:
explicit VPalette(const QString &p_file);
QString color(const QString &p_name) const;
// Read QSS file.
QString fetchQtStyleSheet() const;
private:
void init(const QString &p_file);
void initPaleteFromSettings(QSettings *p_settings, const QString &p_group);
void initMetaData(QSettings *p_settings, const QString &p_group);
void fillStyle(QString &p_style) const;
void fillAbsoluteUrl(QString &p_style) const;
// File path of the palette file.
QString m_file;
QHash<QString, QString> m_palette;
QString m_qssFile;
};
#endif // VPALETTE_H