[meld/ui-next: 10/35] filediff: Integrate ActionGutter in to FileDiff



commit 515b4902d779ab0195f189352034bc6e1e87b319
Author: Kai Willadsen <kai willadsen gmail com>
Date:   Tue Feb 12 06:43:10 2019 +1000

    filediff: Integrate ActionGutter in to FileDiff
    
    This has required several changes to the GtkBuilder file, including
    switching to GtkGrid. This shouldn't be permanent, but currently
    DiffGrid can't actually handle the layout because of its fixed column
    index logic.

 meld/filediff.py              |  67 ++++++++++++++++--
 meld/resources/ui/filediff.ui | 158 ++++++++++++++++++++++++++++++++++++------
 2 files changed, 198 insertions(+), 27 deletions(-)
---
diff --git a/meld/filediff.py b/meld/filediff.py
index 5cc02d41..ef717157 100644
--- a/meld/filediff.py
+++ b/meld/filediff.py
@@ -16,6 +16,7 @@
 
 import copy
 import functools
+import logging
 import math
 
 from gi.repository import Gdk
@@ -28,7 +29,7 @@ from gi.repository import GtkSource
 # TODO: Don't from-import whole modules
 from meld import misc
 from meld.conf import _, ui_file
-from meld.const import ActionMode, NEWLINES
+from meld.const import ActionMode, ChunkAction, NEWLINES
 from meld.gutterrendererchunk import GutterRendererChunkLines
 from meld.iohelpers import prompt_save_filename
 from meld.matchers.diffutil import Differ, merged_chunk_order
@@ -49,6 +50,8 @@ from meld.ui.util import (
     make_multiobject_property_action, map_widgets_into_lists)
 from meld.undo import UndoSequence
 
+log = logging.getLogger(__name__)
+
 
 def with_scroll_lock(lock_attr):
     """Decorator for locking a callback based on an instance attribute
@@ -117,6 +120,14 @@ class FileDiff(Gtk.VBox, MeldDoc):
     )
 
     actiongroup = Template.Child('FilediffActions')
+    actiongutter0 = Template.Child()
+    actiongutter1 = Template.Child()
+    actiongutter2 = Template.Child()
+    actiongutter3 = Template.Child()
+    dummy_toolbar_actiongutter0 = Template.Child()
+    dummy_toolbar_actiongutter1 = Template.Child()
+    dummy_toolbar_actiongutter2 = Template.Child()
+    dummy_toolbar_actiongutter3 = Template.Child()
     dummy_toolbar_linkmap0 = Template.Child()
     dummy_toolbar_linkmap1 = Template.Child()
     fileentry0 = Template.Child()
@@ -205,6 +216,7 @@ class FileDiff(Gtk.VBox, MeldDoc):
             "scrolledwindow", "textview", "vbox",
             "dummy_toolbar_linkmap", "filelabel_toolitem", "filelabel",
             "fileentry_toolitem", "statusbar",
+            "actiongutter", "dummy_toolbar_actiongutter",
         ]
         map_widgets_into_lists(self, widget_lists)
 
@@ -284,6 +296,11 @@ class FileDiff(Gtk.VBox, MeldDoc):
                 'overwrite', self.textview[0], 'overwrite',
                 GObject.BindingFlags.BIDIRECTIONAL)
 
+        for gutter in self.actiongutter:
+            self.bind_property('action_mode', gutter, 'action_mode')
+            gutter.connect(
+                'chunk_action_activated', self.on_chunk_action_activated)
+
         self.linediffer.connect("diffs-changed", self.on_diffs_changed)
         self.undosequence.connect("checkpointed", self.on_undo_checkpointed)
         self.connect("next-conflict-changed", self.on_next_conflict_changed)
@@ -612,6 +629,29 @@ class FileDiff(Gtk.VBox, MeldDoc):
         dst = src + direction
         return (dst, src) if reverse else (src, dst)
 
+    def on_chunk_action_activated(
+            self, gutter, action, from_view, to_view, chunk):
+
+        try:
+            chunk_action = ChunkAction(action)
+        except ValueError:
+            log.error('Invalid chunk action %s', action)
+            return
+
+        # TODO: There's no reason the replace_chunk(), etc. calls should take
+        # an index instead of just taking the views themselves.
+        from_pane = self.textview.index(from_view)
+        to_pane = self.textview.index(to_view)
+
+        if chunk_action == ChunkAction.replace:
+            self.replace_chunk(from_pane, to_pane, chunk)
+        elif chunk_action == ChunkAction.delete:
+            self.delete_chunk(from_pane, chunk)
+        elif chunk_action == ChunkAction.copy_up:
+            self.copy_chunk(from_pane, to_pane, chunk, copy_up=True)
+        elif chunk_action == ChunkAction.copy_down:
+            self.copy_chunk(from_pane, to_pane, chunk, copy_up=False)
+
     @Template.Callback()
     def action_push_change_left(self, *args):
         src, dst = self.get_action_panes(PANE_LEFT)
@@ -1413,6 +1453,15 @@ class FileDiff(Gtk.VBox, MeldDoc):
         set_action_enabled("MergeAll", mergeable[0] or mergeable[1])
 
     def on_diffs_changed(self, linediffer, chunk_changes):
+
+        # TODO: Break out highlight recalculation to its own method,
+        # and just update chunk lists in children here.
+        for gutter in self.actiongutter:
+            from_pane = self.textview.index(gutter.source_view)
+            to_pane = self.textview.index(gutter.target_view)
+            gutter.chunks = list(linediffer.paired_all_single_changes(
+                from_pane, to_pane))
+
         removed_chunks, added_chunks, modified_chunks = chunk_changes
 
         # We need to clear removed and modified chunks, and need to
@@ -1829,6 +1878,8 @@ class FileDiff(Gtk.VBox, MeldDoc):
             t.queue_draw()
         for i in range(self.num_panes-1):
             self.linkmap[i].queue_draw()
+        for gutter in self.actiongutter:
+            gutter.queue_draw()
 
     @Template.Callback()
     def on_action_lock_scrolling_toggled(self, action):
@@ -1923,8 +1974,12 @@ class FileDiff(Gtk.VBox, MeldDoc):
             if i == 1:
                 master, target_line = 1, other_line
 
+        # FIXME: We should really hook into the adjustments directly on
+        # the widgets instead of doing this.
         for lm in self.linkmap:
             lm.queue_draw()
+        for gutter in self.actiongutter:
+            gutter.queue_draw()
 
     def set_num_panes(self, n):
         if n == self.num_panes or n not in (1, 2, 3):
@@ -1934,15 +1989,17 @@ class FileDiff(Gtk.VBox, MeldDoc):
         for widget in (
                 self.vbox[:n] + self.file_toolbar[:n] +
                 self.linkmap[:n - 1] + self.dummy_toolbar_linkmap[:n - 1] +
-                self.statusbar[:n]
-                ):
+                self.statusbar[:n] +
+                self.actiongutter[:(n - 1) * 2] +
+                self.dummy_toolbar_actiongutter[:(n - 1) * 2]):
             widget.show()
 
         for widget in (
                 self.vbox[n:] + self.file_toolbar[n:] +
                 self.linkmap[n - 1:] + self.dummy_toolbar_linkmap[n - 1:] +
-                self.statusbar[n:]
-                ):
+                self.statusbar[n:] +
+                self.actiongutter[(n - 1) * 2:] +
+                self.dummy_toolbar_actiongutter[(n - 1) * 2:]):
             widget.hide()
 
         self.actiongroup.get_action("MakePatch").set_sensitive(n > 1)
diff --git a/meld/resources/ui/filediff.ui b/meld/resources/ui/filediff.ui
index e5d4f8b1..cf0636a1 100644
--- a/meld/resources/ui/filediff.ui
+++ b/meld/resources/ui/filediff.ui
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!-- Generated with glade 3.22.1 -->
 <interface>
-  <requires lib="gtk+" version="3.0"/>
+  <requires lib="gtk+" version="3.20"/>
   <requires lib="meld.ui.gladesupport" version="0.0"/>
   <template class="FileDiff" parent="GtkVBox">
     <property name="visible">True</property>
@@ -9,7 +9,7 @@
     <signal name="key-press-event" handler="on_key_event" swapped="no"/>
     <signal name="key-release-event" handler="on_key_event" swapped="no"/>
     <child>
-      <object class="DiffGrid" id="grid">
+      <object class="GtkGrid" id="grid">
         <property name="visible">True</property>
         <property name="can_focus">False</property>
         <child>
@@ -83,7 +83,7 @@
             </style>
           </object>
           <packing>
-            <property name="left_attach">5</property>
+            <property name="left_attach">8</property>
             <property name="top_attach">0</property>
           </packing>
         </child>
@@ -158,7 +158,7 @@
             </style>
           </object>
           <packing>
-            <property name="left_attach">3</property>
+            <property name="left_attach">4</property>
             <property name="top_attach">0</property>
           </packing>
         </child>
@@ -233,7 +233,7 @@
             </style>
           </object>
           <packing>
-            <property name="left_attach">1</property>
+            <property name="left_attach">0</property>
             <property name="top_attach">0</property>
           </packing>
         </child>
@@ -258,9 +258,6 @@
                 <property name="can_focus">False</property>
                 <property name="hexpand">True</property>
                 <property name="vexpand">True</property>
-                <property name="vscrollbar_policy">always</property>
-                <property name="window_placement">top-right</property>
-                <property name="overlay_scrolling">False</property>
                 <signal name="size-allocate" handler="on_scrolledwindow_size_allocate" swapped="no"/>
                 <child>
                   <object class="MeldSourceView" id="textview0">
@@ -283,7 +280,7 @@
             </child>
           </object>
           <packing>
-            <property name="left_attach">1</property>
+            <property name="left_attach">0</property>
             <property name="top_attach">1</property>
           </packing>
         </child>
@@ -308,8 +305,6 @@
                 <property name="can_focus">False</property>
                 <property name="hexpand">True</property>
                 <property name="vexpand">True</property>
-                <property name="vscrollbar_policy">always</property>
-                <property name="overlay_scrolling">False</property>
                 <signal name="size-allocate" handler="on_scrolledwindow_size_allocate" swapped="no"/>
                 <child>
                   <object class="MeldSourceView" id="textview2">
@@ -332,7 +327,7 @@
             </child>
           </object>
           <packing>
-            <property name="left_attach">5</property>
+            <property name="left_attach">8</property>
             <property name="top_attach">1</property>
           </packing>
         </child>
@@ -357,8 +352,6 @@
                 <property name="can_focus">False</property>
                 <property name="hexpand">True</property>
                 <property name="vexpand">True</property>
-                <property name="vscrollbar_policy">always</property>
-                <property name="overlay_scrolling">False</property>
                 <signal name="size-allocate" handler="on_scrolledwindow_size_allocate" swapped="no"/>
                 <child>
                   <object class="MeldSourceView" id="textview1">
@@ -381,7 +374,7 @@
             </child>
           </object>
           <packing>
-            <property name="left_attach">3</property>
+            <property name="left_attach">4</property>
             <property name="top_attach">1</property>
           </packing>
         </child>
@@ -420,7 +413,7 @@
             </style>
           </object>
           <packing>
-            <property name="left_attach">4</property>
+            <property name="left_attach">6</property>
             <property name="top_attach">0</property>
           </packing>
         </child>
@@ -433,7 +426,7 @@
             <signal name="scroll-event" handler="on_linkmap_scroll_event" swapped="no"/>
           </object>
           <packing>
-            <property name="left_attach">4</property>
+            <property name="left_attach">6</property>
             <property name="top_attach">1</property>
           </packing>
         </child>
@@ -446,7 +439,7 @@
             </style>
           </object>
           <packing>
-            <property name="left_attach">1</property>
+            <property name="left_attach">0</property>
             <property name="top_attach">3</property>
           </packing>
         </child>
@@ -459,7 +452,8 @@
             </style>
           </object>
           <packing>
-            <property name="left_attach">2</property>
+            <property name="left_attach">1</property>
+            <property name="width">3</property>
             <property name="top_attach">3</property>
           </packing>
         </child>
@@ -472,7 +466,7 @@
             </style>
           </object>
           <packing>
-            <property name="left_attach">3</property>
+            <property name="left_attach">4</property>
             <property name="top_attach">3</property>
           </packing>
         </child>
@@ -485,7 +479,7 @@
             </style>
           </object>
           <packing>
-            <property name="left_attach">4</property>
+            <property name="left_attach">5</property>
             <property name="width">3</property>
             <property name="top_attach">3</property>
           </packing>
@@ -499,10 +493,130 @@
             </style>
           </object>
           <packing>
-            <property name="left_attach">5</property>
+            <property name="left_attach">8</property>
             <property name="top_attach">3</property>
           </packing>
         </child>
+        <child>
+          <object class="GtkToolbar" id="dummy_toolbar_actiongutter0">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <style>
+              <class name="meld-notebook-toolbar"/>
+            </style>
+          </object>
+          <packing>
+            <property name="left_attach">1</property>
+            <property name="top_attach">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkToolbar" id="dummy_toolbar_actiongutter1">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <style>
+              <class name="meld-notebook-toolbar"/>
+            </style>
+          </object>
+          <packing>
+            <property name="left_attach">3</property>
+            <property name="top_attach">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkToolbar" id="dummy_toolbar_actiongutter2">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <style>
+              <class name="meld-notebook-toolbar"/>
+            </style>
+          </object>
+          <packing>
+            <property name="left_attach">5</property>
+            <property name="top_attach">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkToolbar" id="dummy_toolbar_actiongutter3">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <style>
+              <class name="meld-notebook-toolbar"/>
+            </style>
+          </object>
+          <packing>
+            <property name="left_attach">7</property>
+            <property name="top_attach">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="ActionGutter" id="actiongutter0">
+            <property name="width_request">20</property>
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="source_view">textview0</property>
+            <property name="target_view">textview1</property>
+            <property name="icon_direction">GTK_ICON_LOOKUP_DIR_LTR</property>
+          </object>
+          <packing>
+            <property name="left_attach">1</property>
+            <property name="top_attach">1</property>
+          </packing>
+        </child>
+        <child>
+          <object class="ActionGutter" id="actiongutter1">
+            <property name="width_request">20</property>
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="source_view">textview1</property>
+            <property name="target_view">textview0</property>
+            <property name="icon_direction">GTK_ICON_LOOKUP_DIR_RTL</property>
+          </object>
+          <packing>
+            <property name="left_attach">3</property>
+            <property name="top_attach">1</property>
+          </packing>
+        </child>
+        <child>
+          <object class="ActionGutter" id="actiongutter2">
+            <property name="width_request">20</property>
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="source_view">textview1</property>
+            <property name="target_view">textview2</property>
+            <property name="icon_direction">GTK_ICON_LOOKUP_DIR_LTR</property>
+          </object>
+          <packing>
+            <property name="left_attach">5</property>
+            <property name="top_attach">1</property>
+          </packing>
+        </child>
+        <child>
+          <object class="ActionGutter" id="actiongutter3">
+            <property name="width_request">20</property>
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="source_view">textview2</property>
+            <property name="target_view">textview1</property>
+            <property name="icon_direction">GTK_ICON_LOOKUP_DIR_RTL</property>
+          </object>
+          <packing>
+            <property name="left_attach">7</property>
+            <property name="top_attach">1</property>
+          </packing>
+        </child>
+        <child>
+          <placeholder/>
+        </child>
+        <child>
+          <placeholder/>
+        </child>
+        <child>
+          <placeholder/>
+        </child>
+        <child>
+          <placeholder/>
+        </child>
         <child>
           <placeholder/>
         </child>


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