# Python imports import os import uuid import pickle # Lib imports import gi gi.require_version('Gtk', '3.0') from gi.repository import Gtk from gi.repository import GLib # Application imports from .dynamic_header_widget import DynamicHeaderWidget class DynamicWidgetException(Exception): ... class DynamicWidget(Gtk.Box): def __init__(self, move_callback, path = None, x = None, y = None): super(DynamicWidget, self).__init__() self.uuid = str(uuid.uuid4()) self._header_widget = DynamicHeaderWidget(move_callback, x, y) self._body_widget = None self.save_needed = False self.is_not_stop_watcher = True self.is_self_destroyed = False self._setup_styling() self._setup_signals() self._subscribe_to_events() self._load_widgets() if not path else self.load_from_path(path) self.show_all() GLib.timeout_add(5000, self._save_watcher, GLib.PRIORITY_LOW) def _save_watcher(self, widget = None, eve = None): if self.save_needed: self.save() self.save_needed = False return self.is_not_stop_watcher # NOTE: Must be true to continue idle timeout calls def _setup_styling(self): self.set_orientation(1) self.set_size_request(256, 45) ctx = self.get_style_context() ctx.add_class("dynamic-widget") def _setup_signals(self): ... def _subscribe_to_events(self): ... def _load_widgets(self): try: self._body_widget = event_system.emit_and_await("get_widget_type") if not self._body_widget: raise Exception("No widget detected... Will not insert anything.") self.add(self._header_widget) self.add(self._body_widget) except DynamicWidgetException as e: logger.debug(e) raise Exception("No widget loaded!") def get_header(self): return self._header_widget def get_body(self): return self._body_widget def load_from_path(self, path): with open(path, "rb") as f: save_collection = pickle.load(f) event_system.emit("set_widget_type", save_collection["widget_type"]) self._load_widgets() self._load_collection_data(save_collection) def _load_collection_data(self, save_collection): self.uuid = save_collection["uuid"] self._header_widget._current_w = save_collection["w"] self._header_widget._current_h = save_collection["h"] self._header_widget._current_x = save_collection["x"] self._header_widget._current_y = save_collection["y"] self._header_widget.set_size_request(self._header_widget._current_w, self._header_widget._current_h) self._body_widget.set_saveable_data(save_collection) self._body_widget.load_saveable_data() def delete(self): path = f"{settings.get_active_page()}{self.uuid}" logger.debug(f"Deleteing: {path}") try: if os.path.exists(path): if os.path.isfile(path): os.remove(path) except Exception as e: logger.debug(f"Could not delete: {path}\n{e}") return self.is_self_destroyed = True self.is_not_stop_watcher = False self._header_widget.destroy() self._body_widget.destroy() self.destroy() def save(self): if not self.is_self_destroyed: save_collection = self._body_widget.get_saveable_data() save_collection["uuid"] = self.uuid save_collection["w"] = self._header_widget._current_w save_collection["h"] = self._header_widget._current_h save_collection["x"] = self._header_widget._current_x save_collection["y"] = self._header_widget._current_y path = f"{settings.get_active_page()}{self.uuid}" logger.debug(f"Saving: {path}") with open(path, "wb") as f: pickle.dump(save_collection, f, protocol = pickle.HIGHEST_PROTOCOL, fix_imports = True, buffer_callback = None)