From 9282b39f2a1decc35da35ad1159a1d90b229b1ac Mon Sep 17 00:00:00 2001 From: Veronica Berglyd Olsen <1619840+vkbo@users.noreply.github.com> Date: Wed, 8 Nov 2023 16:54:15 +0100 Subject: [PATCH] Change the menu icon to three dots --- .../assets/icons/typicons_dark/icons.conf | 2 +- .../icons/typicons_dark/typ_th-dot-menu.svg | 4 + .../icons/typicons_dark/typ_th-menu.svg | 4 - .../assets/icons/typicons_light/icons.conf | 2 +- .../icons/typicons_light/typ_th-dot-menu.svg | 4 + .../icons/typicons_light/typ_th-menu.svg | 4 - novelwriter/core/options.py | 8 +- novelwriter/gui/noveltree.py | 224 ++++++++---------- novelwriter/gui/outline.py | 1 + novelwriter/gui/projtree.py | 7 +- 10 files changed, 120 insertions(+), 140 deletions(-) create mode 100644 novelwriter/assets/icons/typicons_dark/typ_th-dot-menu.svg delete mode 100644 novelwriter/assets/icons/typicons_dark/typ_th-menu.svg create mode 100644 novelwriter/assets/icons/typicons_light/typ_th-dot-menu.svg delete mode 100644 novelwriter/assets/icons/typicons_light/typ_th-menu.svg diff --git a/novelwriter/assets/icons/typicons_dark/icons.conf b/novelwriter/assets/icons/typicons_dark/icons.conf index d0b69572..c8446123 100644 --- a/novelwriter/assets/icons/typicons_dark/icons.conf +++ b/novelwriter/assets/icons/typicons_dark/icons.conf @@ -48,7 +48,7 @@ edit = typ_pencil.svg export = typ_export.svg forward = typ_chevron-right.svg maximise = typ_arrow-maximise.svg -menu = typ_th-menu.svg +menu = typ_th-dot-menu.svg minimise = typ_arrow-minimise.svg noncheckable = mixed_input-none.svg proj_chapter = mixed_document-chapter.svg diff --git a/novelwriter/assets/icons/typicons_dark/typ_th-dot-menu.svg b/novelwriter/assets/icons/typicons_dark/typ_th-dot-menu.svg new file mode 100644 index 00000000..19ec3bde --- /dev/null +++ b/novelwriter/assets/icons/typicons_dark/typ_th-dot-menu.svg @@ -0,0 +1,4 @@ + + + + diff --git a/novelwriter/assets/icons/typicons_dark/typ_th-menu.svg b/novelwriter/assets/icons/typicons_dark/typ_th-menu.svg deleted file mode 100644 index 4bf1c92f..00000000 --- a/novelwriter/assets/icons/typicons_dark/typ_th-menu.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/novelwriter/assets/icons/typicons_light/icons.conf b/novelwriter/assets/icons/typicons_light/icons.conf index 22fd9456..d9aa905c 100644 --- a/novelwriter/assets/icons/typicons_light/icons.conf +++ b/novelwriter/assets/icons/typicons_light/icons.conf @@ -48,7 +48,7 @@ edit = typ_pencil.svg export = typ_export.svg forward = typ_chevron-right.svg maximise = typ_arrow-maximise.svg -menu = typ_th-menu.svg +menu = typ_th-dot-menu.svg minimise = typ_arrow-minimise.svg noncheckable = mixed_input-none.svg proj_chapter = mixed_document-chapter.svg diff --git a/novelwriter/assets/icons/typicons_light/typ_th-dot-menu.svg b/novelwriter/assets/icons/typicons_light/typ_th-dot-menu.svg new file mode 100644 index 00000000..3b5d6383 --- /dev/null +++ b/novelwriter/assets/icons/typicons_light/typ_th-dot-menu.svg @@ -0,0 +1,4 @@ + + + + diff --git a/novelwriter/assets/icons/typicons_light/typ_th-menu.svg b/novelwriter/assets/icons/typicons_light/typ_th-menu.svg deleted file mode 100644 index c23c08ca..00000000 --- a/novelwriter/assets/icons/typicons_light/typ_th-menu.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/novelwriter/core/options.py b/novelwriter/core/options.py index 0dd62f06..48a0c594 100644 --- a/novelwriter/core/options.py +++ b/novelwriter/core/options.py @@ -28,7 +28,7 @@ import json import logging from enum import Enum -from typing import TYPE_CHECKING, Any +from typing import TYPE_CHECKING, Any, TypeVar from pathlib import Path from novelwriter.error import logException @@ -40,6 +40,8 @@ if TYPE_CHECKING: # pragma: no cover logger = logging.getLogger(__name__) +NWEnum = TypeVar("NWEnum", bound=Enum) + VALID_MAP = { "GuiWritingStats": { "winWidth", "winHeight", "widthCol0", "widthCol1", "widthCol2", @@ -201,11 +203,11 @@ class OptionState: return checkBool(self._state[group].get(name, default), default) return default - def getEnum(self, group: str, name: str, lookup: type, default: Enum) -> Enum: + def getEnum(self, group: str, name: str, lookup: type, default: NWEnum) -> NWEnum: """Return the value mapped to an enum. Otherwise return the default value. """ - if issubclass(lookup, Enum): + if issubclass(lookup, type(default)): if group in self._state: if name in self._state[group]: value = self._state[group][name] diff --git a/novelwriter/gui/noveltree.py b/novelwriter/gui/noveltree.py index 0742ab54..24683733 100644 --- a/novelwriter/gui/noveltree.py +++ b/novelwriter/gui/noveltree.py @@ -29,9 +29,10 @@ import logging from enum import Enum from time import time +from typing import TYPE_CHECKING -from PyQt5.QtGui import QFont, QPalette -from PyQt5.QtCore import Qt, QSize, pyqtSlot, pyqtSignal +from PyQt5.QtGui import QFocusEvent, QFont, QMouseEvent, QPalette, QResizeEvent +from PyQt5.QtCore import QModelIndex, QPoint, Qt, QSize, pyqtSlot, pyqtSignal from PyQt5.QtWidgets import ( QAbstractItemView, QActionGroup, QFrame, QHBoxLayout, QHeaderView, QInputDialog, QMenu, QSizePolicy, QToolButton, QToolTip, QTreeWidget, @@ -42,8 +43,12 @@ from novelwriter import CONFIG, SHARED from novelwriter.enum import nwDocMode, nwItemClass, nwOutline from novelwriter.common import minmax from novelwriter.constants import nwHeaders, nwKeyWords, nwLabels, trConst +from novelwriter.core.index import IndexHeading from novelwriter.extensions.novelselector import NovelSelector +if TYPE_CHECKING: # pragma: no cover + from novelwriter.guimain import GuiMain + logger = logging.getLogger(__name__) @@ -63,7 +68,7 @@ class GuiNovelView(QWidget): selectedItemChanged = pyqtSignal(str) openDocumentRequest = pyqtSignal(str, Enum, str, bool) - def __init__(self, mainGui): + def __init__(self, mainGui: GuiMain) -> None: super().__init__(parent=mainGui) self.mainGui = mainGui @@ -92,33 +97,29 @@ class GuiNovelView(QWidget): # Methods ## - def updateTheme(self): - """Update theme elements. - """ + def updateTheme(self) -> None: + """Update theme elements.""" self.novelBar.updateTheme() self.novelTree.updateTheme() self.refreshTree() return - def initSettings(self): - """Initialise GUI elements that depend on specific settings. - """ + def initSettings(self) -> None: + """Initialise GUI elements that depend on specific settings.""" self.novelTree.initSettings() return - def clearNovelView(self): - """Clear project-related GUI content. - """ + def clearNovelView(self) -> None: + """Clear project-related GUI content.""" self.novelTree.clearContent() self.novelBar.clearContent() self.novelBar.setEnabled(False) return - def openProjectTasks(self): - """Run open project tasks. - """ + def openProjectTasks(self) -> None: + """Run open project tasks.""" lastNovel = SHARED.project.data.getLastHandle("novelTree") - if lastNovel not in SHARED.project.tree: + if lastNovel and lastNovel not in SHARED.project.tree: lastNovel = SHARED.project.tree.findRoot(nwItemClass.NOVEL) logger.debug("Setting novel tree to root item '%s'", lastNovel) @@ -140,7 +141,7 @@ class GuiNovelView(QWidget): return - def closeProjectTasks(self): + def closeProjectTasks(self) -> None: """Run closing project tasks.""" lastColType = self.novelTree.lastColType lastColSize = self.novelTree.lastColSize @@ -150,15 +151,13 @@ class GuiNovelView(QWidget): self.clearNovelView() return - def setTreeFocus(self): - """Set the focus to the tree widget. - """ + def setTreeFocus(self) -> None: + """Set the focus to the tree widget.""" self.novelTree.setFocus() return - def treeHasFocus(self): - """Check if the novel tree has focus. - """ + def treeHasFocus(self) -> bool: + """Check if the novel tree has focus.""" return self.novelTree.hasFocus() ## @@ -166,21 +165,19 @@ class GuiNovelView(QWidget): ## @pyqtSlot() - def refreshTree(self): - """Refresh the current tree. - """ + def refreshTree(self) -> None: + """Refresh the current tree.""" self.novelTree.refreshTree(rootHandle=SHARED.project.data.getLastHandle("novelTree")) return @pyqtSlot(str) - def updateRootItem(self, tHandle): - """If any root item changes, rebuild the novel root menu. - """ + def updateRootItem(self, tHandle: str) -> None: + """If any root item changes, rebuild the novel root menu.""" self.novelBar.buildNovelRootMenu() return @pyqtSlot(str) - def updateNovelItemMeta(self, tHandle): + def updateNovelItemMeta(self, tHandle: str) -> None: """The meta data of a novel item has changed, and the tree item needs to be refreshed. """ @@ -192,7 +189,7 @@ class GuiNovelView(QWidget): class GuiNovelToolBar(QWidget): - def __init__(self, novelView): + def __init__(self, novelView: GuiNovelView) -> None: super().__init__(parent=novelView) logger.debug("Create: GuiNovelToolBar") @@ -269,9 +266,8 @@ class GuiNovelToolBar(QWidget): # Methods ## - def updateTheme(self): - """Update theme elements. - """ + def updateTheme(self) -> None: + """Update theme elements.""" # Icons self.tbNovel.setIcon(SHARED.theme.getIcon("cls_novel")) self.tbRefresh.setIcon(SHARED.theme.getIcon("refresh")) @@ -287,10 +283,11 @@ class GuiNovelToolBar(QWidget): "QToolButton {{padding: {0}px; border: none; background: transparent;}} " "QToolButton:hover {{border: none; background: rgba({1},{2},{3},0.2);}}" ).format(CONFIG.pxInt(2), fadeCol.red(), fadeCol.green(), fadeCol.blue()) + buttonStyleMenu = f"{buttonStyle} QToolButton::menu-indicator {{image: none;}}" self.tbNovel.setStyleSheet(buttonStyle) self.tbRefresh.setStyleSheet(buttonStyle) - self.tbMore.setStyleSheet(buttonStyle) + self.tbMore.setStyleSheet(buttonStyleMenu) self.novelValue.setStyleSheet( "QComboBox {border-style: none; padding-left: 0;} " @@ -301,30 +298,26 @@ class GuiNovelToolBar(QWidget): return - def clearContent(self): - """Run clearing project tasks. - """ + def clearContent(self) -> None: + """Run clearing project tasks.""" self.novelValue.clear() self.novelValue.setToolTip("") return - def buildNovelRootMenu(self): - """Build the novel root menu. - """ + def buildNovelRootMenu(self) -> None: + """Build the novel root menu.""" self.novelValue.updateList(prefix=self.novelPrefix) self.tbNovel.setVisible(self.novelValue.count() > 1) return - def setCurrentRoot(self, rootHandle): - """Set the current active root handle. - """ + def setCurrentRoot(self, rootHandle: str | None) -> None: + """Set the current active root handle.""" self.novelValue.setHandle(rootHandle) self.novelView.novelTree.refreshTree(rootHandle=rootHandle, overRide=True) return - def setLastColType(self, colType, doRefresh=True): - """Set the last column type. - """ + def setLastColType(self, colType: NovelTreeColumn, doRefresh: bool = True) -> None: + """Set the last column type.""" self.aLastCol[colType].setChecked(True) self.novelView.novelTree.setLastColType(colType, doRefresh=doRefresh) return @@ -334,24 +327,21 @@ class GuiNovelToolBar(QWidget): ## @pyqtSlot() - def _openNovelSelector(self): - """Trigger the dropdown list of the novel selector. - """ + def _openNovelSelector(self) -> None: + """Trigger the dropdown list of the novel selector.""" self.novelValue.showPopup() return @pyqtSlot() - def _refreshNovelTree(self): - """Rebuild the current tree. - """ + def _refreshNovelTree(self) -> None: + """Rebuild the current tree.""" rootHandle = SHARED.project.data.getLastHandle("novelTree") self.novelView.novelTree.refreshTree(rootHandle=rootHandle, overRide=True) return @pyqtSlot() - def _selectLastColumnSize(self): - """Set the maximum width for the last column. - """ + def _selectLastColumnSize(self) -> None: + """Set the maximum width for the last column.""" oldSize = self.novelView.novelTree.lastColSize newSize, isOk = QInputDialog.getInt( self, self.tr("Column Size"), self.tr("Maximum column size in %"), oldSize, 15, 75, 5 @@ -365,9 +355,8 @@ class GuiNovelToolBar(QWidget): # Internal Functions ## - def _addLastColAction(self, colType, actionLabel): - """Add a column selection entry to the last column menu. - """ + def _addLastColAction(self, colType, actionLabel) -> None: + """Add a column selection entry to the last column menu.""" aLast = self.mLastCol.addAction(actionLabel) aLast.setCheckable(True) aLast.setActionGroup(self.gLastCol) @@ -391,7 +380,7 @@ class GuiNovelTree(QTreeWidget): D_KEY = Qt.ItemDataRole.UserRole + 2 D_EXTRA = Qt.ItemDataRole.UserRole + 3 - def __init__(self, novelView): + def __init__(self, novelView: GuiNovelView) -> None: super().__init__(parent=novelView) logger.debug("Create: GuiNovelTree") @@ -461,9 +450,8 @@ class GuiNovelTree(QTreeWidget): return - def initSettings(self): - """Set or update tree widget settings. - """ + def initSettings(self) -> None: + """Set or update tree widget settings.""" # Scroll bars if CONFIG.hideVScroll: self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) @@ -477,9 +465,8 @@ class GuiNovelTree(QTreeWidget): return - def updateTheme(self): - """Update theme elements. - """ + def updateTheme(self) -> None: + """Update theme elements.""" iPx = SHARED.theme.baseIconSize self._pMore = SHARED.theme.loadDecoration("deco_doc_more", pxH=iPx) return @@ -489,28 +476,26 @@ class GuiNovelTree(QTreeWidget): ## @property - def lastColType(self): + def lastColType(self) -> NovelTreeColumn: return self._lastCol @property - def lastColSize(self): + def lastColSize(self) -> int: return int(self._lastColSize * 100) ## # Class Methods ## - def clearContent(self): - """Clear the GUI content and the related maps. - """ + def clearContent(self) -> None: + """Clear the GUI content and the related maps.""" self.clear() self._treeMap = {} self._lastBuild = 0 return - def refreshTree(self, rootHandle=None, overRide=False): - """Refresh the tree if it has been changed. - """ + def refreshTree(self, rootHandle: str | None = None, overRide: bool = False) -> None: + """Refresh the tree if it has been changed.""" logger.debug("Requesting refresh of the novel tree") if rootHandle is None: rootHandle = SHARED.project.tree.findRoot(nwItemClass.NOVEL) @@ -534,9 +519,8 @@ class GuiNovelTree(QTreeWidget): return - def refreshHandle(self, tHandle): - """Refresh the data for a given handle. - """ + def refreshHandle(self, tHandle: str) -> None: + """Refresh the data for a given handle.""" idxData = SHARED.project.index.getItemData(tHandle) if idxData is None: return @@ -554,7 +538,7 @@ class GuiNovelTree(QTreeWidget): return - def getSelectedHandle(self): + def getSelectedHandle(self) -> tuple[str | None, str | None]: """Get the currently selected or active handle. If multiple items are selected, return the first. """ @@ -566,9 +550,8 @@ class GuiNovelTree(QTreeWidget): return tHandle, sTitle return None, None - def setLastColType(self, colType, doRefresh=True): - """Change the content type of the last column and rebuild. - """ + def setLastColType(self, colType: NovelTreeColumn, doRefresh: bool = True) -> None: + """Change the content type of the last column and rebuild.""" if self._lastCol != colType: logger.debug("Changing last column to %s", colType.name) self._lastCol = colType @@ -578,15 +561,13 @@ class GuiNovelTree(QTreeWidget): self.refreshTree(rootHandle=lastNovel, overRide=True) return - def setLastColSize(self, colSize): - """Set the column size in integer values between 15 and 75. - """ + def setLastColSize(self, colSize: int) -> None: + """Set the column size in integer values between 15 and 75.""" self._lastColSize = minmax(colSize, 15, 75)/100.0 return - def setActiveHandle(self, tHandle): - """Highlight the rows associated with a given handle. - """ + def setActiveHandle(self, tHandle: str | None) -> None: + """Highlight the rows associated with a given handle.""" tStart = time() self._actHandle = tHandle @@ -612,20 +593,20 @@ class GuiNovelTree(QTreeWidget): # Events ## - def mousePressEvent(self, theEvent): + def mousePressEvent(self, event: QMouseEvent) -> None: """Overload mousePressEvent to clear selection if clicking the mouse in a blank area of the tree view, and to load a document for viewing if the user middle-clicked. """ - super().mousePressEvent(theEvent) + super().mousePressEvent(event) - if theEvent.button() == Qt.LeftButton: - selItem = self.indexAt(theEvent.pos()) + if event.button() == Qt.LeftButton: + selItem = self.indexAt(event.pos()) if not selItem.isValid(): self.clearSelection() - elif theEvent.button() == Qt.MiddleButton: - selItem = self.itemAt(theEvent.pos()) + elif event.button() == Qt.MiddleButton: + selItem = self.itemAt(event.pos()) if not isinstance(selItem, QTreeWidgetItem): return @@ -637,16 +618,14 @@ class GuiNovelTree(QTreeWidget): return - def focusOutEvent(self, theEvent): - """Clear the selection when the tree no longer has focus. - """ - super().focusOutEvent(theEvent) + def focusOutEvent(self, event: QFocusEvent) -> None: + """Clear the selection when the tree no longer has focus.""" + super().focusOutEvent(event) self.clearSelection() return - def resizeEvent(self, event): - """Elide labels in the extra column. - """ + def resizeEvent(self, event: QResizeEvent) -> None: + """Elide labels in the extra column.""" super().resizeEvent(event) newW = event.size().width() oldW = event.oldSize().width() @@ -665,18 +644,17 @@ class GuiNovelTree(QTreeWidget): ## @pyqtSlot("QModelIndex") - def _treeItemClicked(self, mIndex): - """The user clicked on an item in the tree. - """ - if mIndex.column() == self.C_MORE: - tHandle = mIndex.siblingAtColumn(self.C_DATA).data(self.D_HANDLE) - sTitle = mIndex.siblingAtColumn(self.C_DATA).data(self.D_TITLE) - tipPos = self.mapToGlobal(self.visualRect(mIndex).topRight()) + def _treeItemClicked(self, index: QModelIndex) -> None: + """The user clicked on an item in the tree.""" + if index.column() == self.C_MORE: + tHandle = index.siblingAtColumn(self.C_DATA).data(self.D_HANDLE) + sTitle = index.siblingAtColumn(self.C_DATA).data(self.D_TITLE) + tipPos = self.mapToGlobal(self.visualRect(index).topRight()) self._popMetaBox(tipPos, tHandle, sTitle) return @pyqtSlot() - def _treeSelectionChange(self): + def _treeSelectionChange(self) -> None: """Extract the handle and line number of the currently selected title, and send it to the tree meta panel. """ @@ -686,7 +664,7 @@ class GuiNovelTree(QTreeWidget): return @pyqtSlot("QTreeWidgetItem*", int) - def _treeDoubleClick(self, tItem, colNo): + def _treeDoubleClick(self, item: QTreeWidgetItem, column: int) -> None: """Extract the handle and line number of the title double- clicked, and send it to the main gui class for opening in the document editor. @@ -699,9 +677,8 @@ class GuiNovelTree(QTreeWidget): # Internal Functions ## - def _populateTree(self, rootHandle): - """Build the tree based on the project index. - """ + def _populateTree(self, rootHandle: str | None) -> None: + """Build the tree based on the project index.""" self.clearContent() tStart = time() logger.debug("Building novel tree for root item '%s'", rootHandle) @@ -728,9 +705,9 @@ class GuiNovelTree(QTreeWidget): return - def _updateTreeItemValues(self, trItem, idxItem, tHandle, sTitle): - """Set the tree item values from the index entry. - """ + def _updateTreeItemValues(self, trItem: QTreeWidgetItem, idxItem: IndexHeading, + tHandle: str, sTitle: str) -> None: + """Set the tree item values from the index entry.""" iLevel = nwHeaders.H_LEVEL.get(idxItem.level, 0) hDec = SHARED.theme.getHeaderDecoration(iLevel) @@ -750,9 +727,8 @@ class GuiNovelTree(QTreeWidget): return - def _getLastColumnText(self, tHandle, sTitle): - """Generate the text for the last column based on user settings. - """ + def _getLastColumnText(self, tHandle: str, sTitle: str) -> tuple[str, str]: + """Generate text for the last column based on user settings.""" if self._lastCol == NovelTreeColumn.HIDDEN: return "", "" @@ -777,14 +753,15 @@ class GuiNovelTree(QTreeWidget): return "", "" - def _popMetaBox(self, qPos, tHandle, sTitle): - """Show the novel meta data box. - """ + def _popMetaBox(self, qPos: QPoint, tHandle: str, sTitle: str) -> None: + """Show the novel meta data box.""" logger.debug("Generating meta data tooltip for '%s:%s'", tHandle, sTitle) pIndex = SHARED.project.index novIdx = pIndex.getItemHeader(tHandle, sTitle) refTags = pIndex.getReferences(tHandle, sTitle) + if not novIdx: + return synopText = novIdx.synopsis if synopText: @@ -814,9 +791,8 @@ class GuiNovelTree(QTreeWidget): return @staticmethod - def _appendMetaTag(refs, key, lines): - """Generate a reference list for a given reference key. - """ + def _appendMetaTag(refs: dict, key: str, lines: list[str]) -> list[str]: + """Generate a reference list for a given reference key.""" tags = ", ".join(refs.get(key, [])) if tags: lines.append(f"{trConst(nwLabels.KEY_NAME[key])}: {tags}") diff --git a/novelwriter/gui/outline.py b/novelwriter/gui/outline.py index 84234ccf..596a422b 100644 --- a/novelwriter/gui/outline.py +++ b/novelwriter/gui/outline.py @@ -261,6 +261,7 @@ class GuiOutlineToolBar(QToolBar): self.novelValue.updateList(includeAll=True) self.aRefresh.setIcon(SHARED.theme.getIcon("refresh")) self.tbColumns.setIcon(SHARED.theme.getIcon("menu")) + self.tbColumns.setStyleSheet("QToolButton::menu-indicator {image: none;}") return def populateNovelList(self) -> None: diff --git a/novelwriter/gui/projtree.py b/novelwriter/gui/projtree.py index 787f5671..d1c2f903 100644 --- a/novelwriter/gui/projtree.py +++ b/novelwriter/gui/projtree.py @@ -361,12 +361,13 @@ class GuiProjectToolBar(QWidget): "QToolButton {{padding: {0}px; border: none; background: transparent;}} " "QToolButton:hover {{border: none; background: rgba({1},{2},{3},0.2);}}" ).format(CONFIG.pxInt(2), fadeCol.red(), fadeCol.green(), fadeCol.blue()) + buttonStyleMenu = f"{buttonStyle} QToolButton::menu-indicator {{image: none;}}" - self.tbQuick.setStyleSheet(buttonStyle) + self.tbQuick.setStyleSheet(buttonStyleMenu) self.tbMoveU.setStyleSheet(buttonStyle) self.tbMoveD.setStyleSheet(buttonStyle) - self.tbAdd.setStyleSheet(buttonStyle) - self.tbMore.setStyleSheet(buttonStyle) + self.tbAdd.setStyleSheet(buttonStyleMenu) + self.tbMore.setStyleSheet(buttonStyleMenu) self.tbQuick.setIcon(SHARED.theme.getIcon("bookmark")) self.tbMoveU.setIcon(SHARED.theme.getIcon("up"))