diff --git a/qtile_extras/widget/groupbox2.py b/qtile_extras/widget/groupbox2.py index 20c46bff..bfe0cc26 100644 --- a/qtile_extras/widget/groupbox2.py +++ b/qtile_extras/widget/groupbox2.py @@ -22,9 +22,11 @@ import math from copy import deepcopy from enum import Flag, auto +from pathlib import Path from typing import TYPE_CHECKING from libqtile import bar, hook +from libqtile.images import Img from libqtile.log_utils import logger from libqtile.scratchpad import ScratchPad from libqtile.utils import describe_attributes @@ -33,6 +35,9 @@ if TYPE_CHECKING: from typing import Any, Callable +IMAGE_CACHE: dict[str, Img] = {} +BAD_IMAGES: list[str] = [] + class Sentinel: def __bool__(self): @@ -69,6 +74,7 @@ class GroupBoxRule: "block_corner_radius", "line_width", "line_colour", + "image", "text", ] @@ -81,6 +87,7 @@ def __init__( block_corner_radius=SENTINEL, line_width=SENTINEL, line_colour=SENTINEL, + image=SENTINEL, text=SENTINEL, ): self.text_colour = text_colour @@ -90,6 +97,7 @@ def __init__( self.block_corner_radius = block_corner_radius self.line_width = line_width self.line_colour = line_colour + self.image = image self.text = text self.screen = ScreenRule.UNSET self.focused = None @@ -234,6 +242,25 @@ def _set_formats(self): if not self.text: self.text = self.group.label or self.group.name + if self.image: + self._load_image() + + def _load_image(self): + path = Path(self.image).expanduser() + if not path.exists() and path.is_file(): + if path not in BAD_IMAGES: + logger.warning("Image file does not exist: %s", path.as_posix()) + BAD_IMAGES.append(path) + self.image = None + return + + if self.image in IMAGE_CACHE: + return IMAGE_CACHE[self.image] + + img = Img.from_path(path.as_posix()) + img.resize(height=self.bar.height - 2 * self.margin_y) + IMAGE_CACHE[self.image] = img + @property def rule_attrs(self): return GroupBoxRule.attrs @@ -250,13 +277,11 @@ def _update_format(self, rule): @property def size(self): self._prepare() + del self.layout.width self.layout.text = self.text - if self.current_screen_focused_width is not None: - if self.focused and self.current_screen: - self.layout.width = self.current_screen_focused_width - else: - # Reset layout width - del self.layout.width + + if self.image: + return IMAGE_CACHE[self.image].width + 2 * self.margin_x return self.layout.width + 2 * self.padding_x @@ -305,6 +330,13 @@ def draw_block(self): ctx.new_path() + def draw_image(self): + self.drawer.ctx.save() + self.drawer.ctx.translate(self.margin_x, self.margin_y) + self.drawer.ctx.set_source(IMAGE_CACHE[self.image].pattern) + self.drawer.ctx.paint() + self.drawer.ctx.restore() + def draw_text(self): self.layout.colour = self.text_colour self.layout.draw(self.padding_x, (self.bar.height - self.layout.height) // 2) @@ -318,7 +350,9 @@ def draw(self, offset): if self.has_line: pass - if self.text: + if self.image: + self.draw_image() + elif self.text: self.draw_text() self.drawer.ctx.restore()