summaryrefslogtreecommitdiff
path: root/plugins/externaltools/tools/manager.py
diff options
context:
space:
mode:
authorPerberos <[email protected]>2011-11-07 16:46:58 -0300
committerPerberos <[email protected]>2011-11-07 16:46:58 -0300
commit528c1e5ff51e213936e800fc5a9a25da99c0bdf2 (patch)
tree77f8aa456b09367ba81f04d4562fc935f898a951 /plugins/externaltools/tools/manager.py
downloadpluma-528c1e5ff51e213936e800fc5a9a25da99c0bdf2.tar.bz2
pluma-528c1e5ff51e213936e800fc5a9a25da99c0bdf2.tar.xz
initial
Diffstat (limited to 'plugins/externaltools/tools/manager.py')
-rwxr-xr-xplugins/externaltools/tools/manager.py948
1 files changed, 948 insertions, 0 deletions
diff --git a/plugins/externaltools/tools/manager.py b/plugins/externaltools/tools/manager.py
new file mode 100755
index 00000000..e28a088a
--- /dev/null
+++ b/plugins/externaltools/tools/manager.py
@@ -0,0 +1,948 @@
+# -*- coding: utf-8 -*-
+# Gedit External Tools plugin
+# Copyright (C) 2005-2006 Steve Frécinaux <[email protected]>
+#
+# 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, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+__all__ = ('Manager', )
+
+import gedit
+import gtk
+import gtksourceview2 as gsv
+import os.path
+from library import *
+from functions import *
+import hashlib
+from xml.sax import saxutils
+import gobject
+
+class LanguagesPopup(gtk.Window):
+ COLUMN_NAME = 0
+ COLUMN_ID = 1
+ COLUMN_ENABLED = 2
+
+ def __init__(self, languages):
+ gtk.Window.__init__(self, gtk.WINDOW_POPUP)
+
+ self.set_default_size(200, 200)
+ self.props.can_focus = True
+
+ self.build()
+ self.init_languages(languages)
+
+ self.show()
+ self.map()
+
+ self.grab_add()
+
+ gtk.gdk.keyboard_grab(self.window, False, 0L)
+ gtk.gdk.pointer_grab(self.window, False, gtk.gdk.BUTTON_PRESS_MASK |
+ gtk.gdk.BUTTON_RELEASE_MASK |
+ gtk.gdk.POINTER_MOTION_MASK |
+ gtk.gdk.ENTER_NOTIFY_MASK |
+ gtk.gdk.LEAVE_NOTIFY_MASK |
+ gtk.gdk.PROXIMITY_IN_MASK |
+ gtk.gdk.PROXIMITY_OUT_MASK, None, None, 0L)
+
+ self.view.get_selection().select_path((0,))
+
+ def build(self):
+ self.model = gtk.ListStore(str, str, bool)
+
+ self.sw = gtk.ScrolledWindow()
+ self.sw.show()
+
+ self.sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
+ self.sw.set_shadow_type(gtk.SHADOW_ETCHED_IN)
+
+ self.view = gtk.TreeView(self.model)
+ self.view.show()
+
+ self.view.set_headers_visible(False)
+
+ column = gtk.TreeViewColumn()
+
+ renderer = gtk.CellRendererToggle()
+ column.pack_start(renderer, False)
+ column.set_attributes(renderer, active=self.COLUMN_ENABLED)
+
+ renderer.connect('toggled', self.on_language_toggled)
+
+ renderer = gtk.CellRendererText()
+ column.pack_start(renderer, True)
+ column.set_attributes(renderer, text=self.COLUMN_NAME)
+
+ self.view.append_column(column)
+ self.view.set_row_separator_func(self.on_separator)
+
+ self.sw.add(self.view)
+
+ self.add(self.sw)
+
+ def enabled_languages(self, model, path, piter, ret):
+ enabled = model.get_value(piter, self.COLUMN_ENABLED)
+
+ if path == (0,) and enabled:
+ return True
+
+ if enabled:
+ ret.append(model.get_value(piter, self.COLUMN_ID))
+
+ return False
+
+ def languages(self):
+ ret = []
+
+ self.model.foreach(self.enabled_languages, ret)
+ return ret
+
+ def on_separator(self, model, piter):
+ val = model.get_value(piter, self.COLUMN_NAME)
+ return val == '-'
+
+ def init_languages(self, languages):
+ manager = gsv.LanguageManager()
+ langs = gedit.language_manager_list_languages_sorted(manager, True)
+
+ self.model.append([_('All languages'), None, not languages])
+ self.model.append(['-', None, False])
+ self.model.append([_('Plain Text'), 'plain', 'plain' in languages])
+ self.model.append(['-', None, False])
+
+ for lang in langs:
+ self.model.append([lang.get_name(), lang.get_id(), lang.get_id() in languages])
+
+ def correct_all(self, model, path, piter, enabled):
+ if path == (0,):
+ return False
+
+ model.set_value(piter, self.COLUMN_ENABLED, enabled)
+
+ def on_language_toggled(self, renderer, path):
+ piter = self.model.get_iter(path)
+
+ enabled = self.model.get_value(piter, self.COLUMN_ENABLED)
+ self.model.set_value(piter, self.COLUMN_ENABLED, not enabled)
+
+ if path == '0':
+ self.model.foreach(self.correct_all, False)
+ else:
+ self.model.set_value(self.model.get_iter_first(), self.COLUMN_ENABLED, False)
+
+ def do_key_press_event(self, event):
+ if event.keyval == gtk.keysyms.Escape:
+ self.destroy()
+ return True
+ else:
+ event.window = self.view.get_bin_window()
+ return self.view.event(event)
+
+ def do_key_release_event(self, event):
+ event.window = self.view.get_bin_window()
+ return self.view.event(event)
+
+ def in_window(self, event, window=None):
+ if not window:
+ window = self.window
+
+ geometry = window.get_geometry()
+ origin = window.get_origin()
+
+ return event.x_root >= origin[0] and \
+ event.x_root <= origin[0] + geometry[2] and \
+ event.y_root >= origin[1] and \
+ event.y_root <= origin[1] + geometry[3]
+
+ def do_destroy(self):
+ gtk.gdk.keyboard_ungrab(0L)
+ gtk.gdk.pointer_ungrab(0L)
+
+ return gtk.Window.do_destroy(self)
+
+ def setup_event(self, event, window):
+ fr = event.window.get_origin()
+ to = window.get_origin()
+
+ event.window = window
+ event.x += fr[0] - to[0]
+ event.y += fr[1] - to[1]
+
+ def resolve_widgets(self, root):
+ res = [root]
+
+ if isinstance(root, gtk.Container):
+ root.forall(lambda x, y: res.extend(self.resolve_widgets(x)), None)
+
+ return res
+
+ def resolve_windows(self, window):
+ if not window:
+ return []
+
+ res = [window]
+ res.extend(window.get_children())
+
+ return res
+
+ def propagate_mouse_event(self, event):
+ allwidgets = self.resolve_widgets(self.get_child())
+ allwidgets.reverse()
+
+ orig = [event.x, event.y]
+
+ for widget in allwidgets:
+ windows = self.resolve_windows(widget.window)
+ windows.reverse()
+
+ for window in windows:
+ if not (window.get_events() & event.type):
+ continue
+
+ if self.in_window(event, window):
+ self.setup_event(event, window)
+
+ if widget.event(event):
+ return True
+
+ return False
+
+ def do_button_press_event(self, event):
+ if not self.in_window(event):
+ self.destroy()
+ else:
+ return self.propagate_mouse_event(event)
+
+ def do_button_release_event(self, event):
+ if not self.in_window(event):
+ self.destroy()
+ else:
+ return self.propagate_mouse_event(event)
+
+ def do_scroll_event(self, event):
+ return self.propagate_mouse_event(event)
+
+ def do_motion_notify_event(self, event):
+ return self.propagate_mouse_event(event)
+
+ def do_enter_notify_event(self, event):
+ return self.propagate_mouse_event(event)
+
+ def do_leave_notify_event(self, event):
+ return self.propagate_mouse_event(event)
+
+ def do_proximity_in_event(self, event):
+ return self.propagate_mouse_event(event)
+
+ def do_proximity_out_event(self, event):
+ return self.propagate_mouse_event(event)
+
+gobject.type_register(LanguagesPopup)
+
+class Manager:
+ TOOL_COLUMN = 0 # For Tree
+ NAME_COLUMN = 1 # For Combo
+
+ def __init__(self, datadir):
+ self.datadir = datadir
+ self.dialog = None
+ self._languages = {}
+ self._tool_rows = {}
+
+ self.build()
+
+ def build(self):
+ callbacks = {
+ 'on_new_tool_button_clicked' : self.on_new_tool_button_clicked,
+ 'on_remove_tool_button_clicked' : self.on_remove_tool_button_clicked,
+ 'on_tool_manager_dialog_response' : self.on_tool_manager_dialog_response,
+ 'on_tool_manager_dialog_focus_out': self.on_tool_manager_dialog_focus_out,
+ 'on_accelerator_key_press' : self.on_accelerator_key_press,
+ 'on_accelerator_focus_in' : self.on_accelerator_focus_in,
+ 'on_accelerator_focus_out' : self.on_accelerator_focus_out,
+ 'on_languages_button_clicked' : self.on_languages_button_clicked
+ }
+
+ # Load the "main-window" widget from the ui file.
+ self.ui = gtk.Builder()
+ self.ui.add_from_file(os.path.join(self.datadir, 'ui', 'tools.ui'))
+ self.ui.connect_signals(callbacks)
+ self.dialog = self.ui.get_object('tool-manager-dialog')
+
+ self.view = self.ui.get_object('view')
+
+ self.__init_tools_model()
+ self.__init_tools_view()
+
+ for name in ['input', 'output', 'applicability', 'save-files']:
+ self.__init_combobox(name)
+
+ self.do_update()
+
+ def expand_from_doc(self, doc):
+ row = None
+
+ if doc:
+ if doc.get_language():
+ lid = doc.get_language().get_id()
+
+ if lid in self._languages:
+ row = self._languages[lid]
+ elif 'plain' in self._languages:
+ row = self._languages['plain']
+
+ if not row and None in self._languages:
+ row = self._languages[None]
+
+ if not row:
+ return
+
+ self.view.expand_row(row.get_path(), False)
+ self.view.get_selection().select_path(row.get_path())
+
+ def run(self, window):
+ if self.dialog == None:
+ self.build()
+
+ # Open up language
+ self.expand_from_doc(window.get_active_document())
+
+ self.dialog.set_transient_for(window)
+ window.get_group().add_window(self.dialog)
+ self.dialog.present()
+
+ def add_accelerator(self, item):
+ if not item.shortcut:
+ return
+
+ if item.shortcut in self.accelerators:
+ if not item in self.accelerators[item.shortcut]:
+ self.accelerators[item.shortcut].append(item)
+ else:
+ self.accelerators[item.shortcut] = [item]
+
+ def remove_accelerator(self, item, shortcut=None):
+ if not shortcut:
+ shortcut = item.shortcut
+
+ if not shortcut in self.accelerators:
+ return
+
+ self.accelerators[shortcut].remove(item)
+
+ if not self.accelerators[shortcut]:
+ del self.accelerators[shortcut]
+
+ def add_tool_to_language(self, tool, language):
+ if isinstance(language, gsv.Language):
+ lid = language.get_id()
+ else:
+ lid = language
+
+ if not lid in self._languages:
+ piter = self.model.append(None, [language])
+
+ parent = gtk.TreeRowReference(self.model, self.model.get_path(piter))
+ self._languages[lid] = parent
+ else:
+ parent = self._languages[lid]
+
+ piter = self.model.get_iter(parent.get_path())
+ child = self.model.append(piter, [tool])
+
+ if not tool in self._tool_rows:
+ self._tool_rows[tool] = []
+
+ self._tool_rows[tool].append(gtk.TreeRowReference(self.model, self.model.get_path(child)))
+ return child
+
+ def add_tool(self, tool):
+ manager = gsv.LanguageManager()
+ ret = None
+
+ for lang in tool.languages:
+ l = manager.get_language(lang)
+
+ if l:
+ ret = self.add_tool_to_language(tool, l)
+ elif lang == 'plain':
+ ret = self.add_tool_to_language(tool, 'plain')
+
+ if not ret:
+ ret = self.add_tool_to_language(tool, None)
+
+ self.add_accelerator(tool)
+ return ret
+
+ def __init_tools_model(self):
+ self.tools = ToolLibrary()
+ self.current_node = None
+ self.script_hash = None
+ self.accelerators = dict()
+
+ self.model = gtk.TreeStore(object)
+ self.view.set_model(self.model)
+
+ for tool in self.tools.tree.tools:
+ self.add_tool(tool)
+
+ self.model.set_default_sort_func(self.sort_tools)
+ self.model.set_sort_column_id(-1, gtk.SORT_ASCENDING)
+
+ def sort_tools(self, model, iter1, iter2):
+ # For languages, sort All before everything else, otherwise alphabetical
+ t1 = model.get_value(iter1, self.TOOL_COLUMN)
+ t2 = model.get_value(iter2, self.TOOL_COLUMN)
+
+ if model.iter_parent(iter1) == None:
+ if t1 == None:
+ return -1
+
+ if t2 == None:
+ return 1
+
+ def lang_name(lang):
+ if isinstance(lang, gsv.Language):
+ return lang.get_name()
+ else:
+ return _('Plain Text')
+
+ n1 = lang_name(t1)
+ n2 = lang_name(t2)
+ else:
+ n1 = t1.name
+ n2 = t2.name
+
+ return cmp(n1.lower(), n2.lower())
+
+ def __init_tools_view(self):
+ # Tools column
+ column = gtk.TreeViewColumn('Tools')
+ renderer = gtk.CellRendererText()
+ column.pack_start(renderer, False)
+ renderer.set_property('editable', True)
+ self.view.append_column(column)
+
+ column.set_cell_data_func(renderer, self.get_cell_data_cb)
+
+ renderer.connect('edited', self.on_view_label_cell_edited)
+ renderer.connect('editing-started', self.on_view_label_cell_editing_started)
+
+ self.selection_changed_id = self.view.get_selection().connect('changed', self.on_view_selection_changed, None)
+
+ def __init_combobox(self, name):
+ combo = self[name]
+ combo.set_active(0)
+
+ # Convenience function to get an object from its name
+ def __getitem__(self, key):
+ return self.ui.get_object(key)
+
+ def set_active_by_name(self, combo_name, option_name):
+ combo = self[combo_name]
+ model = combo.get_model()
+ piter = model.get_iter_first()
+ while piter is not None:
+ if model.get_value(piter, self.NAME_COLUMN) == option_name:
+ combo.set_active_iter(piter)
+ return True
+ piter = model.iter_next(piter)
+ return False
+
+ def get_selected_tool(self):
+ model, piter = self.view.get_selection().get_selected()
+
+ if piter is not None:
+ tool = model.get_value(piter, self.TOOL_COLUMN)
+
+ if not isinstance(tool, Tool):
+ tool = None
+
+ return piter, tool
+ else:
+ return None, None
+
+ def compute_hash(self, string):
+ return hashlib.md5(string).hexdigest()
+
+ def save_current_tool(self):
+ if self.current_node is None:
+ return
+
+ if self.current_node.filename is None:
+ self.current_node.autoset_filename()
+
+ def combo_value(o, name):
+ combo = o[name]
+ return combo.get_model().get_value(combo.get_active_iter(), self.NAME_COLUMN)
+
+ self.current_node.input = combo_value(self, 'input')
+ self.current_node.output = combo_value(self, 'output')
+ self.current_node.applicability = combo_value(self, 'applicability')
+ self.current_node.save_files = combo_value(self, 'save-files')
+
+ buf = self['commands'].get_buffer()
+ script = buf.get_text(*buf.get_bounds())
+ h = self.compute_hash(script)
+ if h != self.script_hash:
+ # script has changed -> save it
+ self.current_node.save_with_script([line + "\n" for line in script.splitlines()])
+ self.script_hash = h
+ else:
+ self.current_node.save()
+
+ self.update_remove_revert()
+
+ def clear_fields(self):
+ self['accelerator'].set_text('')
+
+ buf = self['commands'].get_buffer()
+ buf.begin_not_undoable_action()
+ buf.set_text('')
+ buf.end_not_undoable_action()
+
+ for nm in ('input', 'output', 'applicability', 'save-files'):
+ self[nm].set_active(0)
+
+ self['languages_label'].set_text(_('All Languages'))
+
+ def fill_languages_button(self):
+ if not self.current_node or not self.current_node.languages:
+ self['languages_label'].set_text(_('All Languages'))
+ else:
+ manager = gsv.LanguageManager()
+ langs = []
+
+ for lang in self.current_node.languages:
+ if lang == 'plain':
+ langs.append(_('Plain Text'))
+ else:
+ l = manager.get_language(lang)
+
+ if l:
+ langs.append(l.get_name())
+
+ self['languages_label'].set_text(', '.join(langs))
+
+ def fill_fields(self):
+ node = self.current_node
+ self['accelerator'].set_text(default(node.shortcut, ''))
+
+ buf = self['commands'].get_buffer()
+ script = default(''.join(node.get_script()), '')
+
+ buf.begin_not_undoable_action()
+ buf.set_text(script)
+ buf.end_not_undoable_action()
+
+ self.script_hash = self.compute_hash(script)
+ contenttype = gio.content_type_guess(data=script)
+ lmanager = gedit.get_language_manager()
+ language = lmanager.guess_language(content_type=contenttype)
+
+ if language is not None:
+ buf.set_language(language)
+ buf.set_highlight_syntax(True)
+ else:
+ buf.set_highlight_syntax(False)
+
+ for nm in ('input', 'output', 'applicability', 'save-files'):
+ model = self[nm].get_model()
+ piter = model.get_iter_first()
+
+ self.set_active_by_name(nm,
+ default(node.__getattribute__(nm.replace('-', '_')),
+ model.get_value(piter, self.NAME_COLUMN)))
+
+ self.fill_languages_button()
+
+ def update_remove_revert(self):
+ piter, node = self.get_selected_tool()
+
+ removable = node is not None and node.is_local()
+
+ self['remove-tool-button'].set_sensitive(removable)
+ self['revert-tool-button'].set_sensitive(removable)
+
+ if node is not None and node.is_global():
+ self['remove-tool-button'].hide()
+ self['revert-tool-button'].show()
+ else:
+ self['remove-tool-button'].show()
+ self['revert-tool-button'].hide()
+
+ def do_update(self):
+ self.update_remove_revert()
+
+ piter, node = self.get_selected_tool()
+ self.current_node = node
+
+ if node is not None:
+ self.fill_fields()
+ self['tool-table'].set_sensitive(True)
+ else:
+ self.clear_fields()
+ self['tool-table'].set_sensitive(False)
+
+ def language_id_from_iter(self, piter):
+ if not piter:
+ return None
+
+ tool = self.model.get_value(piter, self.TOOL_COLUMN)
+
+ if isinstance(tool, Tool):
+ piter = self.model.iter_parent(piter)
+ tool = self.model.get_value(piter, self.TOOL_COLUMN)
+
+ if isinstance(tool, gsv.Language):
+ return tool.get_id()
+ elif tool:
+ return 'plain'
+
+ return None
+
+ def selected_language_id(self):
+ # Find current language if there is any
+ model, piter = self.view.get_selection().get_selected()
+
+ return self.language_id_from_iter(piter)
+
+ def on_new_tool_button_clicked(self, button):
+ self.save_current_tool()
+
+ # block handlers while inserting a new item
+ self.view.get_selection().handler_block(self.selection_changed_id)
+
+ self.current_node = Tool(self.tools.tree);
+ self.current_node.name = _('New tool')
+ self.tools.tree.tools.append(self.current_node)
+
+ lang = self.selected_language_id()
+
+ if lang:
+ self.current_node.languages = [lang]
+
+ piter = self.add_tool(self.current_node)
+
+ self.view.set_cursor(self.model.get_path(piter), self.view.get_column(self.TOOL_COLUMN), True)
+ self.fill_fields()
+
+ self['tool-table'].set_sensitive(True)
+ self.view.get_selection().handler_unblock(self.selection_changed_id)
+
+ def tool_changed(self, tool, refresh=False):
+ for row in self._tool_rows[tool]:
+ self.model.row_changed(row.get_path(), self.model.get_iter(row.get_path()))
+
+ if refresh and tool == self.current_node:
+ self.fill_fields()
+
+ self.update_remove_revert()
+
+ def on_remove_tool_button_clicked(self, button):
+ piter, node = self.get_selected_tool()
+
+ if not node:
+ return
+
+ if node.is_global():
+ shortcut = node.shortcut
+
+ if node.parent.revert_tool(node):
+ self.remove_accelerator(node, shortcut)
+ self.add_accelerator(node)
+
+ self['revert-tool-button'].set_sensitive(False)
+ self.fill_fields()
+
+ self.tool_changed(node)
+ else:
+ parent = self.model.iter_parent(piter)
+ language = self.language_id_from_iter(parent)
+
+ self.model.remove(piter)
+
+ if language in node.languages:
+ node.languages.remove(language)
+
+ self._tool_rows[node] = filter(lambda x: x.valid(), self._tool_rows[node])
+
+ if not self._tool_rows[node]:
+ del self._tool_rows[node]
+
+ if node.parent.delete_tool(node):
+ self.remove_accelerator(node)
+ self.current_node = None
+ self.script_hash = None
+
+ if self.model.iter_is_valid(piter):
+ self.view.set_cursor(self.model.get_path(piter), self.view.get_column(self.TOOL_COLUMN), False)
+
+ self.view.grab_focus()
+
+ path = self._languages[language].get_path()
+ parent = self.model.get_iter(path)
+
+ if not self.model.iter_has_child(parent):
+ self.model.remove(parent)
+ del self._languages[language]
+
+ def on_view_label_cell_edited(self, cell, path, new_text):
+ if new_text != '':
+ piter = self.model.get_iter(path)
+ tool = self.model.get_value(piter, self.TOOL_COLUMN)
+
+ tool.name = new_text
+
+ self.save_current_tool()
+ self.tool_changed(tool)
+
+ def on_view_label_cell_editing_started(self, renderer, editable, path):
+ piter = self.model.get_iter(path)
+ tool = self.model.get_value(piter, self.TOOL_COLUMN)
+
+ if isinstance(editable, gtk.Entry):
+ editable.set_text(tool.name)
+ editable.grab_focus()
+
+ def on_view_selection_changed(self, selection, userdata):
+ self.save_current_tool()
+ self.do_update()
+
+ def accelerator_collision(self, name, node):
+ if not name in self.accelerators:
+ return []
+
+ ret = []
+
+ for other in self.accelerators[name]:
+ if not other.languages or not node.languages:
+ ret.append(other)
+ continue
+
+ for lang in other.languages:
+ if lang in node.languages:
+ ret.append(other)
+ continue
+
+ return ret
+
+ def set_accelerator(self, keyval, mod):
+ # Check whether accelerator already exists
+ self.remove_accelerator(self.current_node)
+
+ name = gtk.accelerator_name(keyval, mod)
+
+ if name == '':
+ self.current_node.shorcut = None
+ self.save_current_tool()
+ return True
+
+ col = self.accelerator_collision(name, self.current_node)
+
+ if col:
+ dialog = gtk.MessageDialog(self.dialog,
+ gtk.DIALOG_MODAL,
+ gtk.MESSAGE_ERROR,
+ gtk.BUTTONS_OK,
+ _('This accelerator is already bound to %s') % (', '.join(map(lambda x: x.name, col)),))
+
+ dialog.run()
+ dialog.destroy()
+
+ self.add_accelerator(self.current_node)
+ return False
+
+ self.current_node.shortcut = name
+ self.add_accelerator(self.current_node)
+ self.save_current_tool()
+
+ return True
+
+ def on_accelerator_key_press(self, entry, event):
+ mask = event.state & gtk.accelerator_get_default_mod_mask()
+
+ if event.keyval == gtk.keysyms.Escape:
+ entry.set_text(default(self.current_node.shortcut, ''))
+ self['commands'].grab_focus()
+ return True
+ elif event.keyval == gtk.keysyms.Delete \
+ or event.keyval == gtk.keysyms.BackSpace:
+ entry.set_text('')
+ self.remove_accelerator(self.current_node)
+ self.current_node.shortcut = None
+ self['commands'].grab_focus()
+ return True
+ elif event.keyval in range(gtk.keysyms.F1, gtk.keysyms.F12 + 1):
+ # New accelerator
+ if self.set_accelerator(event.keyval, mask):
+ entry.set_text(default(self.current_node.shortcut, ''))
+ self['commands'].grab_focus()
+
+ # Capture all `normal characters`
+ return True
+ elif gtk.gdk.keyval_to_unicode(event.keyval):
+ if mask:
+ # New accelerator
+ if self.set_accelerator(event.keyval, mask):
+ entry.set_text(default(self.current_node.shortcut, ''))
+ self['commands'].grab_focus()
+ # Capture all `normal characters`
+ return True
+ else:
+ return False
+
+ def on_accelerator_focus_in(self, entry, event):
+ if self.current_node is None:
+ return
+ if self.current_node.shortcut:
+ entry.set_text(_('Type a new accelerator, or press Backspace to clear'))
+ else:
+ entry.set_text(_('Type a new accelerator'))
+
+ def on_accelerator_focus_out(self, entry, event):
+ if self.current_node is not None:
+ entry.set_text(default(self.current_node.shortcut, ''))
+ self.tool_changed(self.current_node)
+
+ def on_tool_manager_dialog_response(self, dialog, response):
+ if response == gtk.RESPONSE_HELP:
+ gedit.help_display(self.dialog, 'gedit', 'gedit-external-tools-plugin')
+ return
+
+ self.on_tool_manager_dialog_focus_out(dialog, None)
+
+ self.dialog.destroy()
+ self.dialog = None
+ self.tools = None
+
+ def on_tool_manager_dialog_focus_out(self, dialog, event):
+ self.save_current_tool()
+
+ for window in gedit.app_get_default().get_windows():
+ helper = window.get_data("ExternalToolsPluginWindowData")
+ helper.menu.update()
+
+ def get_cell_data_cb(self, column, cell, model, piter):
+ tool = model.get_value(piter, self.TOOL_COLUMN)
+
+ if tool == None or not isinstance(tool, Tool):
+ if tool == None:
+ label = _('All Languages')
+ elif not isinstance(tool, gsv.Language):
+ label = _('Plain Text')
+ else:
+ label = tool.get_name()
+
+ markup = saxutils.escape(label)
+ editable = False
+ else:
+ escaped = saxutils.escape(tool.name)
+
+ if tool.shortcut:
+ markup = '%s (<b>%s</b>)' % (escaped, saxutils.escape(tool.shortcut))
+ else:
+ markup = escaped
+
+ editable = True
+
+ cell.set_properties(markup=markup, editable=editable)
+
+ def tool_in_language(self, tool, lang):
+ if not lang in self._languages:
+ return False
+
+ ref = self._languages[lang]
+ parent = ref.get_path()
+
+ for row in self._tool_rows[tool]:
+ path = row.get_path()
+
+ if path[0] == parent[0]:
+ return True
+
+ return False
+
+ def update_languages(self, popup):
+ self.current_node.languages = popup.languages()
+ self.fill_languages_button()
+
+ piter, node = self.get_selected_tool()
+ ret = None
+
+ if node:
+ ref = gtk.TreeRowReference(self.model, self.model.get_path(piter))
+
+ # Update languages, make sure to inhibit selection change stuff
+ self.view.get_selection().handler_block(self.selection_changed_id)
+
+ # Remove all rows that are no longer
+ for row in list(self._tool_rows[self.current_node]):
+ piter = self.model.get_iter(row.get_path())
+ language = self.language_id_from_iter(piter)
+
+ if (not language and not self.current_node.languages) or \
+ (language in self.current_node.languages):
+ continue
+
+ # Remove from language
+ self.model.remove(piter)
+ self._tool_rows[self.current_node].remove(row)
+
+ # If language is empty, remove it
+ parent = self.model.get_iter(self._languages[language].get_path())
+
+ if not self.model.iter_has_child(parent):
+ self.model.remove(parent)
+ del self._languages[language]
+
+ # Now, add for any that are new
+ manager = gsv.LanguageManager()
+
+ for lang in self.current_node.languages:
+ if not self.tool_in_language(self.current_node, lang):
+ l = manager.get_language(lang)
+
+ if not l:
+ l = 'plain'
+
+ self.add_tool_to_language(self.current_node, l)
+
+ if not self.current_node.languages and not self.tool_in_language(self.current_node, None):
+ self.add_tool_to_language(self.current_node, None)
+
+ # Check if we can still keep the current
+ if not ref or not ref.valid():
+ # Change selection to first language
+ path = self._tool_rows[self.current_node][0].get_path()
+ piter = self.model.get_iter(path)
+ parent = self.model.iter_parent(piter)
+
+ # Expand parent, select child and scroll to it
+ self.view.expand_row(self.model.get_path(parent), False)
+ self.view.get_selection().select_path(path)
+ self.view.set_cursor(path, self.view.get_column(self.TOOL_COLUMN), False)
+
+ self.view.get_selection().handler_unblock(self.selection_changed_id)
+
+ def on_languages_button_clicked(self, button):
+ popup = LanguagesPopup(self.current_node.languages)
+ popup.set_transient_for(self.dialog)
+
+ origin = button.window.get_origin()
+ popup.move(origin[0], origin[1] - popup.allocation.height)
+
+ popup.connect('destroy', self.update_languages)
+
+# ex:et:ts=4: