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",