home *** CD-ROM | disk | FTP | other *** search
/ PC Welt 2006 November (DVD) / PCWELT_11_2006.ISO / casper / filesystem.squashfs / usr / lib / gedit-2 / plugins / externaltools / manager.py < prev    next >
Encoding:
Python Source  |  2006-08-27  |  12.1 KB  |  359 lines

  1. # -*- coding: utf-8 -*-
  2. #    Gedit External Tools plugin
  3. #    Copyright (C) 2005-2006  Steve Fr├⌐cinaux <steve@istique.net>
  4. #
  5. #    This program is free software; you can redistribute it and/or modify
  6. #    it under the terms of the GNU General Public License as published by
  7. #    the Free Software Foundation; either version 2 of the License, or
  8. #    (at your option) any later version.
  9. #
  10. #    This program is distributed in the hope that it will be useful,
  11. #    but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. #    GNU General Public License for more details.
  14. #
  15. #    You should have received a copy of the GNU General Public License
  16. #    along with this program; if not, write to the Free Software
  17. #    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  18.  
  19. __all__ = ('Manager', )
  20.  
  21. import gtk
  22. import gtksourceview as gsv
  23. from gtk import glade
  24. import os.path
  25.  
  26. from functions import *
  27. import ElementTree as et
  28.  
  29. class Manager:
  30.     GLADE_FILE = os.path.join(os.path.dirname(__file__), "tools.glade")
  31.  
  32.     LABEL_COLUMN = 0 # For Combo and Tree
  33.     NODE_COLUMN  = 1 # For Tree only
  34.     NAME_COLUMN = 1  # For Combo only
  35.  
  36.     __shared_state = None
  37.  
  38.     combobox_items = {
  39.         'input': (
  40.             ('nothing'  , _('Nothing')),
  41.             ('document' , _('Current document')),
  42.             ('selection', _('Current selection')),
  43.             ('line'     , _('Current line')),
  44.             ('word'     , _('Current word'))
  45.         ),
  46.         'output': (
  47.             ('output-panel'     , _('Insert in output panel')),
  48.             ('new-document'     , _('Create new document')),
  49.             ('append-document'  , _('Append to current document')),
  50.             ('replace-document' , _('Replace current document')),
  51.             ('replace-selection', _('Replace current selection')),
  52.             ('insert'           , _('Insert at cursor position'))
  53.         ),
  54.         'applicability': (
  55.             ('all'     , _('All documents')),
  56.             ('titled'  , _('All documents except untitled ones')),
  57.             ('local'   , _('Local files only')),
  58.             ('remote'  , _('Remote files only')),
  59.             ('untitled', _('Untitled documents only'))
  60.         )
  61.     }
  62.  
  63.     def __init__(self):
  64.         if Manager.__shared_state is not None:
  65.             self.__dict__ = Manager.__shared_state
  66.             if self.dialog: return
  67.         else:
  68.             Manager.__shared_state = self.__dict__
  69.         
  70.         callbacks = {
  71.             'on_new_tool_button_clicked'      : self.on_new_tool_button_clicked,
  72.             'on_remove_tool_button_clicked'   : self.on_remove_tool_button_clicked,
  73.             'on_tool_manager_dialog_response' : self.on_tool_manager_dialog_response,
  74.             'on_tool_manager_dialog_focus_out': self.on_tool_manager_dialog_focus_out,
  75.             'on_accelerator_key_press'        : self.on_accelerator_key_press,
  76.             'on_accelerator_focus_in'         : self.on_accelerator_focus_in,
  77.             'on_accelerator_focus_out'        : self.on_accelerator_focus_out
  78.         }
  79.         
  80.         # Load the "main-window" widget from the glade file.
  81.         glade.set_custom_handler(self.custom_handler)
  82.         self.ui = glade.XML(self.GLADE_FILE, 'tool-manager-dialog')
  83.         self.ui.signal_autoconnect(callbacks)
  84.         self.dialog = self.ui.get_widget('tool-manager-dialog')
  85.         self.view = self.ui.get_widget('view')
  86.         for name in ['input', 'output', 'applicability']:
  87.             self.__init_combobox(name)
  88.         self.__init_tools_model()
  89.         self.__init_tools_view()
  90.         self.dialog.show()
  91.  
  92.     def __init_tools_model(self):
  93.         self.tools = ToolsTree()
  94.         self.current_node = None
  95.  
  96.         self.model = gtk.ListStore(str, object)
  97.         self.view.set_model(self.model)
  98.  
  99.         for item in self.tools:
  100.             self.model.append([item.get('label'), item])
  101.         
  102.         self.row_changed_id = self.model.connect('row-changed', self.on_tools_model_row_changed)
  103.  
  104.     def __init_tools_view(self):
  105.         # Tools column
  106.         column = gtk.TreeViewColumn('Tools')
  107.         renderer = gtk.CellRendererText()
  108.         column.pack_start(renderer, False)
  109.         column.set_attributes(renderer, text = self.LABEL_COLUMN)
  110.         renderer.set_property('editable', True)
  111.         self.view.append_column(column)
  112.         
  113.         renderer.connect('edited', self.on_view_label_cell_edited)
  114.         self.selection_changed_id = self.view.get_selection().connect('changed', self.on_view_selection_changed, None)
  115.             
  116.     def __init_combobox(self, name):
  117.         combo = self[name]
  118.         model = gtk.ListStore(str, str)
  119.         combo.set_model(model)
  120.  
  121.         for name, label in Manager.combobox_items[name]:
  122.             model.append((label, name))
  123.         combo.set_active(0)
  124.     
  125.     def __getitem__(self, key):
  126.         """Convenience function to get a widget from its name"""
  127.         return self.ui.get_widget(key)
  128.  
  129.     def custom_handler(self, xml, function_name, widget_name,
  130.                        str1, str2, int1 , int2):
  131.         if function_name == 'create_commands':
  132.             buf = gsv.SourceBuffer()
  133.             manager = gsv.SourceLanguagesManager()
  134.             language = manager.get_language_from_mime_type('text/x-shellscript')
  135.             buf.set_language(language)
  136.             buf.set_highlight(True)
  137.             view = gsv.SourceView(buf)
  138.             view.set_wrap_mode(gtk.WRAP_WORD)
  139.             view.show()
  140.             return view
  141.         else:
  142.             return None
  143.  
  144.     def set_active_by_name(self, combo_name, option_name):
  145.         combo = self[combo_name]
  146.         model = combo.get_model()
  147.         piter = model.get_iter_first()
  148.         while piter is not None:
  149.             if model.get_value(piter, self.NAME_COLUMN) == option_name:
  150.                 combo.set_active_iter(piter)
  151.                 return True
  152.             piter = model.iter_next(piter)
  153.         return False
  154.  
  155.     def get_selected_tool(self):
  156.         model, piter = self.view.get_selection().get_selected()
  157.         
  158.         if piter is not None:
  159.             return piter, model.get_value(piter, self.NODE_COLUMN);
  160.         else:
  161.             return None, None
  162.  
  163.     def save_current_tool(self):
  164.         if self.current_node is None:
  165.             return
  166.  
  167.         buf = self['commands'].get_buffer()
  168.         self.current_node.text = buf.get_text(buf.get_start_iter(),
  169.                                               buf.get_end_iter())
  170.  
  171.         self.current_node.set('description',
  172.                           self['description'].get_text())
  173.  
  174.         for name in ('input', 'output', 'applicability'):
  175.             combo = self[name]
  176.             self.current_node.set(name,
  177.                                   combo.get_model().get_value(
  178.                                          combo.get_active_iter(),
  179.                                          self.NAME_COLUMN))
  180.  
  181.     def clear_fields(self):
  182.         self['description'].set_text('')
  183.         self['accelerator'].set_text('')
  184.         self['commands'].get_buffer().set_text('')
  185.  
  186.         self.set_active_by_name('input', Manager.combobox_items['input'][0][0])
  187.         self.set_active_by_name('output', Manager.combobox_items['output'][0][0])
  188.         self.set_active_by_name('applicability', Manager.combobox_items['applicability'][0][0])
  189.         self['title'].set_label(_('Edit tool <i>%s</i>:') % '') # a bit ugly, but we're string frozen
  190.  
  191.     def fill_fields(self):
  192.         node = self.current_node
  193.         self['description'].set_text(default(node.get('description'), _('A Brand New Tool')))
  194.         self['accelerator'].set_text(default(node.get('accelerator'), ''))
  195.         self['commands'].get_buffer().set_text(default(node.text, ''))
  196.         
  197.         self.set_active_by_name('input',
  198.                                 default(node.get('input'),
  199.                                         Manager.combobox_items['input'][0][0]))
  200.         self.set_active_by_name('output',
  201.                                 default(node.get('output'),
  202.                                         Manager.combobox_items['output'][0][0]))
  203.         self.set_active_by_name('applicability',
  204.                                 default(node.get('applicability'),
  205.                                         Manager.combobox_items['applicability'][0][0]))
  206.         self['title'].set_label(_('Edit tool <i>%s</i>:') % node.get('label'))
  207.  
  208.     def on_new_tool_button_clicked(self, button):
  209.         self.save_current_tool()
  210.  
  211.         # block handlers while inserting a new item
  212.         self.model.handler_block(self.row_changed_id)
  213.         self.view.get_selection().handler_block(self.selection_changed_id)
  214.  
  215.         self.current_node = et.Element('tool');
  216.         self.current_node.set('label', _('New tool'))
  217.         self.tools.root.append(self.current_node)
  218.         piter = self.model.append([self.current_node.get('label'),
  219.                                    self.current_node])
  220.         self.view.set_cursor(self.model.get_path(piter),
  221.                              self.view.get_column(self.LABEL_COLUMN),
  222.                              True)
  223.         self.fill_fields()
  224.         self['tool-table'].set_sensitive(True)
  225.  
  226.         self.view.get_selection().handler_unblock(self.selection_changed_id)
  227.         self.model.handler_unblock(self.row_changed_id)
  228.  
  229.     def on_remove_tool_button_clicked(self, button):
  230.         piter, node = self.get_selected_tool()
  231.         self.tools.root.remove(node)
  232.         self.current_node = None
  233.         if self.model.remove(piter):
  234.             self.view.set_cursor(self.model.get_path(piter),
  235.                                  self.view.get_column(self.LABEL_COLUMN),
  236.                                  False)
  237.             self.view.grab_focus()
  238.  
  239.     def on_view_label_cell_edited(self, cell, path, new_text):
  240.         if new_text != '':
  241.             piter = self.model.get_iter(path)
  242.             node = self.model.get_value(piter, self.NODE_COLUMN)
  243.             node.set("label", new_text)
  244.             self.model.set(piter, self.LABEL_COLUMN, new_text)
  245.             self['title'].set_label(_('Edit tool <i>%s</i>:') % new_text)
  246.  
  247.     def on_view_selection_changed(self, selection, userdata):
  248.         self.save_current_tool()
  249.         piter, node = self.get_selected_tool()
  250.  
  251.         self['remove-tool-button'].set_sensitive(piter is not None)
  252.  
  253.         if node is not None:
  254.             self.current_node = node
  255.             self.fill_fields()
  256.             self['tool-table'].set_sensitive(True)
  257.         else:
  258.             self.clear_fields()
  259.             self['tool-table'].set_sensitive(False)
  260.  
  261.     def on_tools_model_row_changed(self, model, path, piter):
  262.         tool = model.get_value(piter, self.NODE_COLUMN)
  263.         if tool is not self.tools.root[path[0]]:
  264.             if tool in self.tools.root.items():
  265.                 self.tools.root.remove(tool)
  266.             self.tools.root.insert(path[0], tool)
  267.  
  268.     def set_accelerator(self, keyval, mod):
  269.         # Check whether accelerator already exists
  270.         
  271.          tool = self.tools.get_tool_from_accelerator(keyval,
  272.                                                      mod, 
  273.                                                      self.current_node)
  274.          if tool is not None:
  275.              dialog = gtk.MessageDialog(self.dialog,
  276.                                         gtk.DIALOG_MODAL,
  277.                                         gtk.MESSAGE_ERROR,
  278.                                         gtk.BUTTONS_OK,
  279.                                         _('This accelerator is already bound to %s') % tool.get('label'))
  280.             dialog.run()
  281.             dialog.destroy()
  282.              return False
  283.          
  284.         name = gtk.accelerator_name(keyval, mod)
  285.          if name != '':
  286.             self.current_node.set('accelerator', name)
  287.         else:
  288.             self.current_node.set('accelerator', None)
  289.         return True
  290.  
  291.     def on_accelerator_key_press(self, entry, event):
  292.         mask = event.state & gtk.accelerator_get_default_mod_mask()
  293.  
  294.         if event.keyval == gtk.keysyms.Escape:
  295.             entry.set_text(
  296.                        default(self.current_node.get('accelerator'),
  297.                                ''))
  298.             self['commands'].grab_focus()
  299.             return True
  300.         elif event.keyval == gtk.keysyms.Delete \
  301.           or event.keyval == gtk.keysyms.BackSpace:
  302.             entry.set_text('')
  303.             self.current_node.set('accelerator', '')
  304.             self['commands'].grab_focus()
  305.             return True
  306.         elif event.keyval in range(gtk.keysyms.F1, gtk.keysyms.F12):
  307.             # New accelerator
  308.             self.set_accelerator(event.keyval, mask)
  309.             entry.set_text(
  310.                        default(self.current_node.get('accelerator'),
  311.                                ''))
  312.             self['commands'].grab_focus()
  313.             # Capture all `normal characters`
  314.             return True            
  315.         elif gtk.gdk.keyval_to_unicode(event.keyval):
  316.             if mask:
  317.                 # New accelerator
  318.                 self.set_accelerator(event.keyval, mask)
  319.                 entry.set_text(
  320.                    default(self.current_node.get('accelerator'),
  321.                            ''))
  322.                 self['commands'].grab_focus()
  323.             # Capture all `normal characters`
  324.             return True
  325.         else:
  326.             return False
  327.     
  328.     def on_accelerator_focus_in(self, entry, event):
  329.         if self.current_node is None:
  330.             return
  331.         if self.current_node.get('accelerator'):
  332.             entry.set_text(_('Type a new accelerator, or press Backspace to clear'))
  333.         else:
  334.             entry.set_text(_('Type a new accelerator'))
  335.     
  336.     def on_accelerator_focus_out(self, entry, event):
  337.         if self.current_node is not None:
  338.             entry.set_text(default(self.current_node.get('accelerator'), ''))
  339.  
  340.     def on_tool_manager_dialog_response(self, dialog, response):
  341.         if response == gtk.RESPONSE_HELP:
  342.             gedit.help_display(self.dialog, 'gedit.xml', 'gedit-plugins')
  343.             return
  344.  
  345.         self.save_current_tool()
  346.  
  347.         self.dialog.destroy()
  348.         self.dialog = None
  349.  
  350.         self.tools.save()
  351.         update_tools_menu(tools = self.tools)
  352.         self.tools = None
  353.     
  354.     def on_tool_manager_dialog_focus_out(self, dialog, event):
  355.         self.save_current_tool()
  356.         update_tools_menu(tools = self.tools)
  357.  
  358. # ex:noet:ts=8:
  359.