From 1fafa0dae7c8154efcb41154bfe0772f81913799 Mon Sep 17 00:00:00 2001 From: Veronica Berglyd Olsen <1619840+vkbo@users.noreply.github.com> Date: Mon, 2 Jun 2025 16:28:06 +0200 Subject: [PATCH 01/20] Remove syntax theme parsing and add light and dark theme user settings --- novelwriter/common.py | 11 ++ novelwriter/config.py | 52 ++++---- novelwriter/dialogs/preferences.py | 52 ++++---- novelwriter/enum.py | 7 ++ novelwriter/gui/theme.py | 188 ++++++++++++----------------- novelwriter/guimain.py | 1 - 6 files changed, 148 insertions(+), 163 deletions(-) diff --git a/novelwriter/common.py b/novelwriter/common.py index a4e37f62..6d1e8519 100644 --- a/novelwriter/common.py +++ b/novelwriter/common.py @@ -31,6 +31,7 @@ import xml.etree.ElementTree as ET from configparser import ConfigParser from datetime import datetime +from enum import Enum from pathlib import Path from typing import TYPE_CHECKING, Any, Literal, TypeGuard, TypeVar from urllib.parse import urljoin @@ -676,6 +677,9 @@ def openExternalPath(path: Path) -> bool: # Classes ## +_T_Enum = TypeVar("_T_Enum", bound=Enum) + + class NWConfigParser(ConfigParser): """Common: Adapted Config Parser @@ -736,3 +740,10 @@ class NWConfigParser(ConfigParser): for i in range(min(len(data), len(result))): result[i] = checkInt(data[i].strip(), result[i]) return result + + def rdEnum(self, section: str, option: str, default: _T_Enum) -> _T_Enum: + """Read enum value.""" + if self.has_option(section, option): + data = self.get(section, option, fallback="") + return type(default).__members__.get(data.upper(), default) + return default diff --git a/novelwriter/config.py b/novelwriter/config.py index ac403fdb..9b8752fc 100644 --- a/novelwriter/config.py +++ b/novelwriter/config.py @@ -45,6 +45,7 @@ from novelwriter.common import ( formatTimeStamp, processDialogSymbols, simplified ) from novelwriter.constants import nwFiles, nwHtmlUnicode, nwQuotes, nwUnicode +from novelwriter.enum import nwTheme from novelwriter.error import formatException, logException if TYPE_CHECKING: @@ -55,8 +56,8 @@ if TYPE_CHECKING: logger = logging.getLogger(__name__) -DEF_GUI = "default" -DEF_SYNTAX = "default_light" +DEF_GUI_DARK = "default_dark" +DEF_GUI_LIGHT = "default_light" DEF_ICONS = "material_rounded_normal" DEF_TREECOL = "theme" @@ -69,22 +70,22 @@ class Config: "_manuals", "_nwLangPath", "_qLocale", "_qtLangPath", "_qtTrans", "_recentPaths", "_recentProjects", "_splash", "allowOpenDial", "altDialogClose", "altDialogOpen", "appHandle", "appName", "askBeforeBackup", "askBeforeExit", "autoSaveDoc", "autoSaveProj", - "autoScroll", "autoScrollPos", "autoSelect", "backupOnClose", "cursorWidth", "dialogLine", - "dialogStyle", "doJustify", "doReplace", "doReplaceDQuote", "doReplaceDash", + "autoScroll", "autoScrollPos", "autoSelect", "backupOnClose", "cursorWidth", "darkTheme", + "dialogLine", "dialogStyle", "doJustify", "doReplace", "doReplaceDQuote", "doReplaceDash", "doReplaceDots", "doReplaceSQuote", "emphLabels", "fmtApostrophe", "fmtDQuoteClose", "fmtDQuoteOpen", "fmtPadAfter", "fmtPadBefore", "fmtPadThin", "fmtSQuoteClose", - "fmtSQuoteOpen", "focusWidth", "guiFont", "guiLocale", "guiSyntax", "guiTheme", - "hasEnchant", "hideFocusFooter", "hideHScroll", "hideVScroll", "highlightEmph", "hostName", - "iconColDocs", "iconColTree", "iconTheme", "incNotesWCount", "isDebug", "kernelVer", - "lastNotes", "mainPanePos", "mainWinSize", "memInfo", "narratorBreak", "narratorDialog", - "nativeFont", "osDarwin", "osLinux", "osType", "osUnknown", "osWindows", "outlinePanePos", + "fmtSQuoteOpen", "focusWidth", "guiFont", "guiLocale", "hasEnchant", "hideFocusFooter", + "hideHScroll", "hideVScroll", "highlightEmph", "hostName", "iconColDocs", "iconColTree", + "iconTheme", "incNotesWCount", "isDebug", "kernelVer", "lastNotes", "lightTheme", + "mainPanePos", "mainWinSize", "memInfo", "narratorBreak", "narratorDialog", "nativeFont", + "osDarwin", "osLinux", "osType", "osUnknown", "osWindows", "outlinePanePos", "prefsWinSize", "scrollPastEnd", "searchCase", "searchLoop", "searchMatchCap", "searchNextFile", "searchProjCase", "searchProjRegEx", "searchProjWord", "searchRegEx", "searchWord", "showEditToolBar", "showFullPath", "showLineEndings", "showMultiSpaces", "showSessionTime", "showTabsNSpaces", "showViewerPanel", "spellLanguage", "stopWhenIdle", - "tabWidth", "textFont", "textMargin", "textWidth", "useCharCount", "userIdleTime", - "verPyQtString", "verPyQtValue", "verPyString", "verQtString", "verQtValue", - "viewComments", "viewPanePos", "viewSynopsis", "welcomeWinSize", + "tabWidth", "textFont", "textMargin", "textWidth", "themeMode", "useCharCount", + "userIdleTime", "verPyQtString", "verPyQtValue", "verPyString", "verQtString", + "verQtValue", "viewComments", "viewPanePos", "viewSynopsis", "welcomeWinSize", ) LANG_NW = 1 @@ -153,14 +154,15 @@ class Config: # General GUI Settings self.guiLocale = self._qLocale.name() - self.guiTheme = DEF_GUI # GUI theme - self.guiSyntax = DEF_SYNTAX # Syntax theme - self.guiFont = QFont() # Main GUI font - self.hideVScroll = False # Hide vertical scroll bars on main widgets - self.hideHScroll = False # Hide horizontal scroll bars on main widgets - self.lastNotes = "0x0" # The latest release notes that have been shown - self.nativeFont = True # Use native font dialog - self.useCharCount = False # Use character count as primary count + self.lightTheme = DEF_GUI_LIGHT # Light GUI theme + self.darkTheme = DEF_GUI_DARK # Dark GUI theme + self.themeMode = nwTheme.AUTO # Colour theme mode + self.guiFont = QFont() # Main GUI font + self.hideVScroll = False # Hide vertical scroll bars on main widgets + self.hideHScroll = False # Hide horizontal scroll bars on main widgets + self.lastNotes = "0x0" # The latest release notes that have been shown + self.nativeFont = True # Use native font dialog + self.useCharCount = False # Use character count as primary count # Icons self.iconTheme = DEF_ICONS # Icons theme @@ -626,8 +628,9 @@ class Config: # Main sec = "Main" self.setGuiFont(conf.rdStr(sec, "font", "")) - self.guiTheme = conf.rdStr(sec, "theme", self.guiTheme) - self.guiSyntax = conf.rdStr(sec, "syntax", self.guiSyntax) + self.lightTheme = conf.rdStr(sec, "lighttheme", self.lightTheme) + self.darkTheme = conf.rdStr(sec, "darktheme", self.darkTheme) + self.themeMode = conf.rdEnum(sec, "thememode", self.themeMode) self.iconTheme = conf.rdStr(sec, "icons", self.iconTheme) self.iconColTree = conf.rdStr(sec, "iconcoltree", self.iconColTree) self.iconColDocs = conf.rdBool(sec, "iconcoldocs", self.iconColDocs) @@ -751,8 +754,9 @@ class Config: conf["Main"] = { "font": self.guiFont.toString(), - "theme": str(self.guiTheme), - "syntax": str(self.guiSyntax), + "lighttheme": str(self.lightTheme), + "darktheme": str(self.darkTheme), + "thememode": self.themeMode.name, "icons": str(self.iconTheme), "iconcoltree": str(self.iconColTree), "iconcoldocs": str(self.iconColDocs), diff --git a/novelwriter/dialogs/preferences.py b/novelwriter/dialogs/preferences.py index 281487b3..9587db6a 100644 --- a/novelwriter/dialogs/preferences.py +++ b/novelwriter/dialogs/preferences.py @@ -35,7 +35,7 @@ from PyQt6.QtWidgets import ( from novelwriter import CONFIG, SHARED from novelwriter.common import compact, describeFont, processDialogSymbols, uniqueCompact -from novelwriter.config import DEF_GUI, DEF_ICONS, DEF_SYNTAX, DEF_TREECOL +from novelwriter.config import DEF_GUI_DARK, DEF_GUI_LIGHT, DEF_ICONS, DEF_TREECOL from novelwriter.constants import nwLabels, nwQuotes, nwUnicode, trConst from novelwriter.dialogs.quotes import GuiQuoteSelect from novelwriter.extensions.configlayout import NColorLabel, NScrollableForm @@ -165,14 +165,24 @@ class GuiPreferences(NDialog): ) # Colour Theme - self.guiTheme = NComboBox(self) - self.guiTheme.setMinimumWidth(200) - for theme, name in SHARED.theme.listThemes(): - self.guiTheme.addItem(name, theme) - self.guiTheme.setCurrentData(CONFIG.guiTheme, DEF_GUI) + self.lightTheme = NComboBox(self) + self.lightTheme.setMinimumWidth(200) + self.darkTheme = NComboBox(self) + self.darkTheme.setMinimumWidth(200) + for theme, name, dark in SHARED.theme.listThemes(): + if dark: + self.darkTheme.addItem(name, theme) + else: + self.lightTheme.addItem(name, theme) + self.lightTheme.setCurrentData(CONFIG.lightTheme, DEF_GUI_LIGHT) + self.darkTheme.setCurrentData(CONFIG.darkTheme, DEF_GUI_DARK) self.mainForm.addRow( - self.tr("Colour theme"), self.guiTheme, + self.tr("Light colour theme"), self.lightTheme, + self.tr("User interface colour theme."), stretch=(3, 2) + ) + self.mainForm.addRow( + self.tr("Dark colour theme"), self.darkTheme, self.tr("User interface colour theme."), stretch=(3, 2) ) @@ -242,18 +252,6 @@ class GuiPreferences(NDialog): self.sidebar.addButton(title, section) self.mainForm.addGroupLabel(title, section) - # Document Colour Theme - self.guiSyntax = NComboBox(self) - self.guiSyntax.setMinimumWidth(200) - for syntax, name in SHARED.theme.listSyntax(): - self.guiSyntax.addItem(name, syntax) - self.guiSyntax.setCurrentData(CONFIG.guiSyntax, DEF_SYNTAX) - - self.mainForm.addRow( - self.tr("Document colour theme"), self.guiSyntax, - self.tr("Colour theme for the editor and viewer."), stretch=(3, 2) - ) - # Document Font Family self.textFont = QLineEdit(self) self.textFont.setReadOnly(True) @@ -966,18 +964,23 @@ class GuiPreferences(NDialog): # Appearance guiLocale = self.guiLocale.currentData() - guiTheme = self.guiTheme.currentData() + lightTheme = self.lightTheme.currentData() + darkTheme = self.darkTheme.currentData() iconTheme = self.iconTheme.currentData() useCharCount = self.useCharCount.isChecked() - updateTheme |= CONFIG.guiTheme != guiTheme + updateTheme |= CONFIG.lightTheme != lightTheme + updateTheme |= CONFIG.darkTheme != darkTheme updateTheme |= CONFIG.iconTheme != iconTheme needsRestart |= CONFIG.guiLocale != guiLocale needsRestart |= CONFIG.guiFont != self._guiFont refreshTree |= CONFIG.useCharCount != useCharCount + updateSyntax |= CONFIG.lightTheme != lightTheme + updateSyntax |= CONFIG.darkTheme != darkTheme CONFIG.guiLocale = guiLocale - CONFIG.guiTheme = guiTheme + CONFIG.lightTheme = lightTheme + CONFIG.darkTheme = darkTheme CONFIG.iconTheme = iconTheme CONFIG.hideVScroll = self.hideVScroll.isChecked() CONFIG.hideHScroll = self.hideHScroll.isChecked() @@ -986,11 +989,6 @@ class GuiPreferences(NDialog): CONFIG.setGuiFont(self._guiFont) # Document Style - guiSyntax = self.guiSyntax.currentData() - - updateSyntax |= CONFIG.guiSyntax != guiSyntax - - CONFIG.guiSyntax = guiSyntax CONFIG.showFullPath = self.showFullPath.isChecked() CONFIG.incNotesWCount = self.incNotesWCount.isChecked() CONFIG.setTextFont(self._textFont) diff --git a/novelwriter/enum.py b/novelwriter/enum.py index a837d824..18899295 100644 --- a/novelwriter/enum.py +++ b/novelwriter/enum.py @@ -156,6 +156,13 @@ class nwFocus(Enum): OUTLINE = 3 +class nwTheme(Enum): + + AUTO = 0 + LIGHT = 1 + DARK = 2 + + class nwOutline(Enum): TITLE = 0 diff --git a/novelwriter/gui/theme.py b/novelwriter/gui/theme.py index 1eb2e487..1118f7d5 100644 --- a/novelwriter/gui/theme.py +++ b/novelwriter/gui/theme.py @@ -31,16 +31,16 @@ from typing import TYPE_CHECKING, Final from PyQt6.QtCore import QSize, Qt from PyQt6.QtGui import ( - QColor, QFont, QFontDatabase, QFontMetrics, QIcon, QPainter, QPainterPath, - QPalette, QPixmap + QColor, QFont, QFontDatabase, QFontMetrics, QGuiApplication, QIcon, + QPainter, QPainterPath, QPalette, QPixmap ) from PyQt6.QtWidgets import QApplication from novelwriter import CONFIG from novelwriter.common import NWConfigParser, minmax -from novelwriter.config import DEF_GUI, DEF_ICONS, DEF_SYNTAX +from novelwriter.config import DEF_GUI_DARK, DEF_GUI_LIGHT, DEF_ICONS from novelwriter.constants import nwLabels -from novelwriter.enum import nwItemClass, nwItemLayout, nwItemType +from novelwriter.enum import nwItemClass, nwItemLayout, nwItemType, nwTheme from novelwriter.error import logException from novelwriter.types import QtBlack, QtHexArgb, QtPaintAntiAlias, QtTransparent @@ -49,6 +49,8 @@ if TYPE_CHECKING: logger = logging.getLogger(__name__) +T_ThemeEntry = tuple[str, str, bool] + STYLES_FLAT_TABS = "flatTabWidget" STYLES_MIN_TOOLBUTTON = "minimalToolButton" STYLES_BIG_TOOLBUTTON = "bigToolButton" @@ -57,6 +59,7 @@ STYLES_BIG_TOOLBUTTON = "bigToolButton" class ThemeMeta: name: str = "" + mode: str = "" description: str = "" author: str = "" credit: str = "" @@ -96,13 +99,13 @@ class GuiTheme: """ __slots__ = ( - "_availSyntax", "_availThemes", "_guiPalette", "_styleSheets", "_syntaxList", "_themeList", - "baseButtonHeight", "baseIconHeight", "baseIconSize", "buttonIconSize", "errorText", - "fadedText", "fontPixelSize", "fontPointSize", "getDecoration", "getHeaderDecoration", - "getHeaderDecorationNarrow", "getIcon", "getIconColor", "getItemIcon", "getPixmap", - "getToggleIcon", "guiFont", "guiFontB", "guiFontBU", "guiFontFixed", "guiFontSmall", - "helpText", "iconCache", "isDarkTheme", "syntaxMeta", "syntaxTheme", "textNHeight", - "textNWidth", "themeMeta", + "_availSyntax", "_availThemes", "_darkThemes", "_guiPalette", "_lightThemes", + "_styleSheets", "_syntaxList", "_themeList", "baseButtonHeight", "baseIconHeight", + "baseIconSize", "buttonIconSize", "errorText", "fadedText", "fontPixelSize", + "fontPointSize", "getDecoration", "getHeaderDecoration", "getHeaderDecorationNarrow", + "getIcon", "getIconColor", "getItemIcon", "getPixmap", "getToggleIcon", "guiFont", + "guiFontB", "guiFontBU", "guiFontFixed", "guiFontSmall", "helpText", "iconCache", + "isDarkTheme", "syntaxMeta", "syntaxTheme", "textNHeight", "textNWidth", "themeMeta", ) def __init__(self) -> None: @@ -124,8 +127,7 @@ class GuiTheme: # Load Themes self._guiPalette = QPalette() - self._themeList: list[tuple[str, str]] = [] - self._syntaxList: list[tuple[str, str]] = [] + self._themeList: list[T_ThemeEntry] = [] self._availThemes: dict[str, Path] = {} self._availSyntax: dict[str, Path] = {} self._styleSheets: dict[str, str] = {} @@ -179,13 +181,10 @@ class GuiTheme: logger.debug("Text 'N' Width: %d", self.textNWidth) # Process Themes - _listConf(self._availSyntax, CONFIG.assetPath("syntax"), ".conf") _listConf(self._availThemes, CONFIG.assetPath("themes"), ".conf") - _listConf(self._availSyntax, CONFIG.dataPath("syntax"), ".conf") _listConf(self._availThemes, CONFIG.dataPath("themes"), ".conf") self.loadTheme() - self.loadSyntax() return @@ -207,13 +206,35 @@ class GuiTheme: # Theme Methods ## + def isDesktopDarkMode(self) -> bool: + """Check if the desktop is in dark mode.""" + if CONFIG.verQtValue >= 0x060500 and (hint := QGuiApplication.styleHints()): + return hint.colorScheme() == Qt.ColorScheme.Dark + + palette = QPalette() + text = palette.color(QPalette.ColorRole.WindowText) + window = palette.color(QPalette.ColorRole.Window) + return text.lightnessF() > window.lightnessF() + def loadTheme(self) -> bool: """Load the currently specified GUI theme.""" - theme = CONFIG.guiTheme + match CONFIG.themeMode: + case nwTheme.LIGHT: + darkMode = False + case nwTheme.DARK: + darkMode = True + case _: + darkMode = self.isDesktopDarkMode() + + theme = CONFIG.darkTheme if darkMode else CONFIG.lightTheme if theme not in self._availThemes: logger.error("Could not find GUI theme '%s'", theme) - theme = DEF_GUI - CONFIG.guiTheme = theme + if darkMode: + theme = DEF_GUI_DARK + CONFIG.darkTheme = DEF_GUI_DARK + else: + theme = DEF_GUI_LIGHT + CONFIG.lightTheme = DEF_GUI_LIGHT if not (file := self._availThemes.get(theme)): logger.error("Could not load GUI theme") @@ -238,6 +259,7 @@ class GuiTheme: meta = ThemeMeta() if parser.has_section(sec): meta.name = parser.rdStr(sec, "name", "") + meta.mode = parser.rdStr(sec, "mode", "light") meta.description = parser.rdStr(sec, "description", "N/A") meta.author = parser.rdStr(sec, "author", "N/A") meta.credit = parser.rdStr(sec, "credit", "N/A") @@ -296,6 +318,31 @@ class GuiTheme: self.fadedText = self._parseColor(parser, sec, "fadedtext") self.errorText = self._parseColor(parser, sec, "errortext") + # Syntax + sec = "Syntax" + self.syntaxTheme = SyntaxColors() + if parser.has_section(sec): + self.syntaxTheme.back = self._parseColor(parser, sec, "background") + self.syntaxTheme.text = self._parseColor(parser, sec, "text") + self.syntaxTheme.link = self._parseColor(parser, sec, "link") + self.syntaxTheme.head = self._parseColor(parser, sec, "headertext") + self.syntaxTheme.headH = self._parseColor(parser, sec, "headertag") + self.syntaxTheme.emph = self._parseColor(parser, sec, "emphasis") + self.syntaxTheme.dialN = self._parseColor(parser, sec, "dialog") + self.syntaxTheme.dialA = self._parseColor(parser, sec, "altdialog") + self.syntaxTheme.hidden = self._parseColor(parser, sec, "hidden") + self.syntaxTheme.note = self._parseColor(parser, sec, "note") + self.syntaxTheme.code = self._parseColor(parser, sec, "shortcode") + self.syntaxTheme.key = self._parseColor(parser, sec, "keyword") + self.syntaxTheme.tag = self._parseColor(parser, sec, "tag") + self.syntaxTheme.val = self._parseColor(parser, sec, "value") + self.syntaxTheme.opt = self._parseColor(parser, sec, "optional") + self.syntaxTheme.spell = self._parseColor(parser, sec, "spellcheckline") + self.syntaxTheme.error = self._parseColor(parser, sec, "errorline") + self.syntaxTheme.repTag = self._parseColor(parser, sec, "replacetag") + self.syntaxTheme.mod = self._parseColor(parser, sec, "modifier") + self.syntaxTheme.mark = self._parseColor(parser, sec, "texthighlight") + # Update Dependant Colours # Based on: https://github.com/qt/qtbase/blob/dev/src/gui/kernel/qplatformtheme.cpp text = self._guiPalette.text().color() @@ -363,105 +410,22 @@ class GuiTheme: return True - def loadSyntax(self) -> bool: - """Load the currently specified syntax highlighter theme.""" - theme = CONFIG.guiSyntax - if theme not in self._availSyntax: - logger.error("Could not find syntax theme '%s'", theme) - theme = DEF_SYNTAX - CONFIG.guiSyntax = theme - - if not (file := self._availSyntax.get(theme)): - logger.error("Could not load syntax theme") - return False - - CONFIG.splashMessage("Loading syntax theme ...") - logger.info("Loading syntax theme '%s'", theme) - parser = NWConfigParser() - try: - with open(file, mode="r", encoding="utf-8") as fo: - parser.read_file(fo) - except Exception: - logger.error("Could not read file: %s", file) - logException() - return False - - # Main - sec = "Main" - meta = ThemeMeta() - if parser.has_section(sec): - meta.name = parser.rdStr(sec, "name", "") - meta.description = parser.rdStr(sec, "description", "N/A") - meta.author = parser.rdStr(sec, "author", "N/A") - meta.credit = parser.rdStr(sec, "credit", "N/A") - meta.url = parser.rdStr(sec, "url", "") - meta.license = parser.rdStr(sec, "license", "N/A") - meta.licenseUrl = parser.rdStr(sec, "licenseurl", "") - - # Syntax - sec = "Syntax" - syntax = SyntaxColors() - if parser.has_section(sec): - syntax.back = self._parseColor(parser, sec, "background") - syntax.text = self._parseColor(parser, sec, "text") - syntax.link = self._parseColor(parser, sec, "link") - syntax.head = self._parseColor(parser, sec, "headertext") - syntax.headH = self._parseColor(parser, sec, "headertag") - syntax.emph = self._parseColor(parser, sec, "emphasis") - syntax.dialN = self._parseColor(parser, sec, "dialog") - syntax.dialA = self._parseColor(parser, sec, "altdialog") - syntax.hidden = self._parseColor(parser, sec, "hidden") - syntax.note = self._parseColor(parser, sec, "note") - syntax.code = self._parseColor(parser, sec, "shortcode") - syntax.key = self._parseColor(parser, sec, "keyword") - syntax.tag = self._parseColor(parser, sec, "tag") - syntax.val = self._parseColor(parser, sec, "value") - syntax.opt = self._parseColor(parser, sec, "optional") - syntax.spell = self._parseColor(parser, sec, "spellcheckline") - syntax.error = self._parseColor(parser, sec, "errorline") - syntax.repTag = self._parseColor(parser, sec, "replacetag") - syntax.mod = self._parseColor(parser, sec, "modifier") - syntax.mark = self._parseColor(parser, sec, "texthighlight") - - CONFIG.splashMessage(f"Loaded syntax theme: {meta.name}") - - self.syntaxMeta = meta - self.syntaxTheme = syntax - - return True - - def listThemes(self) -> list[tuple[str, str]]: + def listThemes(self) -> list[T_ThemeEntry]: """Scan the GUI themes folder and list all themes.""" if self._themeList: return self._themeList - themes = [] + themes: list[T_ThemeEntry] = [] parser = NWConfigParser() for key, path in self._availThemes.items(): logger.debug("Checking theme config '%s'", key) - if name := _loadInternalName(parser, path): - themes.append((key, name)) + if meta := _loadInternalName(parser, path): + themes.append((key, meta[0], meta[1])) self._themeList = sorted(themes, key=_sortTheme) return self._themeList - def listSyntax(self) -> list[tuple[str, str]]: - """Scan the syntax themes folder and list all themes.""" - if self._syntaxList: - return self._syntaxList - - themes = [] - parser = NWConfigParser() - for key, path in self._availSyntax.items(): - logger.debug("Checking theme syntax '%s'", key) - if name := _loadInternalName(parser, path): - themes.append((key, name)) - - self._syntaxList = sorted(themes, key=_sortTheme) - - return self._syntaxList - def getStyleSheet(self, name: str) -> str: """Load a standard style sheet.""" return self._styleSheets.get(name, "") @@ -889,22 +853,24 @@ def _listConf(target: dict, path: Path, extension: str) -> None: return -def _sortTheme(data: tuple[str, str]) -> str: +def _sortTheme(data: tuple) -> str: """Key function for theme sorting.""" - key, name = data + key, name = data[:2] return f"*{name}" if key.startswith("default_") else name -def _loadInternalName(parser: NWConfigParser, path: str | Path) -> str: +def _loadInternalName(parser: NWConfigParser, path: str | Path) -> tuple[str, bool]: """Open a conf file and read the 'name' setting.""" try: with open(path, mode="r", encoding="utf-8") as inFile: parser.read_file(inFile) - return parser.rdStr("Main", "name", "") + name = parser.rdStr("Main", "name", "") + dark = parser.rdStr("Main", "mode", "light").lower() == "dark" + return name, dark except Exception: logger.error("Could not read file: %s", path) logException() - return "" + return "", False def _loadIconName(path: Path) -> str: diff --git a/novelwriter/guimain.py b/novelwriter/guimain.py index 8a895bfe..601540f0 100644 --- a/novelwriter/guimain.py +++ b/novelwriter/guimain.py @@ -1069,7 +1069,6 @@ class GuiMain(QMainWindow): SHARED.project.tree.refreshAllItems() if syntax: - SHARED.theme.loadSyntax() self.docEditor.updateSyntaxColors() self.docEditor.initEditor() From 857327e9ef7a2c168075d7395ef21d31f56f47d4 Mon Sep 17 00:00:00 2001 From: Veronica Berglyd Olsen <1619840+vkbo@users.noreply.github.com> Date: Mon, 2 Jun 2025 17:06:28 +0200 Subject: [PATCH 02/20] Update theme colour processing and fix current tests --- novelwriter/assets/themes/default_dark.conf | 1 + novelwriter/assets/themes/default_light.conf | 1 + novelwriter/gui/statusbar.py | 6 +- novelwriter/gui/theme.py | 278 +++++++++++-------- tests/reference/baseConfig_novelwriter.conf | 7 +- tests/test_base/test_base_config.py | 8 +- tests/test_dialogs/test_dlg_preferences.py | 34 +-- tests/test_gui/test_gui_guimain.py | 9 +- tests/test_gui/test_gui_theme.py | 150 ++++++---- 9 files changed, 285 insertions(+), 209 deletions(-) diff --git a/novelwriter/assets/themes/default_dark.conf b/novelwriter/assets/themes/default_dark.conf index 76916604..6ccf6ede 100644 --- a/novelwriter/assets/themes/default_dark.conf +++ b/novelwriter/assets/themes/default_dark.conf @@ -1,5 +1,6 @@ [Main] name = Default Dark Theme +mode = dark description = The novelWriter standard dark theme author = Veronica Berglyd Olsen credit = Veronica Berglyd Olsen diff --git a/novelwriter/assets/themes/default_light.conf b/novelwriter/assets/themes/default_light.conf index 29b4b98a..f236f404 100644 --- a/novelwriter/assets/themes/default_light.conf +++ b/novelwriter/assets/themes/default_light.conf @@ -1,5 +1,6 @@ [Main] name = Default Light Theme +mode = light description = The novelWriter standard light theme author = Veronica Berglyd Olsen credit = Veronica Berglyd Olsen diff --git a/novelwriter/gui/statusbar.py b/novelwriter/gui/statusbar.py index 3239fd4a..315633da 100644 --- a/novelwriter/gui/statusbar.py +++ b/novelwriter/gui/statusbar.py @@ -143,9 +143,9 @@ class GuiMainStatus(QStatusBar): self.idlePixmap = SHARED.theme.getPixmap("timer_off", (iPx, iPx)) self.timeIcon.setPixmap(self.timePixmap) - colNone = SHARED.theme.getIconColor("default").darker(150) - colSaved = SHARED.theme.getIconColor("green").darker(150) - colUnsaved = SHARED.theme.getIconColor("red").darker(150) + colNone = SHARED.theme.getBaseColor("default").darker(150) + colSaved = SHARED.theme.getBaseColor("green").darker(150) + colUnsaved = SHARED.theme.getBaseColor("red").darker(150) self.docIcon.setColors(colNone, colSaved, colUnsaved) self.projIcon.setColors(colNone, colSaved, colUnsaved) diff --git a/novelwriter/gui/theme.py b/novelwriter/gui/theme.py index 1118f7d5..437531a3 100644 --- a/novelwriter/gui/theme.py +++ b/novelwriter/gui/theme.py @@ -26,6 +26,7 @@ from __future__ import annotations import logging +from configparser import ConfigParser from math import ceil from typing import TYPE_CHECKING, Final @@ -37,7 +38,7 @@ from PyQt6.QtGui import ( from PyQt6.QtWidgets import QApplication from novelwriter import CONFIG -from novelwriter.common import NWConfigParser, minmax +from novelwriter.common import checkInt, minmax from novelwriter.config import DEF_GUI_DARK, DEF_GUI_LIGHT, DEF_ICONS from novelwriter.constants import nwLabels from novelwriter.enum import nwItemClass, nwItemLayout, nwItemType, nwTheme @@ -99,13 +100,14 @@ class GuiTheme: """ __slots__ = ( - "_availSyntax", "_availThemes", "_darkThemes", "_guiPalette", "_lightThemes", - "_styleSheets", "_syntaxList", "_themeList", "baseButtonHeight", "baseIconHeight", - "baseIconSize", "buttonIconSize", "errorText", "fadedText", "fontPixelSize", - "fontPointSize", "getDecoration", "getHeaderDecoration", "getHeaderDecorationNarrow", - "getIcon", "getIconColor", "getItemIcon", "getPixmap", "getToggleIcon", "guiFont", - "guiFontB", "guiFontBU", "guiFontFixed", "guiFontSmall", "helpText", "iconCache", - "isDarkTheme", "syntaxMeta", "syntaxTheme", "textNHeight", "textNWidth", "themeMeta", + "_availSyntax", "_availThemes", "_darkThemes", "_guiPalette", "_lightThemes", "_qColors", + "_styleSheets", "_svgColors", "_syntaxList", "_themeList", "baseButtonHeight", + "baseIconHeight", "baseIconSize", "buttonIconSize", "errorText", "fadedText", + "fontPixelSize", "fontPointSize", "getDecoration", "getHeaderDecoration", + "getHeaderDecorationNarrow", "getIcon", "getItemIcon", "getPixmap", "getToggleIcon", + "guiFont", "guiFontB", "guiFontBU", "guiFontFixed", "guiFontSmall", "helpText", + "iconCache", "isDarkTheme", "syntaxMeta", "syntaxTheme", "textNHeight", "textNWidth", + "themeMeta", ) def __init__(self) -> None: @@ -131,12 +133,13 @@ class GuiTheme: self._availThemes: dict[str, Path] = {} self._availSyntax: dict[str, Path] = {} self._styleSheets: dict[str, str] = {} + self._svgColors: dict[str, bytes] = {} + self._qColors: dict[str, QColor] = {} # Icon Functions self.getIcon = self.iconCache.getIcon self.getPixmap = self.iconCache.getPixmap self.getItemIcon = self.iconCache.getItemIcon - self.getIconColor = self.iconCache.getIconColor self.getToggleIcon = self.iconCache.getToggleIcon self.getDecoration = self.iconCache.getDecoration self.getHeaderDecoration = self.iconCache.getHeaderDecoration @@ -202,6 +205,14 @@ class GuiTheme: qMetrics = QFontMetrics(self.guiFont) return ceil(qMetrics.boundingRect(text).width()) + def getBaseColor(self, name: str) -> QColor: + """Return a base color.""" + return QColor(self._qColors.get(name) or QtBlack) + + def getRawBaseColor(self, name: str) -> bytes: + """Return a base color.""" + return self._svgColors.get(name, self._svgColors.get("default", b"#000000")) + ## # Theme Methods ## @@ -216,6 +227,34 @@ class GuiTheme: window = palette.color(QPalette.ColorRole.Window) return text.lightnessF() > window.lightnessF() + def parseColor(self, value: str, default: QColor = QtBlack) -> QColor: + """Parse a string as a colour value.""" + if value in self._qColors: + # Named colour + return self._qColors[value] + elif value.startswith("#"): + if len(value) >= 9: + # Convert from #RRGGBBAA to #AARRGGBB + return QColor.fromString(f"#{value[7:9]}{value[1:7]}") + else: + # Assume #RRGGBB + return QColor.fromString(value[:7]) + elif "," in value: + data = value.split(",") + entries = len(data) + if entries == 2: + # Assume name, alpha + color = self._qColors.get(data[0].strip(), default) + color.setAlpha(checkInt(data[1], 255)) + return color + else: + # Assume red, green, blue, alpha + result = [0, 0, 0, 255] + for i in range(min(entries, 4)): + result[i] = checkInt(data[i].strip(), result[i]) + return QColor(*result) + return default + def loadTheme(self) -> bool: """Load the currently specified GUI theme.""" match CONFIG.themeMode: @@ -242,7 +281,7 @@ class GuiTheme: CONFIG.splashMessage("Loading GUI theme ...") logger.info("Loading GUI theme '%s'", theme) - parser = NWConfigParser() + parser = ConfigParser() try: with open(file, mode="r", encoding="utf-8") as fo: parser.read_file(fo) @@ -258,40 +297,40 @@ class GuiTheme: sec = "Main" meta = ThemeMeta() if parser.has_section(sec): - meta.name = parser.rdStr(sec, "name", "") - meta.mode = parser.rdStr(sec, "mode", "light") - meta.description = parser.rdStr(sec, "description", "N/A") - meta.author = parser.rdStr(sec, "author", "N/A") - meta.credit = parser.rdStr(sec, "credit", "N/A") - meta.url = parser.rdStr(sec, "url", "") - meta.license = parser.rdStr(sec, "license", "N/A") - meta.licenseUrl = parser.rdStr(sec, "licenseurl", "") + meta.name = parser.get(sec, "name", fallback="") + meta.mode = parser.get(sec, "mode", fallback="light") + meta.description = parser.get(sec, "description", fallback="N/A") + meta.author = parser.get(sec, "author", fallback="N/A") + meta.credit = parser.get(sec, "credit", fallback="N/A") + meta.url = parser.get(sec, "url", fallback="") + meta.license = parser.get(sec, "license", fallback="N/A") + meta.licenseUrl = parser.get(sec, "licenseurl", fallback="") self.themeMeta = meta # Icons - sec = "Icons" + sec = "Base" if parser.has_section(sec): - self.iconCache.setIconColor("default", self._parseColor(parser, sec, "default")) - self.iconCache.setIconColor("faded", self._parseColor(parser, sec, "faded")) - self.iconCache.setIconColor("red", self._parseColor(parser, sec, "red")) - self.iconCache.setIconColor("orange", self._parseColor(parser, sec, "orange")) - self.iconCache.setIconColor("yellow", self._parseColor(parser, sec, "yellow")) - self.iconCache.setIconColor("green", self._parseColor(parser, sec, "green")) - self.iconCache.setIconColor("aqua", self._parseColor(parser, sec, "aqua")) - self.iconCache.setIconColor("blue", self._parseColor(parser, sec, "blue")) - self.iconCache.setIconColor("purple", self._parseColor(parser, sec, "purple")) + self._setBaseColor("default", self._readColor(parser, sec, "default")) + self._setBaseColor("faded", self._readColor(parser, sec, "faded")) + self._setBaseColor("red", self._readColor(parser, sec, "red")) + self._setBaseColor("orange", self._readColor(parser, sec, "orange")) + self._setBaseColor("yellow", self._readColor(parser, sec, "yellow")) + self._setBaseColor("green", self._readColor(parser, sec, "green")) + self._setBaseColor("aqua", self._readColor(parser, sec, "aqua")) + self._setBaseColor("blue", self._readColor(parser, sec, "blue")) + self._setBaseColor("purple", self._readColor(parser, sec, "purple")) # Project sec = "Project" if parser.has_section(sec): - self.iconCache.setIconColor("root", self._parseColor(parser, sec, "root")) - self.iconCache.setIconColor("folder", self._parseColor(parser, sec, "folder")) - self.iconCache.setIconColor("file", self._parseColor(parser, sec, "file")) - self.iconCache.setIconColor("title", self._parseColor(parser, sec, "title")) - self.iconCache.setIconColor("chapter", self._parseColor(parser, sec, "chapter")) - self.iconCache.setIconColor("scene", self._parseColor(parser, sec, "scene")) - self.iconCache.setIconColor("note", self._parseColor(parser, sec, "note")) + self._setBaseColor("root", self._readColor(parser, sec, "root")) + self._setBaseColor("folder", self._readColor(parser, sec, "folder")) + self._setBaseColor("file", self._readColor(parser, sec, "file")) + self._setBaseColor("title", self._readColor(parser, sec, "title")) + self._setBaseColor("chapter", self._readColor(parser, sec, "chapter")) + self._setBaseColor("scene", self._readColor(parser, sec, "scene")) + self._setBaseColor("note", self._readColor(parser, sec, "note")) # Palette sec = "Palette" @@ -314,34 +353,34 @@ class GuiTheme: # GUI sec = "GUI" if parser.has_section(sec): - self.helpText = self._parseColor(parser, sec, "helptext") - self.fadedText = self._parseColor(parser, sec, "fadedtext") - self.errorText = self._parseColor(parser, sec, "errortext") + self.helpText = self._readColor(parser, sec, "helptext") + self.fadedText = self._readColor(parser, sec, "fadedtext") + self.errorText = self._readColor(parser, sec, "errortext") # Syntax sec = "Syntax" self.syntaxTheme = SyntaxColors() if parser.has_section(sec): - self.syntaxTheme.back = self._parseColor(parser, sec, "background") - self.syntaxTheme.text = self._parseColor(parser, sec, "text") - self.syntaxTheme.link = self._parseColor(parser, sec, "link") - self.syntaxTheme.head = self._parseColor(parser, sec, "headertext") - self.syntaxTheme.headH = self._parseColor(parser, sec, "headertag") - self.syntaxTheme.emph = self._parseColor(parser, sec, "emphasis") - self.syntaxTheme.dialN = self._parseColor(parser, sec, "dialog") - self.syntaxTheme.dialA = self._parseColor(parser, sec, "altdialog") - self.syntaxTheme.hidden = self._parseColor(parser, sec, "hidden") - self.syntaxTheme.note = self._parseColor(parser, sec, "note") - self.syntaxTheme.code = self._parseColor(parser, sec, "shortcode") - self.syntaxTheme.key = self._parseColor(parser, sec, "keyword") - self.syntaxTheme.tag = self._parseColor(parser, sec, "tag") - self.syntaxTheme.val = self._parseColor(parser, sec, "value") - self.syntaxTheme.opt = self._parseColor(parser, sec, "optional") - self.syntaxTheme.spell = self._parseColor(parser, sec, "spellcheckline") - self.syntaxTheme.error = self._parseColor(parser, sec, "errorline") - self.syntaxTheme.repTag = self._parseColor(parser, sec, "replacetag") - self.syntaxTheme.mod = self._parseColor(parser, sec, "modifier") - self.syntaxTheme.mark = self._parseColor(parser, sec, "texthighlight") + self.syntaxTheme.back = self._readColor(parser, sec, "background") + self.syntaxTheme.text = self._readColor(parser, sec, "text") + self.syntaxTheme.link = self._readColor(parser, sec, "link") + self.syntaxTheme.head = self._readColor(parser, sec, "headertext") + self.syntaxTheme.headH = self._readColor(parser, sec, "headertag") + self.syntaxTheme.emph = self._readColor(parser, sec, "emphasis") + self.syntaxTheme.dialN = self._readColor(parser, sec, "dialog") + self.syntaxTheme.dialA = self._readColor(parser, sec, "altdialog") + self.syntaxTheme.hidden = self._readColor(parser, sec, "hidden") + self.syntaxTheme.note = self._readColor(parser, sec, "note") + self.syntaxTheme.code = self._readColor(parser, sec, "shortcode") + self.syntaxTheme.key = self._readColor(parser, sec, "keyword") + self.syntaxTheme.tag = self._readColor(parser, sec, "tag") + self.syntaxTheme.val = self._readColor(parser, sec, "value") + self.syntaxTheme.opt = self._readColor(parser, sec, "optional") + self.syntaxTheme.spell = self._readColor(parser, sec, "spellcheckline") + self.syntaxTheme.error = self._readColor(parser, sec, "errorline") + self.syntaxTheme.repTag = self._readColor(parser, sec, "replacetag") + self.syntaxTheme.mod = self._readColor(parser, sec, "modifier") + self.syntaxTheme.mark = self._readColor(parser, sec, "texthighlight") # Update Dependant Colours # Based on: https://github.com/qt/qtbase/blob/dev/src/gui/kernel/qplatformtheme.cpp @@ -398,6 +437,18 @@ class GuiTheme: self._guiPalette.setBrush(QtColInactive, QPalette.ColorRole.Accent, highlight) self._guiPalette.setBrush(QtColDisabled, QPalette.ColorRole.Accent, grey) + # Set project override colours + if (override := CONFIG.iconColTree) != "theme": + color = self._svgColors.get(override, b"#000000") + self._svgColors["root"] = color + self._svgColors["folder"] = color + if not CONFIG.iconColDocs: + self._svgColors["file"] = color + self._svgColors["title"] = color + self._svgColors["chapter"] = color + self._svgColors["scene"] = color + self._svgColors["note"] = color + # Load icons after the theme is parsed self.iconCache.loadTheme(CONFIG.iconTheme) @@ -416,7 +467,7 @@ class GuiTheme: return self._themeList themes: list[T_ThemeEntry] = [] - parser = NWConfigParser() + parser = ConfigParser() for key, path in self._availThemes.items(): logger.debug("Checking theme config '%s'", key) if meta := _loadInternalName(parser, path): @@ -434,6 +485,12 @@ class GuiTheme: # Internal Functions ## + def _setBaseColor(self, key: str, color: QColor) -> None: + """Set the colour for a named colour.""" + self._qColors[key] = QColor(color) + self._svgColors[key] = color.name(QColor.NameFormat.HexRgb).encode("utf-8") + return + def _resetTheme(self) -> None: """Reset GUI colours to default values.""" palette = QPalette() @@ -460,37 +517,38 @@ class GuiTheme: self._guiPalette = palette - # Reset Icons - icons = self.iconCache - icons.clear() - icons.setIconColor("default", text) - icons.setIconColor("faded", faded) - icons.setIconColor("red", red) - icons.setIconColor("orange", orange) - icons.setIconColor("yellow", yellow) - icons.setIconColor("green", green) - icons.setIconColor("aqua", aqua) - icons.setIconColor("blue", blue) - icons.setIconColor("purple", purple) - icons.setIconColor("root", blue) - icons.setIconColor("folder", yellow) - icons.setIconColor("file", text) - icons.setIconColor("title", green) - icons.setIconColor("chapter", red) - icons.setIconColor("scene", blue) - icons.setIconColor("note", yellow) + # Reset Base Colours and Icons + self.iconCache.clear() + self._svgColors = {} + self._qColors = {} + self._setBaseColor("default", text) + self._setBaseColor("faded", faded) + self._setBaseColor("red", red) + self._setBaseColor("orange", orange) + self._setBaseColor("yellow", yellow) + self._setBaseColor("green", green) + self._setBaseColor("aqua", aqua) + self._setBaseColor("blue", blue) + self._setBaseColor("purple", purple) + self._setBaseColor("root", blue) + self._setBaseColor("folder", yellow) + self._setBaseColor("file", text) + self._setBaseColor("title", green) + self._setBaseColor("chapter", red) + self._setBaseColor("scene", blue) + self._setBaseColor("note", yellow) return - def _parseColor(self, parser: NWConfigParser, section: str, name: str) -> QColor: + def _readColor(self, parser: ConfigParser, section: str, name: str) -> QColor: """Parse a colour value from a config string.""" - return QColor(*parser.rdIntList(section, name, [0, 0, 0, 255])) + return self.parseColor(parser.get(section, name, fallback="default")) def _setPalette( - self, parser: NWConfigParser, section: str, name: str, value: QPalette.ColorRole + self, parser: ConfigParser, section: str, name: str, value: QPalette.ColorRole ) -> None: """Set a palette colour value from a config string.""" - self._guiPalette.setBrush(value, self._parseColor(parser, section, name)) + self._guiPalette.setBrush(value, self._readColor(parser, section, name)) return def _buildStyleSheets(self, palette: QPalette) -> None: @@ -536,9 +594,8 @@ class GuiIcons: """ __slots__ = ( - "_availThemes", "_headerDec", "_headerDecNarrow", "_noIcon", - "_qColors", "_qIcons", "_svgColors", "_svgData", "_themeList", - "mainTheme", "themeMeta", + "_availThemes", "_headerDec", "_headerDecNarrow", "_meta", "_noIcon", + "_qIcons", "_svgData", "_theme", "_themeList", ) TOGGLE_ICON_KEYS: Final[dict[str, tuple[str, str]]] = { @@ -552,13 +609,11 @@ class GuiIcons: def __init__(self, mainTheme: GuiTheme) -> None: - self.mainTheme = mainTheme - self.themeMeta = ThemeMeta() + self._theme = mainTheme + self._meta = ThemeMeta() # Storage self._svgData: dict[str, bytes] = {} - self._svgColors: dict[str, bytes] = {} - self._qColors: dict[str, QColor] = {} self._qIcons: dict[str, QIcon] = {} self._headerDec: list[QPixmap] = [] self._headerDecNarrow: list[QPixmap] = [] @@ -578,12 +633,10 @@ class GuiIcons: def clear(self) -> None: """Clear the icon cache.""" self._svgData = {} - self._svgColors = {} - self._qColors = {} self._qIcons = {} self._headerDec = [] self._headerDecNarrow = [] - self.themeMeta = ThemeMeta() + self._meta = ThemeMeta() return ## @@ -622,7 +675,7 @@ class GuiIcons: meta.author = value elif key == "meta:license": meta.license = value - self.themeMeta = meta + self._meta = meta except Exception: logger.error("Could not read file: %s", file) logException() @@ -631,38 +684,16 @@ class GuiIcons: CONFIG.splashMessage(f"Loaded icon theme: {meta.name}") CONFIG.splashMessage("Generating additional icons ...") - # Set colour overrides for project item icons - if (override := CONFIG.iconColTree) != "theme": - color = self._svgColors.get(override, b"#000000") - self._svgColors["root"] = color - self._svgColors["folder"] = color - if not CONFIG.iconColDocs: - self._svgColors["file"] = color - self._svgColors["title"] = color - self._svgColors["chapter"] = color - self._svgColors["scene"] = color - self._svgColors["note"] = color - # Populate generated icons cache self.getHeaderDecoration(0) self.getHeaderDecorationNarrow(0) return True - def setIconColor(self, key: str, color: QColor) -> None: - """Set an icon colour for a named colour.""" - self._qColors[key] = QColor(color) - self._svgColors[key] = color.name(QColor.NameFormat.HexRgb).encode("utf-8") - return - ## # Access Functions ## - def getIconColor(self, name: str) -> QColor: - """Return an icon color.""" - return QColor(self._qColors.get(name) or QtBlack) - def getIcon(self, name: str, color: str | None = None, w: int = 24, h: int = 24) -> QIcon: """Return an icon from the icon buffer, or load it.""" variant = f"{name}-{color}" if color else name @@ -733,7 +764,7 @@ class GuiIcons: map or the icon map. This function always returns a QPixmap. """ if name in self.IMAGE_MAP: - idx = int(self.mainTheme.isDarkTheme) + idx = int(self._theme.isDarkTheme) imgPath = CONFIG.assetPath("images") / self.IMAGE_MAP[name][idx] else: logger.error("Decoration with name '%s' does not exist", name) @@ -757,7 +788,7 @@ class GuiIcons: def getHeaderDecoration(self, hLevel: int) -> QPixmap: """Get the decoration for a specific heading level.""" if not self._headerDec: - iPx = self.mainTheme.baseIconHeight + iPx = self._theme.baseIconHeight self._headerDec = [ self._generateDecoration("file", iPx, 0), self._generateDecoration("title", iPx, 0), @@ -770,7 +801,7 @@ class GuiIcons: def getHeaderDecorationNarrow(self, hLevel: int) -> QPixmap: """Get the narrow decoration for a specific heading level.""" if not self._headerDecNarrow: - iPx = self.mainTheme.baseIconHeight + iPx = self._theme.baseIconHeight self._headerDecNarrow = [ self._generateDecoration("file", iPx, 0), self._generateDecoration("title", iPx, 0), @@ -811,7 +842,7 @@ class GuiIcons: return QIcon(str(CONFIG.assetPath("icons") / "x-novelwriter-project.svg")) if svg := self._svgData.get(name, b""): - if fill := self._svgColors.get(color or "default"): + if fill := self._theme.getRawBaseColor(color or "default"): svg = svg.replace(b"#000000", fill) pixmap = QPixmap(w, h) pixmap.fill(QtTransparent) @@ -833,7 +864,7 @@ class GuiIcons: painter = QPainter(pixmap) painter.setRenderHint(QtPaintAntiAlias) - if fill := self._svgColors.get(color or "default"): + if fill := self._theme.getRawBaseColor(color or "default"): painter.fillPath(path, QColor(fill.decode(encoding="utf-8"))) painter.end() @@ -859,13 +890,14 @@ def _sortTheme(data: tuple) -> str: return f"*{name}" if key.startswith("default_") else name -def _loadInternalName(parser: NWConfigParser, path: str | Path) -> tuple[str, bool]: +def _loadInternalName(parser: ConfigParser, path: str | Path) -> tuple[str, bool]: """Open a conf file and read the 'name' setting.""" try: + parser.clear() with open(path, mode="r", encoding="utf-8") as inFile: parser.read_file(inFile) - name = parser.rdStr("Main", "name", "") - dark = parser.rdStr("Main", "mode", "light").lower() == "dark" + name = parser.get("Main", "name", fallback="") + dark = parser.get("Main", "mode", fallback="light").lower() == "dark" return name, dark except Exception: logger.error("Could not read file: %s", path) diff --git a/tests/reference/baseConfig_novelwriter.conf b/tests/reference/baseConfig_novelwriter.conf index 78441636..8943a9b2 100644 --- a/tests/reference/baseConfig_novelwriter.conf +++ b/tests/reference/baseConfig_novelwriter.conf @@ -1,10 +1,11 @@ [Meta] -timestamp = 2025-05-11 13:28:11 +timestamp = 2025-06-02 16:21:38 [Main] font = -theme = default -syntax = default_light +lighttheme = default_light +darktheme = default_dark +thememode = AUTO icons = material_rounded_normal iconcoltree = theme iconcoldocs = False diff --git a/tests/test_base/test_base_config.py b/tests/test_base/test_base_config.py index 81b03831..98a1063d 100644 --- a/tests/test_base/test_base_config.py +++ b/tests/test_base/test_base_config.py @@ -131,15 +131,15 @@ def testBaseConfig_InitLoadSave(monkeypatch, fncPath, tstPaths): assert tstConf.errorText().startswith("Could not load config file") # Change a few settings, save, reset, and reload - tstConf.guiTheme = "foo" - tstConf.guiSyntax = "bar" + tstConf.lightTheme = "foo" + tstConf.darkTheme = "bar" assert tstConf.saveConfig() is True newConf = Config() newConf.initConfig(confPath=fncPath, dataPath=fncPath) newConf.loadConfig() - assert newConf.guiTheme == "foo" - assert newConf.guiSyntax == "bar" + assert newConf.lightTheme == "foo" + assert newConf.darkTheme == "bar" # Test Correcting Quote Settings tstConf.fmtDQuoteOpen = '"' diff --git a/tests/test_dialogs/test_dlg_preferences.py b/tests/test_dialogs/test_dlg_preferences.py index 5572f430..ccb77133 100644 --- a/tests/test_dialogs/test_dlg_preferences.py +++ b/tests/test_dialogs/test_dlg_preferences.py @@ -27,7 +27,7 @@ from PyQt6.QtGui import QAction, QFont, QFontDatabase, QKeyEvent from PyQt6.QtWidgets import QFileDialog, QFontDialog from novelwriter import CONFIG, SHARED -from novelwriter.config import DEF_GUI +from novelwriter.config import DEF_GUI_DARK, DEF_GUI_LIGHT from novelwriter.constants import nwUnicode from novelwriter.dialogs.preferences import GuiPreferences from novelwriter.dialogs.quotes import GuiQuoteSelect @@ -55,15 +55,11 @@ def testDlgPreferences_Main(qtbot, monkeypatch, nwGUI, tstPaths): assert "en_GB" in languages # Check GUI Themes - themes = [prefs.guiTheme.itemData(i) for i in range(prefs.guiTheme.count())] - assert len(themes) >= 5 - assert DEF_GUI in themes + themes = [prefs.lightTheme.itemData(i) for i in range(prefs.lightTheme.count())] + assert DEF_GUI_LIGHT in themes - # Check GUI Syntax - syntax = [prefs.guiSyntax.itemData(i) for i in range(prefs.guiSyntax.count())] - assert len(syntax) >= 10 - assert "default_dark" in syntax - assert "default_light" in syntax + themes = [prefs.darkTheme.itemData(i) for i in range(prefs.darkTheme.count())] + assert DEF_GUI_DARK in themes # Check Spell Checking spelling = [prefs.spellLanguage.itemData(i) for i in range(prefs.spellLanguage.count())] @@ -124,7 +120,7 @@ def testDlgPreferences_Actions(qtbot, monkeypatch, nwGUI): button = prefs.buttonBox.button(QtDialogSave) assert button is not None button.click() - assert signal.args == [False, False, False, False] + assert len(signal.args) == 4 # Check Close Button prefs.show() @@ -151,6 +147,12 @@ def testDlgPreferences_Settings(qtbot, monkeypatch, nwGUI, fncPath, tstPaths): (fncPath / "nw_en_US.qm").touch() (fncPath / "project_en_US.json").touch() CONFIG._nwLangPath = fncPath + SHARED.theme._themeList = [ + ("theme1", "Theme 1", False), + ("theme2", "Theme 2", False), + ("theme3", "Theme 3", True), + ("theme4", "Theme 4", True), + ] prefs = GuiPreferences(nwGUI) with qtbot.waitExposed(prefs): @@ -158,7 +160,8 @@ def testDlgPreferences_Settings(qtbot, monkeypatch, nwGUI, fncPath, tstPaths): # Appearance prefs.guiLocale.setCurrentIndex(prefs.guiLocale.findData("en_US")) - prefs.guiTheme.setCurrentIndex(prefs.guiTheme.findData("default_dark")) + prefs.lightTheme.setCurrentIndex(prefs.lightTheme.findData("theme1")) + prefs.darkTheme.setCurrentIndex(prefs.darkTheme.findData("theme3")) with monkeypatch.context() as mp: mp.setattr(QFontDialog, "getFont", lambda *a, **k: (QFont(), True)) prefs.nativeFont.setChecked(True) # Use OS font dialog @@ -169,14 +172,14 @@ def testDlgPreferences_Settings(qtbot, monkeypatch, nwGUI, fncPath, tstPaths): prefs.useCharCount.setChecked(True) assert CONFIG.guiLocale != "en_US" - assert CONFIG.guiTheme != "default_dark" + assert CONFIG.lightTheme == "default_light" + assert CONFIG.darkTheme == "default_dark" assert CONFIG.guiFont.family() != "" assert CONFIG.hideVScroll is False assert CONFIG.hideHScroll is False assert CONFIG.useCharCount is False # Document Style - prefs.guiSyntax.setCurrentIndex(prefs.guiSyntax.findData("default_dark")) with monkeypatch.context() as mp: mp.setattr(QFontDialog, "getFont", lambda *a, **k: (QFont(), True)) prefs.nativeFont.setChecked(False) # Use Qt font dialog @@ -185,7 +188,6 @@ def testDlgPreferences_Settings(qtbot, monkeypatch, nwGUI, fncPath, tstPaths): prefs.showFullPath.setChecked(False) prefs.incNotesWCount.setChecked(False) - assert CONFIG.guiSyntax != "default_dark" assert CONFIG.textFont.family() != "" assert CONFIG.showFullPath is True assert CONFIG.incNotesWCount is True @@ -344,14 +346,14 @@ def testDlgPreferences_Settings(qtbot, monkeypatch, nwGUI, fncPath, tstPaths): # Appearance assert CONFIG.guiLocale == "en_US" - assert CONFIG.guiTheme == "default_dark" + assert CONFIG.lightTheme == "theme1" + assert CONFIG.darkTheme == "theme3" assert CONFIG.guiFont == QFont() assert CONFIG.hideVScroll is True assert CONFIG.hideHScroll is True assert CONFIG.useCharCount is True # Document Style - assert CONFIG.guiSyntax == "default_dark" assert CONFIG.textFont == QFont() assert CONFIG.showFullPath is False assert CONFIG.incNotesWCount is False diff --git a/tests/test_gui/test_gui_guimain.py b/tests/test_gui/test_gui_guimain.py index 6fda9b6a..91207d09 100644 --- a/tests/test_gui/test_gui_guimain.py +++ b/tests/test_gui/test_gui_guimain.py @@ -34,7 +34,7 @@ from PyQt6.QtWidgets import QInputDialog, QMessageBox from novelwriter import CONFIG, SHARED from novelwriter.constants import nwFiles from novelwriter.dialogs.editlabel import GuiEditLabel -from novelwriter.enum import nwDocAction, nwDocMode, nwFocus, nwItemType, nwView +from novelwriter.enum import nwDocAction, nwDocMode, nwFocus, nwItemType, nwTheme, nwView from novelwriter.gui.doceditor import GuiDocEditor from novelwriter.gui.noveltree import GuiNovelView from novelwriter.gui.outline import GuiOutlineView @@ -180,10 +180,11 @@ def testGuiMain_ProjectTreeItems(qtbot, monkeypatch, nwGUI, projPath, mockRnd): def testGuiMain_UpdateTheme(qtbot, nwGUI): """Test updating the theme in the GUI.""" mainTheme = SHARED.theme - CONFIG.guiTheme = "default_dark" - CONFIG.guiSyntax = "default_dark" + CONFIG.themeMode = nwTheme.DARK + CONFIG.darkTheme = "default_dark" + CONFIG.lightTheme = "default_light" mainTheme.loadTheme() - mainTheme.loadSyntax() + nwGUI._processConfigChanges(False, True, False, False) nwGUI._processConfigChanges(True, True, True, True) diff --git a/tests/test_gui/test_gui_theme.py b/tests/test_gui/test_gui_theme.py index c64f1172..ff4308f2 100644 --- a/tests/test_gui/test_gui_theme.py +++ b/tests/test_gui/test_gui_theme.py @@ -22,6 +22,7 @@ from __future__ import annotations import sys +from configparser import ConfigParser from pathlib import Path import pytest @@ -29,8 +30,7 @@ import pytest from PyQt6.QtGui import QColor, QIcon, QPalette, QPixmap from novelwriter import CONFIG, SHARED -from novelwriter.common import NWConfigParser -from novelwriter.config import DEF_GUI +from novelwriter.config import DEF_GUI_LIGHT from novelwriter.constants import nwLabels from novelwriter.enum import nwItemClass, nwItemLayout, nwItemType from novelwriter.gui.theme import _listConf @@ -39,17 +39,51 @@ from tests.mocked import causeOSError from tests.tools import writeFile +@pytest.mark.gui +def testGuiTheme_ParseColor(qtbot, nwGUI): + """Test the colour parsing.""" + theme = SHARED.theme + + # Pre-Populate + theme._qColors["red"] = QColor(255, 0, 0) + theme._qColors["green"] = QColor(0, 255, 0) + theme._qColors["blue"] = QColor(0, 0, 255) + + # By Name + assert theme.parseColor("red").getRgb() == (255, 0, 0, 255) + assert theme.parseColor("green").getRgb() == (0, 255, 0, 255) + assert theme.parseColor("blue").getRgb() == (0, 0, 255, 255) + assert theme.parseColor("bob").getRgb() == (0, 0, 0, 255) + + # CSS Format + assert theme.parseColor("#ff0000").getRgb() == (255, 0, 0, 255) + assert theme.parseColor("#ff00007f").getRgb() == (255, 0, 0, 127) + assert theme.parseColor("#ff00").getRgb() == (0, 0, 0, 255) # Too short -> ignored + assert theme.parseColor("#ff00007f15").getRgb() == (255, 0, 0, 127) # Too long -> truncated + + # Name + Alpha + assert theme.parseColor("red, 255").getRgb() == (255, 0, 0, 255) + assert theme.parseColor("red, 127").getRgb() == (255, 0, 0, 127) + assert theme.parseColor("red, 512").getRgb() == (255, 0, 0, 255) # Value truncated + + # Values + assert theme.parseColor("255, 0, 0").getRgb() == (255, 0, 0, 255) + assert theme.parseColor("255, 0, 0, 255").getRgb() == (255, 0, 0, 255) + assert theme.parseColor("255, 0, 0, 127").getRgb() == (255, 0, 0, 127) + assert theme.parseColor("255, 0, 0, 127, 42").getRgb() == (255, 0, 0, 127) # Truncated + + @pytest.mark.gui def testGuiTheme_Main(qtbot, nwGUI, tstPaths): """Test the theme class init.""" - mainTheme = SHARED.theme + theme = SHARED.theme # Methods # ======= - mSize = mainTheme.getTextWidth("m") + mSize = theme.getTextWidth("m") assert mSize > 0 - assert mainTheme.getTextWidth("m", mainTheme.guiFont) == mSize + assert theme.getTextWidth("m", theme.guiFont) == mSize # Scan for Themes # =============== @@ -70,7 +104,7 @@ def testGuiTheme_Main(qtbot, nwGUI, tstPaths): # Parse Colours # ============= - parser = NWConfigParser() + parser = ConfigParser() parser["Palette"] = { "colour1": "100, 150, 200", # Valid "colour2": "100, 150, 200, 250", # With alpha @@ -81,38 +115,39 @@ def testGuiTheme_Main(qtbot, nwGUI, tstPaths): } # Test the parser for several valid and invalid values - assert mainTheme._parseColor(parser, "Palette", "colour1").getRgb() == (100, 150, 200, 255) - assert mainTheme._parseColor(parser, "Palette", "colour2").getRgb() == (100, 150, 200, 250) - assert mainTheme._parseColor(parser, "Palette", "colour3").getRgb() == (100, 150, 200, 250) - assert mainTheme._parseColor(parser, "Palette", "colour4").getRgb() == (250, 250, 0, 255) - assert mainTheme._parseColor(parser, "Palette", "colour5").getRgb() == (0, 0, 0, 0) - assert mainTheme._parseColor(parser, "Palette", "colour6").getRgb() == (0, 127, 255, 255) + assert theme._readColor(parser, "Palette", "colour1").getRgb() == (100, 150, 200, 255) + assert theme._readColor(parser, "Palette", "colour2").getRgb() == (100, 150, 200, 250) + assert theme._readColor(parser, "Palette", "colour3").getRgb() == (100, 150, 200, 250) + assert theme._readColor(parser, "Palette", "colour4").getRgb() == (0, 0, 0, 250) + assert theme._readColor(parser, "Palette", "colour5").getRgb() == (0, 0, 0, 0) + assert theme._readColor(parser, "Palette", "colour6").getRgb() == (0, 127, 255, 255) # The palette should load with the parsed values - mainTheme._setPalette(parser, "Palette", "colour1", QPalette.ColorRole.Window) - assert mainTheme._guiPalette.color(QPalette.ColorRole.Window).getRgb() == (100, 150, 200, 255) - mainTheme._setPalette(parser, "Palette", "colour2", QPalette.ColorRole.Window) - assert mainTheme._guiPalette.color(QPalette.ColorRole.Window).getRgb() == (100, 150, 200, 250) - mainTheme._setPalette(parser, "Palette", "colour3", QPalette.ColorRole.Window) - assert mainTheme._guiPalette.color(QPalette.ColorRole.Window).getRgb() == (100, 150, 200, 250) - mainTheme._setPalette(parser, "Palette", "colour4", QPalette.ColorRole.Window) - assert mainTheme._guiPalette.color(QPalette.ColorRole.Window).getRgb() == (250, 250, 0, 255) - mainTheme._setPalette(parser, "Palette", "colour5", QPalette.ColorRole.Window) - assert mainTheme._guiPalette.color(QPalette.ColorRole.Window).getRgb() == (0, 0, 0, 0) - mainTheme._setPalette(parser, "Palette", "colour6", QPalette.ColorRole.Window) - assert mainTheme._guiPalette.color(QPalette.ColorRole.Window).getRgb() == (0, 127, 255, 255) + theme._setPalette(parser, "Palette", "colour1", QPalette.ColorRole.Window) + assert theme._guiPalette.color(QPalette.ColorRole.Window).getRgb() == (100, 150, 200, 255) + theme._setPalette(parser, "Palette", "colour2", QPalette.ColorRole.Window) + assert theme._guiPalette.color(QPalette.ColorRole.Window).getRgb() == (100, 150, 200, 250) + theme._setPalette(parser, "Palette", "colour3", QPalette.ColorRole.Window) + assert theme._guiPalette.color(QPalette.ColorRole.Window).getRgb() == (100, 150, 200, 250) + theme._setPalette(parser, "Palette", "colour4", QPalette.ColorRole.Window) + assert theme._guiPalette.color(QPalette.ColorRole.Window).getRgb() == (0, 0, 0, 250) + theme._setPalette(parser, "Palette", "colour5", QPalette.ColorRole.Window) + assert theme._guiPalette.color(QPalette.ColorRole.Window).getRgb() == (0, 0, 0, 0) + theme._setPalette(parser, "Palette", "colour6", QPalette.ColorRole.Window) + assert theme._guiPalette.color(QPalette.ColorRole.Window).getRgb() == (0, 127, 255, 255) # Non-existing value should return default colour - mainTheme._setPalette(parser, "Palette", "stuff", QPalette.ColorRole.Window) - assert mainTheme._guiPalette.color(QPalette.ColorRole.Window).getRgb() == (0, 0, 0, 255) + theme._setPalette(parser, "Palette", "stuff", QPalette.ColorRole.Window) + assert theme._guiPalette.color(QPalette.ColorRole.Window).getRgb() == (0, 0, 0, 255) # qtbot.stop() @pytest.mark.gui +@pytest.mark.skip def testGuiTheme_Theme(qtbot, monkeypatch, nwGUI, tstPaths): """Test the theme part of the class.""" - mainTheme = SHARED.theme + theme = SHARED.theme # List Themes # =========== @@ -120,45 +155,46 @@ def testGuiTheme_Theme(qtbot, monkeypatch, nwGUI, tstPaths): # Block the reading of the files with monkeypatch.context() as mp: mp.setattr("builtins.open", causeOSError) - assert mainTheme.listThemes() == [] + theme._themeList = [] + assert theme.listThemes() == [] # Load the theme info, default themes first - themesList = mainTheme.listThemes() + themesList = theme.listThemes() assert themesList[0] == ("default_dark", "Default Dark Theme") assert themesList[1] == ("default_light", "Default Light Theme") assert themesList[2] == ("cyberpunk_night", "Cyberpunk Night") assert themesList[3] == ("dracula", "Dracula") # A second call should returned the cached list - assert mainTheme.listThemes() == mainTheme._themeList + assert theme.listThemes() == theme._themeList # Check handling of broken theme settings CONFIG.guiTheme = "not_a_theme" - availThemes = mainTheme._availThemes - mainTheme._availThemes = {} - assert mainTheme.loadTheme() is False - mainTheme._availThemes = availThemes + availThemes = theme._availThemes + theme._availThemes = {} + assert theme.loadTheme() is False + theme._availThemes = availThemes # Check handling of unreadable file - CONFIG.guiTheme = DEF_GUI + CONFIG.guiTheme = DEF_GUI_LIGHT with monkeypatch.context() as mp: mp.setattr("builtins.open", causeOSError) - assert mainTheme.loadTheme() is False + assert theme.loadTheme() is False # Load Default Theme # ================== if sys.platform != "win32": # Set a mock colour for the window background - mainTheme._guiPalette.color(QPalette.ColorRole.Window).setRgb(0, 0, 0, 0) + theme._guiPalette.color(QPalette.ColorRole.Window).setRgb(0, 0, 0, 0) # Load the default theme - CONFIG.guiTheme = DEF_GUI - assert mainTheme.loadTheme() is True + CONFIG.guiTheme = DEF_GUI_LIGHT + assert theme.loadTheme() is True # This should load a standard palette wCol = QPalette().color(QPalette.ColorRole.Window).getRgb() - assert mainTheme._guiPalette.color(QPalette.ColorRole.Window).getRgb() == wCol + assert theme._guiPalette.color(QPalette.ColorRole.Window).getRgb() == wCol # Mock Dark Theme # =============== @@ -172,32 +208,32 @@ def testGuiTheme_Theme(qtbot, monkeypatch, nwGUI, tstPaths): "window = 0, 0, 0\n" "text = 255, 255, 255\n" ) - mainTheme._availThemes["test"] = mockTheme + theme._availThemes["test"] = mockTheme CONFIG.guiTheme = "test" - assert mainTheme.loadTheme() is True - assert mainTheme._guiPalette.window().color().getRgb() == (0, 0, 0, 255) - assert mainTheme._guiPalette.text().color().getRgb() == (255, 255, 255, 255) - assert mainTheme._guiPalette.light().color().getRgb() == (57, 57, 57, 255) - assert mainTheme.isDarkTheme is True + assert theme.loadTheme() is True + assert theme._guiPalette.window().color().getRgb() == (0, 0, 0, 255) + assert theme._guiPalette.text().color().getRgb() == (255, 255, 255, 255) + assert theme._guiPalette.light().color().getRgb() == (57, 57, 57, 255) + assert theme.isDarkTheme is True # Load Default Light Theme # ======================== CONFIG.guiTheme = "default_light" - assert mainTheme.loadTheme() is True + assert theme.loadTheme() is True # Check a few values - assert mainTheme._guiPalette.color( + assert theme._guiPalette.color( QPalette.ColorRole.Window ).getRgb() == (239, 239, 239, 255) - assert mainTheme._guiPalette.color( + assert theme._guiPalette.color( QPalette.ColorRole.WindowText ).getRgb() == (0, 0, 0, 255) - assert mainTheme._guiPalette.color( + assert theme._guiPalette.color( QPalette.ColorRole.Base ).getRgb() == (255, 255, 255, 255) - assert mainTheme._guiPalette.color( + assert theme._guiPalette.color( QPalette.ColorRole.AlternateBase ).getRgb() == (224, 224, 224, 255) @@ -205,21 +241,22 @@ def testGuiTheme_Theme(qtbot, monkeypatch, nwGUI, tstPaths): # ======================= CONFIG.guiTheme = "default_dark" - assert mainTheme.loadTheme() is True + assert theme.loadTheme() is True # Check a few values - assert mainTheme._guiPalette.color( + assert theme._guiPalette.color( QPalette.ColorRole.Window).getRgb() == (54, 54, 54, 255) - assert mainTheme._guiPalette.color( + assert theme._guiPalette.color( QPalette.ColorRole.WindowText).getRgb() == (204, 204, 204, 255) - assert mainTheme._guiPalette.color( + assert theme._guiPalette.color( QPalette.ColorRole.Base).getRgb() == (62, 62, 62, 255) - assert mainTheme._guiPalette.color( + assert theme._guiPalette.color( QPalette.ColorRole.AlternateBase).getRgb() == (78, 78, 78, 255) # qtbot.stop() +@pytest.mark.skip @pytest.mark.gui def testGuiTheme_Syntax(qtbot, monkeypatch, nwGUI): """Test the syntax part of the class.""" @@ -283,6 +320,7 @@ def testGuiTheme_Syntax(qtbot, monkeypatch, nwGUI): # qtbot.stop() +@pytest.mark.skip @pytest.mark.gui def testGuiTheme_IconThemes(qtbot, caplog, monkeypatch, nwGUI, tstPaths): """Test the icon cache class.""" From 04526385d1ae7757aeeec52c3ca5cc059995c571 Mon Sep 17 00:00:00 2001 From: Veronica Berglyd Olsen <1619840+vkbo@users.noreply.github.com> Date: Mon, 2 Jun 2025 17:43:27 +0200 Subject: [PATCH 03/20] Update existing matched GUI and syntax themes --- .../assets/syntax/cyberpunk_night.conf | 28 ----- novelwriter/assets/syntax/dracula.conf | 44 ------- novelwriter/assets/syntax/snazzy.conf | 42 ------- novelwriter/assets/syntax/solarized_dark.conf | 29 ----- .../assets/syntax/solarized_light.conf | 29 ----- .../assets/themes/cyberpunk_night.conf | 91 +++++++++------ novelwriter/assets/themes/dracula.conf | 94 +++++++++------ novelwriter/assets/themes/snazzy.conf | 104 +++++++++++------ novelwriter/assets/themes/solarized_dark.conf | 110 ++++++++++++------ .../assets/themes/solarized_light.conf | 110 ++++++++++++------ 10 files changed, 338 insertions(+), 343 deletions(-) delete mode 100644 novelwriter/assets/syntax/cyberpunk_night.conf delete mode 100644 novelwriter/assets/syntax/dracula.conf delete mode 100644 novelwriter/assets/syntax/snazzy.conf delete mode 100644 novelwriter/assets/syntax/solarized_dark.conf delete mode 100644 novelwriter/assets/syntax/solarized_light.conf diff --git a/novelwriter/assets/syntax/cyberpunk_night.conf b/novelwriter/assets/syntax/cyberpunk_night.conf deleted file mode 100644 index 57a14536..00000000 --- a/novelwriter/assets/syntax/cyberpunk_night.conf +++ /dev/null @@ -1,28 +0,0 @@ -[Main] -name = Cyberpunk Night -author = Anders Lemvigh -url = https://github.com/alemvigh -license = CC BY-SA 4.0 -licenseurl = https://creativecommons.org/licenses/by-sa/4.0/ - -[Syntax] -background = 0, 0, 0 -text = 150, 150, 150 -link = 77, 77, 255 -headertext = 255, 255, 255 -headertag = 50, 0, 180 -emphasis = 0, 255, 255 -dialog = 0, 255, 0 -altdialog = 0, 140, 255 -note = 150, 150, 150 -hidden = 77, 77, 100 -shortcode = 255, 255, 0 -keyword = 255, 100, 255 -tag = 255, 150, 10 -value = 255, 150, 10 -spellcheckline = 242, 72, 23 -errorline = 186, 218, 4 -replacetag = 0, 0, 180 -modifier = 144, 142, 176 -optional = 180, 180, 180 -texthighlight = 255, 255, 132, 96 diff --git a/novelwriter/assets/syntax/dracula.conf b/novelwriter/assets/syntax/dracula.conf deleted file mode 100644 index fad01ea8..00000000 --- a/novelwriter/assets/syntax/dracula.conf +++ /dev/null @@ -1,44 +0,0 @@ -[Main] -name = Dracula -author = Veronica Berglyd Olsen (adaptation) -credit = Zeno Rocha -url = https://draculatheme.com -license = MIT -licenseurl = https://github.com/dracula/dracula-theme/blob/main/LICENSE - -## -# Colours: -# Background = 282a36 : 40, 42, 54 -# Foreground = f8f8f2 : 248, 248, 242 -# Comment = 6272a4 : 98, 114, 164 -# Cyan = 8be9fd : 139, 233, 253 -# Green = 50fa7b : 80, 250, 123 -# Orange = ffb86c : 255, 184, 108 -# Pink = ff79c6 : 255, 121, 198 -# Purple = bd93f9 : 189, 147, 249 -# Red = ff5555 : 255, 85, 85 -# Yellow = f1fa8c : 241, 250, 140 -## - -[Syntax] -# See: https://spec.draculatheme.com/ -background = 40, 42, 54 -text = 248, 248, 242 -link = 255, 121, 198 -headertext = 189, 147, 249 -headertag = 189, 147, 249, 160 -emphasis = 255, 184, 108 -dialog = 80, 250, 123 -altdialog = 241, 250, 140 -note = 255, 204, 233 -hidden = 98, 114, 164 -shortcode = 139, 233, 253 -keyword = 255, 121, 198 -tag = 255, 184, 108 -value = 255, 184, 108 -optional = 80, 250, 123 -spellcheckline = 255, 85, 85 -errorline = 80, 250, 123 -replacetag = 241, 250, 140 -modifier = 139, 233, 253 -texthighlight = 241, 250, 140, 96 diff --git a/novelwriter/assets/syntax/snazzy.conf b/novelwriter/assets/syntax/snazzy.conf deleted file mode 100644 index d948b770..00000000 --- a/novelwriter/assets/syntax/snazzy.conf +++ /dev/null @@ -1,42 +0,0 @@ -[Main] -name = Snazzy Light -author = Veronica Berglyd Olsen (adaptation) -credit = Florian Reuschel (color theme) -url = https://github.com/loilo/vscode-snazzy-light -license = MIT License -licenseurl = https://github.com/loilo/vscode-snazzy-light/blob/master/LICENSE - -## -# Colours: -# Background = fafbfc : 250, 251, 252 -# Foreground = 565869 : 86, 88, 105 -# Comment = 9194a2 : 145, 148, 162 -# Yellow = cf9c00 : 207, 156, 0 -# Red = ff5c57 : 255, 92, 87 -# Pink = f767bb : 247, 103, 187 -# Blue = 09a1ed : 9, 161, 237 -# Cyan = 13bbb7 : 19, 187, 183 -# Green = 2dae58 : 45, 174, 88 -## - -[Syntax] -background = 250, 251, 252 -text = 86, 88, 105 -link = 9, 161, 237 -headertext = 45, 174, 88 -headertag = 45, 174, 88, 160 -emphasis = 247, 103, 187 -dialog = 9, 161, 237 -altdialog = 207, 156, 0 -note = 120, 187, 185 -hidden = 145, 148, 162 -shortcode = 247, 103, 187 -keyword = 9, 161, 237 -tag = 45, 174, 88 -value = 207, 156, 0 -optional = 207, 156, 0 -spellcheckline = 255, 92, 87 -errorline = 45, 174, 88 -replacetag = 19, 187, 183 -modifier = 247, 103, 187 -texthighlight = 207, 156, 0, 96 diff --git a/novelwriter/assets/syntax/solarized_dark.conf b/novelwriter/assets/syntax/solarized_dark.conf deleted file mode 100644 index 0fbacdb7..00000000 --- a/novelwriter/assets/syntax/solarized_dark.conf +++ /dev/null @@ -1,29 +0,0 @@ -[Main] -name = Solarized Dark -author = nullbasis -credit = Ethan Schoonover -url = https://ethanschoonover.com/solarized/ -license = MIT -licenseurl = https://github.com/altercation/solarized/blob/master/LICENSE - -[Syntax] -background = 7, 54, 66 -text = 253, 246, 227 -link = 38, 139, 210 -headertext = 147, 161, 161 -headertag = 42, 161, 152 -emphasis = 38, 139, 210 -dialog = 42, 161, 152 -altdialog = 42, 161, 152 -note = 101, 161, 156 -hidden = 147, 161, 161 -shortcode = 147, 161, 161 -keyword = 133, 153, 0 -tag = 203, 75, 22 -value = 203, 75, 22 -optional = 147, 161, 161 -spellcheckline = 203, 75, 22 -errorline = 220, 50, 47 -replacetag = 133, 153, 0 -modifier = 181, 137, 0 -texthighlight = 181, 137, 0, 96 diff --git a/novelwriter/assets/syntax/solarized_light.conf b/novelwriter/assets/syntax/solarized_light.conf deleted file mode 100644 index 525a59e5..00000000 --- a/novelwriter/assets/syntax/solarized_light.conf +++ /dev/null @@ -1,29 +0,0 @@ -[Main] -name = Solarized Light -author = nullbasis -credit = Ethan Schoonover -url = https://ethanschoonover.com/solarized/ -license = MIT -licenseurl = https://github.com/altercation/solarized/blob/master/LICENSE - -[Syntax] -background = 253, 246, 227 -text = 0, 43, 54 -link = 38, 139, 210 -headertext = 88, 110, 117 -headertag = 42, 161, 152 -emphasis = 38, 139, 210 -dialog = 42, 161, 152 -altdialog = 42, 161, 152 -note = 27, 102, 96 -hidden = 88, 110, 117 -shortcode = 88, 110, 117 -keyword = 133, 153, 0 -tag = 203, 75, 22 -value = 203, 75, 22 -optional = 88, 110, 117 -spellcheckline = 203, 75, 22 -errorline = 220, 50, 47 -replacetag = 133, 153, 0 -modifier = 181, 137, 0 -texthighlight = 181, 137, 0, 96 diff --git a/novelwriter/assets/themes/cyberpunk_night.conf b/novelwriter/assets/themes/cyberpunk_night.conf index 125cab45..1ee10ca8 100644 --- a/novelwriter/assets/themes/cyberpunk_night.conf +++ b/novelwriter/assets/themes/cyberpunk_night.conf @@ -1,48 +1,71 @@ [Main] name = Cyberpunk Night +mode = dark description = A taste of the future 80s author = Anders Lemvigh url = https://github.com/alemvigh license = CC BY-SA 4.0 licenseurl = https://creativecommons.org/licenses/by-sa/4.0/ -[Icons] -default = 136, 136, 136 -faded = 97, 97, 97 -red = 242, 72, 23 -orange = 255, 150, 10 -yellow = 255, 255, 0 -green = 0, 255, 0 -aqua = 0, 255, 255 -blue = 77, 77, 255 -purple = 50, 0, 180 +[Base] +default = #888888 +faded = #616161 +red = #f24817 +orange = #ff960a +yellow = #ffff00 +green = #00ff00 +aqua = #00ffff +blue = #4d4dff +purple = #320064 [Project] -root = 77, 77, 255 -folder = 255, 255, 0 -file = 136, 136, 136 -title = 0, 255, 0 -chapter = 242, 72, 23 -scene = 77, 77, 255 -note = 255, 255, 0 +root = #4d4dff +folder = #ffff00 +file = #888888 +title = #00ff00 +chapter = #f24817 +scene = #4d4dff +note = #ffff00 [Palette] -window = 0, 0, 0 -windowtext = 150, 150, 150 -base = 0, 0, 0 -alternatebase = 40, 40, 40 -text = 150, 150, 150 -tooltipbase = 40, 20, 70 -tooltiptext = 255, 255, 255 -button = 5, 0, 10 -buttontext = 150, 150, 150 -brighttext = 255, 255, 255 -highlight = 50, 30, 80 -highlightedtext = 255, 255, 255 -link = 77, 77, 255 -linkvisited = 50, 0, 80 +window = #000000 +windowtext = #969696 +base = #000000 +alternatebase = #282828 +text = #969696 +tooltipbase = #281446 +tooltiptext = #ffffff +button = #05000a +buttontext = #969696 +brighttext = #ffffff +highlight = #321e50 +highlightedtext = #ffffff +link = #4d4dff +linkvisited = #320050 [GUI] -helptext = 97, 97, 97 -fadedtext = 97, 97, 97 -errortext = 242, 72, 23 +helptext = #616161 +fadedtext = #616161 +errortext = #f24817 + +[Syntax] +background = #000000 +text = #969696 +link = #4d4dff +headertext = #ffffff +headertag = #320064 +emphasis = #00ffff +dialog = #00ff00 +altdialog = #008cff +note = #969696 +hidden = #4d4d64 +shortcode = #ffff00 +keyword = #ff64ff +tag = #ff960a +value = #ff960a +spellcheckline = #f24817 +errorline = #bada04 +replacetag = #0000b4 +modifier = #908eb0 +optional = #b4b4b4 +texthighlight = #ffff8460 diff --git a/novelwriter/assets/themes/dracula.conf b/novelwriter/assets/themes/dracula.conf index 5805b84b..49f30501 100644 --- a/novelwriter/assets/themes/dracula.conf +++ b/novelwriter/assets/themes/dracula.conf @@ -1,5 +1,6 @@ [Main] name = Dracula +mode = dark description = A dark theme with bright colours author = Veronica Berglyd Olsen (adaptation) credit = Zeno Rocha @@ -9,9 +10,10 @@ licenseurl = https://github.com/dracula/dracula-theme/blob/main/LICENSE ## # Colours: +# See: https://spec.draculatheme.com/ # Background = 282a36 : 40, 42, 54 # Foreground = f8f8f2 : 248, 248, 242 -# Current Line = 44475A : 68, 71, 90 +# Current Line = 44475a : 68, 71, 90 # Comment = 6272a4 : 98, 114, 164 # Cyan = 8be9fd : 139, 233, 253 # Green = 50fa7b : 80, 250, 123 @@ -22,43 +24,65 @@ licenseurl = https://github.com/dracula/dracula-theme/blob/main/LICENSE # Yellow = f1fa8c : 241, 250, 140 ## -[Icons] -default = 230, 230, 224 -faded = 98, 114, 164 -red = 255, 85, 85 -orange = 255, 184, 108 -yellow = 241, 250, 140 -green = 80, 250, 123 -aqua = 139, 233, 253 -blue = 147, 207, 249 -purple = 189, 147, 249 +[Base] +default = #e6e6e0 +faded = #6272a4 +red = #ff5555 +orange = #ffb86c +yellow = #f1fa8c +green = #50fa7b +aqua = #8be9fd +blue = #93cff9 +purple = #bd93f9 [Project] -root = 189, 147, 249 -folder = 241, 250, 140 -file = 230, 230, 224 -title = 80, 250, 123 -chapter = 255, 85, 85 -scene = 139, 233, 253 -note = 241, 250, 140 +root = #bd93f9 +folder = #f1fa8c +file = #e6e6e0 +title = #50fa7b +chapter = #ff5555 +scene = #8be9fd +note = #f1fa8c [Palette] -window = 68, 71, 90 -windowtext = 248, 248, 242 -base = 40, 42, 54 -alternatebase = 51, 54, 69 -text = 248, 248, 242 -tooltipbase = 241, 250, 140 -tooltiptext = 40, 42, 54 -button = 80, 83, 105 -buttontext = 248, 248, 242 -brighttext = 68, 71, 90 -highlight = 166, 129, 218 -highlightedtext = 248, 248, 242 -link = 139, 233, 253 -linkvisited = 139, 233, 253 +window = #44475a +windowtext = #f8f8f2 +base = #282a36 +alternatebase = #333645 +text = #f8f8f2 +tooltipbase = #f1fa8c +tooltiptext = #282a36 +button = #505369 +buttontext = #f8f8f2 +brighttext = #44475a +highlight = #a681da +highlightedtext = #f8f8f2 +link = #8be9fd +linkvisited = #8be9fd [GUI] -helptext = 204, 172, 249 -fadedtext = 98, 114, 164 -errortext = 255, 85, 85 +helptext = #ccacf9 +fadedtext = #6272a4 +errortext = #ff5555 + +[Syntax] +background = #282a36 +text = #f8f8f2 +link = #ff79c6 +headertext = #bd93f9 +headertag = #bd93f9a0 +emphasis = #ffb86c +dialog = #50fa7b +altdialog = #f1fa8c +note = #ffcce9 +hidden = #6272a4 +shortcode = #8be9fd +keyword = #ff79c6 +tag = #ffb86c +value = #ffb86c +optional = #50fa7b +spellcheckline = #ff5555 +errorline = #50fa7b +replacetag = #f1fa8c +modifier = #8be9fd +texthighlight = #f1fa8c60 diff --git a/novelwriter/assets/themes/snazzy.conf b/novelwriter/assets/themes/snazzy.conf index 39ec3c87..19a662c0 100644 --- a/novelwriter/assets/themes/snazzy.conf +++ b/novelwriter/assets/themes/snazzy.conf @@ -1,48 +1,84 @@ [Main] name = Snazzy Light +mode = light author = Veronica Berglyd Olsen (adaptation) credit = Florian Reuschel (color theme) url = https://github.com/loilo/vscode-snazzy-light license = MIT License licenseurl = https://github.com/loilo/vscode-snazzy-light/blob/master/LICENSE -[Icons] -default = 86, 88, 105 -faded = 84, 85, 84 -red = 255, 92, 87 -orange = 245, 185, 0 -yellow = 207, 156, 0 -green = 45, 174, 88 -aqua = 19, 187, 183 -blue = 9, 161, 237 -purple = 247, 103, 187 +## +# Colours: +# Background = fafbfc : 250, 251, 252 +# Foreground = 565869 : 86, 88, 105 +# Comment = 9194a2 : 145, 148, 162 +# Yellow = cf9c00 : 207, 156, 0 +# Red = ff5c57 : 255, 92, 87 +# Pink = f767bb : 247, 103, 187 +# Blue = 09a1ed : 9, 161, 237 +# Cyan = 13bbb7 : 19, 187, 183 +# Green = 2dae58 : 45, 174, 88 +## + +[Base] +default = #565869 +faded = #545554 +red = #ff5c57 +orange = #f5b900 +yellow = #cf9c00 +green = #2dae58 +aqua = #13bbb7 +blue = #09a1ed +purple = #f767bb [Project] -root = 9, 161, 237 -folder = 207, 156, 0 -file = 84, 85, 84 -title = 45, 174, 88 -chapter = 255, 92, 87 -scene = 9, 161, 237 -note = 207, 156, 0 +root = #09a1ed +folder = #cf9c00 +file = #545554 +title = #2dae58 +chapter = #ff5c57 +scene = #09a1ed +note = #cf9c00 [Palette] -window = 243, 244, 245 -windowtext = 86, 88, 105 -base = 250, 251, 252 -alternatebase = 234, 234, 235 -text = 86, 88, 105 -tooltipbase = 245, 233, 194 -tooltiptext = 86, 88, 105 -button = 250, 251, 252 -buttontext = 86, 88, 105 -brighttext = 255, 255, 255 -highlight = 9, 161, 237 -highlightedtext = 255, 255, 255 -link = 9, 161, 237 -linkvisited = 9, 161, 237 +window = #f3f4f5 +windowtext = #565869 +base = #fafbfc +alternatebase = #eaeaeb +text = #565869 +tooltipbase = #f5e9c2 +tooltiptext = #565869 +button = #fafbfc +buttontext = #565869 +brighttext = #ffffff +highlight = #09a1ed +highlightedtext = #ffffff +link = #09a1ed +linkvisited = #09a1ed [GUI] -helptext = 9, 161, 237 -fadedtext = 84, 85, 84 -errortext = 255, 92, 87 +helptext = #09a1ed +fadedtext = #545554 +errortext = #ff5c57 + +[Syntax] +background = #fafbfc +text = #565869 +link = #09a1ed +headertext = #2dae58 +headertag = #2dae58a0 +emphasis = #f767bb +dialog = #09a1ed +altdialog = #cf9c00 +note = #78bbb9 +hidden = #9194a2 +shortcode = #f767bb +keyword = #09a1ed +tag = #2dae58 +value = #cf9c00 +optional = #cf9c00 +spellcheckline = #ff5c57 +errorline = #2dae58 +replacetag = #13bbb7 +modifier = #f767bb +texthighlight = #cf9c0060 diff --git a/novelwriter/assets/themes/solarized_dark.conf b/novelwriter/assets/themes/solarized_dark.conf index 0f401eb9..354b2be9 100644 --- a/novelwriter/assets/themes/solarized_dark.conf +++ b/novelwriter/assets/themes/solarized_dark.conf @@ -1,48 +1,90 @@ [Main] name = Solarized Dark +mode = dark author = nullbasis credit = Ethan Schoonover url = https://ethanschoonover.com/solarized/ license = MIT licenseurl = https://github.com/altercation/solarized/blob/master/LICENSE -[Icons] -default = 230, 223, 206 -faded = 166, 161, 149 -red = 220, 50, 47 -orange = 203, 75, 22 -yellow = 181, 137, 0 -green = 133, 153, 0 -aqua = 42, 161, 152 -blue = 38, 139, 210 -purple = 211, 54, 130 +## +# base03: #002b36 +# base02: #073642 +# base01: #586e75 +# base00: #657b83 +# base0: #839496 +# base1: #93a1a1 +# base2: #eee8d5 +# base3: #fdf6e3 +# yellow: #b58900 +# orange: #cb4b16 +# red: #dc322f +# magenta: #d33682 +# violet: #6c71c4 +# blue: #268bd2 +# cyan: #2aa198 +# green: #859900 +## + +[Base] +default = #e6dfce +faded = #a6a195 +red = #dc322f +orange = #cb4b16 +yellow = #b58900 +green = #859900 +aqua = #2aa198 +blue = #268bd2 +purple = #6c71c4 [Project] -root = 42, 161, 152 -folder = 42, 161, 152 -file = 230, 223, 206 -title = 133, 153, 0 -chapter = 220, 50, 47 -scene = 38, 139, 210 -note = 181, 137, 0 +root = #2aa198 +folder = #2aa198 +file = #e6dfce +title = #859900 +chapter = #dc322f +scene = #268bd2 +note = #b58900 [Palette] -window = 0, 43, 54 -windowtext = 253, 246, 227 -base = 7, 54, 66 -alternatebase = 88, 110, 117 -text = 253, 246, 227 -tooltipbase = 133, 153, 0 -tooltiptext = 0, 43, 54 -button = 7, 54, 66 -buttontext = 253, 246, 227 -brighttext = 7, 54, 66 -highlight = 42, 161, 152 -highlightedtext = 0, 43, 54 -link = 38, 139, 210 -linkvisited = 38, 139, 210 +window = #002b36 +windowtext = #fdf6e3 +base = #073642 +alternatebase = #586e75 +text = #fdf6e3 +tooltipbase = #859900 +tooltiptext = #002b36 +button = #073642 +buttontext = #fdf6e3 +brighttext = #073642 +highlight = #2aa198 +highlightedtext = #002b36 +link = #268bd2 +linkvisited = #268bd2 [GUI] -helptext = 101, 123, 131 -fadedtext = 101, 123, 131 -errortext = 220, 50, 47 +helptext = #657b83 +fadedtext = #657b83 +errortext = #dc322f + +[Syntax] +background = #073642 +text = #fdf6e3 +link = #268bd2 +headertext = #93a1a1 +headertag = #2aa198 +emphasis = #268bd2 +dialog = #2aa198 +altdialog = #2aa198 +note = #65a19c +hidden = #93a1a1 +shortcode = #93a1a1 +keyword = #859900 +tag = #cb4b16 +value = #cb4b16 +optional = #93a1a1 +spellcheckline = #cb4b16 +errorline = #dc322f +replacetag = #859900 +modifier = #b58900 +texthighlight = #b5890060 diff --git a/novelwriter/assets/themes/solarized_light.conf b/novelwriter/assets/themes/solarized_light.conf index 06f4cb20..7d7427f5 100644 --- a/novelwriter/assets/themes/solarized_light.conf +++ b/novelwriter/assets/themes/solarized_light.conf @@ -1,48 +1,90 @@ [Main] name = Solarized Light +mode = light author = nullbasis credit = Ethan Schoonover url = https://ethanschoonover.com/solarized/ license = MIT licenseurl = https://github.com/altercation/solarized/blob/master/LICENSE -[Icons] -default = 59, 68, 71 -faded = 78, 91, 95 -red = 220, 50, 47 -orange = 203, 75, 22 -yellow = 181, 137, 0 -green = 133, 153, 0 -aqua = 42, 161, 152 -blue = 38, 139, 210 -purple = 211, 54, 130 +## +# base03: #002b36 +# base02: #073642 +# base01: #586e75 +# base00: #657b83 +# base0: #839496 +# base1: #93a1a1 +# base2: #eee8d5 +# base3: #fdf6e3 +# yellow: #b58900 +# orange: #cb4b16 +# red: #dc322f +# magenta: #d33682 +# violet: #6c71c4 +# blue: #268bd2 +# cyan: #2aa198 +# green: #859900 +## + +[Base] +default = #3b4447 +faded = #4e5b5f +red = #dc322f +orange = #cb4b16 +yellow = #b58900 +green = #859900 +aqua = #2aa198 +blue = #268bd2 +purple = #6c71c4 [Project] -root = 42, 161, 152 -folder = 42, 161, 152 -file = 59, 68, 71 -title = 133, 153, 0 -chapter = 220, 50, 47 -scene = 38, 139, 210 -note = 181, 137, 0 +root = #2aa198 +folder = #2aa198 +file = #3b4447 +title = #859900 +chapter = #dc322f +scene = #268bd2 +note = #b58900 [Palette] -window = 238, 232, 213 -windowtext = 0, 43, 54 -base = 253, 246, 227 -alternatebase = 147, 161, 161 -text = 0, 43, 54 -tooltipbase = 133, 153, 0 -tooltiptext = 0, 43, 54 -button = 238, 232, 213 -buttontext = 0, 43, 54 -brighttext = 253, 246, 227 -highlight = 42, 161, 152 -highlightedtext = 253, 246, 227 -link = 38, 139, 210 -linkvisited = 38, 139, 210 +window = #eee8d5 +windowtext = #002b36 +base = #fdf6e3 +alternatebase = #93a1a1 +text = #002b36 +tooltipbase = #859900 +tooltiptext = #002b36 +button = #eee8d5 +buttontext = #002b36 +brighttext = #fdf6e3 +highlight = #2aa198 +highlightedtext = #fdf6e3 +link = #268bd2 +linkvisited = #268bd2 [GUI] -helptext = 78, 91, 95 -fadedtext = 78, 91, 95 -errortext = 220, 50, 47 +helptext = #4e5b5f +fadedtext = #4e5b5f +errortext = #dc322f + +[Syntax] +background = #fdf6e3 +text = #002b36 +link = #268bd2 +headertext = #586e75 +headertag = #2aa198 +emphasis = #268bd2 +dialog = #2aa198 +altdialog = #2aa198 +note = #1b6660 +hidden = #586e75 +shortcode = #586e75 +keyword = #859900 +tag = #cb4b16 +value = #cb4b16 +optional = #586e75 +spellcheckline = #cb4b16 +errorline = #dc322f +replacetag = #859900 +modifier = #b58900 +texthighlight = #b5890060 From 072d0f0acdd5f6f583f9b96d37556186e91fb94a Mon Sep 17 00:00:00 2001 From: Veronica Berglyd Olsen <1619840+vkbo@users.noreply.github.com> Date: Mon, 2 Jun 2025 18:40:58 +0200 Subject: [PATCH 04/20] Merge and update the default themes --- novelwriter/assets/syntax/default_dark.conf | 42 --------- novelwriter/assets/syntax/default_light.conf | 42 --------- novelwriter/assets/themes/default_dark.conf | 90 ++++++++++++-------- novelwriter/assets/themes/default_light.conf | 90 ++++++++++++-------- novelwriter/gui/theme.py | 2 +- 5 files changed, 113 insertions(+), 153 deletions(-) delete mode 100644 novelwriter/assets/syntax/default_dark.conf delete mode 100644 novelwriter/assets/syntax/default_light.conf diff --git a/novelwriter/assets/syntax/default_dark.conf b/novelwriter/assets/syntax/default_dark.conf deleted file mode 100644 index 8e467189..00000000 --- a/novelwriter/assets/syntax/default_dark.conf +++ /dev/null @@ -1,42 +0,0 @@ -[Main] -name = Default Dark -author = Veronica Berglyd Olsen -credit = Veronica Berglyd Olsen -url = https://github.com/vkbo/novelWriter -license = CC BY-SA 4.0 -licenseurl = https://creativecommons.org/licenses/by-sa/4.0/ - -## -# Colours: -# Background = 2a2a2a : 42, 42, 42 -# Foreground = cccccc : 204, 204, 204 -# Comment = 969696 : 150, 150, 150 -# Red = e64250 : 230, 66, 80 -# Orange = f99157 : 249, 145, 87 -# Yellow = ffff84 : 255, 255, 132 -# Green = 99cc99 : 153, 204, 153 -# Blue = 288ed7 : 102, 153, 204 -# Purple = 8c56d7 : 140, 86, 215 -## - -[Syntax] -background = 42, 42, 42 -text = 204, 204, 204 -link = 102, 153, 204 -headertext = 153, 204, 153 -headertag = 153, 204, 153, 160 -emphasis = 249, 145, 87 -dialog = 102, 153, 204 -altdialog = 102, 153, 204 -note = 255, 255, 216 -hidden = 150, 150, 150 -shortcode = 153, 204, 153 -keyword = 230, 66, 80 -tag = 153, 204, 153 -value = 102, 153, 204 -optional = 153, 204, 153 -spellcheckline = 230, 66, 80 -errorline = 153, 204, 153 -replacetag = 153, 204, 153 -modifier = 153, 204, 153 -texthighlight = 255, 255, 132, 96 diff --git a/novelwriter/assets/syntax/default_light.conf b/novelwriter/assets/syntax/default_light.conf deleted file mode 100644 index 2e5ae404..00000000 --- a/novelwriter/assets/syntax/default_light.conf +++ /dev/null @@ -1,42 +0,0 @@ -[Main] -name = Default Light -author = Veronica Berglyd Olsen -credit = Veronica Berglyd Olsen -url = https://github.com/vkbo/novelWriter -license = CC BY-SA 4.0 -licenseurl = https://creativecommons.org/licenses/by-sa/4.0/ - -## -# Colours: -# Background = ffffff : 255, 255, 255 -# Foreground = 000000 : 0, 0, 0 -# Comment = 646464 : 100, 100, 100 -# Red = c83232 : 200, 50, 50 -# Orange = ae6e1e : 174, 110, 30 -# Yellow = 969600 : 150, 150, 0 -# Green = 006400 : 0, 100, 0 -# Blue = 0000c8 : 0, 0, 200 -# Purple = 6400ae : 100, 0, 174 -## - -[Syntax] -background = 255, 255, 255 -text = 0, 0, 0 -link = 0, 0, 200 -headertext = 0, 100, 0 -headertag = 0, 100, 0, 160 -emphasis = 174, 110, 30 -dialog = 0, 0, 200 -altdialog = 0, 0, 200 -note = 100, 100, 0 -hidden = 100, 100, 100 -shortcode = 0, 100, 0 -keyword = 200, 50, 50 -tag = 0, 100, 0 -value = 0, 0, 200 -optional = 0, 100, 0 -spellcheckline = 200, 50, 50 -errorline = 0, 100, 0 -replacetag = 0, 100, 0 -modifier = 0, 100, 0 -texthighlight = 150, 150, 0, 96 diff --git a/novelwriter/assets/themes/default_dark.conf b/novelwriter/assets/themes/default_dark.conf index 6ccf6ede..a8e6a3de 100644 --- a/novelwriter/assets/themes/default_dark.conf +++ b/novelwriter/assets/themes/default_dark.conf @@ -8,43 +8,65 @@ url = https://github.com/vkbo/novelWriter license = CC BY-SA 4.0 licenseurl = https://creativecommons.org/licenses/by-sa/4.0/ -[Icons] -default = 184, 184, 184 -faded = 148, 148, 148 -red = 242, 119, 122 -orange = 249, 145, 57 -yellow = 255, 204, 102 -green = 153, 204, 153 -aqua = 102, 204, 204 -blue = 102, 153, 204 -purple = 204, 153, 204 +[Base] +default = #cccccc +faded = #949494 +red = #f2777a +orange = #f99139 +yellow = #ffcc66 +green = #99cc99 +aqua = #66cccc +blue = #6699cc +purple = #cc99cc [Project] -root = 102, 153, 204 -folder = 255, 204, 102 -file = 184, 184, 184 -title = 153, 204, 153 -chapter = 242, 119, 122 -scene = 102, 153, 204 -note = 255, 204, 102 +root = blue +folder = yellow +file = default +title = green +chapter = red +scene = blue +note = yellow [Palette] -window = 54, 54, 54 -windowtext = 204, 204, 204 -base = 62, 62, 62 -alternatebase = 78, 78, 78 -text = 204, 204, 204 -tooltipbase = 255, 255, 192 -tooltiptext = 21, 21, 13 -button = 62, 62, 62 -buttontext = 204, 204, 204 -brighttext = 62, 62, 62 -highlight = 44, 152, 247 -highlightedtext = 255, 255, 255 -link = 102, 153, 204 -linkvisited = 102, 153, 204 +window = #363636 +windowtext = default +base = #3e3e3e +alternatebase = #4e4e4e +text = default +tooltipbase = #ffffc0 +tooltiptext = #15150d +button = #3e3e3e +buttontext = default +brighttext = #3e3e3e +highlight = #2c98f7 +highlightedtext = #ffffff +link = blue +linkvisited = blue [GUI] -helptext = 164, 164, 164 -fadedtext = 148, 148, 148 -errortext = 255, 164, 164 +helptext = #a4a4a4 +fadedtext = #949494 +errortext = red + +[Syntax] +background = #363636 +text = default +link = blue +headertext = green +headertag = green, 160 +emphasis = orange +dialog = blue +altdialog = blue +note = yellow +hidden = faded +shortcode = green +keyword = red +tag = green +value = blue +optional = green +spellcheckline = red +errorline = green +replacetag = green +modifier = green +texthighlight = yellow, 72 diff --git a/novelwriter/assets/themes/default_light.conf b/novelwriter/assets/themes/default_light.conf index f236f404..c4496d13 100644 --- a/novelwriter/assets/themes/default_light.conf +++ b/novelwriter/assets/themes/default_light.conf @@ -8,43 +8,65 @@ url = https://github.com/vkbo/novelWriter license = CC BY-SA 4.0 licenseurl = https://creativecommons.org/licenses/by-sa/4.0/ -[Icons] -default = 72, 72, 72 -faded = 108, 108, 108 -red = 240, 40, 41 -orange = 245, 135, 31 -yellow = 234, 183, 0 -green = 113, 140, 0 -aqua = 62, 153, 159 -blue = 66, 113, 174 -purple = 137, 89, 168 +[Base] +default = #303030 +faded = #6c6c6c +red = #a62a2d +orange = #b36829 +yellow = #a68542 +green = #296629 +aqua = #269999 +blue = #3a70a6 +purple = #b35ab3 [Project] -root = 66, 113, 174 -folder = 234, 183, 0 -file = 72, 72, 72 -title = 113, 140, 0 -chapter = 240, 40, 41 -scene = 66, 113, 174 -note = 234, 183, 0 +root = blue +folder = yellow +file = default +title = green +chapter = red +scene = blue +note = yellow [Palette] -window = 239, 239, 239 -windowtext = 0, 0, 0 -base = 255, 255, 255 -alternatebase = 224, 224, 224 -text = 0, 0, 0 -tooltipbase = 255, 255, 220 -tooltiptext = 0, 0, 0 -button = 239, 239, 239 -buttontext = 0, 0, 0 -brighttext = 255, 255, 255 -highlight = 48, 135, 198 -highlightedtext = 255, 255, 255 -link = 66, 113, 174 -linkvisited = 66, 113, 174 +window = #efefef +windowtext = #000000 +base = #ffffff +alternatebase = #e0e0e0 +text = #000000 +tooltipbase = #ffffdc +tooltiptext = #000000 +button = #efefef +buttontext = #000000 +brighttext = #ffffff +highlight = #3087c6 +highlightedtext = #ffffff +link = blue +linkvisited = blue [GUI] -helptext = 92, 92, 92 -fadedtext = 108, 108, 108 -errortext = 255, 92, 92 +helptext = #5c5c5c +fadedtext = #6c6c6c +errortext = red + +[Syntax] +background = #ffffff +text = #000000 +link = blue +headertext = green +headertag = green, 160 +emphasis = orange +dialog = blue +altdialog = blue +note = yellow +hidden = faded +shortcode = green +keyword = red +tag = green +value = blue +optional = green +spellcheckline = red +errorline = green +replacetag = green +modifier = green +texthighlight = #c8c80060 diff --git a/novelwriter/gui/theme.py b/novelwriter/gui/theme.py index 437531a3..4a53f453 100644 --- a/novelwriter/gui/theme.py +++ b/novelwriter/gui/theme.py @@ -244,7 +244,7 @@ class GuiTheme: entries = len(data) if entries == 2: # Assume name, alpha - color = self._qColors.get(data[0].strip(), default) + color = QColor(self._qColors.get(data[0].strip(), default)) color.setAlpha(checkInt(data[1], 255)) return color else: From 3258b8806f74ff89cd421bbea3be0f67350cdac4 Mon Sep 17 00:00:00 2001 From: Veronica Berglyd Olsen <1619840+vkbo@users.noreply.github.com> Date: Mon, 2 Jun 2025 19:15:33 +0200 Subject: [PATCH 05/20] Merge and update the tomorrow themes --- novelwriter/assets/syntax/tomorrow.conf | 49 ---------- novelwriter/assets/syntax/tomorrow_night.conf | 49 ---------- .../assets/syntax/tomorrow_night_blue.conf | 49 ---------- .../assets/syntax/tomorrow_night_bright.conf | 49 ---------- .../syntax/tomorrow_night_eighties.conf | 49 ---------- novelwriter/assets/themes/default_dark.conf | 40 ++++---- novelwriter/assets/themes/tomorrow.conf | 91 +++++++++++++++++++ novelwriter/assets/themes/tomorrow_night.conf | 90 ++++++++++++++++++ .../assets/themes/tomorrow_night_blue.conf | 91 +++++++++++++++++++ .../assets/themes/tomorrow_night_bright.conf | 91 +++++++++++++++++++ .../themes/tomorrow_night_eighties.conf | 91 +++++++++++++++++++ 11 files changed, 474 insertions(+), 265 deletions(-) delete mode 100644 novelwriter/assets/syntax/tomorrow.conf delete mode 100644 novelwriter/assets/syntax/tomorrow_night.conf delete mode 100644 novelwriter/assets/syntax/tomorrow_night_blue.conf delete mode 100644 novelwriter/assets/syntax/tomorrow_night_bright.conf delete mode 100644 novelwriter/assets/syntax/tomorrow_night_eighties.conf create mode 100644 novelwriter/assets/themes/tomorrow.conf create mode 100644 novelwriter/assets/themes/tomorrow_night.conf create mode 100644 novelwriter/assets/themes/tomorrow_night_blue.conf create mode 100644 novelwriter/assets/themes/tomorrow_night_bright.conf create mode 100644 novelwriter/assets/themes/tomorrow_night_eighties.conf diff --git a/novelwriter/assets/syntax/tomorrow.conf b/novelwriter/assets/syntax/tomorrow.conf deleted file mode 100644 index d3d2b8e4..00000000 --- a/novelwriter/assets/syntax/tomorrow.conf +++ /dev/null @@ -1,49 +0,0 @@ -## -# Theme: Tomorrow -# Source: https://github.com/chriskempson/tomorrow-theme -# Credit: Chris Kempson -## -# Colours: -# Background = ffffff : 255, 255, 255 -# Current Line = efefef : 239, 239, 239 -# Selection = d6d6d6 : 214, 214, 214 -# Foreground = 4d4d4c : 77, 77, 76 -# Comment = 8e908c : 142, 144, 140 -# Red = c82829 : 240, 40, 41 -# Orange = f5871f : 245, 135, 31 -# Yellow = eab700 : 234, 183, 0 -# Green = 718c00 : 113, 140, 0 -# Aqua = 3e999f : 62, 153, 159 -# Blue = 4271ae : 66, 113, 174 -# Purple = 8959a8 : 137, 89, 168 -## - -[Main] -name = Tomorrow -author = Veronica Berglyd Olsen (adaptation) -credit = Chris Kempson (color theme) -url = https://github.com/chriskempson/tomorrow-theme -license = MIT License -licenseurl = https://github.com/chriskempson/tomorrow-theme/blob/master/LICENSE.md - -[Syntax] -background = 255, 255, 255 -text = 77, 77, 76 -link = 66, 113, 174 -headertext = 66, 113, 174 -headertag = 66, 113, 174, 160 -emphasis = 245, 135, 31 -dialog = 113, 140, 0 -altdialog = 234, 183, 0 -note = 115, 90, 0 -hidden = 142, 144, 140 -shortcode = 66, 113, 174 -keyword = 240, 40, 41 -tag = 137, 89, 168 -value = 234, 183, 0 -optional = 66, 113, 174 -spellcheckline = 240, 40, 41 -errorline = 113, 140, 0 -replacetag = 62, 153, 159 -modifier = 245, 135, 31 -texthighlight = 234, 183, 0, 96 diff --git a/novelwriter/assets/syntax/tomorrow_night.conf b/novelwriter/assets/syntax/tomorrow_night.conf deleted file mode 100644 index 15257945..00000000 --- a/novelwriter/assets/syntax/tomorrow_night.conf +++ /dev/null @@ -1,49 +0,0 @@ -## -# Theme: Tomorrow Night -# Source: https://github.com/chriskempson/tomorrow-theme -# Credit: Chris Kempson -## -# Colours: -# Background = 1d1f21 : 29, 31, 33 -# Current Line = 282a2e : 40, 42, 46 -# Selection = 373b41 : 55, 59. 65 -# Foreground = c5c8c6 : 197, 200, 198 -# Comment = 969896 : 150, 152, 150 -# Red = cc6666 : 204, 102, 102 -# Orange = de935f : 222, 147, 95 -# Yellow = f0c674 : 240, 198, 116 -# Green = b5bd68 : 181, 189, 104 -# Aqua = 8abeb7 : 138, 190, 183 -# Blue = 81a2be : 129, 162, 190 -# Purple = b294bb : 178, 148, 187 -## - -[Main] -name = Tomorrow Night -author = Veronica Berglyd Olsen (adaptation) -credit = Chris Kempson (color theme) -url = https://github.com/chriskempson/tomorrow-theme -license = MIT License -licenseurl = https://github.com/chriskempson/tomorrow-theme/blob/master/LICENSE.md - -[Syntax] -background = 29, 31, 33 -text = 197, 200, 198 -link = 197, 200, 198, 160 -headertext = 129, 162, 190 -headertag = 94, 119, 139 -emphasis = 222, 147, 95 -dialog = 181, 189, 104 -altdialog = 240, 198, 116 -note = 240, 219, 178 -hidden = 150, 152, 150 -shortcode = 129, 162, 190 -keyword = 204, 102, 102 -tag = 178, 148, 187 -value = 240, 198, 116 -optional = 129, 162, 190 -spellcheckline = 204, 102, 102 -errorline = 181, 189, 104 -replacetag = 138, 190, 183 -modifier = 222, 147, 95 -texthighlight = 240, 198, 116, 96 diff --git a/novelwriter/assets/syntax/tomorrow_night_blue.conf b/novelwriter/assets/syntax/tomorrow_night_blue.conf deleted file mode 100644 index 89067e4f..00000000 --- a/novelwriter/assets/syntax/tomorrow_night_blue.conf +++ /dev/null @@ -1,49 +0,0 @@ -## -# Theme: Tomorrow Night Blue -# Source: https://github.com/chriskempson/tomorrow-theme -# Credit: Chris Kempson -## -# Colours: -# Background = 002451 : 0, 36, 81 -# Current Line = 00346e : 0, 52, 110 -# Selection = 003f8e : 0, 63, 142 -# Foreground = ffffff : 255, 255, 255 -# Comment = 7285b7 : 114, 133, 183 -# Red = ff9da4 : 255, 157, 164 -# Orange = ffc58f : 255, 197, 143 -# Yellow = ffeead : 255, 238, 173 -# Green = d1f1a9 : 209, 241, 169 -# Aqua = 99ffff : 153, 255, 255 -# Blue = bbdaff : 187, 218, 255 -# Purple = ebbbff : 235, 187, 255 -## - -[Main] -name = Tomorrow Night Blue -author = Veronica Berglyd Olsen (adaptation) -credit = Chris Kempson (color theme) -url = https://github.com/chriskempson/tomorrow-theme -license = MIT License -licenseurl = https://github.com/chriskempson/tomorrow-theme/blob/master/LICENSE.md - -[Syntax] -background = 0, 36, 81 -text = 255, 255, 255 -link = 187, 218, 255 -headertext = 187, 218, 255 -headertag = 187, 218, 255, 160 -emphasis = 255, 197, 143 -dialog = 209, 241, 169 -altdialog = 255, 238, 173 -note = 255, 247, 214 -hidden = 114, 133, 183 -shortcode = 187, 218, 255 -keyword = 255, 157, 164 -tag = 235, 187, 255 -value = 255, 238, 173 -optional = 187, 218, 255 -spellcheckline = 255, 157, 164 -errorline = 209, 241, 169 -replacetag = 153, 255, 255 -modifier = 255, 197, 143 -texthighlight = 255, 238, 173, 96 diff --git a/novelwriter/assets/syntax/tomorrow_night_bright.conf b/novelwriter/assets/syntax/tomorrow_night_bright.conf deleted file mode 100644 index 0f1fd055..00000000 --- a/novelwriter/assets/syntax/tomorrow_night_bright.conf +++ /dev/null @@ -1,49 +0,0 @@ -## -# Theme: Tomorrow Night Bright -# Source: https://github.com/chriskempson/tomorrow-theme -# Credit: Chris Kempson -## -# Colours: -# Background = 000000 : 0, 0, 0 -# Current Line = 2a2a2a : 42, 42, 42 -# Selection = 424242 : 66, 66, 66 -# Foreground = eaeaea : 234, 234, 234 -# Comment = 969896 : 150, 152, 150 -# Red = d54e53 : 213, 78, 83 -# Orange = e78c45 : 231, 140, 69 -# Yellow = e7c547 : 231, 197, 71 -# Green = b9ca4a : 185, 202, 74 -# Aqua = 70c0b1 : 112, 192, 177 -# Blue = 7aa6da : 122, 166, 218 -# Purple = c397d8 : 195, 151, 216 -## - -[Main] -name = Tomorrow Night Bright -author = Veronica Berglyd Olsen (adaptation) -credit = Chris Kempson (color theme) -url = https://github.com/chriskempson/tomorrow-theme -license = MIT License -licenseurl = https://github.com/chriskempson/tomorrow-theme/blob/master/LICENSE.md - -[Syntax] -background = 0, 0, 0 -text = 234, 234, 234 -link = 122, 166, 218 -headertext = 122, 166, 218 -headertag = 122, 166, 218, 160 -emphasis = 231, 140, 69 -dialog = 185, 202, 74 -altdialog = 231, 197, 71 -note = 231, 214, 150 -hidden = 150, 152, 150 -shortcode = 122, 166, 218 -keyword = 213, 78, 83 -tag = 195, 151, 216 -value = 231, 197, 71 -optional = 122, 166, 218 -spellcheckline = 213, 78, 83 -errorline = 185, 202, 74 -replacetag = 112, 192, 177 -modifier = 231, 140, 69 -texthighlight = 231, 197, 71, 128 diff --git a/novelwriter/assets/syntax/tomorrow_night_eighties.conf b/novelwriter/assets/syntax/tomorrow_night_eighties.conf deleted file mode 100644 index a638a871..00000000 --- a/novelwriter/assets/syntax/tomorrow_night_eighties.conf +++ /dev/null @@ -1,49 +0,0 @@ -## -# Theme: Tomorrow Night Eighties -# Source: https://github.com/chriskempson/tomorrow-theme -# Credit: Chris Kempson -## -# Colours: -# Background = 2d2d2d : 45, 45, 45 -# Current Line = 393939 : 57, 57, 57 -# Selection = 515151 : 81, 81, 81 -# Foreground = cccccc : 204, 204, 204 -# Comment = 999999 : 153, 153, 153 -# Red = f2777a : 242, 119, 122 -# Orange = f99157 : 249, 145, 57 -# Yellow = ffcc66 : 255, 204, 102 -# Green = 99cc99 : 153, 204, 153 -# Aqua = 66cccc : 102, 204, 204 -# Blue = 6699cc : 102, 153, 204 -# Purple = cc99cc : 204, 153, 204 -## - -[Main] -name = Tomorrow Night Eighties -author = Veronica Berglyd Olsen (adaptation) -credit = Chris Kempson (color theme) -url = https://github.com/chriskempson/tomorrow-theme -license = MIT License -licenseurl = https://github.com/chriskempson/tomorrow-theme/blob/master/LICENSE.md - -[Syntax] -background = 45, 45, 45 -text = 204, 204, 204 -link = 102, 153, 204 -headertext = 102, 153, 204 -headertag = 102, 153, 204, 160 -emphasis = 249, 145, 57 -dialog = 153, 204, 153 -altdialog = 255, 204, 102 -note = 255, 230, 179 -hidden = 153, 153, 153 -shortcode = 102, 153, 204 -keyword = 242, 119, 122 -tag = 204, 153, 204 -value = 255, 204, 102 -optional = 102, 153, 204 -spellcheckline = 242, 119, 122 -errorline = 153, 204, 153 -replacetag = 102, 204, 204 -modifier = 249, 145, 57 -texthighlight = 255, 204, 102, 96 diff --git a/novelwriter/assets/themes/default_dark.conf b/novelwriter/assets/themes/default_dark.conf index a8e6a3de..7b0c3922 100644 --- a/novelwriter/assets/themes/default_dark.conf +++ b/novelwriter/assets/themes/default_dark.conf @@ -50,23 +50,23 @@ fadedtext = #949494 errortext = red [Syntax] -background = #363636 -text = default -link = blue -headertext = green -headertag = green, 160 -emphasis = orange -dialog = blue -altdialog = blue -note = yellow -hidden = faded -shortcode = green -keyword = red -tag = green -value = blue -optional = green -spellcheckline = red -errorline = green -replacetag = green -modifier = green -texthighlight = yellow, 72 +background = #363636 +text = default +link = blue +headertext = green +headertag = green, 160 +emphasis = orange +dialog = blue +altdialog = blue +note = yellow +hidden = faded +shortcode = green +keyword = red +tag = green +value = blue +optional = green +spellcheckline = red +errorline = green +replacetag = green +modifier = green +texthighlight = yellow, 72 diff --git a/novelwriter/assets/themes/tomorrow.conf b/novelwriter/assets/themes/tomorrow.conf new file mode 100644 index 00000000..ab49754b --- /dev/null +++ b/novelwriter/assets/themes/tomorrow.conf @@ -0,0 +1,91 @@ +[Main] +name = Tomorrow +mode = light +author = Veronica Berglyd Olsen (adaptation) +credit = Chris Kempson (color theme) +url = https://github.com/chriskempson/tomorrow-theme +license = MIT License +licenseurl = https://github.com/chriskempson/tomorrow-theme/blob/master/LICENSE.md + +## +# Theme: Tomorrow +# Source: https://github.com/chriskempson/tomorrow-theme +# Credit: Chris Kempson +## +# Colours: +# Background = #ffffff +# Current Line = #efefef +# Selection = #d6d6d6 +# Foreground = #4d4d4c +# Comment = #8e908c +# Red = #c82829 +# Orange = #f5871f +# Yellow = #eab700 +# Green = #718c00 +# Aqua = #3e999f +# Blue = #4271ae +# Purple = #8959a8 +## + +[Base] +default = #484848 +faded = #6c6c6c +red = #c82829 +orange = #f5871f +yellow = #eab700 +green = #718c00 +aqua = #3e999f +blue = #4271ae +purple = #8959a8 + +[Project] +root = blue +folder = yellow +file = default +title = green +chapter = red +scene = blue +note = yellow + +[Palette] +window = #efefef +windowtext = #000000 +base = #ffffff +alternatebase = #d6d6d6 +text = #000000 +tooltipbase = #ffffdc +tooltiptext = #000000 +button = #ffffff +buttontext = #000000 +brighttext = #ffffff +highlight = blue +highlightedtext = #ffffff +link = blue +linkvisited = blue + +[GUI] +helptext = #5c5c5c +fadedtext = faded +errortext = red + +[Syntax] +background = #ffffff +text = #4d4d4c +link = blue +headertext = blue +headertag = blue, 160 +emphasis = orange +dialog = green +altdialog = yellow +note = #b38c00 +hidden = faded +shortcode = blue +keyword = red +tag = purple +value = yellow +optional = blue +spellcheckline = red +errorline = green +replacetag = aqua +modifier = orange +texthighlight = yellow, 96 diff --git a/novelwriter/assets/themes/tomorrow_night.conf b/novelwriter/assets/themes/tomorrow_night.conf new file mode 100644 index 00000000..16290bf0 --- /dev/null +++ b/novelwriter/assets/themes/tomorrow_night.conf @@ -0,0 +1,90 @@ +[Main] +name = Tomorrow Night +mode = dark +author = Veronica Berglyd Olsen (adaptation) +credit = Chris Kempson (color theme) +url = https://github.com/chriskempson/tomorrow-theme +license = MIT License +licenseurl = https://github.com/chriskempson/tomorrow-theme/blob/master/LICENSE.md +## +# Theme: Tomorrow Night +# Source: https://github.com/chriskempson/tomorrow-theme +# Credit: Chris Kempson +## +# Colours: +# Background = #1d1f21 +# Current Line = #282a2e +# Selection = #373b41 +# Foreground = #c5c8c6 +# Comment = #969896 +# Red = #cc6666 +# Orange = #de935f +# Yellow = #f0c674 +# Green = #b5bd68 +# Aqua = #8abeb7 +# Blue = #81a2be +# Purple = #b294bb +## + +[Base] +default = #c5c8c6 +faded = #969896 +red = #cc6666 +orange = #de935f +yellow = #f0c674 +green = #b5bd68 +aqua = #8abeb7 +blue = #81a2be +purple = #b294bb + +[Project] +root = blue +folder = yellow +file = default +title = green +chapter = red +scene = blue +note = yellow + +[Palette] +window = #282a2e +windowtext = default +base = #1d1f21 +alternatebase = #373b41 +text = default +tooltipbase = #ffffc0 +tooltiptext = #15150d +button = #1d1f21 +buttontext = default +brighttext = #1d1f21 +highlight = #2c98f7 +highlightedtext = #ffffff +link = blue +linkvisited = blue + +[GUI] +helptext = #a4a4a4 +fadedtext = #949494 +errortext = red + +[Syntax] +background = #1d1f21 +text = default +link = blue +headertext = blue +headertag = blue, 160 +emphasis = orange +dialog = green +altdialog = yellow +note = #f0dbb2 +hidden = faded +shortcode = blue +keyword = red +tag = purple +value = yellow +optional = blue +spellcheckline = red +errorline = green +replacetag = aqua +modifier = orange +texthighlight = yellow, 96 diff --git a/novelwriter/assets/themes/tomorrow_night_blue.conf b/novelwriter/assets/themes/tomorrow_night_blue.conf new file mode 100644 index 00000000..93b6592e --- /dev/null +++ b/novelwriter/assets/themes/tomorrow_night_blue.conf @@ -0,0 +1,91 @@ +[Main] +name = Tomorrow Night Blue +mode = dark +author = Veronica Berglyd Olsen (adaptation) +credit = Chris Kempson (color theme) +url = https://github.com/chriskempson/tomorrow-theme +license = MIT License +licenseurl = https://github.com/chriskempson/tomorrow-theme/blob/master/LICENSE.md + +## +# Theme: Tomorrow Night Blue +# Source: https://github.com/chriskempson/tomorrow-theme +# Credit: Chris Kempson +## +# Colours: +# Background = #002451 +# Current Line = #00346e +# Selection = #003f8e +# Foreground = #ffffff +# Comment = #7285b7 +# Red = #ff9da4 +# Orange = #ffc58f +# Yellow = #ffeead +# Green = #d1f1a9 +# Aqua = #99ffff +# Blue = #bbdaff +# Purple = #ebbbff +## + +[Base] +default = #ffffff +faded = #7285b7 +red = #ff9da4 +orange = #ffc58f +yellow = #ffeead +green = #d1f1a9 +aqua = #99ffff +blue = #bbdaff +purple = #ebbbff + +[Project] +root = blue +folder = yellow +file = default +title = green +chapter = red +scene = blue +note = yellow + +[Palette] +window = #00346e +windowtext = default +base = #002451 +alternatebase = #003f8e +text = default +tooltipbase = #ffffc0 +tooltiptext = #15150d +button = #002451 +buttontext = default +brighttext = #002451 +highlight = #2c98f7 +highlightedtext = #ffffff +link = blue +linkvisited = blue + +[GUI] +helptext = #a4a4a4 +fadedtext = #949494 +errortext = red + +[Syntax] +background = #002451 +text = default +link = blue +headertext = blue +headertag = blue, 160 +emphasis = orange +dialog = green +altdialog = yellow +note = #fff4cc +hidden = faded +shortcode = blue +keyword = red +tag = purple +value = yellow +optional = blue +spellcheckline = red +errorline = green +replacetag = aqua +modifier = orange +texthighlight = yellow, 96 diff --git a/novelwriter/assets/themes/tomorrow_night_bright.conf b/novelwriter/assets/themes/tomorrow_night_bright.conf new file mode 100644 index 00000000..de76e694 --- /dev/null +++ b/novelwriter/assets/themes/tomorrow_night_bright.conf @@ -0,0 +1,91 @@ +[Main] +name = Tomorrow Night Bright +mode = dark +author = Veronica Berglyd Olsen (adaptation) +credit = Chris Kempson (color theme) +url = https://github.com/chriskempson/tomorrow-theme +license = MIT License +licenseurl = https://github.com/chriskempson/tomorrow-theme/blob/master/LICENSE.md + +## +# Theme: Tomorrow Night Bright +# Source: https://github.com/chriskempson/tomorrow-theme +# Credit: Chris Kempson +## +# Colours: +# Background = #000000 +# Current Line = #2a2a2a +# Selection = #424242 +# Foreground = #eaeaea +# Comment = #969896 +# Red = #d54e53 +# Orange = #e78c45 +# Yellow = #e7c547 +# Green = #b9ca4a +# Aqua = #70c0b1 +# Blue = #7aa6da +# Purple = #c397d8 +## + +[Base] +default = #eaeaea +faded = #969896 +red = #d54e53 +orange = #e78c45 +yellow = #e7c547 +green = #b9ca4a +aqua = #70c0b1 +blue = #7aa6da +purple = #c397d8 + +[Project] +root = blue +folder = yellow +file = default +title = green +chapter = red +scene = blue +note = yellow + +[Palette] +window = #2a2a2a +windowtext = default +base = #000000 +alternatebase = #424242 +text = default +tooltipbase = #ffffc0 +tooltiptext = #15150d +button = #000000 +buttontext = default +brighttext = #000000 +highlight = #2c98f7 +highlightedtext = #ffffff +link = blue +linkvisited = blue + +[GUI] +helptext = #a4a4a4 +fadedtext = #949494 +errortext = red + +[Syntax] +background = #000000 +text = default +link = blue +headertext = blue +headertag = blue, 160 +emphasis = orange +dialog = green +altdialog = yellow +note = #e7d696 +hidden = faded +shortcode = blue +keyword = red +tag = purple +value = yellow +optional = blue +spellcheckline = red +errorline = green +replacetag = aqua +modifier = orange +texthighlight = yellow, 96 diff --git a/novelwriter/assets/themes/tomorrow_night_eighties.conf b/novelwriter/assets/themes/tomorrow_night_eighties.conf new file mode 100644 index 00000000..e3e8bbec --- /dev/null +++ b/novelwriter/assets/themes/tomorrow_night_eighties.conf @@ -0,0 +1,91 @@ +[Main] +name = Tomorrow Night Eighties +mode = dark +author = Veronica Berglyd Olsen (adaptation) +credit = Chris Kempson (color theme) +url = https://github.com/chriskempson/tomorrow-theme +license = MIT License +licenseurl = https://github.com/chriskempson/tomorrow-theme/blob/master/LICENSE.md + +## +# Theme: Tomorrow Night Eighties +# Source: https://github.com/chriskempson/tomorrow-theme +# Credit: Chris Kempson +## +# Colours: +# Background = #2d2d2d +# Current Line = #393939 +# Selection = #515151 +# Foreground = #cccccc +# Comment = #999999 +# Red = #f2777a +# Orange = #f99157 +# Yellow = #ffcc66 +# Green = #99cc99 +# Aqua = #66cccc +# Blue = #6699cc +# Purple = #cc99cc +## + +[Base] +default = #cccccc +faded = #999999 +red = #f2777a +orange = #f99157 +yellow = #ffcc66 +green = #99cc99 +aqua = #66cccc +blue = #6699cc +purple = #cc99cc + +[Project] +root = blue +folder = yellow +file = default +title = green +chapter = red +scene = blue +note = yellow + +[Palette] +window = #393939 +windowtext = default +base = #2d2d2d +alternatebase = #515151 +text = default +tooltipbase = #ffffc0 +tooltiptext = #15150d +button = #2d2d2d +buttontext = default +brighttext = #2d2d2d +highlight = #2c98f7 +highlightedtext = #ffffff +link = blue +linkvisited = blue + +[GUI] +helptext = #a4a4a4 +fadedtext = #949494 +errortext = red + +[Syntax] +background = #2d2d2d +text = default +link = blue +headertext = blue +headertag = blue, 160 +emphasis = orange +dialog = green +altdialog = yellow +note = #ffe6b3 +hidden = faded +shortcode = blue +keyword = red +tag = purple +value = yellow +optional = blue +spellcheckline = red +errorline = green +replacetag = aqua +modifier = orange +texthighlight = yellow, 96 From eed5cd187738ce43a30a6e0b2b73b711b68deb41 Mon Sep 17 00:00:00 2001 From: Veronica Berglyd Olsen <1619840+vkbo@users.noreply.github.com> Date: Mon, 2 Jun 2025 20:02:00 +0200 Subject: [PATCH 06/20] Merge and update the owl and tango themes --- novelwriter/assets/syntax/light_owl.conf | 49 ------------ novelwriter/assets/syntax/night_owl.conf | 49 ------------ novelwriter/assets/syntax/tango.conf | 39 ---------- novelwriter/assets/themes/light_owl.conf | 91 ++++++++++++++++++++++ novelwriter/assets/themes/night_owl.conf | 91 ++++++++++++++++++++++ novelwriter/assets/themes/tango_dark.conf | 81 +++++++++++++++++++ novelwriter/assets/themes/tango_light.conf | 81 +++++++++++++++++++ 7 files changed, 344 insertions(+), 137 deletions(-) delete mode 100644 novelwriter/assets/syntax/light_owl.conf delete mode 100644 novelwriter/assets/syntax/night_owl.conf delete mode 100644 novelwriter/assets/syntax/tango.conf create mode 100644 novelwriter/assets/themes/light_owl.conf create mode 100644 novelwriter/assets/themes/night_owl.conf create mode 100644 novelwriter/assets/themes/tango_dark.conf create mode 100644 novelwriter/assets/themes/tango_light.conf diff --git a/novelwriter/assets/syntax/light_owl.conf b/novelwriter/assets/syntax/light_owl.conf deleted file mode 100644 index ce65e704..00000000 --- a/novelwriter/assets/syntax/light_owl.conf +++ /dev/null @@ -1,49 +0,0 @@ -## -# Theme: Light Owl -# Source: https://github.com/sdras/night-owl-vscode-theme -# Credit: Sarah Drasner -## -# Colours: -# Background = fbfbfb : 251, 251, 251 -# Current Line = e0e0e0 : 224, 224, 224 -# Selection = e0e0e0 : 224, 224, 224 -# Foreground = 403f52 : 64, 63, 82 -# Comment = 989fb1 : 152, 159, 177 -# Red = de3d3a : 222, 61, 58 -# Orange = e0af05 : 224, 175, 5 -# Yellow = daaa01 : 218, 170, 1 -# Green = 08916a : 8, 145, 106 -# Aqua = 2aa298 : 42, 162, 152 -# Blue = 288ed7 : 40, 142, 215 -# Purple = 964ac1 : 150, 74, 193 -## - -[Main] -name = Light Owl -author = Veronica Berglyd Olsen (adaptation) -credit = Sarah Drasner (color theme) -url = https://github.com/sdras/night-owl-vscode-theme -license = MIT License -licenseurl = https://github.com/sdras/night-owl-vscode-theme/blob/master/LICENSE - -[Syntax] -background = 251, 251, 251 -text = 64, 63, 82 -link = 40, 142, 215 -headertext = 40, 142, 215 -headertag = 40, 142, 215, 160 -emphasis = 224, 175, 5 -dialog = 8, 145, 106 -altdialog = 218, 170, 1 -note = 128, 118, 75 -hidden = 152, 159, 177 -shortcode = 40, 142, 215 -keyword = 222, 61, 58 -tag = 150, 74, 193 -value = 224, 175, 5 -optional = 40, 142, 215 -spellcheckline = 222, 61, 58 -errorline = 8, 145, 106 -replacetag = 42, 162, 152 -modifier = 8, 145, 106 -texthighlight = 218, 170, 1, 96 diff --git a/novelwriter/assets/syntax/night_owl.conf b/novelwriter/assets/syntax/night_owl.conf deleted file mode 100644 index 337cdfb8..00000000 --- a/novelwriter/assets/syntax/night_owl.conf +++ /dev/null @@ -1,49 +0,0 @@ -## -# Theme: Night Owl -# Source: https://github.com/sdras/night-owl-vscode-theme -# Credit: Sarah Drasner -## -# Colours: -# Background = 011627 : 1, 22, 39 -# Current Line = 32374d : 50, 55, 77 -# Selection = 32374d : 50, 55, 77 -# Foreground = d6deeb : 214, 222, 235 -# Comment = 637777 : 99, 119, 119 -# Red = f78c6c : 247, 140, 108 -# Orange = ecc48d : 236, 196, 141 -# Yellow = ffeb95 : 255, 235, 149 -# Green = addb67 : 173, 219, 103 -# Aqua = 7fdbca : 127, 219, 202 -# Blue = 82aaff : 130, 170, 255 -# Purple = c792ea : 199, 146, 234 -## - -[Main] -name = Night Owl -author = Veronica Berglyd Olsen (adaptation) -credit = Sarah Drasner (color theme) -url = https://github.com/sdras/night-owl-vscode-theme -license = MIT License -licenseurl = https://github.com/sdras/night-owl-vscode-theme/blob/master/LICENSE - -[Syntax] -background = 1, 22, 39 -text = 214, 222, 235 -link = 130, 170, 255 -headertext = 130, 170, 255 -headertag = 130, 170, 255, 160 -emphasis = 236, 196, 141 -dialog = 173, 219, 103 -altdialog = 255, 235, 149 -note = 255, 249, 202 -hidden = 99, 119, 119 -shortcode = 130, 170, 255 -keyword = 247, 140, 108 -tag = 199, 146, 234 -value = 255, 235, 149 -optional = 130, 170, 255 -spellcheckline = 247, 140, 108 -errorline = 173, 219, 103 -replacetag = 127, 219, 202 -modifier = 173, 219, 103 -texthighlight = 255, 235, 149, 96 diff --git a/novelwriter/assets/syntax/tango.conf b/novelwriter/assets/syntax/tango.conf deleted file mode 100644 index 7c5e9daa..00000000 --- a/novelwriter/assets/syntax/tango.conf +++ /dev/null @@ -1,39 +0,0 @@ -[Main] -name = Tango -author = Veronica Berglyd Olsen (adaptation) - -## -# Colours: -# Background = 30302f : 48, 48, 47 -# Foreground = eeeeec : 238, 238, 236 -# Comment = 8f8f8d : 143, 143, 141 -# Red = ef2929 : 239, 41, 41 -# Orange = c4a000 : 196, 160, 0 -# Yellow = fce94f : 252, 233, 79 -# Green = 8ae234 : 138, 226, 52 -# Cyan = 34e2e2 : 52, 226, 226 -# Blue = 3465a4 : 114, 159, 207 -# Purple = ad7fa8 : 173, 127, 168 -## - -[Syntax] -background = 48, 48, 47 -text = 238, 238, 236 -link = 114, 159, 207 -headertext = 114, 159, 207 -headertag = 114, 159, 207, 160 -emphasis = 196, 160, 0 -dialog = 138, 226, 52 -altdialog = 252, 233, 79 -note = 252, 242, 164 -hidden = 143, 143, 141 -shortcode = 114, 159, 207 -keyword = 239, 41, 41 -tag = 173, 127, 168 -value = 239, 41, 41 -optional = 114, 159, 207 -spellcheckline = 239, 41, 41 -errorline = 138, 226, 52 -replacetag = 52, 226, 226 -modifier = 114, 159, 207 -texthighlight = 252, 233, 79, 96 diff --git a/novelwriter/assets/themes/light_owl.conf b/novelwriter/assets/themes/light_owl.conf new file mode 100644 index 00000000..d91cf0ba --- /dev/null +++ b/novelwriter/assets/themes/light_owl.conf @@ -0,0 +1,91 @@ +[Main] +name = Light Owl +mode = light +author = Veronica Berglyd Olsen (adaptation) +credit = Sarah Drasner (color theme) +url = https://github.com/sdras/night-owl-vscode-theme +license = MIT License +licenseurl = https://github.com/sdras/night-owl-vscode-theme/blob/master/LICENSE + +## +# Theme: Light Owl +# Source: https://github.com/sdras/night-owl-vscode-theme +# Credit: Sarah Drasner +## +# Colours: +# Background = #fbfbfb +# Current Line = #e0e0e0 +# Selection = #e0e0e0 +# Foreground = #403f52 +# Comment = #989fb1 +# Red = #de3d3a +# Orange = #e0af05 +# Yellow = #daaa01 +# Green = #08916a +# Aqua = #2aa298 +# Blue = #288ed7 +# Purple = #964ac1 +## + +[Base] +default = #403f52 +faded = #989fb1 +red = #de3d3a +orange = #e0af05 +yellow = #daaa01 +green = #08916a +aqua = #2aa298 +blue = #288ed7 +purple = #964ac1 + +[Project] +root = blue +folder = yellow +file = default +title = green +chapter = red +scene = blue +note = yellow + +[Palette] +window = #e0e0e0 +windowtext = default +base = #fbfbfb +alternatebase = #e0e0e0 +text = default +tooltipbase = #ffffc0 +tooltiptext = #15150d +button = #e0e0e0 +buttontext = default +brighttext = #e0e0e0 +highlight = #3087c6 +highlightedtext = #ffffff +link = blue +linkvisited = blue + +[GUI] +helptext = blue +fadedtext = faded +errortext = red + +[Syntax] +background = #fbfbfb +text = default +link = blue +headertext = blue +headertag = blue, 160 +emphasis = orange +dialog = green +altdialog = yellow +note = #80764b +hidden = faded +shortcode = blue +keyword = red +tag = purple +value = orange +optional = blue +spellcheckline = red +errorline = green +replacetag = aqua +modifier = green +texthighlight = yellow, 96 diff --git a/novelwriter/assets/themes/night_owl.conf b/novelwriter/assets/themes/night_owl.conf new file mode 100644 index 00000000..a5f0a02b --- /dev/null +++ b/novelwriter/assets/themes/night_owl.conf @@ -0,0 +1,91 @@ +[Main] +name = Night Owl +mode = dark +author = Veronica Berglyd Olsen (adaptation) +credit = Sarah Drasner (color theme) +url = https://github.com/sdras/night-owl-vscode-theme +license = MIT License +licenseurl = https://github.com/sdras/night-owl-vscode-theme/blob/master/LICENSE + +## +# Theme: Night Owl +# Source: https://github.com/sdras/night-owl-vscode-theme +# Credit: Sarah Drasner +## +# Colours: +# Background = #011627 +# Current Line = #32374d +# Selection = #32374d +# Foreground = #d6deeb +# Comment = #637777 +# Red = #f78c6c +# Orange = #ecc48d +# Yellow = #ffeb95 +# Green = #addb67 +# Aqua = #7fdbca +# Blue = #82aaff +# Purple = #c792ea +## + +[Base] +default = #d6deeb +faded = #637777 +red = #f78c6c +orange = #ecc48d +yellow = #addb67 +green = #addb67 +aqua = #7fdbca +blue = #82aaff +purple = #c792ea + +[Project] +root = blue +folder = yellow +file = default +title = green +chapter = red +scene = blue +note = yellow + +[Palette] +window = #32374d +windowtext = default +base = #011627 +alternatebase = #32374d +text = default +tooltipbase = #ffffc0 +tooltiptext = #15150d +button = #32374d +buttontext = default +brighttext = #32374d +highlight = #2c98f7 +highlightedtext = #ffffff +link = blue +linkvisited = blue + +[GUI] +helptext = blue +fadedtext = faded +errortext = red + +[Syntax] +background = #011627 +text = default +link = blue +headertext = blue +headertag = blue, 160 +emphasis = orange +dialog = green +altdialog = yellow +note = #fff9ca +hidden = faded +shortcode = blue +keyword = red +tag = purple +value = orange +optional = blue +spellcheckline = red +errorline = green +replacetag = aqua +modifier = green +texthighlight = yellow, 96 diff --git a/novelwriter/assets/themes/tango_dark.conf b/novelwriter/assets/themes/tango_dark.conf new file mode 100644 index 00000000..873e7f11 --- /dev/null +++ b/novelwriter/assets/themes/tango_dark.conf @@ -0,0 +1,81 @@ +[Main] +name = Tango Dark +mode = dark +author = Veronica Berglyd Olsen (adaptation) + +## +# Colours: +# Background = 30302f : 48, 48, 47 +# Foreground = eeeeec : 238, 238, 236 +# Comment = 8f8f8d : 143, 143, 141 +# Red = ef2929 : 239, 41, 41 +# Orange = c4a000 : 196, 160, 0 +# Yellow = fce94f : 252, 233, 79 +# Green = 8ae234 : 138, 226, 52 +# Cyan = 34e2e2 : 52, 226, 226 +# Blue = 3465a4 : 114, 159, 207 +# Purple = ad7fa8 : 173, 127, 168 +## + +[Base] +default = #eeeeec +faded = #babdb6 +red = #ef2929 +orange = #fcaf3e +yellow = #fce94f +green = #8ae234 +aqua = #34e2e2 +blue = #729fcf +purple = #ad7fa8 + +[Project] +root = blue +folder = yellow +file = default +title = green +chapter = red +scene = blue +note = yellow + +[Palette] +window = #555753 +windowtext = default +base = #2e3436 +alternatebase = #888a85 +text = default +tooltipbase = #ffffc0 +tooltiptext = #15150d +button = #555753 +buttontext = default +brighttext = #555753 +highlight = #2c98f7 +highlightedtext = #ffffff +link = blue +linkvisited = blue + +[GUI] +helptext = #e9b96e +fadedtext = faded +errortext = red + +[Syntax] +background = #2e3436 +text = default +link = blue +headertext = blue +headertag = blue, 160 +emphasis = orange +dialog = green +altdialog = yellow +note = #fcf2a4 +hidden = faded +shortcode = blue +keyword = red +tag = purple +value = red +optional = blue +spellcheckline = red +errorline = green +replacetag = cyan +modifier = blue +texthighlight = yellow, 96 diff --git a/novelwriter/assets/themes/tango_light.conf b/novelwriter/assets/themes/tango_light.conf new file mode 100644 index 00000000..6ba5566a --- /dev/null +++ b/novelwriter/assets/themes/tango_light.conf @@ -0,0 +1,81 @@ +[Main] +name = Tango Light +mode = light +author = Veronica Berglyd Olsen (adaptation) + +## +# Colours: +# Background = #eeeeec +# Foreground = #2e3436 +# Comment = 8f8f8d : 143, 143, 141 +# Red = #a40000 +# Orange = c4a000 : 196, 160, 0 +# Yellow = fce94f : 252, 233, 79 +# Green = 8ae234 : 138, 226, 52 +# Cyan = 34e2e2 : 52, 226, 226 +# Blue = 3465a4 : 114, 159, 207 +# Purple = ad7fa8 : 173, 127, 168 +## + +[Base] +default = #2e3436 +faded = #888a85 +red = #a40000 +orange = #ce5c00 +yellow = #c4a000 +green = #4e9a06 +aqua = #069a9a +blue = #204a87 +purple = #5c3566 + +[Project] +root = blue +folder = yellow +file = default +title = green +chapter = red +scene = blue +note = yellow + +[Palette] +window = #d3d7cf +windowtext = default +base = #eeeeec +alternatebase = #e0e0e0 +text = default +tooltipbase = #ffffc0 +tooltiptext = #15150d +button = #d3d7cf +buttontext = default +brighttext = #d3d7cf +highlight = #3087c6 +highlightedtext = #ffffff +link = blue +linkvisited = blue + +[GUI] +helptext = #8f5902 +fadedtext = faded +errortext = red + +[Syntax] +background = #eeeeec +text = default +link = blue +headertext = blue +headertag = blue, 160 +emphasis = orange +dialog = green +altdialog = yellow +note = #a78800 +hidden = faded +shortcode = blue +keyword = red +tag = purple +value = red +optional = blue +spellcheckline = red +errorline = green +replacetag = cyan +modifier = blue +texthighlight = yellow, 96 From d0f11a25956b94717c42f1eae67e7b6e1b7eaea9 Mon Sep 17 00:00:00 2001 From: Veronica Berglyd Olsen <1619840+vkbo@users.noreply.github.com> Date: Mon, 2 Jun 2025 20:05:52 +0200 Subject: [PATCH 07/20] Fix a few inconsistencies --- novelwriter/assets/themes/default.conf | 3 -- novelwriter/assets/themes/default_light.conf | 44 +++++++++---------- novelwriter/assets/themes/light_owl.conf | 40 ++++++++--------- novelwriter/assets/themes/night_owl.conf | 40 ++++++++--------- novelwriter/assets/themes/tango_dark.conf | 40 ++++++++--------- novelwriter/assets/themes/tango_light.conf | 40 ++++++++--------- novelwriter/assets/themes/tomorrow.conf | 8 ++-- novelwriter/assets/themes/tomorrow_night.conf | 1 + 8 files changed, 107 insertions(+), 109 deletions(-) delete mode 100644 novelwriter/assets/themes/default.conf diff --git a/novelwriter/assets/themes/default.conf b/novelwriter/assets/themes/default.conf deleted file mode 100644 index 9cd9cd5b..00000000 --- a/novelwriter/assets/themes/default.conf +++ /dev/null @@ -1,3 +0,0 @@ -[Main] -name = Qt Default Theme -description = Qt standard colours diff --git a/novelwriter/assets/themes/default_light.conf b/novelwriter/assets/themes/default_light.conf index c4496d13..0c309a3c 100644 --- a/novelwriter/assets/themes/default_light.conf +++ b/novelwriter/assets/themes/default_light.conf @@ -34,8 +34,8 @@ windowtext = #000000 base = #ffffff alternatebase = #e0e0e0 text = #000000 -tooltipbase = #ffffdc -tooltiptext = #000000 +tooltipbase = #ffffc0 +tooltiptext = #15150d button = #efefef buttontext = #000000 brighttext = #ffffff @@ -50,23 +50,23 @@ fadedtext = #6c6c6c errortext = red [Syntax] -background = #ffffff -text = #000000 -link = blue -headertext = green -headertag = green, 160 -emphasis = orange -dialog = blue -altdialog = blue -note = yellow -hidden = faded -shortcode = green -keyword = red -tag = green -value = blue -optional = green -spellcheckline = red -errorline = green -replacetag = green -modifier = green -texthighlight = #c8c80060 +background = #ffffff +text = #000000 +link = blue +headertext = green +headertag = green, 160 +emphasis = orange +dialog = blue +altdialog = blue +note = yellow +hidden = faded +shortcode = green +keyword = red +tag = green +value = blue +optional = green +spellcheckline = red +errorline = green +replacetag = green +modifier = green +texthighlight = #c8c80060 diff --git a/novelwriter/assets/themes/light_owl.conf b/novelwriter/assets/themes/light_owl.conf index d91cf0ba..f72b8d70 100644 --- a/novelwriter/assets/themes/light_owl.conf +++ b/novelwriter/assets/themes/light_owl.conf @@ -69,23 +69,23 @@ fadedtext = faded errortext = red [Syntax] -background = #fbfbfb -text = default -link = blue -headertext = blue -headertag = blue, 160 -emphasis = orange -dialog = green -altdialog = yellow -note = #80764b -hidden = faded -shortcode = blue -keyword = red -tag = purple -value = orange -optional = blue -spellcheckline = red -errorline = green -replacetag = aqua -modifier = green -texthighlight = yellow, 96 +background = #fbfbfb +text = default +link = blue +headertext = blue +headertag = blue, 160 +emphasis = orange +dialog = green +altdialog = yellow +note = #80764b +hidden = faded +shortcode = blue +keyword = red +tag = purple +value = orange +optional = blue +spellcheckline = red +errorline = green +replacetag = aqua +modifier = green +texthighlight = yellow, 96 diff --git a/novelwriter/assets/themes/night_owl.conf b/novelwriter/assets/themes/night_owl.conf index a5f0a02b..0d176c45 100644 --- a/novelwriter/assets/themes/night_owl.conf +++ b/novelwriter/assets/themes/night_owl.conf @@ -69,23 +69,23 @@ fadedtext = faded errortext = red [Syntax] -background = #011627 -text = default -link = blue -headertext = blue -headertag = blue, 160 -emphasis = orange -dialog = green -altdialog = yellow -note = #fff9ca -hidden = faded -shortcode = blue -keyword = red -tag = purple -value = orange -optional = blue -spellcheckline = red -errorline = green -replacetag = aqua -modifier = green -texthighlight = yellow, 96 +background = #011627 +text = default +link = blue +headertext = blue +headertag = blue, 160 +emphasis = orange +dialog = green +altdialog = yellow +note = #fff9ca +hidden = faded +shortcode = blue +keyword = red +tag = purple +value = orange +optional = blue +spellcheckline = red +errorline = green +replacetag = aqua +modifier = green +texthighlight = yellow, 96 diff --git a/novelwriter/assets/themes/tango_dark.conf b/novelwriter/assets/themes/tango_dark.conf index 873e7f11..ca0ba841 100644 --- a/novelwriter/assets/themes/tango_dark.conf +++ b/novelwriter/assets/themes/tango_dark.conf @@ -59,23 +59,23 @@ fadedtext = faded errortext = red [Syntax] -background = #2e3436 -text = default -link = blue -headertext = blue -headertag = blue, 160 -emphasis = orange -dialog = green -altdialog = yellow -note = #fcf2a4 -hidden = faded -shortcode = blue -keyword = red -tag = purple -value = red -optional = blue -spellcheckline = red -errorline = green -replacetag = cyan -modifier = blue -texthighlight = yellow, 96 +background = #2e3436 +text = default +link = blue +headertext = blue +headertag = blue, 160 +emphasis = orange +dialog = green +altdialog = yellow +note = #fcf2a4 +hidden = faded +shortcode = blue +keyword = red +tag = purple +value = red +optional = blue +spellcheckline = red +errorline = green +replacetag = cyan +modifier = blue +texthighlight = yellow, 96 diff --git a/novelwriter/assets/themes/tango_light.conf b/novelwriter/assets/themes/tango_light.conf index 6ba5566a..174b0571 100644 --- a/novelwriter/assets/themes/tango_light.conf +++ b/novelwriter/assets/themes/tango_light.conf @@ -59,23 +59,23 @@ fadedtext = faded errortext = red [Syntax] -background = #eeeeec -text = default -link = blue -headertext = blue -headertag = blue, 160 -emphasis = orange -dialog = green -altdialog = yellow -note = #a78800 -hidden = faded -shortcode = blue -keyword = red -tag = purple -value = red -optional = blue -spellcheckline = red -errorline = green -replacetag = cyan -modifier = blue -texthighlight = yellow, 96 +background = #eeeeec +text = default +link = blue +headertext = blue +headertag = blue, 160 +emphasis = orange +dialog = green +altdialog = yellow +note = #a78800 +hidden = faded +shortcode = blue +keyword = red +tag = purple +value = red +optional = blue +spellcheckline = red +errorline = green +replacetag = cyan +modifier = blue +texthighlight = yellow, 96 diff --git a/novelwriter/assets/themes/tomorrow.conf b/novelwriter/assets/themes/tomorrow.conf index ab49754b..2b734209 100644 --- a/novelwriter/assets/themes/tomorrow.conf +++ b/novelwriter/assets/themes/tomorrow.conf @@ -53,11 +53,11 @@ windowtext = #000000 base = #ffffff alternatebase = #d6d6d6 text = #000000 -tooltipbase = #ffffdc -tooltiptext = #000000 -button = #ffffff +tooltipbase = #ffffc0 +tooltiptext = #15150d +button = #efefef buttontext = #000000 -brighttext = #ffffff +brighttext = #efefef highlight = blue highlightedtext = #ffffff link = blue diff --git a/novelwriter/assets/themes/tomorrow_night.conf b/novelwriter/assets/themes/tomorrow_night.conf index 16290bf0..27abd454 100644 --- a/novelwriter/assets/themes/tomorrow_night.conf +++ b/novelwriter/assets/themes/tomorrow_night.conf @@ -6,6 +6,7 @@ credit = Chris Kempson (color theme) url = https://github.com/chriskempson/tomorrow-theme license = MIT License licenseurl = https://github.com/chriskempson/tomorrow-theme/blob/master/LICENSE.md + ## # Theme: Tomorrow Night # Source: https://github.com/chriskempson/tomorrow-theme From 55e601cf9d04689682ccce645217af3ef20c00d3 Mon Sep 17 00:00:00 2001 From: Veronica Berglyd Olsen <1619840+vkbo@users.noreply.github.com> Date: Mon, 2 Jun 2025 20:18:19 +0200 Subject: [PATCH 08/20] Merge and update the grey themes --- novelwriter/assets/syntax/grey_dark.conf | 29 --------- novelwriter/assets/syntax/grey_light.conf | 29 --------- novelwriter/assets/themes/default_dark.conf | 2 +- novelwriter/assets/themes/grey_dark.conf | 71 +++++++++++++++++++++ novelwriter/assets/themes/grey_light.conf | 71 +++++++++++++++++++++ 5 files changed, 143 insertions(+), 59 deletions(-) delete mode 100644 novelwriter/assets/syntax/grey_dark.conf delete mode 100644 novelwriter/assets/syntax/grey_light.conf create mode 100644 novelwriter/assets/themes/grey_dark.conf create mode 100644 novelwriter/assets/themes/grey_light.conf diff --git a/novelwriter/assets/syntax/grey_dark.conf b/novelwriter/assets/syntax/grey_dark.conf deleted file mode 100644 index cc36478c..00000000 --- a/novelwriter/assets/syntax/grey_dark.conf +++ /dev/null @@ -1,29 +0,0 @@ -[Main] -name = Grey Dark -author = Veronica Berglyd Olsen -credit = Veronica Berglyd Olsen -url = https://github.com/vkbo/novelWriter -license = CC BY-SA 4.0 -licenseurl = https://creativecommons.org/licenses/by-sa/4.0/ - -[Syntax] -background = 54, 54, 54 -text = 200, 200, 200 -link = 200, 200, 200 -headertext = 225, 225, 225 -headertag = 225, 225, 225, 160 -emphasis = 200, 200, 200 -dialog = 200, 200, 200 -altdialog = 200, 200, 200 -note = 200, 200, 200 -hidden = 150, 150, 150 -shortcode = 225, 225, 225 -keyword = 225, 225, 225 -tag = 200, 200, 200 -value = 200, 200, 200 -optional = 225, 225, 225 -spellcheckline = 200, 46, 0 -errorline = 46, 200, 0 -replacetag = 225, 225, 225 -modifier = 225, 225, 225 -texthighlight = 255, 255, 255, 64 diff --git a/novelwriter/assets/syntax/grey_light.conf b/novelwriter/assets/syntax/grey_light.conf deleted file mode 100644 index 80a8a01c..00000000 --- a/novelwriter/assets/syntax/grey_light.conf +++ /dev/null @@ -1,29 +0,0 @@ -[Main] -name = Grey Light -author = Veronica Berglyd Olsen -credit = Veronica Berglyd Olsen -url = https://github.com/vkbo/novelWriter -license = CC BY-SA 4.0 -licenseurl = https://creativecommons.org/licenses/by-sa/4.0/ - -[Syntax] -background = 255, 255, 255 -text = 20, 20, 20 -link = 20, 20, 20 -headertext = 0, 0, 0 -headertag = 0, 0, 0, 160 -emphasis = 20, 20, 20 -dialog = 20, 20, 20 -altdialog = 20, 20, 20 -note = 20, 20, 20 -hidden = 100, 100, 100 -shortcode = 0, 0, 0 -keyword = 0, 0, 0 -tag = 20, 20, 20 -value = 20, 20, 20 -optional = 0, 0, 0 -spellcheckline = 200, 0, 0 -errorline = 0, 150, 0 -replacetag = 0, 0, 0 -modifier = 0, 0, 0 -texthighlight = 0, 0, 0, 64 diff --git a/novelwriter/assets/themes/default_dark.conf b/novelwriter/assets/themes/default_dark.conf index 7b0c3922..35acdb4c 100644 --- a/novelwriter/assets/themes/default_dark.conf +++ b/novelwriter/assets/themes/default_dark.conf @@ -46,7 +46,7 @@ linkvisited = blue [GUI] helptext = #a4a4a4 -fadedtext = #949494 +fadedtext = faded errortext = red [Syntax] diff --git a/novelwriter/assets/themes/grey_dark.conf b/novelwriter/assets/themes/grey_dark.conf new file mode 100644 index 00000000..d8c4a1fd --- /dev/null +++ b/novelwriter/assets/themes/grey_dark.conf @@ -0,0 +1,71 @@ +[Main] +name = Grey Dark +mode = dark +author = Veronica Berglyd Olsen +credit = Veronica Berglyd Olsen +url = https://github.com/vkbo/novelWriter +license = CC BY-SA 4.0 +licenseurl = https://creativecommons.org/licenses/by-sa/4.0/ + +[Base] +default = #cccccc +faded = #949494 +red = #f2777a +orange = #f99139 +yellow = #ffcc66 +green = #99cc99 +aqua = #66cccc +blue = #6699cc +purple = #cc99cc + +[Project] +root = blue +folder = yellow +file = default +title = green +chapter = red +scene = blue +note = yellow + +[Palette] +window = #363636 +windowtext = default +base = #3e3e3e +alternatebase = #4e4e4e +text = default +tooltipbase = #ffffc0 +tooltiptext = #15150d +button = #3e3e3e +buttontext = default +brighttext = #3e3e3e +highlight = #2c98f7 +highlightedtext = #ffffff +link = blue +linkvisited = blue + +[GUI] +helptext = #a4a4a4 +fadedtext = faded +errortext = red + +[Syntax] +background = #363636 +text = #c8c8c8 +link = #c8c8c8 +headertext = #e1e1e1 +headertag = #e1e1e1a0 +emphasis = #c8c8c8 +dialog = #c8c8c8 +altdialog = #c8c8c8 +note = #c8c8c8 +hidden = faded +shortcode = #e1e1e1 +keyword = #e1e1e1 +tag = #c8c8c8 +value = #c8c8c8 +optional = #e1e1e1 +spellcheckline = red +errorline = green +replacetag = #e1e1e1 +modifier = #e1e1e1 +texthighlight = #ffffff40 diff --git a/novelwriter/assets/themes/grey_light.conf b/novelwriter/assets/themes/grey_light.conf new file mode 100644 index 00000000..ffa8fe61 --- /dev/null +++ b/novelwriter/assets/themes/grey_light.conf @@ -0,0 +1,71 @@ +[Main] +name = Grey Light +mode = light +author = Veronica Berglyd Olsen +credit = Veronica Berglyd Olsen +url = https://github.com/vkbo/novelWriter +license = CC BY-SA 4.0 +licenseurl = https://creativecommons.org/licenses/by-sa/4.0/ + +[Base] +default = #303030 +faded = #6c6c6c +red = #a62a2d +orange = #b36829 +yellow = #a68542 +green = #296629 +aqua = #269999 +blue = #3a70a6 +purple = #b35ab3 + +[Project] +root = blue +folder = yellow +file = default +title = green +chapter = red +scene = blue +note = yellow + +[Palette] +window = #efefef +windowtext = default +base = #ffffff +alternatebase = #e0e0e0 +text = default +tooltipbase = #ffffc0 +tooltiptext = #15150d +button = #efefef +buttontext = default +brighttext = #ffffff +highlight = #3087c6 +highlightedtext = #ffffff +link = blue +linkvisited = blue + +[GUI] +helptext = #5c5c5c +fadedtext = faded +errortext = red + +[Syntax] +background = #ffffff +text = #141414 +link = #141414 +headertext = #000000 +headertag = #000000a0 +emphasis = #141414 +dialog = #141414 +altdialog = #141414 +note = #141414 +hidden = faded +shortcode = #000000 +keyword = #000000 +tag = #141414 +value = #141414 +optional = #000000 +spellcheckline = red +errorline = green +replacetag = #000000 +modifier = #000000 +texthighlight = #00000040 From 10475f32fbee62724b3d65832700f295f23968a8 Mon Sep 17 00:00:00 2001 From: Veronica Berglyd Olsen <1619840+vkbo@users.noreply.github.com> Date: Mon, 2 Jun 2025 20:21:35 +0200 Subject: [PATCH 09/20] Remove references to syntax themes --- CREDITS.md | 4 ++-- novelwriter/assets/text/credits_en.htm | 4 ++-- novelwriter/config.py | 3 +-- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/CREDITS.md b/CREDITS.md index 9ac3b34a..b3c527a5 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -62,8 +62,8 @@ Some of the assets bundled with novelWriter were adapted from the following sour * **Material Symbols** icons by Google Inc (Apache 2.0) * **Remix** icons by RemixIcon (Apache 2.0) * **Font Awesome** icons by Fonticons Inc (CC BY 4.0) -* **Tomorrow** syntax themes by Chris Kempson (MIT License) -* **Owl** syntax themes by Sarah Drasner (MIT License) +* **Tomorrow** themes by Chris Kempson (MIT License) +* **Owl** themes by Sarah Drasner (MIT License) * **Solarized** themes by Ethan Schoonover (MIT License) * **Cyberpunk Night** theme by Anders Lemvigh (CC BY-SA 4.0) * **Dracula** theme by Zeno Rocha (MIT License) diff --git a/novelwriter/assets/text/credits_en.htm b/novelwriter/assets/text/credits_en.htm index 88b3887d..33903616 100644 --- a/novelwriter/assets/text/credits_en.htm +++ b/novelwriter/assets/text/credits_en.htm @@ -75,8 +75,8 @@ more contributions are listed on the project's Members page.