home *** CD-ROM | disk | FTP | other *** search
/ Mac Easy 2010 May / Mac Life Ubuntu.iso / casper / filesystem.squashfs / usr / lib / gedit-2 / plugins / externaltools / manager.py < prev    next >
Encoding:
Python Source  |  2009-04-14  |  13.6 KB  |  362 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 gedit
  22. import gtk
  23. import gtksourceview2 as gsv
  24. import os.path
  25. from library import *
  26. from functions import *
  27. import hashlib
  28.  
  29. class Singleton(object):
  30.     _instance = None
  31.  
  32.     def __new__(cls, *args, **kwargs):
  33.         if not cls._instance:
  34.             cls._instance = super(Singleton, cls).__new__(
  35.                              cls, *args, **kwargs)
  36.             cls._instance.__init_once__()
  37.  
  38.         return cls._instance
  39.  
  40. class Manager(Singleton):
  41.     LABEL_COLUMN = 0 # For Combo and Tree
  42.     NODE_COLUMN  = 1 # For Tree only
  43.     NAME_COLUMN = 1  # For Combo only
  44.  
  45.     def __init__(self, datadir):
  46.         self.datadir = datadir
  47.  
  48.     def __init_once__(self):
  49.         self.default_size = None
  50.         self.dialog = None
  51.     
  52.     def build(self):
  53.         callbacks = {
  54.             'on_new_tool_button_clicked'      : self.on_new_tool_button_clicked,
  55.             'on_remove_tool_button_clicked'   : self.on_remove_tool_button_clicked,
  56.             'on_tool_manager_dialog_response' : self.on_tool_manager_dialog_response,
  57.             'on_tool_manager_dialog_focus_out': self.on_tool_manager_dialog_focus_out,
  58.             'on_accelerator_key_press'        : self.on_accelerator_key_press,
  59.             'on_accelerator_focus_in'         : self.on_accelerator_focus_in,
  60.             'on_accelerator_focus_out'        : self.on_accelerator_focus_out
  61.         }
  62.  
  63.         # Load the "main-window" widget from the ui file.
  64.         self.ui = gtk.Builder()
  65.         self.ui.add_from_file(os.path.join(self.datadir, 'ui', 'tools.ui'))
  66.         self.ui.connect_signals(callbacks)
  67.         self.dialog = self.ui.get_object('tool-manager-dialog')
  68.         
  69.         if self.default_size != None:
  70.             self.dialog.set_default_size(*self.default_size)
  71.         
  72.         self.view = self.ui.get_object('view')
  73.         for name in ['input', 'output', 'applicability']:
  74.             self.__init_combobox(name)
  75.         self.__init_tools_model()
  76.         self.__init_tools_view()
  77.     
  78.     def run(self):
  79.         if self.dialog == None:
  80.             self.build()
  81.             self.dialog.show()
  82.         else:
  83.             self.dialog.present()
  84.         
  85.     def __init_tools_model(self):
  86.         self.tools = ToolLibrary()
  87.         self.current_node = None
  88.         self.script_hash = None
  89.         self.accelerators = dict()
  90.  
  91.         self.model = gtk.ListStore(str, object)
  92.         self.view.set_model(self.model)
  93.  
  94.         for item in self.tools.tree.tools:
  95.             self.model.append([item.name, item])
  96.             if item.shortcut:
  97.                 self.accelerators[item.shortcut] = item
  98.  
  99.     def __init_tools_view(self):
  100.         # Tools column
  101.         column = gtk.TreeViewColumn('Tools')
  102.         renderer = gtk.CellRendererText()
  103.         column.pack_start(renderer, False)
  104.         column.set_attributes(renderer, text = self.LABEL_COLUMN)
  105.         renderer.set_property('editable', True)
  106.         self.view.append_column(column)
  107.  
  108.         renderer.connect('edited', self.on_view_label_cell_edited)
  109.         self.selection_changed_id = self.view.get_selection().connect('changed', self.on_view_selection_changed, None)
  110.  
  111.     def __init_combobox(self, name):
  112.         combo = self[name]
  113.         combo.set_active(0)
  114.  
  115.     # Convenience function to get an object from its name
  116.     def __getitem__(self, key):
  117.         return self.ui.get_object(key)
  118.  
  119.     def set_active_by_name(self, combo_name, option_name):
  120.         combo = self[combo_name]
  121.         model = combo.get_model()
  122.         piter = model.get_iter_first()
  123.         while piter is not None:
  124.             if model.get_value(piter, self.NAME_COLUMN) == option_name:
  125.                 combo.set_active_iter(piter)
  126.                 return True
  127.             piter = model.iter_next(piter)
  128.         return False
  129.  
  130.     def get_selected_tool(self):
  131.         model, piter = self.view.get_selection().get_selected()
  132.  
  133.         if piter is not None:
  134.             return piter, model.get_value(piter, self.NODE_COLUMN);
  135.         else:
  136.             return None, None
  137.  
  138.     def compute_hash(self, string):
  139.         return hashlib.md5(string).hexdigest()
  140.  
  141.     def save_current_tool(self):
  142.         if self.current_node is None:
  143.              return
  144.  
  145.         if self.current_node.filename is None:
  146.             self.current_node.autoset_filename()
  147.  
  148.         def combo_value(o, name):
  149.             combo = o[name]
  150.             return combo.get_model().get_value(combo.get_active_iter(), self.NAME_COLUMN)
  151.  
  152.         self.current_node.input = combo_value(self, 'input')
  153.         self.current_node.output = combo_value(self, 'output')
  154.         self.current_node.applicability = combo_value(self, 'applicability')
  155.         self.current_node.comment = self['description'].get_text()
  156.  
  157.         buf = self['commands'].get_buffer()
  158.         script  = buf.get_text(*buf.get_bounds())
  159.         h = self.compute_hash(script)
  160.         if h != self.script_hash:
  161.             # script has changed -> save it
  162.             self.current_node.save_with_script([line + "\n" for line in script.splitlines()])
  163.             self.script_hash = h
  164.         else:
  165.             self.current_node.save()
  166.  
  167.     def clear_fields(self):
  168.         self['description'].set_text('')
  169.         self['accelerator'].set_text('')
  170.         self['commands'].get_buffer().set_text('')
  171.  
  172.         for nm in ('input', 'output', 'applicability'):
  173.             self[nm].set_active(0)
  174.  
  175.         self['title'].set_label(_('Edit tool <i>%s</i>:') % '') # a bit ugly, but we're string frozen
  176.     
  177.     def fill_fields(self):
  178.         node = self.current_node
  179.         self['description'].set_text(default(node.comment, _('A Brand New Tool')))
  180.         self['accelerator'].set_text(default(node.shortcut, ''))
  181.  
  182.         buf = self['commands'].get_buffer()
  183.         script = default(''.join(node.get_script()), '')
  184.         buf.set_text(script)
  185.         self.script_hash = self.compute_hash(script)
  186.         contenttype = gio.content_type_guess(data=script)
  187.         lmanager = gedit.get_language_manager()
  188.         language = lmanager.guess_language(content_type=contenttype)
  189.  
  190.         if language is not None:
  191.             buf.set_language(language)
  192.             buf.set_highlight_syntax(True)
  193.         else:
  194.             buf.set_highlight_syntax(False)
  195.  
  196.         for nm in ('input', 'output', 'applicability'):
  197.             model = self[nm].get_model()
  198.             piter = model.get_iter_first()
  199.             
  200.             self.set_active_by_name(nm,
  201.                                     default(node.__getattribute__(nm),
  202.                                     model.get_value(piter, self.NAME_COLUMN)))
  203.  
  204.         self['title'].set_label(_('Edit tool <i>%s</i>:') % node.name)
  205.  
  206.     def on_new_tool_button_clicked(self, button):
  207.         self.save_current_tool()
  208.         
  209.         # block handlers while inserting a new item
  210.         self.view.get_selection().handler_block(self.selection_changed_id)
  211.  
  212.         self.current_node = Tool(self.tools.tree);
  213.         self.current_node.name = _('New tool')
  214.         self.tools.tree.tools.append(self.current_node)
  215.         piter = self.model.append([self.current_node.name, self.current_node])
  216.         self.view.set_cursor(self.model.get_path(piter),
  217.                              self.view.get_column(self.LABEL_COLUMN),
  218.                              True)
  219.         self.fill_fields()
  220.         self['tool-table'].set_sensitive(True)
  221.  
  222.         self.view.get_selection().handler_unblock(self.selection_changed_id)
  223.  
  224.     def on_remove_tool_button_clicked(self, button):
  225.         piter, node = self.get_selected_tool()
  226.  
  227.         if node.is_global():
  228.             if node.parent.revert_tool(node):
  229.                 if self.current_node.shortcut and \
  230.                    self.current_node.shortcut in self.accelerator:
  231.                     del self.accelerators[self.current_node.shortcut]                
  232.                 self['revert-tool-button'].set_sensitive(False)
  233.                 self.fill_fields()
  234.         else:
  235.             if node.parent.delete_tool(node):
  236.                 if self.current_node.shortcut:
  237.                     del self.accelerators[self.current_node.shortcut]
  238.                 self.current_node = None
  239.                 self.script_hash = None
  240.                 if self.model.remove(piter):
  241.                     self.view.set_cursor(self.model.get_path(piter),
  242.                                          self.view.get_column(self.LABEL_COLUMN),
  243.                                         False)
  244.                     self.view.grab_focus()
  245.  
  246.     def on_view_label_cell_edited(self, cell, path, new_text):
  247.         if new_text != '':
  248.             piter = self.model.get_iter(path)
  249.             node = self.model.get_value(piter, self.NODE_COLUMN)
  250.             node.name = new_text
  251.             self.model.set(piter, self.LABEL_COLUMN, new_text)
  252.             self['title'].set_label(_('Edit tool <i>%s</i>:') % new_text)
  253.  
  254.     def on_view_selection_changed(self, selection, userdata):
  255.         print 'saving current tool'
  256.         self.save_current_tool()
  257.         piter, node = self.get_selected_tool()
  258.  
  259.         removable = piter is not None and node is not None and node.is_local()
  260.         self['remove-tool-button'].set_sensitive(removable)
  261.         self['revert-tool-button'].set_sensitive(removable)
  262.         if node is not None and node.is_global():
  263.             self['remove-tool-button'].hide()
  264.             self['revert-tool-button'].show()
  265.         else:
  266.             self['remove-tool-button'].show()
  267.             self['revert-tool-button'].hide()
  268.  
  269.         if node is not None:
  270.             self.current_node = node
  271.             self.fill_fields()
  272.             self['tool-table'].set_sensitive(True)
  273.         else:
  274.             self.clear_fields()
  275.             self['tool-table'].set_sensitive(False)
  276.  
  277.     def set_accelerator(self, keyval, mod):
  278.         # Check whether accelerator already exists
  279.  
  280.         if self.current_node.shortcut:
  281.             del self.accelerators[self.current_node.shortcut]
  282.         name = gtk.accelerator_name(keyval, mod)
  283.         if name != '':
  284.             if name in self.accelerators:
  285.                 dialog = gtk.MessageDialog(self.dialog,
  286.                                            gtk.DIALOG_MODAL,
  287.                                            gtk.MESSAGE_ERROR,
  288.                                            gtk.BUTTONS_OK,
  289.                                            _('This accelerator is already bound to %s') % self.accelerators[name].name)
  290.                 dialog.run()
  291.                 dialog.destroy()
  292.                 return False
  293.             self.current_node.shortcut = name
  294.             self.accelerators[name] = self.current_node
  295.         else:
  296.             self.current_node.shortcut = None
  297.         return True
  298.  
  299.     def on_accelerator_key_press(self, entry, event):
  300.         mask = event.state & gtk.accelerator_get_default_mod_mask()
  301.  
  302.         if event.keyval == gtk.keysyms.Escape:
  303.             entry.set_text(default(self.current_node.shortcut, ''))
  304.             self['commands'].grab_focus()
  305.             return True
  306.         elif event.keyval == gtk.keysyms.Delete \
  307.           or event.keyval == gtk.keysyms.BackSpace:
  308.             entry.set_text('')
  309.             self.current_node.shortcut = None
  310.             self['commands'].grab_focus()
  311.             return True
  312.         elif event.keyval in range(gtk.keysyms.F1, gtk.keysyms.F12 + 1):
  313.             # New accelerator
  314.             self.set_accelerator(event.keyval, mask)
  315.             entry.set_text(default(self.current_node.shortcut, ''))
  316.             self['commands'].grab_focus()
  317.             # Capture all `normal characters`
  318.             return True
  319.         elif gtk.gdk.keyval_to_unicode(event.keyval):
  320.             if mask:
  321.                 # New accelerator
  322.                 self.set_accelerator(event.keyval, mask)
  323.                 entry.set_text(default(self.current_node.shortcut, ''))
  324.                 self['commands'].grab_focus()
  325.             # Capture all `normal characters`
  326.             return True
  327.         else:
  328.             return False
  329.  
  330.     def on_accelerator_focus_in(self, entry, event):
  331.         pass
  332.         if self.current_node is None:
  333.             return
  334.         if self.current_node.shortcut:
  335.             entry.set_text(_('Type a new accelerator, or press Backspace to clear'))
  336.         else:
  337.             entry.set_text(_('Type a new accelerator'))
  338.  
  339.     def on_accelerator_focus_out(self, entry, event):
  340.         if self.current_node is not None:
  341.             entry.set_text(default(self.current_node.shortcut, ''))
  342.  
  343.     def on_tool_manager_dialog_response(self, dialog, response):
  344.         if response == gtk.RESPONSE_HELP:
  345.             gedit.help_display(self.dialog, 'gedit', 'gedit-external-tools-plugin')
  346.             return
  347.  
  348.         self.on_tool_manager_dialog_focus_out(dialog, None)
  349.         self.default_size = [self.dialog.allocation.width, self.dialog.allocation.height]
  350.         
  351.         self.dialog.destroy()
  352.         self.dialog = None
  353.         self.tools = None
  354.  
  355.     def on_tool_manager_dialog_focus_out(self, dialog, event):
  356.         self.save_current_tool()
  357.         for window in gedit.app_get_default().get_windows():
  358.             helper = window.get_data("ExternalToolsPluginWindowData")
  359.             helper.menu.update()
  360.  
  361. # ex:et:ts=4:
  362.