Improve file loading robustness and drag-and-drop handling
- Add error handling for UTF-8 decoding to gracefully handle invalid bytes - Refactor DnD target handling with explicit target list and proper context completion - Remove completed TODO item for file open event emission - Clean up memory by deleting file contents after decoding
This commit is contained in:
1
TODO.md
1
TODO.md
@@ -4,7 +4,6 @@ ___
|
|||||||
1. Add TreeSitter
|
1. Add TreeSitter
|
||||||
1. Add Collapsable code blocks
|
1. Add Collapsable code blocks
|
||||||
1. Add Terminal plugin
|
1. Add Terminal plugin
|
||||||
1. Add event to emit on file open so plugins could try to open
|
|
||||||
1. Add Plugin to <Shift\><Ctrl\>| and <Ctrl\>| to split views up, down, left, right
|
1. Add Plugin to <Shift\><Ctrl\>| and <Ctrl\>| to split views up, down, left, right
|
||||||
1. Add <Ctrl\>i to **lsp_manager** to list who implements xyz
|
1. Add <Ctrl\>i to **lsp_manager** to list who implements xyz
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,10 @@
|
|||||||
# Lib imports
|
# Lib imports
|
||||||
import gi
|
import gi
|
||||||
gi.require_version('Gtk', '3.0')
|
gi.require_version('Gtk', '3.0')
|
||||||
|
#gi.require_version('Gdk', '3.0')
|
||||||
from gi.repository import Gtk
|
from gi.repository import Gtk
|
||||||
|
#from gi.repository import Gdk
|
||||||
|
|
||||||
|
|
||||||
# Application imports
|
# Application imports
|
||||||
|
|
||||||
@@ -12,25 +15,41 @@ from gi.repository import Gtk
|
|||||||
class SourceViewDnDMixin:
|
class SourceViewDnDMixin:
|
||||||
|
|
||||||
def _set_up_dnd(self):
|
def _set_up_dnd(self):
|
||||||
PLAIN_TEXT_TARGET_TYPE = 70
|
URI_TARGET_TYPE = 10
|
||||||
URI_TARGET_TYPE = 80
|
PLAIN_TEXT_TARGET_TYPE = 50
|
||||||
text_target = Gtk.TargetEntry.new('text/plain', Gtk.TargetFlags(0), PLAIN_TEXT_TARGET_TYPE)
|
|
||||||
uri_target = Gtk.TargetEntry.new('text/uri-list', Gtk.TargetFlags(0), URI_TARGET_TYPE)
|
uri_target = Gtk.TargetEntry.new(
|
||||||
targets = [ text_target, uri_target ]
|
'text/uri-list', Gtk.TargetFlags(0), URI_TARGET_TYPE
|
||||||
|
)
|
||||||
|
text_target = Gtk.TargetEntry.new(
|
||||||
|
'text/plain', Gtk.TargetFlags(0), PLAIN_TEXT_TARGET_TYPE
|
||||||
|
)
|
||||||
|
targets = Gtk.TargetList.new([ uri_target, text_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(
|
||||||
if info == 70: return
|
self, widget, drag_context, x, y, data, info, time
|
||||||
|
):
|
||||||
|
target = data.get_target().name()
|
||||||
|
|
||||||
if info == 80:
|
if (info == 10) or (target == "text/uri-list"):
|
||||||
uris = data.get_uris()
|
uris = data.get_uris()
|
||||||
|
|
||||||
if not uris:
|
if not uris:
|
||||||
uris = data.get_text().split("\n")
|
uris = data.get_text().split("\n")
|
||||||
|
|
||||||
self._on_uri_data_received(uris)
|
self._on_uri_data_received(uris)
|
||||||
|
|
||||||
|
drag_context.finish(True, False, time)
|
||||||
|
|
||||||
|
return
|
||||||
|
elif (info == 50) or (target == "text/plain"):
|
||||||
|
...
|
||||||
|
else:
|
||||||
|
logger.info(f"DnD Dropped File Type: {target}")
|
||||||
|
|
||||||
|
drag_context.finish(False, False, time)
|
||||||
|
|
||||||
def _on_uri_data_received(self, uris: list[str]):
|
def _on_uri_data_received(self, uris: list[str]):
|
||||||
uris = self.command.filter_out_loaded_files(uris)
|
uris = self.command.filter_out_loaded_files(uris)
|
||||||
if not uris: return
|
if not uris: return
|
||||||
|
|||||||
@@ -169,7 +169,12 @@ class SourceFile(GtkSource.File):
|
|||||||
loaded, contents, etag_out = gfile.load_contents()
|
loaded, contents, etag_out = gfile.load_contents()
|
||||||
if not loaded: raise Exception("File couldn't be loaded...'")
|
if not loaded: raise Exception("File couldn't be loaded...'")
|
||||||
|
|
||||||
text = contents.decode("UTF-8")
|
# Note:
|
||||||
|
# "strict" (default) -> raises an error on invalid bytes
|
||||||
|
# "ignore" -> skips invalid bytes entirely
|
||||||
|
# "replace" -> replaces invalid bytes with <20>
|
||||||
|
# "backslashreplace" -> uses escape sequences like \xFF
|
||||||
|
text = contents.decode("UTF-8", errors = "replace")
|
||||||
info = gfile.query_info('standard::content-type', Gio.FileQueryInfoFlags.NONE, None)
|
info = gfile.query_info('standard::content-type', Gio.FileQueryInfoFlags.NONE, None)
|
||||||
content_type = info.get_content_type()
|
content_type = info.get_content_type()
|
||||||
self.ftype = Gio.content_type_get_mime_type(content_type) \
|
self.ftype = Gio.content_type_get_mime_type(content_type) \
|
||||||
@@ -177,6 +182,7 @@ class SourceFile(GtkSource.File):
|
|||||||
.replace("text/", "") \
|
.replace("text/", "") \
|
||||||
.replace("x-", "")
|
.replace("x-", "")
|
||||||
|
|
||||||
|
del contents
|
||||||
self.set_path(gfile)
|
self.set_path(gfile)
|
||||||
logger.debug(f"File content type: {self.ftype}")
|
logger.debug(f"File content type: {self.ftype}")
|
||||||
self._load_data(text)
|
self._load_data(text)
|
||||||
|
|||||||
Reference in New Issue
Block a user