Re: opening new diffs in existing window



On 11/2/06, Stephen Kennedy <stevek gnome org> wrote:
> > I really like meld for visual diffing, but I often have several files
> > diffed at the same time, so it would be very helpful to have new diffs
> > open in an existing meld window - something that for example gedit
> > currently does. To be precise, I would like meld to check, on startup,
> > if there's another instance open already and if it is, open the
> > requested diff in a new tab in the existing window. What's great is
> > that meld already has tabs - all we need to do is check for an
> > existing instance on startup, and pass it the arguments.

> The most modern gnomish library for handling IPC is probably dbus, and
> appears to be what evince uses for this type of "successive concurrent
> executions open within the original parent process" functionality. See

dbus is certainly the way to go here. The python binding are quite good too.

It would also solve another tricky problem. Meld does not return a
useful exit code because of the tabbed interface, which confuses some
tools. It would be great to have a helper app which can open a single
tab and wait for its exit status.

What follows is a patch against meld-1.1.3 that implements
open-in-existing-window functionality through dbus. The limitation is
that the dbus bingings require python 2.4 for remote object instances.
If dbus is not installed on the system, meld will silently ignore all
the dbus stuff, but I could alternatively print a message informing
the user.

I haven't looked at returning a useful return code, but the dbus
support is easily extendible if anyone's interested in doing that.

I may have done things in a way not agreeable with the original
creators. Comments, criticism, questions welcome and appreciated. In
case the inline patch is frobbed by some mail system, you can also
find the patch at:
http://kacper.doesntexist.org/hacks/meld-dbus.patch

diff -ru meld-1.1.3/meldapp.py meld-1.1.3-kw/meldapp.py
--- meld-1.1.3/meldapp.py	2006-01-29 01:17:28.000000000 +0100
+++ meld-1.1.3-kw/meldapp.py	2006-11-18 13:05:23.584357970 +0100
@@ -34,6 +34,24 @@
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():
@@ -787,6 +805,30 @@
            sys.exit(0)


+    def parseargs(self,args):
+        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:
+                self.append_vcview( [a] )
+
+        elif len(args) in (2,3):
+            self.append_diff(args)
+        else:
+            self.usage( _("Wrong number of arguments (Got %i)") % len(args))
+

################################################################################
#
@@ -804,6 +846,7 @@
Options:
    -h, --help                  Show this help text and exit
    -v, --version               Display the version and exit
+    -n, --new-window            Open new window regardless

For more information choose help -> contents.
Report bugs at http://bugzilla.gnome.org/buglist.cgi?product=meld
@@ -815,6 +858,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
#
################################################################################
@@ -829,6 +922,7 @@
            return getattr(self.file, attr)
    sys.stdout = Unbuffered(sys.stdout)
    args = sys.argv[1:]
+    force_new_window = 0

    if args:
        if "-h" in args or "--help" in args:
@@ -837,30 +931,22 @@
        if "-v" in args or "--version" in args:
            print version_string
            return
+        if "-n" in args or "--new-window" in args:
+            force_new_window = 1

-    app = MeldApp()

-    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:
-            app.append_vcview( [a] )
-
-    elif len(args) in (2,3):
-        app.append_diff(args)
-    else:
-        app.usage( _("Wrong number of arguments (Got %i)") % len(args))
+    running_already = 0
+    if dbus_available:
+        running_already = try_dbus()
+        if running_already:
+            if args and not force_new_window:
+                pass_args_dbus(args)
+                return
+    # either you're forcing a new window or it ain't running yet
+    app = MeldApp()
+    if dbus_available and not running_already:
+        register_dbus(app)

+    app.parseargs(args)
    app.main()



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