diff --git a/novelwriter/assets/icons/remix_filled.icons b/novelwriter/assets/icons/remix_filled.icons
new file mode 100644
index 00000000..f811c500
--- /dev/null
+++ b/novelwriter/assets/icons/remix_filled.icons
@@ -0,0 +1,106 @@
+# This file is automatically generated. Do not edit.
+
+# Meta
+meta:name = Remix Icon - Filled
+meta:author = Remix Icon
+meta:license = Apache 2.0
+
+# Icons
+icon:alert_error =
+icon:alert_info =
+icon:alert_question =
+icon:alert_warn =
+icon:cls_archive =
+icon:cls_character =
+icon:cls_custom =
+icon:cls_entity =
+icon:cls_none =
+icon:cls_novel =
+icon:cls_object =
+icon:cls_plot =
+icon:cls_template =
+icon:cls_timeline =
+icon:cls_trash =
+icon:cls_world =
+icon:prj_folder =
+icon:prj_document =
+icon:prj_title =
+icon:prj_chapter =
+icon:prj_scene =
+icon:prj_note =
+icon:fmt_bold =
+icon:fmt_italic =
+icon:fmt_mark =
+icon:fmt_strike =
+icon:fmt_subscript =
+icon:fmt_superscript =
+icon:fmt_underline =
+icon:fmt_toolbar =
+icon:search =
+icon:search_cancel =
+icon:search_case =
+icon:search_loop =
+icon:search_preserve =
+icon:search_project =
+icon:search_regex =
+icon:search_replace =
+icon:search_word =
+icon:bullet-off =
+icon:bullet-on =
+icon:unfold-hide =
+icon:unfold-show =
+icon:sb_build =
+icon:sb_novel =
+icon:sb_outline =
+icon:sb_project =
+icon:sb_search =
+icon:add =
+icon:bookmarks =
+icon:browse =
+icon:build_settings =
+icon:cancel =
+icon:checked =
+icon:chevron_down =
+icon:chevron_left =
+icon:chevron_right =
+icon:chevron_up =
+icon:close =
+icon:copy =
+icon:document_add =
+icon:document =
+icon:edit =
+icon:exclude =
+icon:export =
+icon:filter =
+icon:fit_height =
+icon:fit_width =
+icon:folder =
+icon:font =
+icon:import =
+icon:language =
+icon:lines =
+icon:list =
+icon:margin_bottom =
+icon:margin_left =
+icon:margin_right =
+icon:margin_top =
+icon:maximise =
+icon:minimise =
+icon:more_arrow =
+icon:more_vertical =
+icon:noncheckable =
+icon:open =
+icon:panel =
+icon:pin =
+icon:quote =
+icon:refresh =
+icon:remove =
+icon:revert =
+icon:settings =
+icon:star =
+icon:stats =
+icon:text =
+icon:timer_off =
+icon:timer =
+icon:unchecked =
+icon:view =
diff --git a/novelwriter/assets/icons/remix_outline.icons b/novelwriter/assets/icons/remix_outline.icons
new file mode 100644
index 00000000..ecf7e9ab
--- /dev/null
+++ b/novelwriter/assets/icons/remix_outline.icons
@@ -0,0 +1,106 @@
+# This file is automatically generated. Do not edit.
+
+# Meta
+meta:name = Remix Icon - Outline
+meta:author = Remix Icon
+meta:license = Apache 2.0
+
+# Icons
+icon:alert_error =
+icon:alert_info =
+icon:alert_question =
+icon:alert_warn =
+icon:cls_archive =
+icon:cls_character =
+icon:cls_custom =
+icon:cls_entity =
+icon:cls_none =
+icon:cls_novel =
+icon:cls_object =
+icon:cls_plot =
+icon:cls_template =
+icon:cls_timeline =
+icon:cls_trash =
+icon:cls_world =
+icon:prj_folder =
+icon:prj_document =
+icon:prj_title =
+icon:prj_chapter =
+icon:prj_scene =
+icon:prj_note =
+icon:fmt_bold =
+icon:fmt_italic =
+icon:fmt_mark =
+icon:fmt_strike =
+icon:fmt_subscript =
+icon:fmt_superscript =
+icon:fmt_underline =
+icon:fmt_toolbar =
+icon:search =
+icon:search_cancel =
+icon:search_case =
+icon:search_loop =
+icon:search_preserve =
+icon:search_project =
+icon:search_regex =
+icon:search_replace =
+icon:search_word =
+icon:bullet-off =
+icon:bullet-on =
+icon:unfold-hide =
+icon:unfold-show =
+icon:sb_build =
+icon:sb_novel =
+icon:sb_outline =
+icon:sb_project =
+icon:sb_search =
+icon:add =
+icon:bookmarks =
+icon:browse =
+icon:build_settings =
+icon:cancel =
+icon:checked =
+icon:chevron_down =
+icon:chevron_left =
+icon:chevron_right =
+icon:chevron_up =
+icon:close =
+icon:copy =
+icon:document_add =
+icon:document =
+icon:edit =
+icon:exclude =
+icon:export =
+icon:filter =
+icon:fit_height =
+icon:fit_width =
+icon:folder =
+icon:font =
+icon:import =
+icon:language =
+icon:lines =
+icon:list =
+icon:margin_bottom =
+icon:margin_left =
+icon:margin_right =
+icon:margin_top =
+icon:maximise =
+icon:minimise =
+icon:more_arrow =
+icon:more_vertical =
+icon:noncheckable =
+icon:open =
+icon:panel =
+icon:pin =
+icon:quote =
+icon:refresh =
+icon:remove =
+icon:revert =
+icon:settings =
+icon:star =
+icon:stats =
+icon:text =
+icon:timer_off =
+icon:timer =
+icon:unchecked =
+icon:view =
diff --git a/novelwriter/tools/manusbuild.py b/novelwriter/tools/manusbuild.py
index 4c90aa73..b636ac3c 100644
--- a/novelwriter/tools/manusbuild.py
+++ b/novelwriter/tools/manusbuild.py
@@ -189,7 +189,7 @@ class GuiManuscriptBuild(NDialog):
self.buttonBox.addButton(self.btnOpen, QtRoleAction)
self.btnBuild = QPushButton(
- SHARED.theme.getIcon("manuscript", "blue"), self.tr("&Build"), self
+ SHARED.theme.getIcon("sb_build", "blue"), self.tr("&Build"), self
)
self.btnBuild.setIconSize(bSz)
self.btnBuild.setAutoDefault(True)
diff --git a/novelwriter/tools/manuscript.py b/novelwriter/tools/manuscript.py
index c0ea46f5..07501af1 100644
--- a/novelwriter/tools/manuscript.py
+++ b/novelwriter/tools/manuscript.py
@@ -490,7 +490,7 @@ class GuiManuscript(NToolDialog):
for key, name in self._builds.builds():
bItem = QListWidgetItem()
bItem.setText(name)
- bItem.setIcon(SHARED.theme.getIcon("manuscript", "blue"))
+ bItem.setIcon(SHARED.theme.getIcon("build_settings", "blue"))
bItem.setData(self.D_KEY, key)
self.buildList.addItem(bItem)
self._buildMap[key] = bItem
diff --git a/pkgutils.py b/pkgutils.py
index aa4ddad6..8e0d5cbf 100755
--- a/pkgutils.py
+++ b/pkgutils.py
@@ -35,7 +35,7 @@ import zipfile
from pathlib import Path
-from utils.icon_themes import processFontAwesome, processMaterialIcons
+from utils.icon_themes import processFontAwesome, processMaterialIcons, processRemix
CURR_DIR = Path(__file__).parent
SETUP_DIR = CURR_DIR / "setup"
@@ -391,6 +391,18 @@ def buildIconTheme(args: argparse.Namespace) -> None:
},
})
+ if style in ("all", "remix"):
+ processRemix(workDir, iconsDir, {
+ "remix_outline": {
+ "name": "Remix Icon - Outline",
+ "filled": False,
+ },
+ "remix_filled": {
+ "name": "Remix Icon - Filled",
+ "filled": True,
+ },
+ })
+
print("Done")
print("")
diff --git a/utils/icon_themes.py b/utils/icon_themes.py
index 01a5bdf6..53d974d5 100644
--- a/utils/icon_themes.py
+++ b/utils/icon_themes.py
@@ -27,10 +27,7 @@ from pathlib import Path
from xml.etree import ElementTree as ET
UTILS = Path(__file__).parent
-
ET.register_namespace("", "http://www.w3.org/2000/svg")
-MATERIAL_REPO = "https://github.com/google/material-design-icons.git"
-FONT_AWESOME_REPO = "https://github.com/FortAwesome/Font-Awesome.git"
ICONS = [
"alert_error",
"alert_info",
@@ -81,15 +78,16 @@ ICONS = [
"unfold-hide",
"unfold-show",
- "sb_project",
- "sb_novel",
- "sb_search",
- "sb_outline",
"sb_build",
+ "sb_novel",
+ "sb_outline",
+ "sb_project",
+ "sb_search",
"add",
"bookmarks",
"browse",
+ "build_settings",
"cancel",
"checked",
"chevron_down",
@@ -112,7 +110,6 @@ ICONS = [
"language",
"lines",
"list",
- "manuscript",
"margin_bottom",
"margin_left",
"margin_right",
@@ -194,7 +191,7 @@ def _cloneRepo(repoPath: Path, repoUrl: str) -> None:
def processMaterialIcons(workDir: Path, iconsDir: Path, jobs: dict) -> None:
"""Process material icons of a given spec and write output file."""
srcRepo = workDir / "material-design-icons"
- _cloneRepo(srcRepo, MATERIAL_REPO)
+ _cloneRepo(srcRepo, "https://github.com/google/material-design-icons.git")
for file, job in jobs.items():
name: str = job["name"]
@@ -211,10 +208,10 @@ def processMaterialIcons(workDir: Path, iconsDir: Path, jobs: dict) -> None:
iconSrc = srcRepo / "symbols" / "web"
for key, icon in _loadMap("material_symbols").items():
if kind:
- fileNmae = f"{icon}_{kind}_24px.svg"
+ fileName = f"{icon}_{kind}_24px.svg"
else:
- fileNmae = f"{icon}_24px.svg"
- iconFile = iconSrc / icon / f"materialsymbols{style}" / fileNmae
+ fileName = f"{icon}_24px.svg"
+ iconFile = iconSrc / icon / f"materialsymbols{style}" / fileName
if iconFile.is_file():
icons[key] = ET.fromstring(iconFile.read_text(encoding="utf-8"))
else:
@@ -231,7 +228,7 @@ def processMaterialIcons(workDir: Path, iconsDir: Path, jobs: dict) -> None:
def processFontAwesome(workDir: Path, iconsDir: Path, jobs: dict) -> None:
"""Process Font Awesome icons of a given spec and write output file."""
srcRepo = workDir / "Font-Awesome"
- _cloneRepo(srcRepo, FONT_AWESOME_REPO)
+ _cloneRepo(srcRepo, "https://github.com/FortAwesome/Font-Awesome.git")
for file, job in jobs.items():
name: str = job["name"]
@@ -271,3 +268,46 @@ def processFontAwesome(workDir: Path, iconsDir: Path, jobs: dict) -> None:
print("")
return
+
+
+def processRemix(workDir: Path, iconsDir: Path, jobs: dict) -> None:
+ """Process Remix icons of a given spec and write output file."""
+ srcRepo = workDir / "RemixIcon"
+ _cloneRepo(srcRepo, "https://github.com/Remix-Design/RemixIcon.git")
+
+ for file, job in jobs.items():
+ name: str = job["name"]
+ style = "fill" if job["filled"] else "line"
+
+ print(f"Processing: {name}")
+
+ icons: dict[str, ET.Element] = {}
+ iconSrc = srcRepo / "icons"
+ iconGroups = [x for x in iconSrc.iterdir() if x.is_dir()]
+ for key, icon in _loadMap("remix").items():
+ if icon.endswith(("-line", "-fill")):
+ fileName = f"{icon}.svg"
+ else:
+ fileName = f"{icon}-{style}.svg"
+ for group in iconGroups:
+ iconFile = group / fileName
+ if iconFile.is_file():
+ break
+ else:
+ fileName = f"{icon}.svg"
+ for group in iconGroups:
+ iconFile = group / fileName
+ if iconFile.is_file():
+ break
+ else:
+ print(f"Not Found: {fileName}")
+ continue
+
+ icons[key] = ET.fromstring(iconFile.read_text(encoding="utf-8"))
+
+ target = iconsDir / f"{file}.icons"
+ _writeThemeFile(target, name, "Remix Icon", "Apache 2.0", icons)
+
+ print("")
+
+ return
diff --git a/utils/remix.json b/utils/remix.json
new file mode 100644
index 00000000..f62a9ee6
--- /dev/null
+++ b/utils/remix.json
@@ -0,0 +1,108 @@
+{
+ "alert_error": "error-warning",
+ "alert_info": "information",
+ "alert_question": "question",
+ "alert_warn": "alarm-warning",
+
+ "cls_archive": "archive",
+ "cls_character": "group",
+ "cls_custom": "price-tag-3",
+ "cls_entity": "building",
+ "cls_none": "checkbox-blank",
+ "cls_novel": "git-repository",
+ "cls_object": "key-2",
+ "cls_plot": "puzzle-2",
+ "cls_template": "folder-add",
+ "cls_timeline": "hourglass",
+ "cls_trash": "delete-bin",
+ "cls_world": "earth",
+
+ "prj_folder": "folder-6",
+ "prj_document": "file-text",
+ "prj_title": "file-text",
+ "prj_chapter": "file-text",
+ "prj_scene": "file-text",
+ "prj_note": "file-4",
+
+ "fmt_bold": "bold",
+ "fmt_italic": "italic",
+ "fmt_mark": "mark-pen",
+ "fmt_strike": "strikethrough",
+ "fmt_subscript": "subscript",
+ "fmt_superscript": "superscript",
+ "fmt_underline": "underline",
+ "fmt_toolbar": "font-color",
+
+ "search": "search-line",
+ "search_cancel": "close",
+ "search_case": "font-size",
+ "search_loop": "loop-right",
+ "search_preserve": "font-size-2",
+ "search_project": "file-search",
+ "search_regex": "asterisk",
+ "search_replace": "find-replace-line",
+ "search_word": "space",
+
+ "bullet-off": "checkbox-blank-circle-line",
+ "bullet-on": "checkbox-blank-circle-fill",
+ "unfold-hide": "arrow-right-s-fill",
+ "unfold-show": "arrow-down-s-fill",
+
+ "sb_build": "stack",
+ "sb_novel": "booklet",
+ "sb_outline": "table-view",
+ "sb_project": "file-edit",
+ "sb_search": "file-search",
+
+ "add": "add",
+ "bookmarks": "bookmark",
+ "browse": "folder-2",
+ "build_settings": "file-settings",
+ "cancel": "prohibited-2",
+ "checked": "checkbox",
+ "chevron_down": "arrow-down-s-line",
+ "chevron_left": "arrow-left-s-line",
+ "chevron_right": "arrow-right-s-line",
+ "chevron_up": "arrow-up-s-line",
+ "close": "close-large",
+ "copy": "file-copy",
+ "document_add": "file-add",
+ "document": "file-text",
+ "edit": "edit",
+ "exclude": "close-circle",
+ "export": "export",
+ "filter": "filter-2",
+ "fit_height": "expand-height-line",
+ "fit_width": "expand-width-line",
+ "folder": "folder-6",
+ "font": "font-sans",
+ "import": "import",
+ "language": "translate-2",
+ "lines": "menu-2",
+ "list": "list-unordered",
+ "margin_bottom": "skip-down-line",
+ "margin_left": "skip-left-line",
+ "margin_right": "skip-right-line",
+ "margin_top": "skip-up-line",
+ "maximise": "fullscreen",
+ "minimise": "fullscreen-exit",
+ "more_arrow": "arrow-right-s-fill",
+ "more_vertical": "more-2",
+ "noncheckable": "checkbox-indeterminate",
+ "open": "file-upload",
+ "panel": "layout-bottom",
+ "pin": "pushpin",
+ "project_copy": "",
+ "quote": "double-quotes-l",
+ "refresh": "refresh-line",
+ "remove": "subtract",
+ "revert": "reset-left",
+ "settings": "settings-2",
+ "star": "star-fill",
+ "stats": "numbers",
+ "text": "file-text",
+ "timer_off": "pause",
+ "timer": "timer",
+ "unchecked": "checkbox-blank",
+ "view": "eye-fill"
+}