Initial push
This commit is contained in:
3
src/core/__init__.py
Normal file
3
src/core/__init__.py
Normal file
@@ -0,0 +1,3 @@
|
||||
"""
|
||||
Core Module
|
||||
"""
|
75
src/core/controller.py
Normal file
75
src/core/controller.py
Normal file
@@ -0,0 +1,75 @@
|
||||
# Python imports
|
||||
import os
|
||||
|
||||
# Lib imports
|
||||
import gi
|
||||
gi.require_version('Gtk', '3.0')
|
||||
from gi.repository import Gtk
|
||||
|
||||
# Application imports
|
||||
from .mixins.signals_mixins import SignalsMixins
|
||||
from .controller_data import ControllerData
|
||||
from .widgets.transparency_scale import TransparencyScale
|
||||
|
||||
|
||||
|
||||
class Controller(SignalsMixins, ControllerData):
|
||||
def __init__(self, args, unknownargs):
|
||||
self.setup_controller_data()
|
||||
|
||||
self._setup_styling()
|
||||
self._setup_signals()
|
||||
self._subscribe_to_events()
|
||||
|
||||
for arg in unknownargs + [args.new_tab,]:
|
||||
if os.path.isfile(arg):
|
||||
message = f"FILE|{arg}"
|
||||
event_system.emit("post_file_to_ipc", message)
|
||||
|
||||
logger.info(f"Made it past {self.__class__} loading...")
|
||||
|
||||
|
||||
def _setup_styling(self):
|
||||
...
|
||||
|
||||
def _setup_signals(self):
|
||||
self.window.connect("focus-out-event", self.unset_keys_and_data)
|
||||
self.window.connect("key-press-event", self.on_global_key_press_controller)
|
||||
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("remove_transparency", self._remove_transparency)
|
||||
event_system.subscribe("update_transparency", self._update_transparency)
|
||||
|
||||
def setup_builder_and_container(self):
|
||||
self.builder = Gtk.Builder()
|
||||
self.builder.add_from_file(settings_manager.get_glade_file())
|
||||
self.builder.expose_object("main_window", self.window)
|
||||
|
||||
settings_manager.set_builder(self.builder)
|
||||
|
||||
glade_box = self.builder.get_object("glade_box")
|
||||
self.base_container = glade_box
|
||||
self.ctx = self.base_container.get_style_context()
|
||||
|
||||
self.ctx.add_class(f"mw_transparency_{settings.theming.transparency}")
|
||||
settings_manager.register_signals_to_builder([self, self.base_container])
|
||||
|
||||
TransparencyScale()
|
||||
self.window.add(glade_box)
|
||||
|
||||
|
||||
def _interactive_debug(self, widget = None, eve = None):
|
||||
event_system.emit("load_interactive_debug")
|
||||
|
||||
def _remove_transparency(self):
|
||||
self.ctx.remove_class(f"mw_transparency_{settings.theming.transparency}")
|
||||
|
||||
def _update_transparency(self):
|
||||
self.ctx.add_class(f"mw_transparency_{settings.theming.transparency}")
|
||||
|
||||
|
||||
def _close_app(self):
|
||||
event_system.emit("tear_down")
|
174
src/core/controller_data.py
Normal file
174
src/core/controller_data.py
Normal file
@@ -0,0 +1,174 @@
|
||||
# Python imports
|
||||
import os
|
||||
import subprocess
|
||||
import collections
|
||||
import tempfile
|
||||
|
||||
# Lib imports
|
||||
import gi
|
||||
gi.require_version('Gtk', '3.0')
|
||||
gi.require_version('GtkSource', '4')
|
||||
from gi.repository import GObject
|
||||
from gi.repository import Gtk
|
||||
from gi.repository import Gdk
|
||||
from gi.repository import GtkSource
|
||||
|
||||
# Application imports
|
||||
|
||||
|
||||
|
||||
class ControllerData:
|
||||
''' ControllerData contains most of the state of the app at ay given time. It also has some support methods. '''
|
||||
|
||||
def setup_controller_data(self) -> None:
|
||||
# Needed hack to get GtkSourceView widget to run from glade file...
|
||||
GtkSource.View()
|
||||
|
||||
self.window = settings_manager.get_main_window()
|
||||
self.builder = None
|
||||
self.base_container = None
|
||||
|
||||
self.setup_builder_and_container()
|
||||
|
||||
self.was_midified_key = False
|
||||
self.ctrl_down = False
|
||||
self.shift_down = False
|
||||
self.alt_down = False
|
||||
|
||||
|
||||
self.language_id = 'c'
|
||||
self.language_name = 'C'
|
||||
self.black_color = Gdk.color_parse('#000000');
|
||||
self.gui_style_ids = [
|
||||
'bracket-match', 'bracket-mismatch',
|
||||
'current-line', 'cursor', 'line-numbers',
|
||||
'secondary-cursor', 'selection',
|
||||
'selection-unfocused', 'text'
|
||||
]
|
||||
|
||||
self.styles_list = self.builder.get_object('styles_list')
|
||||
self.languages_list = self.builder.get_object('languages_list')
|
||||
|
||||
self.languages_dropdown = self.builder.get_object('languages_dropdown')
|
||||
self.styles_treeview = self.builder.get_object('styles_treeview')
|
||||
|
||||
self.bold_tggle_btn = self.builder.get_object('bold_tggle_btn')
|
||||
self.italic_tggle_btn = self.builder.get_object('italic_tggle_btn')
|
||||
self.underline_tggle_btn = self.builder.get_object('underline_tggle_btn')
|
||||
self.strikethrough_tggle_btn = self.builder.get_object('strikethrough_tggle_btn')
|
||||
self.fr_check_btn = self.builder.get_object('fr_check_btn')
|
||||
self.br_check_btn = self.builder.get_object('br_check_btn')
|
||||
self.fr_color_btn = self.builder.get_object('fr_color_btn')
|
||||
self.br_color_btn = self.builder.get_object('br_color_btn')
|
||||
self.reset_btn = self.builder.get_object('reset_btn')
|
||||
|
||||
self.name_entry = self.builder.get_object('name_entry')
|
||||
self.id_entry = self.builder.get_object('id_entry')
|
||||
self.desc_entry = self.builder.get_object('desc_entry')
|
||||
self.authr_entry = self.builder.get_object('authr_entry')
|
||||
self.sample_lbl = self.builder.get_object('sample_lbl')
|
||||
self.src_buffer = GtkSource.Buffer(max_undo_levels = 0)
|
||||
self.src_preview = self.builder.get_object('src_preview')
|
||||
|
||||
|
||||
self.scheme_manager = GtkSource.StyleSchemeManager()
|
||||
self.language_manager = GtkSource.LanguageManager()
|
||||
self.all_styles_dict = collections.OrderedDict()
|
||||
|
||||
self.language = self.language_manager.get_language(self.language_id)
|
||||
self.current_lang_id = self.language_id
|
||||
self.current_lang_name = self.language_name
|
||||
self.orig_scheme_file = None
|
||||
|
||||
self.bold_tggl_handler = self.get_handler_id(self.bold_tggle_btn, 'toggled')
|
||||
self.italic_tggl_handler = self.get_handler_id(self.italic_tggle_btn, 'toggled')
|
||||
self.underline_tggl_handler = self.get_handler_id(self.underline_tggle_btn, 'toggled')
|
||||
self.strikethrough_tggl_handler = self.get_handler_id(self.strikethrough_tggle_btn, 'toggled')
|
||||
self.foreground_tggl_handler = self.get_handler_id(self.fr_check_btn, 'toggled')
|
||||
self.background_tggl_handler = self.get_handler_id(self.br_check_btn, 'toggled')
|
||||
|
||||
# watch temp directory to help the sample viewer
|
||||
self.scheme_manager.append_search_path( tempfile.gettempdir() )
|
||||
self.src_preview.set_buffer(self.src_buffer)
|
||||
self.load_initial_data()
|
||||
|
||||
def load_initial_data(self, from_file = None):
|
||||
if from_file and os.path.isfile(from_file):
|
||||
self.load_scheme(from_file)
|
||||
else:
|
||||
self.load_scheme('cobalt')
|
||||
|
||||
languages = self.language_manager.get_language_ids()
|
||||
languages.sort()
|
||||
self.lang_map_name_to_id = {}
|
||||
|
||||
self.languages_list.append(['Default styles'])
|
||||
self.lang_map_name_to_id['Default styles'] = 'def'
|
||||
|
||||
for lang in languages:
|
||||
lang_name = self.language_manager.get_language(lang).get_name()
|
||||
self.lang_map_name_to_id[lang_name] = lang
|
||||
|
||||
if lang_name != 'Defaults':
|
||||
self.languages_list.append([lang_name])
|
||||
|
||||
self.styles_treeview_selection = self.styles_treeview.get_selection()
|
||||
self.styles_treeview_selection.connect('changed', self.on_style_selected)
|
||||
|
||||
# select the first language
|
||||
self.languages_dropdown.set_active(0)
|
||||
|
||||
# select the first style
|
||||
model = self.styles_treeview.get_model()
|
||||
tree_iter = model.get_iter_first()
|
||||
self.styles_treeview_selection.select_iter(tree_iter)
|
||||
self.selected_style_id = model[tree_iter][0]
|
||||
|
||||
def get_handler_id(self, obj, signal_name):
|
||||
signal_id, detail = GObject.signal_parse_name(signal_name, obj, True)
|
||||
return GObject.signal_handler_find(obj, GObject.SignalMatchType.ID, signal_id, detail, None, None, None)
|
||||
|
||||
def get_base_container(self):
|
||||
return self.base_container
|
||||
|
||||
def clear_console(self) -> None:
|
||||
''' Clears the terminal screen. '''
|
||||
os.system('cls' if os.name == 'nt' else 'clear')
|
||||
|
||||
def call_method(self, _method_name: str, data: type) -> type:
|
||||
'''
|
||||
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: type, method: type) -> type:
|
||||
''' Checks if a given method exists. '''
|
||||
return callable(getattr(obj, method, None))
|
||||
|
||||
def clear_children(self, widget: type) -> None:
|
||||
''' Clear children of a gtk widget. '''
|
||||
for child in widget.get_children():
|
||||
widget.remove(child)
|
||||
|
||||
def get_clipboard_data(self, encoding = "utf-8") -> str:
|
||||
proc = subprocess.Popen(['xclip','-selection', 'clipboard', '-o'], stdout = subprocess.PIPE)
|
||||
retcode = proc.wait()
|
||||
data = proc.stdout.read()
|
||||
return data.decode(encoding).strip()
|
||||
|
||||
def set_clipboard_data(self, data: type, encoding = "utf-8") -> None:
|
||||
proc = subprocess.Popen(['xclip','-selection','clipboard'], stdin = subprocess.PIPE)
|
||||
proc.stdin.write(data.encode(encoding))
|
||||
proc.stdin.close()
|
||||
retcode = proc.wait()
|
3
src/core/mixins/__init__.py
Normal file
3
src/core/mixins/__init__.py
Normal file
@@ -0,0 +1,3 @@
|
||||
"""
|
||||
Generic Mixins Module
|
||||
"""
|
3
src/core/mixins/signals/__init__.py
Normal file
3
src/core/mixins/signals/__init__.py
Normal file
@@ -0,0 +1,3 @@
|
||||
"""
|
||||
Signals module
|
||||
"""
|
17
src/core/mixins/signals/ipc_signals_mixin.py
Normal file
17
src/core/mixins/signals/ipc_signals_mixin.py
Normal file
@@ -0,0 +1,17 @@
|
||||
# Python imports
|
||||
|
||||
# Lib imports
|
||||
|
||||
# Application imports
|
||||
|
||||
|
||||
|
||||
|
||||
class IPCSignalsMixin:
|
||||
""" IPCSignalsMixin handle messages from another starting solarfm process. """
|
||||
|
||||
def print_to_console(self, message=None):
|
||||
logger.debug(message)
|
||||
|
||||
def handle_file_from_ipc(self, path: str) -> None:
|
||||
logger.debug(f"File From IPC: {path}")
|
94
src/core/mixins/signals/keyboard_signals_mixin.py
Normal file
94
src/core/mixins/signals/keyboard_signals_mixin.py
Normal file
@@ -0,0 +1,94 @@
|
||||
# Python imports
|
||||
import re
|
||||
|
||||
# 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
|
||||
|
||||
# Application imports
|
||||
|
||||
|
||||
|
||||
valid_keyvalue_pat = re.compile(r"[a-z0-9A-Z-_\[\]\(\)\| ]")
|
||||
|
||||
|
||||
|
||||
class KeyboardSignalsMixin:
|
||||
""" KeyboardSignalsMixin keyboard hooks controller. """
|
||||
|
||||
# TODO: Need to set methods that use this to somehow check the keybindings state instead.
|
||||
def unset_keys_and_data(self, widget=None, eve=None):
|
||||
self.ctrl_down = False
|
||||
self.shift_down = False
|
||||
self.alt_down = False
|
||||
|
||||
def on_global_key_press_controller(self, eve, user_data):
|
||||
keyname = Gdk.keyval_name(user_data.keyval).lower()
|
||||
modifiers = Gdk.ModifierType(user_data.get_state() & ~Gdk.ModifierType.LOCK_MASK)
|
||||
|
||||
self.was_midified_key = True if modifiers != 0 else False
|
||||
|
||||
if keyname.replace("_l", "").replace("_r", "") in ["control", "alt", "shift"]:
|
||||
if "control" in keyname:
|
||||
self.ctrl_down = True
|
||||
if "shift" in keyname:
|
||||
self.shift_down = True
|
||||
if "alt" in keyname:
|
||||
self.alt_down = True
|
||||
|
||||
def on_global_key_release_controller(self, widget, event):
|
||||
""" Handler for keyboard events """
|
||||
keyname = Gdk.keyval_name(event.keyval).lower()
|
||||
modifiers = Gdk.ModifierType(event.get_state() & ~Gdk.ModifierType.LOCK_MASK)
|
||||
|
||||
if keyname.replace("_l", "").replace("_r", "") in ["control", "alt", "shift"]:
|
||||
should_return = self.was_midified_key and (self.ctrl_down or self.shift_down or self.alt_down)
|
||||
|
||||
if "control" in keyname:
|
||||
self.ctrl_down = False
|
||||
if "shift" in keyname:
|
||||
self.shift_down = False
|
||||
if "alt" in keyname:
|
||||
self.alt_down = False
|
||||
|
||||
# NOTE: In effect a filter after releasing a modifier and we have a modifier mapped
|
||||
if should_return:
|
||||
self.was_midified_key = False
|
||||
return
|
||||
|
||||
mapping = keybindings.lookup(event)
|
||||
logger.debug(f"on_global_key_release_controller > key > {keyname}")
|
||||
logger.debug(f"on_global_key_release_controller > keyval > {event.keyval}")
|
||||
logger.debug(f"on_global_key_release_controller > mapping > {mapping}")
|
||||
|
||||
if mapping:
|
||||
# See if in controller scope
|
||||
try:
|
||||
getattr(self, mapping)()
|
||||
return True
|
||||
except Exception:
|
||||
# Must be plugins scope, event call, OR we forgot to add method to controller scope
|
||||
if "||" in mapping:
|
||||
sender, eve_type = mapping.split("||")
|
||||
else:
|
||||
sender = ""
|
||||
eve_type = mapping
|
||||
|
||||
self.handle_key_event_system(sender, eve_type)
|
||||
else:
|
||||
logger.debug(f"on_global_key_release_controller > key > {keyname}")
|
||||
|
||||
if self.ctrl_down:
|
||||
if not keyname in ["1", "kp_1", "2", "kp_2", "3", "kp_3", "4", "kp_4"]:
|
||||
self.handle_key_event_system(None, mapping)
|
||||
else:
|
||||
...
|
||||
|
||||
def handle_key_event_system(self, sender, eve_type):
|
||||
event_system.emit(eve_type)
|
||||
|
||||
def keyboard_close_tab(self):
|
||||
...
|
37
src/core/mixins/signals/main_signals_mixin.py
Normal file
37
src/core/mixins/signals/main_signals_mixin.py
Normal file
@@ -0,0 +1,37 @@
|
||||
# Python imports
|
||||
|
||||
# Lib imports
|
||||
|
||||
# Application imports
|
||||
from utils.style_properties import StyleProperties
|
||||
|
||||
from .widget_signals.list_signals_mixin import ListSignalsMixin
|
||||
from .widget_signals.tggle_and_check_box_signals_mixin import TggleAndCheckBoxSignals
|
||||
from .widget_signals.sourceview_signals_mixin import SourceviewSignalsMixin
|
||||
from .widget_signals.dialog_signals_mixin import DialogSignalsMixin
|
||||
|
||||
|
||||
|
||||
class MainSignalsMixin(ListSignalsMixin, TggleAndCheckBoxSignals, SourceviewSignalsMixin, DialogSignalsMixin):
|
||||
|
||||
def on_style_changed(self, data):
|
||||
if self.selected_style_id not in self.all_styles_dict:
|
||||
self.all_styles_dict[self.selected_style_id] = StyleProperties()
|
||||
|
||||
color_scale = 255.0/65535.0
|
||||
if data == self.br_color_btn:
|
||||
color = data.get_color()
|
||||
self.all_styles_dict[self.selected_style_id].background = ('#%02x%02x%02x' % (color.red * color_scale, color.green * color_scale, color.blue * color_scale))
|
||||
elif data == self.fr_color_btn:
|
||||
color = data.get_color()
|
||||
self.all_styles_dict[self.selected_style_id].foreground = ('#%02x%02x%02x' % (color.red * color_scale, color.green * color_scale, color.blue * color_scale))
|
||||
elif data == self.bold_tggle_btn:
|
||||
self.all_styles_dict[self.selected_style_id].bold = data.get_active()
|
||||
elif data == self.italic_tggle_btn:
|
||||
self.all_styles_dict[self.selected_style_id].italic = data.get_active()
|
||||
elif data == self.underline_tggle_btn:
|
||||
self.all_styles_dict[self.selected_style_id].underline = data.get_active()
|
||||
elif data == self.strikethrough_tggle_btn:
|
||||
self.all_styles_dict[self.selected_style_id].strikethrough = data.get_active()
|
||||
|
||||
self.update_sample_view()
|
3
src/core/mixins/signals/widget_signals/__init__.py
Normal file
3
src/core/mixins/signals/widget_signals/__init__.py
Normal file
@@ -0,0 +1,3 @@
|
||||
"""
|
||||
Widget signals module
|
||||
"""
|
139
src/core/mixins/signals/widget_signals/dialog_signals_mixin.py
Normal file
139
src/core/mixins/signals/widget_signals/dialog_signals_mixin.py
Normal file
@@ -0,0 +1,139 @@
|
||||
# Python imports
|
||||
import os
|
||||
|
||||
# Lib imports
|
||||
import gi
|
||||
gi.require_version('Gtk', '3.0')
|
||||
from gi.repository import Gtk
|
||||
|
||||
# Application imports
|
||||
|
||||
|
||||
|
||||
class DialogSignalsMixin():
|
||||
def on_open_clicked(self, param):
|
||||
file_chooser = Gtk.FileChooserDialog('Open', self.window, Gtk.FileChooserAction.OPEN, (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, Gtk.STOCK_OPEN, Gtk.ResponseType.OK))
|
||||
|
||||
file_filter = Gtk.FileFilter()
|
||||
file_filter.set_name('XML files')
|
||||
file_filter.add_pattern('*.xml')
|
||||
file_chooser.add_filter(file_filter)
|
||||
|
||||
file_filter = Gtk.FileFilter()
|
||||
file_filter.set_name('All files')
|
||||
file_filter.add_pattern('*')
|
||||
file_chooser.add_filter(file_filter)
|
||||
|
||||
file_chooser.set_default_response(Gtk.ResponseType.OK)
|
||||
file_chooser.set_current_folder(os.path.expanduser('~'))
|
||||
|
||||
path = None
|
||||
response = file_chooser.run()
|
||||
if response == Gtk.ResponseType.OK:
|
||||
path = file_chooser.get_filename()
|
||||
if path and not os.access(path, os.R_OK):
|
||||
abspath = os.path.abspath(path)
|
||||
self.message_dialog(Gtk.MessageType.ERROR, ('Could not open file "%s"') % abspath, ('The file "%s" could not be opened. ' 'Permission denied.') % abspath, file_chooser)
|
||||
path = None
|
||||
|
||||
file_chooser.destroy()
|
||||
if not path: return
|
||||
self.load_scheme(path)
|
||||
|
||||
def on_save_clicked(self, param):
|
||||
if not self.origSchemeFile:
|
||||
filename = run_save_as_dialog(self.window, self.entryId.get_text() + '.xml')
|
||||
|
||||
if filename and not '.' in os.path.basename(filename):
|
||||
filename = f"{filename}.xml"
|
||||
|
||||
if filename:
|
||||
self.write_scheme(filename, self.entryId.get_text())
|
||||
self.origSchemeFile = filename
|
||||
else:
|
||||
self.write_scheme(self.origSchemeFile, self.entryId.get_text())
|
||||
|
||||
def on_save_as_clicked(self, param):
|
||||
filename = run_save_as_dialog(self.window, self.entryId.get_text() + '.xml')
|
||||
if filename and not '.' in os.path.basename(filename):
|
||||
filename = f"{filename}.xml"
|
||||
|
||||
if filename:
|
||||
self.write_scheme(filename, self.entryId.get_text())
|
||||
self.origSchemeFile = filename
|
||||
|
||||
|
||||
def message_dialog(
|
||||
dialog_type,
|
||||
short_msg,
|
||||
long_msg = None,
|
||||
parent = None,
|
||||
buttons = Gtk.ButtonsType.OK,
|
||||
additional_buttons = None
|
||||
):
|
||||
dialog = Gtk.MessageDialog(parent = parent, flags = Gtk.DialogFlags.MODAL, type = dialog_type, buttons = buttons)
|
||||
|
||||
if additional_buttons:
|
||||
dialog.add_buttons(*additional_buttons)
|
||||
|
||||
dialog.set_markup(short_msg)
|
||||
if long_msg:
|
||||
if isinstance(long_msg, Gtk.Widget):
|
||||
widget = long_msg
|
||||
elif isinstance(long_msg, str):
|
||||
widget = Gtk.Label()
|
||||
widget.set_markup(long_msg)
|
||||
else:
|
||||
raise TypeError('"long_msg" must be a Gtk.Widget or a string')
|
||||
|
||||
expander = Gtk.Expander(label = 'Click here for details')
|
||||
expander.set_border_width(6)
|
||||
expander.add(widget)
|
||||
dialog.vbox.pack_end(expander, True, True, 0)
|
||||
|
||||
dialog.show_all()
|
||||
response = dialog.run()
|
||||
dialog.destroy()
|
||||
|
||||
return response
|
||||
|
||||
def run_save_as_dialog(parent, current_name):
|
||||
file_chooser = Gtk.FileChooserDialog('Save As', parent, Gtk.FileChooserAction.SAVE, (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, Gtk.STOCK_SAVE, Gtk.ResponseType.OK))
|
||||
|
||||
file_filter = Gtk.FileFilter()
|
||||
file_filter.set_name('XML files')
|
||||
file_filter.add_pattern('*.xml')
|
||||
file_chooser.add_filter(file_filter)
|
||||
|
||||
file_filter = Gtk.FileFilter()
|
||||
file_filter.set_name('All files')
|
||||
file_filter.add_pattern('*')
|
||||
file_chooser.add_filter(file_filter)
|
||||
|
||||
file_chooser.set_default_response(Gtk.ResponseType.OK)
|
||||
file_chooser.set_current_folder( os.path.expanduser('~') )
|
||||
|
||||
if current_name:
|
||||
file_chooser.set_current_name(current_name)
|
||||
|
||||
file_chooser.set_default_response(Gtk.ResponseType.OK)
|
||||
|
||||
path = None
|
||||
while True:
|
||||
response = file_chooser.run()
|
||||
if response != Gtk.ResponseType.OK:
|
||||
path = None
|
||||
break
|
||||
|
||||
path = file_chooser.get_filename()
|
||||
if not os.path.exists(path): break
|
||||
|
||||
sub_msg_1 = ('A file named "%s" already exists') % os.path.abspath(path)
|
||||
sub_msg_2 = ('Do you which to replace it with the current project?')
|
||||
text = '<span weight="bold" size="larger">%s</span>\n\n%s\n' % (sub_msg_1, sub_msg_2)
|
||||
result = message_dialog(Gtk.MessageType.ERROR, text, parent = parent, buttons = Gtk.ButtonsType.NONE, additional_buttons = (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, 'Replace', Gtk.ResponseType.YES))
|
||||
|
||||
if result == Gtk.ResponseType.YES: break
|
||||
|
||||
file_chooser.destroy()
|
||||
return path
|
107
src/core/mixins/signals/widget_signals/list_signals_mixin.py
Normal file
107
src/core/mixins/signals/widget_signals/list_signals_mixin.py
Normal file
@@ -0,0 +1,107 @@
|
||||
# Python imports
|
||||
|
||||
# Lib imports
|
||||
import gi
|
||||
gi.require_version('Gtk', '3.0')
|
||||
from gi.repository import Gdk
|
||||
|
||||
# Application imports
|
||||
from utils.languages import samples
|
||||
|
||||
|
||||
|
||||
|
||||
class ListSignalsMixin:
|
||||
def on_language_selected(self, combo):
|
||||
tree_iter = combo.get_active_iter()
|
||||
|
||||
if tree_iter:
|
||||
model = combo.get_model()
|
||||
self.current_lang_name = model[tree_iter][0]
|
||||
self.current_lang_id = self.lang_map_name_to_id[self.current_lang_name]
|
||||
|
||||
self.styles_list.clear()
|
||||
|
||||
remove_len = len(self.current_lang_id) + 1
|
||||
lang = self.language_manager.get_language(self.current_lang_id)
|
||||
|
||||
if lang:
|
||||
style_ids = lang.get_style_ids()
|
||||
style_ids.sort()
|
||||
|
||||
if self.current_lang_id == 'def':
|
||||
for style_id in self.gui_style_ids:
|
||||
self.styles_list.append([style_id])
|
||||
|
||||
for style_id in style_ids:
|
||||
self.styles_list.append([style_id[remove_len:]])
|
||||
|
||||
tree_iter = self.styles_treeview.get_model().get_iter_first()
|
||||
self.styles_treeview_selection.select_iter(tree_iter)
|
||||
model = self.styles_treeview.get_model()
|
||||
self.selected_style_id = model[tree_iter][0]
|
||||
|
||||
if self.current_lang_id in samples:
|
||||
self.src_buffer.set_language(lang);
|
||||
self.src_buffer.set_text(samples[self.current_lang_id])
|
||||
self.sample_lbl.set_text(f"{self.current_lang_name} sample")
|
||||
else:
|
||||
self.src_buffer.set_language(self.language);
|
||||
self.src_buffer.set_text(samples[self.language_id])
|
||||
self.sample_lbl.set_text(f"{self.language_name} sample")
|
||||
|
||||
def on_style_selected(self, selection):
|
||||
model, tree_iter = selection.get_selected()
|
||||
if not tree_iter: return
|
||||
|
||||
self.selected_style_id = f"{self.current_lang_id}:{model[tree_iter][0]}"
|
||||
|
||||
# handle the special case for GUI styles
|
||||
if self.selected_style_id not in self.all_styles_dict and self.current_lang_id == 'def':
|
||||
self.selected_style_id = model[tree_iter][0]
|
||||
|
||||
# block all the toggle handlers so they dont get triggered
|
||||
self.bold_tggle_btn.handler_block(self.bold_tggl_handler)
|
||||
self.italic_tggle_btn.handler_block(self.italic_tggl_handler)
|
||||
self.underline_tggle_btn.handler_block(self.underline_tggl_handler)
|
||||
self.strikethrough_tggle_btn.handler_block(self.strikethrough_tggl_handler)
|
||||
self.fr_check_btn.handler_block(self.foreground_tggl_handler)
|
||||
self.br_check_btn.handler_block(self.background_tggl_handler)
|
||||
|
||||
if self.selected_style_id in self.all_styles_dict:
|
||||
this_style = self.all_styles_dict[self.selected_style_id]
|
||||
|
||||
# handle foreground and background colors
|
||||
if this_style.foreground:
|
||||
self.fr_color_btn.set_color(Gdk.color_parse(this_style.foreground))
|
||||
self.fr_color_btn.set_sensitive(True)
|
||||
self.fr_check_btn.set_active(True)
|
||||
else:
|
||||
self.fr_color_btn.set_color(self.black_color)
|
||||
self.fr_color_btn.set_sensitive(False)
|
||||
self.fr_check_btn.set_active(False)
|
||||
|
||||
if this_style.background:
|
||||
self.br_color_btn.set_color(Gdk.color_parse(this_style.background))
|
||||
self.br_color_btn.set_sensitive(True)
|
||||
self.br_check_btn.set_active(True)
|
||||
else:
|
||||
self.br_color_btn.set_color(self.black_color)
|
||||
self.br_color_btn.set_sensitive(False)
|
||||
self.br_check_btn.set_active(False)
|
||||
|
||||
# handle text styling
|
||||
self.italic_tggle_btn.set_active(this_style.italic)
|
||||
self.bold_tggle_btn.set_active(this_style.bold)
|
||||
self.strikethrough_tggle_btn.set_active(this_style.strikethrough)
|
||||
self.underline_tggle_btn.set_active(this_style.underline)
|
||||
self.reset_btn.set_sensitive(True)
|
||||
else:
|
||||
self.clear_and_disable_style_buttons()
|
||||
|
||||
self.bold_tggle_btn.handler_unblock(self.bold_tggl_handler)
|
||||
self.italic_tggle_btn.handler_unblock(self.italic_tggl_handler)
|
||||
self.underline_tggle_btn.handler_unblock(self.underline_tggl_handler)
|
||||
self.strikethrough_tggle_btn.handler_unblock(self.strikethrough_tggl_handler)
|
||||
self.fr_check_btn.handler_unblock(self.foreground_tggl_handler)
|
||||
self.br_check_btn.handler_unblock(self.background_tggl_handler)
|
@@ -0,0 +1,107 @@
|
||||
# Python imports
|
||||
import os
|
||||
import tempfile
|
||||
from xml.etree import ElementTree as ET
|
||||
|
||||
# Lib imports
|
||||
|
||||
# Application imports
|
||||
from utils.style_properties import StyleProperties
|
||||
|
||||
|
||||
|
||||
class SourceviewSignalsMixin:
|
||||
def update_sample_view(self):
|
||||
"""
|
||||
Update the sample shown in the GUI.
|
||||
To do this we must write the scheme to disk and reload it from there.
|
||||
"""
|
||||
|
||||
self.write_scheme(self.temp_scheme_file, self.temp_scheme_id)
|
||||
self.scheme_manager.force_rescan()
|
||||
|
||||
new_scheme = self.scheme_manager.get_scheme(self.temp_scheme_id)
|
||||
self.src_buffer.set_style_scheme(new_scheme);
|
||||
|
||||
def load_scheme(self, scheme_id_or_file):
|
||||
xml_tree = None
|
||||
|
||||
if os.path.isfile(scheme_id_or_file):
|
||||
directory = os.path.dirname(scheme_id_or_file)
|
||||
|
||||
if directory not in self.scheme_manager.get_search_path():
|
||||
self.scheme_manager.prepend_search_path(directory)
|
||||
|
||||
with open(scheme_id_or_file, 'r') as f:
|
||||
xml_tree = ET.parse(f)
|
||||
|
||||
if xml_tree.getroot().tag == 'style-scheme':
|
||||
this_scheme = self.scheme_manager.get_scheme( xml_tree.getroot().attrib['id'] )
|
||||
|
||||
if not this_scheme: return False
|
||||
|
||||
testFilename = this_scheme.get_filename()
|
||||
|
||||
if testFilename != scheme_id_or_file:
|
||||
text = '<span weight="bold" size="larger">There was a problem opening the file</span>\n\nYou appear to have schemes with the same IDs in different directories\n'
|
||||
self.message_dialog(Gtk.MessageType.ERROR, text, buttons = Gtk.ButtonsType.NONE, additional_buttons = (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL))
|
||||
return False
|
||||
|
||||
self.orig_scheme_file = scheme_id_or_file
|
||||
else:
|
||||
this_scheme = self.scheme_manager.get_scheme(scheme_id_or_file)
|
||||
if not this_scheme: return False
|
||||
|
||||
self.currentScheme = this_scheme
|
||||
|
||||
self.name_entry.set_text( this_scheme.get_name() )
|
||||
self.authr_entry.set_text( ', '.join( this_scheme.get_authors() ) )
|
||||
self.desc_entry.set_text( this_scheme.get_description() )
|
||||
self.id_entry.set_text( this_scheme.get_id() )
|
||||
|
||||
scheme_file = self.currentScheme.get_filename()
|
||||
with open(scheme_file, 'r') as f:
|
||||
xml_tree = ET.parse(f)
|
||||
|
||||
style_elems = xml_tree.findall('style')
|
||||
self.all_styles_dict.clear()
|
||||
|
||||
for style_elem in style_elems:
|
||||
this_style = self.currentScheme.get_style(style_elem.attrib['name'])
|
||||
styleProps = StyleProperties()
|
||||
styleProps.from_gtk_source_style(this_style)
|
||||
self.all_styles_dict[style_elem.attrib['name']] = styleProps;
|
||||
|
||||
self.src_buffer.set_style_scheme(self.currentScheme);
|
||||
|
||||
# set up temp file so the sample view can be updated
|
||||
self.temp_scheme_id = f"{this_scheme.get_id()}_temp"
|
||||
self.temp_scheme_file = f"{tempfile.gettempdir()}/{self.temp_scheme_id}.xml"
|
||||
|
||||
return True
|
||||
|
||||
def write_scheme(self, location, scheme_id):
|
||||
output = f'<style-scheme name="{self.name_entry.get_text()}" id="{scheme_id}" version="1.0">\n'
|
||||
output += f' <author> {self.authr_entry.get_text()}</author>\n'
|
||||
output += f' <description>{self.desc_entry.get_text()}</description>\n\n'
|
||||
for k, v in self.all_styles_dict.items():
|
||||
output += f' <style name="{k}"\t'
|
||||
|
||||
if (v.foreground): output += f'foreground="{v.foreground}" '
|
||||
if (v.background): output += f'background="{v.background}" '
|
||||
if (v.italic): output += 'italic="true" '
|
||||
if (v.bold): output += 'bold="true" '
|
||||
if (v.underline): output += 'underline="true" '
|
||||
if (v.strikethrough): output += 'strikethrough="true" '
|
||||
|
||||
output += '/>\n'
|
||||
|
||||
output += '</style-scheme>\n'
|
||||
|
||||
with open(location, 'w') as f:
|
||||
try:
|
||||
f.write(output)
|
||||
except:
|
||||
return False
|
||||
|
||||
return True
|
@@ -0,0 +1,47 @@
|
||||
# Python imports
|
||||
|
||||
# Lib imports
|
||||
|
||||
# Application imports
|
||||
|
||||
|
||||
|
||||
class TggleAndCheckBoxSignals:
|
||||
def on_reset_clicked(self, param):
|
||||
if self.selected_style_id in self.all_styles_dict:
|
||||
del self.all_styles_dict[self.selected_style_id]
|
||||
self.clear_and_disable_style_buttons()
|
||||
self.update_sample_view()
|
||||
|
||||
def on_background_toggled(self, param):
|
||||
if param.get_active():
|
||||
self.br_color_btn.set_sensitive(True)
|
||||
self.br_color_btn.activate()
|
||||
else:
|
||||
self.br_color_btn.set_sensitive(False)
|
||||
self.all_styles_dict[self.selected_style_id].background = None;
|
||||
self.update_sample_view()
|
||||
|
||||
def on_foreground_toggled(self, param):
|
||||
if param.get_active():
|
||||
self.fr_color_btn.set_sensitive(True)
|
||||
self.fr_color_btn.activate()
|
||||
else:
|
||||
self.fr_color_btn.set_sensitive(False)
|
||||
self.all_styles_dict[self.selected_style_id].foreground = None;
|
||||
self.update_sample_view()
|
||||
|
||||
def clear_and_disable_style_buttons(self):
|
||||
self.fr_color_btn.set_color(self.black_color)
|
||||
self.br_color_btn.set_color(self.black_color)
|
||||
self.fr_color_btn.set_sensitive(False)
|
||||
self.fr_check_btn.set_active(False)
|
||||
self.br_color_btn.set_sensitive(False)
|
||||
self.br_check_btn.set_active(False)
|
||||
|
||||
self.italic_tggle_btn.set_active(False)
|
||||
self.bold_tggle_btn.set_active(False)
|
||||
self.strikethrough_tggle_btn.set_active(False)
|
||||
self.underline_tggle_btn.set_active(False)
|
||||
|
||||
self.reset_btn.set_sensitive(False)
|
13
src/core/mixins/signals_mixins.py
Normal file
13
src/core/mixins/signals_mixins.py
Normal file
@@ -0,0 +1,13 @@
|
||||
# Python imports
|
||||
|
||||
# Lib imports
|
||||
|
||||
# Application imports
|
||||
from .signals.ipc_signals_mixin import IPCSignalsMixin
|
||||
from .signals.keyboard_signals_mixin import KeyboardSignalsMixin
|
||||
from .signals.main_signals_mixin import MainSignalsMixin
|
||||
|
||||
|
||||
|
||||
class SignalsMixins(KeyboardSignalsMixin, IPCSignalsMixin, MainSignalsMixin):
|
||||
...
|
3
src/core/widgets/__init__.py
Normal file
3
src/core/widgets/__init__.py
Normal file
@@ -0,0 +1,3 @@
|
||||
"""
|
||||
Widgets Module
|
||||
"""
|
3
src/core/widgets/controls/__init__.py
Normal file
3
src/core/widgets/controls/__init__.py
Normal file
@@ -0,0 +1,3 @@
|
||||
"""
|
||||
Widgets.Controls Module
|
||||
"""
|
58
src/core/widgets/controls/open_file_button.py
Normal file
58
src/core/widgets/controls/open_file_button.py
Normal file
@@ -0,0 +1,58 @@
|
||||
# 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 OpenFileButton(Gtk.Button):
|
||||
"""docstring for OpenFileButton."""
|
||||
|
||||
def __init__(self):
|
||||
super(OpenFileButton, 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):
|
||||
chooser = Gtk.FileChooserDialog("Open File...", None,
|
||||
Gtk.FileChooserAction.OPEN,
|
||||
(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,
|
||||
Gtk.STOCK_OPEN, Gtk.ResponseType.OK))
|
||||
|
||||
response = chooser.run()
|
||||
if response == Gtk.ResponseType.OK:
|
||||
filename = chooser.get_filename()
|
||||
if filename:
|
||||
path = filename if os.path.isabs(filename) else os.path.abspath(filename)
|
||||
_gfile = Gio.File.new_for_path(path)
|
||||
event_system.emit("keyboard_open_file", (_gfile,))
|
||||
|
||||
chooser.destroy()
|
39
src/core/widgets/controls/save_as_button.py
Normal file
39
src/core/widgets/controls/save_as_button.py
Normal file
@@ -0,0 +1,39 @@
|
||||
# Python imports
|
||||
|
||||
# Lib imports
|
||||
import gi
|
||||
gi.require_version('Gtk', '3.0')
|
||||
from gi.repository import Gtk
|
||||
|
||||
# Application imports
|
||||
|
||||
|
||||
|
||||
class SaveAsButton(Gtk.Button):
|
||||
def __init__(self):
|
||||
super(SaveAsButton, self).__init__()
|
||||
|
||||
self._setup_styling()
|
||||
self._setup_signals()
|
||||
self._subscribe_to_events()
|
||||
self._load_widgets()
|
||||
|
||||
|
||||
def _setup_styling(self):
|
||||
self.set_label("Save As")
|
||||
self.set_image( Gtk.Image.new_from_icon_name("gtk-save-as", 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("released", self._emit_save_as_eve)
|
||||
|
||||
def _subscribe_to_events(self):
|
||||
...
|
||||
|
||||
def _load_widgets(self):
|
||||
...
|
||||
|
||||
def _emit_save_as_eve(self, widget, eve = None):
|
||||
event_system.emit('keyboard_save_file')
|
67
src/core/widgets/save_file_dialog.py
Normal file
67
src/core/widgets/save_file_dialog.py
Normal file
@@ -0,0 +1,67 @@
|
||||
# Python imports
|
||||
|
||||
# Lib imports
|
||||
import gi
|
||||
gi.require_version('Gtk', '3.0')
|
||||
from gi.repository import Gtk
|
||||
from gi.repository import Gio
|
||||
|
||||
# Application imports
|
||||
|
||||
|
||||
|
||||
class SaveFileDialog:
|
||||
"""docstring for SaveFileDialog."""
|
||||
|
||||
def __init__(self):
|
||||
super(SaveFileDialog, self).__init__()
|
||||
|
||||
self._setup_styling()
|
||||
self._setup_signals()
|
||||
self._subscribe_to_events()
|
||||
self._load_widgets()
|
||||
|
||||
|
||||
def _setup_styling(self):
|
||||
...
|
||||
|
||||
def _setup_signals(self):
|
||||
...
|
||||
|
||||
def _subscribe_to_events(self):
|
||||
event_system.subscribe("save_file_dialog", self.save_file_dialog)
|
||||
|
||||
def _load_widgets(self):
|
||||
self._file_filter_text = Gtk.FileFilter()
|
||||
self._file_filter_text.set_name("XML Files")
|
||||
|
||||
for p in settings.filters.xml:
|
||||
self._file_filter_text.add_pattern(p)
|
||||
|
||||
self._file_filter_all = Gtk.FileFilter()
|
||||
self._file_filter_all.set_name("All Files")
|
||||
self._file_filter_all.add_pattern("*.*")
|
||||
|
||||
|
||||
def save_file_dialog(self, current_filename: str = "", current_file: Gio.File = None) -> str:
|
||||
# TODO: Move Chooser logic to own widget
|
||||
dlg = Gtk.FileChooserDialog(title = "Please choose a file...", parent = None, action = 1)
|
||||
|
||||
dlg.add_buttons("Cancel", Gtk.ResponseType.CANCEL, "Save", Gtk.ResponseType.OK)
|
||||
dlg.set_do_overwrite_confirmation(True)
|
||||
dlg.add_filter(self._file_filter_text)
|
||||
dlg.add_filter(self._file_filter_all)
|
||||
|
||||
if current_filename == "":
|
||||
import os
|
||||
dlg.set_current_name("new.xml")
|
||||
filechooser.set_current_folder(os.path.expanduser('~'))
|
||||
else:
|
||||
dlg.set_current_folder(current_file.get_parent().get_path())
|
||||
dlg.set_current_name(current_filename)
|
||||
|
||||
response = dlg.run()
|
||||
file = dlg.get_filename() if response == Gtk.ResponseType.OK else ""
|
||||
dlg.destroy()
|
||||
|
||||
return Gio.File.new_for_path(file) if not file == "" else None
|
51
src/core/widgets/transparency_scale.py
Normal file
51
src/core/widgets/transparency_scale.py
Normal file
@@ -0,0 +1,51 @@
|
||||
# Python imports
|
||||
|
||||
# Lib imports
|
||||
import gi
|
||||
gi.require_version('Gtk', '3.0')
|
||||
from gi.repository import Gtk
|
||||
|
||||
# Application imports
|
||||
|
||||
|
||||
|
||||
class TransparencyScale(Gtk.Scale):
|
||||
def __init__(self):
|
||||
super(TransparencyScale, self).__init__()
|
||||
|
||||
builder = settings_manager.get_builder()
|
||||
builder.get_object("menu_box").add(self)
|
||||
|
||||
self._setup_styling()
|
||||
self._setup_signals()
|
||||
self._subscribe_to_events()
|
||||
self._load_widgets()
|
||||
|
||||
self.show_all()
|
||||
|
||||
|
||||
def _setup_styling(self):
|
||||
self.set_digits(0)
|
||||
self.set_value_pos(Gtk.PositionType.RIGHT)
|
||||
self.add_mark(0.0, Gtk.PositionType.LEFT, "Transparency")
|
||||
self.add_mark(50.0, Gtk.PositionType.TOP, "50%")
|
||||
self.set_hexpand(True)
|
||||
|
||||
def _setup_signals(self):
|
||||
self.connect("value-changed", self._update_transparency)
|
||||
|
||||
def _subscribe_to_events(self):
|
||||
...
|
||||
|
||||
def _load_widgets(self):
|
||||
adjust = self.get_adjustment()
|
||||
adjust.set_lower(0)
|
||||
adjust.set_upper(99)
|
||||
adjust.set_value(settings.theming.transparency)
|
||||
adjust.set_step_increment(1.0)
|
||||
|
||||
def _update_transparency(self, range):
|
||||
event_system.emit("remove_transparency")
|
||||
tp = int(range.get_value())
|
||||
settings.theming.transparency = tp
|
||||
event_system.emit("update_transparency")
|
121
src/core/window.py
Normal file
121
src/core/window.py
Normal file
@@ -0,0 +1,121 @@
|
||||
# Python imports
|
||||
import signal
|
||||
|
||||
# Lib imports
|
||||
import gi
|
||||
import cairo
|
||||
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 GLib
|
||||
|
||||
# Application imports
|
||||
from core.controller import Controller
|
||||
|
||||
|
||||
class ControllerStartExceptiom(Exception):
|
||||
...
|
||||
|
||||
|
||||
|
||||
|
||||
class Window(Gtk.ApplicationWindow):
|
||||
""" docstring for Window. """
|
||||
|
||||
def __init__(self, args, unknownargs):
|
||||
super(Window, self).__init__()
|
||||
settings_manager.set_main_window(self)
|
||||
|
||||
self._controller = None
|
||||
|
||||
self._set_window_data()
|
||||
self._setup_styling()
|
||||
self._setup_signals()
|
||||
self._subscribe_to_events()
|
||||
self._load_widgets(args, unknownargs)
|
||||
|
||||
self._set_size_constraints()
|
||||
self.show()
|
||||
|
||||
|
||||
def _setup_styling(self):
|
||||
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
|
||||
|
||||
ctx = self.get_style_context()
|
||||
ctx.add_class("main-window")
|
||||
ctx.add_class(f"mw_transparency_{settings.theming.transparency}")
|
||||
|
||||
def _setup_signals(self):
|
||||
GLib.unix_signal_add(GLib.PRIORITY_DEFAULT, signal.SIGINT, self._tear_down)
|
||||
self.connect("delete-event", 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)
|
||||
|
||||
def _load_widgets(self, args, unknownargs):
|
||||
if settings_manager.is_debug():
|
||||
self.set_interactive_debugging(True)
|
||||
|
||||
self._controller = Controller(args, unknownargs)
|
||||
if not self._controller:
|
||||
raise ControllerStartException("Controller exited and doesn't exist...")
|
||||
|
||||
self.add( self._controller.get_base_container() )
|
||||
|
||||
def _set_size_constraints(self):
|
||||
_window_x = settings.config.main_window_x
|
||||
_window_y = settings.config.main_window_y
|
||||
_min_width = settings.config.main_window_min_width
|
||||
_min_height = settings.config.main_window_min_height
|
||||
_width = settings.config.main_window_width
|
||||
_height = settings.config.main_window_height
|
||||
|
||||
self.move(_window_x, _window_y - 28)
|
||||
self.set_size_request(_min_width, _min_height)
|
||||
self.set_default_size(_width, _height)
|
||||
|
||||
def _set_window_data(self) -> None:
|
||||
screen = self.get_screen()
|
||||
visual = screen.get_rgba_visual()
|
||||
|
||||
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)
|
||||
|
||||
# bind css file
|
||||
cssProvider = Gtk.CssProvider()
|
||||
cssProvider.load_from_path( settings_manager.get_css_file() )
|
||||
screen = Gdk.Screen.get_default()
|
||||
styleContext = Gtk.StyleContext()
|
||||
styleContext.add_provider_for_screen(screen, cssProvider, Gtk.STYLE_PROVIDER_PRIORITY_USER)
|
||||
|
||||
def _area_draw(self, widget: Gtk.ApplicationWindow, cr: cairo.Context) -> None:
|
||||
cr.set_source_rgba( *settings_manager.get_paint_bg_color() )
|
||||
cr.set_operator(cairo.OPERATOR_SOURCE)
|
||||
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")
|
||||
|
||||
size = self.get_default_size()
|
||||
pos = self.get_position()
|
||||
|
||||
settings_manager.set_main_window_width(size.width)
|
||||
settings_manager.set_main_window_height(size.height)
|
||||
settings_manager.set_main_window_x(pos.root_x)
|
||||
settings_manager.set_main_window_y(pos.root_y)
|
||||
settings_manager.save_settings()
|
||||
|
||||
settings_manager.clear_pid()
|
||||
Gtk.main_quit()
|
Reference in New Issue
Block a user