generated from itdominator/Python-With-Gtk-Template
Added more keyboard events, slight refactoring, ui changes, etc
This commit is contained in:
parent
1268449824
commit
3088aa8c44
|
@ -32,7 +32,9 @@ if __name__ == "__main__":
|
||||||
# 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("--file", "-f", default="default", help="JUST SOME FILE ARG.")
|
parser.add_argument("--no-plugins", "-np", default="false", help="Do not load plugins.")
|
||||||
|
parser.add_argument("--new-tab", "-t", default="", help="Open a file into new tab.")
|
||||||
|
parser.add_argument("--new-window", "-w", default="", help="Open a file into a new window.")
|
||||||
|
|
||||||
# Read arguments (If any...)
|
# Read arguments (If any...)
|
||||||
args, unknownargs = parser.parse_known_args()
|
args, unknownargs = parser.parse_known_args()
|
||||||
|
|
|
@ -26,7 +26,7 @@ class Application(IPCServer):
|
||||||
|
|
||||||
if not self.is_ipc_alive:
|
if not self.is_ipc_alive:
|
||||||
for arg in unknownargs + [args.new_tab,]:
|
for arg in unknownargs + [args.new_tab,]:
|
||||||
if os.path.isdir(arg):
|
if os.path.isfile(arg):
|
||||||
message = f"FILE|{arg}"
|
message = f"FILE|{arg}"
|
||||||
self.send_ipc_message(message)
|
self.send_ipc_message(message)
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
# Python imports
|
# Python imports
|
||||||
|
import os
|
||||||
|
|
||||||
# Lib imports
|
# Lib imports
|
||||||
import gi
|
import gi
|
||||||
|
@ -23,6 +24,14 @@ class Controller(SignalsMixins, ControllerData):
|
||||||
self._setup_signals()
|
self._setup_signals()
|
||||||
self._subscribe_to_events()
|
self._subscribe_to_events()
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
|
||||||
def _setup_styling(self):
|
def _setup_styling(self):
|
||||||
...
|
...
|
||||||
|
|
|
@ -7,8 +7,8 @@ from gi.repository import Gtk
|
||||||
|
|
||||||
# Application imports
|
# Application imports
|
||||||
from .widgets.base.banner_controls import BannerControls
|
from .widgets.base.banner_controls import BannerControls
|
||||||
from .widgets.base.notebook.editor_notebook import EditorNotebook
|
from .editors_container import EditorsContainer
|
||||||
from .widgets.base.bottom_status_info_widget import BottomStatusInfoWidget
|
from .widgets.base.general_info_widget import GeneralInfoWidget
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -34,6 +34,5 @@ class CoreWidget(Gtk.Box):
|
||||||
|
|
||||||
def _load_widgets(self):
|
def _load_widgets(self):
|
||||||
self.add(BannerControls())
|
self.add(BannerControls())
|
||||||
self.add(EditorNotebook())
|
GeneralInfoWidget()
|
||||||
|
self.add(EditorsContainer())
|
||||||
BottomStatusInfoWidget()
|
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
# Python imports
|
||||||
|
|
||||||
|
# Lib imports
|
||||||
|
import gi
|
||||||
|
gi.require_version('Gtk', '3.0')
|
||||||
|
from gi.repository import Gtk
|
||||||
|
|
||||||
|
# Application imports
|
||||||
|
from .widgets.base.notebook.editor_notebook import EditorNotebook
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class EditorsContainer(Gtk.Paned):
|
||||||
|
def __init__(self):
|
||||||
|
super(EditorsContainer, self).__init__()
|
||||||
|
|
||||||
|
self._setup_styling()
|
||||||
|
self._setup_signals()
|
||||||
|
self._subscribe_to_events()
|
||||||
|
self._load_widgets()
|
||||||
|
|
||||||
|
self.show()
|
||||||
|
|
||||||
|
|
||||||
|
def _setup_styling(self):
|
||||||
|
self.set_wide_handle(True)
|
||||||
|
self.set_vexpand(True)
|
||||||
|
|
||||||
|
def _setup_signals(self):
|
||||||
|
...
|
||||||
|
|
||||||
|
def _subscribe_to_events(self):
|
||||||
|
...
|
||||||
|
|
||||||
|
def _load_widgets(self):
|
||||||
|
self.add1(EditorNotebook())
|
||||||
|
self.add2(EditorNotebook())
|
|
@ -6,12 +6,12 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class IPCSignalsMixin:
|
class IPCSignalsMixin:
|
||||||
""" IPCSignalsMixin handle messages from another starting solarfm process. """
|
""" IPCSignalsMixin handle messages from another starting solarfm process. """
|
||||||
|
|
||||||
def print_to_console(self, message=None):
|
def print_to_console(self, message=None):
|
||||||
print(message)
|
print(message)
|
||||||
|
|
||||||
def handle_file_from_ipc(self, path: str) -> None:
|
def handle_file_from_ipc(self, path: any) -> None:
|
||||||
print(f"Path From IPC: {path}")
|
logger.debug(f"Path From IPC: {path}")
|
||||||
|
event_system.emit("create_view", (path,))
|
||||||
|
|
|
@ -12,13 +12,13 @@ from gi.repository import Gio
|
||||||
# NOTE: https://github.com/rwaldron/gtksourceview/blob/master/tests/test-widget.py
|
# NOTE: https://github.com/rwaldron/gtksourceview/blob/master/tests/test-widget.py
|
||||||
|
|
||||||
|
|
||||||
class BottomStatusInfoWidget:
|
class GeneralInfoWidget:
|
||||||
"""docstring for BottomStatusInfoWidget."""
|
""" docstring for StatusInfoWidget. """
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super(BottomStatusInfoWidget, self).__init__()
|
super(GeneralInfoWidget, self).__init__()
|
||||||
|
|
||||||
_GLADE_FILE = f"{settings.get_ui_widgets_path()}/bottom_status_info_ui.glade"
|
_GLADE_FILE = f"{settings.get_ui_widgets_path()}/general_info_ui.glade"
|
||||||
self._builder = Gtk.Builder()
|
self._builder = Gtk.Builder()
|
||||||
self._builder.add_from_file(_GLADE_FILE)
|
self._builder.add_from_file(_GLADE_FILE)
|
||||||
|
|
||||||
|
@ -45,11 +45,11 @@ class BottomStatusInfoWidget:
|
||||||
def _load_widgets(self):
|
def _load_widgets(self):
|
||||||
builder = settings.get_builder()
|
builder = settings.get_builder()
|
||||||
|
|
||||||
self.bottom_status_info = self._builder.get_object("bottom_status_info")
|
self.bottom_status_info = self._builder.get_object("general_info")
|
||||||
self.bottom_path_label = self._builder.get_object("bottom_path_label")
|
self.bottom_path_label = self._builder.get_object("path_label")
|
||||||
self.bottom_encoding_label = self._builder.get_object("bottom_encoding_label")
|
self.bottom_encoding_label = self._builder.get_object("encoding_label")
|
||||||
self.bottom_line_char_label = self._builder.get_object("bottom_line_char_label")
|
self.bottom_line_char_label = self._builder.get_object("line_char_label")
|
||||||
self.bottom_file_type_label = self._builder.get_object("bottom_file_type_label")
|
self.bottom_file_type_label = self._builder.get_object("file_type_label")
|
||||||
|
|
||||||
builder.expose_object(f"bottom_status_info", self.bottom_status_info)
|
builder.expose_object(f"bottom_status_info", self.bottom_status_info)
|
||||||
builder.expose_object(f"bottom_path_label", self.bottom_path_label)
|
builder.expose_object(f"bottom_path_label", self.bottom_path_label)
|
||||||
|
@ -63,22 +63,25 @@ class BottomStatusInfoWidget:
|
||||||
builder.get_object("core_widget").add(self.bottom_status_info)
|
builder.get_object("core_widget").add(self.bottom_status_info)
|
||||||
|
|
||||||
|
|
||||||
def set_bottom_labels(self, gfile, info):
|
def set_bottom_labels(self, path = None, line_char = None, file_type = None, encoding_type = None):
|
||||||
|
self._set_path_label(path)
|
||||||
|
self._set_line_char_label()
|
||||||
|
self._set_file_type_label(file_type)
|
||||||
|
self._set_encoding_label()
|
||||||
|
|
||||||
|
def _set_path_label(self, gfile = ""):
|
||||||
|
if isinstance(gfile, str):
|
||||||
|
self.bottom_path_label.set_text( gfile )
|
||||||
|
self.bottom_path_label.set_tooltip_text( gfile )
|
||||||
|
else:
|
||||||
self.bottom_path_label.set_text( gfile.get_path() )
|
self.bottom_path_label.set_text( gfile.get_path() )
|
||||||
self.bottom_path_label.set_tooltip_text( gfile.get_path() )
|
self.bottom_path_label.set_tooltip_text( gfile.get_path() )
|
||||||
|
|
||||||
self.bottom_encoding_label.set_text("utf-8")
|
def _set_line_char_label(self, line_char = "1:1"):
|
||||||
self.bottom_line_char_label.set_text("1:1")
|
self.bottom_line_char_label.set_text(line_char)
|
||||||
self.bottom_file_type_label.set_text( info.get_content_type() )
|
|
||||||
|
|
||||||
def _set_path_label(self):
|
def _set_file_type_label(self, file_type = "buffer"):
|
||||||
...
|
self.bottom_file_type_label.set_text(file_type)
|
||||||
|
|
||||||
def _set_encoding_label(self):
|
def _set_encoding_label(self, encoding_type = "utf-8"):
|
||||||
...
|
self.bottom_encoding_label.set_text(encoding_type)
|
||||||
|
|
||||||
def _set_line_char_label(self, label = "0:0"):
|
|
||||||
self.bottom_line_char_label.set_text(label)
|
|
||||||
|
|
||||||
def _set_file_type_label(self):
|
|
||||||
...
|
|
|
@ -7,11 +7,18 @@
|
||||||
|
|
||||||
|
|
||||||
class EditorControllerMixin:
|
class EditorControllerMixin:
|
||||||
def action_controller(self, action = "", query = ""):
|
def get_active_view(self):
|
||||||
page_num = self.get_current_page()
|
page_num = self.get_current_page()
|
||||||
container = self.get_nth_page( page_num )
|
container = self.get_nth_page( page_num )
|
||||||
source_view = container.get_source_view()
|
source_view = container.get_source_view()
|
||||||
|
return page_num, container, source_view
|
||||||
|
|
||||||
|
def action_controller(self, action = "", query = ""):
|
||||||
|
# NOTE: Not efficent here as multiple same calls
|
||||||
|
if not self.is_editor_focused: # TODO: Find way to converge this
|
||||||
|
return
|
||||||
|
|
||||||
|
page_num, container, source_view = self.get_active_view()
|
||||||
if action == "do_text_search":
|
if action == "do_text_search":
|
||||||
self.do_text_search(source_view, query)
|
self.do_text_search(source_view, query)
|
||||||
if action == "set_buffer_language":
|
if action == "set_buffer_language":
|
||||||
|
@ -30,6 +37,14 @@ class EditorControllerMixin:
|
||||||
self.keyboard_prev_tab(page_num)
|
self.keyboard_prev_tab(page_num)
|
||||||
if action == "keyboard_next_tab":
|
if action == "keyboard_next_tab":
|
||||||
self.keyboard_next_tab(page_num)
|
self.keyboard_next_tab(page_num)
|
||||||
|
if action == "keyboard_move_tab_left":
|
||||||
|
self.keyboard_move_tab_left(page_num)
|
||||||
|
if action == "keyboard_move_tab_right":
|
||||||
|
self.keyboard_move_tab_right(page_num)
|
||||||
|
if action == "keyboard_move_tab_to_1":
|
||||||
|
self.keyboard_move_tab_to_1(page_num)
|
||||||
|
if action == "keyboard_move_tab_to_2":
|
||||||
|
self.keyboard_move_tab_to_2(page_num)
|
||||||
if action == "save_file":
|
if action == "save_file":
|
||||||
source_view.save_file()
|
source_view.save_file()
|
||||||
if action == "save_file_as":
|
if action == "save_file_as":
|
||||||
|
|
|
@ -3,42 +3,49 @@
|
||||||
# Lib imports
|
# Lib imports
|
||||||
|
|
||||||
# Application imports
|
# Application imports
|
||||||
|
from ..sourceview_container import SourceViewContainer
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class EditorEventsMixin:
|
class EditorEventsMixin:
|
||||||
def _toggle_highlight_line(self):
|
def create_view(self, widget = None, eve = None, gfile = None):
|
||||||
self.action_controller("toggle_highlight_line")
|
container = SourceViewContainer(self.close_tab)
|
||||||
|
|
||||||
def _keyboard_close_tab(self):
|
page_num = self.append_page(container, container.get_tab_widget())
|
||||||
self.action_controller("close_tab")
|
self.set_tab_detachable(container, True)
|
||||||
|
|
||||||
def _keyboard_open_file(self, gfile):
|
ctx = self.get_style_context()
|
||||||
self.open_file(gfile)
|
ctx.add_class("notebook-unselected-focus")
|
||||||
|
self.set_tab_reorderable(container, True)
|
||||||
|
|
||||||
def _keyboard_create_tab(self, _gfile=None):
|
if gfile:
|
||||||
self.create_view(gfile=_gfile)
|
source_view = container.get_source_view()
|
||||||
|
source_view.open_file(gfile)
|
||||||
|
|
||||||
def _keyboard_next_tab(self):
|
self.show_all()
|
||||||
self.action_controller("keyboard_next_tab")
|
self.set_current_page(page_num)
|
||||||
|
|
||||||
def _keyboard_prev_tab(self):
|
def open_file(self, gfile):
|
||||||
self.action_controller("keyboard_prev_tab")
|
page_num = self.get_current_page()
|
||||||
|
container = self.get_nth_page( page_num )
|
||||||
|
source_view = container.get_source_view()
|
||||||
|
|
||||||
def _keyboard_scale_up_text(self):
|
if source_view._current_filename == "":
|
||||||
self.action_controller("scale_up_text")
|
source_view.open_file(gfile)
|
||||||
|
else:
|
||||||
|
self.create_view(None, None, gfile)
|
||||||
|
|
||||||
def _keyboard_scale_down_text(self):
|
def close_tab(self, button, container, source_view, eve = None):
|
||||||
self.action_controller("scale_down_text")
|
if self.NAME == "notebook_1" and self.get_n_pages() == 1:
|
||||||
|
return
|
||||||
|
|
||||||
def _keyboard_save_file(self):
|
page_num = self.page_num(container)
|
||||||
self.action_controller("save_file")
|
source_view._cancel_current_file_watchers()
|
||||||
|
self.remove_page(page_num)
|
||||||
|
|
||||||
def _keyboard_save_file_as(self):
|
if self.NAME == "notebook_2" and self.get_n_pages() == 0:
|
||||||
self.action_controller("save_file_as")
|
self.hide()
|
||||||
|
|
||||||
def _text_search(self, widget = None, eve = None):
|
|
||||||
self.action_controller("do_text_search", widget.get_text())
|
|
||||||
|
|
||||||
def do_text_search(self, query = ""):
|
def do_text_search(self, query = ""):
|
||||||
source_view.scale_down_text()
|
source_view.scale_down_text()
|
||||||
|
@ -57,6 +64,48 @@ class EditorEventsMixin:
|
||||||
page_num = 0 if self.get_n_pages() - 1 == page_num else page_num + 1
|
page_num = 0 if self.get_n_pages() - 1 == page_num else page_num + 1
|
||||||
self.set_current_page(page_num)
|
self.set_current_page(page_num)
|
||||||
|
|
||||||
|
def keyboard_move_tab_to_1(self, page_num):
|
||||||
|
notebook = self.builder.get_object("notebook_1")
|
||||||
|
if self.NAME == "notebook_1":
|
||||||
|
if self.get_n_pages() == 1:
|
||||||
|
return
|
||||||
|
|
||||||
|
notebook = self.builder.get_object("notebook_2")
|
||||||
|
|
||||||
|
page = self.get_nth_page(page_num)
|
||||||
|
tab = page.get_tab_widget()
|
||||||
|
self.detach_tab(page)
|
||||||
|
|
||||||
|
notebook.insert_page(page, tab, -1)
|
||||||
|
notebook.show()
|
||||||
|
|
||||||
|
def keyboard_move_tab_to_2(self, page_num):
|
||||||
|
if self.NAME == "notebook_1" and self.get_n_pages() == 1:
|
||||||
|
return
|
||||||
|
|
||||||
|
notebook = self.builder.get_object("notebook_2")
|
||||||
|
if self.NAME == "notebook_2":
|
||||||
|
notebook = self.builder.get_object("notebook_1")
|
||||||
|
|
||||||
|
page = self.get_nth_page(page_num)
|
||||||
|
tab = page.get_tab_widget()
|
||||||
|
self.detach_tab(page)
|
||||||
|
|
||||||
|
notebook.insert_page(page, tab, -1)
|
||||||
|
notebook.show()
|
||||||
|
if self.NAME == "notebook_2" and self.get_n_pages() == 0:
|
||||||
|
self.hide()
|
||||||
|
|
||||||
|
def keyboard_move_tab_left(self, page_num):
|
||||||
|
page = self.get_nth_page(page_num)
|
||||||
|
page_num = self.get_n_pages() - 1 if page_num == 0 else page_num - 1
|
||||||
|
self.reorder_child(page, page_num)
|
||||||
|
|
||||||
|
def keyboard_move_tab_right(self, page_num):
|
||||||
|
page = self.get_nth_page(page_num)
|
||||||
|
page_num = 0 if self.get_n_pages() - 1 == page_num else page_num + 1
|
||||||
|
self.reorder_child(page, page_num)
|
||||||
|
|
||||||
def scale_up_text(self, source_view):
|
def scale_up_text(self, source_view):
|
||||||
source_view.scale_up_text()
|
source_view.scale_up_text()
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,6 @@ from gi.repository import Gdk
|
||||||
from gi.repository import Gio
|
from gi.repository import Gio
|
||||||
|
|
||||||
# Application imports
|
# Application imports
|
||||||
from ..sourceview_container import SourceViewContainer
|
|
||||||
from .editor_controller import EditorControllerMixin
|
from .editor_controller import EditorControllerMixin
|
||||||
from .editor_events import EditorEventsMixin
|
from .editor_events import EditorEventsMixin
|
||||||
|
|
||||||
|
@ -18,10 +17,23 @@ from .editor_events import EditorEventsMixin
|
||||||
# NOTE: https://github.com/Axel-Erfurt/TextEdit/tree/b65f09be945196eb05bef83d81a6abcd129b4eb0
|
# NOTE: https://github.com/Axel-Erfurt/TextEdit/tree/b65f09be945196eb05bef83d81a6abcd129b4eb0
|
||||||
|
|
||||||
class EditorNotebook(EditorEventsMixin, EditorControllerMixin, Gtk.Notebook):
|
class EditorNotebook(EditorEventsMixin, EditorControllerMixin, Gtk.Notebook):
|
||||||
|
ccount = 0
|
||||||
|
|
||||||
|
def __new__(cls, *args, **kwargs):
|
||||||
|
obj = super(EditorNotebook, cls).__new__(cls)
|
||||||
|
cls.ccount += 1
|
||||||
|
|
||||||
|
return obj
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super(EditorNotebook, self).__init__()
|
super(EditorNotebook, self).__init__()
|
||||||
|
|
||||||
|
self.NAME = f"notebook_{self.ccount}"
|
||||||
|
self.is_editor_focused = False
|
||||||
self.set_group_name("editor_widget")
|
self.set_group_name("editor_widget")
|
||||||
|
self.builder = settings.get_builder()
|
||||||
|
|
||||||
|
self.builder.expose_object(self.NAME, self)
|
||||||
|
|
||||||
self._add_action_widgets()
|
self._add_action_widgets()
|
||||||
self._setup_styling()
|
self._setup_styling()
|
||||||
|
@ -31,6 +43,10 @@ class EditorNotebook(EditorEventsMixin, EditorControllerMixin, Gtk.Notebook):
|
||||||
|
|
||||||
self.show_all()
|
self.show_all()
|
||||||
|
|
||||||
|
print(self.NAME)
|
||||||
|
if self.NAME == "notebook_2":
|
||||||
|
self.hide()
|
||||||
|
|
||||||
|
|
||||||
def _setup_styling(self):
|
def _setup_styling(self):
|
||||||
self.set_scrollable(True)
|
self.set_scrollable(True)
|
||||||
|
@ -42,7 +58,7 @@ class EditorNotebook(EditorEventsMixin, EditorControllerMixin, Gtk.Notebook):
|
||||||
|
|
||||||
def _subscribe_to_events(self):
|
def _subscribe_to_events(self):
|
||||||
# event_system.subscribe("set_buffer_language", self.action_controller, *("set_buffer_language",))
|
# event_system.subscribe("set_buffer_language", self.action_controller, *("set_buffer_language",))
|
||||||
event_system.subscribe("create_view", self.create_view)
|
event_system.subscribe("create_view", self._create_view)
|
||||||
event_system.subscribe("set_buffer_style", self.action_controller)
|
event_system.subscribe("set_buffer_style", self.action_controller)
|
||||||
event_system.subscribe("set_buffer_language", self.action_controller)
|
event_system.subscribe("set_buffer_language", self.action_controller)
|
||||||
event_system.subscribe("set_buffer_style", self.action_controller)
|
event_system.subscribe("set_buffer_style", self.action_controller)
|
||||||
|
@ -52,10 +68,19 @@ class EditorNotebook(EditorEventsMixin, EditorControllerMixin, Gtk.Notebook):
|
||||||
event_system.subscribe("keyboard_close_tab", self._keyboard_close_tab)
|
event_system.subscribe("keyboard_close_tab", self._keyboard_close_tab)
|
||||||
event_system.subscribe("keyboard_prev_tab", self._keyboard_prev_tab)
|
event_system.subscribe("keyboard_prev_tab", self._keyboard_prev_tab)
|
||||||
event_system.subscribe("keyboard_next_tab", self._keyboard_next_tab)
|
event_system.subscribe("keyboard_next_tab", self._keyboard_next_tab)
|
||||||
|
event_system.subscribe("keyboard_move_tab_left", self._keyboard_move_tab_left)
|
||||||
|
event_system.subscribe("keyboard_move_tab_right", self._keyboard_move_tab_right)
|
||||||
|
event_system.subscribe("keyboard_move_tab_to_1", self._keyboard_move_tab_to_1)
|
||||||
|
event_system.subscribe("keyboard_move_tab_to_2", self._keyboard_move_tab_to_2)
|
||||||
event_system.subscribe("keyboard_scale_up_text", self._keyboard_scale_up_text)
|
event_system.subscribe("keyboard_scale_up_text", self._keyboard_scale_up_text)
|
||||||
event_system.subscribe("keyboard_scale_down_text", self._keyboard_scale_down_text)
|
event_system.subscribe("keyboard_scale_down_text", self._keyboard_scale_down_text)
|
||||||
event_system.subscribe("keyboard_save_file", self._keyboard_save_file)
|
event_system.subscribe("keyboard_save_file", self._keyboard_save_file)
|
||||||
event_system.subscribe("keyboard_save_file_as", self._keyboard_save_file_as)
|
event_system.subscribe("keyboard_save_file_as", self._keyboard_save_file_as)
|
||||||
|
event_system.subscribe("focused_target_changed", self._focused_target_changed)
|
||||||
|
|
||||||
|
|
||||||
|
def _focused_target_changed(self, target):
|
||||||
|
self.is_editor_focused = True if target == self.NAME else False
|
||||||
|
|
||||||
def _add_action_widgets(self):
|
def _add_action_widgets(self):
|
||||||
start_box = Gtk.Box()
|
start_box = Gtk.Box()
|
||||||
|
@ -81,6 +106,7 @@ class EditorNotebook(EditorEventsMixin, EditorControllerMixin, Gtk.Notebook):
|
||||||
self.set_action_widget(end_box, 1)
|
self.set_action_widget(end_box, 1)
|
||||||
|
|
||||||
def _load_widgets(self):
|
def _load_widgets(self):
|
||||||
|
if self.NAME == "notebook_1":
|
||||||
self.create_view()
|
self.create_view()
|
||||||
|
|
||||||
def _dbl_click_create_view(self, notebook, eve):
|
def _dbl_click_create_view(self, notebook, eve):
|
||||||
|
@ -93,38 +119,67 @@ class EditorNotebook(EditorEventsMixin, EditorControllerMixin, Gtk.Notebook):
|
||||||
if gfile:
|
if gfile:
|
||||||
source_view.load_file_info( gfile )
|
source_view.load_file_info( gfile )
|
||||||
source_view.update_cursor_position()
|
source_view.update_cursor_position()
|
||||||
|
|
||||||
def create_view(self, widget = None, eve = None, gfile = None):
|
|
||||||
container = SourceViewContainer(self.close_tab)
|
|
||||||
|
|
||||||
index = self.append_page(container, container.get_tab_widget())
|
|
||||||
self.set_tab_detachable(container, True)
|
|
||||||
|
|
||||||
ctx = self.get_style_context()
|
|
||||||
ctx.add_class("notebook-unselected-focus")
|
|
||||||
self.set_tab_reorderable(container, True)
|
|
||||||
|
|
||||||
if gfile:
|
|
||||||
source_view = container.get_source_view()
|
|
||||||
source_view.open_file(gfile)
|
|
||||||
|
|
||||||
self.show_all()
|
|
||||||
self.set_current_page(index)
|
|
||||||
|
|
||||||
def open_file(self, gfile):
|
|
||||||
page_num = self.get_current_page()
|
|
||||||
container = self.get_nth_page( page_num )
|
|
||||||
source_view = container.get_source_view()
|
|
||||||
|
|
||||||
if source_view._current_filename == "":
|
|
||||||
source_view.open_file(gfile)
|
|
||||||
else:
|
else:
|
||||||
self.create_view(None, None, gfile)
|
event_system.emit("set_path_label", ("",))
|
||||||
|
event_system.emit("set_file_type_label", (source_view._current_filetype,))
|
||||||
|
|
||||||
def close_tab(self, button, container, source_view, eve = None):
|
def _create_view(self, gfile = None):
|
||||||
if self.get_n_pages() == 1:
|
if not self.is_editor_focused: # TODO: Find way to converge this
|
||||||
return
|
return
|
||||||
|
|
||||||
page_num = self.page_num(container)
|
if isinstance(gfile, str):
|
||||||
source_view._cancel_current_file_watchers()
|
gfile = Gio.File.new_for_path(gfile)
|
||||||
self.remove_page(page_num)
|
|
||||||
|
self.create_view(None, None, gfile,)
|
||||||
|
|
||||||
|
def _keyboard_open_file(self, gfile):
|
||||||
|
if not self.is_editor_focused: # TODO: Find way to converge this
|
||||||
|
return
|
||||||
|
|
||||||
|
self.open_file(gfile)
|
||||||
|
|
||||||
|
def _keyboard_create_tab(self, _gfile=None):
|
||||||
|
if not self.is_editor_focused: # TODO: Find way to converge this
|
||||||
|
return
|
||||||
|
|
||||||
|
self.create_view(gfile=_gfile)
|
||||||
|
|
||||||
|
|
||||||
|
def _keyboard_close_tab(self):
|
||||||
|
self.action_controller("close_tab")
|
||||||
|
|
||||||
|
def _toggle_highlight_line(self):
|
||||||
|
self.action_controller("toggle_highlight_line")
|
||||||
|
|
||||||
|
def _keyboard_next_tab(self):
|
||||||
|
self.action_controller("keyboard_next_tab")
|
||||||
|
|
||||||
|
def _keyboard_move_tab_left(self):
|
||||||
|
self.action_controller("keyboard_move_tab_left")
|
||||||
|
|
||||||
|
def _keyboard_move_tab_right(self):
|
||||||
|
self.action_controller("keyboard_move_tab_right")
|
||||||
|
|
||||||
|
def _keyboard_move_tab_to_1(self):
|
||||||
|
self.action_controller("keyboard_move_tab_to_1")
|
||||||
|
|
||||||
|
def _keyboard_move_tab_to_2(self):
|
||||||
|
self.action_controller("keyboard_move_tab_to_2")
|
||||||
|
|
||||||
|
def _keyboard_prev_tab(self):
|
||||||
|
self.action_controller("keyboard_prev_tab")
|
||||||
|
|
||||||
|
def _keyboard_scale_up_text(self):
|
||||||
|
self.action_controller("scale_up_text")
|
||||||
|
|
||||||
|
def _keyboard_scale_down_text(self):
|
||||||
|
self.action_controller("scale_down_text")
|
||||||
|
|
||||||
|
def _keyboard_save_file(self):
|
||||||
|
self.action_controller("save_file")
|
||||||
|
|
||||||
|
def _keyboard_save_file_as(self):
|
||||||
|
self.action_controller("save_file_as")
|
||||||
|
|
||||||
|
def _text_search(self, widget = None, eve = None):
|
||||||
|
self.action_controller("do_text_search", widget.get_text())
|
||||||
|
|
|
@ -25,15 +25,18 @@ class SourceView(SourceViewEventsMixin, GtkSource.View):
|
||||||
self._style_scheme_manager = GtkSource.StyleSchemeManager()
|
self._style_scheme_manager = GtkSource.StyleSchemeManager()
|
||||||
|
|
||||||
self._general_style_tag = None
|
self._general_style_tag = None
|
||||||
|
self._file_loader = None
|
||||||
self._file_change_watcher = None
|
self._file_change_watcher = None
|
||||||
self._file_cdr_watcher = None
|
self._file_cdr_watcher = None
|
||||||
|
self._last_eve_in_queue = None
|
||||||
|
self._current_file: Gio.File = None
|
||||||
|
|
||||||
|
self._current_filename: str = ""
|
||||||
|
self._current_filepath: str = None
|
||||||
|
self._current_filetype: str = "buffer"
|
||||||
|
|
||||||
self._is_changed = False
|
self._is_changed = False
|
||||||
self._ignore_internal_change = False
|
self._ignore_internal_change = False
|
||||||
self._last_eve_in_queue = None
|
|
||||||
self._current_file: Gio.File = None
|
|
||||||
self._current_filename: str = ""
|
|
||||||
self._file_loader = None
|
|
||||||
self._buffer = self.get_buffer()
|
self._buffer = self.get_buffer()
|
||||||
self._completion = self.get_completion()
|
self._completion = self.get_completion()
|
||||||
|
|
||||||
|
@ -48,7 +51,6 @@ class SourceView(SourceViewEventsMixin, GtkSource.View):
|
||||||
self._file_filter_all.set_name("All Files")
|
self._file_filter_all.set_name("All Files")
|
||||||
self._file_filter_all.add_pattern("*.*")
|
self._file_filter_all.add_pattern("*.*")
|
||||||
|
|
||||||
|
|
||||||
self._setup_styling()
|
self._setup_styling()
|
||||||
self._setup_signals()
|
self._setup_signals()
|
||||||
self._set_up_dnd()
|
self._set_up_dnd()
|
||||||
|
@ -108,13 +110,38 @@ class SourceView(SourceViewEventsMixin, GtkSource.View):
|
||||||
self._general_style_tag.set_property('size', 100)
|
self._general_style_tag.set_property('size', 100)
|
||||||
self._general_style_tag.set_property('scale', 100)
|
self._general_style_tag.set_property('scale', 100)
|
||||||
|
|
||||||
|
def _is_modified(self, *args):
|
||||||
|
self._is_changed = True
|
||||||
|
self.update_cursor_position()
|
||||||
|
|
||||||
|
def _on_cursor_move(self, buf, cursor_iter, mark, user_data = None):
|
||||||
|
if mark != buf.get_insert(): return
|
||||||
|
|
||||||
|
target = self.get_parent().get_parent().NAME
|
||||||
|
path = self._current_file if self._current_file else ""
|
||||||
|
|
||||||
|
event_system.emit('focused_target_changed', (target,))
|
||||||
|
event_system.emit("set_path_label", (path,))
|
||||||
|
event_system.emit("set_encoding_label")
|
||||||
|
event_system.emit("set_file_type_label", (self._current_filetype,))
|
||||||
|
self.update_cursor_position()
|
||||||
|
|
||||||
def _set_up_dnd(self):
|
def _set_up_dnd(self):
|
||||||
|
WIDGET_TARGET_TYPE = 70
|
||||||
URI_TARGET_TYPE = 80
|
URI_TARGET_TYPE = 80
|
||||||
|
widget_target = Gtk.TargetEntry.new('dummy', Gtk.TargetFlags(0), WIDGET_TARGET_TYPE)
|
||||||
uri_target = Gtk.TargetEntry.new('text/uri-list', Gtk.TargetFlags(0), URI_TARGET_TYPE)
|
uri_target = Gtk.TargetEntry.new('text/uri-list', Gtk.TargetFlags(0), URI_TARGET_TYPE)
|
||||||
targets = [ uri_target ]
|
targets = [ widget_target, uri_target ]
|
||||||
self.drag_dest_set_target_list(targets)
|
self.drag_dest_set_target_list(targets)
|
||||||
|
|
||||||
def _on_drag_data_received(self, widget, drag_context, x, y, data, info, time):
|
def _on_drag_data_received(self, widget, drag_context, x, y, data, info, time):
|
||||||
|
if info == 70:
|
||||||
|
print(drag_context)
|
||||||
|
print(data)
|
||||||
|
print(info)
|
||||||
|
# detach_tab(child)
|
||||||
|
return
|
||||||
|
|
||||||
if info == 80:
|
if info == 80:
|
||||||
uris = data.get_uris()
|
uris = data.get_uris()
|
||||||
|
|
||||||
|
@ -141,14 +168,6 @@ class SourceView(SourceViewEventsMixin, GtkSource.View):
|
||||||
|
|
||||||
event_system.emit('create_view', (None, None, gfile,))
|
event_system.emit('create_view', (None, None, gfile,))
|
||||||
|
|
||||||
def _is_modified(self, *args):
|
|
||||||
self._is_changed = True
|
|
||||||
self.update_cursor_position()
|
|
||||||
|
|
||||||
def _on_cursor_move(self, buf, cursor_iter, mark, user_data = None):
|
|
||||||
if mark != buf.get_insert(): return
|
|
||||||
|
|
||||||
self.update_cursor_position()
|
|
||||||
|
|
||||||
def _create_file_watcher(self, gfile = None):
|
def _create_file_watcher(self, gfile = None):
|
||||||
if not gfile: return
|
if not gfile: return
|
||||||
|
@ -186,37 +205,6 @@ class SourceView(SourceViewEventsMixin, GtkSource.View):
|
||||||
self._file_cdr_watcher.cancel()
|
self._file_cdr_watcher.cancel()
|
||||||
self._file_cdr_watcher = None
|
self._file_cdr_watcher = None
|
||||||
|
|
||||||
def save_file(self):
|
|
||||||
if not self._current_file:
|
|
||||||
self.save_file_as()
|
|
||||||
return
|
|
||||||
|
|
||||||
self._write_file(self._current_file)
|
|
||||||
|
|
||||||
|
|
||||||
def save_file_as(self):
|
|
||||||
# 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 self._current_filename == "":
|
|
||||||
dlg.set_current_name("new.txt")
|
|
||||||
else:
|
|
||||||
dlg.set_current_folder(self._current_file.get_parent().get_path())
|
|
||||||
dlg.set_current_name(self._current_filename)
|
|
||||||
|
|
||||||
response = dlg.run()
|
|
||||||
file = dlg.get_filename() if response == Gtk.ResponseType.OK else ""
|
|
||||||
dlg.destroy()
|
|
||||||
|
|
||||||
if not file == "":
|
|
||||||
gfile = Gio.File.new_for_path(file)
|
|
||||||
self._write_file(gfile, True)
|
|
||||||
|
|
||||||
def _write_file(self, gfile, save_as = False):
|
def _write_file(self, gfile, save_as = False):
|
||||||
with open(gfile.get_path(), 'w') as f:
|
with open(gfile.get_path(), 'w') as f:
|
||||||
if not save_as:
|
if not save_as:
|
||||||
|
|
|
@ -5,6 +5,7 @@ import gi
|
||||||
gi.require_version('Gtk', '3.0')
|
gi.require_version('Gtk', '3.0')
|
||||||
gi.require_version('GtkSource', '4')
|
gi.require_version('GtkSource', '4')
|
||||||
from gi.repository import Gtk
|
from gi.repository import Gtk
|
||||||
|
from gi.repository import Gio
|
||||||
from gi.repository import GtkSource
|
from gi.repository import GtkSource
|
||||||
|
|
||||||
# Application imports
|
# Application imports
|
||||||
|
@ -77,22 +78,52 @@ class SourceViewEventsMixin:
|
||||||
self._create_file_watcher(gfile)
|
self._create_file_watcher(gfile)
|
||||||
self.grab_focus()
|
self.grab_focus()
|
||||||
|
|
||||||
|
def save_file(self):
|
||||||
|
if not self._current_file:
|
||||||
|
self.save_file_as()
|
||||||
|
return
|
||||||
|
|
||||||
|
self._write_file(self._current_file)
|
||||||
|
|
||||||
|
def save_file_as(self):
|
||||||
|
# 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 self._current_filename == "":
|
||||||
|
dlg.set_current_name("new.txt")
|
||||||
|
else:
|
||||||
|
dlg.set_current_folder(self._current_file.get_parent().get_path())
|
||||||
|
dlg.set_current_name(self._current_filename)
|
||||||
|
|
||||||
|
response = dlg.run()
|
||||||
|
file = dlg.get_filename() if response == Gtk.ResponseType.OK else ""
|
||||||
|
dlg.destroy()
|
||||||
|
|
||||||
|
if not file == "":
|
||||||
|
gfile = Gio.File.new_for_path(file)
|
||||||
|
self._write_file(gfile, True)
|
||||||
|
|
||||||
def load_file_info(self, gfile):
|
def load_file_info(self, gfile):
|
||||||
info = gfile.query_info("standard::*", 0, cancellable=None)
|
info = gfile.query_info("standard::*", 0, cancellable=None)
|
||||||
content_type = info.get_content_type()
|
content_type = info.get_content_type()
|
||||||
display_name = info.get_display_name()
|
display_name = info.get_display_name()
|
||||||
tab_widget = self.get_parent().get_tab_widget()
|
|
||||||
self._current_filename = display_name
|
self._current_filename = display_name
|
||||||
|
|
||||||
try:
|
try:
|
||||||
lm = self._language_manager.guess_language(None, content_type)
|
lm = self._language_manager.guess_language(None, content_type)
|
||||||
self.set_buffer_language( lm.get_id() )
|
self._current_filetype = lm.get_id()
|
||||||
|
self.set_buffer_language(self._current_filetype)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
...
|
...
|
||||||
|
|
||||||
logger.debug(f"Detected Content Type: {content_type}")
|
logger.debug(f"Detected Content Type: {content_type}")
|
||||||
tab_widget.set_tab_label(display_name)
|
if self._current_filetype == "buffer":
|
||||||
event_system.emit("set_bottom_labels", (gfile, info))
|
self._current_filetype = info.get_content_type()
|
||||||
|
|
||||||
def load_file_async(self, gfile):
|
def load_file_async(self, gfile):
|
||||||
file = GtkSource.File()
|
file = GtkSource.File()
|
||||||
|
@ -104,6 +135,10 @@ class SourceViewEventsMixin:
|
||||||
self._is_changed = False
|
self._is_changed = False
|
||||||
self._document_loaded()
|
self._document_loaded()
|
||||||
|
|
||||||
|
tab_widget = self.get_parent().get_tab_widget()
|
||||||
|
tab_widget.set_tab_label(self._current_filename)
|
||||||
|
event_system.emit("set_bottom_labels", (gfile, None, self._current_filetype, None))
|
||||||
|
|
||||||
self._file_loader.load_async(io_priority = 98,
|
self._file_loader.load_async(io_priority = 98,
|
||||||
cancellable = None,
|
cancellable = None,
|
||||||
progress_callback = None,
|
progress_callback = None,
|
||||||
|
|
|
@ -6,6 +6,7 @@ from multiprocessing.connection import Client
|
||||||
from multiprocessing.connection import Listener
|
from multiprocessing.connection import Listener
|
||||||
|
|
||||||
# Lib imports
|
# Lib imports
|
||||||
|
from gi.repository import GLib
|
||||||
|
|
||||||
# Application imports
|
# Application imports
|
||||||
|
|
||||||
|
@ -56,17 +57,19 @@ class IPCServer:
|
||||||
@daemon_threaded
|
@daemon_threaded
|
||||||
def _run_ipc_loop(self, listener) -> None:
|
def _run_ipc_loop(self, listener) -> None:
|
||||||
while True:
|
while True:
|
||||||
|
try:
|
||||||
conn = listener.accept()
|
conn = listener.accept()
|
||||||
start_time = time.perf_counter()
|
start_time = time.perf_counter()
|
||||||
self._handle_ipc_message(conn, start_time)
|
GLib.idle_add(self._handle_ipc_message, *(conn, start_time,))
|
||||||
|
except Exception as e:
|
||||||
|
...
|
||||||
|
|
||||||
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 True:
|
||||||
msg = conn.recv()
|
msg = conn.recv()
|
||||||
if settings.is_debug():
|
logger.debug(msg)
|
||||||
print(msg)
|
|
||||||
|
|
||||||
if "FILE|" in msg:
|
if "FILE|" in msg:
|
||||||
file = msg.split("FILE|")[1].strip()
|
file = msg.split("FILE|")[1].strip()
|
||||||
|
|
|
@ -18,8 +18,8 @@ function main() {
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# NOTE: Remove if you want to pass file(s) besides directories...
|
# NOTE: Remove if you want to pass file(s) besides directories...
|
||||||
if [ ! -d "${path}" ]; then
|
if [ ! -f "${path}" ]; then
|
||||||
echo "Newton: Path given not a directory..."
|
echo "Newton: Path given not a file..."
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
|
@ -14,8 +14,12 @@
|
||||||
"keyboard_down" : "Down",
|
"keyboard_down" : "Down",
|
||||||
"keyboard_left" : "Left",
|
"keyboard_left" : "Left",
|
||||||
"keyboard_riht" : "Right",
|
"keyboard_riht" : "Right",
|
||||||
"keyboard_prev_tab" : "<Control>Page_Up",
|
"keyboard_move_tab_to_1" : "<Shift><Control>Down",
|
||||||
"keyboard_next_tab" : "<Control>Page_Down",
|
"keyboard_move_tab_to_2" : "<Shift><Control>Up",
|
||||||
|
"keyboard_move_tab_right" : "<Alt>Right",
|
||||||
|
"keyboard_move_tab_left" : "<Alt>Left",
|
||||||
|
"keyboard_next_tab" : "<Alt>Up",
|
||||||
|
"keyboard_prev_tab" : "<Alt>Down",
|
||||||
"keyboard_scale_up_text" : "<Control>equal",
|
"keyboard_scale_up_text" : "<Control>equal",
|
||||||
"keyboard_scale_down_text" : "<Control>minus"
|
"keyboard_scale_down_text" : "<Control>minus"
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<!-- Generated with glade 3.40.0 -->
|
<!-- Generated with glade 3.40.0 -->
|
||||||
<interface>
|
<interface>
|
||||||
<requires lib="gtk+" version="3.22"/>
|
<requires lib="gtk+" version="3.22"/>
|
||||||
<object class="GtkStatusbar" id="bottom_status_info">
|
<object class="GtkStatusbar" id="general_info">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can-focus">False</property>
|
<property name="can-focus">False</property>
|
||||||
<property name="margin-left">10</property>
|
<property name="margin-left">10</property>
|
||||||
|
@ -14,7 +14,7 @@
|
||||||
<property name="spacing">15</property>
|
<property name="spacing">15</property>
|
||||||
<property name="baseline-position">top</property>
|
<property name="baseline-position">top</property>
|
||||||
<child type="center">
|
<child type="center">
|
||||||
<object class="GtkLabel" id="bottom_line_char_label">
|
<object class="GtkLabel" id="line_char_label">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can-focus">False</property>
|
<property name="can-focus">False</property>
|
||||||
<property name="single-line-mode">True</property>
|
<property name="single-line-mode">True</property>
|
||||||
|
@ -27,7 +27,7 @@
|
||||||
</packing>
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkLabel" id="bottom_path_label">
|
<object class="GtkLabel" id="path_label">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can-focus">False</property>
|
<property name="can-focus">False</property>
|
||||||
<property name="ellipsize">start</property>
|
<property name="ellipsize">start</property>
|
||||||
|
@ -41,7 +41,7 @@
|
||||||
</packing>
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkLabel" id="bottom_file_type_label">
|
<object class="GtkLabel" id="file_type_label">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can-focus">False</property>
|
<property name="can-focus">False</property>
|
||||||
</object>
|
</object>
|
||||||
|
@ -53,7 +53,7 @@
|
||||||
</packing>
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkLabel" id="bottom_encoding_label">
|
<object class="GtkLabel" id="encoding_label">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can-focus">False</property>
|
<property name="can-focus">False</property>
|
||||||
</object>
|
</object>
|
Loading…
Reference in New Issue