diff options
Diffstat (limited to 'support/autolatex/plugins/gedit3/autolatexeditor/__init__.py')
-rw-r--r-- | support/autolatex/plugins/gedit3/autolatexeditor/__init__.py | 526 |
1 files changed, 526 insertions, 0 deletions
diff --git a/support/autolatex/plugins/gedit3/autolatexeditor/__init__.py b/support/autolatex/plugins/gedit3/autolatexeditor/__init__.py new file mode 100644 index 0000000000..40c6a58b6c --- /dev/null +++ b/support/autolatex/plugins/gedit3/autolatexeditor/__init__.py @@ -0,0 +1,526 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# +# Copyright (C) 2013-14 Stephane Galland <galland@arakhne.org> +# +# 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; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. + +#--------------------------------- +# IMPORTS +#--------------------------------- + +# Import standard python libs +import os +import tempfile +import re +import gettext +# Include the Glib, Gtk and Gedit libraries +from gi.repository import GObject, Gtk, Gio, GdkPixbuf, Gedit, PeasGtk + +# AutoLaTeX shared libs + +from autolatex.utils import utils as autolatex_utils +from autolatex.utils import gsettings as autolatex_gsettings +from autolatex.config import window as cli_config + +# AutoLaTeX-Gedit internal libs + +from .utils import gedit_runner +from .config import main_panel as plugin_config +from .widgets import latex_console + +#--------------------------------- +# PLUGIN CONFIGURATION +#--------------------------------- + +autolatex_utils.init_plugin_configuration(__file__, 'autolatex-gedit3') + +#--------------------------------- +# INTERNATIONALIZATION +#--------------------------------- + +_T = gettext.gettext + +#--------------------------------- +# CLASS AutoLaTeXPlugin +#--------------------------------- + +# Plugin for Gedit +class AutoLaTeXPlugin(GObject.Object, Gedit.WindowActivatable, PeasGtk.Configurable): + __gtype_name__ = "AutoLaTeXPlugin" + window = GObject.property(type=Gedit.Window) + + #Constructor + def __init__(self): + GObject.Object.__init__(self) + self._status_bar_context_id = None + self._compilation_under_progress = False # Indicate if the compilation is under progress + self._console_icon = None # Icon of the error console + self._gsettings = autolatex_gsettings.Manager() + self._syntex_regex = re.compile('\%.*mainfile:\s*(.*)$') + + # Invoked when the configuration window is open + def do_create_configure_widget(self): + return plugin_config.Panel(self._gsettings, self.window) + + # Invoked when the plugin is activated + def do_activate(self): + self._console_icon = self._get_icon('console') + self._latex_console = latex_console.Console(self) # Current instance of the error console + if not self._gsettings: + self._gsettings = autolatex_gsettings.Manager() + self._add_ui() + self._check_autolatex_binaries() + + # Invoke when the plugin is desactivated + def do_deactivate(self): + gedit_runner.kill_all_runners() + self._remove_ui() + self._gsettings.unbind() + self._gsettings = None + + # Check if the AutoLaTeX binaries were found + def _check_autolatex_binaries(self): + if not autolatex_utils.AUTOLATEX_BINARY and not autolatex_utils.AUTOLATEX_BACKEND_BINARY: + dialog = Gtk.MessageDialog(self.window, Gtk.DialogFlags.MODAL, Gtk.MessageType.ERROR, Gtk.ButtonsType.OK, _T("The programs 'autolatex' and 'autolatex-backend'\nwere not found.\nPlease fix the configuration of the AutoLaTeX plugin.")) + answer = dialog.run() + dialog.destroy() + elif not autolatex_utils.AUTOLATEX_BINARY: + dialog = Gtk.MessageDialog(self.window, Gtk.DialogFlags.MODAL, Gtk.MessageType.ERROR, Gtk.ButtonsType.OK, _T("The program 'autolatex' was not found.\nPlease fix the configuration of the AutoLaTeX plugin.")) + answer = dialog.run() + dialog.destroy() + elif not autolatex_utils.AUTOLATEX_BACKEND_BINARY: + dialog = Gtk.MessageDialog(self.window, Gtk.DialogFlags.MODAL, Gtk.MessageType.ERROR, Gtk.ButtonsType.OK, _T("The program 'autolatex-backend' was not found.\nPlease fix the configuration of the AutoLaTeX plugin.")) + answer = dialog.run() + dialog.destroy() + + # Invoke when the UI is updated + def do_update_state(self): + directory = self._find_AutoLaTeX_dir() + hasTeXDocument = self._is_TeX_document() + hasAutoLaTeXDocument = (directory is not None) + isInTeXContext = (hasTeXDocument or hasAutoLaTeXDocument) + # Display or hide the menus + self._menu.set_visible(isInTeXContext) + self._document_actions.set_visible(isInTeXContext) + self._texsensitive_actions.set_visible(isInTeXContext) + self._general_actions.set_visible(isInTeXContext) + + if directory: + cfgFile = autolatex_utils.get_autolatex_document_config_file(directory) + hasDocConfFile = os.path.exists(cfgFile) + else: + hasDocConfFile = False + hasUserConfFile = os.path.exists(autolatex_utils.get_autolatex_user_config_file()) + # Change the sensitivity + if self._document_actions: + self._document_actions.set_sensitive(hasAutoLaTeXDocument and not self._compilation_under_progress) + if self._texsensitive_actions: + self._texsensitive_actions.set_sensitive(hasTeXDocument and not self._compilation_under_progress) + if self._docconfsensitive_actions: + self._docconfsensitive_actions.set_sensitive(hasDocConfFile and not self._compilation_under_progress) + if self._userconfsensitive_actions: + self._userconfsensitive_actions.set_sensitive(hasUserConfFile and not self._compilation_under_progress) + action = self._document_actions.get_action('AutoLaTeXNextError') + assert action is not None + action.set_sensitive(self._latex_console.has_next_error()) + action = self._document_actions.get_action('AutoLaTeXPreviousError') + assert action is not None + action.set_sensitive(self._latex_console.has_previous_error()) + + def _open_latex_console(self, set_visible=True): + bottom_panel = self.window.get_bottom_panel() + console_parent = self._latex_console.get_parent() + if (console_parent is None): + bottom_panel.add_item(self._latex_console, + "autolatex-console-panel", + _T("AutoLaTeX Console"), + Gtk.Image.new_from_pixbuf(self._console_icon)) + bottom_panel.activate_item(self._latex_console) + if set_visible and bottom_panel.get_property("visible") == False: + bottom_panel.set_property("visible", True) + + # Update the UI according to the flag "compilation under progress" + # and to compilation outputs + def _update_action_validity(self, valid, console_content, latex_warnings): + bottom_panel = self.window.get_bottom_panel() + statusbar = self.window.get_statusbar() + statusbar.remove_all(self._statusbar_id) + # Display or hide the error console if an error message is given or not + show_console = self._latex_console.set_log( + console_content, + latex_warnings, + self._find_AutoLaTeX_dir()) + if show_console != latex_console.ConsoleMode.HIDE: + self._open_latex_console(show_console == latex_console.ConsoleMode.SHOW) + # Update the status bar + if show_console == latex_console.ConsoleMode.OPTIONAL and bottom_panel.get_property("visible") == False: + statusbar.push(self._statusbar_id, + _T("LaTeX warnings were found. Please open the bottom panel to see them.")) + # Update the sensitivities of the Widgets + self._compilation_under_progress = not valid + GObject.idle_add(self.do_update_state) + + # Load an icon from the AutoLaTeX package + def _get_icon(self, icon): + return GdkPixbuf.Pixbuf.new_from_file(autolatex_utils.make_toolbar_icon_path('autolatex-'+icon+'.png')) + + + # Add any contribution to the Gtk UI + def _add_ui(self): + # Get status bar id + self._statusbar_id = self.window.get_statusbar().get_context_id('gedit-autolatex-plugin') + # Get the UI manager + manager = self.window.get_ui_manager() + # Create the Top menu for AutoLaTeX + self._menu = Gtk.ActionGroup("AutoLaTeXMenu") + self._menu.add_actions([ + ('AutoLaTeXMenu', None, _T("AutoLaTeX"), + None, _T("AutoLaTeX"), + None), + ]) + manager.insert_action_group(self._menu) + # Create the menu for SyncTeX + self._synctex_menu = Gtk.ActionGroup("AutoLaTeXSyncTeXMenu") + self._synctex_menu.add_actions([ + ('AutoLaTeXSyncTeXMenu', Gtk.STOCK_DISCONNECT, _T("SyncTeX"), + None, _T("SyncTeX"), + None), + ]) + manager.insert_action_group(self._synctex_menu) + # Create the group of actions that are needing an AutoLaTeX document + self._document_actions = Gtk.ActionGroup("AutoLaTeXDocumentActions") + self._document_actions.add_actions([ + ('AutoLaTeXGenerateImageAction', None, _T("Generate images"), + None, _T("Generate the images with AutoLaTeX"), + self.on_generateimage_action_activate), + ('AutoLaTeXCompileAction', None, _T("Compile"), + '<ctrl>B', _T("Compile with AutoLaTeX"), + self.on_compile_action_activate), + ('AutoLaTeXCleanAction', None, _T("Remove temporary files"), + None, _T("Clean with AutoLaTeX"), + self.on_clean_action_activate), + ('AutoLaTeXCleanallAction', None, _T("Clean all"), + None, _T("Clean all with AutoLaTeX"), + self.on_cleanall_action_activate), + ('AutoLaTeXViewAction', None, _T("View the PDF"), + None, _T("Open the PDF viewer"), + self.on_view_action_activate), + ('AutoLaTeXMakeFlatAction', None, _T("Create flat version of the TeX document"), + None, _T("Create a flat version of the document, to be submitted to on-line publication systems (Elsevier...)"), + self.on_makeflat_action_activate), + ('AutoLaTeXNextError', None, _T("Show next error/warning"), + 'F4', _T("Show the next error or warning from the LaTeX console"), + self.on_autolatex_next_error_action), + ('AutoLaTeXPreviousError', None, _T("Show previous error/warning"), + '<shift>F4', _T("Show the previous error or warning from the LaTeX console"), + self.on_autolatex_previous_error_action), + ]) + manager.insert_action_group(self._document_actions) + # Create the group of actions that are needing an TeX document + self._texsensitive_actions = Gtk.ActionGroup("AutoLaTeXTeXSensitiveActions") + self._texsensitive_actions.add_actions([ + ('AutoLaTeXDocumentConfAction', None, _T("Document configuration"), + None, _T("Change the configuration for the document"), + self.on_document_configuration_action_activate), + ]) + manager.insert_action_group(self._texsensitive_actions) + # Create the group of actions that are needing the configuration file of a document + self._docconfsensitive_actions = Gtk.ActionGroup("AutoLaTeXDocConfSensitiveActions") + self._docconfsensitive_actions.add_actions([ + ('AutoLaTeXRemoveDocumentConfAction', None, _T("Delete document configuration"), + None, _T("Delete the configuration for the document"), + self.on_delete_document_configuration_action_activate), + ]) + manager.insert_action_group(self._docconfsensitive_actions) + # Create the group of actions that are needing the configuration file of the user + self._userconfsensitive_actions = Gtk.ActionGroup("AutoLaTeXUserConfSensitiveActions") + self._userconfsensitive_actions.add_actions([ + ('AutoLaTeXRemoveUserConfAction', None, _T("Delete user configuration"), + None, _T("Delete the configuration for the user"), + self.on_delete_user_configuration_action_activate), + ]) + manager.insert_action_group(self._userconfsensitive_actions) + # Create the group of actions that are not needing any special document + self._general_actions = Gtk.ActionGroup("AutoLaTeXGeneralActions") + self._general_actions.add_toggle_actions([ + ('AutoLaTeXEnableSyncTeXAction', None, _T("Force the use of SyncTeX"), + None, _T("Use SyncTeX even if the document and user configurations say 'no'"), + self.on_enable_synctex_action_activate), + ]) + self._general_actions.add_actions([ + ('AutoLaTeXUpdateForSyncTeXAction', None, _T("Update TeX file with SyncTeX reference"), + None, _T("Update the text of the TeX file to add the reference to the main document"), + self.on_update_for_synctex_action_activate), + ('AutoLaTeXUserConfAction', None, _T("User configuration"), + None, _T("Change the configuration for the user"), + self.on_user_configuration_action_activate), + ]) + manager.insert_action_group(self._general_actions) + # Put the icons into the actions + for definition in [ (self._document_actions, 'AutoLaTeXGenerateImageAction', 'images'), + (self._document_actions, 'AutoLaTeXCompileAction', 'compile'), + (self._document_actions, 'AutoLaTeXCleanAction', 'clean'), + (self._document_actions, 'AutoLaTeXCleanallAction', 'cleanall'), + (self._document_actions, 'AutoLaTeXViewAction', 'view'), + (self._texsensitive_actions, 'AutoLaTeXDocumentConfAction', 'preferences'), + (self._general_actions, 'AutoLaTeXUserConfAction', 'preferences') + ]: + action = definition[0].get_action(definition[1]) + action.set_gicon(self._get_icon(definition[2])) + # Add the Gtk contributions + ui_path = os.path.join(autolatex_utils.AUTOLATEX_APP_PATH, 'ui') + self._ui_merge_ids = [] + for ui_file in [ 'menu.ui', 'toolbar.ui' ]: + self._ui_merge_ids.append(manager.add_ui_from_file(os.path.join(ui_path, ui_file))) + manager.ensure_update() + # Change the state of the check-boxes + checkbox = self._general_actions.get_action('AutoLaTeXEnableSyncTeXAction') + checkbox.set_active(self._gsettings.get_force_synctex()) + # Connect from gsettings + self._gsettings.connect('force-synctex', self.on_gsettings_changed) + self._gsettings.connect('save-before-run-autolatex', self.on_gsettings_changed) + + # Remove all contributions to the Gtk UI + def _remove_ui(self): + # Disconnect from gsettings + self._gsettings.disconnect('force-synctex') + self._gsettings.disconnect('save-before-run-autolatex') + # Remove the error console + if self._latex_console: + if self._latex_console.get_parent() is not None: + panel = self.window.get_bottom_panel() + panel.remove_item(self._latex_console) + self._latex_console = None + # Remove the Gtk Widgets + manager = self.window.get_ui_manager() + manager.remove_action_group(self._document_actions) + manager.remove_action_group(self._texsensitive_actions) + manager.remove_action_group(self._docconfsensitive_actions) + manager.remove_action_group(self._userconfsensitive_actions) + manager.remove_action_group(self._general_actions) + manager.remove_action_group(self._synctex_menu) + manager.remove_action_group(self._menu) + for merge_id in self._ui_merge_ids: + manager.remove_ui(merge_id) + manager.ensure_update() + + # Replies if the active document is a TeX document + def _is_TeX_document(self): + doc = self.window.get_active_document() + if doc: + doc = Gedit.Document.get_location(doc) + if doc: + return autolatex_utils.is_TeX_document(doc.get_path()) + return False + + # Try to find the directory where an AutoLaTeX configuration file is + # located. The search is traversing the parent directory from the current + # document. + def _find_AutoLaTeX_dir(self): + adir = None + doc = self.window.get_active_document() + if doc: + doc = Gedit.Document.get_location(doc) + if doc: + return autolatex_utils.find_AutoLaTeX_directory(doc.get_path()) + return adir + + def _save_documents(self): + for document in self.window.get_unsaved_documents(): + is_untitled = document.is_untitled() + is_deleted = document.get_deleted() + is_readonly = document.get_readonly() + if not is_untitled and not is_deleted and not is_readonly : + document.save(Gedit.DocumentSaveFlags.IGNORE_MTIME) + + def _apply_general_autolatex_cli_options(self, params): + if self._gsettings.get_force_synctex(): + params = [ '--synctex' ] + params + params = [ autolatex_utils.DEFAULT_LOG_LEVEL ] + params + return params + + def on_clean_action_activate(self, action, data=None): + self._launch_AutoLaTeX( + _T("Removing the generated files (except the figures)"), + 'clean', self._apply_general_autolatex_cli_options( + [ '--noview' ]), + False) + + def on_cleanall_action_activate(self, action, data=None): + self._launch_AutoLaTeX( + _T("Removing the generated files and figures"), + 'cleanall', self._apply_general_autolatex_cli_options( + [ '--noview' ]), + False) + + def on_compile_action_activate(self, action, data=None): + self._launch_AutoLaTeX( + _T("Generating the document"), + 'all', self._apply_general_autolatex_cli_options( + [ '--noview' ]), + True) + + def on_generateimage_action_activate(self, action, data=None): + self._launch_AutoLaTeX( + _T("Generating the figures with the translators"), + 'images', self._apply_general_autolatex_cli_options( + [ '--noview' ]), + False) + + def on_view_action_activate(self, action, data=None): + self._launch_AutoLaTeX( + _T("Launching the viewer"), + 'view', self._apply_general_autolatex_cli_options( + [ '--asyncview' ]), + True) + + def on_document_configuration_action_activate(self, action, data=None): + directory = self._find_AutoLaTeX_dir() + if directory: + cli_config.open_configuration_dialog(self.window, True, directory) + + def on_delete_document_configuration_action_activate(self, action, data=None): + directory = self._find_AutoLaTeX_dir() + if directory: + cfgFile = autolatex_utils.get_autolatex_document_config_file(directory) + if os.path.exists(cfgFile): + dialog = Gtk.MessageDialog(self.window, Gtk.DialogFlags.MODAL, Gtk.MessageType.QUESTION, Gtk.ButtonsType.YES_NO, _T("Do you want to delete the document configuration?")) + answer = dialog.run() + dialog.destroy() + if answer == Gtk.ResponseType.YES: + os.unlink(cfgFile) + self.do_update_state() + + def on_user_configuration_action_activate(self, action, data=None): + directory = self._find_AutoLaTeX_dir() + if directory: + cli_config.open_configuration_dialog(self.window, False, directory) + + def on_delete_user_configuration_action_activate(self, action, data=None): + cfgFile = autolatex_utils.get_autolatex_user_config_file() + if os.path.exists(cfgFile): + dialog = Gtk.MessageDialog(self.window, Gtk.DialogFlags.MODAL, Gtk.MessageType.QUESTION, Gtk.ButtonsType.YES_NO, _T("Do you want to delete the user configuration?")) + answer = dialog.run() + dialog.destroy() + if answer == Gtk.ResponseType.YES: + os.unlink(cfgFile) + self.do_update_state() + + def on_enable_synctex_action_activate(self, action, data=None): + checkbox = self._general_actions.get_action('AutoLaTeXEnableSyncTeXAction') + self._gsettings.set_force_synctex(checkbox.get_active()) + + def on_update_for_synctex_action_activate(self, action, data=None): + if self._is_TeX_document(): + directory = self._find_AutoLaTeX_dir() + view = self.window.get_active_view() + text_buffer = view.get_buffer() + found = None + # Search in the first tree lines + if text_buffer.get_line_count() > 0: + found = self.__search_for_synctex_flag(text_buffer, 0) + # Search in the last tree lines + if not found and text_buffer.get_line_count() > 3: + found = self.__search_for_synctex_flag(text_buffer, + max(3,text_buffer.get_line_count()-3)) + # Add the SyncTeX flag + if not found: + private_config = autolatex_utils.backend_get_configuration( + directory, + 'all', '__private__'); + main_file = private_config.get('input', 'latex file', ''); + current_dir = Gio.File.new_for_path(os.getcwd()) + main_file = current_dir.resolve_relative_path(main_file).get_path() + current_document = self.window.get_active_document() + document_file = Gedit.Document.get_location(current_document) + if document_file: + document_filename = current_dir.resolve_relative_path(document_file.get_path()) + document_filename = document_filename.get_path() + if main_file != document_filename: + document_dir = document_file.get_parent() + rel_path = os.path.relpath(main_file, document_dir.get_path()) + text_buffer.insert_interactive( + text_buffer.get_iter_at_line(0), + unicode("% mainfile: "+rel_path+"\n"), + -1, + view.get_editable()) + + def __search_for_synctex_flag(self, text_buffer, line_number): + found = None + i = 0 + text_iter1 = text_buffer.get_iter_at_line(line_number) + while text_iter1 and i<3 and not found: + text_iter2 = text_iter1.copy(); + text_iter2.forward_to_line_end() + line = text_iter1.get_visible_text(text_iter2) + mo = re.match(self._syntex_regex, line) + if mo: + found = mo.group(1) + text_iter1 = text_iter2 + if not text_iter1.forward_line(): + i = 4 + else: + i = i + 1 + return found + + def on_gsettings_changed(self, settings, key, data=None): + if key == 'force-synctex': + checkbox = self._general_actions.get_action('AutoLaTeXEnableSyncTeXAction') + checkbox.set_active(self._gsettings.get_force_synctex()) + elif key == 'save-before-run-autolatex': + pass + + def on_enable_synctex_action_activate(self, action, data=None): + checkbox = self._general_actions.get_action('AutoLaTeXEnableSyncTeXAction') + self._gsettings.set_force_synctex(checkbox.get_active()) + + def on_makeflat_action_activate(self, action, data=None): + self._launch_AutoLaTeX( + _T("Making the \"flat\" version of the document"), + 'makeflat', self._apply_general_autolatex_cli_options( + [ '--noview' ], + True)) + + def on_autolatex_next_error_action(self, action, data=None): + show_console = self._latex_console.show_next_error() + if show_console != latex_console.ConsoleMode.HIDE: + self._open_latex_console(show_console == latex_console.ConsoleMode.SHOW) + self.do_update_state() + + def on_autolatex_previous_error_action(self, action, data=None): + show_console = self._latex_console.show_previous_error() + if show_console != latex_console.ConsoleMode.HIDE: + self._open_latex_console(show_console == latex_console.ConsoleMode.SHOW) + self.do_update_state() + + def _launch_AutoLaTeX(self, label, directive, params, enable_saving): + directory = self._find_AutoLaTeX_dir() + if directory: + GObject.idle_add(self._update_action_validity, False, None, None) + + # Save the documents if necessary + if enable_saving and self._gsettings.get_save_before_run_autolatex(): + self._save_documents() + + thread = gedit_runner.Runner( + self, + label, + self._gsettings.get_progress_info_visibility(), + directory, + directive, + params) + thread.start() |