Compare commits
6 Commits
62debf9ece
...
cca007db76
Author | SHA1 | Date | |
---|---|---|---|
cca007db76 | |||
33c0827ca2 | |||
f2b33066af | |||
fafc1a985f | |||
e2e9dc8c1f | |||
25b6b5305b |
@ -9,6 +9,7 @@ A template project for Python with Gtk applications.
|
|||||||
* sqlmodel (SQL databases and is powered by Pydantic and SQLAlchemy)
|
* sqlmodel (SQL databases and is powered by Pydantic and SQLAlchemy)
|
||||||
|
|
||||||
### Note
|
### Note
|
||||||
|
* pyrightconfig.json can prompt IDEs that use pyright lsp on where imports are located- look at venvPath and venv. "venvPath" is parent path of "venv" where "venv" is just the name of the folder under the parent path that is the python created venv.
|
||||||
* Move respetive sub folder content under user_config to the same places in Linux. Though, user/share/<app name> can go to ~/.config folder if prefered.
|
* Move respetive sub folder content under user_config to the same places in Linux. Though, user/share/<app name> can go to ~/.config folder if prefered.
|
||||||
* In additiion, place the plugins folder in the same app folder you moved to /usr/share/<app name> or ~/.config/<app name> .
|
* In additiion, place the plugins folder in the same app folder you moved to /usr/share/<app name> or ~/.config/<app name> .
|
||||||
There are a "\<change_me\>" strings and files that need to be set according to your app's name located at:
|
There are a "\<change_me\>" strings and files that need to be set according to your app's name located at:
|
||||||
|
13
pyrightconfig.json
Normal file
13
pyrightconfig.json
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"reportUndefinedVariable": false,
|
||||||
|
"reportUnusedVariable": false,
|
||||||
|
"reportUnusedImport": true,
|
||||||
|
"reportDuplicateImport": true,
|
||||||
|
"executionEnvironments": [
|
||||||
|
{
|
||||||
|
"root": "./src/versions/solarfm-0.0.1/solarfm"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"venvPath": ".",
|
||||||
|
"venv": ".venv"
|
||||||
|
}
|
@ -46,9 +46,11 @@ builtins.settings_manager = SettingsManager()
|
|||||||
settings_manager.load_settings()
|
settings_manager.load_settings()
|
||||||
|
|
||||||
builtins.settings = settings_manager.settings
|
builtins.settings = settings_manager.settings
|
||||||
builtins.logger = Logger(settings_manager.get_home_config_path(), \
|
builtins.logger = Logger(
|
||||||
_ch_log_lvl=settings.debugging.ch_log_lvl, \
|
settings_manager.get_home_config_path(), \
|
||||||
_fh_log_lvl=settings.debugging.fh_log_lvl).get_logger()
|
_ch_log_lvl = settings.debugging.ch_log_lvl, \
|
||||||
|
_fh_log_lvl = settings.debugging.fh_log_lvl
|
||||||
|
).get_logger()
|
||||||
|
|
||||||
builtins.threaded = threaded_wrapper
|
builtins.threaded = threaded_wrapper
|
||||||
builtins.daemon_threaded = daemon_threaded_wrapper
|
builtins.daemon_threaded = daemon_threaded_wrapper
|
||||||
@ -60,6 +62,6 @@ def custom_except_hook(exc_type, exc_value, exc_traceback):
|
|||||||
sys.__excepthook__(exc_type, exc_value, exc_traceback)
|
sys.__excepthook__(exc_type, exc_value, exc_traceback)
|
||||||
return
|
return
|
||||||
|
|
||||||
logger.error("Uncaught exception", exc_info=(exc_type, exc_value, exc_traceback))
|
logger.error("Uncaught exception", exc_info = (exc_type, exc_value, exc_traceback))
|
||||||
|
|
||||||
sys.excepthook = custom_except_hook
|
sys.excepthook = custom_except_hook
|
@ -1,3 +1,3 @@
|
|||||||
"""
|
"""
|
||||||
Start of package.
|
Src Package.
|
||||||
"""
|
"""
|
@ -17,8 +17,9 @@ from app import Application
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
def main(args, unknownargs):
|
def main():
|
||||||
setproctitle(f'{APP_NAME}')
|
setproctitle(f'{APP_NAME}')
|
||||||
|
settings_manager.set_start_load_time()
|
||||||
|
|
||||||
if args.debug == "true":
|
if args.debug == "true":
|
||||||
settings_manager.set_debug(True)
|
settings_manager.set_debug(True)
|
||||||
@ -27,7 +28,7 @@ def main(args, unknownargs):
|
|||||||
settings_manager.set_trace_debug(True)
|
settings_manager.set_trace_debug(True)
|
||||||
|
|
||||||
settings_manager.do_dirty_start_check()
|
settings_manager.do_dirty_start_check()
|
||||||
Application(args, unknownargs)
|
Application()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -36,19 +37,20 @@ if __name__ == "__main__":
|
|||||||
|
|
||||||
parser = argparse.ArgumentParser()
|
parser = argparse.ArgumentParser()
|
||||||
# Add long and short arguments
|
# Add long and short arguments
|
||||||
parser.add_argument("--debug", "-d", default="false", help="Do extra console messaging.")
|
parser.add_argument("--debug", "-d", default = "false", help = "Do extra console messaging.")
|
||||||
parser.add_argument("--trace-debug", "-td", default="false", help="Disable saves, ignore IPC lock, do extra console messaging.")
|
parser.add_argument("--trace-debug", "-td", default = "false", help = "Disable saves, ignore IPC lock, do extra console messaging.")
|
||||||
parser.add_argument("--no-plugins", "-np", default="false", help="Do not load plugins.")
|
parser.add_argument("--no-plugins", "-np", default = "false", help = "Do not load plugins.")
|
||||||
|
|
||||||
parser.add_argument("--new-tab", "-nt", default="false", help="Opens a 'New Tab' if a handler is set for it.")
|
parser.add_argument("--new-tab", "-nt", default = "false", help = "Opens a 'New Tab' if a handler is set for it.")
|
||||||
parser.add_argument("--file", "-f", default="default", help="JUST SOME FILE ARG.")
|
parser.add_argument("--file", "-f", default = "default", help = "JUST SOME FILE ARG.")
|
||||||
|
|
||||||
# Read arguments (If any...)
|
# Read arguments (If any...)
|
||||||
args, unknownargs = parser.parse_known_args()
|
args, unknownargs = parser.parse_known_args()
|
||||||
|
settings_manager.set_starting_args( args, unknownargs )
|
||||||
|
|
||||||
try:
|
try:
|
||||||
faulthandler.enable() # For better debug info
|
faulthandler.enable() # For better debug info
|
||||||
main(args, unknownargs)
|
main()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
quit()
|
quit()
|
14
src/app.py
14
src/app.py
@ -19,20 +19,22 @@ class AppLaunchException(Exception):
|
|||||||
class Application:
|
class Application:
|
||||||
""" docstring for Application. """
|
""" docstring for Application. """
|
||||||
|
|
||||||
def __init__(self, args, unknownargs):
|
def __init__(self):
|
||||||
super(Application, self).__init__()
|
super(Application, self).__init__()
|
||||||
|
|
||||||
if not settings_manager.is_trace_debug():
|
if not settings_manager.is_trace_debug():
|
||||||
self.load_ipc(args, unknownargs)
|
self.load_ipc()
|
||||||
|
|
||||||
self.setup_debug_hook()
|
self.setup_debug_hook()
|
||||||
Window(args, unknownargs).main()
|
Window().main()
|
||||||
|
|
||||||
|
|
||||||
def load_ipc(self, args, unknownargs):
|
def load_ipc(self):
|
||||||
ipc_server = IPCServer()
|
args, \
|
||||||
|
unknownargs = settings_manager.get_starting_args()
|
||||||
|
ipc_server = IPCServer()
|
||||||
|
|
||||||
self.ipc_realization_check(ipc_server)
|
self.ipc_realization_check(ipc_server)
|
||||||
|
|
||||||
if not ipc_server.is_ipc_alive:
|
if not ipc_server.is_ipc_alive:
|
||||||
for arg in unknownargs + [args.new_tab,]:
|
for arg in unknownargs + [args.new_tab,]:
|
||||||
if os.path.isfile(arg):
|
if os.path.isfile(arg):
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
"""
|
"""
|
||||||
Core Module
|
Core Package
|
||||||
"""
|
"""
|
@ -1,3 +1,3 @@
|
|||||||
"""
|
"""
|
||||||
Containers Module
|
Containers Package
|
||||||
"""
|
"""
|
@ -22,7 +22,7 @@ class BaseContainer(Gtk.Box):
|
|||||||
self._subscribe_to_events()
|
self._subscribe_to_events()
|
||||||
self._load_widgets()
|
self._load_widgets()
|
||||||
|
|
||||||
self.show_all()
|
self.show()
|
||||||
|
|
||||||
|
|
||||||
def _setup_styling(self):
|
def _setup_styling(self):
|
||||||
|
@ -23,7 +23,7 @@ class BodyContainer(Gtk.Box):
|
|||||||
self._subscribe_to_events()
|
self._subscribe_to_events()
|
||||||
self._load_widgets()
|
self._load_widgets()
|
||||||
|
|
||||||
self.show_all()
|
self.show()
|
||||||
|
|
||||||
|
|
||||||
def _setup_styling(self):
|
def _setup_styling(self):
|
||||||
|
@ -21,6 +21,8 @@ class CenterContainer(Gtk.Box):
|
|||||||
self._subscribe_to_events()
|
self._subscribe_to_events()
|
||||||
self._load_widgets()
|
self._load_widgets()
|
||||||
|
|
||||||
|
self.show()
|
||||||
|
|
||||||
|
|
||||||
def _setup_styling(self):
|
def _setup_styling(self):
|
||||||
self.set_orientation(Gtk.Orientation.VERTICAL)
|
self.set_orientation(Gtk.Orientation.VERTICAL)
|
||||||
@ -39,6 +41,9 @@ class CenterContainer(Gtk.Box):
|
|||||||
|
|
||||||
button.connect("clicked", self._hello_world)
|
button.connect("clicked", self._hello_world)
|
||||||
|
|
||||||
|
button.show()
|
||||||
|
glade_box.show()
|
||||||
|
|
||||||
self.add(button)
|
self.add(button)
|
||||||
self.add(glade_box)
|
self.add(glade_box)
|
||||||
self.add( WebkitUI() )
|
self.add( WebkitUI() )
|
||||||
|
@ -48,4 +48,4 @@ class HeaderContainer(Gtk.Box):
|
|||||||
event_system.emit("load-interactive-debug")
|
event_system.emit("load-interactive-debug")
|
||||||
|
|
||||||
def tggl_top_main_menubar(self):
|
def tggl_top_main_menubar(self):
|
||||||
self.hide() if self.is_visible() else self.show()
|
self.hide() if self.is_visible() else self.show_all()
|
@ -18,6 +18,8 @@ class LeftContainer(Gtk.Box):
|
|||||||
self._subscribe_to_events()
|
self._subscribe_to_events()
|
||||||
self._load_widgets()
|
self._load_widgets()
|
||||||
|
|
||||||
|
self.show()
|
||||||
|
|
||||||
|
|
||||||
def _setup_styling(self):
|
def _setup_styling(self):
|
||||||
self.set_orientation(Gtk.Orientation.VERTICAL)
|
self.set_orientation(Gtk.Orientation.VERTICAL)
|
||||||
|
@ -6,6 +6,7 @@ gi.require_version('Gtk', '3.0')
|
|||||||
from gi.repository import Gtk
|
from gi.repository import Gtk
|
||||||
|
|
||||||
# Application imports
|
# Application imports
|
||||||
|
from ..widgets.vte_widget import VteWidget
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -18,6 +19,8 @@ class RightContainer(Gtk.Box):
|
|||||||
self._subscribe_to_events()
|
self._subscribe_to_events()
|
||||||
self._load_widgets()
|
self._load_widgets()
|
||||||
|
|
||||||
|
self.show()
|
||||||
|
|
||||||
|
|
||||||
def _setup_styling(self):
|
def _setup_styling(self):
|
||||||
self.set_orientation(Gtk.Orientation.VERTICAL)
|
self.set_orientation(Gtk.Orientation.VERTICAL)
|
||||||
@ -31,4 +34,5 @@ class RightContainer(Gtk.Box):
|
|||||||
...
|
...
|
||||||
|
|
||||||
def _load_widgets(self):
|
def _load_widgets(self):
|
||||||
...
|
vte_widget = VteWidget()
|
||||||
|
self.add( vte_widget )
|
@ -1,3 +1,3 @@
|
|||||||
"""
|
"""
|
||||||
Controllers Module
|
Controllers Package
|
||||||
"""
|
"""
|
@ -17,26 +17,18 @@ from .bridge_controller import BridgeController
|
|||||||
|
|
||||||
|
|
||||||
class BaseController(IPCSignalsMixin, KeyboardSignalsMixin, BaseControllerData):
|
class BaseController(IPCSignalsMixin, KeyboardSignalsMixin, BaseControllerData):
|
||||||
def __init__(self, args, unknownargs):
|
def __init__(self):
|
||||||
self.collect_files_dirs(args, unknownargs)
|
|
||||||
|
|
||||||
self.setup_controller_data()
|
|
||||||
|
|
||||||
|
self._setup_controller_data()
|
||||||
self._setup_styling()
|
self._setup_styling()
|
||||||
self._setup_signals()
|
self._setup_signals()
|
||||||
self._subscribe_to_events()
|
self._subscribe_to_events()
|
||||||
self._load_controllers()
|
self._load_controllers()
|
||||||
|
self._load_plugins_and_files()
|
||||||
if args.no_plugins == "false":
|
|
||||||
self.plugins_controller.pre_launch_plugins()
|
|
||||||
|
|
||||||
if args.no_plugins == "false":
|
|
||||||
self.plugins_controller.post_launch_plugins()
|
|
||||||
|
|
||||||
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...")
|
logger.info(f"Made it past {self.__class__} loading...")
|
||||||
|
settings_manager.set_end_load_time()
|
||||||
|
settings_manager.log_load_time()
|
||||||
|
|
||||||
|
|
||||||
def _setup_styling(self):
|
def _setup_styling(self):
|
||||||
@ -56,15 +48,25 @@ class BaseController(IPCSignalsMixin, KeyboardSignalsMixin, BaseControllerData):
|
|||||||
def _load_controllers(self):
|
def _load_controllers(self):
|
||||||
BridgeController()
|
BridgeController()
|
||||||
|
|
||||||
|
def _load_plugins_and_files(self):
|
||||||
|
args, unknownargs = settings_manager.get_starting_args()
|
||||||
|
if args.no_plugins == "false":
|
||||||
|
self.plugins_controller.pre_launch_plugins()
|
||||||
|
|
||||||
|
if args.no_plugins == "false":
|
||||||
|
self.plugins_controller.post_launch_plugins()
|
||||||
|
|
||||||
|
for file in settings_manager.get_starting_files():
|
||||||
|
event_system.emit("post-file-to-ipc", file)
|
||||||
|
|
||||||
def _tggl_top_main_menubar(self):
|
def _tggl_top_main_menubar(self):
|
||||||
logger.debug("_tggl_top_main_menubar > stub...")
|
logger.debug("_tggl_top_main_menubar > stub...")
|
||||||
|
|
||||||
def _load_glade_file(self):
|
def _load_glade_file(self):
|
||||||
self.builder.add_from_file(settings_manager.get_glade_file())
|
self.builder.add_from_file( settings_manager.get_glade_file() )
|
||||||
self.builder.expose_object("main_window", self.window)
|
self.builder.expose_object("main_window", self.window)
|
||||||
|
|
||||||
settings_manager.set_builder(self.builder)
|
settings_manager.set_builder(self.builder)
|
||||||
self.base_container = BaseContainer()
|
self.base_container = BaseContainer()
|
||||||
|
|
||||||
settings_manager.register_signals_to_builder([self, self.base_container])
|
settings_manager.register_signals_to_builder([self, self.base_container])
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@ from ..builder_wrapper import BuilderWrapper
|
|||||||
class BaseControllerData:
|
class BaseControllerData:
|
||||||
''' BaseControllerData contains most of the state of the app at ay given time. It also has some support methods. '''
|
''' BaseControllerData contains most of the state of the app at ay given time. It also has some support methods. '''
|
||||||
|
|
||||||
def setup_controller_data(self) -> None:
|
def _setup_controller_data(self) -> None:
|
||||||
self.window = settings_manager.get_main_window()
|
self.window = settings_manager.get_main_window()
|
||||||
self.builder = BuilderWrapper()
|
self.builder = BuilderWrapper()
|
||||||
self.plugins_controller = PluginsController()
|
self.plugins_controller = PluginsController()
|
||||||
@ -25,11 +25,15 @@ class BaseControllerData:
|
|||||||
self.shift_down = False
|
self.shift_down = False
|
||||||
self.alt_down = False
|
self.alt_down = False
|
||||||
|
|
||||||
|
self._collect_files_dirs()
|
||||||
self._load_glade_file()
|
self._load_glade_file()
|
||||||
|
|
||||||
|
|
||||||
def collect_files_dirs(self, args, unknownargs):
|
def _collect_files_dirs(self):
|
||||||
files = []
|
args, \
|
||||||
|
unknownargs = settings_manager.get_starting_args()
|
||||||
|
files = []
|
||||||
|
|
||||||
for arg in unknownargs + [args.new_tab,]:
|
for arg in unknownargs + [args.new_tab,]:
|
||||||
if os.path.isdir( arg.replace("file://", "") ):
|
if os.path.isdir( arg.replace("file://", "") ):
|
||||||
files.append( f"DIR|{arg.replace('file://', '')}" )
|
files.append( f"DIR|{arg.replace('file://', '')}" )
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
"""
|
"""
|
||||||
Widgets Module
|
Widgets Package
|
||||||
"""
|
"""
|
@ -1,3 +1,3 @@
|
|||||||
"""
|
"""
|
||||||
Widgets.Controls Module
|
Widgets.Controls Package
|
||||||
"""
|
"""
|
125
src/core/widgets/vte_widget.py
Normal file
125
src/core/widgets/vte_widget.py
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
# Python imports
|
||||||
|
import os
|
||||||
|
|
||||||
|
# Lib imports
|
||||||
|
import gi
|
||||||
|
gi.require_version('Gtk', '3.0')
|
||||||
|
gi.require_version('Gdk', '3.0')
|
||||||
|
gi.require_version('Vte', '2.91')
|
||||||
|
from gi.repository import Gtk
|
||||||
|
from gi.repository import Gdk
|
||||||
|
from gi.repository import GLib
|
||||||
|
from gi.repository import Vte
|
||||||
|
|
||||||
|
# Application imports
|
||||||
|
from libs.dto.event import Event
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class VteWidgetException(Exception):
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class VteWidget(Vte.Terminal):
|
||||||
|
"""
|
||||||
|
https://stackoverflow.com/questions/60454326/how-to-implement-a-linux-terminal-in-a-pygtk-app-like-vscode-and-pycharm-has
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
super(VteWidget, self).__init__()
|
||||||
|
|
||||||
|
self.cd_cmd_prefix = ("cd".encode(), "cd ".encode())
|
||||||
|
self.dont_process = False
|
||||||
|
|
||||||
|
self._setup_styling()
|
||||||
|
self._setup_signals()
|
||||||
|
self._subscribe_to_events()
|
||||||
|
self._load_widgets()
|
||||||
|
self._do_session_spawn()
|
||||||
|
|
||||||
|
self.show()
|
||||||
|
|
||||||
|
|
||||||
|
def _setup_styling(self):
|
||||||
|
ctx = self.get_style_context()
|
||||||
|
ctx.add_class("vte-widget")
|
||||||
|
|
||||||
|
self.set_clear_background(False)
|
||||||
|
self.set_enable_sixel(True)
|
||||||
|
self.set_cursor_shape( Vte.CursorShape.IBEAM )
|
||||||
|
|
||||||
|
def _setup_signals(self):
|
||||||
|
self.connect("commit", self._commit)
|
||||||
|
|
||||||
|
def _subscribe_to_events(self):
|
||||||
|
event_system.subscribe("update_term_path", self.update_term_path)
|
||||||
|
|
||||||
|
def _load_widgets(self):
|
||||||
|
...
|
||||||
|
|
||||||
|
def _do_session_spawn(self):
|
||||||
|
self.spawn_sync(
|
||||||
|
Vte.PtyFlags.DEFAULT,
|
||||||
|
settings_manager.get_home_path(),
|
||||||
|
["/bin/bash"],
|
||||||
|
[],
|
||||||
|
GLib.SpawnFlags.DEFAULT,
|
||||||
|
None, None,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Note: '-->:' is used as a delimiter to split on to get command actual.
|
||||||
|
# !!! DO NOT REMOVE UNLESS CODE UPDATED ACCORDINGLY !!!
|
||||||
|
startup_cmds = [
|
||||||
|
"env -i /bin/bash --noprofile --norc\n",
|
||||||
|
"export TERM='xterm-256color'\n",
|
||||||
|
"export LC_ALL=C\n",
|
||||||
|
"export XDG_RUNTIME_DIR='/run/user/1000'\n",
|
||||||
|
"export DISPLAY=:0\n",
|
||||||
|
f"export XAUTHORITY='{settings_manager.get_home_path()}/.Xauthority'\n",
|
||||||
|
f"\nexport HOME='{settings_manager.get_home_path()}'\n",
|
||||||
|
"export PS1='\\h@\\u \\W -->: '\n",
|
||||||
|
"clear\n"
|
||||||
|
]
|
||||||
|
|
||||||
|
for i in startup_cmds:
|
||||||
|
self.run_command(i)
|
||||||
|
|
||||||
|
def _commit(self, terminal, text, size):
|
||||||
|
if self.dont_process:
|
||||||
|
self.dont_process = False
|
||||||
|
return
|
||||||
|
|
||||||
|
if not text.encode() == "\r".encode(): return
|
||||||
|
|
||||||
|
text, attributes = self.get_text()
|
||||||
|
lines = text.strip().splitlines()
|
||||||
|
command_ran = None
|
||||||
|
|
||||||
|
try:
|
||||||
|
command_ran = lines[-1].split("-->:")[1].strip()
|
||||||
|
except VteWidgetException as e:
|
||||||
|
logger.debud(e)
|
||||||
|
return
|
||||||
|
|
||||||
|
if not command_ran[0:3].encode() in self.cd_cmd_prefix:
|
||||||
|
return
|
||||||
|
|
||||||
|
target_path = command_ran.split( command_ran[0:3] )[1]
|
||||||
|
if target_path in (".", "./"): return
|
||||||
|
|
||||||
|
if not target_path:
|
||||||
|
target_path = settings_manager.get_home_path()
|
||||||
|
|
||||||
|
event = Event("pty_path_updated", "", target_path)
|
||||||
|
event_system.emit("handle_bridge_event", (event,))
|
||||||
|
|
||||||
|
def update_term_path(self, fpath):
|
||||||
|
self.dont_process = True
|
||||||
|
|
||||||
|
cmds = [f"cd '{fpath}'\n", "clear\n"]
|
||||||
|
for i in cmds:
|
||||||
|
self.run_command(i)
|
||||||
|
|
||||||
|
def run_command(self, cmd):
|
||||||
|
self.feed_child_binary(bytes(cmd, 'utf8'))
|
@ -1,3 +1,3 @@
|
|||||||
"""
|
"""
|
||||||
WebKit2 UI Module
|
WebKit2 UI Package
|
||||||
"""
|
"""
|
@ -24,7 +24,7 @@ class ControllerStartExceptiom(Exception):
|
|||||||
class Window(Gtk.ApplicationWindow):
|
class Window(Gtk.ApplicationWindow):
|
||||||
""" docstring for Window. """
|
""" docstring for Window. """
|
||||||
|
|
||||||
def __init__(self, args, unknownargs):
|
def __init__(self):
|
||||||
super(Window, self).__init__()
|
super(Window, self).__init__()
|
||||||
settings_manager.set_main_window(self)
|
settings_manager.set_main_window(self)
|
||||||
|
|
||||||
@ -34,7 +34,7 @@ class Window(Gtk.ApplicationWindow):
|
|||||||
self._setup_styling()
|
self._setup_styling()
|
||||||
self._setup_signals()
|
self._setup_signals()
|
||||||
self._subscribe_to_events()
|
self._subscribe_to_events()
|
||||||
self._load_widgets(args, unknownargs)
|
self._load_widgets()
|
||||||
|
|
||||||
self._set_window_data()
|
self._set_window_data()
|
||||||
self._set_size_constraints()
|
self._set_size_constraints()
|
||||||
@ -63,11 +63,11 @@ class Window(Gtk.ApplicationWindow):
|
|||||||
event_system.subscribe("tear-down", self._tear_down)
|
event_system.subscribe("tear-down", self._tear_down)
|
||||||
event_system.subscribe("load-interactive-debug", self._load_interactive_debug)
|
event_system.subscribe("load-interactive-debug", self._load_interactive_debug)
|
||||||
|
|
||||||
def _load_widgets(self, args, unknownargs):
|
def _load_widgets(self):
|
||||||
if settings_manager.is_debug():
|
if settings_manager.is_debug():
|
||||||
self.set_interactive_debugging(True)
|
self.set_interactive_debugging(True)
|
||||||
|
|
||||||
self._controller = BaseController(args, unknownargs)
|
self._controller = BaseController()
|
||||||
self._status_icon = StatusIcon()
|
self._status_icon = StatusIcon()
|
||||||
if not self._controller:
|
if not self._controller:
|
||||||
raise ControllerStartException("BaseController exited and doesn't exist...")
|
raise ControllerStartException("BaseController exited and doesn't exist...")
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
"""
|
"""
|
||||||
Utils module
|
Libs Package
|
||||||
"""
|
"""
|
@ -1,5 +1,5 @@
|
|||||||
"""
|
"""
|
||||||
DB module
|
DB Package
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from .models import User
|
from .models import User
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
"""
|
"""
|
||||||
Dasta Class module
|
Dasta Class Package
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from .event import Event
|
from .event import Event
|
@ -56,7 +56,7 @@ class IPCServer(Singleton):
|
|||||||
@daemon_threaded
|
@daemon_threaded
|
||||||
def _run_ipc_loop(self, listener) -> None:
|
def _run_ipc_loop(self, listener) -> None:
|
||||||
# NOTE: Not thread safe if using with Gtk. Need to import GLib and use idle_add
|
# NOTE: Not thread safe if using with Gtk. Need to import GLib and use idle_add
|
||||||
while True:
|
while self.is_ipc_alive:
|
||||||
try:
|
try:
|
||||||
conn = listener.accept()
|
conn = listener.accept()
|
||||||
start_time = time.perf_counter()
|
start_time = time.perf_counter()
|
||||||
@ -67,7 +67,7 @@ class IPCServer(Singleton):
|
|||||||
listener.close()
|
listener.close()
|
||||||
|
|
||||||
def _handle_ipc_message(self, conn, start_time) -> None:
|
def _handle_ipc_message(self, conn, start_time) -> None:
|
||||||
while True:
|
while self.is_ipc_alive:
|
||||||
msg = conn.recv()
|
msg = conn.recv()
|
||||||
logger.debug(msg)
|
logger.debug(msg)
|
||||||
|
|
||||||
@ -76,6 +76,9 @@ class IPCServer(Singleton):
|
|||||||
if file:
|
if file:
|
||||||
event_system.emit("handle-file-from-ipc", file)
|
event_system.emit("handle-file-from-ipc", file)
|
||||||
|
|
||||||
|
conn.close()
|
||||||
|
break
|
||||||
|
|
||||||
if "DIR|" in msg:
|
if "DIR|" in msg:
|
||||||
file = msg.split("DIR|")[1].strip()
|
file = msg.split("DIR|")[1].strip()
|
||||||
if file:
|
if file:
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
"""
|
"""
|
||||||
Utils/Mixins module
|
Libs.Mixins Package
|
||||||
"""
|
"""
|
@ -1,6 +1,8 @@
|
|||||||
# Python imports
|
# Python imports
|
||||||
|
|
||||||
# Lib imports
|
# Lib imports
|
||||||
|
import gi
|
||||||
|
from gi.repository import GLib
|
||||||
|
|
||||||
# Application imports
|
# Application imports
|
||||||
|
|
||||||
@ -8,13 +10,22 @@
|
|||||||
|
|
||||||
|
|
||||||
class IPCSignalsMixin:
|
class IPCSignalsMixin:
|
||||||
""" IPCSignalsMixin handle messages from another starting solarfm process. """
|
""" IPCSignalsMixin handle messages from another starting {APP_NAME} process. """
|
||||||
|
|
||||||
def print_to_console(self, message=None):
|
def print_to_console(self, message = None):
|
||||||
logger.debug(message)
|
logger.debug(message)
|
||||||
|
|
||||||
def handle_file_from_ipc(self, path: str) -> None:
|
def handle_file_from_ipc(self, fpath: str) -> None:
|
||||||
logger.debug(f"File From IPC: {path}")
|
logger.debug(f"File From IPC: {fpath}")
|
||||||
|
GLib.idle_add(
|
||||||
|
self.broadcast_message, "handle-file", (fpath,)
|
||||||
|
)
|
||||||
|
|
||||||
def handle_dir_from_ipc(self, path: str) -> None:
|
def handle_dir_from_ipc(self, fpath: str) -> None:
|
||||||
logger.debug(f"Dir From IPC: {path}")
|
logger.debug(f"Dir From IPC: {fpath}")
|
||||||
|
GLib.idle_add(
|
||||||
|
self.broadcast_message, "handle-folder", (fpath,)
|
||||||
|
)
|
||||||
|
|
||||||
|
def broadcast_message(self, message_type: str = "none", data: () = ()) -> None:
|
||||||
|
event_system.emit(message_type, data)
|
@ -1,4 +1,4 @@
|
|||||||
"""
|
"""
|
||||||
Settings module
|
Settings Package
|
||||||
"""
|
"""
|
||||||
from .manager import SettingsManager
|
from .manager import SettingsManager
|
@ -1,5 +1,6 @@
|
|||||||
# Python imports
|
# Python imports
|
||||||
import inspect
|
import inspect
|
||||||
|
import time
|
||||||
import json
|
import json
|
||||||
import zipfile
|
import zipfile
|
||||||
|
|
||||||
@ -22,35 +23,35 @@ class MissingConfigError(Exception):
|
|||||||
|
|
||||||
class SettingsManager(StartCheckMixin, Singleton):
|
class SettingsManager(StartCheckMixin, Singleton):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self._SCRIPT_PTH = path.dirname(path.realpath(__file__))
|
self._SCRIPT_PTH: str = path.dirname(path.realpath(__file__))
|
||||||
self._USER_HOME = path.expanduser('~')
|
self._USER_HOME: str = path.expanduser('~')
|
||||||
self._HOME_CONFIG_PATH = f"{self._USER_HOME}/.config/{APP_NAME.lower()}"
|
self._HOME_CONFIG_PATH: str = f"{self._USER_HOME}/.config/{APP_NAME.lower()}"
|
||||||
self._USR_PATH = f"/usr/share/{APP_NAME.lower()}"
|
self._USR_PATH: str = f"/usr/share/{APP_NAME.lower()}"
|
||||||
self._USR_CONFIG_FILE = f"{self._USR_PATH}/settings.json"
|
self._USR_CONFIG_FILE: str = f"{self._USR_PATH}/settings.json"
|
||||||
|
|
||||||
self._CONTEXT_PATH = f"{self._HOME_CONFIG_PATH}/context_path"
|
self._CONTEXT_PATH: str = f"{self._HOME_CONFIG_PATH}/context_path"
|
||||||
self._PLUGINS_PATH = f"{self._HOME_CONFIG_PATH}/plugins"
|
self._PLUGINS_PATH: str = f"{self._HOME_CONFIG_PATH}/plugins"
|
||||||
self._DEFAULT_ICONS = f"{self._HOME_CONFIG_PATH}/icons"
|
self._DEFAULT_ICONS: str = f"{self._HOME_CONFIG_PATH}/icons"
|
||||||
self._CONFIG_FILE = f"{self._HOME_CONFIG_PATH}/settings.json"
|
self._CONFIG_FILE: str = f"{self._HOME_CONFIG_PATH}/settings.json"
|
||||||
self._GLADE_FILE = f"{self._HOME_CONFIG_PATH}/Main_Window.glade"
|
self._GLADE_FILE: str = f"{self._HOME_CONFIG_PATH}/Main_Window.glade"
|
||||||
self._CSS_FILE = f"{self._HOME_CONFIG_PATH}/stylesheet.css"
|
self._CSS_FILE: str = f"{self._HOME_CONFIG_PATH}/stylesheet.css"
|
||||||
self._KEY_BINDINGS_FILE = f"{self._HOME_CONFIG_PATH}/key-bindings.json"
|
self._KEY_BINDINGS_FILE: str = f"{self._HOME_CONFIG_PATH}/key-bindings.json"
|
||||||
self._PID_FILE = f"{self._HOME_CONFIG_PATH}/{APP_NAME.lower()}.pid"
|
self._PID_FILE: str = f"{self._HOME_CONFIG_PATH}/{APP_NAME.lower()}.pid"
|
||||||
self._UI_WIDEGTS_PATH = f"{self._HOME_CONFIG_PATH}/ui_widgets"
|
self._UI_WIDEGTS_PATH: str = f"{self._HOME_CONFIG_PATH}/ui_widgets"
|
||||||
self._CONTEXT_MENU = f"{self._HOME_CONFIG_PATH}/contexct_menu.json"
|
self._CONTEXT_MENU: str = f"{self._HOME_CONFIG_PATH}/contexct_menu.json"
|
||||||
self._WINDOW_ICON = f"{self._DEFAULT_ICONS}/{APP_NAME.lower()}.png"
|
self._WINDOW_ICON: str = f"{self._DEFAULT_ICONS}/{APP_NAME.lower()}.png"
|
||||||
|
|
||||||
# self._USR_CONFIG_FILE = f"{self._USR_PATH}/settings.json"
|
# self._USR_CONFIG_FILE: str = f"{self._USR_PATH}/settings.json"
|
||||||
# self._PLUGINS_PATH = f"plugins"
|
# self._PLUGINS_PATH: str = f"plugins"
|
||||||
# self._CONFIG_FILE = f"settings.json"
|
# self._CONFIG_FILE: str = f"settings.json"
|
||||||
# self._GLADE_FILE = f"Main_Window.glade"
|
# self._GLADE_FILE: str = f"Main_Window.glade"
|
||||||
# self._CSS_FILE = f"stylesheet.css"
|
# self._CSS_FILE: str = f"stylesheet.css"
|
||||||
# self._KEY_BINDINGS_FILE = f"key-bindings.json"
|
# self._KEY_BINDINGS_FILE: str = f"key-bindings.json"
|
||||||
# self._PID_FILE = f"{APP_NAME.lower()}.pid"
|
# self._PID_FILE: str = f"{APP_NAME.lower()}.pid"
|
||||||
# self._WINDOW_ICON = f"{APP_NAME.lower()}.png"
|
# self._WINDOW_ICON: str = f"{APP_NAME.lower()}.png"
|
||||||
# self._UI_WIDEGTS_PATH = f"ui_widgets"
|
# self._UI_WIDEGTS_PATH: str = f"ui_widgets"
|
||||||
# self._CONTEXT_MENU = f"contexct_menu.json"
|
# self._CONTEXT_MENU: str = f"contexct_menu.json"
|
||||||
# self._DEFAULT_ICONS = f"icons"
|
# self._DEFAULT_ICONS: str = f"icons"
|
||||||
|
|
||||||
|
|
||||||
# with zipfile.ZipFile("files.zip", mode="r", allowZip64=True) as zf:
|
# with zipfile.ZipFile("files.zip", mode="r", allowZip64=True) as zf:
|
||||||
@ -102,25 +103,25 @@ class SettingsManager(StartCheckMixin, Singleton):
|
|||||||
print( f"Settings Manager: {self._CONTEXT_MENU}\n\t\t{repr(e)}" )
|
print( f"Settings Manager: {self._CONTEXT_MENU}\n\t\t{repr(e)}" )
|
||||||
|
|
||||||
|
|
||||||
self.settings: Settings = None
|
self.settings: Settings = None
|
||||||
self._main_window = None
|
self._main_window = None
|
||||||
self._builder = None
|
self._builder = None
|
||||||
self.PAINT_BG_COLOR = (0, 0, 0, 0.0)
|
self.PAINT_BG_COLOR: tuple = (0, 0, 0, 0.0)
|
||||||
|
|
||||||
self._trace_debug = False
|
self._trace_debug: bool = False
|
||||||
self._debug = False
|
self._debug: bool = False
|
||||||
self._dirty_start = False
|
self._dirty_start: bool = False
|
||||||
self._passed_in_file = False
|
self._passed_in_file: bool = False
|
||||||
self._starting_files = []
|
self._starting_files: list = []
|
||||||
|
|
||||||
|
|
||||||
def register_signals_to_builder(self, classes=None):
|
def register_signals_to_builder(self, classes = None):
|
||||||
handlers = {}
|
handlers = {}
|
||||||
|
|
||||||
for c in classes:
|
for c in classes:
|
||||||
methods = None
|
methods = None
|
||||||
try:
|
try:
|
||||||
methods = inspect.getmembers(c, predicate=inspect.ismethod)
|
methods = inspect.getmembers(c, predicate = inspect.ismethod)
|
||||||
handlers.update(methods)
|
handlers.update(methods)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
...
|
...
|
||||||
@ -153,34 +154,45 @@ class SettingsManager(StartCheckMixin, Singleton):
|
|||||||
def get_home_config_path(self) -> str: return self._HOME_CONFIG_PATH
|
def get_home_config_path(self) -> str: return self._HOME_CONFIG_PATH
|
||||||
def get_window_icon(self) -> str: return self._WINDOW_ICON
|
def get_window_icon(self) -> str: return self._WINDOW_ICON
|
||||||
def get_home_path(self) -> str: return self._USER_HOME
|
def get_home_path(self) -> str: return self._USER_HOME
|
||||||
def get_starting_files(self) -> []: return self._starting_files
|
def get_starting_files(self) -> list: return self._starting_files
|
||||||
|
|
||||||
|
def get_starting_args(self):
|
||||||
|
return self.args, self.unknownargs
|
||||||
|
|
||||||
|
def set_main_window_x(self, x: int = 0): self.settings.config.main_window_x = x
|
||||||
|
def set_main_window_y(self, y: int = 0): self.settings.config.main_window_y = y
|
||||||
|
def set_main_window_width(self, width: int = 800): self.settings.config.main_window_width = width
|
||||||
|
def set_main_window_height(self, height: int = 600): self.settings.config.main_window_height = height
|
||||||
|
def set_main_window_min_width(self, width: int = 720): self.settings.config.main_window_min_width = width
|
||||||
|
def set_main_window_min_height(self, height: int = 480): self.settings.config.main_window_min_height = height
|
||||||
|
def set_starting_files(self, files: list): self._starting_files = files
|
||||||
|
def set_start_load_time(self): self._start_load_time = time.perf_counter()
|
||||||
|
def set_end_load_time(self): self._end_load_time = time.perf_counter()
|
||||||
|
|
||||||
|
def set_starting_args(self, args, unknownargs):
|
||||||
|
self.args = args
|
||||||
|
self.unknownargs = unknownargs
|
||||||
|
|
||||||
|
def set_trace_debug(self, trace_debug: bool):
|
||||||
|
self._trace_debug = trace_debug
|
||||||
|
|
||||||
|
def set_debug(self, debug: bool):
|
||||||
|
self._debug = debug
|
||||||
|
|
||||||
|
def set_is_starting_with_file(self, is_passed_in_file: bool = False):
|
||||||
|
self._passed_in_file = is_passed_in_file
|
||||||
|
|
||||||
def is_trace_debug(self) -> str: return self._trace_debug
|
def is_trace_debug(self) -> str: return self._trace_debug
|
||||||
def is_debug(self) -> str: return self._debug
|
def is_debug(self) -> str: return self._debug
|
||||||
def is_starting_with_file(self) -> bool: return self._passed_in_file
|
def is_starting_with_file(self) -> bool: return self._passed_in_file
|
||||||
|
|
||||||
def call_method(self, target_class = None, _method_name = None, data = None):
|
def log_load_time(self): logger.info( f"Load Time: {self._end_load_time - self._start_load_time}" )
|
||||||
|
|
||||||
|
def call_method(self, target_class: any = None, _method_name: str = "", data: any = None):
|
||||||
method_name = str(_method_name)
|
method_name = str(_method_name)
|
||||||
method = getattr(target_class, method_name, lambda data: f"No valid key passed...\nkey={method_name}\nargs={data}")
|
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()
|
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_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
|
|
||||||
|
|
||||||
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):
|
def load_settings(self):
|
||||||
if not path.exists(self._CONFIG_FILE):
|
if not path.exists(self._CONFIG_FILE):
|
||||||
self.settings = Settings()
|
self.settings = Settings()
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
"""
|
"""
|
||||||
Options module
|
Settings.Options Package
|
||||||
"""
|
"""
|
||||||
from .settings import Settings
|
from .settings import Settings
|
||||||
from .config import Config
|
from .config import Config
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
"""
|
"""
|
||||||
Settings Other module
|
Settings.Other Package
|
||||||
"""
|
"""
|
@ -69,3 +69,7 @@ class ManifestProcessor:
|
|||||||
loading_data["bind_keys"] = requests["bind_keys"]
|
loading_data["bind_keys"] = requests["bind_keys"]
|
||||||
|
|
||||||
return self._plugin, loading_data
|
return self._plugin, loading_data
|
||||||
|
|
||||||
|
def is_pre_launch(self):
|
||||||
|
return self._plugin.pre_launch
|
||||||
|
|
||||||
|
@ -43,6 +43,6 @@
|
|||||||
|
|
||||||
|
|
||||||
/* Other message text colors */
|
/* Other message text colors */
|
||||||
.errorTxt { color: rgb(170, 18, 18); }
|
.error-txt { color: rgb(170, 18, 18); }
|
||||||
.warningTxt { color: rgb(255, 168, 0); }
|
.warning-txt { color: rgb(255, 168, 0); }
|
||||||
.successTxt { color: rgb(136, 204, 39); }
|
.success=txt { color: rgb(136, 204, 39); }
|
@ -1,6 +1,7 @@
|
|||||||
html, body {
|
html, body {
|
||||||
display: block;
|
display: block;
|
||||||
background-color: #32383e00;
|
// background-color: #32383e00;
|
||||||
|
background-color: rgba(39, 43, 52, 0.64);
|
||||||
color: #ffffff;
|
color: #ffffff;
|
||||||
text-wrap: wrap;
|
text-wrap: wrap;
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,14 @@
|
|||||||
/* ---- Make most desired things base transparent ---- */
|
/* ---- Make most desired things base transparent ---- */
|
||||||
|
/* ---- Make most desired things base transparent ---- */
|
||||||
popover,
|
popover,
|
||||||
popover > *,
|
popover > box
|
||||||
scrolledwindow > *,
|
.main-window,
|
||||||
textview > *,
|
.base-container,
|
||||||
.main-window > .base-container > .body-container,
|
.body-container,
|
||||||
.main-window > .base-container > .body-container > .left-container,
|
.center-container,
|
||||||
.main-window > .base-container > .body-container > .center-container,
|
.header-container,
|
||||||
.main-window > .base-container > .body-container > .right-container {
|
.left-containerm,
|
||||||
|
.right-container {
|
||||||
background: rgba(0, 0, 0, 0.0);
|
background: rgba(0, 0, 0, 0.0);
|
||||||
color: rgba(255, 255, 255, 1);
|
color: rgba(255, 255, 255, 1);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user