diff --git a/qt/aqt/BUILD.bazel b/qt/aqt/BUILD.bazel
index bf9c8a20d..e4bac550a 100644
--- a/qt/aqt/BUILD.bazel
+++ b/qt/aqt/BUILD.bazel
@@ -32,7 +32,6 @@ _py_srcs = glob(
_py_srcs_and_forms = _py_srcs + [
"//qt/aqt/forms:forms",
- "//qt/aqt/forms:icons",
]
aqt_core_data = [
diff --git a/qt/aqt/__init__.py b/qt/aqt/__init__.py
index c74149823..566250522 100644
--- a/qt/aqt/__init__.py
+++ b/qt/aqt/__init__.py
@@ -587,6 +587,11 @@ def _run(argv: Optional[list[str]] = None, exec: bool = True) -> Optional[AnkiAp
)
return None
+ # make image resources available
+ from aqt.utils import aqt_data_folder
+
+ QDir.addSearchPath("icons", os.path.join(aqt_data_folder(), "qt", "icons"))
+
if pmLoadResult.firstTime:
pm.setDefaultLang(lang[0])
diff --git a/qt/aqt/browser/previewer.py b/qt/aqt/browser/previewer.py
index d3a4c882d..35314208a 100644
--- a/qt/aqt/browser/previewer.py
+++ b/qt/aqt/browser/previewer.py
@@ -53,7 +53,7 @@ class Previewer(QDialog):
self._close_callback = on_close
self.mw = mw
icon = QIcon()
- icon.addPixmap(QPixmap(":/icons/anki.png"), QIcon.Normal, QIcon.Off)
+ icon.addPixmap(QPixmap("icons:anki.png"), QIcon.Normal, QIcon.Off)
disable_help_button(self)
self.setWindowIcon(icon)
diff --git a/qt/aqt/browser/sidebar/toolbar.py b/qt/aqt/browser/sidebar/toolbar.py
index 0f9c53fc3..61a0b0b5e 100644
--- a/qt/aqt/browser/sidebar/toolbar.py
+++ b/qt/aqt/browser/sidebar/toolbar.py
@@ -18,8 +18,8 @@ class SidebarTool(Enum):
class SidebarToolbar(QToolBar):
_tools: tuple[tuple[SidebarTool, str, Callable[[], str]], ...] = (
- (SidebarTool.SEARCH, ":/icons/magnifying_glass.svg", tr.actions_search),
- (SidebarTool.SELECT, ":/icons/select.svg", tr.actions_select),
+ (SidebarTool.SEARCH, "icons:magnifying_glass.svg", tr.actions_search),
+ (SidebarTool.SELECT, "icons:select.svg", tr.actions_select),
)
def __init__(self, sidebar: aqt.browser.sidebar.SidebarTreeView) -> None:
diff --git a/qt/aqt/browser/sidebar/tree.py b/qt/aqt/browser/sidebar/tree.py
index 28da752b8..d3b1e9245 100644
--- a/qt/aqt/browser/sidebar/tree.py
+++ b/qt/aqt/browser/sidebar/tree.py
@@ -527,7 +527,7 @@ class SidebarTreeView(QTreeView):
###########################
def _saved_searches_tree(self, root: SidebarItem) -> None:
- icon = ":/icons/heart-outline.svg"
+ icon = "icons:heart-outline.svg"
saved = self._get_saved_searches()
root = self._section_root(
@@ -551,7 +551,7 @@ class SidebarTreeView(QTreeView):
###########################
def _today_tree(self, root: SidebarItem) -> None:
- icon = ":/icons/clock-outline.svg"
+ icon = "icons:clock-outline.svg"
root = self._section_root(
root=root,
name=tr.browsing_today(),
@@ -621,8 +621,8 @@ class SidebarTreeView(QTreeView):
###########################
def _card_state_tree(self, root: SidebarItem) -> None:
- icon = ":/icons/circle.svg"
- icon_outline = ":/icons/circle-outline.svg"
+ icon = "icons:circle.svg"
+ icon_outline = "icons:circle-outline.svg"
root = self._section_root(
root=root,
@@ -670,8 +670,8 @@ class SidebarTreeView(QTreeView):
###########################
def _flags_tree(self, root: SidebarItem) -> None:
- icon = ":/icons/flag.svg"
- icon_outline = ":/icons/flag-outline.svg"
+ icon = "icons:flag.svg"
+ icon_outline = "icons:flag-outline.svg"
root = self._section_root(
root=root,
@@ -704,8 +704,8 @@ class SidebarTreeView(QTreeView):
###########################
def _tag_tree(self, root: SidebarItem) -> None:
- icon = ":/icons/tag-outline.svg"
- icon_off = ":/icons/tag-off-outline.svg"
+ icon = "icons:tag-outline.svg"
+ icon_off = "icons:tag-off-outline.svg"
def render(
root: SidebarItem, nodes: Iterable[TagTreeNode], head: str = ""
@@ -752,9 +752,9 @@ class SidebarTreeView(QTreeView):
###########################
def _deck_tree(self, root: SidebarItem) -> None:
- icon = ":/icons/book-outline.svg"
- icon_current = ":/icons/book-clock-outline.svg"
- icon_filtered = ":/icons/book-cog-outline.svg"
+ icon = "icons:book-outline.svg"
+ icon_current = "icons:book-clock-outline.svg"
+ icon_filtered = "icons:book-cog-outline.svg"
def render(
root: SidebarItem, nodes: Iterable[DeckTreeNode], head: str = ""
@@ -807,9 +807,9 @@ class SidebarTreeView(QTreeView):
###########################
def _notetype_tree(self, root: SidebarItem) -> None:
- notetype_icon = ":/icons/newspaper.svg"
- template_icon = ":/icons/iframe-braces-outline.svg"
- field_icon = ":/icons/form-textbox.svg"
+ notetype_icon = "icons:newspaper.svg"
+ template_icon = "icons:iframe-braces-outline.svg"
+ field_icon = "icons:form-textbox.svg"
root = self._section_root(
root=root,
diff --git a/qt/aqt/data/BUILD.bazel b/qt/aqt/data/BUILD.bazel
index efd53c8ca..f8745bed2 100644
--- a/qt/aqt/data/BUILD.bazel
+++ b/qt/aqt/data/BUILD.bazel
@@ -2,6 +2,7 @@ filegroup(
name = "data",
srcs = [
"//qt/aqt/data/lib",
+ "//qt/aqt/data/qt",
"//qt/aqt/data/web",
],
visibility = ["//qt:__subpackages__"],
diff --git a/qt/aqt/data/qt/BUILD.bazel b/qt/aqt/data/qt/BUILD.bazel
new file mode 100644
index 000000000..a98b579a8
--- /dev/null
+++ b/qt/aqt/data/qt/BUILD.bazel
@@ -0,0 +1,27 @@
+load("@rules_python//python:defs.bzl", "py_binary")
+
+py_binary(
+ name = "build_qrc",
+ srcs = ["build_qrc.py"],
+ legacy_create_init = False,
+)
+
+genrule(
+ name = "icons_qrc",
+ srcs = ["//qt/aqt/data/qt/icons"],
+ outs = ["icons.qrc"],
+ cmd = "$(location build_qrc) $(location icons.qrc) $(SRCS)",
+ tools = ["build_qrc"],
+ visibility = ["//qt/aqt:__pkg__"],
+)
+
+filegroup(
+ name = "qt",
+ srcs = [
+ "//qt/aqt/data/qt/icons",
+ # not needed at runtime, but including it here ensures
+ # it's up to date when a dev opens Qt Designer after a ./run
+ ":icons_qrc",
+ ],
+ visibility = ["//qt:__subpackages__"],
+)
diff --git a/qt/aqt/forms/build_qrc.py b/qt/aqt/data/qt/build_qrc.py
similarity index 52%
rename from qt/aqt/forms/build_qrc.py
rename to qt/aqt/data/qt/build_qrc.py
index 6d385b402..18afceae5 100644
--- a/qt/aqt/forms/build_qrc.py
+++ b/qt/aqt/data/qt/build_qrc.py
@@ -1,5 +1,8 @@
-import sys
+# Copyright: Ankitects Pty Ltd and contributors
+# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
+
import os
+import sys
qrc_file = os.path.abspath(sys.argv[1])
icons = sys.argv[2:]
@@ -15,10 +18,13 @@ FILES
indent = " " * 8
lines = []
for icon in icons:
- alias = ""
+ base = os.path.basename(icon)
path = os.path.relpath(icon, start=os.path.dirname(qrc_file))
- alias = "" if os.path.dirname(path) == "icons" else f' alias="icons/{os.path.basename(path)}"'
- line = f"{indent}{path}"
+ if not path.startswith("icons/"):
+ path = f"../data/qt/icons/{base}"
+ else:
+ path = f"../../../bazel-bin/qt/aqt/data/qt/icons/{base}"
+ line = f'{indent}{path}'
lines.append(line)
with open(qrc_file, "w") as file:
diff --git a/qt/aqt/forms/icons/BUILD.bazel b/qt/aqt/data/qt/icons/BUILD.bazel
similarity index 80%
rename from qt/aqt/forms/icons/BUILD.bazel
rename to qt/aqt/data/qt/icons/BUILD.bazel
index db492a4dc..f991a4220 100644
--- a/qt/aqt/forms/icons/BUILD.bazel
+++ b/qt/aqt/data/qt/icons/BUILD.bazel
@@ -1,4 +1,5 @@
-load("//ts:vendor.bzl", "copy_mdi_icons", "copy_bootstrap_icons")
+load("//ts:vendor.bzl", "copy_mdi_icons")
+load("@rules_python//python:defs.bzl", "py_binary")
copy_mdi_icons(
name = "mdi-icons",
@@ -37,6 +38,9 @@ copy_mdi_icons(
filegroup(
name = "icons",
- srcs = ["mdi-icons"] + glob(["*.svg", "*.png"]),
+ srcs = ["mdi-icons"] + glob([
+ "*.svg",
+ "*.png",
+ ]),
visibility = ["//visibility:public"],
)
diff --git a/qt/aqt/forms/icons/anki.png b/qt/aqt/data/qt/icons/anki.png
similarity index 100%
rename from qt/aqt/forms/icons/anki.png
rename to qt/aqt/data/qt/icons/anki.png
diff --git a/qt/aqt/forms/icons/card-state.svg b/qt/aqt/data/qt/icons/card-state.svg
similarity index 100%
rename from qt/aqt/forms/icons/card-state.svg
rename to qt/aqt/data/qt/icons/card-state.svg
diff --git a/qt/aqt/forms/icons/clock.svg b/qt/aqt/data/qt/icons/clock.svg
similarity index 100%
rename from qt/aqt/forms/icons/clock.svg
rename to qt/aqt/data/qt/icons/clock.svg
diff --git a/qt/aqt/forms/icons/collection.svg b/qt/aqt/data/qt/icons/collection.svg
similarity index 100%
rename from qt/aqt/forms/icons/collection.svg
rename to qt/aqt/data/qt/icons/collection.svg
diff --git a/qt/aqt/forms/icons/deck.svg b/qt/aqt/data/qt/icons/deck.svg
similarity index 100%
rename from qt/aqt/forms/icons/deck.svg
rename to qt/aqt/data/qt/icons/deck.svg
diff --git a/qt/aqt/forms/icons/flag.svg b/qt/aqt/data/qt/icons/flag.svg
similarity index 100%
rename from qt/aqt/forms/icons/flag.svg
rename to qt/aqt/data/qt/icons/flag.svg
diff --git a/qt/aqt/forms/icons/heart.svg b/qt/aqt/data/qt/icons/heart.svg
similarity index 100%
rename from qt/aqt/forms/icons/heart.svg
rename to qt/aqt/data/qt/icons/heart.svg
diff --git a/qt/aqt/forms/icons/magnifying_glass.svg b/qt/aqt/data/qt/icons/magnifying_glass.svg
similarity index 100%
rename from qt/aqt/forms/icons/magnifying_glass.svg
rename to qt/aqt/data/qt/icons/magnifying_glass.svg
diff --git a/qt/aqt/forms/icons/media-record.png b/qt/aqt/data/qt/icons/media-record.png
similarity index 100%
rename from qt/aqt/forms/icons/media-record.png
rename to qt/aqt/data/qt/icons/media-record.png
diff --git a/qt/aqt/forms/icons/notetype.svg b/qt/aqt/data/qt/icons/notetype.svg
similarity index 100%
rename from qt/aqt/forms/icons/notetype.svg
rename to qt/aqt/data/qt/icons/notetype.svg
diff --git a/qt/aqt/forms/icons/select.svg b/qt/aqt/data/qt/icons/select.svg
similarity index 100%
rename from qt/aqt/forms/icons/select.svg
rename to qt/aqt/data/qt/icons/select.svg
diff --git a/qt/aqt/forms/icons/tag.svg b/qt/aqt/data/qt/icons/tag.svg
similarity index 100%
rename from qt/aqt/forms/icons/tag.svg
rename to qt/aqt/data/qt/icons/tag.svg
diff --git a/qt/aqt/flags.py b/qt/aqt/flags.py
index e1e209aeb..64ee04524 100644
--- a/qt/aqt/flags.py
+++ b/qt/aqt/flags.py
@@ -56,7 +56,7 @@ class FlagManager:
def _load_flags(self) -> None:
labels = cast(dict[str, str], self.mw.col.get_config("flagLabels", {}))
- icon = ColoredIcon(path=":/icons/flag.svg", color=colors.DISABLED)
+ icon = ColoredIcon(path="icons:flag.svg", color=colors.DISABLED)
self._flags = [
Flag(
diff --git a/qt/aqt/forms/BUILD.bazel b/qt/aqt/forms/BUILD.bazel
index 0bdf3afbc..931df6037 100644
--- a/qt/aqt/forms/BUILD.bazel
+++ b/qt/aqt/forms/BUILD.bazel
@@ -15,35 +15,3 @@ py_binary(
legacy_create_init = False,
deps = ["@pyqt5//:pkg"],
)
-
-py_binary(
- name = "build_qrc",
- srcs = ["build_qrc.py"],
- legacy_create_init = False,
- deps = ["@pyqt5//:pkg"],
-)
-
-py_binary(
- name = "build_rcc",
- srcs = ["build_rcc.py"],
- legacy_create_init = False,
- deps = ["@pyqt5//:pkg"],
-)
-
-genrule(
- name = "icons_qrc",
- srcs = ["//qt/aqt/forms/icons"],
- outs = ["icons.qrc"],
- cmd = "$(location build_qrc) $(location icons.qrc) $(SRCS)",
- tools = ["build_qrc"],
- visibility = ["//qt/aqt:__pkg__"],
-)
-
-genrule(
- name = "icons",
- srcs = ["icons_qrc", "//qt/aqt/forms/icons"],
- outs = ["icons_rc.py"],
- cmd = "$(location build_rcc) $(location icons_qrc) $(location icons_rc.py)",
- tools = ["build_rcc"],
- visibility = ["//qt/aqt:__pkg__"],
-)
diff --git a/qt/aqt/forms/build_rcc.py b/qt/aqt/forms/build_rcc.py
deleted file mode 100644
index b2dd530a8..000000000
--- a/qt/aqt/forms/build_rcc.py
+++ /dev/null
@@ -1,12 +0,0 @@
-import sys
-import os
-from PyQt5.pyrcc_main import processResourceFile
-
-icons_qrc = sys.argv[1]
-py_file = os.path.abspath(sys.argv[2])
-
-# make paths relative for pyrcc
-os.chdir(os.path.dirname(icons_qrc))
-icons_qrc = os.path.basename(icons_qrc)
-
-processResourceFile([icons_qrc], py_file, False)
diff --git a/qt/aqt/forms/build_ui.py b/qt/aqt/forms/build_ui.py
index a36857ff0..d45d4f8ac 100644
--- a/qt/aqt/forms/build_ui.py
+++ b/qt/aqt/forms/build_ui.py
@@ -29,6 +29,9 @@ for line in outdata.splitlines():
if substr in line:
line = line + " # type: ignore"
break
+ if line == "from . import icons_rc":
+ continue
+ line = line.replace(":/icons/", "icons:")
outlines.append(line)
with open(py_file, "w") as file:
diff --git a/qt/aqt/forms/icons.qrc b/qt/aqt/forms/icons.qrc
index e2b267b80..d17297082 120000
--- a/qt/aqt/forms/icons.qrc
+++ b/qt/aqt/forms/icons.qrc
@@ -1 +1 @@
-../../../bazel-bin/qt/aqt/forms/icons.qrc
\ No newline at end of file
+../../../bazel-bin/qt/aqt/data/qrc/icons.qrc
\ No newline at end of file
diff --git a/qt/aqt/profiles.py b/qt/aqt/profiles.py
index 8154778ca..38042621e 100644
--- a/qt/aqt/profiles.py
+++ b/qt/aqt/profiles.py
@@ -190,7 +190,7 @@ class ProfileManager:
app = QtWidgets.QApplication([])
icon = QtGui.QIcon()
icon.addPixmap(
- QtGui.QPixmap(":/icons/anki.png"),
+ QtGui.QPixmap("icons:anki.png"),
QtGui.QIcon.Normal,
QtGui.QIcon.Off,
)
diff --git a/qt/aqt/sound.py b/qt/aqt/sound.py
index f00568fc7..d0d088889 100644
--- a/qt/aqt/sound.py
+++ b/qt/aqt/sound.py
@@ -734,7 +734,7 @@ class RecordDialog(QDialog):
def _setup_dialog(self) -> None:
self.setWindowTitle("Anki")
icon = QLabel()
- icon.setPixmap(QPixmap(":/icons/media-record.png"))
+ icon.setPixmap(QPixmap("icons:media-record.png"))
self.label = QLabel("...")
hbox = QHBoxLayout()
hbox.addWidget(icon)