Update icons in the GUI

This commit is contained in:
Veronica Berglyd Olsen
2025-01-07 19:19:11 +01:00
parent 8a671dee59
commit b97844512a
25 changed files with 225 additions and 189 deletions
+13 -13
View File
@@ -2438,9 +2438,9 @@ class GuiDocToolBar(QWidget):
palette.setColor(QPalette.ColorRole.Text, SHARED.theme.colText)
self.setPalette(palette)
self.tbBoldMD.setThemeIcon("fmt_bold-md")
self.tbItalicMD.setThemeIcon("fmt_italic-md")
self.tbStrikeMD.setThemeIcon("fmt_strike-md")
self.tbBoldMD.setThemeIcon("fmt_bold", "orange")
self.tbItalicMD.setThemeIcon("fmt_italic", "orange")
self.tbStrikeMD.setThemeIcon("fmt_strike", "orange")
self.tbBold.setThemeIcon("fmt_bold")
self.tbItalic.setThemeIcon("fmt_italic")
self.tbStrike.setThemeIcon("fmt_strike")
@@ -2690,8 +2690,8 @@ class GuiDocEditSearch(QFrame):
self.toggleProject.setIcon(SHARED.theme.getIcon("search_project"))
self.toggleMatchCap.setIcon(SHARED.theme.getIcon("search_preserve"))
self.cancelSearch.setIcon(SHARED.theme.getIcon("search_cancel"))
self.searchButton.setThemeIcon("search")
self.replaceButton.setThemeIcon("search_replace")
self.searchButton.setThemeIcon("search", "green")
self.replaceButton.setThemeIcon("search_replace", "green")
# Set stylesheets
self.searchOpt.setStyleSheet("QToolBar {padding: 0;}")
@@ -2954,11 +2954,11 @@ class GuiDocEditHeader(QWidget):
def updateTheme(self) -> None:
"""Update theme elements."""
self.tbButton.setThemeIcon("toolbar")
self.outlineButton.setThemeIcon("list")
self.searchButton.setThemeIcon("search")
self.minmaxButton.setThemeIcon("maximise")
self.closeButton.setThemeIcon("close")
self.tbButton.setThemeIcon("fmt_toolbar", "blue")
self.outlineButton.setThemeIcon("list", "blue")
self.searchButton.setThemeIcon("search", "blue")
self.minmaxButton.setThemeIcon("maximise", "blue")
self.closeButton.setThemeIcon("close", "red")
buttonStyle = SHARED.theme.getStyleSheet(STYLES_MIN_TOOLBUTTON)
self.tbButton.setStyleSheet(buttonStyle)
@@ -3031,7 +3031,7 @@ class GuiDocEditHeader(QWidget):
@pyqtSlot(bool)
def _focusModeChanged(self, focusMode: bool) -> None:
"""Update minimise/maximise icon of the Focus Mode button."""
self.minmaxButton.setThemeIcon("minimise" if focusMode else "maximise")
self.minmaxButton.setThemeIcon("minimise" if focusMode else "maximise", "blue")
return
##
@@ -3165,8 +3165,8 @@ class GuiDocEditFooter(QWidget):
def updateTheme(self) -> None:
"""Update theme elements."""
iPx = round(0.9*SHARED.theme.baseIconHeight)
self.linesIcon.setPixmap(SHARED.theme.getPixmap("status_lines", (iPx, iPx)))
self.wordsIcon.setPixmap(SHARED.theme.getPixmap("status_stats", (iPx, iPx)))
self.linesIcon.setPixmap(SHARED.theme.getPixmap("lines", (iPx, iPx)))
self.wordsIcon.setPixmap(SHARED.theme.getPixmap("stats", (iPx, iPx)))
self.matchColours()
return
+7 -7
View File
@@ -760,12 +760,12 @@ class GuiDocViewHeader(QWidget):
def updateTheme(self) -> None:
"""Update theme elements."""
self.outlineButton.setThemeIcon("list")
self.backButton.setThemeIcon("backward")
self.forwardButton.setThemeIcon("forward")
self.editButton.setThemeIcon("edit")
self.refreshButton.setThemeIcon("refresh")
self.closeButton.setThemeIcon("close")
self.outlineButton.setThemeIcon("list", "blue")
self.backButton.setThemeIcon("chevron_left", "blue")
self.forwardButton.setThemeIcon("chevron_right", "blue")
self.editButton.setThemeIcon("edit", "green")
self.refreshButton.setThemeIcon("refresh", "green")
self.closeButton.setThemeIcon("close", "red")
buttonStyle = SHARED.theme.getStyleSheet(STYLES_MIN_TOOLBUTTON)
self.outlineButton.setStyleSheet(buttonStyle)
@@ -951,7 +951,7 @@ class GuiDocViewFooter(QWidget):
"""Update theme elements."""
# Icons
fPx = int(0.9*SHARED.theme.fontPixelSize)
bulletIcon = SHARED.theme.getToggleIcon("bullet", (fPx, fPx))
bulletIcon = SHARED.theme.getToggleIcon("bullet", (fPx, fPx), "blue")
self.showHide.setThemeIcon("panel")
self.showComments.setIcon(bulletIcon)
+15 -11
View File
@@ -101,7 +101,7 @@ class GuiDocViewerPanel(QWidget):
def updateTheme(self, updateTabs: bool = True) -> None:
"""Update theme elements."""
self.optsButton.setThemeIcon("menu")
self.optsButton.setThemeIcon("more_vertical")
self.optsButton.setStyleSheet(SHARED.theme.getStyleSheet(STYLES_MIN_TOOLBUTTON))
self.mainTabs.setStyleSheet(SHARED.theme.getStyleSheet(STYLES_FLAT_TABS))
self.updateHandle(self._lastHandle)
@@ -268,8 +268,8 @@ class _ViewPanelBackRefs(QTreeWidget):
treeHeader.setSectionsMovable(False)
# Cache Icons Locally
self._editIcon = SHARED.theme.getIcon("edit")
self._viewIcon = SHARED.theme.getIcon("view")
self._editIcon = SHARED.theme.getIcon("edit", "green")
self._viewIcon = SHARED.theme.getIcon("view", "blue")
# Signals
self.clicked.connect(self._treeItemClicked)
@@ -279,8 +279,8 @@ class _ViewPanelBackRefs(QTreeWidget):
def updateTheme(self) -> None:
"""Update theme elements."""
self._editIcon = SHARED.theme.getIcon("edit")
self._viewIcon = SHARED.theme.getIcon("view")
self._editIcon = SHARED.theme.getIcon("edit", "green")
self._viewIcon = SHARED.theme.getIcon("view", "blue")
for i in range(self.topLevelItemCount()):
if item := self.topLevelItem(i):
item.setIcon(self.C_EDIT, self._editIcon)
@@ -410,9 +410,11 @@ class _ViewPanelKeyWords(QTreeWidget):
treeHeader.setSectionsMovable(False)
# Cache Icons Locally
self._classIcon = SHARED.theme.getIcon(nwLabels.CLASS_ICON[itemClass])
self._editIcon = SHARED.theme.getIcon("edit")
self._viewIcon = SHARED.theme.getIcon("view")
self._classIcon = SHARED.theme.getIcon(
nwLabels.CLASS_ICON[itemClass], nwLabels.CLASS_COLOR[itemClass]
)
self._editIcon = SHARED.theme.getIcon("edit", "green")
self._viewIcon = SHARED.theme.getIcon("view", "blue")
# Signals
self.clicked.connect(self._treeItemClicked)
@@ -422,9 +424,11 @@ class _ViewPanelKeyWords(QTreeWidget):
def updateTheme(self) -> None:
"""Update theme elements."""
self._classIcon = SHARED.theme.getIcon(nwLabels.CLASS_ICON[self._class])
self._editIcon = SHARED.theme.getIcon("edit")
self._viewIcon = SHARED.theme.getIcon("view")
self._classIcon = SHARED.theme.getIcon(
nwLabels.CLASS_ICON[self._class], nwLabels.CLASS_COLOR[self._class]
)
self._editIcon = SHARED.theme.getIcon("edit", "green")
self._viewIcon = SHARED.theme.getIcon("view", "blue")
for i in range(self.topLevelItemCount()):
if item := self.topLevelItem(i):
item.setIcon(self.C_EDIT, self._editIcon)
+6 -4
View File
@@ -237,11 +237,11 @@ class GuiItemDetails(QWidget):
if nwItem.isFileType():
if nwItem.isActive:
self.labelIcon.setPixmap(SHARED.theme.getPixmap("checked", (iPx, iPx)))
self.labelIcon.setPixmap(SHARED.theme.getPixmap("checked", (iPx, iPx), "green"))
else:
self.labelIcon.setPixmap(SHARED.theme.getPixmap("unchecked", (iPx, iPx)))
self.labelIcon.setPixmap(SHARED.theme.getPixmap("unchecked", (iPx, iPx), "red"))
else:
self.labelIcon.setPixmap(SHARED.theme.getPixmap("noncheckable", (iPx, iPx)))
self.labelIcon.setPixmap(SHARED.theme.getPixmap("noncheckable", (iPx, iPx), "orange"))
self.labelData.setText(elide(nwItem.itemName, 100))
@@ -255,7 +255,9 @@ class GuiItemDetails(QWidget):
# Class
# =====
classIcon = SHARED.theme.getIcon(nwLabels.CLASS_ICON[nwItem.itemClass])
classIcon = SHARED.theme.getIcon(
nwLabels.CLASS_ICON[nwItem.itemClass], nwLabels.CLASS_COLOR[nwItem.itemClass]
)
self.classIcon.setPixmap(classIcon.pixmap(iPx, iPx))
self.classData.setText(trConst(nwLabels.CLASS_NAME[nwItem.itemClass]))
+2 -2
View File
@@ -268,8 +268,8 @@ class GuiNovelToolBar(QWidget):
"""Update theme elements."""
# Icons
self.tbNovel.setThemeIcon("cls_novel")
self.tbRefresh.setThemeIcon("refresh")
self.tbMore.setThemeIcon("menu")
self.tbRefresh.setThemeIcon("refresh", "green")
self.tbMore.setThemeIcon("more_vertical")
qPalette = self.palette()
qPalette.setBrush(QPalette.ColorRole.Window, qPalette.base())
+3 -3
View File
@@ -268,9 +268,9 @@ class GuiOutlineToolBar(QToolBar):
"""Update theme elements."""
self.setStyleSheet("QToolBar {border: 0px;}")
self.novelValue.refreshNovelList()
self.aRefresh.setIcon(SHARED.theme.getIcon("refresh"))
self.aExport.setIcon(SHARED.theme.getIcon("export"))
self.tbColumns.setIcon(SHARED.theme.getIcon("menu"))
self.aRefresh.setIcon(SHARED.theme.getIcon("refresh", "green"))
self.aExport.setIcon(SHARED.theme.getIcon("export", "blue"))
self.tbColumns.setIcon(SHARED.theme.getIcon("more_vertical"))
self.tbColumns.setStyleSheet("QToolButton::menu-indicator {image: none;}")
self.novelLabel.setTextColors(color=self.palette().windowText().color())
return
+16 -12
View File
@@ -363,17 +363,17 @@ class GuiProjectToolBar(QWidget):
self.tbAdd.setStyleSheet(buttonStyle)
self.tbMore.setStyleSheet(buttonStyle)
self.tbQuick.setThemeIcon("bookmark")
self.tbMoveU.setThemeIcon("up")
self.tbMoveD.setThemeIcon("down")
self.tbAdd.setThemeIcon("add")
self.tbMore.setThemeIcon("menu")
self.tbQuick.setThemeIcon("bookmarks", "blue")
self.tbMoveU.setThemeIcon("chevron_up", "blue")
self.tbMoveD.setThemeIcon("chevron_down", "blue")
self.tbAdd.setThemeIcon("add", "green")
self.tbMore.setThemeIcon("more_vertical")
self.aAddEmpty.setIcon(SHARED.theme.getIcon("proj_document"))
self.aAddChap.setIcon(SHARED.theme.getIcon("proj_chapter"))
self.aAddScene.setIcon(SHARED.theme.getIcon("proj_scene"))
self.aAddNote.setIcon(SHARED.theme.getIcon("proj_note"))
self.aAddFolder.setIcon(SHARED.theme.getIcon("proj_folder"))
self.aAddEmpty.setIcon(SHARED.theme.getIcon("document"))
self.aAddChap.setIcon(SHARED.theme.getIcon("document", "red"))
self.aAddScene.setIcon(SHARED.theme.getIcon("document", "blue"))
self.aAddNote.setIcon(SHARED.theme.getIcon("document", "yellow"))
self.aAddFolder.setIcon(SHARED.theme.getIcon("folder"))
self.buildTemplatesMenu()
self.buildQuickLinksMenu()
@@ -394,7 +394,9 @@ class GuiProjectToolBar(QWidget):
for tHandle, nwItem in SHARED.project.tree.iterRoots(None):
action = self.mQuick.addAction(nwItem.itemName)
action.setData(tHandle)
action.setIcon(SHARED.theme.getIcon(nwLabels.CLASS_ICON[nwItem.itemClass]))
action.setIcon(SHARED.theme.getIcon(
nwLabels.CLASS_ICON[nwItem.itemClass], nwLabels.CLASS_COLOR[nwItem.itemClass]
))
action.triggered.connect(
qtLambda(self.projView.setSelectedHandle, tHandle, doScroll=True)
)
@@ -441,7 +443,9 @@ class GuiProjectToolBar(QWidget):
"""Build the rood folder menu."""
def addClass(itemClass: nwItemClass) -> None:
aNew = self.mAddRoot.addAction(trConst(nwLabels.CLASS_NAME[itemClass]))
aNew.setIcon(SHARED.theme.getIcon(nwLabels.CLASS_ICON[itemClass]))
aNew.setIcon(SHARED.theme.getIcon(
nwLabels.CLASS_ICON[itemClass], nwLabels.CLASS_COLOR[itemClass]
))
aNew.triggered.connect(
qtLambda(self.projTree.newTreeItem, nwItemType.ROOT, itemClass)
)
+2 -2
View File
@@ -105,7 +105,7 @@ class GuiProjectSearch(QWidget):
self.searchText.setClearButtonEnabled(True)
self.searchAction = self.searchText.addAction(
SHARED.theme.getIcon("search"), QLineEdit.ActionPosition.TrailingPosition
SHARED.theme.getIcon("search", "blue"), QLineEdit.ActionPosition.TrailingPosition
)
self.searchAction.triggered.connect(self._processSearch)
@@ -173,7 +173,7 @@ class GuiProjectSearch(QWidget):
f"QLineEdit:focus {{border: {bPx}px solid {colFocus};}} "
)
self.searchAction.setIcon(SHARED.theme.getIcon("search"))
self.searchAction.setIcon(SHARED.theme.getIcon("search", "blue"))
self.toggleCase.setIcon(SHARED.theme.getIcon("search_case"))
self.toggleWord.setIcon(SHARED.theme.getIcon("search_word"))
self.toggleRegEx.setIcon(SHARED.theme.getIcon("search_regex"))
+7 -7
View File
@@ -140,13 +140,13 @@ class GuiSideBar(QWidget):
self.tbStats.setStyleSheet(buttonStyle)
self.tbSettings.setStyleSheet(buttonStyle)
self.tbProject.setThemeIcon("view_editor")
self.tbNovel.setThemeIcon("view_novel")
self.tbSearch.setThemeIcon("view_search")
self.tbOutline.setThemeIcon("view_outline")
self.tbBuild.setThemeIcon("view_build")
self.tbDetails.setThemeIcon("proj_details")
self.tbStats.setThemeIcon("proj_stats")
self.tbProject.setThemeIcon("project_view")
self.tbNovel.setThemeIcon("novel_view")
self.tbSearch.setThemeIcon("search")
self.tbOutline.setThemeIcon("outline")
self.tbBuild.setThemeIcon("manuscript")
self.tbDetails.setThemeIcon("list")
self.tbStats.setThemeIcon("stats")
self.tbSettings.setThemeIcon("settings")
return
+4 -4
View File
@@ -129,10 +129,10 @@ class GuiMainStatus(QStatusBar):
def updateTheme(self) -> None:
"""Update theme elements."""
iPx = SHARED.theme.baseIconHeight
self.langIcon.setPixmap(SHARED.theme.getPixmap("status_lang", (iPx, iPx)))
self.statsIcon.setPixmap(SHARED.theme.getPixmap("status_stats", (iPx, iPx)))
self.timePixmap = SHARED.theme.getPixmap("status_time", (iPx, iPx))
self.idlePixmap = SHARED.theme.getPixmap("status_idle", (iPx, iPx))
self.langIcon.setPixmap(SHARED.theme.getPixmap("language", (iPx, iPx)))
self.statsIcon.setPixmap(SHARED.theme.getPixmap("stats", (iPx, iPx)))
self.timePixmap = SHARED.theme.getPixmap("timer", (iPx, iPx))
self.idlePixmap = SHARED.theme.getPixmap("timer_off", (iPx, iPx))
self.timeIcon.setPixmap(self.timePixmap)
colNone = SHARED.theme.statNone
+29 -61
View File
@@ -501,36 +501,7 @@ class GuiIcons:
ICON_KEYS: set[str] = {
# Project and GUI Icons
"novelwriter", "alert_error", "alert_info", "alert_question", "alert_warn",
"build_excluded", "build_filtered", "build_included", "proj_chapter", "proj_details",
"proj_document", "proj_folder", "proj_note", "proj_nwx", "proj_section", "proj_scene",
"proj_stats", "proj_title", "status_idle", "status_lang", "status_lines", "status_stats",
"status_time", "view_build", "view_editor", "view_novel", "view_outline", "view_search",
# Class Icons
"cls_archive", "cls_character", "cls_custom", "cls_entity", "cls_none", "cls_novel",
"cls_object", "cls_plot", "cls_template", "cls_timeline", "cls_trash", "cls_world",
# Search Icons
"search_cancel", "search_case", "search_loop", "search_preserve", "search_project",
"search_regex", "search_word",
# Format Icons
"fmt_bold", "fmt_bold-md", "fmt_italic", "fmt_italic-md", "fmt_mark", "fmt_strike",
"fmt_strike-md", "fmt_subscript", "fmt_superscript", "fmt_underline", "margin_bottom",
"margin_left", "margin_right", "margin_top", "size_height", "size_width",
# General Button Icons
"add", "add_document", "backward", "bookmark", "browse", "checked", "close", "copy",
"cross", "document", "down", "edit", "export", "font", "forward", "import", "list",
"maximise", "menu", "minimise", "more", "noncheckable", "open", "panel", "quote",
"refresh", "remove", "revert", "search_replace", "search", "settings", "star", "toolbar",
"unchecked", "up", "view",
# Switches
"sticky-on", "sticky-off",
"bullet-on", "bullet-off",
"unfold-show", "unfold-hide",
"novelwriter", "proj_nwx"
# Decorations
"deco_doc_h0", "deco_doc_h1", "deco_doc_h2", "deco_doc_h3", "deco_doc_h4", "deco_doc_more",
@@ -539,7 +510,6 @@ class GuiIcons:
}
TOGGLE_ICON_KEYS: dict[str, tuple[str, str]] = {
"sticky": ("sticky-on", "sticky-off"),
"bullet": ("bullet-on", "bullet-off"),
"unfold": ("unfold-show", "unfold-hide"),
}
@@ -631,7 +601,7 @@ class GuiIcons:
iconPath = themePath / iconFile
if iconPath.is_file():
self._themeMap[iconName] = iconPath
logger.debug("Icon slot '%s' using file '%s'", iconName, iconFile)
# logger.debug("Icon slot '%s' using file '%s'", iconName, iconFile)
else:
logger.error("Icon file '%s' not in theme folder", iconFile)
@@ -657,7 +627,7 @@ class GuiIcons:
def loadNewTheme(self, iconTheme: str) -> bool:
"""Load new style theme."""
themePath = self._iconPath / "material_outline_normal.icons"
themePath = self._iconPath / "material_outline_bold.icons"
with open(themePath, mode="r", encoding="utf-8") as icons:
for icon in icons:
key, _, svg = icon.partition(" = ")
@@ -703,60 +673,62 @@ class GuiIcons:
return pixmap
def getIcon(self, name: str, color: str | None = None) -> QIcon:
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."""
key = f"{name}_{color}" if color else name
if key in self._qIcons:
return self._qIcons[name]
variant = f"{name}-{color}" if color else name
if (key := f"{variant}-{w}x{h}") in self._qIcons:
return self._qIcons[key]
else:
icon = self._loadIcon(name, color)
icon = self._loadIcon(name, color, w, h)
self._qIcons[key] = icon
logger.info("Icon: %s", key)
return icon
def getToggleIcon(self, name: str, size: tuple[int, int]) -> QIcon:
def getToggleIcon(self, name: str, size: tuple[int, int], color: str | None = None) -> QIcon:
"""Return a toggle icon from the icon buffer. or load it."""
if name in self.TOGGLE_ICON_KEYS:
pOne = self.getPixmap(self.TOGGLE_ICON_KEYS[name][0], size)
pTwo = self.getPixmap(self.TOGGLE_ICON_KEYS[name][1], size)
pOne = self.getPixmap(self.TOGGLE_ICON_KEYS[name][0], size, color)
pTwo = self.getPixmap(self.TOGGLE_ICON_KEYS[name][1], size, color)
icon = QIcon()
icon.addPixmap(pOne, QIcon.Mode.Normal, QIcon.State.On)
icon.addPixmap(pTwo, QIcon.Mode.Normal, QIcon.State.Off)
return icon
return self._noIcon
def getPixmap(self, name: str, size: tuple[int, int]) -> QPixmap:
def getPixmap(self, name: str, size: tuple[int, int], color: str | None = None) -> QPixmap:
"""Return an icon from the icon buffer as a QPixmap. If it
doesn't exist, return an empty QPixmap.
"""
return self.getIcon(name).pixmap(size[0], size[1], QIcon.Mode.Normal)
w, h = size
return self.getIcon(name, color, w, h).pixmap(w, h, QIcon.Mode.Normal)
def getItemIcon(self, tType: nwItemType, tClass: nwItemClass,
tLayout: nwItemLayout, hLevel: str = "H0") -> QIcon:
"""Get the correct icon for a project item based on type, class
and heading level
"""
iconName = None
name = None
color = "default"
if tType == nwItemType.ROOT:
iconName = nwLabels.CLASS_ICON[tClass]
name = nwLabels.CLASS_ICON[tClass]
color = nwLabels.CLASS_COLOR[tClass]
elif tType == nwItemType.FOLDER:
iconName = "proj_folder"
name = "folder"
elif tType == nwItemType.FILE:
iconName = "proj_document"
name = "document"
if tLayout == nwItemLayout.DOCUMENT:
if hLevel == "H1":
iconName = "proj_title"
color = "green"
elif hLevel == "H2":
iconName = "proj_chapter"
color = "red"
elif hLevel == "H3":
iconName = "proj_scene"
elif hLevel == "H4":
iconName = "proj_section"
color = "blue"
elif tLayout == nwItemLayout.NOTE:
iconName = "proj_note"
if iconName is None:
color = "yellow"
if name is None:
return self._noIcon
return self.getIcon(iconName)
return self.getIcon(name, color)
def getHeaderDecoration(self, hLevel: int) -> QPixmap:
"""Get the decoration for a specific heading level."""
@@ -789,14 +761,10 @@ class GuiIcons:
# Internal Functions
##
def _loadIcon(self, name: str, color: str | None = None) -> QIcon:
def _loadIcon(self, name: str, color: str | None = None, w: int = 24, h: int = 24) -> QIcon:
"""Load an icon from the assets themes folder. Is guaranteed to
return a QIcon.
"""
# if name not in self.ICON_KEYS:
# logger.error("Requested unknown icon name '%s'", name)
# return self._noIcon
# If we just want the app icons, return right away
if name == "novelwriter":
return QIcon(str(self._iconPath / "novelwriter.svg"))
@@ -806,7 +774,7 @@ class GuiIcons:
if svg := self._svgData.get(name, b""):
if fill := self._svgColours.get(color or "default"):
svg = svg.replace(b"#000000", fill)
pixmap = QPixmap(24, 24)
pixmap = QPixmap(w, h)
pixmap.fill(QtTransparent)
pixmap.loadFromData(svg, "svg")
return QIcon(pixmap)