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 import borg
from config import Config from config import Config
from util import dbg, err, get_config_dir from util import dbg, err, get_config_dir
from terminator import Terminator
class Plugin(object): class Plugin(object):
"""Definition of our base plugin class""" """Definition of our base plugin class"""
capabilities = None capabilities = None
is_permanent = None
def __init__(self): def __init__(self):
"""Class initialiser.""" """Class initialiser."""
pass pass
def unload(self):
"""Prepare to be unloaded"""
pass
class PluginRegistry(borg.Borg): class PluginRegistry(borg.Borg):
"""Definition of a class to store plugin instances""" """Definition of a class to store plugin instances"""
available_plugins = None available_plugins = None
@ -128,29 +132,18 @@ for %s' % (len(self.instances), capability))
not""" not"""
return(self.instances.has_key(plugin)) 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): def enable(self, plugin):
"""Enable a plugin""" """Enable a plugin"""
if plugin in self.instances:
err("Cannot enable plugin %s, already enabled" % plugin)
dbg("Enabling %s" % 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): def disable(self, plugin):
"""Disable a plugin""" """Disable a plugin"""
if self.instances[plugin].is_permanent: dbg("Disabling %s" % plugin)
dbg("Refusing to disable permanent plugin %s" % plugin) self.instances[plugin].unload()
else: del(self.instances[plugin])
dbg("Disabling %s" % plugin)
del(self.instances[plugin])
# This is where we should define a base class for each type of plugin we # This is where we should define a base class for each type of plugin we
# support # support
@ -162,12 +155,28 @@ class URLHandler(Plugin):
capabilities = ['url_handler'] capabilities = ['url_handler']
handler_name = None handler_name = None
match = 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): def callback(self, url):
"""Callback to transform the enclosed URL""" """Callback to transform the enclosed URL"""
raise NotImplementedError 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 # MenuItem - This is able to execute code during the construction of the
# context menu of a Terminal. # context menu of a Terminal.
class MenuItem(Plugin): class MenuItem(Plugin):

View File

@ -2865,51 +2865,32 @@
<object class="GtkHBox" id="hbox7"> <object class="GtkHBox" id="hbox7">
<property name="visible">True</property> <property name="visible">True</property>
<child> <child>
<object class="GtkVBox" id="vbox12"> <object class="GtkTreeView" id="pluginlist">
<property name="visible">True</property> <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> <child>
<object class="GtkTreeView" id="pluginlist"> <object class="GtkTreeViewColumn" id="plugincolumn1">
<property name="visible">True</property> <property name="title">Plugin</property>
<property name="can_focus">True</property> <property name="clickable">True</property>
<property name="model">PluginListStore</property>
<property name="hadjustment">adjustment2</property>
<property name="vadjustment">adjustment3</property>
<property name="search_column">0</property>
<child> <child>
<object class="GtkTreeViewColumn" id="plugincolumn1"> <object class="GtkCellRendererToggle" id="cellrenderertext15">
<property name="title">Plugin</property> <signal name="toggled" handler="on_plugin_toggled"/>
<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> </object>
<attributes>
<attribute name="active">1</attribute>
</attributes>
</child>
<child>
<object class="GtkCellRendererText" id="cellrenderertext16"/>
<attributes>
<attribute name="text">0</attribute>
</attributes>
</child> </child>
</object> </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> </child>
</object> </object>
<packing> <packing>

View File

@ -1025,6 +1025,13 @@ class PrefsEditor:
model = treeview.get_model() model = treeview.get_model()
plugin = model[path][0] 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] self.plugins[plugin] = not self.plugins[plugin]
# Update the treeview # Update the treeview
model[path][1] = self.plugins[plugin] model[path][1] = self.plugins[plugin]

View File

@ -268,12 +268,31 @@ class Terminal(gtk.VBox):
for urlplugin in plugins: for urlplugin in plugins:
name = urlplugin.handler_name name = urlplugin.handler_name
match = urlplugin.match 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) self.matches[name] = self.vte.match_add(match)
dbg('Terminal::update_matches: added plugin URL handler \ dbg('Terminal::update_matches: added plugin URL handler \
for %s (%s)' % (name, urlplugin.__class__.__name__)) for %s (%s)' % (name, urlplugin.__class__.__name__))
except Exception, ex: except Exception, ex:
err('Terminal::update_url_matches: %s' % 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): def connect_signals(self):
"""Connect all the gtk signals and drag-n-drop mechanics""" """Connect all the gtk signals and drag-n-drop mechanics"""