# Python imports # 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 # Application imports class ImageView(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._setup_styling() self._setup_signals() self._subscribe_to_events() self._load_widgets() self.show_all() def _setup_styling(self): ... def _setup_signals(self): ... def _subscribe_to_events(self): event_system.subscribe("zoom_out", self._zoom_out) event_system.subscribe("handle_file_from_dnd", self._handle_file_from_dnd) event_system.subscribe("vertical_flip", self._vertical_flip) event_system.subscribe("rotate_left", self._rotate_left) event_system.subscribe("scale_1_two_1", self._scale_1_two_1) event_system.subscribe("fit_to_container", self._fit_to_container) event_system.subscribe("horizontal_flip", self._horizontal_flip) event_system.subscribe("rotate_right", self._rotate_right) event_system.subscribe("zoom_in", self._zoom_in) event_system.subscribe("size_allocate", self._size_allocate) def _load_widgets(self): ... def _handle_file_from_dnd(self, path = None): logger.debug(f"Loading image from: {path}") self.load_path(path) if self.animation: logger.debug("Start animation stub...") def load_path(self, path): self.pixbuf = None self.work_pixbuf = None self.animation = None if path.endswith(".gif"): self.work_pixbuf = GdkPixbuf.PixbufAnimation.new_from_file(path).get_static_image() try: self.animation = Gtk.Image.new_from_file(path).get_animation() except Exception: self.animation = Gtk.Image.new_from_resource(path).get_animation() if not self.work_pixbuf: try: self.work_pixbuf = Gtk.Image.new_from_file(path).get_pixbuf() except Exception: self.work_pixbuf = Gtk.Image.new_from_resource(path).get_pixbuf() self.pixbuf = self.work_pixbuf self.set_from_pixbuf(self.work_pixbuf) if self.fit_to_win: self._fit_to_container() event_system.emit("update_path_label", (path,)) def _zoom_out(self): if self.work_pixbuf and self.pixbuf: # 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 w = self.work_pixbuf.get_width() - stepx h = self.work_pixbuf.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) 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) 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) 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) def _fit_to_container(self): self.fit_to_win = True if self.work_pixbuf and self.pixbuf: 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() w = 0 h = 0 if iw == 0 or ih == 0: return w = pw; h = ((ih * w) / iw + 0.5) if h > ph: h = ph w = (iw * h) / ih + 0.5 self.work_pixbuf = self.pixbuf.scale_simple(w, h, 2) # 2 = BILINEAR and is best by default self.set_from_pixbuf(self.work_pixbuf) 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) 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) def _zoom_in(self): if self.work_pixbuf and self.pixbuf: # 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 w = self.work_pixbuf.get_width() + stepx h = self.work_pixbuf.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) def _size_allocate(self): if self.fit_to_win: self._fit_to_container()