From 8b02c95f51fedc8f3b5313dd876441e9f833e179 Mon Sep 17 00:00:00 2001 From: Veronica Berglyd Olsen <1619840+vkbo@users.noreply.github.com> Date: Sun, 26 Oct 2025 02:04:03 +0100 Subject: [PATCH] Add theme update handling to manuscript build settings --- novelwriter/dialogs/preferences.py | 10 +-- novelwriter/dialogs/projectsettings.py | 4 +- novelwriter/extensions/modified.py | 12 +-- novelwriter/extensions/pagedsidebar.py | 7 ++ novelwriter/tools/manuscript.py | 4 + novelwriter/tools/manussettings.py | 119 ++++++++++++++++++------- 6 files changed, 114 insertions(+), 42 deletions(-) diff --git a/novelwriter/dialogs/preferences.py b/novelwriter/dialogs/preferences.py index 71cfca38..1c96b7e1 100644 --- a/novelwriter/dialogs/preferences.py +++ b/novelwriter/dialogs/preferences.py @@ -158,7 +158,7 @@ class GuiPreferences(NDialog): self.mainForm.addGroupLabel(title, section) # Display Language - self.guiLocale = NComboBox(self) + self.guiLocale = NComboBox(self, scrollable=False) self.guiLocale.setMinimumWidth(200) for lang, name in CONFIG.listLanguages(CONFIG.LANG_NW): self.guiLocale.addItem(name, lang) @@ -170,9 +170,9 @@ class GuiPreferences(NDialog): ) # Colour Theme - self.lightTheme = NComboBox(self) + self.lightTheme = NComboBox(self, scrollable=False) self.lightTheme.setMinimumWidth(200) - self.darkTheme = NComboBox(self) + self.darkTheme = NComboBox(self, scrollable=False) self.darkTheme.setMinimumWidth(200) for key, theme in SHARED.theme.colourThemes.items(): if theme.dark: @@ -193,7 +193,7 @@ class GuiPreferences(NDialog): ) # Icon Theme - self.iconTheme = NComboBox(self) + self.iconTheme = NComboBox(self, scrollable=False) self.iconTheme.setMinimumWidth(200) for key, theme in SHARED.theme.iconCache.iconThemes.items(): self.iconTheme.addItem(theme.name, key) @@ -511,7 +511,7 @@ class GuiPreferences(NDialog): self.mainForm.addGroupLabel(title, section) # Spell Checking - self.spellLanguage = NComboBox(self) + self.spellLanguage = NComboBox(self, scrollable=False) self.spellLanguage.setMinimumWidth(200) if CONFIG.hasEnchant: diff --git a/novelwriter/dialogs/projectsettings.py b/novelwriter/dialogs/projectsettings.py index dcb7f8de..37704f70 100644 --- a/novelwriter/dialogs/projectsettings.py +++ b/novelwriter/dialogs/projectsettings.py @@ -257,7 +257,7 @@ class _SettingsPage(NScrollableForm): # Project Language projLang = data.language or CONFIG.guiLocale - self.projLang = NComboBox(self) + self.projLang = NComboBox(self, scrollable=False) self.projLang.setMinimumWidth(200) for tag, language in CONFIG.listLanguages(CONFIG.LANG_PROJ): self.projLang.addItem(language, tag) @@ -269,7 +269,7 @@ class _SettingsPage(NScrollableForm): ) # Spell Check Language - self.spellLang = NComboBox(self) + self.spellLang = NComboBox(self, scrollable=False) self.spellLang.setMinimumWidth(200) self.spellLang.addItem(self.tr("Default"), "None") if CONFIG.hasEnchant: diff --git a/novelwriter/extensions/modified.py b/novelwriter/extensions/modified.py index abc12da1..90d0ffbb 100644 --- a/novelwriter/extensions/modified.py +++ b/novelwriter/extensions/modified.py @@ -125,14 +125,16 @@ class NComboBox(QComboBox): window of many widgets. """ - def __init__(self, parent: QWidget | None = None, maxItems: int = 15) -> None: + def __init__( + self, parent: QWidget | None = None, maxItems: int = 15, scrollable: bool = True + ) -> None: super().__init__(parent=parent) self.setFocusPolicy(Qt.FocusPolicy.StrongFocus) self.setMaxVisibleItems(maxItems) - - # The style sheet disables Fusion style pop-up mode on some platforms - # and allows for scrolling of long lists of items - self.setStyleSheet("QComboBox {combobox-popup: 0;}") + if not scrollable: + # The style sheet disables Fusion style pop-up mode on some + # platforms and allows for scrolling of long lists of items + self.setStyleSheet("QComboBox {combobox-popup: 0;}") def wheelEvent(self, event: QWheelEvent) -> None: """Only capture the mouse wheel if the widget has focus.""" diff --git a/novelwriter/extensions/pagedsidebar.py b/novelwriter/extensions/pagedsidebar.py index fd332495..04c284ed 100644 --- a/novelwriter/extensions/pagedsidebar.py +++ b/novelwriter/extensions/pagedsidebar.py @@ -72,6 +72,9 @@ class NPagedSideBar(QToolBar): def setLabelColor(self, color: QColor) -> None: """Set the text color for the labels.""" self._labelCol = color + for widget in self.children(): + if isinstance(widget, _NPagedToolLabel): + widget.setTextColor(color) def addLabel(self, text: str) -> None: """Add a new label to the toolbar.""" @@ -188,6 +191,10 @@ class _NPagedToolLabel(QLabel): self._textCol = textColor or self.palette().text().color() + def setTextColor(self, textColor: QColor | None = None) -> None: + """Set a new text colour.""" + self._textCol = textColor or self.palette().text().color() + def paintEvent(self, event: QPaintEvent) -> None: """Overload the paint event to draw a simple, left aligned text label that matches the button style. diff --git a/novelwriter/tools/manuscript.py b/novelwriter/tools/manuscript.py index 9ad1557e..9646140e 100644 --- a/novelwriter/tools/manuscript.py +++ b/novelwriter/tools/manuscript.py @@ -286,6 +286,10 @@ class GuiManuscript(NToolDialog): self.buildOutline.updateTheme() self.docPreview.updateTheme() + for obj in SHARED.mainGui.children(): + if isinstance(obj, GuiBuildSettings): + obj.updateTheme() + ## # Events ## diff --git a/novelwriter/tools/manussettings.py b/novelwriter/tools/manussettings.py index 407eff5e..318c21f1 100644 --- a/novelwriter/tools/manussettings.py +++ b/novelwriter/tools/manussettings.py @@ -154,6 +154,7 @@ class GuiBuildSettings(NToolDialog): self.outerBox.setSpacing(12) self.setLayout(self.outerBox) + self.updateTheme(init=True) # Set Default Tab self.sidebar.setSelected(self.OPT_FILTERS) @@ -170,6 +171,20 @@ class GuiBuildSettings(NToolDialog): self.optTabHeadings.loadContent() self.optTabFormatting.loadContent() + def updateTheme(self, *, init: bool = False) -> None: + """Update theme elements.""" + if not init: + self.btnApply.updateIcon() + self.btnSave.updateIcon() + self.btnClose.updateIcon() + + self.optTabSelect.updateTheme() + self.optTabHeadings.updateTheme() + self.optTabFormatting.updateTheme() + + self.titleLabel.setTextColors(color=SHARED.theme.helpText) + self.sidebar.setLabelColor(SHARED.theme.helpText) + ## # Properties ## @@ -326,15 +341,13 @@ class _FilterTab(NFixedPage): self.includedButton = NIconToolButton(self, iSz) self.includedButton.setToolTip(self.tr("Always included")) - self.includedButton.setIcon(self._statusFlags[self.F_INCLUDED]) self.includedButton.clicked.connect(qtLambda(self._setSelectedMode, self.F_INCLUDED)) self.excludedButton = NIconToolButton(self, iSz) self.excludedButton.setToolTip(self.tr("Always excluded")) - self.excludedButton.setIcon(self._statusFlags[self.F_EXCLUDED]) self.excludedButton.clicked.connect(qtLambda(self._setSelectedMode, self.F_EXCLUDED)) - self.resetButton = NIconToolButton(self, iSz, "revert", "green") + self.resetButton = NIconToolButton(self, iSz) self.resetButton.setToolTip(self.tr("Reset to default")) self.resetButton.clicked.connect(qtLambda(self._setSelectedMode, self.F_FILTERED)) @@ -376,6 +389,7 @@ class _FilterTab(NFixedPage): pOptions.getInt("GuiBuildSettings", "filterWidth", 300), ]) + self.updateTheme(init=True) self.setCentralWidget(self.mainSplit) def loadContent(self) -> None: @@ -389,6 +403,18 @@ class _FilterTab(NFixedPage): m, n = (sizes[0], sizes[1]) if len(sizes) >= 2 else (0, 0) return m, n + def updateTheme(self, *, init: bool = False) -> None: + """Update theme elements.""" + if not init: + self._statusFlags[self.F_FILTERED] = SHARED.theme.getIcon("filter", "orange") + self._statusFlags[self.F_INCLUDED] = SHARED.theme.getIcon("pin", "blue") + self._statusFlags[self.F_EXCLUDED] = SHARED.theme.getIcon("exclude", "red") + self.loadContent() + + self.includedButton.setIcon(self._statusFlags[self.F_INCLUDED]) + self.excludedButton.setIcon(self._statusFlags[self.F_EXCLUDED]) + self.resetButton.setThemeIcon("revert", "green") + ## # Slots ## @@ -555,7 +581,7 @@ class _HeadingsTab(NScrollablePage): self.lblPart = QLabel(self._build.getLabel("headings.fmtPart"), self) self.fmtPart = QLineEdit("", self) self.fmtPart.setReadOnly(True) - self.btnPart = NIconToolButton(self, iSz, "edit", "green") + self.btnPart = NIconToolButton(self, iSz) self.btnPart.clicked.connect(qtLambda(self._editHeading, self.EDIT_TITLE)) self.swtPart = NSwitch(self, height=iPx) self.hdePart = QLabel(trHide, self) @@ -572,7 +598,7 @@ class _HeadingsTab(NScrollablePage): self.lblChapter = QLabel(self._build.getLabel("headings.fmtChapter"), self) self.fmtChapter = QLineEdit("", self) self.fmtChapter.setReadOnly(True) - self.btnChapter = NIconToolButton(self, iSz, "edit", "green") + self.btnChapter = NIconToolButton(self, iSz) self.btnChapter.clicked.connect(qtLambda(self._editHeading, self.EDIT_CHAPTER)) self.swtChapter = NSwitch(self, height=iPx) self.hdeChapter = QLabel(trHide, self) @@ -589,7 +615,7 @@ class _HeadingsTab(NScrollablePage): self.lblUnnumbered = QLabel(self._build.getLabel("headings.fmtUnnumbered"), self) self.fmtUnnumbered = QLineEdit("", self) self.fmtUnnumbered.setReadOnly(True) - self.btnUnnumbered = NIconToolButton(self, iSz, "edit", "green") + self.btnUnnumbered = NIconToolButton(self, iSz) self.btnUnnumbered.clicked.connect(qtLambda(self._editHeading, self.EDIT_UNNUM)) self.swtUnnumbered = NSwitch(self, height=iPx) self.hdeUnnumbered = QLabel(trHide, self) @@ -606,7 +632,7 @@ class _HeadingsTab(NScrollablePage): self.lblScene = QLabel(self._build.getLabel("headings.fmtScene"), self) self.fmtScene = QLineEdit("", self) self.fmtScene.setReadOnly(True) - self.btnScene = NIconToolButton(self, iSz, "edit", "green") + self.btnScene = NIconToolButton(self, iSz) self.btnScene.clicked.connect(qtLambda(self._editHeading, self.EDIT_SCENE)) self.swtScene = NSwitch(self, height=iPx) self.hdeScene = QLabel(trHide, self) @@ -623,7 +649,7 @@ class _HeadingsTab(NScrollablePage): self.lblAScene = QLabel(self._build.getLabel("headings.fmtAltScene"), self) self.fmtAScene = QLineEdit("", self) self.fmtAScene.setReadOnly(True) - self.btnAScene = NIconToolButton(self, iSz, "edit", "green") + self.btnAScene = NIconToolButton(self, iSz) self.btnAScene.clicked.connect(qtLambda(self._editHeading, self.EDIT_HSCENE)) self.swtAScene = NSwitch(self, height=iPx) self.hdeAScene = QLabel(trHide, self) @@ -640,7 +666,7 @@ class _HeadingsTab(NScrollablePage): self.lblSection = QLabel(self._build.getLabel("headings.fmtSection"), self) self.fmtSection = QLineEdit("", self) self.fmtSection.setReadOnly(True) - self.btnSection = NIconToolButton(self, iSz, "edit", "green") + self.btnSection = NIconToolButton(self, iSz) self.btnSection.clicked.connect(qtLambda(self._editHeading, self.EDIT_SECTION)) self.swtSection = NSwitch(self, height=iPx) self.hdeSection = QLabel(trHide, self) @@ -774,8 +800,21 @@ class _HeadingsTab(NScrollablePage): self.outerBox.addLayout(self.layoutMatrix) self.outerBox.addStretch(1) + self.updateTheme() self.setCentralLayout(self.outerBox) + def updateTheme(self) -> None: + """Update theme elements.""" + self.btnPart.setThemeIcon("edit", "green") + self.btnChapter.setThemeIcon("edit", "green") + self.btnUnnumbered.setThemeIcon("edit", "green") + self.btnScene.setThemeIcon("edit", "green") + self.btnAScene.setThemeIcon("edit", "green") + self.btnSection.setThemeIcon("edit", "green") + + self.formSyntax.initHighlighter() + self.formSyntax.rehighlight() + def loadContent(self) -> None: """Populate the widgets.""" def fmtBreak(text: str) -> str: @@ -907,10 +946,14 @@ class _HeadingSyntaxHighlighter(QSyntaxHighlighter): def __init__(self, document: QTextDocument | None) -> None: super().__init__(document) - syntax = SHARED.theme.syntaxTheme self._fmtSymbol = QTextCharFormat() - self._fmtSymbol.setForeground(syntax.head) self._fmtFormat = QTextCharFormat() + self.initHighlighter() + + def initHighlighter(self) -> None: + """Update theme elements.""" + syntax = SHARED.theme.syntaxTheme + self._fmtSymbol.setForeground(syntax.head) self._fmtFormat.setForeground(syntax.emph) def highlightBlock(self, text: str) -> None: @@ -936,6 +979,7 @@ class _FormattingTab(NScrollableForm): self.setHelpTextStyle(SHARED.theme.helpText) self.buildForm() + self.updateTheme() def buildForm(self) -> None: """Build the formatting form.""" @@ -979,7 +1023,7 @@ class _FormattingTab(NScrollableForm): lambda keyword=keyword: self._updateIgnoredKeywords(keyword) ) - self.ignoredKeywordsButton = NIconToolButton(self, iSz, "add", "green") + self.ignoredKeywordsButton = NIconToolButton(self, iSz) self.ignoredKeywordsButton.setMenu(self.mnKeywords) self.addRow( self._build.getLabel("text.ignoredKeywords"), self.ignoredKeywords, @@ -1001,7 +1045,7 @@ class _FormattingTab(NScrollableForm): # Text Font self.textFont = QLineEdit(self) self.textFont.setReadOnly(True) - self.btnTextFont = NIconToolButton(self, iSz, "font") + self.btnTextFont = NIconToolButton(self, iSz) self.btnTextFont.clicked.connect(self._selectFont) self.addRow( self._build.getLabel("format.textFont"), self.textFont, @@ -1060,12 +1104,12 @@ class _FormattingTab(NScrollableForm): self._sidebar.addButton(title, section) self.addGroupLabel(title, section) - pixT = SHARED.theme.getPixmap("margin_top", (iPx, iPx)) - pixB = SHARED.theme.getPixmap("margin_bottom", (iPx, iPx)) - pixL = SHARED.theme.getPixmap("margin_left", (iPx, iPx)) - pixR = SHARED.theme.getPixmap("margin_right", (iPx, iPx)) - pixH = SHARED.theme.getPixmap("fit_height", (iPx, iPx)) - pixW = SHARED.theme.getPixmap("fit_width", (iPx, iPx)) + self.pixT = QLabel(self) + self.pixB = QLabel(self) + self.pixL = QLabel(self) + self.pixR = QLabel(self) + self.pixH = QLabel(self) + self.pixW = QLabel(self) # Title self.titleMarginT = NDoubleSpinBox(self) @@ -1076,7 +1120,7 @@ class _FormattingTab(NScrollableForm): self.addRow( self._build.getLabel("format.titleMargin"), - [pixT, self.titleMarginT, 6, pixB, self.titleMarginB], + [self.pixT, self.titleMarginT, 6, self.pixB, self.titleMarginB], unit="em", ) @@ -1089,7 +1133,7 @@ class _FormattingTab(NScrollableForm): self.addRow( self._build.getLabel("format.h1Margin"), - [pixT, self.h1MarginT, 6, pixB, self.h1MarginB], + [self.pixT, self.h1MarginT, 6, self.pixB, self.h1MarginB], unit="em", ) @@ -1102,7 +1146,7 @@ class _FormattingTab(NScrollableForm): self.addRow( self._build.getLabel("format.h2Margin"), - [pixT, self.h2MarginT, 6, pixB, self.h2MarginB], + [self.pixT, self.h2MarginT, 6, self.pixB, self.h2MarginB], unit="em", ) @@ -1115,7 +1159,7 @@ class _FormattingTab(NScrollableForm): self.addRow( self._build.getLabel("format.h3Margin"), - [pixT, self.h3MarginT, 6, pixB, self.h3MarginB], + [self.pixT, self.h3MarginT, 6, self.pixB, self.h3MarginB], unit="em", ) @@ -1128,7 +1172,7 @@ class _FormattingTab(NScrollableForm): self.addRow( self._build.getLabel("format.h4Margin"), - [pixT, self.h4MarginT, 6, pixB, self.h4MarginB], + [self.pixT, self.h4MarginT, 6, self.pixB, self.h4MarginB], unit="em", ) @@ -1141,7 +1185,7 @@ class _FormattingTab(NScrollableForm): self.addRow( self._build.getLabel("format.textMargin"), - [pixT, self.textMarginT, 6, pixB, self.textMarginB], + [self.pixT, self.textMarginT, 6, self.pixB, self.textMarginB], unit="em", ) @@ -1154,7 +1198,7 @@ class _FormattingTab(NScrollableForm): self.addRow( self._build.getLabel("format.sepMargin"), - [pixT, self.sepMarginT, 6, pixB, self.sepMarginB], + [self.pixT, self.sepMarginT, 6, self.pixB, self.sepMarginB], unit="em", ) @@ -1188,7 +1232,7 @@ class _FormattingTab(NScrollableForm): self.addRow( self._build.getLabel("format.pageSize"), - [self.pageSize, 6, pixW, self.pageWidth, 6, pixH, self.pageHeight], + [self.pageSize, 6, self.pixW, self.pageWidth, 6, self.pixH, self.pageHeight], ) # Page Margins @@ -1206,11 +1250,11 @@ class _FormattingTab(NScrollableForm): self.addRow( self._build.getLabel("format.pageMargins"), - [pixT, self.topMargin, 6, pixB, self.bottomMargin], + [self.pixT, self.topMargin, 6, self.pixB, self.bottomMargin], ) self.addRow( "", - [pixL, self.leftMargin, 6, pixR, self.rightMargin], + [self.pixL, self.leftMargin, 6, self.pixR, self.rightMargin], ) # Open Document @@ -1224,7 +1268,7 @@ class _FormattingTab(NScrollableForm): # Header self.odtPageHeader = QLineEdit(self) self.odtPageHeader.setMinimumWidth(200) - self.btnPageHeader = NIconToolButton(self, iSz, "revert", "green") + self.btnPageHeader = NIconToolButton(self, iSz) self.btnPageHeader.clicked.connect(self._resetPageHeader) self.addRow( self._build.getLabel("doc.pageHeader"), self.odtPageHeader, @@ -1264,6 +1308,21 @@ class _FormattingTab(NScrollableForm): # Finalise self.finalise() + def updateTheme(self) -> None: + """Update theme elements.""" + iPx = SHARED.theme.baseIconHeight + + self.ignoredKeywordsButton.setThemeIcon("add", "green") + self.btnTextFont.setThemeIcon("font") + self.btnPageHeader.setThemeIcon("revert", "green") + + self.pixT.setPixmap(SHARED.theme.getPixmap("margin_top", (iPx, iPx))) + self.pixB.setPixmap(SHARED.theme.getPixmap("margin_bottom", (iPx, iPx))) + self.pixL.setPixmap(SHARED.theme.getPixmap("margin_left", (iPx, iPx))) + self.pixR.setPixmap(SHARED.theme.getPixmap("margin_right", (iPx, iPx))) + self.pixH.setPixmap(SHARED.theme.getPixmap("fit_height", (iPx, iPx))) + self.pixW.setPixmap(SHARED.theme.getPixmap("fit_width", (iPx, iPx))) + def loadContent(self) -> None: """Populate the widgets.""" # Text Content