Compare commits

...

12 Commits

42 changed files with 281 additions and 213 deletions

View File

@ -3,6 +3,7 @@ A template project for Python with Gtk applications.
### Requirements
* PyGObject (Gtk introspection library)
* pygobject-stubs (For actually getting pylsp or python-language-server to auto complete in LSPs. Do if GTK3 --no-cache-dir --config-settings=config=Gtk3,Gdk3,Soup2)
* pyxdg (Desktop ".desktop" file parser)
* setproctitle (Define process title to search and kill more easily)
* sqlmodel (SQL databases and is powered by Pydantic and SQLAlchemy)

View File

@ -1,4 +1,5 @@
PyGObject
pygobject-stubs --no-cache-dir --config-settings=config=Gtk3,Gdk3,Soup2
pyxdg
setproctitle
sqlmodel
sqlmodel

View File

@ -11,7 +11,7 @@ from libs.event_system import EventSystem
from libs.endpoint_registry import EndpointRegistry
from libs.keybindings import Keybindings
from libs.logger import Logger
from libs.settings_manager.manager import SettingsManager
from libs.settings.manager import SettingsManager
@ -35,7 +35,7 @@ def daemon_threaded_wrapper(fn):
# NOTE: Just reminding myself we can add to builtins two different ways...
# __builtins__.update({"event_system": Builtins()})
builtins.app_name = "<change_me>"
builtins.APP_NAME = "<change_me>"
builtins.keybindings = Keybindings()
builtins.event_system = EventSystem()

View File

@ -18,7 +18,7 @@ from app import Application
def main(args, unknownargs):
setproctitle(f'{app_name}')
setproctitle(f'{APP_NAME}')
if args.debug == "true":
settings_manager.set_debug(True)

View File

@ -39,7 +39,7 @@ class Application:
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...")
raise AppLaunchException(f"{APP_NAME} IPC Server Exists: Have sent path(s) to it and closing...")
def ipc_realization_check(self, ipc_server):
try:
@ -56,7 +56,7 @@ class Application:
try:
# kill -SIGUSR2 <pid> from Linux/Unix or SIGBREAK signal from Windows
signal.signal(
vars(signal).get("SIGBREAK") or vars(signal).get("SIGUSR1"),
vars(signal).get("SIGBREAK") or vars(signal).get("SIGUSR2"),
debug_signal_handler
)
except ValueError:

View File

@ -0,0 +1,33 @@
# Python imports
# Lib imports
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
# Application imports
class BuilderWrapper(Gtk.Builder):
"""docstring for BuilderWrapper."""
def __init__(self):
super(BuilderWrapper, self).__init__()
self.objects = {}
def get_object(self, id: str, use_gtk: bool = True) -> any:
if not use_gtk:
return self.objects[id]
return super(BuilderWrapper, self).get_object(id)
def expose_object(self, id: str, object: any, use_gtk: bool = True) -> None:
if not use_gtk:
self.objects[id] = object
else:
super(BuilderWrapper, self).expose_object(id, object)
def dereference_object(self, id: str) -> None:
del self.objects[id]

View File

@ -33,8 +33,8 @@ class BaseContainer(Gtk.Box):
...
def _subscribe_to_events(self):
event_system.subscribe("update_transparency", self._update_transparency)
event_system.subscribe("remove_transparency", self._remove_transparency)
event_system.subscribe("update-transparency", self._update_transparency)
event_system.subscribe("remove-transparency", self._remove_transparency)
def _load_widgets(self):
self.add(HeaderContainer())

View File

@ -31,7 +31,6 @@ class CenterContainer(Gtk.Box):
...
def _subscribe_to_events(self):
# event_system.subscribe("handle_file_from_ipc", self.handle_file_from_ipc)
...
def _load_widgets(self):

View File

@ -6,7 +6,8 @@ gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
# Application imports
from ..widgets.transparency_scale import TransparencyScale
from ..widgets.controls.open_files_button import OpenFilesButton
from ..widgets.controls.transparency_scale import TransparencyScale
@ -32,15 +33,19 @@ class HeaderContainer(Gtk.Box):
...
def _subscribe_to_events(self):
...
event_system.subscribe("tggl-top-main-menubar", self.tggl_top_main_menubar)
def _load_widgets(self):
button = Gtk.Button(label = "Interactive Debug")
button = Gtk.Button(label = "Interactive Debug")
button.connect("clicked", self._interactive_debug)
self.add(TransparencyScale())
self.add( OpenFilesButton() )
self.add( TransparencyScale() )
self.add(button)
def _interactive_debug(self, widget = None, eve = None):
event_system.emit("load_interactive_debug")
event_system.emit("load-interactive-debug")
def tggl_top_main_menubar(self):
self.hide() if self.is_visible() else self.show()

View File

@ -28,7 +28,6 @@ class LeftContainer(Gtk.Box):
...
def _subscribe_to_events(self):
# event_system.subscribe("handle_file_from_ipc", self.handle_file_from_ipc)
...
def _load_widgets(self):

View File

@ -28,7 +28,6 @@ class RightContainer(Gtk.Box):
...
def _subscribe_to_events(self):
# event_system.subscribe("handle_file_from_ipc", self.handle_file_from_ipc)
...
def _load_widgets(self):

View File

@ -1,5 +1,4 @@
# Python imports
import os
# Lib imports
import gi
@ -19,6 +18,8 @@ from .bridge_controller import BridgeController
class BaseController(IPCSignalsMixin, KeyboardSignalsMixin, BaseControllerData):
def __init__(self, args, unknownargs):
self.collect_files_dirs(args, unknownargs)
self.setup_controller_data()
self._setup_styling()
@ -29,14 +30,8 @@ class BaseController(IPCSignalsMixin, KeyboardSignalsMixin, BaseControllerData):
if args.no_plugins == "false":
self.plugins.launch_plugins()
for arg in unknownargs + [args.new_tab,]:
if os.path.isfile(arg):
message = f"FILE|{arg}"
event_system.emit("post_file_to_ipc", message)
if os.path.isdir(arg):
message = f"DIR|{arg}"
event_system.emit("post_file_to_ipc", message)
for file in settings_manager.get_starting_files():
event_system.emit("post-file-to-ipc", file)
logger.info(f"Made it past {self.__class__} loading...")
@ -50,10 +45,10 @@ class BaseController(IPCSignalsMixin, KeyboardSignalsMixin, BaseControllerData):
self.window.connect("key-release-event", self.on_global_key_release_controller)
def _subscribe_to_events(self):
event_system.subscribe("shutting_down", lambda: print("Shutting down..."))
event_system.subscribe("handle_file_from_ipc", self.handle_file_from_ipc)
event_system.subscribe("handle_dir_from_ipc", self.handle_dir_from_ipc)
event_system.subscribe("tggl_top_main_menubar", self._tggl_top_main_menubar)
event_system.subscribe("shutting-down", lambda: print("Shutting down..."))
event_system.subscribe("handle-file-from-ipc", self.handle_file_from_ipc)
event_system.subscribe("handle-dir-from-ipc", self.handle_dir_from_ipc)
event_system.subscribe("tggl-top-main-menubar", self._tggl_top_main_menubar)
def _load_controllers(self):
BridgeController()
@ -61,12 +56,12 @@ class BaseController(IPCSignalsMixin, KeyboardSignalsMixin, BaseControllerData):
def _tggl_top_main_menubar(self):
logger.debug("_tggl_top_main_menubar > stub...")
def setup_builder_and_container(self):
self.builder = Gtk.Builder()
def _load_glade_file(self):
self.builder.add_from_file(settings_manager.get_glade_file())
self.builder.expose_object("main_window", self.window)
settings_manager.set_builder(self.builder)
self.base_container = BaseContainer()
settings_manager.register_signals_to_builder([self, self.base_container])
settings_manager.register_signals_to_builder([self, self.base_container])

View File

@ -7,6 +7,7 @@ from shutil import which
# Application imports
from plugins.plugins_controller import PluginsController
from ..builder_wrapper import BuilderWrapper
@ -15,16 +16,31 @@ class BaseControllerData:
def setup_controller_data(self) -> None:
self.window = settings_manager.get_main_window()
self.builder = None
self.builder = BuilderWrapper()
self.base_container = None
self.was_midified_key = False
self.ctrl_down = False
self.shift_down = False
self.alt_down = False
self.setup_builder_and_container()
self._load_glade_file()
self.plugins = PluginsController()
def collect_files_dirs(self, args, unknownargs):
files = []
for arg in unknownargs + [args.new_tab,]:
if os.path.isdir( arg.replace("file://", "") ):
files.append( f"DIR|{arg.replace('file://', '')}" )
# NOTE: If passing line number with file split against :
if os.path.isfile( arg.replace("file://", "").split(":")[0] ):
files.append( f"FILE|{arg.replace('file://', '')}" )
if len(files) > 0:
settings_manager.set_is_starting_with_file(True)
settings_manager.set_starting_files(files)
def get_base_container(self):
return self.base_container

View File

@ -20,19 +20,19 @@ class BridgeController:
...
def _subscribe_to_events(self):
event_system.subscribe("handle_bridge_event", self.handle_bridge_event)
event_system.subscribe("handle-bridge-event", self.handle_bridge_event)
def handle_bridge_event(self, event):
match event.topic:
case "save":
event_system.emit(f"handle_file_event_{event.originator}", (event,))
event_system.emit(f"handle-file-event-{event.originator}", (event,))
case "close":
event_system.emit(f"handle_file_event_{event.originator}", (event,))
event_system.emit(f"handle-file-event-{event.originator}", (event,))
case "load_buffer":
event_system.emit(f"handle_file_event_{event.originator}", (event,))
event_system.emit(f"handle-file-event-{event.originator}", (event,))
case "load_file":
event_system.emit(f"handle_file_event_{event.originator}", (event,))
event_system.emit(f"handle-file-event-{event.originator}", (event,))
case "alert":
content = base64.b64decode( event.content.encode() ).decode("utf-8")
logger.info(f"\nMessage Topic: {event.topic}\nMessage Content: {content}")

View File

@ -0,0 +1,3 @@
"""
Widgets.Controls Module
"""

View File

@ -0,0 +1,86 @@
# Python imports
import os
# 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 OpenFilesButton(Gtk.Button):
"""docstring for OpenFilesButton."""
def __init__(self):
super(OpenFilesButton, self).__init__()
self._setup_styling()
self._setup_signals()
self._subscribe_to_events()
self._load_widgets()
def _setup_styling(self):
self.set_label("Open File(s)...")
self.set_image( Gtk.Image.new_from_icon_name("gtk-open", 4) )
self.set_always_show_image(True)
self.set_image_position(1) # Left - 0, Right = 1
self.set_hexpand(False)
def _setup_signals(self):
self.connect("button-release-event", self._open_files)
def _subscribe_to_events(self):
event_system.subscribe("open_files", self._open_files)
def _load_widgets(self):
...
def _open_files(self, widget = None, eve = None, gfile = None):
start_dir = None
_gfiles = []
if gfile and gfile.query_exists():
start_dir = gfile.get_parent()
chooser = Gtk.FileChooserDialog("Open File(s)...", None,
Gtk.FileChooserAction.OPEN,
(
Gtk.STOCK_CANCEL,
Gtk.ResponseType.CANCEL,
Gtk.STOCK_OPEN,
Gtk.ResponseType.OK
)
)
chooser.set_select_multiple(True)
try:
folder = widget.get_current_file().get_parent() if not start_dir else start_dir
chooser.set_current_folder( folder.get_path() )
except Exception as e:
...
response = chooser.run()
if not response == Gtk.ResponseType.OK:
chooser.destroy()
return _gfiles
filenames = chooser.get_filenames()
if not filenames:
chooser.destroy()
return _gfiles
for file in filenames:
path = file if os.path.isabs(file) else os.path.abspath(file)
_gfiles.append( Gio.File.new_for_path(path) )
chooser.destroy()
logger.debug(_gfiles)
return _gfiles

View File

@ -37,12 +37,12 @@ class TransparencyScale(Gtk.Scale):
def _load_widgets(self):
adjust = self.get_adjustment()
adjust.set_lower(0)
adjust.set_upper(99)
adjust.set_upper(100)
adjust.set_value(settings.theming.transparency)
adjust.set_step_increment(1.0)
def _update_transparency(self, range):
event_system.emit("remove_transparency")
event_system.emit("remove-transparency")
tp = int(range.get_value())
settings.theming.transparency = tp
event_system.emit("update_transparency")
event_system.emit("update-transparency")

View File

@ -9,7 +9,8 @@ from gi.repository import Gdk
from gi.repository import WebKit2
# Application imports
from libs.data_types import Event
from libs.settings.other.webkit_ui_settings import WebkitUISettings
from libs.dto.event import Event
@ -17,9 +18,6 @@ class WebkitUI(WebKit2.WebView):
def __init__(self):
super(WebkitUI, self).__init__()
# self.get_context().set_sandbox_enabled(False)
self._load_settings()
self._setup_styling()
self._subscribe_to_events()
self._load_view()
@ -27,10 +25,6 @@ class WebkitUI(WebKit2.WebView):
self.show_all()
if settings_manager.is_debug():
inspector = self.get_inspector()
inspector.show()
def _setup_styling(self):
self.set_vexpand(True)
@ -38,8 +32,8 @@ class WebkitUI(WebKit2.WebView):
self.set_background_color( Gdk.RGBA(0, 0, 0, 0.0) )
def _subscribe_to_events(self):
event_system.subscribe(f"ui_message", self.ui_message)
event_system.subscribe(f"ui-message", self.ui_message)
def _load_settings(self):
self.set_settings( WebkitUISettings() )
@ -54,7 +48,6 @@ class WebkitUI(WebKit2.WebView):
def _setup_content_manager(self):
content_manager = self.get_user_content_manager()
content_manager.connect("script-message-received", self._process_js_message)
content_manager.register_script_message_handler("backend")
@ -64,45 +57,14 @@ class WebkitUI(WebKit2.WebView):
try:
event = Event( **json.loads(message) )
event_system.emit("handle_bridge_event", (event,))
event_system.emit("handle-bridge-event", (event,))
except Exception as e:
logger.info(e)
def ui_message(self, mtype, message):
def ui_message(self, message, mtype):
command = f"displayMessage('{message}', '{mtype}', '3')"
self.run_javascript(command, None, None)
class WebkitUISettings(WebKit2.Settings):
def __init__(self):
super(WebkitUISettings, self).__init__()
self._set_default_settings()
# Note: Highly insecure setup but most "app" like setup I could think of.
# Audit heavily any scripts/links ran/clicked under this setup!
def _set_default_settings(self):
# self.set_enable_xss_auditor(True)
# self.set_enable_hyperlink_auditing(True)
self.set_enable_xss_auditor(False)
self.set_enable_hyperlink_auditing(False)
self.set_enable_dns_prefetching(False)
self.set_allow_file_access_from_file_urls(True)
self.set_allow_universal_access_from_file_urls(True)
# self.set_enable_java(True)
self.set_enable_page_cache(False)
self.set_enable_offline_web_application_cache(False)
self.set_enable_html5_local_storage(False)
self.set_enable_html5_database(False)
self.set_print_backgrounds(False)
self.set_enable_tabs_to_links(False)
self.set_enable_fullscreen(True)
self.set_enable_developer_extras(True)
self.set_enable_webrtc(True)
self.set_enable_webaudio(True)
self.set_enable_accelerated_2d_canvas(True)
self.set_user_agent(f"Mozilla/5.0 {app_name}")
def run_javascript(self, script, cancellable, callback):
logger.debug(script)
super().run_javascript(script, cancellable, callback)

View File

@ -1,64 +0,0 @@
# Python imports
# Lib imports
import gi
gi.require_version('Gdk', '3.0')
gi.require_version('WebKit2', '4.0')
from gi.repository import Gdk
from gi.repository import WebKit2
# Application imports
from libs.settings_manager.other.webkit_ui_settings import WebkitUISettings
class WebkitUI(WebKit2.WebView):
def __init__(self):
super(WebkitUI, self).__init__()
self._setup_styling()
self._subscribe_to_events()
self._load_view()
self._setup_content_manager()
self.show_all()
def _setup_styling(self):
self.set_vexpand(True)
self.set_hexpand(True)
self.set_background_color( Gdk.RGBA(0, 0, 0, 0.0) )
def _subscribe_to_events(self):
event_system.subscribe(f"ui_message", self.ui_message)
def _load_settings(self):
self.set_settings( WebkitUISettings() )
def _load_view(self):
path = settings_manager.get_context_path()
data = None
with open(f"{path}/index.html", "r") as f:
data = f.read()
self.load_html(content = data, base_uri = f"file://{path}/")
def _setup_content_manager(self):
content_manager = self.get_user_content_manager()
content_manager.connect("script-message-received", self._process_js_message)
content_manager.register_script_message_handler("backend")
def _process_js_message(self, user_content_manager, js_result):
js_value = js_result.get_js_value()
message = js_value.to_string()
try:
event = Event( **json.loads(message) )
event_system.emit("handle_bridge_event", (event,))
except Exception as e:
logger.info(e)
def ui_message(self, message, mtype):
command = f"displayMessage('{message}', '{mtype}', '3')"
self.run_javascript(command, None, None)

View File

@ -41,7 +41,7 @@ class Window(Gtk.ApplicationWindow):
def _setup_styling(self):
self.set_title(f"{app_name}")
self.set_title(f"{APP_NAME}")
self.set_icon_from_file( settings_manager.get_window_icon() )
self.set_gravity(5) # 5 = CENTER
self.set_position(1) # 1 = CENTER, 4 = CENTER_ALWAYS
@ -58,8 +58,8 @@ class Window(Gtk.ApplicationWindow):
GLib.unix_signal_add(GLib.PRIORITY_DEFAULT, signal.SIGINT, self._tear_down)
def _subscribe_to_events(self):
event_system.subscribe("tear_down", self._tear_down)
event_system.subscribe("load_interactive_debug", self._load_interactive_debug)
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():
@ -90,7 +90,7 @@ class Window(Gtk.ApplicationWindow):
if visual 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)
# self.connect("draw", self._area_draw)
# bind css file
cssProvider = Gtk.CssProvider()
@ -107,17 +107,17 @@ class Window(Gtk.ApplicationWindow):
def _on_focus_in_event(self, widget, event):
event_system.emit("pause_dnd_signals")
event_system.emit("pause-dnd-signals")
def _on_focus_out_event(self, widget, event):
event_system.emit("listen_dnd_signals")
event_system.emit("listen-dnd-signals")
def _load_interactive_debug(self):
self.set_interactive_debugging(True)
def _tear_down(self, widget = None, eve = None):
event_system.emit("shutting_down")
event_system.emit("shutting-down")
size = self.get_size()
pos = self.get_position()

6
src/libs/db/__init__.py Normal file
View File

@ -0,0 +1,6 @@
"""
DB module
"""
from .models import User
from .db import DB

View File

@ -18,7 +18,7 @@ def debug_signal_handler(signal, frame):
rpdb2.start_embedded_debugger("foobar", True, True)
rpdb2.setbreak(depth=1)
return
except StandardError:
except Exception:
...
try:
@ -26,7 +26,7 @@ def debug_signal_handler(signal, frame):
logger.debug("\n\nStarting embedded rconsole debugger...\n\n")
rconsole.spawn_server()
return
except StandardError as ex:
except Exception as ex:
...
try:
@ -34,7 +34,15 @@ def debug_signal_handler(signal, frame):
logger.debug("\n\nStarting PuDB debugger...\n\n")
set_trace(paused = True)
return
except StandardError as ex:
except Exception as ex:
...
try:
import ipdb
logger.debug("\n\nStarting IPDB debugger...\n\n")
ipdb.set_trace()
return
except Exception as ex:
...
try:
@ -42,11 +50,11 @@ def debug_signal_handler(signal, frame):
logger.debug("\n\nStarting embedded PDB debugger...\n\n")
pdb.Pdb(skip=['gi.*']).set_trace()
return
except StandardError as ex:
except Exception as ex:
...
try:
import code
code.interact()
except StandardError as ex:
logger.debug(f"{ex}, returning to normal program flow...")
except Exception as ex:
logger.debug(f"{ex}, returning to normal program flow...")

View File

@ -13,17 +13,17 @@ from .singleton import Singleton
class IPCServer(Singleton):
""" Create a listener so that other {app_name} instances send requests back to existing instance. """
""" Create a listener so that other {APP_NAME} instances send requests back to existing instance. """
def __init__(self, ipc_address: str = '127.0.0.1', conn_type: str = "socket"):
self.is_ipc_alive = False
self._ipc_port = 4848
self._ipc_address = ipc_address
self._conn_type = conn_type
self._ipc_authkey = b'' + bytes(f'{app_name}-ipc', 'utf-8')
self._ipc_authkey = b'' + bytes(f'{APP_NAME}-ipc', 'utf-8')
self._ipc_timeout = 15.0
if conn_type == "socket":
self._ipc_address = f'/tmp/{app_name}-ipc.sock'
self._ipc_address = f'/tmp/{APP_NAME}-ipc.sock'
elif conn_type == "full_network":
self._ipc_address = '0.0.0.0'
elif conn_type == "full_network_unsecured":
@ -35,7 +35,7 @@ class IPCServer(Singleton):
self._subscribe_to_events()
def _subscribe_to_events(self):
event_system.subscribe("post_file_to_ipc", self.send_ipc_message)
event_system.subscribe("post-file-to-ipc", self.send_ipc_message)
def create_ipc_listener(self) -> None:
@ -74,12 +74,12 @@ class IPCServer(Singleton):
if "FILE|" in msg:
file = msg.split("FILE|")[1].strip()
if file:
event_system.emit("handle_file_from_ipc", file)
event_system.emit("handle-file-from-ipc", file)
if "DIR|" in msg:
file = msg.split("DIR|")[1].strip()
if file:
event_system.emit("handle_dir_from_ipc", file)
event_system.emit("handle-dir-from-ipc", file)
conn.close()
break

View File

@ -67,4 +67,4 @@ class DnDMixin:
files.append(gfile)
event_system.emit('set_pre_drop_dnd', (files,))
event_system.emit('set-pre-drop-dnd', (files,))

View File

@ -68,11 +68,11 @@ class KeyboardSignalsMixin:
if mapping:
self.handle_mapped_key_event(mapping)
else:
self.handle_as_key_event_scope(mapping)
self.handle_as_key_event_scope(keyname)
def handle_mapped_key_event(self, mapping):
try:
self.handle_as_controller_scope()
self.handle_as_controller_scope(mapping)
except Exception:
self.handle_as_plugin_scope(mapping)
@ -86,13 +86,11 @@ class KeyboardSignalsMixin:
sender = ""
eve_type = mapping
self.handle_as_key_event_system(sender, eve_type)
def handle_as_key_event_scope(self, mapping):
logger.debug(f"on_global_key_release_controller > key > {keyname}")
self.handle_key_event_system(sender, eve_type)
def handle_as_key_event_scope(self, keyname):
if self.ctrl_down and not keyname in ["1", "kp_1", "2", "kp_2", "3", "kp_3", "4", "kp_4"]:
self.handle_key_event_system(None, mapping)
self.handle_key_event_system(None, keyname)
def handle_key_event_system(self, sender, eve_type):
event_system.emit(eve_type)

View File

@ -24,8 +24,8 @@ class SettingsManager(StartCheckMixin, Singleton):
def __init__(self):
self._SCRIPT_PTH = path.dirname(path.realpath(__file__))
self._USER_HOME = path.expanduser('~')
self._HOME_CONFIG_PATH = f"{self._USER_HOME}/.config/{app_name.lower()}"
self._USR_PATH = f"/usr/share/{app_name.lower()}"
self._HOME_CONFIG_PATH = f"{self._USER_HOME}/.config/{APP_NAME.lower()}"
self._USR_PATH = f"/usr/share/{APP_NAME.lower()}"
self._USR_CONFIG_FILE = f"{self._USR_PATH}/settings.json"
self._CONTEXT_PATH = f"{self._HOME_CONFIG_PATH}/context_path"
@ -35,10 +35,10 @@ class SettingsManager(StartCheckMixin, Singleton):
self._GLADE_FILE = f"{self._HOME_CONFIG_PATH}/Main_Window.glade"
self._CSS_FILE = f"{self._HOME_CONFIG_PATH}/stylesheet.css"
self._KEY_BINDINGS_FILE = f"{self._HOME_CONFIG_PATH}/key-bindings.json"
self._PID_FILE = f"{self._HOME_CONFIG_PATH}/{app_name.lower()}.pid"
self._PID_FILE = f"{self._HOME_CONFIG_PATH}/{APP_NAME.lower()}.pid"
self._UI_WIDEGTS_PATH = f"{self._HOME_CONFIG_PATH}/ui_widgets"
self._CONTEXT_MENU = f"{self._HOME_CONFIG_PATH}/contexct_menu.json"
self._WINDOW_ICON = f"{self._DEFAULT_ICONS}/{app_name.lower()}.png"
self._WINDOW_ICON = f"{self._DEFAULT_ICONS}/{APP_NAME.lower()}.png"
# self._USR_CONFIG_FILE = f"{self._USR_PATH}/settings.json"
# self._PLUGINS_PATH = f"plugins"
@ -46,8 +46,8 @@ class SettingsManager(StartCheckMixin, Singleton):
# self._GLADE_FILE = f"Main_Window.glade"
# self._CSS_FILE = f"stylesheet.css"
# self._KEY_BINDINGS_FILE = f"key-bindings.json"
# self._PID_FILE = f"{app_name.lower()}.pid"
# self._WINDOW_ICON = f"{app_name.lower()}.png"
# self._PID_FILE = f"{APP_NAME.lower()}.pid"
# self._WINDOW_ICON = f"{APP_NAME.lower()}.png"
# self._UI_WIDEGTS_PATH = f"ui_widgets"
# self._CONTEXT_MENU = f"contexct_menu.json"
# self._DEFAULT_ICONS = f"icons"
@ -79,7 +79,7 @@ class SettingsManager(StartCheckMixin, Singleton):
if not path.exists(self._CSS_FILE):
raise MissingConfigError("Unable to find the application Stylesheet file.")
if not path.exists(self._WINDOW_ICON):
self._WINDOW_ICON = f"{self._USR_PATH}/icons/{app_name.lower()}.png"
self._WINDOW_ICON = f"{self._USR_PATH}/icons/{APP_NAME.lower()}.png"
if not path.exists(self._WINDOW_ICON):
raise MissingConfigError("Unable to find the application icon.")
if not path.exists(self._UI_WIDEGTS_PATH):
@ -110,6 +110,8 @@ class SettingsManager(StartCheckMixin, Singleton):
self._trace_debug = False
self._debug = False
self._dirty_start = False
self._passed_in_file = False
self._starting_files = []
def register_signals_to_builder(self, classes=None):
@ -128,7 +130,6 @@ class SettingsManager(StartCheckMixin, Singleton):
def set_main_window(self, window): self._main_window = window
def set_builder(self, builder) -> any: self._builder = builder
def get_monitor_data(self) -> list:
screen = self._main_window.get_screen()
monitors = []
@ -152,21 +153,24 @@ class SettingsManager(StartCheckMixin, Singleton):
def get_home_config_path(self) -> str: return self._HOME_CONFIG_PATH
def get_window_icon(self) -> str: return self._WINDOW_ICON
def get_home_path(self) -> str: return self._USER_HOME
def get_starting_files(self) -> []: return self._starting_files
def is_trace_debug(self) -> str: return self._trace_debug
def is_debug(self) -> str: return self._debug
def is_starting_with_file(self) -> bool: return self._passed_in_file
def call_method(self, target_class = None, _method_name = None, data = None):
method_name = str(_method_name)
method = getattr(target_class, method_name, lambda data: f"No valid key passed...\nkey={method_name}\nargs={data}")
return method(data) if data else method()
def set_main_window_x(self, x = 0): self.settings.config.main_window_x = x
def set_main_window_y(self, y = 0): self.settings.config.main_window_y = y
def set_main_window_width(self, width = 800): self.settings.config.main_window_width = width
def set_main_window_height(self, height = 600): self.settings.config.main_window_height = height
def set_main_window_x(self, x = 0): self.settings.config.main_window_x = x
def set_main_window_y(self, y = 0): self.settings.config.main_window_y = y
def set_main_window_width(self, width = 800): self.settings.config.main_window_width = width
def set_main_window_height(self, height = 600): self.settings.config.main_window_height = height
def set_main_window_min_width(self, width = 720): self.settings.config.main_window_min_width = width
def set_main_window_min_height(self, height = 480): self.settings.config.main_window_min_height = height
def set_starting_files(self, files: []) -> None: self._starting_files = files
def set_trace_debug(self, trace_debug):
self._trace_debug = trace_debug
@ -174,6 +178,8 @@ class SettingsManager(StartCheckMixin, Singleton):
def set_debug(self, debug):
self._debug = debug
def set_is_starting_with_file(self, is_passed_in_file: False):
self._passed_in_file = is_passed_in_file
def load_settings(self):
if not path.exists(self._CONFIG_FILE):

View File

@ -39,4 +39,4 @@ class WebkitUISettings(WebKit2.Settings):
self.set_enable_webaudio(True)
self.set_enable_accelerated_2d_canvas(True)
self.set_user_agent(f"{app_name}")
self.set_user_agent(f"{APP_NAME}")

View File

@ -41,7 +41,7 @@ class StartCheckMixin:
try:
os.kill(pid, 0)
except OSError:
print(f"{app_name} PID file exists but PID is irrelevant; starting dirty...")
print(f"{APP_NAME} PID file exists but PID is irrelevant; starting dirty...")
self._dirty_start = True
return False
@ -53,7 +53,7 @@ class StartCheckMixin:
self._print_pid(pid)
def _print_pid(self, pid):
print(f"{app_name} PID: {pid}")
print(f"{APP_NAME} PID: {pid}")
def _clean_pid(self):
os.unlink(self._PID_FILE)

View File

@ -1,23 +1,24 @@
{
"keybindings": {
"help" : "F1",
"rename_files" : ["F2", "<Control>e"],
"open_terminal" : "F4",
"refresh_tab" : ["F5", "<Control>r"],
"delete_files" : "Delete",
"tggl_top_main_menubar" : "Alt_L",
"trash_files" : "<Shift><Control>t",
"tear_down" : "<Control>q",
"go_up" : "<Control>Up",
"go_home" : "<Control>slash",
"grab_focus_path_entry" : "<Control>l",
"open_files" : "<Control>o",
"show_hide_hidden_files" : "<Control>h",
"keyboard_create_tab" : "<Control>t",
"keyboard_close_tab" : "<Control>w",
"keyboard_copy_files" : "<Control>c",
"keyboard_cut_files" : "<Control>x",
"paste_files" : "<Control>v",
"show_new_file_menu" : "<Control>n"
"rename-files" : ["F2", "<Control>e"],
"open-terminal" : "F4",
"refresh-tab" : ["F5", "<Control>r"],
"delete-files" : "Delete",
"tggl-top-main-menubar" : "Alt_L",
"tggl-top-main-menubar" : "<Control>0",
"trash-files" : "<Shift><Control>t",
"tear-down" : "<Control>q",
"go-up" : "<Control>Up",
"go-home" : "<Control>slash",
"grab-focus-path-entry" : "<Control>l",
"open-files" : "<Control>o",
"show-hide-hidden-files" : "<Control>h",
"keyboard-create-tab" : "<Control>t",
"keyboard-close-tab" : "<Control>w",
"keyboard-copy-files" : "<Control>c",
"keyboard-cut-files" : "<Control>x",
"paste-files" : "<Control>v",
"show-new-file-menu" : "<Control>n"
}
}

View File

@ -1,3 +1,16 @@
/* ---- Make most desired things base transparent ---- */
popover,
popover > *,
scrolledwindow > *,
textview > *,
.main-window > .base-container > .body-container,
.main-window > .base-container > .body-container > .left-container,
.main-window > .base-container > .body-container > .center-container,
.main-window > .base-container > .body-container > .right-container {
background: rgba(0, 0, 0, 0.0);
color: rgba(255, 255, 255, 1);
}
.base-container {
margin: 10px;
}
@ -128,3 +141,4 @@ XfdesktopIconView.view:active {
.mw_transparency_97 { background: rgba(39, 43, 52, 0.97); }
.mw_transparency_98 { background: rgba(39, 43, 52, 0.98); }
.mw_transparency_99 { background: rgba(39, 43, 52, 0.99); }
.mw_transparency_100 { background: rgba(39, 43, 52, 1.00); }