[latexila] SyncTeX: forward search with evince



commit 0b068381a6c1ccaad44d421066415e01257eb01d
Author: SÃbastien Wilmet <swilmet gnome org>
Date:   Sat Sep 8 15:10:32 2012 +0200

    SyncTeX: forward search with evince
    
    Thanks to Josà Aliste for the implementation in evince and the synctex
    gedit plugin!

 po/POTFILES.in       |    1 +
 src/Makefile.am      |    1 +
 src/main_window.vala |   17 +++++
 src/synctex.vala     |  169 ++++++++++++++++++++++++++++++++++++++++++++++++++
 src/ui/ui.xml        |    2 +
 5 files changed, 190 insertions(+), 0 deletions(-)
---
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 48c5341..778425b 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -50,6 +50,7 @@ src/structure_model.vala
 src/structure.vala
 src/symbols.vala
 src/symbols_view.vala
+src/synctex.vala
 src/tab_info_bar.vala
 src/templates_dialogs.vala
 src/templates.vala
diff --git a/src/Makefile.am b/src/Makefile.am
index 9e56cdb..cc55635 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -57,6 +57,7 @@ vala_files =				\
 	structure.vala			\
 	symbols.vala			\
 	symbols_view.vala		\
+	synctex.vala			\
 	tab_info_bar.vala		\
 	templates_dialogs.vala		\
 	templates.vala			\
diff --git a/src/main_window.vala b/src/main_window.vala
index 96126b6..2d1b1bb 100644
--- a/src/main_window.vala
+++ b/src/main_window.vala
@@ -45,6 +45,8 @@ public class MainWindow : Window
             N_("Search for and replace text"), on_search_replace },
         { "SearchGoToLine", Stock.JUMP_TO, N_("_Go to Line..."), "<Control>G",
             N_("Go to a specific line"), on_search_goto_line },
+        { "SearchForward", null, N_("_Search Forward"), "<Control><Alt>F",
+            N_("Jump to the associated position in the PDF file"), on_search_forward },
 
         // Projects
         { "Projects", null, N_("_Projects") },
@@ -1081,6 +1083,21 @@ public class MainWindow : Window
         _goto_line.show ();
     }
 
+    public void on_search_forward ()
+    {
+        return_if_fail (active_tab != null);
+
+        TextIter iter;
+        TextMark insert = active_document.get_insert ();
+        active_document.get_iter_at_mark (out iter, insert);
+
+        int line = iter.get_line () + 1;
+        int column = iter.get_line_offset ();
+
+        Synctex synctex = new Synctex ();
+        synctex.forward_search (active_document, line, column);
+    }
+
     /* Projects */
 
     public void on_projects_new ()
diff --git a/src/synctex.vala b/src/synctex.vala
new file mode 100644
index 0000000..c822dcf
--- /dev/null
+++ b/src/synctex.vala
@@ -0,0 +1,169 @@
+/*
+ * This file is part of LaTeXila.
+ *
+ * Copyright  2012 SÃbastien Wilmet
+ *
+ * LaTeXila 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * LaTeXila 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 LaTeXila.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: SÃbastien Wilmet
+ */
+
+// SyncTeX: forward and backward search with evince.
+
+[DBus (name = "org.gnome.evince.Daemon")]
+interface EvinceDaemon : Object
+{
+    // Returns the bus name owner (the evince instance).
+    public abstract string find_document (string uri, bool spawn) throws IOError;
+}
+
+[DBus (name = "org.gnome.evince.Application")]
+interface EvinceApplication : Object
+{
+    public abstract string[] get_window_list () throws IOError;
+}
+
+private struct DocPosition
+{
+    int32 line;
+    int32 column;
+}
+
+[DBus (name = "org.gnome.evince.Window")]
+interface EvinceWindow : Object
+{
+    public abstract void sync_view (string source_file, DocPosition source_point,
+        uint32 timestamp) throws IOError;
+
+    public signal void sync_source (string source_file, DocPosition source_point,
+        uint32 timestamp);
+}
+
+public class Synctex : Object
+{
+    public void forward_search (Document doc, int line, int column)
+    {
+        string? pdf_uri = get_pdf_uri (doc);
+        return_if_fail (pdf_uri != null);
+
+        EvinceWindow? ev_window = get_evince_window (pdf_uri);
+        return_if_fail (ev_window != null);
+
+        return_if_fail (doc.location != null);
+        string tex_path = doc.location.get_path ();
+
+        sync_view (ev_window, tex_path, line, column);
+    }
+
+    private string? get_pdf_uri (Document doc)
+    {
+        File? main_file = doc.get_main_file ();
+
+        if (main_file == null)
+            return null;
+
+        string uri = main_file.get_uri ();
+        return Utils.get_shortname (uri) + ".pdf";
+    }
+
+    private EvinceWindow? get_evince_window (string pdf_uri)
+    {
+        EvinceDaemon daemon = null;
+
+        try
+        {
+            daemon = Bus.get_proxy_sync (BusType.SESSION, "org.gnome.evince.Daemon",
+                "/org/gnome/evince/Daemon");
+        }
+        catch (IOError e)
+        {
+            warning ("SyncTeX: can not connect to evince daemon: %s", e.message);
+            return null;
+        }
+
+        string owner = null;
+
+        try
+        {
+            owner = daemon.find_document (pdf_uri, true);
+        }
+        catch (IOError e)
+        {
+            warning ("SyncTeX: find document: %s", e.message);
+            return null;
+        }
+
+        EvinceApplication app = null;
+
+        try
+        {
+            app = Bus.get_proxy_sync (BusType.SESSION, owner, "/org/gnome/evince/Evince");
+        }
+        catch (IOError e)
+        {
+            warning ("SyncTeX: can not connect to evince application: %s", e.message);
+            return null;
+        }
+
+        string[] window_list = {};
+
+        try
+        {
+            window_list = app.get_window_list ();
+        }
+        catch (IOError e)
+        {
+            warning ("SyncTeX: can not get window list: %s", e.message);
+            return null;
+        }
+
+        if (window_list.length == 0)
+        {
+            warning ("SyncTeX: the window list is empty.");
+            return null;
+        }
+
+        // There is normally only one window.
+        string window_path = window_list[0];
+        EvinceWindow window = null;
+
+        try
+        {
+            window = Bus.get_proxy_sync (BusType.SESSION, owner, window_path);
+        }
+        catch (IOError e)
+        {
+            warning ("SyncTeX: can not connect to evince window: %s", e.message);
+            return null;
+        }
+
+        return window;
+    }
+
+    private void sync_view (EvinceWindow window, string tex_path, int line, int column)
+    {
+        DocPosition source_point = DocPosition ();
+        source_point.line = line;
+        source_point.column = column;
+
+        try
+        {
+            window.sync_view (tex_path, source_point, Gdk.CURRENT_TIME);
+        }
+        catch (IOError e)
+        {
+            warning ("SyncTeX: can not sync view: %s", e.message);
+        }
+    }
+}
diff --git a/src/ui/ui.xml b/src/ui/ui.xml
index efed28d..9faff1d 100644
--- a/src/ui/ui.xml
+++ b/src/ui/ui.xml
@@ -70,6 +70,8 @@ along with LaTeXila.  If not, see <http://www.gnu.org/licenses/>.
       <menuitem action="SearchReplace" />
       <separator />
       <menuitem action="SearchGoToLine" />
+      <separator />
+      <menuitem action="SearchForward" />
     </menu>
 
     <menu action="Build" name="BuildMenu">



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