Commit e08baf62 authored by Kai Willadsen's avatar Kai Willadsen

Support new tab opening using D-Bus (closes bgo#616466, bgo#453670)

The goal of this patch is to support opening new tabs in an existing
instance from the command line, enabled by passing a new command line
flag. Communication between instances is enabled by D-Bus.

New tab opening is not the default behaviour, since many VC systems
launch Meld and block waiting for an exit code to indicate success or
failure when doing merges, and we can't break this expectation.

This commit introduces an optional dependency on dbus packages.

Based on a patch from Kacper Wysocki and Antoine.
parent 2be7b904
......@@ -133,9 +133,17 @@ gtk.icon_theme_get_default().append_search_path(meld.paths.icon_dir())
def main():
from meld.meldapp import app
try:
import meld.dbus_service
already_running, dbus_app = meld.dbus_service.setup(app)
except ImportError:
already_running, dbus_app = False, None
meld.meldapp.dbus_app = dbus_app
app.create_window()
app.parse_args(sys.argv[1:])
gtk.main()
new_window = app.parse_args(sys.argv[1:])
if new_window or not already_running:
gtk.main()
if profiling:
import profile
......
# Copyright (C) 2011 Kai Willadsen <kai.willadsen@gmail.com>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
"""This module encapsulates optional D-Bus support for Meld."""
import dbus
import dbus.bus
import dbus.service
import dbus.mainloop.glib
DBUS_NAME = "org.gnome.Meld"
DBUS_PATH = "/org/gnome/Meld"
if getattr(dbus, 'version', (0, 0, 0)) < (0, 83, 0):
raise ImportError("Unsupported dbus version")
class DBusProvider(dbus.service.Object):
"""Implements a simple interface for controlling a MeldApp."""
def __init__(self, bus, name, path, app):
dbus.service.Object.__init__(self, bus, path, name)
self.app = app
@dbus.service.method(DBUS_NAME, in_signature='asu')
def OpenPaths(self, args, timestamp):
"""Attempt to open a new tab comparing the passed paths.
If a valid timestamp is not available, pass 0.
"""
self.app.window.open_paths(args)
if timestamp > 0:
self.app.window.widget.present_with_time(timestamp)
else:
self.app.window.widget.present()
def setup(app):
"""Request and return a dbus interface for controlling the MeldApp."""
dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
bus = dbus.SessionBus()
request = bus.request_name(DBUS_NAME, dbus.bus.NAME_FLAG_DO_NOT_QUEUE)
already_running = request == dbus.bus.REQUEST_NAME_REPLY_EXISTS
if already_running:
obj = dbus.Interface(bus.get_object(DBUS_NAME, DBUS_PATH), DBUS_NAME)
else:
obj = DBusProvider(bus, DBUS_NAME, DBUS_PATH, app)
return already_running, obj
......@@ -167,6 +167,8 @@ class MeldApp(gobject.GObject):
version="%prog " + version)
parser.add_option("-L", "--label", action="append", default=[],
help=_("Set label to use instead of file name"))
parser.add_option("-n", "--newtab", action="store_true", default=False,
help=_("Open a new tab in an already running instance"))
parser.add_option("-a", "--auto-compare", action="store_true", default=False,
help=_("Automatically compare all differing files on startup"))
parser.add_option("-u", "--unified", action="store_true",
......@@ -183,18 +185,29 @@ class MeldApp(gobject.GObject):
elif len(args) == 4 and any([os.path.isdir(f) for f in args]):
parser.error(_("can't compare more than three directories"))
new_window = True
open_paths = self.window.open_paths
if options.newtab:
if not dbus_app:
print _("D-Bus error; comparisons will open in a new window.")
else:
open_paths = lambda f, x: dbus_app.OpenPaths(f, 0)
new_window = False
for files in options.diff:
if len(files) == 4 and any([os.path.isdir(f) for f in files]):
parser.error(_("can't compare more than three directories"))
self.window.open_paths(files)
open_paths(files)
tab = self.window.open_paths(args, options.auto_compare)
tab = open_paths(args, options.auto_compare)
if options.label and tab:
tab.set_labels(options.label)
if options.outfile and tab and isinstance(tab, filediff.FileDiff):
tab.set_merge_output_file(options.outfile)
return new_window
app = MeldApp()
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment