Blame plugins/synctex/synctex/evince_dbus.py

Packit 6978fb
#!/usr/bin/python
Packit 6978fb
# -*- coding: utf-8 -*-
Packit 6978fb
Packit 6978fb
# This file is part of the Gedit Synctex plugin.
Packit 6978fb
#
Packit 6978fb
# Copyright (C) 2010 Jose Aliste <jose.aliste@gmail.com>
Packit 6978fb
#
Packit 6978fb
# This program is free software; you can redistribute it and/or modify it under
Packit 6978fb
# the terms of the GNU General Public Licence as published by the Free Software
Packit 6978fb
# Foundation; either version 2 of the Licence, or (at your option) any later
Packit 6978fb
# version.
Packit 6978fb
#
Packit 6978fb
# This program is distributed in the hope that it will be useful, but WITHOUT
Packit 6978fb
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
Packit 6978fb
# FOR A PARTICULAR PURPOSE.  See the GNU General Public Licence for more
Packit 6978fb
# details.
Packit 6978fb
#
Packit 6978fb
# You should have received a copy of the GNU General Public Licence along with
Packit 6978fb
# this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
Packit 6978fb
# Street, Fifth Floor, Boston, MA  02110-1301, USA
Packit 6978fb
Packit 6978fb
import dbus, subprocess, time
Packit 6978fb
Packit 6978fb
RUNNING, CLOSED = range(2)
Packit 6978fb
Packit 6978fb
EV_DAEMON_PATH = "/org/gnome/evince/Daemon"
Packit 6978fb
EV_DAEMON_NAME = "org.gnome.evince.Daemon"
Packit 6978fb
EV_DAEMON_IFACE = "org.gnome.evince.Daemon"
Packit 6978fb
Packit 6978fb
EVINCE_PATH = "/org/gnome/evince/Evince"
Packit 6978fb
EVINCE_IFACE = "org.gnome.evince.Application"
Packit 6978fb
Packit 6978fb
EV_WINDOW_IFACE = "org.gnome.evince.Window"
Packit 6978fb
Packit 6978fb
Packit 6978fb
Packit 6978fb
class EvinceWindowProxy:
Packit 6978fb
    """A DBUS proxy for an Evince Window."""
Packit 6978fb
    daemon = None
Packit 6978fb
    bus = None
Packit 6978fb
Packit 6978fb
    def __init__(self, uri, spawn = False, logger = None):
Packit 6978fb
        self._log = logger
Packit 6978fb
        self.uri = uri
Packit 6978fb
        self.spawn = spawn
Packit 6978fb
        self.status = CLOSED
Packit 6978fb
        self.source_handler = None
Packit 6978fb
        self.dbus_name = ''
Packit 6978fb
        self._handler = None
Packit 6978fb
        try:
Packit 6978fb
            if EvinceWindowProxy.bus is None:
Packit 6978fb
                EvinceWindowProxy.bus = dbus.SessionBus()
Packit 6978fb
Packit 6978fb
            if EvinceWindowProxy.daemon is None:
Packit 6978fb
                EvinceWindowProxy.daemon = EvinceWindowProxy.bus.get_object(EV_DAEMON_NAME,
Packit 6978fb
                                                EV_DAEMON_PATH,
Packit 6978fb
                                                follow_name_owner_changes=True)
Packit 6978fb
            EvinceWindowProxy.bus.add_signal_receiver(self._on_doc_loaded, signal_name="DocumentLoaded", 
Packit 6978fb
                                                      dbus_interface = EV_WINDOW_IFACE, 
Packit 6978fb
                                                      sender_keyword='sender')
Packit 6978fb
            self._get_dbus_name(False)
Packit 6978fb
Packit 6978fb
        except dbus.DBusException:
Packit 6978fb
            if self._log:
Packit 6978fb
                self._log.debug("Could not connect to the Evince Daemon")
Packit 6978fb
Packit 6978fb
    def _on_doc_loaded(self, uri, **keyargs):
Packit 6978fb
        if uri == self.uri and self._handler is None:
Packit 6978fb
            self.handle_find_document_reply(keyargs['sender'])
Packit 6978fb
        
Packit 6978fb
    def _get_dbus_name(self, spawn):
Packit 6978fb
        EvinceWindowProxy.daemon.FindDocument(self.uri,spawn,
Packit 6978fb
                     reply_handler=self.handle_find_document_reply,
Packit 6978fb
                     error_handler=self.handle_find_document_error,
Packit 6978fb
                     dbus_interface = EV_DAEMON_IFACE)
Packit 6978fb
Packit 6978fb
    def handle_find_document_error(self, error):
Packit 6978fb
        if self._log:
Packit 6978fb
            self._log.debug("FindDocument DBus call has failed")
Packit 6978fb
Packit 6978fb
    def handle_find_document_reply(self, evince_name):
Packit 6978fb
        if self._handler is not None:
Packit 6978fb
            handler = self._handler
Packit 6978fb
        else:
Packit 6978fb
            handler = self.handle_get_window_list_reply
Packit 6978fb
        if evince_name != '':
Packit 6978fb
            self.dbus_name = evince_name
Packit 6978fb
            self.status = RUNNING
Packit 6978fb
            self.evince = EvinceWindowProxy.bus.get_object(self.dbus_name, EVINCE_PATH)
Packit 6978fb
            self.evince.GetWindowList(dbus_interface = EVINCE_IFACE,
Packit 6978fb
                          reply_handler = handler,
Packit 6978fb
                          error_handler = self.handle_get_window_list_error)
Packit 6978fb
Packit 6978fb
    def handle_get_window_list_error (self, e):
Packit 6978fb
        if self._log:
Packit 6978fb
            self._log.debug("GetWindowList DBus call has failed")
Packit 6978fb
Packit 6978fb
    def handle_get_window_list_reply (self, window_list):
Packit 6978fb
        if len(window_list) > 0:
Packit 6978fb
            window_obj = EvinceWindowProxy.bus.get_object(self.dbus_name, window_list[0])
Packit 6978fb
            self.window = dbus.Interface(window_obj,EV_WINDOW_IFACE)
Packit 6978fb
            self.window.connect_to_signal("Closed", self.on_window_close)
Packit 6978fb
            self.window.connect_to_signal("SyncSource", self.on_sync_source)
Packit 6978fb
        else:
Packit 6978fb
            #That should never happen. 
Packit 6978fb
            if self._log:
Packit 6978fb
                self._log.debug("GetWindowList returned empty list")
Packit 6978fb
Packit 6978fb
Packit 6978fb
    def set_source_handler (self, source_handler):
Packit 6978fb
        self.source_handler = source_handler
Packit 6978fb
Packit 6978fb
    def on_window_close(self):
Packit 6978fb
        self.window = None
Packit 6978fb
        self.status = CLOSED
Packit 6978fb
Packit 6978fb
    def on_sync_source(self, input_file, source_link, timestamp):
Packit 6978fb
        if self.source_handler is not None:
Packit 6978fb
            self.source_handler(input_file, source_link, timestamp)
Packit 6978fb
Packit 6978fb
    def SyncView(self, input_file, data, time):
Packit 6978fb
        if self.status == CLOSED:
Packit 6978fb
            if self.spawn:
Packit 6978fb
                self._tmp_syncview = [input_file, data, time];
Packit 6978fb
                self._handler = self._syncview_handler
Packit 6978fb
                self._get_dbus_name(True)
Packit 6978fb
        else:
Packit 6978fb
            self.window.SyncView(input_file, data, time,  dbus_interface = "org.gnome.evince.Window")
Packit 6978fb
Packit 6978fb
    def _syncview_handler(self, window_list):
Packit 6978fb
        self.handle_get_window_list_reply(window_list)
Packit 6978fb
Packit 6978fb
        if self.status == CLOSED: 
Packit 6978fb
            return False
Packit 6978fb
        self.window.SyncView(self._tmp_syncview[0],self._tmp_syncview[1], self._tmp_syncview[2], dbus_interface="org.gnome.evince.Window")
Packit 6978fb
        del self._tmp_syncview
Packit 6978fb
        self._handler = None
Packit 6978fb
        return True
Packit 6978fb
Packit 6978fb
## This file can be used as a script to support forward search and backward search in vim.
Packit 6978fb
## It should be easy to adapt to other editors. 
Packit 6978fb
##  evince_dbus  pdf_file  line_source input_file
Packit 6978fb
if __name__ == '__main__':
Packit 6978fb
    import dbus.mainloop.glib, sys, os, logging
Packit 6978fb
    from gi.repository import GObject
Packit 6978fb
Packit 6978fb
    def print_usage():
Packit 6978fb
        print('''
Packit 6978fb
The usage is evince_dbus output_file line_number input_file from the directory of output_file.
Packit 6978fb
''')
Packit 6978fb
        sys.exit(1)
Packit 6978fb
Packit 6978fb
    if len(sys.argv)!=4:
Packit 6978fb
        print_usage()
Packit 6978fb
    try:
Packit 6978fb
        line_number = int(sys.argv[2])
Packit 6978fb
    except ValueError:
Packit 6978fb
        print_usage()
Packit 6978fb
Packit 6978fb
    output_file = sys.argv[1]
Packit 6978fb
    input_file  = sys.argv[3]
Packit 6978fb
    path_output  = os.getcwd() + '/' + output_file
Packit 6978fb
    path_input   = os.getcwd() + '/' + input_file
Packit 6978fb
Packit 6978fb
    if not os.path.isfile(path_output):
Packit 6978fb
        print_usage()
Packit 6978fb
Packit 6978fb
    dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
Packit 6978fb
    logger = logging.getLogger("evince_dbus")
Packit 6978fb
    logger.setLevel(logging.DEBUG)
Packit 6978fb
    ch = logging.StreamHandler()
Packit 6978fb
    ch.setLevel(logging.DEBUG)
Packit 6978fb
Packit 6978fb
    formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
Packit 6978fb
Packit 6978fb
    ch.setFormatter(formatter)
Packit 6978fb
Packit 6978fb
    logger.addHandler(ch)    
Packit 6978fb
    a = EvinceWindowProxy('file://' + path_output, True,logger=logger)
Packit 6978fb
    
Packit 6978fb
    def sync_view(ev_window, path_input, line_number):
Packit 6978fb
        ev_window.SyncView (path_input, (line_number, 1),0)
Packit 6978fb
Packit 6978fb
    GObject.timeout_add(400, sync_view, a, path_input, line_number)
Packit 6978fb
    loop = GObject.MainLoop()
Packit 6978fb
    loop.run() 
Packit 6978fb
# ex:ts=4:et: