Manuscript theme update fix (#2545)

This commit is contained in:
Veronica Berglyd Olsen
2025-10-26 03:20:40 +01:00
committed by GitHub
22 changed files with 281 additions and 94 deletions
+2
View File
@@ -552,6 +552,8 @@ class NWProject:
def updateTheme(self) -> None: def updateTheme(self) -> None:
"""Update theme elements.""" """Update theme elements."""
logger.debug("Theme Update: NWProject")
self._data.itemStatus.refreshIcons() self._data.itemStatus.refreshIcons()
self._data.itemImport.refreshIcons() self._data.itemImport.refreshIcons()
+5 -5
View File
@@ -158,7 +158,7 @@ class GuiPreferences(NDialog):
self.mainForm.addGroupLabel(title, section) self.mainForm.addGroupLabel(title, section)
# Display Language # Display Language
self.guiLocale = NComboBox(self) self.guiLocale = NComboBox(self, scrollable=True)
self.guiLocale.setMinimumWidth(200) self.guiLocale.setMinimumWidth(200)
for lang, name in CONFIG.listLanguages(CONFIG.LANG_NW): for lang, name in CONFIG.listLanguages(CONFIG.LANG_NW):
self.guiLocale.addItem(name, lang) self.guiLocale.addItem(name, lang)
@@ -170,9 +170,9 @@ class GuiPreferences(NDialog):
) )
# Colour Theme # Colour Theme
self.lightTheme = NComboBox(self) self.lightTheme = NComboBox(self, scrollable=True)
self.lightTheme.setMinimumWidth(200) self.lightTheme.setMinimumWidth(200)
self.darkTheme = NComboBox(self) self.darkTheme = NComboBox(self, scrollable=True)
self.darkTheme.setMinimumWidth(200) self.darkTheme.setMinimumWidth(200)
for key, theme in SHARED.theme.colourThemes.items(): for key, theme in SHARED.theme.colourThemes.items():
if theme.dark: if theme.dark:
@@ -193,7 +193,7 @@ class GuiPreferences(NDialog):
) )
# Icon Theme # Icon Theme
self.iconTheme = NComboBox(self) self.iconTheme = NComboBox(self, scrollable=True)
self.iconTheme.setMinimumWidth(200) self.iconTheme.setMinimumWidth(200)
for key, theme in SHARED.theme.iconCache.iconThemes.items(): for key, theme in SHARED.theme.iconCache.iconThemes.items():
self.iconTheme.addItem(theme.name, key) self.iconTheme.addItem(theme.name, key)
@@ -511,7 +511,7 @@ class GuiPreferences(NDialog):
self.mainForm.addGroupLabel(title, section) self.mainForm.addGroupLabel(title, section)
# Spell Checking # Spell Checking
self.spellLanguage = NComboBox(self) self.spellLanguage = NComboBox(self, scrollable=True)
self.spellLanguage.setMinimumWidth(200) self.spellLanguage.setMinimumWidth(200)
if CONFIG.hasEnchant: if CONFIG.hasEnchant:
+2 -2
View File
@@ -257,7 +257,7 @@ class _SettingsPage(NScrollableForm):
# Project Language # Project Language
projLang = data.language or CONFIG.guiLocale projLang = data.language or CONFIG.guiLocale
self.projLang = NComboBox(self) self.projLang = NComboBox(self, scrollable=True)
self.projLang.setMinimumWidth(200) self.projLang.setMinimumWidth(200)
for tag, language in CONFIG.listLanguages(CONFIG.LANG_PROJ): for tag, language in CONFIG.listLanguages(CONFIG.LANG_PROJ):
self.projLang.addItem(language, tag) self.projLang.addItem(language, tag)
@@ -269,7 +269,7 @@ class _SettingsPage(NScrollableForm):
) )
# Spell Check Language # Spell Check Language
self.spellLang = NComboBox(self) self.spellLang = NComboBox(self, scrollable=True)
self.spellLang.setMinimumWidth(200) self.spellLang.setMinimumWidth(200)
self.spellLang.addItem(self.tr("Default"), "None") self.spellLang.addItem(self.tr("Default"), "None")
if CONFIG.hasEnchant: if CONFIG.hasEnchant:
+2 -6
View File
@@ -27,7 +27,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
""" # noqa """ # noqa
from __future__ import annotations from __future__ import annotations
from PyQt6.QtGui import QColor, QFont, QPalette, QPixmap from PyQt6.QtGui import QColor, QFont, QPalette
from PyQt6.QtWidgets import ( from PyQt6.QtWidgets import (
QAbstractButton, QFrame, QHBoxLayout, QLabel, QLayout, QScrollArea, QAbstractButton, QFrame, QHBoxLayout, QLabel, QLayout, QScrollArea,
QVBoxLayout, QWidget QVBoxLayout, QWidget
@@ -170,7 +170,7 @@ class NScrollableForm(QScrollArea):
def addRow( def addRow(
self, self,
label: str | None, label: str | None,
widget: QWidget | list[QWidget | QPixmap | int], widget: QWidget | list[QWidget | int],
helpText: str = "", helpText: str = "",
unit: str | None = None, unit: str | None = None,
button: QWidget | None = None, button: QWidget | None = None,
@@ -187,10 +187,6 @@ class NScrollableForm(QScrollArea):
for item in widget: for item in widget:
if isinstance(item, QWidget): if isinstance(item, QWidget):
wBox.addWidget(item) wBox.addWidget(item)
elif isinstance(item, QPixmap):
icon = QLabel(self)
icon.setPixmap(item)
wBox.addWidget(icon)
elif isinstance(item, int): elif isinstance(item, int):
wBox.addSpacing(item) wBox.addSpacing(item)
qWidget = QWidget(self) qWidget = QWidget(self)
+15 -13
View File
@@ -125,14 +125,16 @@ class NComboBox(QComboBox):
window of many widgets. 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 = False
) -> None:
super().__init__(parent=parent) super().__init__(parent=parent)
self.setFocusPolicy(Qt.FocusPolicy.StrongFocus) self.setFocusPolicy(Qt.FocusPolicy.StrongFocus)
self.setMaxVisibleItems(maxItems) self.setMaxVisibleItems(maxItems)
if scrollable:
# The style sheet disables Fusion style pop-up mode on some platforms # The style sheet disables Fusion style pop-up mode on some
# and allows for scrolling of long lists of items # platforms and allows for scrolling of long lists of items
self.setStyleSheet("QComboBox {combobox-popup: 0;}") self.setStyleSheet("QComboBox {combobox-popup: 0;}")
def wheelEvent(self, event: QWheelEvent) -> None: def wheelEvent(self, event: QWheelEvent) -> None:
"""Only capture the mouse wheel if the widget has focus.""" """Only capture the mouse wheel if the widget has focus."""
@@ -214,10 +216,10 @@ class NPushButton(QPushButton):
self._color = color self._color = color
self.setText(text) self.setText(text)
self.setIconSize(iconSize) self.setIconSize(iconSize)
self.refreshIcon() self.updateIcon()
def refreshIcon(self) -> None: def updateIcon(self) -> None:
"""Reload the theme icon.""" """Update the theme icon."""
if self._icon: if self._icon:
self.setIcon(SHARED.theme.getIcon(self._icon, self._color)) self.setIcon(SHARED.theme.getIcon(self._icon, self._color))
@@ -239,9 +241,9 @@ class NIconToolButton(QToolButton):
if icon: if icon:
self.setThemeIcon(icon, color) self.setThemeIcon(icon, color)
def setThemeIcon(self, iconKey: str, color: str | None = None) -> None: def setThemeIcon(self, icon: str, color: str | None = None) -> None:
"""Set an icon from the current theme.""" """Set an icon from the current theme."""
self.setIcon(SHARED.theme.getIcon(iconKey, color)) self.setIcon(SHARED.theme.getIcon(icon, color))
class NIconToggleButton(QToolButton): class NIconToggleButton(QToolButton):
@@ -260,10 +262,10 @@ class NIconToggleButton(QToolButton):
if icon: if icon:
self.setThemeIcon(icon) self.setThemeIcon(icon)
def setThemeIcon(self, iconKey: str) -> None: def setThemeIcon(self, icon: str) -> None:
"""Set an icon from the current theme.""" """Set an icon from the current theme."""
iconSize = self.iconSize() size = self.iconSize()
self.setIcon(SHARED.theme.getToggleIcon(iconKey, (iconSize.width(), iconSize.height()))) self.setIcon(SHARED.theme.getToggleIcon(icon, (size.width(), size.height())))
class NClickableLabel(QLabel): class NClickableLabel(QLabel):
+7
View File
@@ -72,6 +72,9 @@ class NPagedSideBar(QToolBar):
def setLabelColor(self, color: QColor) -> None: def setLabelColor(self, color: QColor) -> None:
"""Set the text color for the labels.""" """Set the text color for the labels."""
self._labelCol = color self._labelCol = color
for widget in self.children():
if isinstance(widget, _NPagedToolLabel):
widget.setTextColor(color)
def addLabel(self, text: str) -> None: def addLabel(self, text: str) -> None:
"""Add a new label to the toolbar.""" """Add a new label to the toolbar."""
@@ -188,6 +191,10 @@ class _NPagedToolLabel(QLabel):
self._textCol = textColor or self.palette().text().color() 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: def paintEvent(self, event: QPaintEvent) -> None:
"""Overload the paint event to draw a simple, left aligned text """Overload the paint event to draw a simple, left aligned text
label that matches the button style. label that matches the button style.
+7 -5
View File
@@ -34,7 +34,7 @@ from novelwriter.types import QtNoPen, QtPaintAntiAlias, QtSizeFixed
class NSwitch(QAbstractButton): class NSwitch(QAbstractButton):
"""Custom: Toggle Switch.""" """Custom: Toggle Switch."""
__slots__ = ("_cOff", "_cOn", "_offset", "_rH", "_rR", "_xH", "_xR", "_xW") __slots__ = ("_offset", "_rH", "_rR", "_xH", "_xR", "_xW")
def __init__(self, parent: QWidget, height: int = 0) -> None: def __init__(self, parent: QWidget, height: int = 0) -> None:
super().__init__(parent=parent) super().__init__(parent=parent)
@@ -45,13 +45,11 @@ class NSwitch(QAbstractButton):
self._rH = self._xH - 4 self._rH = self._xH - 4
self._rR = self._xR - 2 self._rR = self._xR - 2
self._cOn = SHARED.theme.accentCol
self._cOff = self.palette().alternateBase()
self.setCheckable(True) self.setCheckable(True)
self.setSizePolicy(QtSizeFixed, QtSizeFixed) self.setSizePolicy(QtSizeFixed, QtSizeFixed)
self.setFixedWidth(self._xW) self.setFixedWidth(self._xW)
self.setFixedHeight(self._xH) self.setFixedHeight(self._xH)
self.setUpdatesEnabled(True)
self._offset = self._xR self._offset = self._xR
self.clicked.connect(self._onClick) self.clicked.connect(self._onClick)
@@ -96,7 +94,7 @@ class NSwitch(QAbstractButton):
painter.setOpacity(1.0 if self.isEnabled() else 0.5) painter.setOpacity(1.0 if self.isEnabled() else 0.5)
painter.setPen(palette.highlight().color() if self.hasFocus() else palette.mid().color()) painter.setPen(palette.highlight().color() if self.hasFocus() else palette.mid().color())
painter.setBrush(self._cOn if self.isChecked() else self._cOff) painter.setBrush(SHARED.theme.accentCol if self.isChecked() else palette.alternateBase())
painter.drawRoundedRect(0, 0, self._xW, self._xH, self._xR, self._xR) painter.drawRoundedRect(0, 0, self._xW, self._xH, self._xR, self._xR)
painter.setPen(QtNoPen) painter.setPen(QtNoPen)
@@ -110,6 +108,10 @@ class NSwitch(QAbstractButton):
self.setCursor(Qt.CursorShape.PointingHandCursor) self.setCursor(Qt.CursorShape.PointingHandCursor)
super().enterEvent(event) super().enterEvent(event)
##
# Internal Functions
##
@pyqtSlot(bool) @pyqtSlot(bool)
def _onClick(self, checked: bool) -> None: def _onClick(self, checked: bool) -> None:
"""Animate the toggle action.""" """Animate the toggle action."""
+12 -3
View File
@@ -292,6 +292,8 @@ class GuiDocEditor(QPlainTextEdit):
def updateTheme(self) -> None: def updateTheme(self) -> None:
"""Update theme elements.""" """Update theme elements."""
logger.debug("Theme Update: GuiDocEditor")
self.docSearch.updateTheme() self.docSearch.updateTheme()
self.docHeader.updateTheme() self.docHeader.updateTheme()
self.docFooter.updateTheme() self.docFooter.updateTheme()
@@ -2478,8 +2480,9 @@ class GuiDocToolBar(QWidget):
def updateTheme(self) -> None: def updateTheme(self) -> None:
"""Initialise GUI elements that depend on specific settings.""" """Initialise GUI elements that depend on specific settings."""
syntax = SHARED.theme.syntaxTheme logger.debug("Theme Update: GuiDocToolBar")
syntax = SHARED.theme.syntaxTheme
palette = self.palette() palette = self.palette()
palette.setColor(QPalette.ColorRole.Window, syntax.back) palette.setColor(QPalette.ColorRole.Window, syntax.back)
palette.setColor(QPalette.ColorRole.WindowText, syntax.text) palette.setColor(QPalette.ColorRole.WindowText, syntax.text)
@@ -2590,7 +2593,7 @@ class GuiDocEditSearch(QFrame):
# Buttons # Buttons
# ======= # =======
self.showReplace = NIconToggleButton(self, iSz, "unfold") self.showReplace = NIconToggleButton(self, iSz)
self.showReplace.toggled.connect(self._doToggleReplace) self.showReplace.toggled.connect(self._doToggleReplace)
self.searchButton = NIconToolButton(self, iSz) self.searchButton = NIconToolButton(self, iSz)
@@ -2716,8 +2719,9 @@ class GuiDocEditSearch(QFrame):
def updateTheme(self) -> None: def updateTheme(self) -> None:
"""Update theme elements.""" """Update theme elements."""
palette = QApplication.palette() logger.debug("Theme Update: GuiDocEditSearch")
palette = QApplication.palette()
self.setPalette(palette) self.setPalette(palette)
self.searchBox.setPalette(palette) self.searchBox.setPalette(palette)
self.replaceBox.setPalette(palette) self.replaceBox.setPalette(palette)
@@ -2732,6 +2736,7 @@ class GuiDocEditSearch(QFrame):
self.cancelSearch.setIcon(SHARED.theme.getIcon("search_cancel")) self.cancelSearch.setIcon(SHARED.theme.getIcon("search_cancel"))
self.searchButton.setThemeIcon("search", "green") self.searchButton.setThemeIcon("search", "green")
self.replaceButton.setThemeIcon("search_replace", "green") self.replaceButton.setThemeIcon("search_replace", "green")
self.showReplace.setThemeIcon("unfold")
# Set stylesheets # Set stylesheets
self.searchOpt.setStyleSheet("QToolBar {padding: 0;}") self.searchOpt.setStyleSheet("QToolBar {padding: 0;}")
@@ -2960,6 +2965,8 @@ class GuiDocEditHeader(QWidget):
def updateTheme(self) -> None: def updateTheme(self) -> None:
"""Update theme elements.""" """Update theme elements."""
logger.debug("Theme Update: GuiDocEditHeader")
self.tbButton.setThemeIcon("fmt_toolbar", "blue") self.tbButton.setThemeIcon("fmt_toolbar", "blue")
self.outlineButton.setThemeIcon("list", "blue") self.outlineButton.setThemeIcon("list", "blue")
self.searchButton.setThemeIcon("search", "blue") self.searchButton.setThemeIcon("search", "blue")
@@ -3149,6 +3156,8 @@ class GuiDocEditFooter(QWidget):
def updateTheme(self) -> None: def updateTheme(self) -> None:
"""Update theme elements.""" """Update theme elements."""
logger.debug("Theme Update: GuiDocEditFooter")
iPx = round(0.9*SHARED.theme.baseIconHeight) iPx = round(0.9*SHARED.theme.baseIconHeight)
self.linesIcon.setPixmap(SHARED.theme.getPixmap("lines", (iPx, iPx))) self.linesIcon.setPixmap(SHARED.theme.getPixmap("lines", (iPx, iPx)))
self.wordsIcon.setPixmap(SHARED.theme.getPixmap("stats", (iPx, iPx))) self.wordsIcon.setPixmap(SHARED.theme.getPixmap("stats", (iPx, iPx)))
+5 -1
View File
@@ -141,6 +141,7 @@ class GuiDocViewer(QTextBrowser):
def updateTheme(self) -> None: def updateTheme(self) -> None:
"""Update theme elements.""" """Update theme elements."""
logger.debug("Theme Update: GuiDocViewer")
self.docHeader.updateTheme() self.docHeader.updateTheme()
self.docFooter.updateTheme() self.docFooter.updateTheme()
@@ -724,6 +725,8 @@ class GuiDocViewHeader(QWidget):
def updateTheme(self) -> None: def updateTheme(self) -> None:
"""Update theme elements.""" """Update theme elements."""
logger.debug("Theme Update: GuiDocViewHeader")
self.outlineButton.setThemeIcon("list", "blue") self.outlineButton.setThemeIcon("list", "blue")
self.backButton.setThemeIcon("chevron_left", "blue") self.backButton.setThemeIcon("chevron_left", "blue")
self.forwardButton.setThemeIcon("chevron_right", "blue") self.forwardButton.setThemeIcon("chevron_right", "blue")
@@ -910,7 +913,8 @@ class GuiDocViewFooter(QWidget):
def updateTheme(self) -> None: def updateTheme(self) -> None:
"""Update theme elements.""" """Update theme elements."""
# Icons logger.debug("Theme Update: GuiDocViewFooter")
fPx = int(0.9*SHARED.theme.fontPixelSize) fPx = int(0.9*SHARED.theme.fontPixelSize)
bulletIcon = SHARED.theme.getToggleIcon("bullet", (fPx, fPx), "blue") bulletIcon = SHARED.theme.getToggleIcon("bullet", (fPx, fPx), "blue")
+6
View File
@@ -106,6 +106,8 @@ class GuiDocViewerPanel(QWidget):
def updateTheme(self, updateTabs: bool = True) -> None: def updateTheme(self, updateTabs: bool = True) -> None:
"""Update theme elements.""" """Update theme elements."""
logger.debug("Theme Update: GuiDocViewerPanel")
self.optsButton.setThemeIcon("more_vertical") self.optsButton.setThemeIcon("more_vertical")
self.optsButton.setStyleSheet(SHARED.theme.getStyleSheet(STYLES_MIN_TOOLBUTTON)) self.optsButton.setStyleSheet(SHARED.theme.getStyleSheet(STYLES_MIN_TOOLBUTTON))
self.mainTabs.setStyleSheet(SHARED.theme.getStyleSheet(STYLES_FLAT_TABS)) self.mainTabs.setStyleSheet(SHARED.theme.getStyleSheet(STYLES_FLAT_TABS))
@@ -270,6 +272,8 @@ class _ViewPanelBackRefs(QTreeWidget):
def updateTheme(self) -> None: def updateTheme(self) -> None:
"""Update theme elements.""" """Update theme elements."""
logger.debug("Theme Update: _ViewPanelBackRefs")
self._editIcon = SHARED.theme.getIcon("edit", "green") self._editIcon = SHARED.theme.getIcon("edit", "green")
self._viewIcon = SHARED.theme.getIcon("view", "blue") self._viewIcon = SHARED.theme.getIcon("view", "blue")
for i in range(self.topLevelItemCount()): for i in range(self.topLevelItemCount()):
@@ -400,6 +404,8 @@ class _ViewPanelKeyWords(QTreeWidget):
def updateTheme(self) -> None: def updateTheme(self) -> None:
"""Update theme elements.""" """Update theme elements."""
logger.debug("Theme Update: _ViewPanelKeyWords")
self._classIcon = SHARED.theme.getIcon(nwLabels.CLASS_ICON[self._class], "root") self._classIcon = SHARED.theme.getIcon(nwLabels.CLASS_ICON[self._class], "root")
self._editIcon = SHARED.theme.getIcon("edit", "green") self._editIcon = SHARED.theme.getIcon("edit", "green")
self._viewIcon = SHARED.theme.getIcon("view", "blue") self._viewIcon = SHARED.theme.getIcon("view", "blue")
+1
View File
@@ -216,6 +216,7 @@ class GuiItemDetails(QWidget):
def updateTheme(self) -> None: def updateTheme(self) -> None:
"""Update theme elements.""" """Update theme elements."""
logger.debug("Theme Update: GuiItemDetails")
self.updateViewBox(self._handle) self.updateViewBox(self._handle)
def updateViewBox(self, tHandle: str | None) -> None: def updateViewBox(self, tHandle: str | None) -> None:
+3 -2
View File
@@ -89,6 +89,7 @@ class GuiNovelView(QWidget):
def updateTheme(self) -> None: def updateTheme(self) -> None:
"""Update theme elements.""" """Update theme elements."""
logger.debug("Theme Update: GuiNovelView")
self.novelBar.updateTheme() self.novelBar.updateTheme()
def initSettings(self) -> None: def initSettings(self) -> None:
@@ -244,12 +245,12 @@ class GuiNovelToolBar(QWidget):
def updateTheme(self) -> None: def updateTheme(self) -> None:
"""Update theme elements.""" """Update theme elements."""
# Icons logger.debug("Theme Update: GuiNovelToolBar")
self.tbNovel.setThemeIcon("cls_novel", "red") self.tbNovel.setThemeIcon("cls_novel", "red")
self.tbRefresh.setThemeIcon("refresh", "green") self.tbRefresh.setThemeIcon("refresh", "green")
self.tbMore.setThemeIcon("more_vertical") self.tbMore.setThemeIcon("more_vertical")
# StyleSheets
buttonStyle = SHARED.theme.getStyleSheet(STYLES_MIN_TOOLBUTTON) buttonStyle = SHARED.theme.getStyleSheet(STYLES_MIN_TOOLBUTTON)
self.tbNovel.setStyleSheet(buttonStyle) self.tbNovel.setStyleSheet(buttonStyle)
self.tbRefresh.setStyleSheet(buttonStyle) self.tbRefresh.setStyleSheet(buttonStyle)
+6
View File
@@ -103,6 +103,8 @@ class GuiOutlineView(QWidget):
def updateTheme(self) -> None: def updateTheme(self) -> None:
"""Update theme elements.""" """Update theme elements."""
logger.debug("Theme Update: GuiOutlineView")
self.outlineBar.updateTheme() self.outlineBar.updateTheme()
self.outlineTree.updateTheme() self.outlineTree.updateTheme()
self.outlineTree.refreshTree( self.outlineTree.refreshTree(
@@ -258,6 +260,8 @@ class GuiOutlineToolBar(QToolBar):
def updateTheme(self) -> None: def updateTheme(self) -> None:
"""Update theme elements.""" """Update theme elements."""
logger.debug("Theme Update: GuiOutlineToolBar")
self.setStyleSheet("QToolBar {border: 0px;}") self.setStyleSheet("QToolBar {border: 0px;}")
self.novelValue.refreshNovelList() self.novelValue.refreshNovelList()
self.aRefresh.setIcon(SHARED.theme.getIcon("refresh", "green")) self.aRefresh.setIcon(SHARED.theme.getIcon("refresh", "green"))
@@ -454,6 +458,8 @@ class GuiOutlineTree(QTreeWidget):
def updateTheme(self) -> None: def updateTheme(self) -> None:
"""Update theme elements.""" """Update theme elements."""
logger.debug("Theme Update: GuiOutlineTree")
iType = nwItemType.FILE iType = nwItemType.FILE
iClass = nwItemClass.NO_CLASS iClass = nwItemClass.NO_CLASS
iLayout = nwItemLayout.DOCUMENT iLayout = nwItemLayout.DOCUMENT
+3
View File
@@ -138,6 +138,7 @@ class GuiProjectView(QWidget):
def updateTheme(self) -> None: def updateTheme(self) -> None:
"""Update theme elements.""" """Update theme elements."""
logger.debug("Theme Update: GuiProjectView")
self.projBar.updateTheme() self.projBar.updateTheme()
def initSettings(self) -> None: def initSettings(self) -> None:
@@ -346,6 +347,8 @@ class GuiProjectToolBar(QWidget):
def updateTheme(self) -> None: def updateTheme(self) -> None:
"""Update theme elements.""" """Update theme elements."""
logger.debug("Theme Update: GuiProjectToolBar")
buttonStyle = SHARED.theme.getStyleSheet(STYLES_MIN_TOOLBUTTON) buttonStyle = SHARED.theme.getStyleSheet(STYLES_MIN_TOOLBUTTON)
self.tbQuick.setStyleSheet(buttonStyle) self.tbQuick.setStyleSheet(buttonStyle)
self.tbMoveU.setStyleSheet(buttonStyle) self.tbMoveU.setStyleSheet(buttonStyle)
+2
View File
@@ -158,6 +158,8 @@ class GuiProjectSearch(QWidget):
def updateTheme(self) -> None: def updateTheme(self) -> None:
"""Update theme elements.""" """Update theme elements."""
logger.debug("Theme Update: GuiProjectSearch")
palette = QApplication.palette() palette = QApplication.palette()
colBase = palette.base().color().name(QtHexArgb) colBase = palette.base().color().name(QtHexArgb)
colFocus = palette.highlight().color().name(QtHexArgb) colFocus = palette.highlight().color().name(QtHexArgb)
+2 -1
View File
@@ -129,8 +129,9 @@ class GuiSideBar(QWidget):
def updateTheme(self) -> None: def updateTheme(self) -> None:
"""Initialise GUI elements that depend on specific settings.""" """Initialise GUI elements that depend on specific settings."""
buttonStyle = SHARED.theme.getStyleSheet(STYLES_BIG_TOOLBUTTON) logger.debug("Theme Update: GuiSideBar")
buttonStyle = SHARED.theme.getStyleSheet(STYLES_BIG_TOOLBUTTON)
self.tbProject.setStyleSheet(buttonStyle) self.tbProject.setStyleSheet(buttonStyle)
self.tbNovel.setStyleSheet(buttonStyle) self.tbNovel.setStyleSheet(buttonStyle)
self.tbSearch.setStyleSheet(buttonStyle) self.tbSearch.setStyleSheet(buttonStyle)
+2
View File
@@ -133,6 +133,8 @@ class GuiMainStatus(QStatusBar):
def updateTheme(self) -> None: def updateTheme(self) -> None:
"""Update theme elements.""" """Update theme elements."""
logger.debug("Theme Update: GuiMainStatus")
iPx = SHARED.theme.baseIconHeight iPx = SHARED.theme.baseIconHeight
self.langIcon.setPixmap(SHARED.theme.getPixmap("language", (iPx, iPx))) self.langIcon.setPixmap(SHARED.theme.getPixmap("language", (iPx, iPx)))
self.statsIcon.setPixmap(SHARED.theme.getPixmap("stats", (iPx, iPx))) self.statsIcon.setPixmap(SHARED.theme.getPixmap("stats", (iPx, iPx)))
+3
View File
@@ -910,6 +910,9 @@ class GuiMain(QMainWindow):
self.mainStatus.updateTheme() self.mainStatus.updateTheme()
SHARED.project.tree.refreshAllItems() SHARED.project.tree.refreshAllItems()
if dialog := SHARED.findTopLevelWidget(GuiManuscript):
dialog.updateTheme()
if syntax: if syntax:
self.docEditor.updateSyntaxColors() self.docEditor.updateSyntaxColors()
+70 -23
View File
@@ -101,30 +101,20 @@ class GuiManuscript(NToolDialog):
# Build Controls # Build Controls
# ============== # ==============
qPalette = self.palette() self.tbAdd = NIconToolButton(self, iSz)
qPalette.setBrush(QPalette.ColorRole.Window, qPalette.base())
self.setPalette(qPalette)
buttonStyle = SHARED.theme.getStyleSheet(STYLES_MIN_TOOLBUTTON)
self.tbAdd = NIconToolButton(self, iSz, "add", "green")
self.tbAdd.setToolTip(self.tr("Add New Build")) self.tbAdd.setToolTip(self.tr("Add New Build"))
self.tbAdd.setStyleSheet(buttonStyle)
self.tbAdd.clicked.connect(self._createNewBuild) self.tbAdd.clicked.connect(self._createNewBuild)
self.tbDel = NIconToolButton(self, iSz, "remove", "red") self.tbDel = NIconToolButton(self, iSz)
self.tbDel.setToolTip(self.tr("Delete Selected Build")) self.tbDel.setToolTip(self.tr("Delete Selected Build"))
self.tbDel.setStyleSheet(buttonStyle)
self.tbDel.clicked.connect(self._deleteSelectedBuild) self.tbDel.clicked.connect(self._deleteSelectedBuild)
self.tbCopy = NIconToolButton(self, iSz, "copy", "blue") self.tbCopy = NIconToolButton(self, iSz)
self.tbCopy.setToolTip(self.tr("Duplicate Selected Build")) self.tbCopy.setToolTip(self.tr("Duplicate Selected Build"))
self.tbCopy.setStyleSheet(buttonStyle)
self.tbCopy.clicked.connect(self._copySelectedBuild) self.tbCopy.clicked.connect(self._copySelectedBuild)
self.tbEdit = NIconToolButton(self, iSz, "edit", "green") self.tbEdit = NIconToolButton(self, iSz)
self.tbEdit.setToolTip(self.tr("Edit Selected Build")) self.tbEdit.setToolTip(self.tr("Edit Selected Build"))
self.tbEdit.setStyleSheet(buttonStyle)
self.tbEdit.clicked.connect(self._editSelectedBuild) self.tbEdit.clicked.connect(self._editSelectedBuild)
self.lblBuilds = QLabel("<b>{0}</b>".format(self.tr("Builds")), self) self.lblBuilds = QLabel("<b>{0}</b>".format(self.tr("Builds")), self)
@@ -159,7 +149,6 @@ class GuiManuscript(NToolDialog):
self.detailsTabs = QTabWidget(self) self.detailsTabs = QTabWidget(self)
self.detailsTabs.addTab(self.buildDetails, self.tr("Details")) self.detailsTabs.addTab(self.buildDetails, self.tr("Details"))
self.detailsTabs.addTab(self.buildOutline, self.tr("Outline")) self.detailsTabs.addTab(self.buildOutline, self.tr("Outline"))
self.detailsTabs.setStyleSheet(SHARED.theme.getStyleSheet(STYLES_FLAT_TABS))
self.buildSplit = QSplitter(Qt.Orientation.Vertical, self) self.buildSplit = QSplitter(Qt.Orientation.Vertical, self)
self.buildSplit.addWidget(self.buildList) self.buildSplit.addWidget(self.buildList)
@@ -247,6 +236,8 @@ class GuiManuscript(NToolDialog):
self.setLayout(self.outerBox) self.setLayout(self.outerBox)
self.setSizeGripEnabled(True) self.setSizeGripEnabled(True)
self.updateTheme(init=True)
# Signals # Signals
self.buildOutline.outlineEntryClicked.connect(self.docPreview.navigateTo) self.buildOutline.outlineEntryClicked.connect(self.docPreview.navigateTo)
@@ -270,6 +261,37 @@ class GuiManuscript(NToolDialog):
self.buildList.setCurrentItem(self._buildMap[selected]) self.buildList.setCurrentItem(self._buildMap[selected])
QTimer.singleShot(200, self._generatePreview) QTimer.singleShot(200, self._generatePreview)
def updateTheme(self, *, init: bool = False) -> None:
"""Update theme elements."""
logger.debug("Theme Update: GuiManuscript, init=%s", init)
if not init:
self.btnPreview.updateIcon()
self.btnPrint.updateIcon()
self.btnBuild.updateIcon()
self.btnClose.updateIcon()
self.tbAdd.setThemeIcon("add", "green")
self.tbDel.setThemeIcon("remove", "red")
self.tbCopy.setThemeIcon("copy", "blue")
self.tbEdit.setThemeIcon("edit", "green")
buttonStyle = SHARED.theme.getStyleSheet(STYLES_MIN_TOOLBUTTON)
self.tbAdd.setStyleSheet(buttonStyle)
self.tbDel.setStyleSheet(buttonStyle)
self.tbCopy.setStyleSheet(buttonStyle)
self.tbEdit.setStyleSheet(buttonStyle)
self.detailsTabs.setStyleSheet(SHARED.theme.getStyleSheet(STYLES_FLAT_TABS))
self.buildDetails.updateTheme()
self.buildOutline.updateTheme()
self.docPreview.updateTheme()
for obj in SHARED.mainGui.children():
if isinstance(obj, GuiBuildSettings):
obj.updateTheme()
## ##
# Events # Events
## ##
@@ -490,6 +512,7 @@ class _DetailsWidget(QWidget):
super().__init__(parent=parent) super().__init__(parent=parent)
self._initExpanded = True self._initExpanded = True
self._build = None
# Tree Widget # Tree Widget
self.listView = QTreeWidget(self) self.listView = QTreeWidget(self)
@@ -612,9 +635,17 @@ class _DetailsWidget(QWidget):
sub.setIcon(1, on if build.getBool(key) else off) sub.setIcon(1, on if build.getBool(key) else off)
item.addChild(sub) item.addChild(sub)
self._build = build
# Restore expanded state # Restore expanded state
self.setExpandedState(expanded) self.setExpandedState(expanded)
def updateTheme(self) -> None:
"""Update theme elements."""
if self._build:
logger.debug("Theme Update: _DetailsWidget")
self.updateInfo(self._build)
class _OutlineWidget(QWidget): class _OutlineWidget(QWidget):
@@ -639,9 +670,9 @@ class _OutlineWidget(QWidget):
self.outerBox.setContentsMargins(0, 0, 0, 0) self.outerBox.setContentsMargins(0, 0, 0, 0)
self.setLayout(self.outerBox) self.setLayout(self.outerBox)
def updateOutline(self, data: dict[str, str]) -> None: def updateOutline(self, data: dict[str, str], *, force: bool = False) -> None:
"""Update the outline.""" """Update the outline."""
if isinstance(data, dict) and data != self._outline: if isinstance(data, dict) and (data != self._outline or force):
self.listView.clear() self.listView.clear()
tFont = self.font() tFont = self.font()
@@ -679,6 +710,11 @@ class _OutlineWidget(QWidget):
self.listView.setIndentation(SHARED.theme.baseIconHeight if indent else 4) self.listView.setIndentation(SHARED.theme.baseIconHeight if indent else 4)
self._outline = data self._outline = data
def updateTheme(self) -> None:
"""Update theme elements."""
logger.debug("Theme Update: _OutlineWidget")
self.updateOutline(self._outline, force=True)
## ##
# Private Slots # Private Slots
## ##
@@ -721,17 +757,12 @@ class _PreviewWidget(QTextBrowser):
self.anchorClicked.connect(self._linkClicked) self.anchorClicked.connect(self._linkClicked)
# Document Age # Document Age
aPalette = self.palette()
aPalette.setColor(QPalette.ColorRole.Window, aPalette.toolTipBase().color())
aPalette.setColor(QPalette.ColorRole.WindowText, aPalette.toolTipText().color())
aFont = self.font() aFont = self.font()
aFont.setPointSizeF(0.9*SHARED.theme.fontPointSize) aFont.setPointSizeF(0.9*SHARED.theme.fontPointSize)
self.ageLabel = QLabel("", self) self.ageLabel = QLabel("", self)
self.ageLabel.setIndent(0) self.ageLabel.setIndent(0)
self.ageLabel.setFont(aFont) self.ageLabel.setFont(aFont)
self.ageLabel.setPalette(aPalette)
self.ageLabel.setAutoFillBackground(True) self.ageLabel.setAutoFillBackground(True)
self.ageLabel.setAlignment(QtAlignCenter) self.ageLabel.setAlignment(QtAlignCenter)
self.ageLabel.setFixedHeight(int(2.1*SHARED.theme.fontPixelSize)) self.ageLabel.setFixedHeight(int(2.1*SHARED.theme.fontPixelSize))
@@ -750,6 +781,7 @@ class _PreviewWidget(QTextBrowser):
self._updateDocMargins() self._updateDocMargins()
self._updateBuildAge() self._updateBuildAge()
self.updateTheme()
self.setTextFont(CONFIG.textFont) self.setTextFont(CONFIG.textFont)
# Age Timer # Age Timer
@@ -815,6 +847,15 @@ class _PreviewWidget(QTextBrowser):
QApplication.processEvents() QApplication.processEvents()
QTimer.singleShot(300, self._postUpdate) QTimer.singleShot(300, self._postUpdate)
def updateTheme(self) -> None:
"""Update theme elements."""
logger.debug("Theme Update: _PreviewWidget")
palette = QApplication.palette()
palette.setColor(QPalette.ColorRole.Window, palette.toolTipBase().color())
palette.setColor(QPalette.ColorRole.WindowText, palette.toolTipText().color())
self.ageLabel.setPalette(palette)
## ##
# Events # Events
## ##
@@ -907,7 +948,7 @@ class _StatsWidget(QWidget):
self.minWidget = QWidget(self) self.minWidget = QWidget(self)
self.maxWidget = QWidget(self) self.maxWidget = QWidget(self)
self.toggleButton = NIconToggleButton(self, SHARED.theme.baseIconSize, "unfold") self.toggleButton = NIconToggleButton(self, SHARED.theme.baseIconSize)
self.toggleButton.toggled.connect(self._toggleView) self.toggleButton.toggled.connect(self._toggleView)
self._buildBottomPanel() self._buildBottomPanel()
@@ -922,6 +963,7 @@ class _StatsWidget(QWidget):
self.outerBox.setContentsMargins(0, 0, 0, 0) self.outerBox.setContentsMargins(0, 0, 0, 0)
self.setLayout(self.outerBox) self.setLayout(self.outerBox)
self.updateTheme()
self._toggleView(False) self._toggleView(False)
@@ -946,6 +988,11 @@ class _StatsWidget(QWidget):
self.maxHeadWordChars.setText(f"{data.get(nwStats.WCHARS_TITLE, 0):n}") self.maxHeadWordChars.setText(f"{data.get(nwStats.WCHARS_TITLE, 0):n}")
self.maxTextWordChars.setText(f"{data.get(nwStats.WCHARS_TEXT, 0):n}") self.maxTextWordChars.setText(f"{data.get(nwStats.WCHARS_TEXT, 0):n}")
def updateTheme(self) -> None:
"""Update theme elements."""
logger.debug("Theme Update: _StatsWidget")
self.toggleButton.setThemeIcon("unfold")
## ##
# Private Slots # Private Slots
## ##
+96 -30
View File
@@ -154,6 +154,7 @@ class GuiBuildSettings(NToolDialog):
self.outerBox.setSpacing(12) self.outerBox.setSpacing(12)
self.setLayout(self.outerBox) self.setLayout(self.outerBox)
self.updateTheme(init=True)
# Set Default Tab # Set Default Tab
self.sidebar.setSelected(self.OPT_FILTERS) self.sidebar.setSelected(self.OPT_FILTERS)
@@ -170,6 +171,22 @@ class GuiBuildSettings(NToolDialog):
self.optTabHeadings.loadContent() self.optTabHeadings.loadContent()
self.optTabFormatting.loadContent() self.optTabFormatting.loadContent()
def updateTheme(self, *, init: bool = False) -> None:
"""Update theme elements."""
logger.debug("Theme Update: GuiBuildSettings, init=%s", init)
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 # Properties
## ##
@@ -326,15 +343,13 @@ class _FilterTab(NFixedPage):
self.includedButton = NIconToolButton(self, iSz) self.includedButton = NIconToolButton(self, iSz)
self.includedButton.setToolTip(self.tr("Always included")) 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.includedButton.clicked.connect(qtLambda(self._setSelectedMode, self.F_INCLUDED))
self.excludedButton = NIconToolButton(self, iSz) self.excludedButton = NIconToolButton(self, iSz)
self.excludedButton.setToolTip(self.tr("Always excluded")) 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.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.setToolTip(self.tr("Reset to default"))
self.resetButton.clicked.connect(qtLambda(self._setSelectedMode, self.F_FILTERED)) self.resetButton.clicked.connect(qtLambda(self._setSelectedMode, self.F_FILTERED))
@@ -376,6 +391,7 @@ class _FilterTab(NFixedPage):
pOptions.getInt("GuiBuildSettings", "filterWidth", 300), pOptions.getInt("GuiBuildSettings", "filterWidth", 300),
]) ])
self.updateTheme(init=True)
self.setCentralWidget(self.mainSplit) self.setCentralWidget(self.mainSplit)
def loadContent(self) -> None: def loadContent(self) -> None:
@@ -389,6 +405,20 @@ class _FilterTab(NFixedPage):
m, n = (sizes[0], sizes[1]) if len(sizes) >= 2 else (0, 0) m, n = (sizes[0], sizes[1]) if len(sizes) >= 2 else (0, 0)
return m, n return m, n
def updateTheme(self, *, init: bool = False) -> None:
"""Update theme elements."""
logger.debug("Theme Update: _FilterTab, init=%s", init)
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 # Slots
## ##
@@ -555,7 +585,7 @@ class _HeadingsTab(NScrollablePage):
self.lblPart = QLabel(self._build.getLabel("headings.fmtPart"), self) self.lblPart = QLabel(self._build.getLabel("headings.fmtPart"), self)
self.fmtPart = QLineEdit("", self) self.fmtPart = QLineEdit("", self)
self.fmtPart.setReadOnly(True) 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.btnPart.clicked.connect(qtLambda(self._editHeading, self.EDIT_TITLE))
self.swtPart = NSwitch(self, height=iPx) self.swtPart = NSwitch(self, height=iPx)
self.hdePart = QLabel(trHide, self) self.hdePart = QLabel(trHide, self)
@@ -572,7 +602,7 @@ class _HeadingsTab(NScrollablePage):
self.lblChapter = QLabel(self._build.getLabel("headings.fmtChapter"), self) self.lblChapter = QLabel(self._build.getLabel("headings.fmtChapter"), self)
self.fmtChapter = QLineEdit("", self) self.fmtChapter = QLineEdit("", self)
self.fmtChapter.setReadOnly(True) 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.btnChapter.clicked.connect(qtLambda(self._editHeading, self.EDIT_CHAPTER))
self.swtChapter = NSwitch(self, height=iPx) self.swtChapter = NSwitch(self, height=iPx)
self.hdeChapter = QLabel(trHide, self) self.hdeChapter = QLabel(trHide, self)
@@ -589,7 +619,7 @@ class _HeadingsTab(NScrollablePage):
self.lblUnnumbered = QLabel(self._build.getLabel("headings.fmtUnnumbered"), self) self.lblUnnumbered = QLabel(self._build.getLabel("headings.fmtUnnumbered"), self)
self.fmtUnnumbered = QLineEdit("", self) self.fmtUnnumbered = QLineEdit("", self)
self.fmtUnnumbered.setReadOnly(True) 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.btnUnnumbered.clicked.connect(qtLambda(self._editHeading, self.EDIT_UNNUM))
self.swtUnnumbered = NSwitch(self, height=iPx) self.swtUnnumbered = NSwitch(self, height=iPx)
self.hdeUnnumbered = QLabel(trHide, self) self.hdeUnnumbered = QLabel(trHide, self)
@@ -606,7 +636,7 @@ class _HeadingsTab(NScrollablePage):
self.lblScene = QLabel(self._build.getLabel("headings.fmtScene"), self) self.lblScene = QLabel(self._build.getLabel("headings.fmtScene"), self)
self.fmtScene = QLineEdit("", self) self.fmtScene = QLineEdit("", self)
self.fmtScene.setReadOnly(True) 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.btnScene.clicked.connect(qtLambda(self._editHeading, self.EDIT_SCENE))
self.swtScene = NSwitch(self, height=iPx) self.swtScene = NSwitch(self, height=iPx)
self.hdeScene = QLabel(trHide, self) self.hdeScene = QLabel(trHide, self)
@@ -623,7 +653,7 @@ class _HeadingsTab(NScrollablePage):
self.lblAScene = QLabel(self._build.getLabel("headings.fmtAltScene"), self) self.lblAScene = QLabel(self._build.getLabel("headings.fmtAltScene"), self)
self.fmtAScene = QLineEdit("", self) self.fmtAScene = QLineEdit("", self)
self.fmtAScene.setReadOnly(True) 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.btnAScene.clicked.connect(qtLambda(self._editHeading, self.EDIT_HSCENE))
self.swtAScene = NSwitch(self, height=iPx) self.swtAScene = NSwitch(self, height=iPx)
self.hdeAScene = QLabel(trHide, self) self.hdeAScene = QLabel(trHide, self)
@@ -640,7 +670,7 @@ class _HeadingsTab(NScrollablePage):
self.lblSection = QLabel(self._build.getLabel("headings.fmtSection"), self) self.lblSection = QLabel(self._build.getLabel("headings.fmtSection"), self)
self.fmtSection = QLineEdit("", self) self.fmtSection = QLineEdit("", self)
self.fmtSection.setReadOnly(True) 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.btnSection.clicked.connect(qtLambda(self._editHeading, self.EDIT_SECTION))
self.swtSection = NSwitch(self, height=iPx) self.swtSection = NSwitch(self, height=iPx)
self.hdeSection = QLabel(trHide, self) self.hdeSection = QLabel(trHide, self)
@@ -774,8 +804,23 @@ class _HeadingsTab(NScrollablePage):
self.outerBox.addLayout(self.layoutMatrix) self.outerBox.addLayout(self.layoutMatrix)
self.outerBox.addStretch(1) self.outerBox.addStretch(1)
self.updateTheme()
self.setCentralLayout(self.outerBox) self.setCentralLayout(self.outerBox)
def updateTheme(self) -> None:
"""Update theme elements."""
logger.debug("Theme Update: _HeadingsTab")
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: def loadContent(self) -> None:
"""Populate the widgets.""" """Populate the widgets."""
def fmtBreak(text: str) -> str: def fmtBreak(text: str) -> str:
@@ -907,10 +952,14 @@ class _HeadingSyntaxHighlighter(QSyntaxHighlighter):
def __init__(self, document: QTextDocument | None) -> None: def __init__(self, document: QTextDocument | None) -> None:
super().__init__(document) super().__init__(document)
syntax = SHARED.theme.syntaxTheme
self._fmtSymbol = QTextCharFormat() self._fmtSymbol = QTextCharFormat()
self._fmtSymbol.setForeground(syntax.head)
self._fmtFormat = QTextCharFormat() 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) self._fmtFormat.setForeground(syntax.emph)
def highlightBlock(self, text: str) -> None: def highlightBlock(self, text: str) -> None:
@@ -936,6 +985,7 @@ class _FormattingTab(NScrollableForm):
self.setHelpTextStyle(SHARED.theme.helpText) self.setHelpTextStyle(SHARED.theme.helpText)
self.buildForm() self.buildForm()
self.updateTheme()
def buildForm(self) -> None: def buildForm(self) -> None:
"""Build the formatting form.""" """Build the formatting form."""
@@ -979,7 +1029,7 @@ class _FormattingTab(NScrollableForm):
lambda keyword=keyword: self._updateIgnoredKeywords(keyword) lambda keyword=keyword: self._updateIgnoredKeywords(keyword)
) )
self.ignoredKeywordsButton = NIconToolButton(self, iSz, "add", "green") self.ignoredKeywordsButton = NIconToolButton(self, iSz)
self.ignoredKeywordsButton.setMenu(self.mnKeywords) self.ignoredKeywordsButton.setMenu(self.mnKeywords)
self.addRow( self.addRow(
self._build.getLabel("text.ignoredKeywords"), self.ignoredKeywords, self._build.getLabel("text.ignoredKeywords"), self.ignoredKeywords,
@@ -1001,7 +1051,7 @@ class _FormattingTab(NScrollableForm):
# Text Font # Text Font
self.textFont = QLineEdit(self) self.textFont = QLineEdit(self)
self.textFont.setReadOnly(True) self.textFont.setReadOnly(True)
self.btnTextFont = NIconToolButton(self, iSz, "font") self.btnTextFont = NIconToolButton(self, iSz)
self.btnTextFont.clicked.connect(self._selectFont) self.btnTextFont.clicked.connect(self._selectFont)
self.addRow( self.addRow(
self._build.getLabel("format.textFont"), self.textFont, self._build.getLabel("format.textFont"), self.textFont,
@@ -1060,12 +1110,12 @@ class _FormattingTab(NScrollableForm):
self._sidebar.addButton(title, section) self._sidebar.addButton(title, section)
self.addGroupLabel(title, section) self.addGroupLabel(title, section)
pixT = SHARED.theme.getPixmap("margin_top", (iPx, iPx)) self.pixT = QLabel(self)
pixB = SHARED.theme.getPixmap("margin_bottom", (iPx, iPx)) self.pixB = QLabel(self)
pixL = SHARED.theme.getPixmap("margin_left", (iPx, iPx)) self.pixL = QLabel(self)
pixR = SHARED.theme.getPixmap("margin_right", (iPx, iPx)) self.pixR = QLabel(self)
pixH = SHARED.theme.getPixmap("fit_height", (iPx, iPx)) self.pixH = QLabel(self)
pixW = SHARED.theme.getPixmap("fit_width", (iPx, iPx)) self.pixW = QLabel(self)
# Title # Title
self.titleMarginT = NDoubleSpinBox(self) self.titleMarginT = NDoubleSpinBox(self)
@@ -1076,7 +1126,7 @@ class _FormattingTab(NScrollableForm):
self.addRow( self.addRow(
self._build.getLabel("format.titleMargin"), self._build.getLabel("format.titleMargin"),
[pixT, self.titleMarginT, 6, pixB, self.titleMarginB], [self.pixT, self.titleMarginT, 6, self.pixB, self.titleMarginB],
unit="em", unit="em",
) )
@@ -1089,7 +1139,7 @@ class _FormattingTab(NScrollableForm):
self.addRow( self.addRow(
self._build.getLabel("format.h1Margin"), self._build.getLabel("format.h1Margin"),
[pixT, self.h1MarginT, 6, pixB, self.h1MarginB], [self.pixT, self.h1MarginT, 6, self.pixB, self.h1MarginB],
unit="em", unit="em",
) )
@@ -1102,7 +1152,7 @@ class _FormattingTab(NScrollableForm):
self.addRow( self.addRow(
self._build.getLabel("format.h2Margin"), self._build.getLabel("format.h2Margin"),
[pixT, self.h2MarginT, 6, pixB, self.h2MarginB], [self.pixT, self.h2MarginT, 6, self.pixB, self.h2MarginB],
unit="em", unit="em",
) )
@@ -1115,7 +1165,7 @@ class _FormattingTab(NScrollableForm):
self.addRow( self.addRow(
self._build.getLabel("format.h3Margin"), self._build.getLabel("format.h3Margin"),
[pixT, self.h3MarginT, 6, pixB, self.h3MarginB], [self.pixT, self.h3MarginT, 6, self.pixB, self.h3MarginB],
unit="em", unit="em",
) )
@@ -1128,7 +1178,7 @@ class _FormattingTab(NScrollableForm):
self.addRow( self.addRow(
self._build.getLabel("format.h4Margin"), self._build.getLabel("format.h4Margin"),
[pixT, self.h4MarginT, 6, pixB, self.h4MarginB], [self.pixT, self.h4MarginT, 6, self.pixB, self.h4MarginB],
unit="em", unit="em",
) )
@@ -1141,7 +1191,7 @@ class _FormattingTab(NScrollableForm):
self.addRow( self.addRow(
self._build.getLabel("format.textMargin"), self._build.getLabel("format.textMargin"),
[pixT, self.textMarginT, 6, pixB, self.textMarginB], [self.pixT, self.textMarginT, 6, self.pixB, self.textMarginB],
unit="em", unit="em",
) )
@@ -1154,7 +1204,7 @@ class _FormattingTab(NScrollableForm):
self.addRow( self.addRow(
self._build.getLabel("format.sepMargin"), self._build.getLabel("format.sepMargin"),
[pixT, self.sepMarginT, 6, pixB, self.sepMarginB], [self.pixT, self.sepMarginT, 6, self.pixB, self.sepMarginB],
unit="em", unit="em",
) )
@@ -1188,7 +1238,7 @@ class _FormattingTab(NScrollableForm):
self.addRow( self.addRow(
self._build.getLabel("format.pageSize"), 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 # Page Margins
@@ -1206,11 +1256,11 @@ class _FormattingTab(NScrollableForm):
self.addRow( self.addRow(
self._build.getLabel("format.pageMargins"), self._build.getLabel("format.pageMargins"),
[pixT, self.topMargin, 6, pixB, self.bottomMargin], [self.pixT, self.topMargin, 6, self.pixB, self.bottomMargin],
) )
self.addRow( self.addRow(
"", "",
[pixL, self.leftMargin, 6, pixR, self.rightMargin], [self.pixL, self.leftMargin, 6, self.pixR, self.rightMargin],
) )
# Open Document # Open Document
@@ -1224,7 +1274,7 @@ class _FormattingTab(NScrollableForm):
# Header # Header
self.odtPageHeader = QLineEdit(self) self.odtPageHeader = QLineEdit(self)
self.odtPageHeader.setMinimumWidth(200) self.odtPageHeader.setMinimumWidth(200)
self.btnPageHeader = NIconToolButton(self, iSz, "revert", "green") self.btnPageHeader = NIconToolButton(self, iSz)
self.btnPageHeader.clicked.connect(self._resetPageHeader) self.btnPageHeader.clicked.connect(self._resetPageHeader)
self.addRow( self.addRow(
self._build.getLabel("doc.pageHeader"), self.odtPageHeader, self._build.getLabel("doc.pageHeader"), self.odtPageHeader,
@@ -1264,6 +1314,22 @@ class _FormattingTab(NScrollableForm):
# Finalise # Finalise
self.finalise() self.finalise()
def updateTheme(self) -> None:
"""Update theme elements."""
logger.debug("Theme Update: _FormattingTab")
self.ignoredKeywordsButton.setThemeIcon("add", "green")
self.btnTextFont.setThemeIcon("font")
self.btnPageHeader.setThemeIcon("revert", "green")
iPx = SHARED.theme.baseIconHeight
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: def loadContent(self) -> None:
"""Populate the widgets.""" """Populate the widgets."""
# Text Content # Text Content
+24 -3
View File
@@ -22,12 +22,13 @@ from __future__ import annotations
import pytest import pytest
from PyQt6.QtCore import QEvent, QPoint, QPointF, Qt from PyQt6.QtCore import QEvent, QPoint, QPointF, QSize, Qt
from PyQt6.QtGui import QKeyEvent, QMouseEvent, QStandardItem, QStandardItemModel, QWheelEvent from PyQt6.QtGui import QKeyEvent, QMouseEvent, QStandardItem, QStandardItemModel, QWheelEvent
from PyQt6.QtWidgets import QWidget from PyQt6.QtWidgets import QWidget
from novelwriter.extensions.modified import ( from novelwriter.extensions.modified import (
NClickableLabel, NComboBox, NDialog, NDoubleSpinBox, NSpinBox, NTreeView NClickableLabel, NComboBox, NDialog, NDoubleSpinBox, NIconToggleButton,
NIconToolButton, NSpinBox, NTreeView
) )
from novelwriter.types import QtModNone, QtMouseLeft, QtMouseMiddle, QtRejected from novelwriter.types import QtModNone, QtMouseLeft, QtMouseMiddle, QtRejected
@@ -168,7 +169,7 @@ def testExtModified_NDoubleSpinBox(qtbot, monkeypatch):
@pytest.mark.gui @pytest.mark.gui
def testExtModified_NClickableLabel(qtbot, monkeypatch): def testExtModified_NClickableLabel(qtbot):
"""Test the NClickableLabel class.""" """Test the NClickableLabel class."""
widget = NClickableLabel() widget = NClickableLabel()
dialog = SimpleDialog(widget) dialog = SimpleDialog(widget)
@@ -181,3 +182,23 @@ def testExtModified_NClickableLabel(qtbot, monkeypatch):
with qtbot.waitSignal(widget.mouseClicked): with qtbot.waitSignal(widget.mouseClicked):
widget.mousePressEvent(event) widget.mousePressEvent(event)
@pytest.mark.gui
def testExtModified_ToolButtons(qtbot):
"""Test the NIconToolButton and NIconToggleButton classes."""
dialog = SimpleDialog(None)
size = QSize(16, 16)
button1 = NIconToolButton(dialog, size, "add", "green")
button2 = NIconToggleButton(dialog, size, "bullet")
assert button1.iconSize() == size
assert button2.iconSize() == size
assert button1.icon().isNull() is False
assert button2.icon().isNull() is False
dialog.addWidget(button1)
dialog.addWidget(button2)
dialog.show()
@@ -72,6 +72,9 @@ def testToolManuscript_Init(monkeypatch, qtbot, nwGUI, projPath, mockRnd):
manus.btnPreview.click() manus.btnPreview.click()
assert manus.docPreview.toPlainText().strip() == allText assert manus.docPreview.toPlainText().strip() == allText
# Trigger a theme update, which is only a visual refresh, but it shouldn't crash
manus.updateTheme()
nwGUI.closeProject() # This should auto-close the manuscript tool nwGUI.closeProject() # This should auto-close the manuscript tool
# qtbot.stop() # qtbot.stop()
@@ -148,6 +151,9 @@ def testToolManuscript_Builds(qtbot, nwGUI, projPath):
assert new is not None assert new is not None
assert new.name == "Test Build 2" assert new.name == "Test Build 2"
# Trigger a theme update, which should propagate to settings
nwGUI.refreshThemeColors()
# Close the dialog should also close the child dialogs # Close the dialog should also close the child dialogs
manus.btnClose.click() manus.btnClose.click()
if isinstance(bSettings, GuiBuildSettings): if isinstance(bSettings, GuiBuildSettings):