diff --git a/novelwriter/assets/icons/typicons_dark/icons.conf b/novelwriter/assets/icons/typicons_dark/icons.conf index c8446123..94b4c633 100644 --- a/novelwriter/assets/icons/typicons_dark/icons.conf +++ b/novelwriter/assets/icons/typicons_dark/icons.conf @@ -46,6 +46,14 @@ cross = typ_times.svg down = typ_chevron-down.svg edit = typ_pencil.svg export = typ_export.svg +fmt_bold = nw_tb-bold.svg +fmt_italic = nw_tb-italic.svg +fmt_mode-md = nw_tb-markdown.svg +fmt_mode-sc = nw_tb-shortcode.svg +fmt_strike = nw_tb-strike.svg +fmt_subscript = nw_tb-subscript.svg +fmt_superscript = nw_tb-superscript.svg +fmt_underline = nw_tb-underline.svg forward = typ_chevron-right.svg maximise = typ_arrow-maximise.svg menu = typ_th-dot-menu.svg diff --git a/novelwriter/assets/icons/typicons_dark/nw_tb-bold.svg b/novelwriter/assets/icons/typicons_dark/nw_tb-bold.svg new file mode 100644 index 00000000..2eaeb846 --- /dev/null +++ b/novelwriter/assets/icons/typicons_dark/nw_tb-bold.svg @@ -0,0 +1,4 @@ + + + + diff --git a/novelwriter/assets/icons/typicons_dark/nw_tb-italic.svg b/novelwriter/assets/icons/typicons_dark/nw_tb-italic.svg new file mode 100644 index 00000000..0ec5fb2a --- /dev/null +++ b/novelwriter/assets/icons/typicons_dark/nw_tb-italic.svg @@ -0,0 +1,4 @@ + + + + diff --git a/novelwriter/assets/icons/typicons_dark/nw_tb-markdown.svg b/novelwriter/assets/icons/typicons_dark/nw_tb-markdown.svg new file mode 100644 index 00000000..02768596 --- /dev/null +++ b/novelwriter/assets/icons/typicons_dark/nw_tb-markdown.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/novelwriter/assets/icons/typicons_dark/nw_tb-shortcode.svg b/novelwriter/assets/icons/typicons_dark/nw_tb-shortcode.svg new file mode 100644 index 00000000..4ea59ec3 --- /dev/null +++ b/novelwriter/assets/icons/typicons_dark/nw_tb-shortcode.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/novelwriter/assets/icons/typicons_dark/nw_tb-strike.svg b/novelwriter/assets/icons/typicons_dark/nw_tb-strike.svg new file mode 100644 index 00000000..639dd694 --- /dev/null +++ b/novelwriter/assets/icons/typicons_dark/nw_tb-strike.svg @@ -0,0 +1,4 @@ + + + + diff --git a/novelwriter/assets/icons/typicons_dark/nw_tb-subscript.svg b/novelwriter/assets/icons/typicons_dark/nw_tb-subscript.svg new file mode 100644 index 00000000..7566bdee --- /dev/null +++ b/novelwriter/assets/icons/typicons_dark/nw_tb-subscript.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/novelwriter/assets/icons/typicons_dark/nw_tb-superscript.svg b/novelwriter/assets/icons/typicons_dark/nw_tb-superscript.svg new file mode 100644 index 00000000..0ac13bf3 --- /dev/null +++ b/novelwriter/assets/icons/typicons_dark/nw_tb-superscript.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/novelwriter/assets/icons/typicons_dark/nw_tb-underline.svg b/novelwriter/assets/icons/typicons_dark/nw_tb-underline.svg new file mode 100644 index 00000000..3a249f4d --- /dev/null +++ b/novelwriter/assets/icons/typicons_dark/nw_tb-underline.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/novelwriter/assets/icons/typicons_light/icons.conf b/novelwriter/assets/icons/typicons_light/icons.conf index d9aa905c..62314511 100644 --- a/novelwriter/assets/icons/typicons_light/icons.conf +++ b/novelwriter/assets/icons/typicons_light/icons.conf @@ -46,6 +46,14 @@ cross = typ_times.svg down = typ_chevron-down.svg edit = typ_pencil.svg export = typ_export.svg +fmt_bold = nw_tb-bold.svg +fmt_italic = nw_tb-italic.svg +fmt_mode-md = nw_tb-markdown.svg +fmt_mode-sc = nw_tb-shortcode.svg +fmt_strike = nw_tb-strike.svg +fmt_subscript = nw_tb-subscript.svg +fmt_superscript = nw_tb-superscript.svg +fmt_underline = nw_tb-underline.svg forward = typ_chevron-right.svg maximise = typ_arrow-maximise.svg menu = typ_th-dot-menu.svg diff --git a/novelwriter/assets/icons/typicons_light/nw_tb-bold.svg b/novelwriter/assets/icons/typicons_light/nw_tb-bold.svg new file mode 100644 index 00000000..3fbfbc88 --- /dev/null +++ b/novelwriter/assets/icons/typicons_light/nw_tb-bold.svg @@ -0,0 +1,4 @@ + + + + diff --git a/novelwriter/assets/icons/typicons_light/nw_tb-italic.svg b/novelwriter/assets/icons/typicons_light/nw_tb-italic.svg new file mode 100644 index 00000000..893d8930 --- /dev/null +++ b/novelwriter/assets/icons/typicons_light/nw_tb-italic.svg @@ -0,0 +1,4 @@ + + + + diff --git a/novelwriter/assets/icons/typicons_light/nw_tb-markdown.svg b/novelwriter/assets/icons/typicons_light/nw_tb-markdown.svg new file mode 100644 index 00000000..24b3809d --- /dev/null +++ b/novelwriter/assets/icons/typicons_light/nw_tb-markdown.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/novelwriter/assets/icons/typicons_light/nw_tb-shortcode.svg b/novelwriter/assets/icons/typicons_light/nw_tb-shortcode.svg new file mode 100644 index 00000000..fc19a690 --- /dev/null +++ b/novelwriter/assets/icons/typicons_light/nw_tb-shortcode.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/novelwriter/assets/icons/typicons_light/nw_tb-strike.svg b/novelwriter/assets/icons/typicons_light/nw_tb-strike.svg new file mode 100644 index 00000000..89f4b7ee --- /dev/null +++ b/novelwriter/assets/icons/typicons_light/nw_tb-strike.svg @@ -0,0 +1,4 @@ + + + + diff --git a/novelwriter/assets/icons/typicons_light/nw_tb-underline.svg b/novelwriter/assets/icons/typicons_light/nw_tb-underline.svg new file mode 100644 index 00000000..ca122269 --- /dev/null +++ b/novelwriter/assets/icons/typicons_light/nw_tb-underline.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/novelwriter/gui/doceditor.py b/novelwriter/gui/doceditor.py index f12220e5..6e204219 100644 --- a/novelwriter/gui/doceditor.py +++ b/novelwriter/gui/doceditor.py @@ -2107,18 +2107,39 @@ class GuiDocToolBar(QWidget): # General Buttons # =============== - self.tbSticky = QToolButton(self) - self.tbSticky.setIconSize(iconSize) + self.tbMode = QToolButton(self) + self.tbMode.setIconSize(iconSize) + self.tbMode.setCheckable(True) - self.tbEdit = QToolButton(self) - self.tbEdit.setIconSize(iconSize) + self.tbBold = QToolButton(self) + self.tbBold.setIconSize(iconSize) + + self.tbItalic = QToolButton(self) + self.tbItalic.setIconSize(iconSize) + + self.tbStrike = QToolButton(self) + self.tbStrike.setIconSize(iconSize) + + self.tbUnderline = QToolButton(self) + self.tbUnderline.setIconSize(iconSize) + + self.tbSuperscript = QToolButton(self) + self.tbSuperscript.setIconSize(iconSize) + + self.tbSubscript = QToolButton(self) + self.tbSubscript.setIconSize(iconSize) # Assemble # ======== self.outerBox = QVBoxLayout() - self.outerBox.addWidget(self.tbSticky) - self.outerBox.addWidget(self.tbEdit) + self.outerBox.addWidget(self.tbMode) + self.outerBox.addWidget(self.tbBold) + self.outerBox.addWidget(self.tbItalic) + self.outerBox.addWidget(self.tbStrike) + self.outerBox.addWidget(self.tbUnderline) + self.outerBox.addWidget(self.tbSuperscript) + self.outerBox.addWidget(self.tbSubscript) self.outerBox.setContentsMargins(cM, cM, cM, cM) self.outerBox.setSpacing(cM) @@ -2150,8 +2171,14 @@ class GuiDocToolBar(QWidget): # buttonStyleMenu = f"{buttonStyle} QToolButton::menu-indicator {{image: none;}}" # self.tbEdit.setStyleSheet(buttonStyle) - self.tbSticky.setIcon(SHARED.theme.getIcon("sticky-off")) - self.tbEdit.setIcon(SHARED.theme.getIcon("edit")) + tPx = int(0.8*SHARED.theme.fontPixelSize) + self.tbMode.setIcon(SHARED.theme.getToggleIcon("fmt_mode", (tPx, tPx))) + self.tbBold.setIcon(SHARED.theme.getIcon("fmt_bold")) + self.tbItalic.setIcon(SHARED.theme.getIcon("fmt_italic")) + self.tbStrike.setIcon(SHARED.theme.getIcon("fmt_strike")) + self.tbUnderline.setIcon(SHARED.theme.getIcon("fmt_underline")) + self.tbSuperscript.setIcon(SHARED.theme.getIcon("fmt_superscript")) + self.tbSubscript.setIcon(SHARED.theme.getIcon("fmt_subscript")) return diff --git a/novelwriter/gui/docviewer.py b/novelwriter/gui/docviewer.py index 9aff4eee..ff548fb6 100644 --- a/novelwriter/gui/docviewer.py +++ b/novelwriter/gui/docviewer.py @@ -34,8 +34,8 @@ from typing import TYPE_CHECKING from PyQt5.QtCore import pyqtSignal, pyqtSlot, QPoint, QSize, Qt, QUrl from PyQt5.QtGui import ( - QColor, QCursor, QFont, QIcon, QMouseEvent, QPalette, QResizeEvent, - QTextCursor, QTextOption + QColor, QCursor, QFont, QMouseEvent, QPalette, QResizeEvent, QTextCursor, + QTextOption ) from PyQt5.QtWidgets import ( QAction, qApp, QFrame, QHBoxLayout, QLabel, QMenu, QScrollArea, @@ -1020,24 +1020,12 @@ class GuiDocViewFooter(QWidget): # Methods ## - def updateTheme(self): - """Update theme elements. - """ + def updateTheme(self) -> None: + """Update theme elements.""" # Icons - fPx = int(0.9*SHARED.theme.fontPixelSize) - - stickyOn = SHARED.theme.getPixmap("sticky-on", (fPx, fPx)) - stickyOff = SHARED.theme.getPixmap("sticky-off", (fPx, fPx)) - stickyIcon = QIcon() - stickyIcon.addPixmap(stickyOn, QIcon.Normal, QIcon.On) - stickyIcon.addPixmap(stickyOff, QIcon.Normal, QIcon.Off) - - bulletOn = SHARED.theme.getPixmap("bullet-on", (fPx, fPx)) - bulletOff = SHARED.theme.getPixmap("bullet-off", (fPx, fPx)) - bulletIcon = QIcon() - bulletIcon.addPixmap(bulletOn, QIcon.Normal, QIcon.On) - bulletIcon.addPixmap(bulletOff, QIcon.Normal, QIcon.Off) + stickyIcon = SHARED.theme.getToggleIcon("sticky", (fPx, fPx)) + bulletIcon = SHARED.theme.getToggleIcon("bullet", (fPx, fPx)) self.showHide.setIcon(SHARED.theme.getIcon("reference")) self.stickyRefs.setIcon(stickyIcon) diff --git a/novelwriter/gui/theme.py b/novelwriter/gui/theme.py index da8f1be4..22d8cf95 100644 --- a/novelwriter/gui/theme.py +++ b/novelwriter/gui/theme.py @@ -130,6 +130,7 @@ class GuiTheme: self.getIcon = self.iconCache.getIcon self.getPixmap = self.iconCache.getPixmap self.getItemIcon = self.iconCache.getItemIcon + self.getToggleIcon = self.iconCache.getToggleIcon self.loadDecoration = self.iconCache.loadDecoration self.getHeaderDecoration = self.iconCache.getHeaderDecoration @@ -447,14 +448,22 @@ class GuiIcons: ICON_KEYS = { # Project and GUI Icons "novelwriter", "alert_error", "alert_info", "alert_question", "alert_warn", - "build_excluded", "build_filtered", "build_included", "cls_archive", "cls_character", - "cls_custom", "cls_entity", "cls_none", "cls_novel", "cls_object", "cls_plot", - "cls_timeline", "cls_trash", "cls_world", "proj_chapter", "proj_details", "proj_document", - "proj_folder", "proj_note", "proj_nwx", "proj_section", "proj_scene", "proj_stats", - "proj_title", "search_cancel", "search_case", "search_loop", "search_preserve", - "search_project", "search_regex", "search_word", "status_idle", "status_lang", - "status_lines", "status_stats", "status_time", "view_build", "view_editor", "view_novel", - "view_outline", + "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", + + # Class Icons + "cls_archive", "cls_character", "cls_custom", "cls_entity", "cls_none", "cls_novel", + "cls_object", "cls_plot", "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_italic", "fmt_mode-md", "fmt_mode-sc", "fmt_strike", "fmt_subscript", + "fmt_superscript", "fmt_underline", # General Button Icons "add", "backward", "bookmark", "browse", "checked", "close", "cross", "down", "edit", @@ -469,6 +478,12 @@ class GuiIcons: "deco_doc_h0", "deco_doc_h1", "deco_doc_h2", "deco_doc_h3", "deco_doc_h4", "deco_doc_more", } + TOGGLE_ICON_KEYS = { + "sticky": ("sticky-on", "sticky-off"), + "bullet": ("bullet-on", "bullet-off"), + "fmt_mode": ("fmt_mode-sc", "fmt_mode-md"), + } + IMAGE_MAP = { "wiz-back": "wizard-back.jpg", } @@ -602,10 +617,7 @@ class GuiIcons: return theDeco def getIcon(self, iconKey): - """Return an icon from the icon buffer. If it doesn't exist, - return, load it, and if it still doesn't exist, return an empty - icon. - """ + """Return an icon from the icon buffer, or load it.""" if iconKey in self._qIcons: return self._qIcons[iconKey] else: @@ -613,6 +625,17 @@ class GuiIcons: self._qIcons[iconKey] = qIcon return qIcon + def getToggleIcon(self, iconKey: str, iconSize: tuple[int, int]) -> QIcon: + """Return a toggle icon from the icon buffer. or load it.""" + if iconKey in self.TOGGLE_ICON_KEYS: + pixOne = self.getPixmap(self.TOGGLE_ICON_KEYS[iconKey][0], iconSize) + pixTwo = self.getPixmap(self.TOGGLE_ICON_KEYS[iconKey][1], iconSize) + qIcon = QIcon() + qIcon.addPixmap(pixOne, QIcon.Normal, QIcon.On) + qIcon.addPixmap(pixTwo, QIcon.Normal, QIcon.Off) + return qIcon + return QIcon() + def getPixmap(self, iconKey, iconSize): """Return an icon from the icon buffer as a QPixmap. If it doesn't exist, return an empty QPixmap.