[meld] Add Previous/Next Conflict actions (closes bgo#602873)
- From: Kai Willadsen <kaiw src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [meld] Add Previous/Next Conflict actions (closes bgo#602873)
- Date: Thu, 30 Sep 2010 21:42:18 +0000 (UTC)
commit dda37c052bdaf07ab7886f0efd4116a3b9d076b7
Author: Kai Willadsen <kai willadsen gmail com>
Date: Mon May 17 09:10:29 2010 +1000
Add Previous/Next Conflict actions (closes bgo#602873)
This patch adds two new actions that complement the existing
chunk-skipping actions with conflict-specific previous/next actions.
Differ: Add and maintain a list of chunk IDs of conflicts
FileDiff: Implement Previous/Next Conflict actions, add a signal for
sensitivity setting, and maintain the cursor's conflict fields
CursorDetails: Add fields for previous and next conflict
data/ui/filediff-ui.xml | 3 +++
meld/diffutil.py | 9 +++++++++
meld/filediff.py | 43 ++++++++++++++++++++++++++++++++++++++++++-
3 files changed, 54 insertions(+), 1 deletions(-)
---
diff --git a/data/ui/filediff-ui.xml b/data/ui/filediff-ui.xml
index 26a83ca..cedb010 100644
--- a/data/ui/filediff-ui.xml
+++ b/data/ui/filediff-ui.xml
@@ -10,6 +10,9 @@
<menubar name="Menubar">
<menu action="ChangesMenu">
<placeholder name="ChangesActions">
+ <menuitem action="PrevConflict"/>
+ <menuitem action="NextConflict"/>
+ <separator/>
<menuitem action="PushLeft"/>
<menuitem action="PushRight"/>
<menuitem action="PullLeft"/>
diff --git a/meld/diffutil.py b/meld/diffutil.py
index d184e15..d8781c6 100644
--- a/meld/diffutil.py
+++ b/meld/diffutil.py
@@ -84,6 +84,7 @@ class Differ(gobject.GObject):
self.num_sequences = 0
self.seqlength = [0, 0, 0]
self.diffs = [[], []]
+ self.conflicts = []
self._merge_cache = []
self._line_cache = [[], [], []]
self.ignore_blanks = False
@@ -112,6 +113,14 @@ class Differ(gobject.GObject):
break
self._has_mergeable_changes = (mergeable0, mergeable1)
+ # Conflicts can only occur when there are three panes, and will always
+ # involve the middle pane.
+ self.conflicts = []
+ for i, (c1, c2) in enumerate(self._merge_cache):
+ if (c1 is not None and c1[0] == 'conflict') or \
+ (c2 is not None and c2[0] == 'conflict'):
+ self.conflicts.append(i)
+
self._update_line_cache()
self.emit("diffs-changed")
diff --git a/meld/filediff.py b/meld/filediff.py
index bcde5de..cb43ed8 100644
--- a/meld/filediff.py
+++ b/meld/filediff.py
@@ -91,7 +91,8 @@ def insert_with_tags_by_name(buffer, line, text, tag):
buffer.insert_with_tags_by_name(get_iter_at_line_or_eof(buffer, line), text, tag)
class CursorDetails(object):
- __slots__ = ("pane", "pos", "line", "offset", "chunk", "prev", "next")
+ __slots__ = ("pane", "pos", "line", "offset", "chunk", "prev", "next",
+ "prev_conflict", "next_conflict")
def __init__(self):
for var in self.__slots__:
@@ -112,6 +113,10 @@ class FileDiff(melddoc.MeldDoc, gnomeglade.Component):
# Identifiers for MsgArea messages
(MSG_SAME,) = range(1)
+ __gsignals__ = {
+ 'next-conflict-changed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, (bool, bool)),
+ }
+
def __init__(self, prefs, num_panes):
"""Start up an filediff with num_panes empty contents.
"""
@@ -179,6 +184,8 @@ class FileDiff(melddoc.MeldDoc, gnomeglade.Component):
actions = (
("FileOpen", gtk.STOCK_OPEN, None, None, _("Open selected"), self.on_open_activate),
("CreatePatch", None, _("Create Patch"), None, _("Create a patch"), self.make_patch),
+ ("PrevConflict", None, _("Previous conflict"), "<Ctrl>I", _("Go to the previous conflict"), lambda x: self.on_next_conflict(gtk.gdk.SCROLL_UP)),
+ ("NextConflict", None, _("Next conflict"), "<Ctrl>K", _("Go to the next conflict"), lambda x: self.on_next_conflict(gtk.gdk.SCROLL_DOWN)),
("PushLeft", gtk.STOCK_GO_BACK, _("Push to left"), "<Alt>Left", _("Push current change to the left"), lambda x: self.push_change(-1)),
("PushRight", gtk.STOCK_GO_FORWARD, _("Push to right"), "<Alt>Right", _("Push current change to the right"), lambda x: self.push_change(1)),
# FIXME: using LAST and FIRST is terrible and unreliable icon abuse
@@ -206,6 +213,7 @@ class FileDiff(melddoc.MeldDoc, gnomeglade.Component):
t.connect("focus-out-event", self.on_current_diff_changed)
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)
def on_focus_change(self):
self.keymask = 0
@@ -271,7 +279,22 @@ class FileDiff(melddoc.MeldDoc, gnomeglade.Component):
if prev != self.cursor.prev or next != self.cursor.next:
self.emit("next-diff-changed", prev is not None,
next is not None)
+
+ prev_conflict, next_conflict = None, None
+ for conflict in self.linediffer.conflicts:
+ if prev is not None and conflict <= prev:
+ prev_conflict = conflict
+ if next is not None and conflict >= next:
+ next_conflict = conflict
+ break
+ if prev_conflict != self.cursor.prev_conflict or \
+ next_conflict != self.cursor.next_conflict:
+ self.emit("next-conflict-changed", prev_conflict is not None,
+ next_conflict is not None)
+
self.cursor.prev, self.cursor.next = prev, next
+ self.cursor.prev_conflict = prev_conflict
+ self.cursor.next_conflict = next_conflict
self.cursor.line, self.cursor.offset = line, offset
def on_current_diff_changed(self, widget, *args):
@@ -313,6 +336,24 @@ class FileDiff(melddoc.MeldDoc, gnomeglade.Component):
# FIXME: don't queue_draw() on everything... just on what changed
self.queue_draw()
+ def on_next_conflict_changed(self, doc, have_prev, have_next):
+ self.actiongroup.get_action("PrevConflict").set_sensitive(have_prev)
+ self.actiongroup.get_action("NextConflict").set_sensitive(have_next)
+
+ def on_next_conflict(self, direction):
+ if direction == gtk.gdk.SCROLL_DOWN:
+ target = self.cursor.next_conflict
+ else: # direction == gtk.gdk.SCROLL_UP
+ target = self.cursor.prev_conflict
+
+ if target is None:
+ return
+
+ buf = self.textbuffer[self.cursor.pane]
+ chunk = self.linediffer.get_chunk(target, self.cursor.pane)
+ buf.place_cursor(buf.get_iter_at_line(chunk[1]))
+ self.textview[self.cursor.pane].scroll_to_mark(buf.get_insert(), 0.1)
+
def push_change(self, direction):
src = self._get_focused_pane()
dst = src + direction
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]