diff --git a/novelwriter/dialogs/preferences.py b/novelwriter/dialogs/preferences.py index 97d5ffb0..8421acf5 100644 --- a/novelwriter/dialogs/preferences.py +++ b/novelwriter/dialogs/preferences.py @@ -173,7 +173,19 @@ class GuiPreferences(NDialog): self.mainForm.addRow( self.tr("Colour theme"), self.guiTheme, - self.tr("General colour theme and icons."), stretch=(3, 2) + self.tr("User interface colour theme."), stretch=(3, 2) + ) + + # Icon Theme + self.guiIcons = NComboBox(self) + self.guiIcons.setMinimumWidth(minWidth) + for theme, name in SHARED.theme.iconCache.listThemes(): + self.guiIcons.addItem(name, theme) + self.guiIcons.setCurrentData(CONFIG.guiIcons, "material_rounded_bold") + + self.mainForm.addRow( + self.tr("Icon theme"), self.guiIcons, + self.tr("User interface icon theme."), stretch=(3, 2) ) # Application Font Family @@ -902,13 +914,16 @@ class GuiPreferences(NDialog): # Appearance guiLocale = self.guiLocale.currentData() guiTheme = self.guiTheme.currentData() + guiIcons = self.guiIcons.currentData() updateTheme |= CONFIG.guiTheme != guiTheme + updateTheme |= CONFIG.guiIcons != guiIcons needsRestart |= CONFIG.guiLocale != guiLocale needsRestart |= CONFIG.guiFont != self._guiFont CONFIG.guiLocale = guiLocale CONFIG.guiTheme = guiTheme + CONFIG.guiIcons = guiIcons CONFIG.hideVScroll = self.hideVScroll.isChecked() CONFIG.hideHScroll = self.hideHScroll.isChecked() CONFIG.nativeFont = self.nativeFont.isChecked() diff --git a/novelwriter/gui/theme.py b/novelwriter/gui/theme.py index 2abb4aa4..6bba79a6 100644 --- a/novelwriter/gui/theme.py +++ b/novelwriter/gui/theme.py @@ -443,8 +443,9 @@ class GuiTheme: """Parse a colour value from a config string.""" return QColor(*parser.rdIntList(section, name, [0, 0, 0, 255])) - def _setPalette(self, parser: NWConfigParser, section: str, - name: str, value: QPalette.ColorRole) -> None: + def _setPalette( + self, parser: NWConfigParser, section: str, name: str, value: QPalette.ColorRole + ) -> None: """Set a palette colour value from a config string.""" self._guiPalette.setColor(value, self._parseColour(parser, section, name)) return @@ -515,6 +516,7 @@ class GuiIcons: self._headerDecNarrow: list[QPixmap] = [] # Icon Theme Path + self._themeList: list[tuple[str, str]] = [] self._iconPath = CONFIG.assetPath("icons") # None Icon @@ -692,6 +694,20 @@ class GuiIcons: ] return self._headerDecNarrow[minmax(hLevel, 0, 5)] + def listThemes(self) -> list[tuple[str, str]]: + """Scan the GUI icons folder and list all themes.""" + if self._themeList: + return self._themeList + + for item in self._iconPath.iterdir(): + if item.is_file() and item.suffix == ".icons": + if name := _loadIconName(item): + self._themeList.append((item.stem, name)) + + self._themeList = sorted(self._themeList, key=_sortTheme) + + return self._themeList + ## # Internal Functions ##