Skip to content

Commit 0fccdab

Browse files
committed
Add recently-used comparison support (closes bgo#652747)
The recent-files API provided by GTK+ doesn't actually work for Meld out-of-the-box, because instead of storing individual files, we need to stored multiple linked files. In other words, we need to store a comparison, not a file. This commit adds support for reading and writing a simple comparison record format with a new Meld-specific mime-type. These files are stored under the user data directory, and are managed by the new 'recent' module. Meld creates these files for new top-level comparisons and inserts them into the recently-used store as proxies for the actual file tuples. Note that we deliberately avoid recording as recently-used comparisons that are invoked from other comparisons; a user may open ten quick file comparisons from a single VC comparison, but they probably don't actually want to re-open those from the recent files menu. There is also support for opening comparison files from the command line. This was added so that recent comparisons can be opened from the desktop recent files menu, but can also be used to manually open specified comparisons.
1 parent b831bb7 commit 0fccdab

12 files changed

Lines changed: 316 additions & 2 deletions

File tree

Makefile

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ SPECIALS := bin/meld meld/paths.py
1212
BROWSER := firefox
1313

1414
.PHONY:all
15-
all: $(addsuffix .install,$(SPECIALS)) meld.desktop
15+
all: $(addsuffix .install,$(SPECIALS)) meld.desktop meld.xml
1616
$(MAKE) -C po
1717
$(MAKE) -C help
1818

@@ -22,6 +22,7 @@ clean:
2222
xargs -0 rm -f
2323
@find ./bin -type f \( -name '*.install' \) -print0 | xargs -0 rm -f
2424
@rm -f data/meld.desktop
25+
@rm -f data/mime/meld.xml
2526
$(MAKE) -C po clean
2627
$(MAKE) -C help clean
2728

@@ -60,6 +61,8 @@ install: $(addsuffix .install,$(SPECIALS)) meld.desktop
6061
$(DESTDIR)$(libdir_)/meld/paths.py
6162
install -m 644 data/meld.desktop \
6263
$(DESTDIR)$(sharedir)/applications
64+
install -m 644 data/mime/meld.xml \
65+
$(DESTDIR)$(sharedir)/mime/packages/
6366
$(PYTHON) -c 'import compileall; compileall.compile_dir("$(DESTDIR)$(libdir_)",10,"$(libdir_)")'
6467
$(PYTHON) -O -c 'import compileall; compileall.compile_dir("$(DESTDIR)$(libdir_)",10,"$(libdir_)")'
6568
install -m 644 data/gtkrc \
@@ -88,10 +91,14 @@ install: $(addsuffix .install,$(SPECIALS)) meld.desktop
8891
$(DESTDIR)$(sharedir)/icons/HighContrast/scalable/apps/meld.svg
8992
$(MAKE) -C po install
9093
$(MAKE) -C help install
94+
update-mime-database $(DESTDIR)$(sharedir)/mime
9195

9296
meld.desktop: data/meld.desktop.in
9397
intltool-merge -d po data/meld.desktop.in data/meld.desktop
9498

99+
meld.xml: data/meld.xml.in
100+
intltool-merge -d po data/mime/meld.xml.in data/mime/meld.xml
101+
95102
%.install: %
96103
$(PYTHON) tools/install_paths \
97104
libdir=$(libdir_) \
@@ -109,7 +116,9 @@ uninstall:
109116
$(libdir_) \
110117
$(bindir)/meld \
111118
$(sharedir)/applications/meld.desktop \
119+
$(sharedir)/mime/packages/meld.xml \
112120
$(sharedir)/pixmaps/meld.png
113121
$(MAKE) -C po uninstall
114122
$(MAKE) -C help uninstall
123+
update-mime-database $(DESTDIR)$(sharedir)/mime
115124

data/meld.desktop.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ Exec=meld %F
77
Terminal=false
88
Type=Application
99
Icon=meld
10+
MimeType=application/x-meld-comparison
1011
StartupNotify=true
1112
Categories=GTK;Development;
1213
X-GNOME-Bugzilla-Bugzilla=GNOME

data/mime/meld.xml.in

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<mime-info xmlns="http://www.freedesktop.org/standards/shared-mime-info">
3+
<mime-type type="application/x-meld-comparison">
4+
<comment>Meld comparison description</comment>
5+
<glob pattern="*.meldcmp"/>
6+
<icon name="meld"/>
7+
</mime-type>
8+
</mime-info>

data/ui/meldapp-ui.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
<separator/>
88
<placeholder name="FileActionsPlaceholder" />
99
<separator/>
10+
<menuitem action="Recent" />
1011
<menuitem action="Close" />
1112
<menuitem action="Quit" />
1213
</menu>

meld/dirdiff.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
from . import tree
3333
from . import misc
3434
from . import paths
35+
from . import recent
3536
from .ui import gnomeglade
3637
from .ui import emblemcellrenderer
3738

@@ -496,6 +497,14 @@ def set_locations(self, locations):
496497
self.recursively_update( (0,) )
497498
self._update_diffmaps()
498499

500+
def get_comparison(self):
501+
root = self.model.get_iter_root()
502+
if root:
503+
folders = self.model.value_paths(root)
504+
else:
505+
folders = []
506+
return recent.TYPE_FOLDER, folders
507+
499508
def recursively_update( self, path ):
500509
"""Recursively update from tree path 'path'.
501510
"""

meld/filediff.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
from . import misc
4141
from . import patchdialog
4242
from . import paths
43+
from . import recent
4344
from . import undo
4445
from .ui import findbar
4546
from .ui import gnomeglade
@@ -980,6 +981,10 @@ def set_files(self, files):
980981
self._connect_buffer_handlers()
981982
self.scheduler.add_task(self._set_files_internal(files))
982983

984+
def get_comparison(self):
985+
files = [b.data.filename for b in self.textbuffer[:self.num_panes]]
986+
return recent.TYPE_FILE, files
987+
983988
def _load_files(self, files, textbuffers):
984989
self.undosequence.clear()
985990
yield _("[%s] Set num panes") % self.label_text

meld/filemerge.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
from . import filediff
2424
from . import meldbuffer
2525
from . import merge
26+
from . import recent
2627

2728

2829
class FileMerge(filediff.FileDiff):
@@ -34,6 +35,10 @@ def _connect_buffer_handlers(self):
3435
self.textview[0].set_editable(0)
3536
self.textview[2].set_editable(0)
3637

38+
def get_comparison(self):
39+
comp = filediff.FileDiff.get_comparison(self)
40+
return recent.TYPE_MERGE, comp[1]
41+
3742
def _set_files_internal(self, files):
3843
self.textview[1].set_buffer(meldbuffer.MeldBuffer())
3944
for i in self._load_files(files, self.textbuffer):

meld/meldapp.py

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,16 @@
2121
import logging
2222
import optparse
2323
import os
24+
import sys
2425
from gettext import gettext as _
2526

27+
import gio
2628
import gobject
2729
import gtk
2830

2931
from . import filters
3032
from . import preferences
33+
from . import recent
3134

3235
version = "1.7.0"
3336

@@ -50,6 +53,7 @@ def __init__(self):
5053
filters.FilterEntry.SHELL)
5154
self.text_filters = self._parse_filters(self.prefs.regexes,
5255
filters.FilterEntry.REGEX)
56+
self.recent_comparisons = recent.RecentFiles(sys.argv[0])
5357

5458
def create_window(self):
5559
self.window = meldwindow.MeldWindow()
@@ -115,6 +119,9 @@ def parse_args(self, rawargs):
115119
help=_("Set the target file for saving a merge result"))
116120
parser.add_option("--auto-merge", None, action="store_true", default=False,
117121
help=_("Automatically merge files"))
122+
parser.add_option("", "--comparison-file", action="store",
123+
type="string", dest="comparison_file", default=None,
124+
help=_("Load a saved comparison from a Meld comparison file"))
118125
parser.add_option("", "--diff", action="callback", callback=self.diff_files_callback,
119126
dest="diff", default=[],
120127
help=_("Creates a diff tab for up to 3 supplied files or directories."))
@@ -140,7 +147,16 @@ def parse_args(self, rawargs):
140147
for files in options.diff:
141148
open_paths(files)
142149

143-
tab = open_paths(args, options.auto_compare, options.auto_merge)
150+
if options.comparison_file:
151+
comparison_file_path = os.path.expanduser(options.comparison_file)
152+
gio_file = gio.File(path=comparison_file_path)
153+
try:
154+
tab = self.window.append_recent(gio_file.get_uri())
155+
except (IOError, ValueError):
156+
parser.error(_("Error reading saved comparison file"))
157+
elif args:
158+
tab = open_paths(args, options.auto_compare, options.auto_merge)
159+
144160
if options.label and tab:
145161
tab.set_labels(options.label)
146162

meld/melddoc.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,10 @@ def __init__(self, prefs):
6262
def get_info_widgets(self):
6363
return self.status_info_labels
6464

65+
def get_comparison(self):
66+
"""Get the comparison type and path(s) being compared"""
67+
pass
68+
6569
def save(self):
6670
pass
6771

meld/meldwindow.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
from . import misc
3030
from . import paths
3131
from . import preferences
32+
from . import recent
3233
from . import task
3334
from . import vcview
3435
from .ui import gnomeglade
@@ -89,6 +90,9 @@ def on_response(self, dialog, arg):
8990
new_tab_idx = self.parentapp.notebook.page_num(new_tab.widget)
9091
self.parentapp.notebook.set_current_page(new_tab_idx)
9192

93+
diff_type = recent.COMPARISON_TYPES[page]
94+
app.recent_comparisons.add(new_tab)
95+
9296
self.widget.destroy()
9397

9498

@@ -162,6 +166,15 @@ def __init__(self):
162166
self.actiongroup.set_translation_domain("meld")
163167
self.actiongroup.add_actions(actions)
164168
self.actiongroup.add_toggle_actions(toggleactions)
169+
170+
recent_action = gtk.RecentAction("Recent", _("Open Recent"),
171+
_("Open recent files"), None)
172+
recent_action.set_show_private(True)
173+
recent_action.set_filter(app.recent_comparisons.recent_filter)
174+
recent_action.set_sort_type(gtk.RECENT_SORT_MRU)
175+
recent_action.connect("item-activated", self.on_action_recent)
176+
self.actiongroup.add_action(recent_action)
177+
165178
self.ui = gtk.UIManager()
166179
self.ui.insert_action_group(self.actiongroup, 0)
167180
self.ui.add_ui_from_file(ui_file)
@@ -391,6 +404,16 @@ def on_menu_save_activate(self, menuitem):
391404
def on_menu_save_as_activate(self, menuitem):
392405
self.current_doc().save_as()
393406

407+
def on_action_recent(self, action):
408+
uri = action.get_current_uri()
409+
if not uri:
410+
return
411+
try:
412+
self.append_recent(uri)
413+
except (IOError, ValueError):
414+
# FIXME: Need error handling, but no sensible display location
415+
pass
416+
394417
def on_menu_close_activate(self, *extra):
395418
i = self.notebook.get_current_page()
396419
if i >= 0:
@@ -672,6 +695,19 @@ def append_vcview(self, location, auto_compare=False):
672695
doc.on_button_diff_clicked(None)
673696
return doc
674697

698+
def append_recent(self, uri):
699+
comparison_type, files, flags = app.recent_comparisons.read(uri)
700+
if comparison_type == recent.TYPE_MERGE:
701+
tab = self.append_filemerge(files)
702+
elif comparison_type == recent.TYPE_FOLDER:
703+
tab = self.append_dirdiff(files)
704+
elif comparison_type == recent.TYPE_VC:
705+
tab = self.append_vcview(files)
706+
else: # comparison_type == recent.TYPE_FILE:
707+
tab = self.append_filediff(files)
708+
app.recent_comparisons.add(tab)
709+
return tab
710+
675711
def _single_file_open(self, path):
676712
doc = vcview.VcView(app.prefs)
677713
def cleanup():
@@ -694,6 +730,7 @@ def open_paths(self, paths, auto_compare=False, auto_merge=False):
694730

695731
elif len(paths) in (2, 3):
696732
tab = self.append_diff(paths, auto_compare, auto_merge)
733+
app.recent_comparisons.add(tab)
697734
return tab
698735

699736
def current_doc(self):

0 commit comments

Comments
 (0)