diff --git a/src/PluginUtils/_PluginWindows.py b/src/PluginUtils/_PluginWindows.py index 49bde0584..3c5349e7d 100644 --- a/src/PluginUtils/_PluginWindows.py +++ b/src/PluginUtils/_PluginWindows.py @@ -56,6 +56,12 @@ import Utils import const import config +def display_message(message): + """ + A default callback for displaying messages. + """ + print message + def version_str_to_tup(sversion, positions): """ Given a string version and positions count, returns a tuple of @@ -349,7 +355,7 @@ class PluginStatus(ManagedWindow.ManagedWindow): hbutbox.set_layout(gtk.BUTTONBOX_SPREAD) self.__add_btn = gtk.Button(_("Install Addon")) hbutbox.add(self.__add_btn) - self.__add_btn.connect('clicked', self.__get_addon) + self.__add_btn.connect('clicked', self.__get_addon_top) self.__add_all_btn = gtk.Button(_("Install All Addons")) hbutbox.add(self.__add_all_btn) self.__add_all_btn.connect('clicked', self.__get_all_addons) @@ -381,12 +387,22 @@ class PluginStatus(ManagedWindow.ManagedWindow): Reloads the addons from the wiki into the list. """ import urllib + from gui.utils import ProgressMeter URL = "%s%s" % (const.URL_WIKISTRING, const.WIKI_EXTRAPLUGINS_RAWDATA) - fp = urllib.urlopen(URL) + try: + fp = urllib.urlopen(URL) + except: + print "Error: cannot open %s" % URL + return + pm = ProgressMeter(_("Refreshing Addon List")) + pm.set_pass(header=_("Reading gramps-project.org...")) state = "read" rows = [] row = [] - for line in fp.readlines(): + lines = fp.readlines() + pm.set_pass(total=len(lines), header=_("Reading gramps-project.org...")) + for line in lines: + pm.step() if line.startswith("|-") or line.startswith("|}"): if row != []: rows.append(row) @@ -402,7 +418,9 @@ class PluginStatus(ManagedWindow.ManagedWindow): self.addon_model.clear() # clear the config list: config.get('plugin.addonplugins')[:] = [] + pm.set_pass(total=len(rows), header=_("Checking addon...")) for row in rows: + pm.step() try: # from wiki: help_name, ptype, image, desc, use, rating, contact, download = row @@ -446,6 +464,7 @@ class PluginStatus(ManagedWindow.ManagedWindow): rating, contact, download, url]) config.get('plugin.addonplugins').append([help_name, name, ptype, image, desc, use, rating, contact, download, url]) + pm.close() config.save() def __get_all_addons(self, obj): @@ -453,29 +472,40 @@ class PluginStatus(ManagedWindow.ManagedWindow): Get all addons from the wiki and install them. """ import urllib + from gui.utils import ProgressMeter + pm = ProgressMeter(_("Install all Addons"), _("Installing..."), message_area=True) + pm.set_pass(total=len(self.addon_model)) for row in self.addon_model: + pm.step() (help_name, name, ptype, image, desc, use, rating, contact, download, url) = row - messages = self.__load_addon_file(url) - # FIXME: display messages - for message in messages: - print message + self.__load_addon_file(url, callback=pm.append_message) + pm.message_area_ok.set_sensitive(True) self.__rebuild_load_list() self.__rebuild_reg_list() - def __get_addon(self, obj): + def __get_addon_top(self, obj): + """ + Toplevel method to get an addon. + """ + from gui.utils import ProgressMeter + pm = ProgressMeter(_("Installing Addon"), message_area=True) + pm.set_pass(total=2, header=_("Reading gramps-project.org...")) + pm.step() + self.__get_addon(obj, callback=pm.append_message) + pm.step() + pm.message_area_ok.set_sensitive(True) + + def __get_addon(self, obj, callback=display_message): """ Get an addon from the wiki or file system and install it. """ path = self.install_addon_path.get_text() - messages = self.__load_addon_file(path) - # FIXME: display messages - for message in messages: - print message + self.__load_addon_file(path, callback) self.__rebuild_load_list() self.__rebuild_reg_list() - def __load_addon_file(self, path): + def __load_addon_file(self, path, callback=display_message): """ Load an addon from a particular path (from URL or file system). """ @@ -485,9 +515,17 @@ class PluginStatus(ManagedWindow.ManagedWindow): if (path.startswith("http://") or path.startswith("https://") or path.startswith("ftp://")): - fp = urllib.urlopen(path) + try: + fp = urllib.urlopen(path) + except: + callback(_("Unable to open '%s'") % path) + return else: - fp = open(path) + try: + fp = open(path) + except: + callback(_("Unable to open '%s'") % path) + return buffer = cStringIO.StringIO(fp.read()) fp.close() # file_obj is either Zipfile or TarFile @@ -499,8 +537,8 @@ class PluginStatus(ManagedWindow.ManagedWindow): return [("Error: unknown file type: '%s'") % path] # First, see what versions we have/are getting: good_gpr = set() - messages = [] for gpr_file in [name for name in file_obj.getnames() if name.endswith(".gpr.py")]: + callback((_("Examining '%s'...") % gpr_file) + "\n") contents = file_obj.extractfile(gpr_file).read() # Put a fake register and _ function in environment: env = make_environment(register=register, @@ -512,7 +550,8 @@ class PluginStatus(ManagedWindow.ManagedWindow): try: exec(contents, env) except: - messages += [_("Error in '%s' file: cannot load.") % gpr_file] + msg = _("Error in '%s' file: cannot load.") % gpr_file + callback(" " + msg + "\n") continue # There can be multiple addons per gpr file: for results in globals()["register_results"]: @@ -523,24 +562,23 @@ class PluginStatus(ManagedWindow.ManagedWindow): if vtup == const.VERSION_TUPLE[0:2]: # If this version is not installed, or > installed, install it good_gpr.add(gpr_file) - messages += [_("'%s' is for this version of Gramps.") % gpr_file] + callback(" " + (_("'%s' is for this version of Gramps.") % gpr_file) + "\n") else: # another register function doesn't have gramps_target_version if gpr_file in good_gpr: s.remove(gpr_file) - messages += [_("Error: missing gramps_target_version = '3.2' in '%s'...") % gpr_file] + callback(" " + (_("Error: missing gramps_target_version = '3.2' in '%s'...") % gpr_file) + "\n") if len(good_gpr) > 0: # Now, install the ok ones file_obj.extractall(const.USER_PLUGINS) - messages += [_("Installing '%s'...") % path] + callback((_("Installing '%s'...") % path) + "\n") gpr_files = set([os.path.split(os.path.join(const.USER_PLUGINS, name))[0] for name in good_gpr]) for gpr_file in gpr_files: - messages += [_("Registered '%s'") % gpr_file] + callback(" " + (_("Registered '%s'") % gpr_file) + "\n") self.__pmgr.reg_plugins(gpr_file) file_obj.close() - return messages def __select_file(self, obj): """ diff --git a/src/gui/utils.py b/src/gui/utils.py index c932e7cb9..7fa5e471f 100644 --- a/src/gui/utils.py +++ b/src/gui/utils.py @@ -93,7 +93,7 @@ class ProgressMeter(object): MODE_ACTIVITY = 1 def __init__(self, title, header='', can_cancel=False, - cancel_callback=None): + cancel_callback=None, message_area=False): """ Specify the title and the current pass header. """ @@ -137,11 +137,48 @@ class ProgressMeter(object): self.__cancel_button = gtk.Button(stock=gtk.STOCK_CANCEL) self.__cancel_button.connect('clicked', self.__cancel_callback) self.__dialog.vbox.add(self.__cancel_button) - + + self.message_area = None + if message_area: + area = gtk.ScrolledWindow() + text = gtk.TextView() + text.set_border_width(6) + text.set_editable(False) + self.message_area = text + area.add_with_viewport(text) + area.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) + self.__dialog.vbox.add(area) + self.message_area_ok = gtk.Button(stock=gtk.STOCK_OK) + self.message_area_ok.connect("clicked", self.close) + self.message_area_ok.set_sensitive(False) + self.__dialog.vbox.pack_start(self.message_area_ok, expand=False, fill=False) + self.__dialog.set_size_request(500, 350) + self.__dialog.show_all() if header == '': self.__lbl.hide() + def append_message(self, text): + """ + Method to add text to message area. + """ + if self.message_area: + buffer = self.message_area.get_buffer() + end = buffer.get_end_iter() + buffer.insert(end, text) + else: + print "Progress:", text + + def set_message(self, text): + """ + Sets the text of the message area. + """ + if self.message_area: + buffer = self.message_area.get_buffer() + buffer.set_text(text) + else: + print "Progress:", text + def handle_cancel(self, *args, **kwargs): """ Default cancel handler (if enabled). @@ -227,7 +264,7 @@ class ProgressMeter(object): self.__dialog) return True - def close(self): + def close(self, widget=None): """ Close the progress meter """