Hi, Here is a new and improved version of the patch based on Kai's comments: - popup_in_pane() changes moved to a separate patch - new Changes menu - proper sensitivity setting - fixes for formatting issues
Comments welcome. Cheers, Piotr
From 3e43f50e715e7f7cc66eb28a61935af599632fd5 Mon Sep 17 00:00:00 2001 From: Piotr Piastucki <[email protected]> Date: Tue, 11 May 2010 13:13:29 +0200 Subject: [PATCH 1/2] Fix Copy All sensitivity Sensitivity of Copy All actions should depend on editable flag of the respective text view. --- meld/filediff.py | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/meld/filediff.py b/meld/filediff.py index 246e054..c5415a6 100644 --- a/meld/filediff.py +++ b/meld/filediff.py @@ -587,8 +587,8 @@ class FileDiff(melddoc.MeldDoc, gnomeglade.Component): self.findbar.hide() def popup_in_pane(self, pane): - self.actiongroup.get_action("CopyAllLeft").set_sensitive(pane > 0) - self.actiongroup.get_action("CopyAllRight").set_sensitive(pane+1 < self.num_panes) + self.actiongroup.get_action("CopyAllLeft").set_sensitive(pane > 0 and self.textview[pane - 1].get_editable()) + self.actiongroup.get_action("CopyAllRight").set_sensitive(pane + 1 < self.num_panes and self.textview[pane + 1].get_editable()) self.popup_menu.popup(None, None, None, 3, gtk.get_current_event_time()) def on_scrolledwindow__size_allocate(self, scrolledwindow, allocation): -- 1.7.0.4
From 8453395f05179da4d923ce0c8db1603e97eff458 Mon Sep 17 00:00:00 2001 From: Piotr Piastucki <[email protected]> Date: Wed, 12 May 2010 11:34:38 +0200 Subject: [PATCH 2/2] Add Changes menu and new change-related actions This commit adds a new menu called Changes and moves all existing actions related to manipulating or navigating chunks there. Moreover, a set of new bulk change actions is added including: Pull all non-conflicing and Merge all non-conflicting. --- data/ui/filediff-ui.xml | 15 ++++++++++--- data/ui/meldapp-ui.xml | 6 +---- meld/filediff.py | 49 +++++++++++++++++++++++++++++++++++++++++++++++ meld/meldapp.py | 2 + meld/merge.py | 45 ++++++++++++++++++++++++++++++++---------- 5 files changed, 97 insertions(+), 20 deletions(-) diff --git a/data/ui/filediff-ui.xml b/data/ui/filediff-ui.xml index 2df3e7f..26e35a4 100644 --- a/data/ui/filediff-ui.xml +++ b/data/ui/filediff-ui.xml @@ -15,15 +15,22 @@ </toolbar> <menubar name="Menubar"> - <menu action="EditMenu"> - <placeholder name="EditActionsPlaceholder"> + <placeholder name="ChangesMenuPlaceholder"> + <menu action="ChangesMenu"> + <menuitem action="Down"/> + <menuitem action="Up"/> + <separator/> <menuitem action="PushLeft"/> <menuitem action="PushRight"/> <menuitem action="PullLeft"/> <menuitem action="PullRight"/> <menuitem action="Delete"/> - </placeholder> - </menu> + <separator/> + <menuitem action="MergeNonConflicting"/> + <menuitem action="PullNonConflictingLeft"/> + <menuitem action="PullNonConflictingRight"/> + </menu> + </placeholder> </menubar> <popup name="Popup"> diff --git a/data/ui/meldapp-ui.xml b/data/ui/meldapp-ui.xml index 28c96b6..4b1244c 100644 --- a/data/ui/meldapp-ui.xml +++ b/data/ui/meldapp-ui.xml @@ -16,17 +16,13 @@ <menuitem action="Copy"/> <menuitem action="Paste"/> <separator/> - <placeholder name="EditActionsPlaceholder" /> - <separator/> <menuitem action="Find"/> <menuitem action="FindNext"/> <menuitem action="Replace"/> <separator/> - <menuitem action="Down"/> - <menuitem action="Up"/> - <separator/> <menuitem name="Preferences" action="Preferences"/> </menu> + <placeholder name="ChangesMenuPlaceholder" /> <menu action="ViewMenu"> <menuitem action="ToolbarVisible" /> <menuitem action="StatusbarVisible" /> diff --git a/meld/filediff.py b/meld/filediff.py index c5415a6..d058364 100644 --- a/meld/filediff.py +++ b/meld/filediff.py @@ -33,6 +33,7 @@ from ui import gnomeglade import misc import melddoc import paths +import merge from util.sourceviewer import srcviewer @@ -185,6 +186,9 @@ class FileDiff(melddoc.MeldDoc, gnomeglade.Component): ("Delete", gtk.STOCK_DELETE, _("Delete"), "<Alt>Delete", _("Delete change"), self.delete_change), ("CopyAllLeft", gtk.STOCK_GOTO_FIRST, _("Copy To Left"), None, _("Copy all changes from right pane to left pane"), lambda x: self.copy_selected(-1)), ("CopyAllRight", gtk.STOCK_GOTO_LAST, _("Copy To Right"), None, _("Copy all changes from left pane to right pane"), lambda x: self.copy_selected(1)), + ("MergeNonConflicting", None, _("Merge all non-conflicting"), None, _("Merge all non-conflicting changes from left and right pane"), lambda x: self.merge_all_non_conflicting_changes()), + ("PullNonConflictingLeft", None, _("Pull all non-conflicting from left"), None, _("Pull all non-conflicting changes from right pane to left pane"), lambda x: self.pull_all_non_conflicting_changes(-1)), + ("PullNonConflictingRight", None, _("Pull all non-conflicting from right"), None, _("Pull all non-conflicting changes from left pane to right pane"), lambda x: self.pull_all_non_conflicting_changes(1)), ) self.ui_file = paths.ui_dir("filediff-ui.xml") @@ -305,6 +309,21 @@ class FileDiff(melddoc.MeldDoc, gnomeglade.Component): self.actiongroup.get_action("PullLeft").set_sensitive(pull_left) self.actiongroup.get_action("PullRight").set_sensitive(pull_right) self.actiongroup.get_action("Delete").set_sensitive(delete) + editable = self.textview[pane].get_editable(); + sensitiveleft = sensitiveright = False + if editable: + for change in self.linediffer.pair_changes(pane - 1, pane): + if change[0] != 'conflict': + sensitiveleft = True + break + for change in self.linediffer.pair_changes(pane + 1, pane): + if change[0] != 'conflict': + sensitiveright = True + break + self.actiongroup.get_action("PullNonConflictingLeft").set_sensitive(pane > 0 and sensitiveleft and editable) + self.actiongroup.get_action("PullNonConflictingRight").set_sensitive(pane + 1 < self.num_panes and sensitiveright and editable) + self.actiongroup.get_action("MergeNonConflicting").set_sensitive(self.num_panes == 3 and self.textview[1].get_editable() and (sensitiveleft or sensitiveright)) + def push_change(self, direction): src = self._get_focused_pane() @@ -324,6 +343,34 @@ class FileDiff(melddoc.MeldDoc, gnomeglade.Component): assert(chunk is not None) self.replace_chunk(src, dst, chunk) + def pull_all_non_conflicting_changes(self, direction): + assert direction in (-1, 1) + dst = self._get_focused_pane() + src = dst + direction + assert src in range(self.num_panes) + merger = merge.Merger() + merger.differ = self.linediffer + merger.texts = [t for t in self._get_texts(raw=1)] + for mergedfile in merger.merge_2_files(src, dst): + pass + self.on_textbuffer__begin_user_action() + self.textbuffer[dst].set_text(mergedfile) + self.on_textbuffer__end_user_action() + self.emit("current-diff-changed") + self.scheduler.add_task(lambda: self._sync_vscroll(self.scrolledwindow[src].get_vadjustment(), src) and None) + + def merge_all_non_conflicting_changes(self): + merger = merge.Merger() + merger.differ = self.linediffer + merger.texts = [t for t in self._get_texts(raw=1)] + for mergedfile in merger.merge_3_files(False): + pass + self.on_textbuffer__begin_user_action() + self.textbuffer[1].set_text(mergedfile) + self.on_textbuffer__end_user_action() + self.emit("current-diff-changed") + self.scheduler.add_task(lambda: self._sync_vscroll(self.scrolledwindow[0].get_vadjustment(), 0) and None) + def delete_change(self, widget): pane = self._get_focused_pane() chunk = self.linediffer.get_chunk(self.cursor.chunk, pane) @@ -365,6 +412,8 @@ class FileDiff(melddoc.MeldDoc, gnomeglade.Component): if not line_end.ends_line(): line_end.forward_to_line_end() return self.buf.get_text(line_start, line_end, False) + def __len__(self): + return self.buf.get_line_count() class FakeTextArray(object): def __init__(self, bufs, textfilter): diff --git a/meld/meldapp.py b/meld/meldapp.py index 7de8ab3..968d8f2 100644 --- a/meld/meldapp.py +++ b/meld/meldapp.py @@ -445,6 +445,8 @@ class MeldApp(gnomeglade.Component): ("Up", gtk.STOCK_GO_UP, None, "<control>E", _("Go to the previous difference"), self.on_menu_edit_up_activate), ("Preferences", gtk.STOCK_PREFERENCES, _("Prefere_nces"), None, _("Configure the application"), self.on_menu_preferences_activate), + ("ChangesMenu", None, _("_Changes")), + ("ViewMenu", None, _("_View")), ("FileStatus", None, _("File status")), ("VcStatus", None, _("Version status")), diff --git a/meld/merge.py b/meld/merge.py index 3333f86..6583ae1 100644 --- a/meld/merge.py +++ b/meld/merge.py @@ -188,7 +188,7 @@ class Merger(diffutil.Differ): else: return change[HI] - change[LO] - def merge_3_files(self): + def merge_3_files(self, mark_conflicts = True): LO, HI = 1, 2 self.unresolved = [] lastline = 0 @@ -208,18 +208,19 @@ class Merger(diffutil.Differ): lastline = low_mark if change[0] != None and change[1] != None and change[0][0] == 'conflict': high_mark = max(change[0][HI], change[1][HI]) - if low_mark < high_mark: - for i in range(low_mark, high_mark): - mergedtext.append("(??)" + self.texts[1][i]) + if mark_conflicts: + if low_mark < high_mark: + for i in range(low_mark, high_mark): + mergedtext.append("(??)" + self.texts[1][i]) + self.unresolved.append(mergedline) + mergedline += 1 + else: + #conflictsize = min(1, max(change[0][HI + 2] - change[0][LO + 2], change[1][HI + 2] - change[1][LO + 2])) + #for i in range(conflictsize): + mergedtext.append("(??)") self.unresolved.append(mergedline) mergedline += 1 - else: - #conflictsize = min(1, max(change[0][HI + 2] - change[0][LO + 2], change[1][HI + 2] - change[1][LO + 2])) - #for i in range(conflictsize): - mergedtext.append("(??)") - self.unresolved.append(mergedline) - mergedline += 1 - lastline = high_mark + lastline = high_mark elif change[0] != None: lastline += self._apply_change(self.texts[0], change[0], mergedtext) mergedline += change[0][HI + 2] - change[0][LO + 2] @@ -231,3 +232,25 @@ class Merger(diffutil.Differ): mergedtext.append(self.texts[1][i]) yield "\n".join(mergedtext) + + def merge_2_files(self, fromindex, toindex): + LO, HI = 1, 2 + self.unresolved = [] + lastline = 0 + mergedtext = [] + for change in self.differ.pair_changes(toindex, fromindex): + yield None + if change[0] == 'conflict': + low_mark = change[HI] + else: + low_mark = change[LO] + for i in range(lastline, low_mark, 1): + mergedtext.append(self.texts[toindex][i]) + lastline = low_mark + if change[0] != 'conflict': + lastline += self._apply_change(self.texts[fromindex], change, mergedtext) + baselen = len(self.texts[toindex]) + for i in range(lastline, baselen, 1): + mergedtext.append(self.texts[toindex][i]) + + yield "\n".join(mergedtext) -- 1.7.0.4
_______________________________________________ meld-list mailing list [email protected] http://mail.gnome.org/mailman/listinfo/meld-list
