diff --git a/src/__main__.py b/src/__main__.py index 5bbe908..d44b8cc 100644 --- a/src/__main__.py +++ b/src/__main__.py @@ -10,9 +10,6 @@ import tracemalloc tracemalloc.start() # Lib imports -import gi -gi.require_version('Gtk', '3.0') -from gi.repository import Gtk # Application imports from __builtins__ import * @@ -20,7 +17,6 @@ from app import Application - if __name__ == "__main__": ''' Set process title, get arguments, and create GTK main thread. ''' @@ -47,7 +43,6 @@ if __name__ == "__main__": settings_manager.do_dirty_start_check() Application(args, unknownargs) - Gtk.main() except Exception as e: traceback.print_exc() quit() \ No newline at end of file diff --git a/src/app.py b/src/app.py index e00fc89..b945b22 100644 --- a/src/app.py +++ b/src/app.py @@ -16,35 +16,39 @@ class AppLaunchException(Exception): -class Application(IPCServer): +class Application: """ docstring for Application. """ def __init__(self, args, unknownargs): super(Application, self).__init__() if not settings_manager.is_trace_debug(): - self.socket_realization_check() - - if not self.is_ipc_alive: - for arg in unknownargs + [args.new_tab,]: - if os.path.isfile(arg): - message = f"FILE|{arg}" - self.send_ipc_message(message) - - raise AppLaunchException(f"{app_name} IPC Server Exists: Have sent path(s) to it and closing...") + self.load_ipc(args, unknownargs) self.setup_debug_hook() - Window(args, unknownargs) + Window(args, unknownargs).main() - def socket_realization_check(self): + def load_ipc(self, args, unknownargs): + ipc_server = IPCServer() + self.ipc_realization_check(ipc_server) + + if not ipc_server.is_ipc_alive: + for arg in unknownargs + [args.new_tab,]: + if os.path.isfile(arg): + message = f"FILE|{arg}" + ipc_server.send_ipc_message(message) + + raise AppLaunchException(f"{app_name} IPC Server Exists: Have sent path(s) to it and closing...") + + def ipc_realization_check(self, ipc_server): try: - self.create_ipc_listener() + ipc_server.create_ipc_listener() except Exception: - self.send_test_ipc_message() + ipc_server.send_test_ipc_message() try: - self.create_ipc_listener() + ipc_server.create_ipc_listener() except Exception as e: ... diff --git a/src/core/window.py b/src/core/window.py index 66b374a..a30c852 100644 --- a/src/core/window.py +++ b/src/core/window.py @@ -20,7 +20,6 @@ class ControllerStartExceptiom(Exception): - class Window(Gtk.ApplicationWindow): """docstring for Window.""" @@ -30,12 +29,12 @@ class Window(Gtk.ApplicationWindow): self._controller = None - self._set_window_data() self._setup_styling() self._setup_signals() self._subscribe_to_events() - self._load_widgets(args, unknownargs) + + self._set_window_data() self._set_size_constraints() self.show() @@ -49,6 +48,7 @@ class Window(Gtk.ApplicationWindow): ctx = self.get_style_context() ctx.add_class("main-window") + ctx.add_class(f"mw_transparency_{settings.theming.transparency}") def _setup_signals(self): self.connect("delete-event", self._tear_down) @@ -56,6 +56,7 @@ class Window(Gtk.ApplicationWindow): def _subscribe_to_events(self): event_system.subscribe("tear_down", self._tear_down) + event_system.subscribe("load_interactive_debug", self._load_interactive_debug) def _load_widgets(self, args, unknownargs): if settings_manager.is_debug(): @@ -83,7 +84,7 @@ class Window(Gtk.ApplicationWindow): screen = self.get_screen() visual = screen.get_rgba_visual() - if visual != None and screen.is_composited(): + if visual != None and screen.is_composited() and settings.config.make_transparent == 0: self.set_visual(visual) self.set_app_paintable(True) self.connect("draw", self._area_draw) @@ -101,6 +102,9 @@ class Window(Gtk.ApplicationWindow): cr.paint() cr.set_operator(cairo.OPERATOR_OVER) + def _load_interactive_debug(self): + self.set_interactive_debugging(True) + def _tear_down(self, widget = None, eve = None): event_system.emit("shutting_down") @@ -116,3 +120,6 @@ class Window(Gtk.ApplicationWindow): settings_manager.clear_pid() Gtk.main_quit() + + def main(self): + Gtk.main() \ No newline at end of file diff --git a/src/libs/data_types/__init__.py b/src/libs/data_types/__init__.py new file mode 100644 index 0000000..16675ec --- /dev/null +++ b/src/libs/data_types/__init__.py @@ -0,0 +1,5 @@ +""" + Dasta Class module +""" + +from .event import Event \ No newline at end of file diff --git a/src/libs/data_types/event.py b/src/libs/data_types/event.py new file mode 100644 index 0000000..0b084b7 --- /dev/null +++ b/src/libs/data_types/event.py @@ -0,0 +1,15 @@ +# Python imports +from dataclasses import dataclass, field + +# Lib imports +import gi + +# Application imports + + + +@dataclass +class Event: + topic: str + target: str + content: str diff --git a/src/libs/mixins/__init__.py b/src/libs/mixins/__init__.py new file mode 100644 index 0000000..6eb3b43 --- /dev/null +++ b/src/libs/mixins/__init__.py @@ -0,0 +1,3 @@ +""" + Utils/Mixins module +""" \ No newline at end of file diff --git a/src/libs/mixins/dnd_mixin.py b/src/libs/mixins/dnd_mixin.py new file mode 100644 index 0000000..e66f7cc --- /dev/null +++ b/src/libs/mixins/dnd_mixin.py @@ -0,0 +1,70 @@ +# Python imports + +# Lib imports +import gi +gi.require_version('Gtk', '3.0') +gi.require_version('Gdk', '3.0') +from gi.repository import Gtk +from gi.repository import Gdk +from gi.repository import Gio + +# Application imports + + + +class DnDMixin: + + def _setup_dnd(self): + flags = Gtk.DestDefaults.ALL + + PLAIN_TEXT_TARGET_TYPE = 70 + URI_TARGET_TYPE = 80 + + text_target = Gtk.TargetEntry.new('text/plain', Gtk.TargetFlags(0), PLAIN_TEXT_TARGET_TYPE) + uri_target = Gtk.TargetEntry.new('text/uri-list', Gtk.TargetFlags(0), URI_TARGET_TYPE) + + # targets = [ text_target, uri_target ] + targets = [ uri_target ] + + action = Gdk.DragAction.COPY + + # self.drag_dest_set_target_list(targets) + self.drag_dest_set(flags, targets, action) + + self._setup_dnd_signals() + + def _setup_dnd_signals(self): + # self.drag_motion_id = self.connect("drag-motion", self._on_drag_motion) + # self.drag_drop_id = self.connect('drag-drop', self._on_drag_set) + self.drag_data_received_id = self.connect("drag-data-received", self._on_drag_data_received) + + def _on_drag_motion(self, widget, drag_context, x, y, time): + Gdk.drag_status(drag_context, drag_context.get_actions(), time) + + return False + + def _on_drag_set(self, widget, drag_context, data, info, time): + self.drag_get_data(drag_context, drag_context.list_targets()[-1], time) + + return False + + def _on_drag_data_received(self, widget, drag_context, x, y, data, info, time): + if info == 70: return + + if info == 80: + uris = data.get_uris() + files = [] + + if len(uris) == 0: + uris = data.get_text().split("\n") + + for uri in uris: + gfile = None + try: + gfile = Gio.File.new_for_uri(uri) + except Exception as e: + gfile = Gio.File.new_for_path(uri) + + files.append(gfile) + + event_system.emit('set_pre_drop_dnd', (files,)) diff --git a/src/libs/settings_manager/start_check_mixin.py b/src/libs/settings_manager/start_check_mixin.py index 688da36..6fc8208 100644 --- a/src/libs/settings_manager/start_check_mixin.py +++ b/src/libs/settings_manager/start_check_mixin.py @@ -11,36 +11,48 @@ import inspect class StartCheckMixin: - def is_dirty_start(self) -> bool: return self._dirty_start - def clear_pid(self): self._clean_pid() + def is_dirty_start(self) -> bool: + return self._dirty_start + + def clear_pid(self): + if not self.is_trace_debug(): + self._clean_pid() def do_dirty_start_check(self): - if not os.path.exists(self._PID_FILE): - self._write_new_pid() - else: - with open(self._PID_FILE, "r") as _pid: - pid = _pid.readline().strip() + if self.is_trace_debug(): + pid = os.getpid() + self._print_pid(pid) + return + + if os.path.exists(self._PID_FILE): + with open(self._PID_FILE, "r") as f: + pid = f.readline().strip() if pid not in ("", None): - self._check_alive_status(int(pid)) - else: - self._write_new_pid() + if self.is_pid_alive( int(pid) ): + print("PID file exists and PID is alive... Letting downstream errors (sans debug args) handle app closure propigation.") + return + + self._write_new_pid() """ Check For the existence of a unix pid. """ - def _check_alive_status(self, pid): + def is_pid_alive(self, pid): print(f"PID Found: {pid}") + try: os.kill(pid, 0) except OSError: - print(f"{app_name} is starting dirty...") + print(f"{app_name} PID file exists but PID is irrelevant; starting dirty...") self._dirty_start = True - self._write_new_pid() - return + return False - print("PID is alive... Let downstream errors (sans debug args) handle app closure propigation.") + return True def _write_new_pid(self): pid = os.getpid() self._write_pid(pid) + self._print_pid(pid) + + def _print_pid(self, pid): print(f"{app_name} PID: {pid}") def _clean_pid(self): @@ -48,4 +60,4 @@ class StartCheckMixin: def _write_pid(self, pid): with open(self._PID_FILE, "w") as _pid: - _pid.write(f"{pid}") + _pid.write(f"{pid}") \ No newline at end of file diff --git a/user_config/usr/share/newton/context_path/index.html b/user_config/usr/share/newton/context_path/index.html new file mode 100644 index 0000000..ab5f99d --- /dev/null +++ b/user_config/usr/share/newton/context_path/index.html @@ -0,0 +1,78 @@ + + +
+ +++
+
`s get reset. However, we also reset the\n// bottom margin to use `rem` units instead of `em`.\n\np {\n margin-top: 0;\n margin-bottom: $paragraph-margin-bottom;\n}\n\n\n// Abbreviations\n//\n// 1. Add the correct text decoration in Chrome, Edge, Opera, and Safari.\n// 2. Add explicit cursor to indicate changed behavior.\n// 3. Prevent the text-decoration to be skipped.\n\nabbr[title] {\n text-decoration: underline dotted; // 1\n cursor: help; // 2\n text-decoration-skip-ink: none; // 3\n}\n\n\n// Address\n\naddress {\n margin-bottom: 1rem;\n font-style: normal;\n line-height: inherit;\n}\n\n\n// Lists\n\nol,\nul {\n padding-left: 2rem;\n}\n\nol,\nul,\ndl {\n margin-top: 0;\n margin-bottom: 1rem;\n}\n\nol ol,\nul ul,\nol ul,\nul ol {\n margin-bottom: 0;\n}\n\ndt {\n font-weight: $dt-font-weight;\n}\n\n// 1. Undo browser default\n\ndd {\n margin-bottom: .5rem;\n margin-left: 0; // 1\n}\n\n\n// Blockquote\n\nblockquote {\n margin: 0 0 1rem;\n}\n\n\n// Strong\n//\n// Add the correct font weight in Chrome, Edge, and Safari\n\nb,\nstrong {\n font-weight: $font-weight-bolder;\n}\n\n\n// Small\n//\n// Add the correct font size in all browsers\n\nsmall {\n @include font-size($small-font-size);\n}\n\n\n// Mark\n\nmark {\n padding: $mark-padding;\n background-color: var(--#{$prefix}highlight-bg);\n}\n\n\n// Sub and Sup\n//\n// Prevent `sub` and `sup` elements from affecting the line height in\n// all browsers.\n\nsub,\nsup {\n position: relative;\n @include font-size($sub-sup-font-size);\n line-height: 0;\n vertical-align: baseline;\n}\n\nsub { bottom: -.25em; }\nsup { top: -.5em; }\n\n\n// Links\n\na {\n color: rgba(var(--#{$prefix}link-color-rgb), var(--#{$prefix}link-opacity, 1));\n text-decoration: $link-decoration;\n\n &:hover {\n --#{$prefix}link-color-rgb: var(--#{$prefix}link-hover-color-rgb);\n text-decoration: $link-hover-decoration;\n }\n}\n\n// And undo these styles for placeholder links/named anchors (without href).\n// It would be more straightforward to just use a[href] in previous block, but that\n// causes specificity issues in many other styles that are too complex to fix.\n// See https://github.com/twbs/bootstrap/issues/19402\n\na:not([href]):not([class]) {\n &,\n &:hover {\n color: inherit;\n text-decoration: none;\n }\n}\n\n\n// Code\n\npre,\ncode,\nkbd,\nsamp {\n font-family: $font-family-code;\n @include font-size(1em); // Correct the odd `em` font sizing in all browsers.\n}\n\n// 1. Remove browser default top margin\n// 2. Reset browser default of `1em` to use `rem`s\n// 3. Don't allow content to break outside\n\npre {\n display: block;\n margin-top: 0; // 1\n margin-bottom: 1rem; // 2\n overflow: auto; // 3\n @include font-size($code-font-size);\n color: $pre-color;\n\n // Account for some code outputs that place code tags in pre tags\n code {\n @include font-size(inherit);\n color: inherit;\n word-break: normal;\n }\n}\n\ncode {\n @include font-size($code-font-size);\n color: var(--#{$prefix}code-color);\n word-wrap: break-word;\n\n // Streamline the style when inside anchors to avoid broken underline and more\n a > & {\n color: inherit;\n }\n}\n\nkbd {\n padding: $kbd-padding-y $kbd-padding-x;\n @include font-size($kbd-font-size);\n color: $kbd-color;\n background-color: $kbd-bg;\n @include border-radius($border-radius-sm);\n\n kbd {\n padding: 0;\n @include font-size(1em);\n font-weight: $nested-kbd-font-weight;\n }\n}\n\n\n// Figures\n//\n// Apply a consistent margin strategy (matches our type styles).\n\nfigure {\n margin: 0 0 1rem;\n}\n\n\n// Images and content\n\nimg,\nsvg {\n vertical-align: middle;\n}\n\n\n// Tables\n//\n// Prevent double borders\n\ntable {\n caption-side: bottom;\n border-collapse: collapse;\n}\n\ncaption {\n padding-top: $table-cell-padding-y;\n padding-bottom: $table-cell-padding-y;\n color: $table-caption-color;\n text-align: left;\n}\n\n// 1. Removes font-weight bold by inheriting\n// 2. Matches default `