use Qt search path instead of resource system
Means URLs like :/icons/foo.jpg should become icons:foo.jpg This is part of the prep work for a PyQt6 update. PyQt6 has dropped pyrcc, so we can longer generate the icons_qrc.py file we did previously. Qt Designer expects us to use the resource system, so we continue to generate the icons.qrc file to make editing the UI files easier. But at runtime, we no longer use that file.
|
@ -32,7 +32,6 @@ _py_srcs = glob(
|
|||
|
||||
_py_srcs_and_forms = _py_srcs + [
|
||||
"//qt/aqt/forms:forms",
|
||||
"//qt/aqt/forms:icons",
|
||||
]
|
||||
|
||||
aqt_core_data = [
|
||||
|
|
|
@ -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])
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -2,6 +2,7 @@ filegroup(
|
|||
name = "data",
|
||||
srcs = [
|
||||
"//qt/aqt/data/lib",
|
||||
"//qt/aqt/data/qt",
|
||||
"//qt/aqt/data/web",
|
||||
],
|
||||
visibility = ["//qt:__subpackages__"],
|
||||
|
|
27
qt/aqt/data/qt/BUILD.bazel
Normal file
|
@ -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__"],
|
||||
)
|
|
@ -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}<file{alias}>{path}</file>"
|
||||
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}<file alias="icons/{base}">{path}</file>'
|
||||
lines.append(line)
|
||||
|
||||
with open(qrc_file, "w") as file:
|
|
@ -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"],
|
||||
)
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 832 B After Width: | Height: | Size: 832 B |
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 2.7 KiB |
Before Width: | Height: | Size: 4 KiB After Width: | Height: | Size: 4 KiB |
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 1 KiB After Width: | Height: | Size: 1 KiB |
Before Width: | Height: | Size: 1 KiB After Width: | Height: | Size: 1 KiB |
Before Width: | Height: | Size: 5.3 KiB After Width: | Height: | Size: 5.3 KiB |
Before Width: | Height: | Size: 727 B After Width: | Height: | Size: 727 B |
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 5.3 KiB After Width: | Height: | Size: 5.3 KiB |
Before Width: | Height: | Size: 1 KiB After Width: | Height: | Size: 1 KiB |
|
@ -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(
|
||||
|
|
|
@ -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__"],
|
||||
)
|
||||
|
|
|
@ -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)
|
|
@ -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:
|
||||
|
|
|
@ -1 +1 @@
|
|||
../../../bazel-bin/qt/aqt/forms/icons.qrc
|
||||
../../../bazel-bin/qt/aqt/data/qrc/icons.qrc
|
|
@ -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,
|
||||
)
|
||||
|
|
|
@ -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)
|
||||
|
|