Refactor file loading to detect external modifications and add reload capability
- Extract _load_data() method from load_path() for reuse in reload() - Add is_extters externally_modified() to track file state changes (mtime/size) - Replace load_bytes() with load_contents() for better error handling - Add reload() method to re-read file from disk - Fix file_state_watcher by properly detecting external changes
This commit is contained in:
@@ -17,13 +17,21 @@ class Plugin(PluginCode):
|
|||||||
|
|
||||||
|
|
||||||
def _controller_message(self, event: Code_Event_Types.CodeEvent):
|
def _controller_message(self, event: Code_Event_Types.CodeEvent):
|
||||||
if isinstance(event, Code_Event_Types.TextChangedEvent):
|
if not isinstance(event, Code_Event_Types.FocusedViewEvent): return
|
||||||
event.file.check_file_on_disk()
|
event = Event_Factory.create_event(
|
||||||
|
"get_file", buffer = event.view.get_buffer()
|
||||||
|
)
|
||||||
|
self.emit_to("files", event)
|
||||||
|
|
||||||
if event.file.is_deleted():
|
file = event.response
|
||||||
file_is_deleted(event, self.emit)
|
if file.ftype == "buffer": return
|
||||||
elif event.file.is_externally_modified():
|
|
||||||
file_is_externally_modified(event, self.emit)
|
file.check_file_on_disk()
|
||||||
|
|
||||||
|
if file.is_deleted():
|
||||||
|
file_is_deleted(file, self.emit)
|
||||||
|
elif file.is_externally_modified():
|
||||||
|
file_is_externally_modified(file, self.emit)
|
||||||
|
|
||||||
def load(self):
|
def load(self):
|
||||||
...
|
...
|
||||||
|
|||||||
@@ -10,23 +10,45 @@ from libs.event_factory import Event_Factory, Code_Event_Types
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
def file_is_deleted(event, emit):
|
def ask_yes_no(message):
|
||||||
event.file.was_deleted = True
|
dialog = Gtk.MessageDialog(
|
||||||
|
parent = None,
|
||||||
|
flags = 0,
|
||||||
|
message_type = Gtk.MessageType.QUESTION,
|
||||||
|
buttons = Gtk.ButtonsType.YES_NO,
|
||||||
|
text = message,
|
||||||
|
)
|
||||||
|
dialog.set_title("Confirm")
|
||||||
|
|
||||||
|
response = dialog.run()
|
||||||
|
dialog.destroy()
|
||||||
|
|
||||||
|
return response == Gtk.ResponseType.YES
|
||||||
|
|
||||||
|
|
||||||
|
def file_is_deleted(file, emit):
|
||||||
|
file.was_deleted = True
|
||||||
event = Event_Factory.create_event(
|
event = Event_Factory.create_event(
|
||||||
"file_externally_deleted",
|
"file_externally_deleted",
|
||||||
file = event.file,
|
file = file,
|
||||||
buffer = event.buffer
|
buffer = file.buffer
|
||||||
)
|
)
|
||||||
emit(event)
|
emit(event)
|
||||||
|
|
||||||
|
|
||||||
def file_is_externally_modified(event, emit):
|
def file_is_externally_modified(file, emit):
|
||||||
# event = Event_Factory.create_event(
|
event = Event_Factory.create_event(
|
||||||
# "file_externally_modified",
|
"file_externally_modified",
|
||||||
# file = event.file,
|
file = file,
|
||||||
# buffer = event.buffer
|
buffer = file.buffer
|
||||||
# )
|
)
|
||||||
# emit(event)
|
emit(event)
|
||||||
|
|
||||||
...
|
if not file.buffer.get_modified():
|
||||||
|
file.reload()
|
||||||
|
return
|
||||||
|
|
||||||
|
result = ask_yes_no("File has been externally modified. Reload?")
|
||||||
|
if not result: return
|
||||||
|
|
||||||
|
file.reload()
|
||||||
|
|||||||
@@ -13,8 +13,6 @@ from gi.repository import Gtk
|
|||||||
|
|
||||||
|
|
||||||
def add_prettify_json(buffer, menu):
|
def add_prettify_json(buffer, menu):
|
||||||
menu.append(separator)
|
|
||||||
|
|
||||||
def on_prettify_json(menuitem, buffer):
|
def on_prettify_json(menuitem, buffer):
|
||||||
start_itr, \
|
start_itr, \
|
||||||
end_itr = buffer.get_start_iter(), buffer.get_end_iter()
|
end_itr = buffer.get_start_iter(), buffer.get_end_iter()
|
||||||
@@ -28,4 +26,4 @@ def add_prettify_json(buffer, menu):
|
|||||||
|
|
||||||
item = Gtk.MenuItem(label = "Prettify JSON")
|
item = Gtk.MenuItem(label = "Prettify JSON")
|
||||||
item.connect("activate", on_prettify_json, buffer)
|
item.connect("activate", on_prettify_json, buffer)
|
||||||
menu.append(item)
|
menu.append(item)
|
||||||
@@ -120,21 +120,7 @@ class SourceFile(GtkSource.File):
|
|||||||
|
|
||||||
return gfile
|
return gfile
|
||||||
|
|
||||||
|
def _load_data(self, text: str, is_new: bool = True):
|
||||||
def load_path(self, gfile: Gio.File):
|
|
||||||
if not gfile: return
|
|
||||||
|
|
||||||
text = gfile.load_bytes()[0].get_data().decode("UTF-8")
|
|
||||||
info = gfile.query_info('standard::content-type', Gio.FileQueryInfoFlags.NONE, None)
|
|
||||||
content_type = info.get_content_type()
|
|
||||||
self.ftype = Gio.content_type_get_mime_type(content_type) \
|
|
||||||
.replace("application/", "") \
|
|
||||||
.replace("text/", "") \
|
|
||||||
.replace("x-", "")
|
|
||||||
|
|
||||||
self.set_path(gfile)
|
|
||||||
logger.debug(f"File content type: {self.ftype}")
|
|
||||||
|
|
||||||
undo_manager = self.buffer.get_undo_manager()
|
undo_manager = self.buffer.get_undo_manager()
|
||||||
|
|
||||||
self.buffer.block_changed_signal()
|
self.buffer.block_changed_signal()
|
||||||
@@ -151,21 +137,49 @@ class SourceFile(GtkSource.File):
|
|||||||
|
|
||||||
self.buffer.delete(start_itr, end_itr)
|
self.buffer.delete(start_itr, end_itr)
|
||||||
self.buffer.insert(start_itr, text, -1)
|
self.buffer.insert(start_itr, text, -1)
|
||||||
|
self.is_externally_modified()
|
||||||
GLib.idle_add(move_insert_to_start)
|
GLib.idle_add(move_insert_to_start)
|
||||||
|
|
||||||
undo_manager.end_not_undoable_action()
|
undo_manager.end_not_undoable_action()
|
||||||
self.buffer.set_modified(False)
|
self.buffer.set_modified(False)
|
||||||
|
|
||||||
eve = Event_Factory.create_event(
|
if is_new:
|
||||||
"loaded_new_file",
|
eve = Event_Factory.create_event(
|
||||||
file = self
|
"loaded_new_file",
|
||||||
)
|
file = self
|
||||||
self.emit(eve)
|
)
|
||||||
|
self.emit(eve)
|
||||||
|
|
||||||
self.buffer.unblock_changed_signal()
|
self.buffer.unblock_changed_signal()
|
||||||
self.buffer.unblock_changed_after_signal()
|
self.buffer.unblock_changed_after_signal()
|
||||||
self.buffer.unblock_modified_changed_signal()
|
self.buffer.unblock_modified_changed_signal()
|
||||||
|
|
||||||
|
def is_externally_modified(self) -> bool:
|
||||||
|
stat = os.stat(self.fpath)
|
||||||
|
current = (stat.st_mtime_ns, stat.st_size)
|
||||||
|
|
||||||
|
is_modified = \
|
||||||
|
hasattr(self, "last_state") and not current == self.last_state
|
||||||
|
|
||||||
|
self.last_state = current
|
||||||
|
return is_modified
|
||||||
|
|
||||||
|
def load_path(self, gfile: Gio.File):
|
||||||
|
if not gfile: return
|
||||||
|
loaded, contents, etag_out = gfile.load_contents()
|
||||||
|
if not loaded: raise Exception("File couldn't be loaded...'")
|
||||||
|
|
||||||
|
text = contents.decode("UTF-8")
|
||||||
|
info = gfile.query_info('standard::content-type', Gio.FileQueryInfoFlags.NONE, None)
|
||||||
|
content_type = info.get_content_type()
|
||||||
|
self.ftype = Gio.content_type_get_mime_type(content_type) \
|
||||||
|
.replace("application/", "") \
|
||||||
|
.replace("text/", "") \
|
||||||
|
.replace("x-", "")
|
||||||
|
|
||||||
|
self.set_path(gfile)
|
||||||
|
logger.debug(f"File content type: {self.ftype}")
|
||||||
|
self._load_data(text)
|
||||||
|
|
||||||
def set_path(self, gfile: Gio.File):
|
def set_path(self, gfile: Gio.File):
|
||||||
if not gfile: return
|
if not gfile: return
|
||||||
@@ -177,9 +191,17 @@ class SourceFile(GtkSource.File):
|
|||||||
event = Event_Factory.create_event("file_path_set", file = self)
|
event = Event_Factory.create_event("file_path_set", file = self)
|
||||||
self.emit(event)
|
self.emit(event)
|
||||||
|
|
||||||
|
def reload(self):
|
||||||
|
loaded, contents, etag_out = self.get_location().load_contents()
|
||||||
|
if not loaded: raise Exception("File couldn't be re-loaded...'")
|
||||||
|
|
||||||
|
text = contents.decode("UTF-8")
|
||||||
|
self._load_data(text, False)
|
||||||
|
|
||||||
def save(self):
|
def save(self):
|
||||||
self._write_file( self.get_location() )
|
self._write_file( self.get_location() )
|
||||||
|
|
||||||
|
self.is_externally_modified()
|
||||||
self.buffer.set_modified(False)
|
self.buffer.set_modified(False)
|
||||||
event = Event_Factory.create_event(
|
event = Event_Factory.create_event(
|
||||||
"saved_file",
|
"saved_file",
|
||||||
|
|||||||
Reference in New Issue
Block a user