mirror of
https://github.com/kovidgoyal/calibre.git
synced 2026-03-31 14:22:30 -04:00
Allow plugins to specify a folder in the zip file to load icons from
kiwidude's plugins use some crazy inefficient code that tries to load an icon in multiple ways. With this change he can simply do: get_icons(zfp, name, plugin_name, folder_in_zip_file='images') This will load the icon efficiently from the user overrides/icon theme, falling back to the icon from the zip file as a last resort. Also, change get_icons() to always read the icon data from the zip file. This is to support upcoming code to change icon themeing to support the case of switching from one them to another during and when the first theme has the icon and the second theme doesnt, loading the fallback/default icon.
This commit is contained in:
parent
6c63a1fa3e
commit
0da6219b4c
@ -13,6 +13,7 @@ import sys
|
||||
import threading
|
||||
import zipfile
|
||||
from collections import OrderedDict
|
||||
from collections.abc import Iterable
|
||||
from functools import partial
|
||||
from importlib.machinery import ModuleSpec
|
||||
from importlib.util import decode_source
|
||||
@ -54,7 +55,11 @@ def get_resources(zfp, name_or_list_of_names, print_tracebacks_for_missing_resou
|
||||
return ans
|
||||
|
||||
|
||||
def get_icons(zfp, name_or_list_of_names, plugin_name='', print_tracebacks_for_missing_resources=True):
|
||||
def get_icons(
|
||||
zfp: str, name_or_list_of_names: str | Iterable[str],
|
||||
plugin_name: str = '', folder_in_zip_file: str = '',
|
||||
print_tracebacks_for_missing_resources: bool = True,
|
||||
):
|
||||
'''
|
||||
Load icons from the plugin zip file
|
||||
|
||||
@ -64,41 +69,34 @@ def get_icons(zfp, name_or_list_of_names, plugin_name='', print_tracebacks_for_m
|
||||
:param plugin_name: The human friendly name of the plugin, used to load icons from
|
||||
the current theme, if present.
|
||||
|
||||
:param folder_in_zip_file: Path to a folder in the zip file from which to load the icons.
|
||||
Default is the root of the zip file. Use / as separator.
|
||||
|
||||
:param print_tracebacks_for_missing_resources: When True missing resources are reported to STDERR
|
||||
|
||||
:return: A dictionary of the form ``{name : QIcon}``. Any names
|
||||
that were not found in the zip file will be null QIcons.
|
||||
If a single path is passed in the return value will
|
||||
be A QIcon.
|
||||
be a QIcon.
|
||||
'''
|
||||
from qt.core import QIcon, QPixmap
|
||||
from qt.core import QIcon
|
||||
namelist = (name_or_list_of_names,) if isinstance(name_or_list_of_names, (str, bytes)) else name_or_list_of_names
|
||||
ans = {}
|
||||
namelist = [name_or_list_of_names] if isinstance(name_or_list_of_names, (str, bytes)) else name_or_list_of_names
|
||||
failed = set()
|
||||
if plugin_name:
|
||||
with zipfile.ZipFile(zfp) as zf:
|
||||
for name in namelist:
|
||||
q = QIcon.ic(f'{plugin_name}/{name}')
|
||||
if q.is_ok():
|
||||
ans[name] = q
|
||||
else:
|
||||
failed.add(name)
|
||||
else:
|
||||
failed = set(namelist)
|
||||
if failed:
|
||||
from_zfp = get_resources(zfp, list(failed), print_tracebacks_for_missing_resources=print_tracebacks_for_missing_resources)
|
||||
if from_zfp is None:
|
||||
from_zfp = {}
|
||||
elif isinstance(from_zfp, (str, bytes)):
|
||||
from_zfp = {namelist[0]: from_zfp}
|
||||
|
||||
for name in failed:
|
||||
p = QPixmap()
|
||||
raw = from_zfp.get(name)
|
||||
if raw:
|
||||
p.loadFromData(raw)
|
||||
ans[name] = QIcon(p)
|
||||
if len(namelist) == 1 and ans:
|
||||
ans = ans.pop(namelist[0])
|
||||
arcname = posixpath.join(folder_in_zip_file, name)
|
||||
theme_name = posixpath.join(plugin_name, name)
|
||||
try:
|
||||
data = zf.read(arcname)
|
||||
except KeyError:
|
||||
data = b''
|
||||
if print_tracebacks_for_missing_resources:
|
||||
print('Failed to load resource:', repr(name), 'from the plugin zip file:', zfp, file=sys.stderr)
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
ans[name] = QIcon.ic(theme_name, fallback=data)
|
||||
if len(namelist) == 1:
|
||||
return ans[name]
|
||||
return ans
|
||||
|
||||
|
||||
|
||||
@ -41,6 +41,7 @@ from qt.core import (
|
||||
QObject,
|
||||
QPainterPath,
|
||||
QPalette,
|
||||
QPixmap,
|
||||
QRectF,
|
||||
QResource,
|
||||
QSettings,
|
||||
@ -251,7 +252,7 @@ class IconResourceManager:
|
||||
icon = self.icon_cache[name] = self(name)
|
||||
return icon
|
||||
|
||||
def __call__(self, name):
|
||||
def __call__(self, name: str, fallback: bytes = b'') -> QIcon:
|
||||
if isinstance(name, QIcon):
|
||||
return name
|
||||
if not name:
|
||||
@ -269,6 +270,11 @@ class IconResourceManager:
|
||||
q = QIcon(f':/icons/calibre-default-{self.color_palette}/images/{name}')
|
||||
if q.is_ok():
|
||||
ans = q
|
||||
if fallback and not ans.is_ok():
|
||||
p = QPixmap()
|
||||
p.loadFromData(fallback)
|
||||
if not p.isNull():
|
||||
ans = QIcon(p)
|
||||
return ans
|
||||
|
||||
def icon_as_png(self, name, as_bytearray=False, compression_level=0):
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user