open diffs in new tab of existing meld instance



Hi all,
some time ago I wrote a patch[1] to open meld diffs in new tabs of
existing windows. I've been using the patch for 7 months now and I've
found it's really useful in combination with source control systems,
especially when merging and commiting changes.

I've posted a bug[2] and pre-built debian&ubuntu packages[3] and I
would really like it if this new feature had some testing beyond me
and a couple of my friends. I've updated the patch to apply cleanly to
meld 1.1.5.

Technical details for the additions of this small patch:
1) move argument parsing to a method
2) instrument this method with dbus
3) on startup, check if the meld dbus interface is registered, and use it
4) The fix from meld 1.1.4 to 1.1.5 is in the use of optargs.

[1] http://mail.gnome.org/archives/meld-list/2006-November/msg00005.html
[2] http://bugzilla.gnome.org/show_bug.cgi?id=453670
[3] http://kacper.doesntexist.org/hacks/#meld

diff -Naur meld-1.1.5/meldapp.py meld-1.1.5-dbus/meldapp.py
--- meld-1.1.5/meldapp.py       2007-06-09 19:29:28.000000000 +0200
+++ meld-1.1.5-dbus/meldapp.py  2007-07-26 11:46:09.000000000 +0200
@@ -34,6 +34,23 @@
import task

# optional
+# dbus
+dbus_available = 0
+try:
+    import dbus
+    import dbus.service
+    if getattr(dbus, 'version', (0,0,0)) >= (0,41,0):
+        import dbus.glib
+        dbus_available = 1
+    else:
+        pass # dbus version too old
+except ImportError:
+    pass
+    # FIXME: Do I print this error or give the silent treatement?
+    #print "Oops, no dbus. Please install the python-dbus package."
+    #print "Meld will not be able to launch new diffs in existing window."
+
+# sourceview
sourceview_available = 0

for sourceview in "gtksourceview sourceview".split():
@@ -814,9 +831,34 @@
            [(gtk.STOCK_QUIT, gtk.RESPONSE_CANCEL), (gtk.STOCK_OK,
gtk.RESPONSE_OK)] )
        if response == gtk.RESPONSE_CANCEL:
            sys.exit(0)
-
-
-
+
+    def parseargs(self, args, label = []):
+        tab = None
+        if len(args) == 0:
+            pass
+
+        elif len(args) == 1:
+            a = args[0]
+            if os.path.isfile(a):
+                doc = vcview.VcView(self.prefs)
+                def cleanup():
+                    self.scheduler.remove_scheduler(doc.scheduler)
+                self.scheduler.add_task(cleanup)
+                self.scheduler.add_scheduler(doc.scheduler)
+                doc.set_location( os.path.dirname(a) )
+                doc.connect("create-diff", lambda obj,arg:
self.append_diff(arg) )
+                doc.run_diff([a])
+            else:
+                tab = self.append_vcview( [a] )
+
+        elif len(args) in (2,3):
+            tab = self.append_diff(args)
+        else:
+            self.usage( _("Wrong number of arguments (Got %i)") % len(args))
+
+        if tab:
+            tab.set_labels( label )
+
################################################################################
#
# usage
@@ -828,6 +870,56 @@

################################################################################
#
+# DBus stuff
+#
+# You either have dbus, or you don't.
+# If you don't, I can't help yah,
+# if you do, you either have meld running already or you don't.
+#
+# If you don't, I'll register the meld dbus interface,
+# if you do, you either want a new window or not.
+#
+# If you don't, I'll pass those args along the bus,
+# if you do, I'll just start a new window.
+#
+# -Kacper Wysocki (comotion users sf net)
+#
+################################################################################
+
+class MeldDbus(dbus.service.Object):
+    def __init__(self, bus_name, app, object_path='/net/sf/meld'):
+        dbus.service.Object.__init__(self, bus_name, object_path)
+        self.app = app
+
+    @dbus.service.method('net.sf.meld')
+    def diff(self, args):
+        self.app.parseargs(args)
+
+def register_dbus(app):
+    session_bus = dbus.SessionBus()
+    bus_name = dbus.service.BusName('net.sf.meld', bus=session_bus)
+    remotemeld = MeldDbus(bus_name, app)
+
+def try_dbus():
+    bus = dbus.SessionBus()
+    proxy = bus.get_object('org.freedesktop.DBus',
+                           '/org/freedesktop/DBus')
+    iface = dbus.Interface(proxy, 'org.freedesktop.DBus')
+    names = iface.ListNames()
+    if "net.sf.meld" in names: # does meld dbus interface exist?
+        return 1 # Found a running instance, passed things along
+    return 0 # didn't
+
+def pass_args_dbus(args):
+    bus = dbus.SessionBus()
+    proxy = bus.get_object('net.sf.meld','/net/sf/meld')
+    iface = dbus.Interface(proxy, 'net.sf.meld')
+    iface.diff(args)
+
+
+
+################################################################################
+#
# Main
#
################################################################################
@@ -842,7 +934,6 @@
        def __getattr__(self, attr):
            return getattr(self.file, attr)
    sys.stdout = Unbuffered(sys.stdout)
-
    parser = optparse.OptionParser(
    usage="""
    %prog                       Start with no windows open
@@ -853,38 +944,25 @@
    description="""Meld is a file and directory comparison tool.""",
    version="%prog "+version)
    parser.add_option("-L", "--label", action="append", default=[],
help=_("Set label to use instead of file name"))
+    parser.add_option("-n", "--new-window", action="store_true",
dest="force_window", help=_("Open new window regardless"))
    parser.add_option("-u", "--unified", action="store_true",
help=_("Ignored for compatibility"))
    parser.add_option("-c", "--context", action="store_true",
help=_("Ignored for compatibility"))
    parser.add_option("-e", "--ed", action="store_true",
help=_("Ignored for compatibility"))
    parser.add_option("-r", "--recursive", action="store_true",
help=_("Ignored for compatibility"))
    options, args = parser.parse_args()

+    running_already = 0
+    if dbus_available:
+        running_already = try_dbus()
+        if running_already:
+            if args and not options.force_window:
+                pass_args_dbus(args)
+                return
+    # either you're forcing a new window or it ain't running yet
    app = MeldApp()
-    tab = None
-
-    if len(args) == 0:
-        pass
-
-    elif len(args) == 1:
-        a = args[0]
-        if os.path.isfile(a):
-            doc = vcview.VcView(app.prefs)
-            def cleanup():
-                app.scheduler.remove_scheduler(doc.scheduler)
-            app.scheduler.add_task(cleanup)
-            app.scheduler.add_scheduler(doc.scheduler)
-            doc.set_location( os.path.dirname(a) )
-            doc.connect("create-diff", lambda obj,arg: app.append_diff(arg) )
-            doc.run_diff([a])
-        else:
-            tab = app.append_vcview( [a] )
-
-    elif len(args) in (2,3):
-        tab = app.append_diff(args)
-    else:
-        app.usage( _("Wrong number of arguments (Got %i)") % len(args))
+    if dbus_available and not running_already:
+        register_dbus(app)

-    if tab:
-        tab.set_labels( options.label )
+    app.parseargs(args, options.label)
    app.main()


--
http://kacper.doesntexist.org
http://windows.dontexist.net
There is symmetry in chaos, and chaos in overmuch order.



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