diff --git a/.github/workflows/build_assets.yml b/.github/workflows/build_assets.yml
index 26f9eace..d9959e37 100644
--- a/.github/workflows/build_assets.yml
+++ b/.github/workflows/build_assets.yml
@@ -26,6 +26,7 @@ jobs:
- name: Build Assets
run: |
python pkgutils.py build-assets
+ python pkgutils.py icons optional
- name: Upload Artifacts
uses: actions/upload-artifact@v4
@@ -35,5 +36,6 @@ jobs:
novelwriter/assets/manual*.pdf
novelwriter/assets/sample.zip
novelwriter/assets/i18n/*.qm
+ novelwriter/assets/icons/*.icons
if-no-files-found: error
retention-days: 14
diff --git a/.gitignore b/.gitignore
index 18a432eb..833d4182 100644
--- a/.gitignore
+++ b/.gitignore
@@ -20,6 +20,10 @@ setup.iss
i18n/*.qm
i18n/*.qph
+# Icons Themes Except Material Symbols
+/novelwriter/assets/icons/*.icons
+!/novelwriter/assets/icons/material_*.icons
+
# Documentation
/docs/build/
/docs/source/locales/**/*.mo
diff --git a/novelwriter/assets/icons/font_awesome.icons b/novelwriter/assets/icons/font_awesome.icons
deleted file mode 100644
index 550fd857..00000000
--- a/novelwriter/assets/icons/font_awesome.icons
+++ /dev/null
@@ -1,109 +0,0 @@
-# This file is automatically generated. Do not edit.
-
-# Meta
-meta:name = Font Awesome 6
-meta:author = Fonticons Inc
-meta:license = CC BY 4.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_details =
-icon:sb_novel =
-icon:sb_outline =
-icon:sb_project =
-icon:sb_search =
-icon:sb_stats =
-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:project_copy =
-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/material_filled_bold.icons b/novelwriter/assets/icons/material_filled_bold.icons
deleted file mode 100644
index bc902698..00000000
--- a/novelwriter/assets/icons/material_filled_bold.icons
+++ /dev/null
@@ -1,109 +0,0 @@
-# This file is automatically generated. Do not edit.
-
-# Meta
-meta:name = Material Symbols - Filled Bold
-meta:author = Google Inc
-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_details =
-icon:sb_novel =
-icon:sb_outline =
-icon:sb_project =
-icon:sb_search =
-icon:sb_stats =
-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:project_copy =
-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/material_filled_normal.icons b/novelwriter/assets/icons/material_filled_normal.icons
index ce666d14..04680813 100644
--- a/novelwriter/assets/icons/material_filled_normal.icons
+++ b/novelwriter/assets/icons/material_filled_normal.icons
@@ -1,7 +1,7 @@
# This file is automatically generated. Do not edit.
# Meta
-meta:name = Material Symbols - Filled Medium
+meta:name = Material Symbols - Filled
meta:author = Google Inc
meta:license = Apache 2.0
diff --git a/novelwriter/assets/icons/material_rounded_bold.icons b/novelwriter/assets/icons/material_rounded_bold.icons
deleted file mode 100644
index 08564be2..00000000
--- a/novelwriter/assets/icons/material_rounded_bold.icons
+++ /dev/null
@@ -1,109 +0,0 @@
-# This file is automatically generated. Do not edit.
-
-# Meta
-meta:name = Material Symbols - Rounded Bold
-meta:author = Google Inc
-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_details =
-icon:sb_novel =
-icon:sb_outline =
-icon:sb_project =
-icon:sb_search =
-icon:sb_stats =
-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:project_copy =
-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/material_rounded_normal.icons b/novelwriter/assets/icons/material_rounded_normal.icons
index 3da2739e..35c021c1 100644
--- a/novelwriter/assets/icons/material_rounded_normal.icons
+++ b/novelwriter/assets/icons/material_rounded_normal.icons
@@ -1,7 +1,7 @@
# This file is automatically generated. Do not edit.
# Meta
-meta:name = Material Symbols - Rounded Medium
+meta:name = Material Symbols - Rounded
meta:author = Google Inc
meta:license = Apache 2.0
diff --git a/novelwriter/assets/icons/material_sharp_normal.icons b/novelwriter/assets/icons/material_sharp_normal.icons
new file mode 100644
index 00000000..a5867da9
--- /dev/null
+++ b/novelwriter/assets/icons/material_sharp_normal.icons
@@ -0,0 +1,109 @@
+# This file is automatically generated. Do not edit.
+
+# Meta
+meta:name = Material Symbols - Sharp
+meta:author = Google Inc
+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_details =
+icon:sb_novel =
+icon:sb_outline =
+icon:sb_project =
+icon:sb_search =
+icon:sb_stats =
+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:project_copy =
+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/material_sharp_thin.icons b/novelwriter/assets/icons/material_sharp_thin.icons
new file mode 100644
index 00000000..485676b2
--- /dev/null
+++ b/novelwriter/assets/icons/material_sharp_thin.icons
@@ -0,0 +1,109 @@
+# This file is automatically generated. Do not edit.
+
+# Meta
+meta:name = Material Symbols - Sharp Thin
+meta:author = Google Inc
+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_details =
+icon:sb_novel =
+icon:sb_outline =
+icon:sb_project =
+icon:sb_search =
+icon:sb_stats =
+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:project_copy =
+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_filled.icons b/novelwriter/assets/icons/remix_filled.icons
deleted file mode 100644
index b2305187..00000000
--- a/novelwriter/assets/icons/remix_filled.icons
+++ /dev/null
@@ -1,109 +0,0 @@
-# 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_details =
-icon:sb_novel =
-icon:sb_outline =
-icon:sb_project =
-icon:sb_search =
-icon:sb_stats =
-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:project_copy =
-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
deleted file mode 100644
index 0fae7c91..00000000
--- a/novelwriter/assets/icons/remix_outline.icons
+++ /dev/null
@@ -1,109 +0,0 @@
-# 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_details =
-icon:sb_novel =
-icon:sb_outline =
-icon:sb_project =
-icon:sb_search =
-icon:sb_stats =
-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:project_copy =
-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/pkgutils.py b/pkgutils.py
index beb5fece..fd9ecf67 100755
--- a/pkgutils.py
+++ b/pkgutils.py
@@ -171,11 +171,15 @@ if __name__ == "__main__":
# =================
# Build Icons
+ styles = ", ".join([
+ "all", "default", "optional", "free", "non_free",
+ *utils.icon_themes.ICON_SOURCES.keys()
+ ])
cmdIcons = parsers.add_parser(
- "icons", help="Build icon theme files from source."
+ "icons", help="Build icon theme files from upstream sources."
)
- cmdIcons.add_argument("sources", help="Working directory for sources.")
- cmdIcons.add_argument("style", help="What icon style to build.")
+ cmdIcons.add_argument("style", help=f"What icon style to build: {styles}")
+ cmdIcons.add_argument("--work-dir", help="Working directory.", default="build_icons")
cmdIcons.set_defaults(func=utils.icon_themes.main)
# Import Translations
@@ -275,9 +279,9 @@ if __name__ == "__main__":
# See https://github.com/pypa/manylinux
# See https://python-appimage.readthedocs.io/en/latest/#available-python-appimages
cmdBuildAppImage = parsers.add_parser("build-appimage", help="Build an AppImage.")
- cmdBuildAppImage.add_argument("linux", help="Manylinux version, e.g. manylinux_2_28.")
- cmdBuildAppImage.add_argument("arch", help="Architecture, e.g. x86_64.")
- cmdBuildAppImage.add_argument("python", help="Python version, e.g. 3.13.")
+ cmdBuildAppImage.add_argument("linux", help="Manylinux version, e.g. manylinux_2_28")
+ cmdBuildAppImage.add_argument("arch", help="Architecture, e.g. x86_64")
+ cmdBuildAppImage.add_argument("python", help="Python version, e.g. 3.13")
cmdBuildAppImage.set_defaults(func=utils.build_appimage.appImage)
# Build Windows Inno Setup Installer
diff --git a/setup/make_pip.sh b/setup/make_pip.sh
index 4c3eb846..681a3cb5 100755
--- a/setup/make_pip.sh
+++ b/setup/make_pip.sh
@@ -24,6 +24,7 @@ echo " Building Dependencies"
echo "================================================================================"
echo ""
python3 pkgutils.py build-assets
+python3 pkgutils.py icons optional
echo ""
echo " Building Packages"
diff --git a/setup/make_release.sh b/setup/make_release.sh
index cbe4ca25..97438bd9 100755
--- a/setup/make_release.sh
+++ b/setup/make_release.sh
@@ -18,6 +18,7 @@ fi
source $ENVPATH/bin/activate
pip3 install -r requirements.txt -r docs/requirements.txt
python3 pkgutils.py build-assets
+python3 pkgutils.py icons optional
deactivate
echo ""
diff --git a/tests/test_gui/test_gui_theme.py b/tests/test_gui/test_gui_theme.py
index c64f1172..7b0f518d 100644
--- a/tests/test_gui/test_gui_theme.py
+++ b/tests/test_gui/test_gui_theme.py
@@ -209,11 +209,11 @@ def testGuiTheme_Theme(qtbot, monkeypatch, nwGUI, tstPaths):
# Check a few values
assert mainTheme._guiPalette.color(
- QPalette.ColorRole.Window).getRgb() == (54, 54, 54, 255)
+ QPalette.ColorRole.Window).getRgb() == (54, 54, 54, 255)
assert mainTheme._guiPalette.color(
- QPalette.ColorRole.WindowText).getRgb() == (204, 204, 204, 255)
+ QPalette.ColorRole.WindowText).getRgb() == (204, 204, 204, 255)
assert mainTheme._guiPalette.color(
- QPalette.ColorRole.Base).getRgb() == (62, 62, 62, 255)
+ QPalette.ColorRole.Base).getRgb() == (62, 62, 62, 255)
assert mainTheme._guiPalette.color(
QPalette.ColorRole.AlternateBase).getRgb() == (78, 78, 78, 255)
@@ -304,7 +304,7 @@ def testGuiTheme_IconThemes(qtbot, caplog, monkeypatch, nwGUI, tstPaths):
# Load working theme file
assert iconCache.loadTheme("material_rounded_normal") is True
- assert iconCache.themeMeta.name == "Material Symbols - Rounded Medium"
+ assert iconCache.themeMeta.name == "Material Symbols - Rounded"
# Load with project colour override
purple = iconCache._svgColors["purple"]
diff --git a/utils/icon_themes.py b/utils/icon_themes.py
index 00d75714..b9ddf16e 100644
--- a/utils/icon_themes.py
+++ b/utils/icon_themes.py
@@ -23,7 +23,8 @@ from __future__ import annotations
import argparse
import json
import subprocess
-import sys
+import urllib.request
+import zipfile
from pathlib import Path
from xml.etree import ElementTree as ET
@@ -32,6 +33,17 @@ from utils.common import ROOT_DIR
UTILS = Path(__file__).parent
ET.register_namespace("", "http://www.w3.org/2000/svg")
+
+ICON_SOURCES = {
+ "material": "https://github.com/google/material-design-icons.git",
+ "font_awesome": "https://github.com/FortAwesome/Font-Awesome/archive/refs/tags/6.7.2.zip",
+ "remix": "https://github.com/Remix-Design/RemixIcon/archive/refs/tags/v4.6.0.zip",
+}
+ICON_EXTRACT = {
+ "material": "material-design-icons",
+ "font_awesome": "Font-Awesome-6.7.2",
+ "remix": "RemixIcon-4.6.0",
+}
ICONS = [
"alert_error",
"alert_info",
@@ -183,21 +195,33 @@ def _writeThemeFile(
return
-def _cloneRepo(repoPath: Path, repoUrl: str) -> None:
+def _updateRepo(path: Path, name: str) -> None:
"""Clone or update a local repo of icons."""
- print(f"Updating: {repoUrl}")
- if not repoPath.is_dir():
- subprocess.call(["git", "clone", repoUrl, "--depth", "50"], cwd=repoPath.parent)
+ print(f"Updating: {ICON_SOURCES[name]}")
+ if not path.is_dir():
+ subprocess.call(["git", "clone", ICON_SOURCES[name], "--depth", "1"], cwd=path.parent)
else:
- subprocess.call(["git", "pull"], cwd=repoPath)
+ subprocess.call(["git", "pull"], cwd=path)
+ print("")
+ return
+
+
+def _downloadIconPack(path: Path, name: str) -> None:
+ """Download and extract icon pack releases."""
+ print(f"Downloading: {ICON_SOURCES[name]}")
+ zipFile = path / f"{name}.zip"
+ urllib.request.urlretrieve(ICON_SOURCES[name], zipFile)
+ print(f"Extracting: {zipFile.name}")
+ with zipfile.ZipFile(zipFile, "r") as inFile:
+ inFile.extractall(path)
print("")
return
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, "https://github.com/google/material-design-icons.git")
+ srcRepo = workDir / ICON_EXTRACT["material"]
+ _updateRepo(srcRepo, "material")
for file, job in jobs.items():
name: str = job["name"]
@@ -233,8 +257,9 @@ 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, "https://github.com/FortAwesome/Font-Awesome.git")
+ srcRepo = workDir / ICON_EXTRACT["font_awesome"]
+ if not srcRepo.is_dir():
+ _downloadIconPack(workDir, "font_awesome")
for file, job in jobs.items():
name: str = job["name"]
@@ -278,8 +303,9 @@ def processFontAwesome(workDir: Path, iconsDir: Path, jobs: dict) -> None:
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")
+ srcRepo = workDir / ICON_EXTRACT["remix"]
+ if not srcRepo.is_dir():
+ _downloadIconPack(workDir, "remix")
for file, job in jobs.items():
name: str = job["name"]
@@ -326,15 +352,12 @@ def main(args: argparse.Namespace) -> None:
print("=================")
print("")
- workDir = Path(args.sources).absolute()
- if not workDir.is_dir():
- print(f"Source directory not found: {workDir}")
- sys.exit(1)
-
+ workDir = Path(args.work_dir).absolute()
+ workDir.mkdir(exist_ok=True)
iconsDir = ROOT_DIR / "novelwriter" / "assets" / "icons"
style = args.style
- if style in ("all", "material"):
+ if style in ("all", "default", "material"):
processMaterialIcons(workDir, iconsDir, {
"material_rounded_thin": {
"name": "Material Symbols - Rounded Thin",
@@ -343,17 +366,11 @@ def main(args: argparse.Namespace) -> None:
"weight": 200,
},
"material_rounded_normal": {
- "name": "Material Symbols - Rounded Medium",
+ "name": "Material Symbols - Rounded",
"style": "rounded",
"filled": False,
"weight": 400,
},
- "material_rounded_bold": {
- "name": "Material Symbols - Rounded Bold",
- "style": "rounded",
- "filled": False,
- "weight": 600,
- },
"material_filled_thin": {
"name": "Material Symbols - Filled Thin",
"style": "rounded",
@@ -361,27 +378,33 @@ def main(args: argparse.Namespace) -> None:
"weight": 200,
},
"material_filled_normal": {
- "name": "Material Symbols - Filled Medium",
+ "name": "Material Symbols - Filled",
"style": "rounded",
"filled": True,
"weight": 400,
},
- "material_filled_bold": {
- "name": "Material Symbols - Filled Bold",
- "style": "rounded",
- "filled": True,
- "weight": 600,
+ "material_sharp_thin": {
+ "name": "Material Symbols - Sharp Thin",
+ "style": "sharp",
+ "filled": False,
+ "weight": 200,
+ },
+ "material_sharp_normal": {
+ "name": "Material Symbols - Sharp",
+ "style": "sharp",
+ "filled": False,
+ "weight": 400,
},
})
- if style in ("all", "fa"):
+ if style in ("all", "optional", "free", "font_awesome"):
processFontAwesome(workDir, iconsDir, {
"font_awesome": {
"name": "Font Awesome 6",
},
})
- if style in ("all", "remix"):
+ if style in ("all", "optional", "non_free", "remix"):
processRemix(workDir, iconsDir, {
"remix_outline": {
"name": "Remix Icon - Outline",