From 8f2c202393c2581b42cb018ff76dbebd95b791cc Mon Sep 17 00:00:00 2001 From: itdominator <1itdominator@gmail.com> Date: Sun, 23 Oct 2022 02:08:53 -0500 Subject: [PATCH] refactoring --- src/__builtins__.py | 21 +++---- src/__main__.py | 1 + src/app.py | 20 ++----- src/core/drawing_area.py | 46 +++++++-------- ...{Main_menu_popup.py => main_menu_popup.py} | 13 ++--- src/core/main_window.py | 52 ++++++++++------- src/utils/endpoint_registry.py | 22 ++++++++ src/utils/event_system.py | 30 ++++++++++ src/utils/logger.py | 56 +++++++++++++++++++ src/utils/settings.py | 44 ++++++++------- src/utils/utils.py | 13 ++--- .../usr/share/cornea/Main_Window.glade | 2 +- 12 files changed, 216 insertions(+), 104 deletions(-) rename src/core/{Main_menu_popup.py => main_menu_popup.py} (79%) create mode 100644 src/utils/endpoint_registry.py create mode 100644 src/utils/event_system.py create mode 100644 src/utils/logger.py diff --git a/src/__builtins__.py b/src/__builtins__.py index 6ed885a..a931b35 100644 --- a/src/__builtins__.py +++ b/src/__builtins__.py @@ -4,6 +4,9 @@ import builtins, threading # Lib imports # Application imports +from utils.event_system import EventSystem +from utils.endpoint_registry import EndpointRegistry +from utils.settings import Settings @@ -21,18 +24,16 @@ def daemon_threaded_wrapper(fn): - -class Builtins: - """Docstring for __builtins__ extender""" - - def __init__(self): - pass - - - - # NOTE: Just reminding myself we can add to builtins two different ways... # __builtins__.update({"event_system": Builtins()}) builtins.app_name = "Cornea" builtins.threaded = threaded_wrapper builtins.daemon_threaded = daemon_threaded_wrapper + +builtins.settings = Settings() +builtins.logger = settings.get_logger() +builtins.event_system = EventSystem() +builtins.endpoint_registry = EndpointRegistry() + +from utils.utils import Utils +builtins.utils = Utils() diff --git a/src/__main__.py b/src/__main__.py index 82cbd5e..3283b7c 100755 --- a/src/__main__.py +++ b/src/__main__.py @@ -14,6 +14,7 @@ gi.require_version('Gtk', '3.0') from gi.repository import Gtk # Application imports +from __builtins__ import * from app import Application diff --git a/src/app.py b/src/app.py index c9966b6..18b5ca3 100644 --- a/src/app.py +++ b/src/app.py @@ -1,36 +1,28 @@ # Python imports -import inspect, signal +import inspect from setproctitle import setproctitle # Lib imports import gi gi.require_version('Gtk', '3.0') from gi.repository import Gtk -from gi.repository import GLib # Application imports -from __builtins__ import Builtins -from utils.settings import Settings -from utils.utils import Utils from core.main_window import MainWindow from core.drawing_area import DrawingArea -from core.Main_menu_popup import MainMenuPopup +from core.main_menu_popup import MainMenuPopup -class Application(Builtins): +class Application: def __init__(self, args, unknownargs): - GLib.unix_signal_add(GLib.PRIORITY_DEFAULT, signal.SIGINT, Gtk.main_quit) - - settings = Settings() builder = settings.get_builder() # Gets the methods from the classes and sets to handler. # Then, builder connects to any signals it needs. - utils = Utils(settings) classes = [ - MainWindow(settings, utils), - DrawingArea(settings, utils), - MainMenuPopup(settings, utils) + MainWindow(), + DrawingArea(), + MainMenuPopup() ] handlers = {} diff --git a/src/core/drawing_area.py b/src/core/drawing_area.py index 13ab53b..ac4647b 100644 --- a/src/core/drawing_area.py +++ b/src/core/drawing_area.py @@ -21,18 +21,15 @@ class MouseButtons: class DrawingArea: - def __init__(self, _settings, _utils): - self.settings = _settings - self.utils = _utils - - self.builder = self.settings.get_builder() + def __init__(self): + self.builder = settings.get_builder() self.main_window = self.builder.get_object('Main_Window') self.region_window = self.builder.get_object('Region_Window') self.region_menu = self.builder.get_object('regionMenu') self.message_label = self.builder.get_object('messageLabel') - MONITOR = self.settings.get_monitor_data() + MONITOR = settings.get_monitor_data() - self.settings.set_window_data(self.region_window) + settings.set_window_data(self.region_window) self.region_window.set_default_size(MONITOR[0].width, MONITOR[0].height) self.region_window.set_size_request(MONITOR[0].width, MONITOR[0].height) self.region_window.set_keep_above(True) @@ -46,8 +43,8 @@ class DrawingArea: self.DRAW_AREA.connect("motion-notify-event", self.on_mouse_move) self.DRAW_AREA.connect("draw", self.on_draw) - area = self.settings.get_monitor_data()[0] - self.SCREENSHOTS_DIR = self.settings.get_screenshots_dir() + area = settings.get_monitor_data()[0] + self.SCREENSHOTS_DIR = settings.get_screenshots_dir() self.WIN_REC = [area.x, area.y, area.width, area.height] self.coords = [[0.0, 0.0], [0.0, 0.0]] # point1 and point2 self.BORDER_COLOR = [255, 0, 0, 0.84] @@ -84,27 +81,31 @@ class DrawingArea: self.coords[1] = [e.x, e.y] self.DRAW_AREA.queue_draw() - @threaded def on_button_release(self, w, e): if e.type == Gdk.EventType.BUTTON_RELEASE and e.button == MouseButtons.LEFT_BUTTON: - GLib.idle_add(self.region_menu.show) + self.region_menu.show() - @threaded + @daemon_threaded def grab_region(self, widget): - self.main_window.hide() - self.region_menu.hide() + GLib.idle_add(self.main_window.hide) + GLib.idle_add(self.region_menu.hide) - GLib.idle_add(self.grab_regionIdle) + while self.main_window.is_visible(): + ... + while self.region_menu.is_visible(): + ... + + time.sleep(0.05) + self.grab_region_idle() - @threaded def go_to_main_window(self, widget): - GLib.idle_add(self.go_to_main_window_idle) + self.go_to_main_window_idle() - def grab_regionIdle(self): + def grab_region_idle(self): self.do_bounding_box_grab(self.rec[0], self.rec[1], self.rec[2], self.rec[3]) - self.utils.referesh_directory_list() - self.region_menu.show() - self.main_window.show() + GLib.idle_add(utils.referesh_directory_list) + GLib.idle_add(self.main_window.show) + GLib.idle_add(self.region_menu.show) def go_to_main_window_idle(self): self.region_window.hide() @@ -153,7 +154,6 @@ class DrawingArea: # Actual region grab def do_bounding_box_grab(self, x1, y1, x2, y2): - self.utils.sleep(0.4) try: temp = 0; if x2 < x1: @@ -167,7 +167,7 @@ class DrawingArea: y2 = temp - self.utils.do_bounding_box_grab(x1, y1, x2, y2) + utils.do_bounding_box_grab(x1, y1, x2, y2) markup = "Grabbed region successfully..." GLib.idle_add(self.message_label.set_markup, markup) except Exception as e: diff --git a/src/core/Main_menu_popup.py b/src/core/main_menu_popup.py similarity index 79% rename from src/core/Main_menu_popup.py rename to src/core/main_menu_popup.py index d764b28..f5a49ff 100644 --- a/src/core/Main_menu_popup.py +++ b/src/core/main_menu_popup.py @@ -8,13 +8,10 @@ import os, subprocess class MainMenuPopup: - def __init__(self, _settings, _utils): - self.settings = _settings - self.utils = _utils - - self.builder = self.settings.get_builder() + def __init__(self): + self.builder = settings.get_builder() self.file_name_entry = self.builder.get_object("fileNameEntry") - self.SCREENSHOTS_DIR = self.settings.get_screenshots_dir() + self.SCREENSHOTS_DIR = settings.get_screenshots_dir() self.backup_name = None @@ -26,7 +23,7 @@ class MainMenuPopup: if os.path.isfile(old_file_path) and new_name: os.rename(old_file_path, new_file_path) self.backup_name = new_name - self.utils.referesh_directory_list() + utils.referesh_directory_list() except Exception as e: print(repr(e)) @@ -40,7 +37,7 @@ class MainMenuPopup: if os.path.isfile(file): os.remove(file) self.builder.get_object("mainMenu").popdown() - self.utils.referesh_directory_list() + utils.referesh_directory_list() except Exception as e: print(repr(e)) diff --git a/src/core/main_window.py b/src/core/main_window.py index 9082efb..ace5f38 100644 --- a/src/core/main_window.py +++ b/src/core/main_window.py @@ -1,5 +1,5 @@ # Python imports -import os +import os, signal, time import pyscreenshot as capture # Lib imports @@ -21,16 +21,13 @@ class MouseButtons: class MainWindow: - def __init__(self, _settings, _utils): - self.settings = _settings - self.utils = _utils - - self.builder = self.settings.get_builder() + def __init__(self): + self.builder = settings.get_builder() self.main_window = self.builder.get_object('Main_Window') self.region_window = self.builder.get_object('Region_Window') self.monitors_view = self.builder.get_object("monitorsView") self.monitor_store = self.builder.get_object("monitorStore") - self.MONITORS = self.settings.get_monitor_data() + self.MONITORS = settings.get_monitor_data() # Not adding the reference monitor i = 0 @@ -42,8 +39,10 @@ class MainWindow: self.monitors_view.set_cursor(1) - self.SCREENSHOTS_DIR = self.settings.get_screenshots_dir() - self.utils.referesh_directory_list() + self.SCREENSHOTS_DIR = settings.get_screenshots_dir() + utils.referesh_directory_list() + + GLib.unix_signal_add(GLib.PRIORITY_DEFAULT, signal.SIGINT, Gtk.main_quit) def take_screenshot(self, widget): @@ -60,39 +59,52 @@ class MainWindow: self.snapshot_monitor() - @threaded def grab_entire_screen(self): self.main_window.hide() - GLib.idle_add(self.get_entire_screen) + self.get_entire_screen() def get_entire_screen(self): # childprocess=False needed to not crash program im = capture.grab(childprocess=False) - im.save(self.utils.generate_screenshot_name()) + im.save(utils.generate_screenshot_name()) self.main_window.show() - self.utils.referesh_directory_list() + utils.referesh_directory_list() def get_active_window(self): - self.utils.sleep() + utils.sleep() screen = Gdk.get_default_root_window().get_screen() w = screen.get_active_window() pb = Gdk.pixbuf_get_from_window(w, *w.get_geometry()) - pb.savev(self.utils.generate_screenshot_name(), "png", (), ()) - self.utils.referesh_directory_list() + pb.savev(utils.generate_screenshot_name(), "png", (), ()) + utils.referesh_directory_list() + + + @daemon_threaded def snapshot_monitor(self): + GLib.idle_add(self.main_window.hide) + + while self.main_window.is_visible(): + ... + + time.sleep(0.05) + GLib.idle_add(self.do_snapshot_monitor) + + + def do_snapshot_monitor(self): iterator = self.monitors_view.get_selection().get_selected()[1] path = self.monitor_store.get_path(iterator) # Slot 0 is ref monitor. Need to add 1 to get proper slot monitor = self.MONITORS[int(str(path)) + 1] - self.utils.sleep() + utils.sleep() x2 = monitor.x + monitor.width y2 = monitor.y + monitor.height - self.utils.do_bounding_box_grab(monitor.x, monitor.y, x2, y2) - self.utils.referesh_directory_list() + utils.do_bounding_box_grab(monitor.x, monitor.y, x2, y2) + utils.referesh_directory_list() + self.main_window.show() def toggle_radio_bttn(self, widget): delay_amount = self.builder.get_object('delayAmount') @@ -115,7 +127,7 @@ class MainWindow: def set_image(self, user_data): # We need the refresh state for the files list b/c GtkTreeSelection # is calling this method b/c caling this too quickly causes issues... - if self.utils.get_refreshing_state() == False: + if utils.get_refreshing_state() == False: selected = user_data.get_selected()[1] if selected: fileNameEntry = self.builder.get_object("fileNameEntry") diff --git a/src/utils/endpoint_registry.py b/src/utils/endpoint_registry.py new file mode 100644 index 0000000..15ffa9e --- /dev/null +++ b/src/utils/endpoint_registry.py @@ -0,0 +1,22 @@ +# Python imports + +# Lib imports + +# Application imports + + + + +class EndpointRegistry(): + def __init__(self): + self._endpoints = {} + + def register(self, rule, **options): + def decorator(f): + self._endpoints[rule] = f + return f + + return decorator + + def get_endpoints(self): + return self._endpoints diff --git a/src/utils/event_system.py b/src/utils/event_system.py new file mode 100644 index 0000000..25c96fc --- /dev/null +++ b/src/utils/event_system.py @@ -0,0 +1,30 @@ +# Python imports +from collections import defaultdict + +# Lib imports + +# Application imports + + + + +class EventSystem: + """ Create event system. """ + + def __init__(self): + self.subscribers = defaultdict(list) + + + def subscribe(self, event_type, fn): + self.subscribers[event_type].append(fn) + + def emit(self, event_type, data = None): + if event_type in self.subscribers: + for fn in self.subscribers[event_type]: + if data: + if hasattr(data, '__iter__') and not type(data) is str: + fn(*data) + else: + fn(data) + else: + fn() diff --git a/src/utils/logger.py b/src/utils/logger.py new file mode 100644 index 0000000..c33444f --- /dev/null +++ b/src/utils/logger.py @@ -0,0 +1,56 @@ +# Python imports +import os, logging + +# Application imports + + +class Logger: + """ + Create a new logging object and return it. + :note: + NOSET # Don't know the actual log level of this... (defaulting or literally none?) + Log Levels (From least to most) + Type Value + CRITICAL 50 + ERROR 40 + WARNING 30 + INFO 20 + DEBUG 10 + :param loggerName: Sets the name of the logger object. (Used in log lines) + :param createFile: Whether we create a log file or just pump to terminal + + :return: the logging object we created + """ + + def __init__(self, config_path: str, _ch_log_lvl = logging.CRITICAL, _fh_log_lvl = logging.INFO): + self._CONFIG_PATH = config_path + self.global_lvl = logging.DEBUG # Keep this at highest so that handlers can filter to their desired levels + self.ch_log_lvl = _ch_log_lvl # Prety much the only one we ever change + self.fh_log_lvl = _fh_log_lvl + + def get_logger(self, loggerName: str = "NO_LOGGER_NAME_PASSED", createFile: bool = True) -> logging.Logger: + log = logging.getLogger(loggerName) + log.setLevel(self.global_lvl) + + # Set our log output styles + fFormatter = logging.Formatter('[%(asctime)s] %(pathname)s:%(lineno)d %(levelname)s - %(message)s', '%m-%d %H:%M:%S') + cFormatter = logging.Formatter('%(pathname)s:%(lineno)d] %(levelname)s - %(message)s') + + ch = logging.StreamHandler() + ch.setLevel(level=self.ch_log_lvl) + ch.setFormatter(cFormatter) + log.addHandler(ch) + + if createFile: + folder = self._CONFIG_PATH + file = f"{folder}/application.log" + + if not os.path.exists(folder): + os.mkdir(folder) + + fh = logging.FileHandler(file) + fh.setLevel(level=self.fh_log_lvl) + fh.setFormatter(fFormatter) + log.addHandler(fh) + + return log diff --git a/src/utils/settings.py b/src/utils/settings.py index 8f8f95a..94d1574 100644 --- a/src/utils/settings.py +++ b/src/utils/settings.py @@ -11,19 +11,22 @@ from gi.repository import Gdk # Application imports +from .logger import Logger + + class Settings: def __init__(self): - self._SCRIPT_PTH = os.path.dirname(os.path.realpath(__file__)) - self._USER_HOME = os.path.expanduser('~') - self._CONFIG_PATH = f"{self._USER_HOME}/.config/{app_name.lower()}" - self._GLADE_FILE = f"{self._CONFIG_PATH}/Main_Window.glade" - self._CSS_FILE = f"{self._CONFIG_PATH}/stylesheet.css" - self._DEFAULT_ICONS = f"{self._CONFIG_PATH}/icons" - self._WINDOW_ICON = f"{self._DEFAULT_ICONS}/{app_name.lower()}.png" - self._USR_PATH = f"/usr/share/{app_name.lower()}" - self.SCREENSHOTS_DIR = f"{self._USER_HOME}/.screenshots" + self._SCRIPT_PTH = os.path.dirname(os.path.realpath(__file__)) + self._USER_HOME = os.path.expanduser('~') + self._CONFIG_PATH = f"{self._USER_HOME}/.config/{app_name.lower()}" + self._GLADE_FILE = f"{self._CONFIG_PATH}/Main_Window.glade" + self._CSS_FILE = f"{self._CONFIG_PATH}/stylesheet.css" + self._DEFAULT_ICONS = f"{self._CONFIG_PATH}/icons" + self._WINDOW_ICON = f"{self._DEFAULT_ICONS}/{app_name.lower()}.png" + self._USR_PATH = f"/usr/share/{app_name.lower()}" + self._SCREENSHOTS_DIR = f"{self._USER_HOME}/.screenshots" if not os.path.exists(self._CONFIG_PATH): os.mkdir(self._CONFIG_PATH) @@ -33,19 +36,19 @@ class Settings: self._CSS_FILE = f"{self._USR_PATH}/stylesheet.css" if not os.path.exists(self._WINDOW_ICON): self._WINDOW_ICON = f"{self._USR_PATH}/icons/{app_name.lower()}.png" - if not os.path.isdir(self.SCREENSHOTS_DIR): - os.mkdir(self.SCREENSHOTS_DIR) + if not os.path.isdir(self._SCREENSHOTS_DIR): + os.mkdir(self._SCREENSHOTS_DIR) # 'Filters' - self.images = ('.png', '.jpg', '.jpeg', '.gif') - - self.builder = Gtk.Builder() - self.builder.add_from_file(self._GLADE_FILE) + self._images = ('.png', '.jpg', '.jpeg', '.gif') + self._builder = Gtk.Builder() + self._builder.add_from_file(self._GLADE_FILE) + self._logger = Logger(self._CONFIG_PATH, _fh_log_lvl=20).get_logger() def create_window(self): # Get window and connect signals - window = self.builder.get_object("Main_Window") + window = self._builder.get_object("Main_Window") window.connect("delete-event", Gtk.main_quit) self.set_window_data(window) return window @@ -65,7 +68,7 @@ class Settings: style_context.add_provider_for_screen(screen, css_provider, Gtk.STYLE_PROVIDER_PRIORITY_USER) def get_monitor_data(self): - screen = self.builder.get_object("Main_Window").get_screen() + screen = self._builder.get_object("Main_Window").get_screen() wdth = screen.get_width() hght = screen.get_height() mon0 = Gdk.Rectangle() @@ -80,8 +83,9 @@ class Settings: return monitors - def get_builder(self): return self.builder - def get_screenshots_dir(self): return self.SCREENSHOTS_DIR + def get_builder(self) -> Gtk.Builder: return self._builder + def get_logger(self) -> Logger: return self._logger + def get_screenshots_dir(self) -> str: return self._SCREENSHOTS_DIR # Filter returns - def get_images_filter(self): return self.images + def get_images_filter(self): return self._images diff --git a/src/utils/utils.py b/src/utils/utils.py index af13fef..da99279 100644 --- a/src/utils/utils.py +++ b/src/utils/utils.py @@ -5,18 +5,16 @@ import os, time, datetime from gi.repository import GLib import pyscreenshot as capture - # Application imports class Utils: - def __init__(self, _settings): - self.settings = _settings - self.builder = self.settings.get_builder() + def __init__(self): + self.builder = settings.get_builder() - self.SCREENSHOTS_DIR = self.settings.get_screenshots_dir() + self.SCREENSHOTS_DIR = settings.get_screenshots_dir() self.file_store = self.builder.get_object("fileStore") self.refreshing_state = False @@ -31,6 +29,7 @@ class Utils: @threaded def referesh_directory_list(self): self.refreshing_state = True + images = self.get_directory_list() images.sort() if len(images) != len(self.file_store): @@ -38,11 +37,9 @@ class Utils: for image in images: GLib.idle_add(self.add_to_store, (image)) - # self.file_store.sort() self.refreshing_state = False - @threaded def add_to_store(self, image): self.file_store.append([image]) @@ -82,7 +79,7 @@ class Utils: data = proc.stdout.read() return data.decode("utf-8").strip() - def setClipboardData(self, data): + def set_clipboard_data(self, data): proc = subprocess.Popen(['xclip','-selection','clipboard'], stdin=subprocess.PIPE) proc.stdin.write(data) proc.stdin.close() diff --git a/user_config/usr/share/cornea/Main_Window.glade b/user_config/usr/share/cornea/Main_Window.glade index 619fb2c..79088d5 100644 --- a/user_config/usr/share/cornea/Main_Window.glade +++ b/user_config/usr/share/cornea/Main_Window.glade @@ -8,7 +8,7 @@ True False False - center + static True