refactor: rename ambiguous variables

This commit is contained in:
Travis Abendshien
2026-07-27 13:06:12 -07:00
parent e050fc0db7
commit ef94c6fdfc
2 changed files with 85 additions and 104 deletions
+80 -99
View File
@@ -56,7 +56,7 @@ logger = structlog.get_logger(__name__)
class FileRenderer:
"""A class for rendering image and file thumbnails."""
"""A class for rendering image previews and thumbnails from files."""
rm: ResourceManager = ResourceManager()
cached_img_ext: str = ".webp"
@@ -107,6 +107,7 @@ class FileRenderer:
return "file_generic"
# NOTE: This method will be replaced with frontend specific decorations (Qt painting)
def _get_mask(
self, size: tuple[int, int], pixel_ratio: float, scale_radius: bool = False
) -> Image.Image:
@@ -130,6 +131,7 @@ class FileRenderer:
self.thumb_masks[(*size, pixel_ratio, radius_scale)] = item
return item
# NOTE: This method will be replaced with frontend specific decorations (Qt painting)
def _get_edge(
self, size: tuple[int, int], pixel_ratio: float
) -> tuple[Image.Image, Image.Image]:
@@ -153,7 +155,7 @@ class FileRenderer:
color: UiColor,
size: tuple[int, int],
theme: Theme,
pixel_ratio: float = 1.0,
dpi_scale: float = 1.0,
bg_image: Image.Image | None = None,
draw_edge: bool = True,
is_corner: bool = False,
@@ -165,7 +167,7 @@ class FileRenderer:
color (str): The color to use for the icon.
size (tuple[int,int]): The size of the icon.
theme (Theme): A theme enum to determine the light/dark theme.
pixel_ratio (float): The screen pixel ratio.
dpi_scale (float): The screen pixel ratio.
bg_image (Image.Image): Optional background image to go behind the icon.
draw_edge (bool): Flag for is the raised edge should be drawn.
is_corner (bool): Flag for is the icon should render with the "corner" style
@@ -174,23 +176,24 @@ class FileRenderer:
if name == "thumb_loading":
draw_border = False
item: Image.Image | None = self.icons.get((name, color, *size, pixel_ratio))
item: Image.Image | None = self.icons.get((name, color, *size, dpi_scale))
if not item:
item_flat: Image.Image = (
self._render_corner_icon(name, color, size, pixel_ratio, theme, bg_image)
self._render_corner_icon(name, color, size, dpi_scale, theme, bg_image)
if is_corner
else self._render_center_icon(
name, color, size, pixel_ratio, theme, draw_border, bg_image
name, color, size, dpi_scale, theme, draw_border, bg_image
)
)
if draw_edge:
edge: tuple[Image.Image, Image.Image] = self._get_edge(size, pixel_ratio)
edge: tuple[Image.Image, Image.Image] = self._get_edge(size, dpi_scale)
item = self._apply_edge(item_flat, edge, theme, faded=True)
self.icons[(name, color, *size, pixel_ratio)] = item
self.icons[(name, color, *size, dpi_scale)] = item
else:
item = item_flat
return item
# NOTE: This method will be replaced with frontend specific decorations (Qt painting)
def _render_mask(
self, size: tuple[int, int], pixel_ratio: float, radius_scale: float = 1
) -> Image.Image:
@@ -221,6 +224,7 @@ class FileRenderer:
)
return im
# NOTE: This method will be replaced with frontend specific decorations (Qt painting)
def _render_edge(
self, size: tuple[int, int], pixel_ratio: float
) -> tuple[Image.Image, Image.Image]:
@@ -248,10 +252,7 @@ class FileRenderer:
outline="white",
width=width,
)
im_hl = im_hl.resize(
size,
resample=Image.Resampling.BILINEAR,
)
im_hl = im_hl.resize(size, resample=Image.Resampling.BILINEAR)
# Shadow
im_sh: Image.Image = Image.new(
@@ -267,10 +268,7 @@ class FileRenderer:
outline="black",
width=width,
)
im_sh = im_sh.resize(
size,
resample=Image.Resampling.BILINEAR,
)
im_sh = im_sh.resize(size, resample=Image.Resampling.BILINEAR)
return (im_hl, im_sh)
@@ -347,10 +345,7 @@ class FileRenderer:
)
# Resize image to final size
im = im.resize(
size,
resample=Image.Resampling.BILINEAR,
)
im = im.resize(size, resample=Image.Resampling.BILINEAR)
fg: Image.Image = Image.new("RGB", size=size, color="#00FF00")
# Get icon by name
@@ -436,15 +431,8 @@ class FileRenderer:
primary_color = colors.get(ColorType.PRIMARY)
# Resize image to final size
im = im.resize(
size,
resample=Image.Resampling.BILINEAR,
)
fg: Image.Image = Image.new(
"RGB",
size=size,
color=primary_color,
)
im = im.resize(size, resample=Image.Resampling.BILINEAR)
fg: Image.Image = Image.new("RGB", size=size, color=primary_color)
# Get icon by name
icon = self.rm.get(name)
@@ -453,21 +441,11 @@ class FileRenderer:
icon = self.rm.file_generic
# Resize icon to fit icon_ratio
icon = icon.resize(
(
math.ceil(size[0] // icon_ratio),
math.ceil(size[1] // icon_ratio),
)
)
icon = icon.resize((math.ceil(size[0] // icon_ratio), math.ceil(size[1] // icon_ratio)))
# Paste icon
im.paste(
im=fg.resize(
(
math.ceil(size[0] // icon_ratio),
math.ceil(size[1] // icon_ratio),
)
),
im=fg.resize((math.ceil(size[0] // icon_ratio), math.ceil(size[1] // icon_ratio))),
box=(size[0] // padding_factor, size[1] // padding_factor),
mask=icon.getchannel(3),
)
@@ -516,6 +494,7 @@ class FileRenderer:
return bg
# NOTE: This method will be replaced with frontend specific decorations (Qt painting)
def _apply_edge(
self,
image: Image.Image,
@@ -557,11 +536,11 @@ class FileRenderer:
cache: CacheManager | None,
timestamp: float,
filepath: Path | str,
base_size: tuple[int, int],
pixel_ratio: float,
size: tuple[int, int],
dpi_scale: float,
theme: Theme = Theme.DARK,
is_loading: bool = False,
is_grid_thumb: bool = False,
is_thumb: bool = False,
):
"""Render a thumbnail or preview image.
@@ -569,39 +548,38 @@ class FileRenderer:
cache (CacheManager | None): A cache manager instance.
timestamp (float): The timestamp for which this job was dispatched.
filepath (str | Path): The path of the file to render a thumbnail for.
base_size (tuple[int,int]): The unmodified base size of the thumbnail.
pixel_ratio (float): The screen pixel ratio.
size (tuple[int, int]): The unmodified base size of the thumbnail.
dpi_scale (float): The screen pixel ratio.
theme (Theme): A theme enum to determine the light/dark theme.
is_loading (bool): Is this a loading graphic?
is_grid_thumb (bool): Is this a thumbnail for the thumbnail grid?
Or else the Preview Pane?
is_thumb (bool): Is this specifically a thumbnail? Use for specifying small variants.
update_on_ratio_change (bool): Should an updated ratio signal be sent?
"""
render_mask_and_edge: bool = True
adj_size = math.ceil(max(base_size[0], base_size[1]) * pixel_ratio)
scaled_size = math.ceil(max(size[0], size[1]) * dpi_scale)
theme_color: UiColor = UiColor.THEME_LIGHT if theme == Theme.LIGHT else UiColor.THEME_DARK
if isinstance(filepath, str):
filepath = Path(filepath)
def render_default(size: tuple[int, int], pixel_ratio: float) -> Image.Image:
def render_default(size: tuple[int, int], dpi_scale: float) -> Image.Image:
im = self._get_icon(
name=self._get_resource_id(filepath),
color=theme_color,
size=size,
theme=theme,
pixel_ratio=pixel_ratio,
dpi_scale=dpi_scale,
)
return im
def render_unlinked(
size: tuple[int, int], pixel_ratio: float, cached_im: Image.Image | None = None
size: tuple[int, int], dpi_scale: float, cached_im: Image.Image | None = None
) -> Image.Image:
im = self._get_icon(
name="broken_link_icon",
color=UiColor.RED,
size=size,
theme=theme,
pixel_ratio=pixel_ratio,
dpi_scale=dpi_scale,
bg_image=cached_im,
draw_edge=not cached_im,
is_corner=False,
@@ -614,9 +592,7 @@ class FileRenderer:
im_ = im
icon: Image.Image = self.rm.ignored
icon = icon.resize((math.ceil(size[0] // icon_ratio), math.ceil(size[1] // icon_ratio)))
im_.paste(
im=icon.resize(
(math.ceil(size[0] // icon_ratio), math.ceil(size[1] // icon_ratio))
@@ -640,13 +616,13 @@ class FileRenderer:
raise UnidentifiedImageError # pyright: ignore[reportUnreachable]
except Exception as e:
logger.error(
"[ThumbRenderer] Couldn't open cached thumbnail!", path=cached_path, error=e
"[FileRenderer] Couldn't open cached thumbnail!", path=cached_path, error=e
)
return image
image: Image.Image | None = None
# Try to get a non-loading thumbnail for the grid.
if not is_loading and is_grid_thumb and filepath and filepath != Path("."):
if not is_loading and is_thumb and filepath and filepath != Path("."):
# Attempt to retrieve cached image from disk
mod_time: str = ""
with contextlib.suppress(Exception):
@@ -668,35 +644,35 @@ class FileRenderer:
# TODO: Audio waveforms are dynamically sized based on the base_size, so hardcoding
# the resolution breaks that.
image = self._render(
cache,
filepath,
(thumb_res, thumb_res),
1,
theme,
is_grid_thumb,
save_to_file=file_name,
cache=cache,
filepath=filepath,
size=(thumb_res, thumb_res),
dpi_scale=1,
theme=theme,
is_thumb=is_thumb,
cache_filename=file_name,
)
# If the normal renderer failed, fallback the defaults
# (with native non-cached sizing!)
if not image:
image = (
render_unlinked((adj_size, adj_size), pixel_ratio)
render_unlinked((scaled_size, scaled_size), dpi_scale)
if not filepath.exists() or filepath.is_dir()
else render_default((adj_size, adj_size), pixel_ratio)
else render_default((scaled_size, scaled_size), dpi_scale)
)
render_mask_and_edge = False
# Apply the mask and edge
if image:
image = self._resize_image(image, (adj_size, adj_size))
image = self._resize_image(image, (scaled_size, scaled_size))
if render_mask_and_edge:
mask = self._get_mask((adj_size, adj_size), pixel_ratio)
mask = self._get_mask((scaled_size, scaled_size), dpi_scale)
edge: tuple[Image.Image, Image.Image] = self._get_edge(
(adj_size, adj_size), pixel_ratio
(scaled_size, scaled_size), dpi_scale
)
image = self._apply_edge(
four_corner_gradient(image, (adj_size, adj_size), mask), edge, theme
four_corner_gradient(image, (scaled_size, scaled_size), mask), edge, theme
)
# Check if the file is supposed to be ignored and render an overlay if needed
@@ -708,7 +684,7 @@ class FileRenderer:
filepath.relative_to(unwrap(self.lib.library_dir))
)
):
image = render_ignored((adj_size, adj_size), image)
image = render_ignored((scaled_size, scaled_size), image)
except TypeError:
pass
@@ -716,13 +692,15 @@ class FileRenderer:
elif is_loading:
# Initialize "Loading" thumbnail
loading_thumb: Image.Image = self._get_icon(
"thumb_loading", theme_color, (adj_size, adj_size), theme, pixel_ratio
"thumb_loading", theme_color, (scaled_size, scaled_size), theme, dpi_scale
)
image = loading_thumb.resize(
(scaled_size, scaled_size), resample=Image.Resampling.BILINEAR
)
image = loading_thumb.resize((adj_size, adj_size), resample=Image.Resampling.BILINEAR)
# A full preview image (never cached)
elif not is_grid_thumb:
image = self._render(cache, filepath, base_size, pixel_ratio, theme)
elif not is_thumb:
image = self._render(cache, filepath, size, dpi_scale, theme)
if not image:
image = (
render_unlinked((512, 512), 2)
@@ -730,7 +708,7 @@ class FileRenderer:
else render_default((512, 512), 2)
)
render_mask_and_edge = False
mask = self._get_mask(image.size, pixel_ratio, scale_radius=True)
mask = self._get_mask(image.size, dpi_scale, scale_radius=True)
bg = Image.new("RGBA", image.size, (0, 0, 0, 0))
bg.paste(image, mask=mask.getchannel(0))
image = bg
@@ -741,7 +719,7 @@ class FileRenderer:
return (
image,
(math.ceil(adj_size / pixel_ratio), math.ceil(image.size[1] / pixel_ratio)),
(math.ceil(scaled_size / dpi_scale), math.ceil(image.size[1] / dpi_scale)),
timestamp,
)
@@ -749,11 +727,11 @@ class FileRenderer:
self,
cache: CacheManager | None,
filepath: str | Path,
base_size: tuple[int, int],
pixel_ratio: float,
size: tuple[int, int],
dpi_scale: float,
theme: Theme = Theme.DARK,
is_grid_thumb: bool = False,
save_to_file: Path | None = None,
is_thumb: bool = False,
cache_filename: Path | None = None,
) -> Image.Image | None:
"""Render a thumbnail or preview image.
@@ -761,18 +739,17 @@ class FileRenderer:
cache (CacheManager | None): A cache manager instance.
timestamp (float): The timestamp for which this job was dispatched.
filepath (str | Path): The path of the file to render a thumbnail for.
base_size (tuple[int,int]): The unmodified base size of the thumbnail.
pixel_ratio (float): The screen pixel ratio.
size (tuple[int, int]): The unmodified base size of the thumbnail.
dpi_scale (float): The screen pixel ratio.
theme (Theme): A theme enum to determine the light/dark theme.
is_grid_thumb (bool): Is this a thumbnail for the thumbnail grid?
Or else the Preview Pane?
save_to_file(Path | None): A filepath to optionally save the output to.
is_thumb (bool): Is this specifically a thumbnail? Use for specifying small variants.
cache_filename (Path | None): An optional filename to use to save to the cache.
"""
adj_size = math.ceil(max(base_size[0], base_size[1]) * pixel_ratio)
scaled_size = math.ceil(max(size[0], size[1]) * dpi_scale)
image: Image.Image | None = None
filepath_: Path = Path(filepath)
savable_media_type: bool = True
is_savable_type: bool = True
if filepath_ and filepath_.is_file():
try:
@@ -810,7 +787,7 @@ class FileRenderer:
elif MediaCategories.is_ext_in_category(
ext, MediaCategories.IMAGE_VECTOR_TYPES, mime_fallback=True
):
image = vector_image_thumb(filepath_, adj_size)
image = vector_image_thumb(filepath_, scaled_size)
# EXR Images -------------------------------------------------------------------
elif ext in [".exr"]:
image = exr_image_thumb(filepath_)
@@ -845,22 +822,22 @@ class FileRenderer:
elif MediaCategories.is_ext_in_category(
ext, MediaCategories.FONT_TYPES, mime_fallback=True
):
if is_grid_thumb:
if is_thumb:
# Short (Aa) Preview
image = font_small_thumb(filepath_, adj_size)
image = font_small_thumb(filepath_, scaled_size)
if image is not None:
image = self._apply_overlay_color(image, UiColor.BLUE, theme)
else:
# Large (Full Alphabet) Preview
image = font_full_preview(filepath_, adj_size)
image = font_full_preview(filepath_, scaled_size)
# Audio ========================================================
elif MediaCategories.is_ext_in_category(
ext, MediaCategories.AUDIO_TYPES, mime_fallback=True
):
image = audio_album_thumb(filepath_, ext)
if image is None:
image = audio_waveform_thumb(filepath_, ext, adj_size, pixel_ratio)
savable_media_type = False
image = audio_waveform_thumb(filepath_, ext, scaled_size, dpi_scale)
is_savable_type = False
if image is not None:
image = self._apply_overlay_color(image, UiColor.GREEN, theme)
# Blender ======================================================
@@ -872,7 +849,7 @@ class FileRenderer:
elif MediaCategories.is_ext_in_category(
ext, MediaCategories.PDF_TYPES, mime_fallback=True
):
image = pdf_thumb(filepath_, adj_size, ext)
image = pdf_thumb(filepath_, scaled_size, ext)
# Archives =====================================================
elif MediaCategories.is_ext_in_category(ext, MediaCategories.ARCHIVE_TYPES):
image = archive_thumb(filepath_, ext)
@@ -887,10 +864,10 @@ class FileRenderer:
raise NoRendererError
if image:
image = self._resize_image(image, (adj_size, adj_size))
image = self._resize_image(image, (scaled_size, scaled_size))
if save_to_file and savable_media_type and image and cache:
cache.save_image(image, save_to_file, mode="RGBA")
if cache_filename and is_savable_type and image and cache:
cache.save_image(image, cache_filename, mode="RGBA")
except (
AssertionError,
@@ -899,7 +876,11 @@ class FileRenderer:
UnidentifiedImageError,
ValueError,
) as e:
logger.error("Couldn't render thumbnail", filepath=filepath, error=type(e).__name__)
logger.error(
"[FileRenderer] Couldn't render thumbnail",
filepath=filepath,
error=type(e).__name__,
)
image = None
except NoRendererError:
image = None
+5 -5
View File
@@ -14,11 +14,11 @@ from tagstudio.qt.previews.renderer import FileRenderer
class QtFileRenderer(QObject):
"""A Qt-specific wrapper for rendering image previews and thumbnails from files."""
updated = Signal(float, QPixmap, QSize, Path)
updated_ratio = Signal(float)
"""A Qt-specific entry point for rendering file previews and thumbnails."""
def __init__(self, library: Library, settings: GlobalSettings) -> None:
super().__init__()
self.renderer = FileRenderer(library, settings)
@@ -43,11 +43,11 @@ class QtFileRenderer(QObject):
cache=cache,
timestamp=timestamp,
filepath=filepath,
base_size=base_size,
pixel_ratio=pixel_ratio,
size=base_size,
dpi_scale=pixel_ratio,
theme=self.theme,
is_loading=is_loading,
is_grid_thumb=is_grid_thumb,
is_thumb=is_grid_thumb,
)
qim = ImageQt.ImageQt(image)
pixmap = QPixmap.fromImage(qim)