0001981: Update plugin status when reloading plugins

Plus some cleanup.

svn: r10439
This commit is contained in:
Brian Matherly 2008-04-01 03:12:08 +00:00
parent e7a6115c91
commit bfe3ee1590
4 changed files with 162 additions and 199 deletions

View File

@ -95,7 +95,7 @@ def load_plugins(direct):
responsible for registering itself in the correct manner. No attempt responsible for registering itself in the correct manner. No attempt
is done in this routine to register the tasks. Returns True on error. """ is done in this routine to register the tasks. Returns True on error. """
global success_list,attempt_list,loaddir_list,failmsg_list global success_list, attempt_list, loaddir_list, failmsg_list
# if the directory does not exist, do nothing # if the directory does not exist, do nothing
if not os.path.isdir(direct): if not os.path.isdir(direct):
@ -132,6 +132,71 @@ def load_plugins(direct):
return len(failmsg_list) != 0 # return True if there are errors return len(failmsg_list) != 0 # return True if there are errors
#-------------------------------------------------------------------------
#
# reload_plugins
#
#-------------------------------------------------------------------------
def reload_plugins():
""" Reload previously loaded plugins """
global success_list, attempt_list, loaddir_list, failmsg_list
pymod = re.compile(r"^(.*)\.py$")
oldfailmsg = failmsg_list[:]
failmsg_list = []
# attempt to reload all plugins that have succeeded in the past
for plugin in success_list:
filename = plugin[0]
filename = filename.replace('pyc','py')
filename = filename.replace('pyo','py')
try:
reload(plugin[1])
except:
failmsg_list.append((filename, sys.exc_info()))
# Remove previously good plugins that are now bad
# from the registered lists
purge_failed()
# attempt to load the plugins that have failed in the past
for (filename, message) in oldfailmsg:
name = os.path.split(filename)
match = pymod.match(name[1])
if not match:
continue
attempt_list.append(filename)
plugin = match.groups()[0]
try:
# For some strange reason second importing of a failed plugin
# results in success. Then reload reveals the actual error.
# Looks like a bug in Python.
a = __import__(plugin)
reload(a)
success_list.append((filename, a))
except:
failmsg_list.append((filename, sys.exc_info()))
# attempt to load any new files found
for directory in loaddir_list:
for filename in os.listdir(directory):
name = os.path.split(filename)
match = pymod.match(name[1])
if not match:
continue
if filename in attempt_list:
continue
attempt_list.append(filename)
plugin = match.groups()[0]
try:
a = __import__(plugin)
if a not in [plugin[1]
for plugin in success_list]:
success_list.append((filename, a))
except:
failmsg_list.append((filename, sys.exc_info()))
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
# #
# Plugin registering # Plugin registering

View File

@ -55,16 +55,17 @@ import _Tool as Tool
class PluginStatus(ManagedWindow.ManagedWindow): class PluginStatus(ManagedWindow.ManagedWindow):
"""Displays a dialog showing the status of loaded plugins""" """Displays a dialog showing the status of loaded plugins"""
def __init__(self, state, uistate, track=[]): def __init__(self, uistate, track=[]):
self.__uistate = uistate
self.title = _("Plugin Status") self.title = _("Plugin Status")
ManagedWindow.ManagedWindow.__init__(self,uistate,track,self.__class__) ManagedWindow.ManagedWindow.__init__(self, uistate, track,
self.__class__)
self.set_window(gtk.Dialog("",uistate.window, self.set_window(gtk.Dialog("", uistate.window,
gtk.DIALOG_DESTROY_WITH_PARENT, gtk.DIALOG_DESTROY_WITH_PARENT,
(gtk.STOCK_CLOSE, gtk.RESPONSE_CLOSE)), (gtk.STOCK_CLOSE, gtk.RESPONSE_CLOSE)),
None, self.title) None, self.title)
self.window.set_size_request(600,400) self.window.set_size_request(600, 400)
self.window.connect('response', self.close) self.window.connect('response', self.close)
scrolled_window = gtk.ScrolledWindow() scrolled_window = gtk.ScrolledWindow()
@ -88,8 +89,19 @@ class PluginStatus(ManagedWindow.ManagedWindow):
scrolled_window.add(self.list) scrolled_window.add(self.list)
self.window.vbox.add(scrolled_window) self.window.vbox.add(scrolled_window)
if __debug__:
# Only show the "Reload" button when in debug mode
# (without -O on the command line)
self.__reload_btn = gtk.Button("Reload")
self.window.action_area.add(self.__reload_btn)
self.__reload_btn.connect('clicked', self.__reload)
self.window.show_all() self.window.show_all()
self.__populate_list()
def __populate_list(self):
""" Build the list of plugins """
for i in PluginMgr.failmsg_list: for i in PluginMgr.failmsg_list:
err = i[1][0] err = i[1][0]
@ -110,6 +122,7 @@ class PluginStatus(ManagedWindow.ManagedWindow):
i[0], descr, None]) i[0], descr, None])
def button_press(self, obj, event): def button_press(self, obj, event):
""" Callback function from the user clicking on a line """
if event.type == gtk.gdk._2BUTTON_PRESS and event.button == 1: if event.type == gtk.gdk._2BUTTON_PRESS and event.button == 1:
model, node = self.selection.get_selected() model, node = self.selection.get_selected()
data = model.get_value(node, 3) data = model.get_value(node, 3)
@ -118,8 +131,16 @@ class PluginStatus(ManagedWindow.ManagedWindow):
PluginTrace(self.uistate, self.track, data, name) PluginTrace(self.uistate, self.track, data, name)
def build_menu_names(self, obj): def build_menu_names(self, obj):
return ( _('Summary'),self.title) return (self.title, "")
def __reload(self, obj):
""" Callback function from the "Reload" button """
PluginMgr.reload_plugins()
self.__uistate.emit('plugins-reloaded',
(PluginMgr.tool_list, PluginMgr.report_list))
self.model.clear()
self.__populate_list()
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
# #
# Details for an individual plugin that failed # Details for an individual plugin that failed
@ -133,15 +154,15 @@ class PluginTrace(ManagedWindow.ManagedWindow):
title = "%s: %s" % (_("Plugin Status"), name) title = "%s: %s" % (_("Plugin Status"), name)
ManagedWindow.ManagedWindow.__init__(self, uistate, track, self) ManagedWindow.ManagedWindow.__init__(self, uistate, track, self)
self.set_window(gtk.Dialog("",uistate.window, self.set_window(gtk.Dialog("", uistate.window,
gtk.DIALOG_DESTROY_WITH_PARENT, gtk.DIALOG_DESTROY_WITH_PARENT,
(gtk.STOCK_CLOSE, gtk.RESPONSE_CLOSE)), (gtk.STOCK_CLOSE, gtk.RESPONSE_CLOSE)),
None, title) None, title)
self.window.set_size_request(600,400) self.window.set_size_request(600, 400)
self.window.connect('response', self.close) self.window.connect('response', self.close)
scrolled_window = gtk.ScrolledWindow() scrolled_window = gtk.ScrolledWindow()
scrolled_window.set_policy(gtk.POLICY_AUTOMATIC,gtk.POLICY_AUTOMATIC) scrolled_window.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
self.text = gtk.TextView() self.text = gtk.TextView()
scrolled_window.add(self.text) scrolled_window.add(self.text)
self.text.get_buffer().set_text( self.text.get_buffer().set_text(
@ -189,18 +210,18 @@ class ToolManagedWindowBase(ManagedWindow.ManagedWindow):
self.style_button = None self.style_button = None
window = gtk.Dialog('Tool') window = gtk.Dialog('Tool')
self.set_window(window,None,self.get_title()) self.set_window(window, None, self.get_title())
#self.window.set_has_separator(False) #self.window.set_has_separator(False)
#self.window.connect('response', self.close) #self.window.connect('response', self.close)
self.cancel = self.window.add_button(gtk.STOCK_CLOSE, self.cancel = self.window.add_button(gtk.STOCK_CLOSE,
gtk.RESPONSE_CANCEL) gtk.RESPONSE_CANCEL)
self.cancel.connect('clicked',self.close) self.cancel.connect('clicked', self.close)
self.ok = self.window.add_button(gtk.STOCK_APPLY, gtk.RESPONSE_OK) self.ok = self.window.add_button(gtk.STOCK_APPLY, gtk.RESPONSE_OK)
self.ok.connect('clicked',self.on_ok_clicked) self.ok.connect('clicked', self.on_ok_clicked)
self.window.set_default_size(600,-1) self.window.set_default_size(600, -1)
# Set up and run the dialog. These calls are not in top down # Set up and run the dialog. These calls are not in top down
# order when looking at the dialog box as there is some # order when looking at the dialog box as there is some
@ -208,7 +229,7 @@ class ToolManagedWindowBase(ManagedWindow.ManagedWindow):
self.setup_title() self.setup_title()
self.setup_header() self.setup_header()
self.tbl = gtk.Table(4,4,False) self.tbl = gtk.Table(4, 4, False)
self.tbl.set_col_spacings(12) self.tbl.set_col_spacings(12)
self.tbl.set_row_spacings(6) self.tbl.set_row_spacings(6)
self.tbl.set_border_width(6) self.tbl.set_border_width(6)
@ -241,7 +262,7 @@ class ToolManagedWindowBase(ManagedWindow.ManagedWindow):
# Callback functions from the dialog # Callback functions from the dialog
# #
#------------------------------------------------------------------------ #------------------------------------------------------------------------
def on_cancel(self,*obj): def on_cancel(self, *obj):
pass # cancel just closes pass # cancel just closes
def on_ok_clicked(self, obj): def on_ok_clicked(self, obj):
@ -266,7 +287,8 @@ class ToolManagedWindowBase(ManagedWindow.ManagedWindow):
iter = view.get_iter_at_location(*buffer_location) iter = view.get_iter_at_location(*buffer_location)
for (tag, person_handle) in self.tags: for (tag, person_handle) in self.tags:
if iter.has_tag(tag): if iter.has_tag(tag):
view.get_window(gtk.TEXT_WINDOW_TEXT).set_cursor(self.link_cursor) _window = view.get_window(gtk.TEXT_WINDOW_TEXT)
_window.set_cursor(self.link_cursor)
return False # handle event further, if necessary return False # handle event further, if necessary
view.get_window(gtk.TEXT_WINDOW_TEXT).set_cursor(self.standard_cursor) view.get_window(gtk.TEXT_WINDOW_TEXT).set_cursor(self.standard_cursor)
return False # handle event further, if necessary return False # handle event further, if necessary
@ -299,7 +321,7 @@ class ToolManagedWindowBase(ManagedWindow.ManagedWindow):
self.results_write(text) self.results_write(text)
start = buffer.get_iter_at_offset(offset) start = buffer.get_iter_at_offset(offset)
end = buffer.get_end_iter() end = buffer.get_end_iter()
self.tags.append((LinkTag(person_handle, buffer),person_handle)) self.tags.append((LinkTag(person_handle, buffer), person_handle))
buffer.apply_tag(self.tags[-1][0], start, end) buffer.apply_tag(self.tags[-1][0], start, end)
def results_write(self, text): def results_write(self, text):
@ -366,7 +388,7 @@ class ToolManagedWindowBase(ManagedWindow.ManagedWindow):
label.set_use_markup(True) label.set_use_markup(True)
self.window.vbox.pack_start(label, True, True, self.border_pad) self.window.vbox.pack_start(label, True, True, self.border_pad)
def add_frame_option(self,frame_name,label_text,widget,tooltip=None): def add_frame_option(self, frame_name, label_text, widget, tooltip=None):
"""Similar to add_option this method takes a frame_name, a """Similar to add_option this method takes a frame_name, a
text string and a Gtk Widget. When the interface is built, text string and a Gtk Widget. When the interface is built,
all widgets with the same frame_name are grouped into a all widgets with the same frame_name are grouped into a
@ -377,12 +399,12 @@ class ToolManagedWindowBase(ManagedWindow.ManagedWindow):
the add_user_options task.""" the add_user_options task."""
if self.frames.has_key(frame_name): if self.frames.has_key(frame_name):
self.frames[frame_name].append((label_text,widget)) self.frames[frame_name].append((label_text, widget))
else: else:
self.frames[frame_name] = [(label_text,widget)] self.frames[frame_name] = [(label_text, widget)]
self.frame_names.append(frame_name) self.frame_names.append(frame_name)
if tooltip: if tooltip:
self.add_tooltip(widget,tooltip) self.add_tooltip(widget, tooltip)
def set_current_frame(self, name): def set_current_frame(self, name):
if name == None: if name == None:
@ -396,7 +418,7 @@ class ToolManagedWindowBase(ManagedWindow.ManagedWindow):
self.notebook.set_current_page(page) self.notebook.set_current_page(page)
return return
def add_results_frame(self,frame_name="Results"): def add_results_frame(self, frame_name="Results"):
if frame_name not in self.frames: if frame_name not in self.frames:
window = gtk.ScrolledWindow() window = gtk.ScrolledWindow()
window.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) window.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
@ -423,18 +445,18 @@ class ToolManagedWindowBase(ManagedWindow.ManagedWindow):
the add_user_options task.""" the add_user_options task."""
for key in self.frame_names: for key in self.frame_names:
flist = self.frames[key] flist = self.frames[key]
table = gtk.Table(3,len(flist)) table = gtk.Table(3, len(flist))
table.set_col_spacings(12) table.set_col_spacings(12)
table.set_row_spacings(6) table.set_row_spacings(6)
table.set_border_width(6) table.set_border_width(6)
l = gtk.Label("<b>%s</b>" % key) l = gtk.Label("<b>%s</b>" % key)
l.set_use_markup(True) l.set_use_markup(True)
self.notebook.append_page(table,l) self.notebook.append_page(table, l)
row = 0 row = 0
for (text,widget) in flist: for (text, widget) in flist:
if text: if text:
text_widget = gtk.Label('%s:' % text) text_widget = gtk.Label('%s:' % text)
text_widget.set_alignment(0.0,0.5) text_widget.set_alignment(0.0, 0.5)
table.attach(text_widget, 1, 2, row, row+1, table.attach(text_widget, 1, 2, row, row+1,
gtk.SHRINK|gtk.FILL, gtk.SHRINK) gtk.SHRINK|gtk.FILL, gtk.SHRINK)
table.attach(widget, 2, 3, row, row+1, table.attach(widget, 2, 3, row, row+1,
@ -467,7 +489,7 @@ class ToolManagedWindowBatch(Tool.BatchTool, ToolManagedWindowBase):
# This constructor will ask a question, set self.fail: # This constructor will ask a question, set self.fail:
self.dbstate = dbstate self.dbstate = dbstate
self.uistate = uistate self.uistate = uistate
Tool.BatchTool.__init__(self,dbstate, options_class, name) Tool.BatchTool.__init__(self, dbstate, options_class, name)
if not self.fail: if not self.fail:
ToolManagedWindowBase.__init__(self, dbstate, uistate, ToolManagedWindowBase.__init__(self, dbstate, uistate,
options_class, name, callback) options_class, name, callback)
@ -476,6 +498,6 @@ class ToolManagedWindow(Tool.Tool, ToolManagedWindowBase):
def __init__(self, dbstate, uistate, options_class, name, callback=None): def __init__(self, dbstate, uistate, options_class, name, callback=None):
self.dbstate = dbstate self.dbstate = dbstate
self.uistate = uistate self.uistate = uistate
Tool.Tool.__init__(self,dbstate, options_class, name) Tool.Tool.__init__(self, dbstate, options_class, name)
ToolManagedWindowBase.__init__(self, dbstate, uistate, options_class, ToolManagedWindowBase.__init__(self, dbstate, uistate, options_class,
name, callback) name, callback)

View File

@ -41,9 +41,6 @@ from gtk import glade
# Standard Python modules # Standard Python modules
# #
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
import os
import sys
import re
from gettext import gettext as _ from gettext import gettext as _
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
@ -52,12 +49,9 @@ from gettext import gettext as _
# #
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
import const import const
import Config
import Errors
from ReportBase import report, standalone_categories from ReportBase import report, standalone_categories
import _Tool import _Tool
import _PluginMgr import _PluginMgr
import _PluginWindows
import ManagedWindow import ManagedWindow
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
@ -74,13 +68,12 @@ UNSUPPORTED = _("Unsupported")
# PluginDialog interface class # PluginDialog interface class
# #
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
class PluginDialog(ManagedWindow.ManagedWindow): class PluginDialog(ManagedWindow.ManagedWindow):
"""Displays the dialog box that allows the user to select the """Displays the dialog box that allows the user to select the
report that is desired.""" report that is desired."""
def __init__(self,state, uistate, track, item_list,categories,msg, def __init__(self, state, uistate, track, item_list, categories, msg,
label=None,button_label=None,tool_tip=None,content=REPORTS): label=None, button_label=None, tool_tip=None, content=REPORTS):
"""Display the dialog box, and build up the list of available """Display the dialog box, and build up the list of available
reports. This is used to build the selection tree on the left reports. This is used to build the selection tree on the left
hand side of the dailog box.""" hand side of the dailog box."""
@ -90,12 +83,12 @@ class PluginDialog(ManagedWindow.ManagedWindow):
self.msg = msg self.msg = msg
self.content = content self.content = content
ManagedWindow.ManagedWindow.__init__(self,uistate,[],self.__class__) ManagedWindow.ManagedWindow.__init__(self, uistate, [], self.__class__)
self.state = state self.state = state
self.uistate = uistate self.uistate = uistate
self.dialog = glade.XML(const.PLUGINS_GLADE,"report","gramps") self.dialog = glade.XML(const.PLUGINS_GLADE, "report", "gramps")
self.dialog.signal_autoconnect({ self.dialog.signal_autoconnect({
"on_report_apply_clicked" : self.on_apply_clicked, "on_report_apply_clicked" : self.on_apply_clicked,
"destroy_passed_object" : self.close, "destroy_passed_object" : self.close,
@ -110,7 +103,7 @@ class PluginDialog(ManagedWindow.ManagedWindow):
self.store = gtk.TreeStore(str) self.store = gtk.TreeStore(str)
self.selection = self.tree.get_selection() self.selection = self.tree.get_selection()
self.selection.connect('changed', self.on_node_selected) self.selection.connect('changed', self.on_node_selected)
col = gtk.TreeViewColumn('',gtk.CellRendererText(),text=0) col = gtk.TreeViewColumn('', gtk.CellRendererText(), text=0)
self.tree.append_column(col) self.tree.append_column(col)
self.tree.set_model(self.store) self.tree.set_model(self.store)
@ -130,34 +123,35 @@ class PluginDialog(ManagedWindow.ManagedWindow):
self.apply_button.set_use_underline(True) self.apply_button.set_use_underline(True)
if tool_tip: if tool_tip:
try: try:
tt = gtk.tooltips_data_get(self.apply_button) tttips = gtk.tooltips_data_get(self.apply_button)
if tt: if tttips:
tt[0].set_tip(self.apply_button,tool_tip) tttips[0].set_tip(self.apply_button, tool_tip)
except AttributeError: except AttributeError:
pass pass
self.item = None self.item = None
self.build_plugin_tree(item_list,categories) self.build_plugin_tree(item_list, categories)
uistate.connect('plugins-reloaded',self.rebuild) uistate.connect('plugins-reloaded', self.rebuild)
self.show() self.show()
def rebuild(self,tool_list,report_list): def rebuild(self, tool_list, report_list):
# This method needs to be overridden in the subclass # This method needs to be overridden in the subclass
assert False, "This method needs to be overridden in the subclass." assert False, "This method needs to be overridden in the subclass."
def build_menu_names(self, obj): def build_menu_names(self, obj):
return (self.msg,None) return (self.msg, None)
def on_apply_clicked(self, obj): def on_apply_clicked(self, obj):
"""Execute the selected report""" """Execute the selected report"""
try: try:
(item_class, options_class,title,category, (item_class, options_class, title, category,
name,require_active) = self.item name, require_active) = self.item
if self.content == REPORTS: if self.content == REPORTS:
report(self.state,self.uistate,self.state.active, report(self.state, self.uistate, self.state.active,
item_class, options_class,title, name,category,require_active) item_class, options_class, title, name,
category, require_active)
else: else:
_Tool.gui_tool(self.state,self.uistate, _Tool.gui_tool(self.state, self.uistate,
item_class, options_class,title, name,category, item_class, options_class,title, name,category,
self.state.db.request_rebuild) self.state.db.request_rebuild)
except TypeError: except TypeError:
@ -174,7 +168,7 @@ class PluginDialog(ManagedWindow.ManagedWindow):
return return
data = self.imap[path] data = self.imap[path]
(report_class, options_class,title,category, name, (report_class, options_class, title, category, name,
doc,status,author,email,unsupported,require_active) = data doc,status,author,email,unsupported,require_active) = data
self.description.set_text(doc) self.description.set_text(doc)
if unsupported: if unsupported:
@ -185,10 +179,10 @@ class PluginDialog(ManagedWindow.ManagedWindow):
self.title.set_use_markup(1) self.title.set_use_markup(1)
self.author_name.set_text(author) self.author_name.set_text(author)
self.author_email.set_text(email) self.author_email.set_text(email)
self.item = (report_class, options_class,title,category, self.item = (report_class, options_class, title, category,
name,require_active) name, require_active)
def build_plugin_tree(self,item_list,categories): def build_plugin_tree(self, item_list, categories):
"""Populates a GtkTree with each menu item assocated with a entry """Populates a GtkTree with each menu item assocated with a entry
in the lists. The list must consist of a tuples with the following in the lists. The list must consist of a tuples with the following
format: format:
@ -225,25 +219,25 @@ class PluginDialog(ManagedWindow.ManagedWindow):
if item_hash.has_key(UNSUPPORTED): if item_hash.has_key(UNSUPPORTED):
key = UNSUPPORTED key = UNSUPPORTED
data = item_hash[key] data = item_hash[key]
node = self.store.insert_after(None,prev) node = self.store.insert_after(None, prev)
self.store.set(node,0,key) self.store.set(node, 0, key)
next = None next = None
data.sort(lambda x,y: cmp(x[2],y[2])) data.sort(lambda x, y: cmp(x[2], y[2]))
for item in data: for item in data:
next = self.store.insert_after(node, next) next = self.store.insert_after(node, next)
ilist.append((next,item)) ilist.append((next, item))
self.store.set(next,0,item[2]) self.store.set(next, 0, item[2])
for key in key_list: for key in key_list:
data = item_hash[key] data = item_hash[key]
node = self.store.insert_after(None,prev) node = self.store.insert_after(None, prev)
self.store.set(node,0,key) self.store.set(node, 0, key)
next = None next = None
data.sort(lambda x,y: cmp(x[2],y[2])) data.sort(lambda x, y: cmp(x[2], y[2]))
for item in data: for item in data:
next = self.store.insert_after(node, next) next = self.store.insert_after(node, next)
ilist.append((next,item)) ilist.append((next, item))
self.store.set(next,0,item[2]) self.store.set(next, 0, item[2])
for next,tab in ilist: for next, tab in ilist:
path = self.store.get_path(next) path = self.store.get_path(next)
self.imap[path] = tab self.imap[path] = tab
@ -256,7 +250,7 @@ class ReportPlugins(PluginDialog):
"""Displays the dialog box that allows the user to select the """Displays the dialog box that allows the user to select the
report that is desired.""" report that is desired."""
def __init__(self,dbstate,uistate,track): def __init__(self, dbstate, uistate, track):
"""Display the dialog box, and build up the list of available """Display the dialog box, and build up the list of available
reports. This is used to build the selection tree on the left reports. This is used to build the selection tree on the left
hand side of the dailog box.""" hand side of the dailog box."""
@ -273,8 +267,8 @@ class ReportPlugins(PluginDialog):
_("_Generate"), _("Generate selected report"), _("_Generate"), _("Generate selected report"),
REPORTS) REPORTS)
def rebuild(self,tool_list,report_list): def rebuild(self, tool_list, report_list):
self.build_plugin_tree(report_list,standalone_categories) self.build_plugin_tree(report_list, standalone_categories)
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
# #
@ -288,7 +282,7 @@ class ToolPlugins(PluginDialog):
__signals__ = { __signals__ = {
'plugins-reloaded' : (list,list), 'plugins-reloaded' : (list,list),
} }
def __init__(self,dbstate,uistate,track): def __init__(self, dbstate, uistate, track):
"""Display the dialog box, and build up the list of available """Display the dialog box, and build up the list of available
reports. This is used to build the selection tree on the left reports. This is used to build the selection tree on the left
hand side of the dailog box.""" hand side of the dailog box."""
@ -306,117 +300,5 @@ class ToolPlugins(PluginDialog):
_("Run selected tool"), _("Run selected tool"),
TOOLS) TOOLS)
def rebuild(self,tool_list,report_list): def rebuild(self, tool_list, report_list):
self.build_plugin_tree(tool_list,_Tool.tool_categories) self.build_plugin_tree(tool_list, _Tool.tool_categories)
#-------------------------------------------------------------------------
#
# Reload plugins
#
#-------------------------------------------------------------------------
class Reload(_Tool.Tool):
def __init__(self, dbstate, uistate, options_class, name, callback=None):
"""
Treated as a callback, causes all plugins to get reloaded.
This is useful when writing and debugging a plugin.
"""
_Tool.Tool.__init__(self,dbstate, options_class, name)
pymod = re.compile(r"^(.*)\.py$")
oldfailmsg = _PluginMgr.failmsg_list[:]
_PluginMgr.failmsg_list = []
# attempt to reload all plugins that have succeeded in the past
for plugin in _PluginMgr.success_list:
filename = plugin[0]
filename = filename.replace('pyc','py')
filename = filename.replace('pyo','py')
try:
reload(plugin[1])
except:
_PluginMgr.failmsg_list.append((filename,sys.exc_info()))
# Remove previously good plugins that are now bad
# from the registered lists
_PluginMgr.purge_failed()
# attempt to load the plugins that have failed in the past
for (filename,message) in oldfailmsg:
name = os.path.split(filename)
match = pymod.match(name[1])
if not match:
continue
_PluginMgr.attempt_list.append(filename)
plugin = match.groups()[0]
try:
# For some strange reason second importing of a failed plugin
# results in success. Then reload reveals the actual error.
# Looks like a bug in Python.
a = __import__(plugin)
reload(a)
_PluginMgr.success_list.append((filename,a))
except:
_PluginMgr.failmsg_list.append((filename,sys.exc_info()))
# attempt to load any new files found
for directory in _PluginMgr.loaddir_list:
for filename in os.listdir(directory):
name = os.path.split(filename)
match = pymod.match(name[1])
if not match:
continue
if filename in _PluginMgr.attempt_list:
continue
_PluginMgr.attempt_list.append(filename)
plugin = match.groups()[0]
try:
a = __import__(plugin)
if a not in [plugin[1]
for plugin in _PluginMgr.success_list]:
_PluginMgr.success_list.append((filename,a))
except:
_PluginMgr.failmsg_list.append((filename,sys.exc_info()))
if Config.get(Config.POP_PLUGIN_STATUS) \
and len(_PluginMgr.failmsg_list):
try:
_PluginWindows.PluginStatus(dbstate,uistate)
except Errors.WindowActiveError:
old_win = uistate.gwm.get_item_from_id(
_PluginWindows.PluginStatus)
old_win.close()
_PluginWindows.PluginStatus(dbstate,uistate)
# Emit signal to re-generate tool and report menus
uistate.emit('plugins-reloaded',
(_PluginMgr.tool_list,_PluginMgr.report_list))
class ReloadOptions(_Tool.ToolOptions):
"""
Defines options and provides handling interface.
"""
def __init__(self, name,person_id=None):
_Tool.ToolOptions.__init__(self, name,person_id)
#-------------------------------------------------------------------------
#
# Register the plugin reloading tool
#
#-------------------------------------------------------------------------
if __debug__:
_PluginMgr.register_tool(
name = 'reload',
category = _Tool.TOOL_DEBUG,
tool_class = Reload,
options_class = ReloadOptions,
modes = _Tool.MODE_GUI,
translated_name = _("Reload Plugins"),
status=(_("Stable")),
author_name = "Donald N. Allingham",
author_email = "don@gramps-project.org",
description=_("Attempt to reload plugins. "
"Note: This tool itself is not reloaded!"),
)

View File

@ -402,7 +402,7 @@ class ViewManager:
('About', gtk.STOCK_ABOUT, _('_About'), None, None, ('About', gtk.STOCK_ABOUT, _('_About'), None, None,
display_about_box), display_about_box),
('PluginStatus', None, _('_Plugin Status'), None, None, ('PluginStatus', None, _('_Plugin Status'), None, None,
self.plugin_status), self.__plugin_status),
('FAQ', None, _('_FAQ'), None, None, faq_activate), ('FAQ', None, _('_FAQ'), None, None, faq_activate),
('KeyBindings', None, _('_Key Bindings'), None, None, key_bindings), ('KeyBindings', None, _('_Key Bindings'), None, None, key_bindings),
('UserManual', gtk.STOCK_HELP, _('_User Manual'), 'F1', None, ('UserManual', gtk.STOCK_HELP, _('_User Manual'), 'F1', None,
@ -607,14 +607,8 @@ class ViewManager:
error |= load_plugins(const.USER_PLUGINS) error |= load_plugins(const.USER_PLUGINS)
# get to ssee if we need to open the plugin status window # get to ssee if we need to open the plugin status window
if Config.get(Config.POP_PLUGIN_STATUS) and error: if error and Config.get(Config.POP_PLUGIN_STATUS):
try: self.__plugin_status()
PluginWindows.PluginStatus(self.state, self.uistate, [])
except Errors.WindowActiveError:
old_win = self.uistate.gwm.get_item_from_id(
PluginWindows.PluginStatus)
old_win.close()
PluginWindows.PluginStatus(self.state, self.uistate, [])
self.uistate.push_message(self.state, _('Ready')) self.uistate.push_message(self.state, _('Ready'))
@ -734,17 +728,17 @@ class ViewManager:
import TipOfDay import TipOfDay
TipOfDay.TipOfDay(self.uistate) TipOfDay.TipOfDay(self.uistate)
def plugin_status(self, obj): def __plugin_status(self, obj=None):
""" """
Display plugin status dialog Display plugin status dialog
""" """
try: try:
PluginWindows.PluginStatus(self.state, self.uistate, []) PluginWindows.PluginStatus(self.uistate, [])
except Errors.WindowActiveError: except Errors.WindowActiveError:
old_win = self.uistate.gwm.get_item_from_id( old_win = self.uistate.gwm.get_item_from_id(
PluginWindows.PluginStatus) PluginWindows.PluginStatus)
old_win.close() old_win.close()
PluginWindows.PluginStatus(self.state, self.uistate, []) PluginWindows.PluginStatus(self.uistate, [])
def sidebar_toggle(self, obj): def sidebar_toggle(self, obj):
""" """