Share pixbufs between frames panel and scrub bar — single disk read per frame
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -131,24 +131,39 @@ class ScrubBar(Gtk.DrawingArea):
|
|||||||
self.queue_draw()
|
self.queue_draw()
|
||||||
|
|
||||||
def add_frame(self, timestamp: float, path: str) -> None:
|
def add_frame(self, timestamp: float, path: str) -> None:
|
||||||
"""Add a single frame thumbnail incrementally."""
|
"""Add a single frame thumbnail from file path."""
|
||||||
if not Path(path).exists():
|
if not Path(path).exists():
|
||||||
return
|
return
|
||||||
thumb_h = BAR_HEIGHT - 4
|
thumb_h = BAR_HEIGHT - 4
|
||||||
thumb_w = int(thumb_h * 16 / 9)
|
thumb_w = int(thumb_h * 16 / 9)
|
||||||
try:
|
try:
|
||||||
pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_scale(path, thumb_w, thumb_h, True)
|
pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_scale(path, thumb_w, thumb_h, True)
|
||||||
surface = self._pixbuf_to_surface(pixbuf)
|
self.add_frame_from_pixbuf(timestamp, pixbuf)
|
||||||
self._frame_thumbs.append({
|
|
||||||
"timestamp": timestamp,
|
|
||||||
"surface": surface,
|
|
||||||
"width": pixbuf.get_width(),
|
|
||||||
"height": pixbuf.get_height(),
|
|
||||||
})
|
|
||||||
self.queue_draw()
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
log.debug("Thumb load failed for %s: %s", path, e)
|
log.debug("Thumb load failed for %s: %s", path, e)
|
||||||
|
|
||||||
|
def add_frame_from_pixbuf(self, timestamp: float, pixbuf) -> None:
|
||||||
|
"""Add a single frame thumbnail from an already-loaded pixbuf (shared with frames panel)."""
|
||||||
|
thumb_h = BAR_HEIGHT - 4
|
||||||
|
thumb_w = int(thumb_h * 16 / 9)
|
||||||
|
scaled = pixbuf.scale_simple(thumb_w, thumb_h, GdkPixbuf.InterpType.BILINEAR)
|
||||||
|
surface = self._pixbuf_to_surface(scaled)
|
||||||
|
self._frame_thumbs.append({
|
||||||
|
"timestamp": timestamp,
|
||||||
|
"surface": surface,
|
||||||
|
"width": scaled.get_width(),
|
||||||
|
"height": scaled.get_height(),
|
||||||
|
})
|
||||||
|
self.queue_draw()
|
||||||
|
|
||||||
|
def set_frames_from_pixbufs(self, frames: list[dict]) -> None:
|
||||||
|
"""Bulk set thumbnails from already-loaded pixbufs. Each dict: {timestamp, pixbuf}."""
|
||||||
|
self._frame_thumbs = []
|
||||||
|
for f in frames:
|
||||||
|
self.add_frame_from_pixbuf(f["timestamp"], f["pixbuf"])
|
||||||
|
# queue_draw already called per frame, but one more to be safe
|
||||||
|
self.queue_draw()
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _pixbuf_to_surface(pixbuf):
|
def _pixbuf_to_surface(pixbuf):
|
||||||
"""Convert a GdkPixbuf to a cairo ImageSurface."""
|
"""Convert a GdkPixbuf to a cairo ImageSurface."""
|
||||||
|
|||||||
@@ -647,9 +647,9 @@ class ChtWindow(Adw.ApplicationWindow):
|
|||||||
self._frames_panel.load_items(items)
|
self._frames_panel.load_items(items)
|
||||||
self._known_frames = {item["id"] for item in items}
|
self._known_frames = {item["id"] for item in items}
|
||||||
self._agent_output.append(f" Loaded {len(items)} frame thumbnails.\n")
|
self._agent_output.append(f" Loaded {len(items)} frame thumbnails.\n")
|
||||||
# Update scrub bar thumbnails
|
# Update scrub bar thumbnails — reuse already-loaded pixbufs
|
||||||
self._timeline_controls.scrub_bar.set_frames(
|
self._timeline_controls.scrub_bar.set_frames_from_pixbufs(
|
||||||
[{"timestamp": e["timestamp"], "path": str(e["path"])} for e in entries]
|
[{"timestamp": it["timestamp"], "pixbuf": it["pixbuf"]} for it in items]
|
||||||
)
|
)
|
||||||
|
|
||||||
def _load_existing_transcript(self):
|
def _load_existing_transcript(self):
|
||||||
@@ -676,7 +676,7 @@ class ChtWindow(Adw.ApplicationWindow):
|
|||||||
pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_scale(str(entry["path"]), 256, 144, True)
|
pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_scale(str(entry["path"]), 256, 144, True)
|
||||||
auto = self._timeline.state.live and not self._transcript_panel.has_selection
|
auto = self._timeline.state.live and not self._transcript_panel.has_selection
|
||||||
self._frames_panel.add_item(fid, pixbuf, entry["timestamp"], auto_select=auto)
|
self._frames_panel.add_item(fid, pixbuf, entry["timestamp"], auto_select=auto)
|
||||||
self._timeline_controls.scrub_bar.add_frame(entry["timestamp"], str(entry["path"]))
|
self._timeline_controls.scrub_bar.add_frame_from_pixbuf(entry["timestamp"], pixbuf)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
log.warning("Thumbnail load failed for %s: %s", fid, e)
|
log.warning("Thumbnail load failed for %s: %s", fid, e)
|
||||||
return True
|
return True
|
||||||
|
|||||||
Reference in New Issue
Block a user