From 2b0703eb60ef8883633fc90fd101551dff63fc38 Mon Sep 17 00:00:00 2001 From: itdominator <1itdominator@gmail.com> Date: Thu, 27 Apr 2023 22:45:20 -0500 Subject: [PATCH] GIF animation finalized, fixed too manyu size-request updates --- src/core/containers/image_view_scroll.py | 15 +++- src/core/widgets/image_view.py | 49 +++++----- src/core/widgets/image_view_mixin.py | 110 +++++++++++++++-------- 3 files changed, 105 insertions(+), 69 deletions(-) diff --git a/src/core/containers/image_view_scroll.py b/src/core/containers/image_view_scroll.py index 1c23348..5807688 100644 --- a/src/core/containers/image_view_scroll.py +++ b/src/core/containers/image_view_scroll.py @@ -18,8 +18,9 @@ class ImageViewScroll(Gtk.ScrolledWindow): def __init__(self): super(ImageViewScroll, self).__init__() - self.fimages = settings.get_images_filter() - self.curent_dir = None + self.fimages = settings.get_images_filter() + self.curent_dir = None + self.size_request = None self._setup_styling() self._setup_signals() @@ -107,5 +108,11 @@ class ImageViewScroll(Gtk.ScrolledWindow): event_system.emit("load_image_list", (path, img_list)) @daemon_threaded - def _size_request_change(self, widget = None, eve = None): - GLib.idle_add(event_system.emit, *("size_allocate",)) + def _size_request_change(self, widget = None, rect = None): + if not self.size_request: + self.size_request = rect + return + + if self.size_request.width != rect.width or self.size_request.height != rect.height: + self.size_request = rect + GLib.idle_add(event_system.emit, *("size_allocate",)) diff --git a/src/core/widgets/image_view.py b/src/core/widgets/image_view.py index e581617..be14996 100644 --- a/src/core/widgets/image_view.py +++ b/src/core/widgets/image_view.py @@ -1,16 +1,14 @@ # Python imports +import inspect # Lib imports import gi gi.require_version('Gtk', '3.0') -gi.require_version('Gdk', '3.0') gi.require_version('GdkPixbuf', '2.0') from gi.repository import Gtk -from gi.repository import Gdk from gi.repository import GdkPixbuf from gi.repository.GLib import Bytes - try: from PIL import Image as PImage logger.debug("Pillow library exists. Loading PIL as PImage...") @@ -27,10 +25,11 @@ class ImageView(ImageViewMixin, Gtk.Image): def __init__(self): super(ImageView, self).__init__() - self.pixbuf = None - self.work_pixbuf = None - self.animation = None - self.fit_to_win = True + self.pixbuff = None + self.work_pixbuff = None + self.fit_to_win = True + self.animation = None + self.playing_animation = False self._setup_styling() self._setup_signals() @@ -68,51 +67,49 @@ class ImageView(ImageViewMixin, Gtk.Image): self.load_path(path) if self.animation: - logger.debug("Start animation stub...") + self._play_animation() def load_path(self, path): - self.pixbuf = None - self.work_pixbuf = None - self.animation = None + self.pixbuff = None + self.work_pixbuff = None + self.animation = None + self._stop_animation() event_system.emit("update_path_label", (path,)) if path.endswith(".gif"): self.set_as_gif(path) + return if PImage and path.endswith(".webp"): self.set_as_webp(path) - if not self.work_pixbuf: + if not self.work_pixbuff: self.set_as_static(path) - self.pixbuf = self.work_pixbuf - if self.animation: - ... - else: - self.set_from_pixbuf(self.work_pixbuf) - if self.fit_to_win: self._fit_to_container() - def set_as_gif(self, path): - self.work_pixbuf = GdkPixbuf.PixbufAnimation.new_from_file(path).get_static_image() + image = None try: - self.animation = Gtk.Image.new_from_file(path).get_animation() + image = GdkPixbuf.PixbufAnimation.new_from_file(path) except Exception: - self.animation = Gtk.Image.new_from_resource(path).get_animation() + image = GdkPixbuf.PixbufAnimation.new_from_resource(path) + + self.animation = image.get_iter() def set_as_static(self, path): try: - self.work_pixbuf = Gtk.Image.new_from_file(path).get_pixbuf() + self.work_pixbuff = Gtk.Image.new_from_file(path).get_pixbuf() except Exception: - self.work_pixbuf = Gtk.Image.new_from_resource(path).get_pixbuf() + self.work_pixbuff = Gtk.Image.new_from_resource(path).get_pixbuf() + + self.pixbuff = self.work_pixbuff def set_as_webp(self, path): w = settings.get_thumbnail_with() h = settings.get_thumbnail_height() - print("shit") - self.work_pixbuf = self.image2pixbuf(path, w, h) + self.work_pixbuff = self.image2pixbuf(path, w, h) @staticmethod def image2pixbuf(path, _w, _h): diff --git a/src/core/widgets/image_view_mixin.py b/src/core/widgets/image_view_mixin.py index 0d14264..bc7409d 100644 --- a/src/core/widgets/image_view_mixin.py +++ b/src/core/widgets/image_view_mixin.py @@ -8,46 +8,55 @@ class ImageViewMixin: def _zoom_out(self): - if self.work_pixbuf and self.pixbuf: + if self.work_pixbuff and self.pixbuff: # TODO: Setup scale factor setting to pull from settings... - stepx = self.work_pixbuf.get_width() * 0.05 - stepy = self.work_pixbuf.get_height() * 0.05 + stepx = self.work_pixbuff.get_width() * 0.05 + stepy = self.work_pixbuff.get_height() * 0.05 - w = self.work_pixbuf.get_width() - stepx - h = self.work_pixbuf.get_height() - stepy + w = self.work_pixbuff.get_width() - stepx + h = self.work_pixbuff.get_height() - stepy - self.work_pixbuf = self.pixbuf.scale_simple(w, h, 2) # 2 = BILINEAR and is best by default - self.set_from_pixbuf(self.work_pixbuf) + self.work_pixbuff = self.pixbuff.scale_simple(w, h, 2) # 2 = BILINEAR and is best by default + self.set_from_pixbuf(self.work_pixbuff) def _rotate_left(self): - if self.work_pixbuf and self.pixbuf: - self.work_pixbuf = self.work_pixbuf.rotate_simple(GdkPixbuf.PixbufRotation.COUNTERCLOCKWISE) - self.pixbuf = self.pixbuf.rotate_simple(GdkPixbuf.PixbufRotation.COUNTERCLOCKWISE) - self.set_from_pixbuf(self.work_pixbuf) + if self.work_pixbuff and self.pixbuff: + self.work_pixbuff = self.work_pixbuff.rotate_simple(GdkPixbuf.PixbufRotation.COUNTERCLOCKWISE) + self.pixbuff = self.pixbuff.rotate_simple(GdkPixbuf.PixbufRotation.COUNTERCLOCKWISE) + self.set_from_pixbuf(self.work_pixbuff) def _vertical_flip(self): - if self.work_pixbuf and self.pixbuf: - self.work_pixbuf = self.work_pixbuf.flip(True) - self.pixbuf = self.pixbuf.flip(True) - self.set_from_pixbuf(self.work_pixbuf) + if self.work_pixbuff and self.pixbuff: + self.work_pixbuff = self.work_pixbuff.flip(True) + self.pixbuff = self.pixbuff.flip(True) + self.set_from_pixbuf(self.work_pixbuff) def _scale_1_two_1(self): self.fit_to_win = False - if self.work_pixbuf and self.pixbuf: - self.work_pixbuf = self.pixbuf - self.set_from_pixbuf(self.work_pixbuf) + if self.work_pixbuff and self.pixbuff: + self.work_pixbuff = self.pixbuff + self.set_from_pixbuf(self.work_pixbuff) - def _fit_to_container(self): + def _fit_to_container(self, pixbuff = None): self.fit_to_win = True - if self.work_pixbuf and self.pixbuf: + print(self.work_pixbuff) + + if (self.work_pixbuff and self.pixbuff) or pixbuff: parent_aloc = self.get_parent().get_parent().get_allocation() pw = parent_aloc.width ph = parent_aloc.height - iw = self.pixbuf.get_width() - ih = self.pixbuf.get_height() + iw = None + ih = None w = 0 h = 0 + if pixbuff: + iw = pixbuff.get_width() + ih = pixbuff.get_height() + else: + iw = self.pixbuff.get_width() + ih = self.pixbuff.get_height() + if iw == 0 or ih == 0: return @@ -58,34 +67,57 @@ class ImageViewMixin: h = ph w = (iw * h) / ih + 0.5 + if not pixbuff in (None, ""): + return pixbuff.scale_simple(w, h, 2) - self.work_pixbuf = self.pixbuf.scale_simple(w, h, 2) # 2 = BILINEAR and is best by default - self.set_from_pixbuf(self.work_pixbuf) + self.work_pixbuff = self.pixbuff.scale_simple(w, h, 2) # 2 = BILINEAR and is best by default + self.set_from_pixbuf(self.work_pixbuff) def _horizontal_flip(self): - if self.work_pixbuf and self.pixbuf: - self.work_pixbuf = self.work_pixbuf.flip(False) - self.pixbuf = self.pixbuf.flip(False) - self.set_from_pixbuf(self.work_pixbuf) + if self.work_pixbuff and self.pixbuff: + self.work_pixbuff = self.work_pixbuff.flip(False) + self.pixbuff = self.pixbuff.flip(False) + self.set_from_pixbuf(self.work_pixbuff) def _rotate_right(self): - if self.work_pixbuf and self.pixbuf: - self.work_pixbuf = self.work_pixbuf.rotate_simple(GdkPixbuf.PixbufRotation.CLOCKWISE) - self.pixbuf = self.pixbuf.rotate_simple(GdkPixbuf.PixbufRotation.CLOCKWISE) - self.set_from_pixbuf(self.work_pixbuf) + if self.work_pixbuff and self.pixbuff: + self.work_pixbuff = self.work_pixbuff.rotate_simple(GdkPixbuf.PixbufRotation.CLOCKWISE) + self.pixbuff = self.pixbuff.rotate_simple(GdkPixbuf.PixbufRotation.CLOCKWISE) + self.set_from_pixbuf(self.work_pixbuff) def _zoom_in(self): - if self.work_pixbuf and self.pixbuf: + if self.work_pixbuff and self.pixbuff: # TODO: Setup scale factor setting to pull from settings... - stepx = self.work_pixbuf.get_width() * 0.05 - stepy = self.work_pixbuf.get_height() * 0.05 + stepx = self.work_pixbuff.get_width() * 0.05 + stepy = self.work_pixbuff.get_height() * 0.05 - w = self.work_pixbuf.get_width() + stepx - h = self.work_pixbuf.get_height() + stepy + w = self.work_pixbuff.get_width() + stepx + h = self.work_pixbuff.get_height() + stepy - self.work_pixbuf = self.pixbuf.scale_simple(w, h, 2) # 2 = BILINEAR and is best by default - self.set_from_pixbuf(self.work_pixbuf) + self.work_pixbuff = self.pixbuff.scale_simple(w, h, 2) # 2 = BILINEAR and is best by default + self.set_from_pixbuf(self.work_pixbuff) def _size_allocate(self): if self.fit_to_win: self._fit_to_container() + + @daemon_threaded + def _play_animation(self): + import time + from gi.repository import GLib + + self.playing_animation = True + # NOTE: Divide by 1000 b/c time.sleep takes seconds but delay is in milliseconds + delay = self.animation.get_delay_time() / 1000 + + while self.playing_animation: + self.animation.advance() + + pixbuff = self.animation.get_pixbuf() + pixbuff = pixbuff if not self.fit_to_win else self._fit_to_container(pixbuff) + + GLib.idle_add(self.set_from_pixbuf, *(pixbuff,)) + time.sleep(delay) + + def _stop_animation(self): + self.playing_animation = False