[meld: 36/63] Move filediff to using GtkSourceFileSaver
- From: Kai Willadsen <kaiw src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [meld: 36/63] Move filediff to using GtkSourceFileSaver
- Date: Wed, 16 Dec 2015 21:22:00 +0000 (UTC)
commit ffd28fcd4ad08be928d9d4aa8a0a4dae04916a71
Author: Kai Willadsen <kai willadsen gmail com>
Date: Wed Aug 12 09:08:59 2015 +1000
Move filediff to using GtkSourceFileSaver
This patch is a first pass at using the saver approach, and includes
lots of async-related bits and pieces.
Getting this right is a real challenge, since we have plenty of error
handling code that assumes that it can call save and know whether the
file has saved when that returns.
meld/filediff.py | 70 +++++++++++++++++++++++++++++++++------------------
meld/meldbuffer.py | 6 ++++
meld/melddoc.py | 5 +++
3 files changed, 56 insertions(+), 25 deletions(-)
---
diff --git a/meld/filediff.py b/meld/filediff.py
index 5dbd0d1..b1c762d 100644
--- a/meld/filediff.py
+++ b/meld/filediff.py
@@ -817,6 +817,8 @@ class FileDiff(melddoc.MeldDoc, gnomeglade.Component):
if response == Gtk.ResponseType.OK:
for i in range(self.num_panes):
if try_save[i]:
+ # FIXME: See save_file; we can't assume that
+ # the save has succeeded at this point.
if not self.save_file(i):
return Gtk.ResponseType.CANCEL
elif response == Gtk.ResponseType.DELETE_EVENT:
@@ -1435,20 +1437,6 @@ class FileDiff(melddoc.MeldDoc, gnomeglade.Component):
return filename
return None
- def _save_text_to_filename(self, filename, text):
- try:
- if not isinstance(text, str):
- raise IOError("couldn't encode text")
- open(filename, "wb").write(text)
- except IOError as err:
- misc.error_dialog(
- primary=_("Could not save file %s.") % filename,
- secondary=_("Couldn't save file due to:\n%s") % (
- GLib.markup_escape_text(str(err))),
- )
- return False
- return True
-
def save_file(self, pane, saveas=False, force_overwrite=False):
buf = self.textbuffer[pane]
bufdata = buf.data
@@ -1488,7 +1476,7 @@ class FileDiff(melddoc.MeldDoc, gnomeglade.Component):
msgarea.connect("response", on_file_changed_response)
msgarea.show_all()
- return
+ return False
start, end = buf.get_bounds()
text = text_type(buf.get_text(start, end, False), 'utf8')
@@ -1518,16 +1506,48 @@ class FileDiff(melddoc.MeldDoc, gnomeglade.Component):
source_encoding = GtkSource.Encoding.get_utf8()
- save_to = bufdata.savefile or bufdata.filename
- if self._save_text_to_filename(save_to, text):
- self.emit("file-changed", save_to)
- self.undosequence.checkpoint(buf)
- bufdata.update_mtime()
- if pane == 1 and self.num_panes == 3:
- self.meta['middle_saved'] = True
- return True
- else:
- return False
+ saver = GtkSource.FileSaver.new_with_target(
+ self.textbuffer[pane], bufdata.sourcefile, bufdata.gfiletarget)
+ # TODO: Think about removing this flag and above handling, and instead
+ # handling the GtkSource.FileSaverError.EXTERNALLY_MODIFIED error
+ if force_overwrite:
+ saver.set_flags(GtkSource.FileSaverFlags.IGNORE_MODIFICATION_TIME)
+ saver.save_async(
+ GLib.PRIORITY_HIGH,
+ callback=self.file_saved_cb,
+ user_data=(pane,)
+ )
+ # TODO: We need to stop assuming that we know whether a save
+ # has been successful at the end of this function; we won't
+ # really know until later.
+ return True
+
+ def file_saved_cb(self, saver, result, user_data):
+ gfile = saver.get_location()
+ pane = user_data[0]
+
+ try:
+ saver.save_finish(result)
+ except GLib.Error as err:
+ # TODO: Handle recoverable error cases, like external modifications
+ # or invalid buffer characters.
+ filename = GLib.markup_escape_text(
+ gfile.get_parse_name()).decode('utf-8')
+ misc.error_dialog(
+ primary=_("Could not save file %s.") % filename,
+ secondary=_("Couldn't save file due to:\n%s") % (
+ GLib.markup_escape_text(str(err))),
+ )
+ self.state = melddoc.STATE_SAVING_ERROR
+ return
+
+ buf = saver.get_buffer()
+ self.emit('file-changed', gfile.get_path())
+ self.undosequence.checkpoint(buf)
+ buf.data.update_mtime()
+ if pane == 1 and self.num_panes == 3:
+ self.meta['middle_saved'] = True
+ self.state = melddoc.STATE_NORMAL
def make_patch(self, *extra):
dialog = patchdialog.PatchDialog(self)
diff --git a/meld/meldbuffer.py b/meld/meldbuffer.py
index 3379c66..1cf86d9 100644
--- a/meld/meldbuffer.py
+++ b/meld/meldbuffer.py
@@ -190,6 +190,12 @@ class MeldBufferData(GObject.GObject):
return self._sourcefile
@property
+ def gfiletarget(self):
+ if self.savefile:
+ return Gio.File.new_for_path(self.savefile)
+ return self.gfile
+
+ @property
def writable(self):
path = self.savefile or self.filename
if not path:
diff --git a/meld/melddoc.py b/meld/melddoc.py
index 9e4d5f0..823fdfa 100644
--- a/meld/melddoc.py
+++ b/meld/melddoc.py
@@ -50,6 +50,10 @@ def make_custom_editor_command(path, line=0):
return shlex.split(cmd)
+# TODO: Consider use-cases for states in gedit-enum-types.c
+STATE_NORMAL, STATE_SAVING_ERROR, NUM_STATES = range(3)
+
+
class MeldDoc(GObject.GObject):
"""Base class for documents in the meld application.
"""
@@ -78,6 +82,7 @@ class MeldDoc(GObject.GObject):
self.label_text = _("untitled")
self.tooltip_text = _("untitled")
self.main_actiongroup = None
+ self.state = STATE_NORMAL
def get_comparison(self):
"""Get the comparison type and path(s) being compared"""
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]