Switch the plugin prefs pane back to live loading/unloading of plugins without silly compromises

This commit is contained in:
Chris Jones 2010-06-23 00:48:06 +01:00
parent 70a66ee218
commit 45a9c26cf2
4 changed files with 75 additions and 59 deletions

View File

@ -28,16 +28,20 @@ import os
import borg
from config import Config
from util import dbg, err, get_config_dir
from terminator import Terminator
class Plugin(object):
"""Definition of our base plugin class"""
capabilities = None
is_permanent = None
def __init__(self):
"""Class initialiser."""
pass
def unload(self):
"""Prepare to be unloaded"""
pass
class PluginRegistry(borg.Borg):
"""Definition of a class to store plugin instances"""
available_plugins = None
@ -128,29 +132,18 @@ for %s' % (len(self.instances), capability))
not"""
return(self.instances.has_key(plugin))
def is_permanent(self, plugin):
"""Return a boolean value indicating whether a plugin is believed to be
permanent. This is impossible to determine for plugins that haven't
been loaded, so they will report as not being permanent until they are
loaded"""
if plugin not in self.instances:
return(False)
else:
return(self.instances[plugin].is_permanent)
def enable(self, plugin):
"""Enable a plugin"""
if plugin in self.instances:
err("Cannot enable plugin %s, already enabled" % plugin)
dbg("Enabling %s" % plugin)
if plugin not in self.instances:
self.instances[plugin] = self.available_plugins[plugin]()
self.instances[plugin] = self.available_plugins[plugin]()
def disable(self, plugin):
"""Disable a plugin"""
if self.instances[plugin].is_permanent:
dbg("Refusing to disable permanent plugin %s" % plugin)
else:
dbg("Disabling %s" % plugin)
del(self.instances[plugin])
dbg("Disabling %s" % plugin)
self.instances[plugin].unload()
del(self.instances[plugin])
# This is where we should define a base class for each type of plugin we
# support
@ -162,12 +155,28 @@ class URLHandler(Plugin):
capabilities = ['url_handler']
handler_name = None
match = None
is_permanent = True
def __init__(self):
"""Class initialiser"""
Plugin.__init__(self)
terminator = Terminator()
for terminal in terminator.terminals:
terminal.match_add(self.handler_name, self.match)
def callback(self, url):
"""Callback to transform the enclosed URL"""
raise NotImplementedError
def unload(self):
"""Handle being removed"""
if not self.match:
err('unload called without self.handler_name being set')
return
terminator = Terminator()
for terminal in terminator.terminals:
print self.handler_name
terminal.match_remove(self.handler_name)
# MenuItem - This is able to execute code during the construction of the
# context menu of a Terminal.
class MenuItem(Plugin):

View File

@ -2865,51 +2865,32 @@
<object class="GtkHBox" id="hbox7">
<property name="visible">True</property>
<child>
<object class="GtkVBox" id="vbox12">
<object class="GtkTreeView" id="pluginlist">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="model">PluginListStore</property>
<property name="hadjustment">adjustment2</property>
<property name="vadjustment">adjustment3</property>
<property name="search_column">0</property>
<child>
<object class="GtkTreeView" id="pluginlist">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="model">PluginListStore</property>
<property name="hadjustment">adjustment2</property>
<property name="vadjustment">adjustment3</property>
<property name="search_column">0</property>
<object class="GtkTreeViewColumn" id="plugincolumn1">
<property name="title">Plugin</property>
<property name="clickable">True</property>
<child>
<object class="GtkTreeViewColumn" id="plugincolumn1">
<property name="title">Plugin</property>
<property name="clickable">True</property>
<child>
<object class="GtkCellRendererToggle" id="cellrenderertext15">
<signal name="toggled" handler="on_plugin_toggled"/>
</object>
<attributes>
<attribute name="active">1</attribute>
</attributes>
</child>
<child>
<object class="GtkCellRendererText" id="cellrenderertext16"/>
<attributes>
<attribute name="text">0</attribute>
</attributes>
</child>
<object class="GtkCellRendererToggle" id="cellrenderertext15">
<signal name="toggled" handler="on_plugin_toggled"/>
</object>
<attributes>
<attribute name="active">1</attribute>
</attributes>
</child>
<child>
<object class="GtkCellRendererText" id="cellrenderertext16"/>
<attributes>
<attribute name="text">0</attribute>
</attributes>
</child>
</object>
<packing>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label13">
<property name="visible">True</property>
<property name="label" translatable="yes">Plugins will be enabled/disabled after restarting Terminator</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>

View File

@ -1025,6 +1025,13 @@ class PrefsEditor:
model = treeview.get_model()
plugin = model[path][0]
if not self.plugins[plugin]:
# Plugin is currently disabled, load it
self.registry.enable(plugin)
else:
# Plugin is currently enabled, unload it
self.registry.disable(plugin)
self.plugins[plugin] = not self.plugins[plugin]
# Update the treeview
model[path][1] = self.plugins[plugin]

View File

@ -268,12 +268,31 @@ class Terminal(gtk.VBox):
for urlplugin in plugins:
name = urlplugin.handler_name
match = urlplugin.match
if name in self.matches:
dbg('Terminal::update_matches: refusing to add \
duplicate match %s' % name)
continue
self.matches[name] = self.vte.match_add(match)
dbg('Terminal::update_matches: added plugin URL handler \
for %s (%s)' % (name, urlplugin.__class__.__name__))
except Exception, ex:
err('Terminal::update_url_matches: %s' % ex)
def match_add(self, name, match):
"""Register a URL match"""
if name in self.matches:
err('Terminal::match_add: Refusing to create duplicate match %s' % name)
return
self.matches[name] = self.vte.match_add(match)
def match_remove(self, name):
"""Remove a previously registered URL match"""
if name not in self.matches:
err('Terminal::match_remove: Unable to remove non-existent match %s' % name)
return
self.vte.match_remove(self.matches[name])
del(self.matches[name])
def connect_signals(self):
"""Connect all the gtk signals and drag-n-drop mechanics"""