Newton_Editor/src/core/widgets/base/source_view.py

225 lines
7.3 KiB
Python

# Python imports
# Lib imports
import gi
gi.require_version('Gtk', '3.0')
gi.require_version('GtkSource', '4')
gi.require_version('Gdk', '3.0')
from gi.repository import Gtk
from gi.repository import Gdk
from gi.repository import Gio
from gi.repository import GtkSource
# Application imports
class SourceView(GtkSource.View):
def __init__(self):
super(SourceView, self).__init__()
self._language_manager = GtkSource.LanguageManager()
self._style_scheme_manager = GtkSource.StyleSchemeManager()
self._general_style_tag = None
self._file_watcher = None
self._is_changed = False
self._buffer = self.get_buffer()
self._setup_styling()
self._setup_signals()
self._set_up_dnd()
self._subscribe_to_events()
self._load_widgets()
def _setup_styling(self):
self.set_show_line_marks(True)
self.set_show_line_numbers(True)
self.set_smart_backspace(True)
self.set_indent_on_tab(True)
self.set_insert_spaces_instead_of_tabs(True)
self.set_auto_indent(True)
self.set_monospace(True)
self.set_tab_width(4)
self.set_show_right_margin(True)
self.set_right_margin_position(80)
self.set_background_pattern(0) # 0 = None, 1 = Grid
self._create_default_tag()
self.set_buffer_language()
self.set_buffer_style()
self.set_vexpand(True)
def _setup_signals(self):
self.connect("drag-data-received", self._on_drag_data_received)
self._buffer.connect("mark-set", self._on_cursor_move)
# self.completion.add_provider(srcCompleteonSnippets)
# self.completion.add_provider(srcCompleteonWords)
def _subscribe_to_events(self):
...
def _load_widgets(self):
...
def _create_default_tag(self):
self._general_style_tag = self._buffer.create_tag('general_style')
self._general_style_tag.set_property('size', 100)
self._general_style_tag.set_property('scale', 100)
def set_buffer_language(self, language = "python3"):
self._buffer.set_language( self._language_manager.get_language(language) )
def set_buffer_style(self, style = "tango"):
self._buffer.set_style_scheme( self._style_scheme_manager.get_scheme(style) )
def get_file_watcher(self):
return self._file_watcher
def create_file_watcher(self, file_path = None):
if not file_path:
return
if self._file_watcher:
self._file_watcher.cancel()
self._file_watcher = None
self._file_watcher = Gio.File.new_for_path(file_path) \
.monitor_file([
Gio.FileMonitorFlags.WATCH_MOVES,
Gio.FileMonitorFlags.WATCH_HARD_LINKS
], Gio.Cancellable())
self._file_watcher.connect("changed", self.file_watch_updates)
def file_watch_updates(self, file_monitor, file, other_file=None, eve_type=None, data=None):
if settings.is_debug():
logger.debug(eve_type)
if eve_type in [Gio.FileMonitorEvent.CREATED,
Gio.FileMonitorEvent.DELETED,
Gio.FileMonitorEvent.RENAMED]:
...
if eve_type in [ Gio.FileMonitorEvent.CHANGED ]:
...
def toggle_highlight_line(self, widget = None, eve = None):
self.set_highlight_current_line( not self.get_highlight_current_line() )
def scale_up_text(self, scale_step = 10):
current_scale = self._general_style_tag.get_property('scale')
start_itr = self._buffer.get_start_iter()
end_itr = self._buffer.get_end_iter()
self._general_style_tag.set_property('scale', current_scale + scale_step)
self._buffer.apply_tag(self._general_style_tag, start_itr, end_itr)
def scale_down_text(self, scale_step = 10):
tag_table = self._buffer.get_tag_table()
start_itr = self._buffer.get_start_iter()
end_itr = self._buffer.get_end_iter()
tag = tag_table.lookup('general_style')
tag.set_property('scale', tag.get_property('scale') - scale_step)
self._buffer.apply_tag(tag, start_itr, end_itr)
def _set_up_dnd(self):
URI_TARGET_TYPE = 80
uri_target = Gtk.TargetEntry.new('text/uri-list', Gtk.TargetFlags(0), URI_TARGET_TYPE)
targets = [ uri_target ]
self.drag_dest_set_target_list(targets)
def _on_drag_data_received(self, widget, drag_context, x, y, data, info, time):
if info == 80:
uris = data.get_uris()
if len(uris) == 0:
uris = data.get_text().split("\n")
if self._is_changed:
# self.maybe_saved()
...
gfile = Gio.File.new_for_uri(uris[0])
self.open_file(gfile)
uris.pop(0)
for uri in uris:
gfile = Gio.File.new_for_uri(uri)
event_system.emit('create_view', (None, None, gfile,))
def open_file(self, gfile, *args):
info = gfile.query_info("standard::*", 0, cancellable=None)
content_type = info.get_content_type()
display_name = info.get_display_name()
tab_widget = self.get_parent().get_tab_widget()
lm = self._language_manager.guess_language(None, content_type)
tab_widget.set_tab_label(display_name)
event_system.emit("set_bottom_labels", (gfile, info))
logger.debug(f"Detected Content Type: {content_type}")
with open(gfile.get_path(), 'r') as f:
data = f.read()
self._buffer.set_text(data)
try:
self.set_buffer_language( lm.get_id() )
except Exception as e:
...
# self.current_file = myfile
# self.current_filename = myfile.rpartition("/")[2]
# self.current_folder = path.dirname(myfile)
f.close()
# self.headerbar.set_subtitle(myfile)
# self.status_label.set_text(f"'{myfile}' loaded")
# self.headerbar.set_title("TextEdit")
self.grab_focus()
# self.is_changed = False
def _on_cursor_move(self, buf, cursor_iter, mark, user_data = None):
if mark != buf.get_insert():
return
self.update_cursor_position()
def update_cursor_position(self):
iter = self._buffer.get_iter_at_mark(self._buffer.get_insert())
chars = iter.get_offset()
row = iter.get_line() + 1
col = self.get_visual_column(iter) + 1
classes = self._buffer.get_context_classes_at_iter(iter)
classes_str = ""
i = 0
for c in classes:
if len(classes) != i + 1:
classes_str += c + ", "
else:
classes_str += c
cursor_data = f"char: {chars}, line: {row}, column: {col}, classes: {classes_str}"
logger.debug(cursor_data)
event_system.emit("set_line_char_label", (f"{row}:{col}",))
# https://github.com/ptomato/inform7-ide/blob/main/src/actions.c
def action_uncomment_selection(self):
...
def action_comment_out_selection(self):
pass