[meld] undo: Take and keep track of the buffers an UndoSequence references



commit eb614e7f1055f89422f498c10433ede8fdc05038
Author: Kai Willadsen <kai willadsen gmail com>
Date:   Sun Feb 11 08:31:56 2018 +1000

    undo: Take and keep track of the buffers an UndoSequence references
    
    We're using weakrefs here because I'm paranoid about the lifecycle
    issues with GTK+ + Python refcounting fun.
    
    Starting a group now means dereferencing and re-referencing these
    buffers, which isn't great, but is probably the least-bad option. The
    other choice here would be to give groups a reference to their parent
    UndoSequence, and have the buffers lookup follow that, which seems...
    more complicated and confusing.

 meld/filediff.py |  2 +-
 meld/undo.py     | 14 +++++++++++---
 2 files changed, 12 insertions(+), 4 deletions(-)
---
diff --git a/meld/filediff.py b/meld/filediff.py
index 0dff0553..b3a82563 100644
--- a/meld/filediff.py
+++ b/meld/filediff.py
@@ -169,7 +169,7 @@ class FileDiff(MeldDoc, Component):
         self.focus_pane = None
         self.textbuffer = [v.get_buffer() for v in self.textview]
         self.buffer_texts = [BufferLines(b) for b in self.textbuffer]
-        self.undosequence = UndoSequence()
+        self.undosequence = UndoSequence(self.textbuffer)
         self.text_filters = []
         self.create_text_filters()
         self.settings_handlers = [
diff --git a/meld/undo.py b/meld/undo.py
index fa634ff3..a8775ff1 100644
--- a/meld/undo.py
+++ b/meld/undo.py
@@ -31,6 +31,8 @@ def on_undo_button_pressed():
     s.undo()
 """
 
+import weakref
+
 from gi.repository import GObject
 
 
@@ -75,8 +77,12 @@ class UndoSequence(GObject.GObject):
         ),
     }
 
-    def __init__(self):
-        """Create an empty UndoSequence.
+    def __init__(self, buffers):
+        """Create an empty UndoSequence
+
+        An undo sequence is tied to a collection of GtkTextBuffers, and
+        expects to maintain undo checkpoints for the same set of
+        buffers for the lifetime of the UndoSequence.
         """
         GObject.GObject.__init__(self)
         self.actions = []
@@ -84,6 +90,7 @@ class UndoSequence(GObject.GObject):
         self.checkpoints = {}
         self.group = None
         self.busy = False
+        self.buffer_refs = [weakref.ref(buf) for buf in buffers]
 
     def clear(self):
         """Remove all undo and redo actions from this sequence
@@ -224,7 +231,8 @@ class UndoSequence(GObject.GObject):
         if self.group:
             self.group.begin_group()
         else:
-            self.group = UndoSequence()
+            buffers = [ref() for ref in self.buffer_refs]
+            self.group = UndoSequence(buffers)
 
     def end_group(self):
         """End a logical group action. See also begin_group().


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]