Bringing to latest changes #3

Merged
itdominator merged 41 commits from develop into master 2022-07-16 19:14:30 +00:00
8 changed files with 123 additions and 63 deletions
Showing only changes of commit ca855712b1 - Show all commits

View File

@ -10,7 +10,7 @@ from controller import IPCServerMixin
class Builtins(IPCServerMixin): class Builtins(IPCServerMixin):
"""Docstring for __builtins__ extender""" """ Inheret IPCServerMixin. Create an pub/sub systems. """
def __init__(self): def __init__(self):
# NOTE: The format used is list of [type, target, (data,)] Where: # NOTE: The format used is list of [type, target, (data,)] Where:

View File

@ -12,6 +12,8 @@ from __builtins__ import Builtins
class Main(Builtins): class Main(Builtins):
''' Create Settings and Controller classes. Bind signal to Builder. Inherit from Builtins to bind global methods and classes.'''
def __init__(self, args, unknownargs): def __init__(self, args, unknownargs):
if not debug: if not debug:
event_system.create_ipc_server() event_system.create_ipc_server()

View File

@ -19,6 +19,8 @@ from __init__ import Main
if __name__ == "__main__": if __name__ == "__main__":
''' Set process title, get arguments, and create GTK main thread. '''
try: try:
# import web_pdb # import web_pdb
# web_pdb.set_trace() # web_pdb.set_trace()

View File

@ -1,5 +1,5 @@
# Python imports # Python imports
import sys, traceback, threading, inspect, os, time import traceback, threading, inspect, os, time
# Lib imports # Lib imports
import gi import gi
@ -7,7 +7,7 @@ gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, GLib from gi.repository import Gtk, GLib
# Application imports # Application imports
from .mixins import UIMixin from .mixins import ExceptionHookMixin, UIMixin
from .signals import IPCSignalsMixin, KeyboardSignalsMixin from .signals import IPCSignalsMixin, KeyboardSignalsMixin
from . import Controller_Data from . import Controller_Data
@ -20,9 +20,9 @@ def threaded(fn):
class Controller(UIMixin, KeyboardSignalsMixin, IPCSignalsMixin, Controller_Data): class Controller(UIMixin, KeyboardSignalsMixin, IPCSignalsMixin, ExceptionHookMixin, Controller_Data):
''' Controller coordinates the mixins and is somewhat the root hub of it all. '''
def __init__(self, args, unknownargs, _settings): def __init__(self, args, unknownargs, _settings):
sys.excepthook = self.custom_except_hook
self.setup_controller_data(_settings) self.setup_controller_data(_settings)
self.window.show() self.window.show()
self.generate_windows(self.state) self.generate_windows(self.state)
@ -71,60 +71,6 @@ class Controller(UIMixin, KeyboardSignalsMixin, IPCSignalsMixin, Controller_Data
data = method(*(self, *parameters)) data = method(*(self, *parameters))
self.plugins.set_message_on_plugin(type, data) self.plugins.set_message_on_plugin(type, data)
def custom_except_hook(self, exctype, value, _traceback):
trace = ''.join(traceback.format_tb(_traceback))
data = f"Exectype: {exctype} <--> Value: {value}\n\n{trace}\n\n\n\n"
start_itr = self.message_buffer.get_start_iter()
self.message_buffer.place_cursor(start_itr)
self.display_message(self.error, data)
def display_message(self, type, text, seconds=None):
self.message_buffer.insert_at_cursor(text)
self.message_widget.popup()
if seconds:
self.hide_message_timeout(seconds)
@threaded
def hide_message_timeout(self, seconds=3):
time.sleep(seconds)
GLib.idle_add(self.message_widget.popdown)
def save_debug_alerts(self, widget=None, eve=None):
start_itr, end_itr = self.message_buffer.get_bounds()
save_location_prompt = Gtk.FileChooserDialog("Choose Save Folder", self.window, \
action = Gtk.FileChooserAction.SAVE, \
buttons = (Gtk.STOCK_CANCEL, \
Gtk.ResponseType.CANCEL, \
Gtk.STOCK_SAVE, \
Gtk.ResponseType.OK))
text = self.message_buffer.get_text(start_itr, end_itr, False)
resp = save_location_prompt.run()
if (resp == Gtk.ResponseType.CANCEL) or (resp == Gtk.ResponseType.DELETE_EVENT):
pass
elif resp == Gtk.ResponseType.OK:
target = save_location_prompt.get_filename();
with open(target, "w") as f:
f.write(text)
save_location_prompt.destroy()
def set_arc_buffer_text(self, widget=None, eve=None):
id = widget.get_active_id()
self.arc_command_buffer.set_text(self.arc_commands[int(id)])
def clear_children(self, widget):
for child in widget.get_children():
widget.remove(child)
def get_current_state(self):
wid, tid = self.window_controller.get_active_data()
view = self.get_fm_window(wid).get_view_by_id(tid)
iconview = self.builder.get_object(f"{wid}|{tid}|iconview")
store = iconview.get_model()
return wid, tid, view, iconview, store
def do_action_from_menu_controls(self, widget, eventbutton): def do_action_from_menu_controls(self, widget, eventbutton):
action = widget.get_name() action = widget.get_name()

View File

@ -1,5 +1,5 @@
# Python imports # Python imports
import signal import sys, os, signal
# Lib imports # Lib imports
from gi.repository import GLib from gi.repository import GLib
@ -13,8 +13,7 @@ from plugins import Plugins
class Controller_Data: class Controller_Data:
def has_method(self, o, name): ''' Controller_Data contains most of the state of the app at ay given time. It also has some support methods. '''
return callable(getattr(o, name, None))
def setup_controller_data(self, _settings): def setup_controller_data(self, _settings):
self.trashman = XDGTrash() self.trashman = XDGTrash()
@ -104,6 +103,53 @@ class Controller_Data:
self.warning = "#ffa800" self.warning = "#ffa800"
self.error = "#ff0000" self.error = "#ff0000"
sys.excepthook = self.custom_except_hook
self.window.connect("delete-event", self.tear_down) self.window.connect("delete-event", self.tear_down)
GLib.unix_signal_add(GLib.PRIORITY_DEFAULT, signal.SIGINT, self.tear_down) GLib.unix_signal_add(GLib.PRIORITY_DEFAULT, signal.SIGINT, self.tear_down)
def get_current_state(self):
'''
Returns the state info most useful for any given context and action intent.
Parameters:
a (obj): self
Returns:
wid, tid, view, iconview, store
'''
wid, tid = self.window_controller.get_active_data()
view = self.get_fm_window(wid).get_view_by_id(tid)
iconview = self.builder.get_object(f"{wid}|{tid}|iconview")
store = iconview.get_model()
return wid, tid, view, iconview, store
def clear_console(self):
''' Clears the terminal screen. '''
os.system('cls' if os.name == 'nt' else 'clear')
def call_method(self, _method_name, data = None):
'''
Calls a method from scope of class.
Parameters:
a (obj): self
b (str): method name to be called
c (*): Data (if any) to be passed to the method.
Note: It must be structured according to the given methods requirements.
Returns:
Return data is that which the calling method gives.
'''
method_name = str(_method_name)
method = getattr(self, method_name, lambda data: f"No valid key passed...\nkey={method_name}\nargs={data}")
return method(data) if data else method()
def has_method(self, obj, name):
''' Checks if a given method exists. '''
return callable(getattr(obj, name, None))
def clear_children(self, widget):
''' Clear children of a gtk widget. '''
for child in widget.get_children():
widget.remove(child)

View File

@ -16,6 +16,7 @@ def threaded(fn):
class IPCServerMixin: class IPCServerMixin:
''' Create a listener so that other SolarFM instances send requests back to existing instance. '''
@threaded @threaded
def create_ipc_server(self): def create_ipc_server(self):

View File

@ -0,0 +1,62 @@
# Python imports
import traceback, threading, time
# Lib imports
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, GLib
# Application imports
def threaded(fn):
def wrapper(*args, **kwargs):
threading.Thread(target=fn, args=args, kwargs=kwargs, daemon=True).start()
return wrapper
class ExceptionHookMixin:
''' ExceptionHookMixin custom exception hook to reroute to a Gtk text area. '''
def custom_except_hook(self, exctype, value, _traceback):
trace = ''.join(traceback.format_tb(_traceback))
data = f"Exectype: {exctype} <--> Value: {value}\n\n{trace}\n\n\n\n"
start_itr = self.message_buffer.get_start_iter()
self.message_buffer.place_cursor(start_itr)
self.display_message(self.error, data)
def display_message(self, type, text, seconds=None):
self.message_buffer.insert_at_cursor(text)
self.message_widget.popup()
if seconds:
self.hide_message_timeout(seconds)
@threaded
def hide_message_timeout(self, seconds=3):
time.sleep(seconds)
GLib.idle_add(self.message_widget.popdown)
def save_debug_alerts(self, widget=None, eve=None):
start_itr, end_itr = self.message_buffer.get_bounds()
save_location_prompt = Gtk.FileChooserDialog("Choose Save Folder", self.window, \
action = Gtk.FileChooserAction.SAVE, \
buttons = (Gtk.STOCK_CANCEL, \
Gtk.ResponseType.CANCEL, \
Gtk.STOCK_SAVE, \
Gtk.ResponseType.OK))
text = self.message_buffer.get_text(start_itr, end_itr, False)
resp = save_location_prompt.run()
if (resp == Gtk.ResponseType.CANCEL) or (resp == Gtk.ResponseType.DELETE_EVENT):
pass
elif resp == Gtk.ResponseType.OK:
target = save_location_prompt.get_filename();
with open(target, "w") as f:
f.write(text)
save_location_prompt.destroy()
def set_arc_buffer_text(self, widget=None, eve=None):
id = widget.get_active_id()
self.arc_command_buffer.set_text(self.arc_commands[int(id)])

View File

@ -1,2 +1,3 @@
from .ShowHideMixin import ShowHideMixin from .ShowHideMixin import ShowHideMixin
from .ExceptionHookMixin import ExceptionHookMixin
from .UIMixin import UIMixin from .UIMixin import UIMixin