[meld] sourceview: Intercept and sanitise text-tags on paste



commit 02dcbd6d245be488bda4bd57f80a8521c12a7c23
Author: Kai Willadsen <kai willadsen gmail com>
Date:   Mon Apr 16 07:28:33 2018 +1000

    sourceview: Intercept and sanitise text-tags on paste
    
    This is a different way of handling bgo#709580, with the change
    triggered by #152.
    
    The original problem here is that if you copy-paste within Meld, the
    tags that we use to indicate an inline difference get pasted as well, by
    GtkTextView/Buffer. This behaviour seems very difficult to opt out of.
    
    The first pass at handling this hacked around the problem by hooking in
    to tag apply and, if we were in an action group, skipping it. This
    basically worked (but was fragile) until we hit an error situation where
    we had unclosed action groups, at which point no tags were ever applied.
    
    This second pass instead hooks in to the textview paste_clipboard vfunc
    and requests and sets a text-only representation in the clipboard. This
    effectively sanitises the clipboard contents and so... seems to work.

 meld/meldbuffer.py | 16 ----------------
 meld/sourceview.py | 13 +++++++++++++
 2 files changed, 13 insertions(+), 16 deletions(-)
---
diff --git a/meld/meldbuffer.py b/meld/meldbuffer.py
index 90746475..311cb8c8 100644
--- a/meld/meldbuffer.py
+++ b/meld/meldbuffer.py
@@ -40,7 +40,6 @@ class MeldBuffer(GtkSource.Buffer):
         GtkSource.Buffer.__init__(self)
         bind_settings(self)
         self.data = MeldBufferData()
-        self.user_action_count = 0
         self.undo_sequence = None
         meldsettings.connect('changed', self.on_setting_changed)
         self.set_style_scheme(meldsettings.style_scheme)
@@ -50,27 +49,12 @@ class MeldBuffer(GtkSource.Buffer):
             self.set_style_scheme(meldsettings.style_scheme)
 
     def do_begin_user_action(self, *args):
-        self.user_action_count += 1
         if self.undo_sequence:
             self.undo_sequence.begin_group()
 
     def do_end_user_action(self, *args):
         if self.undo_sequence:
             self.undo_sequence.end_group()
-        self.user_action_count -= 1
-
-    def do_apply_tag(self, tag, start, end):
-        # Filthy, evil, horrible hack. What we're doing here is trying to
-        # figure out if a tag apply has come from a paste action, in which
-        # case GtkTextBuffer will 'helpfully' apply the existing tags in the
-        # copied selection. There appears to be no way to override this
-        # behaviour, or to hook in to the necessary paste mechanics to just
-        # request that we only get plain text or something. We're abusing the
-        # user_action notion here, because we only apply the tags we actually
-        # want in a callback.
-        if tag.props.name == 'inline' and self.user_action_count > 0:
-            return
-        return GtkSource.Buffer.do_apply_tag(self, tag, start, end)
 
     def get_iter_at_line_or_eof(self, line):
         """Return a Gtk.TextIter at the given line, or the end of the buffer.
diff --git a/meld/sourceview.py b/meld/sourceview.py
index e4aef776..5226b527 100644
--- a/meld/sourceview.py
+++ b/meld/sourceview.py
@@ -164,6 +164,19 @@ class MeldSourceView(GtkSource.View):
 
         meldsettings.connect('changed', self.on_setting_changed)
 
+    def do_paste_clipboard(self, *args):
+        # This is an awful hack to replace another awful hack. The idea
+        # here is to sanitise the clipboard contents so that it doesn't
+        # contain GtkTextTags, by requesting and setting plain text.
+
+        def text_received_cb(clipboard, text, *user_data):
+            clipboard.set_text(text, len(text))
+            self.get_buffer().paste_clipboard(
+                clipboard, None, self.get_editable())
+
+        clipboard = self.get_clipboard(Gdk.SELECTION_CLIPBOARD)
+        clipboard.request_text(text_received_cb)
+
     def get_y_for_line_num(self, line):
         buf = self.get_buffer()
         it = buf.get_iter_at_line(line)


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