4735: Check for updates in a separate thread

svn: r22924
This commit is contained in:
Nick Hall 2013-08-28 23:32:30 +00:00
parent 314cf24850
commit b0a4f75106
6 changed files with 360 additions and 261 deletions

View File

@ -358,6 +358,7 @@ class DisplayState(gen.utils.Callback):
'filters-changed' : (str, ), 'filters-changed' : (str, ),
'filter-name-changed' : (str, unicode, unicode), 'filter-name-changed' : (str, unicode, unicode),
'nameformat-changed' : None, 'nameformat-changed' : None,
'update-available' : (list, ),
} }
#nav_type to message #nav_type to message

View File

@ -32,6 +32,15 @@ General utility functions useful for the generic plugin system
import locale import locale
import sys import sys
import os import os
import datetime
#-------------------------------------------------------------------------
#
# set up logging
#
#-------------------------------------------------------------------------
import logging
LOG = logging.getLogger(".gen.plug")
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
# #
@ -41,6 +50,9 @@ import os
from gen.plug._pluginreg import make_environment from gen.plug._pluginreg import make_environment
import const import const
import Utils import Utils
from gen.plug import BasePluginManager
from gen.utils.configmanager import safe_eval
import config
from gen.ggettext import gettext as _ from gen.ggettext import gettext as _
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
@ -188,6 +200,96 @@ class Zipfile(object):
""" """
return os.path.split(name)[1] return os.path.split(name)[1]
def available_updates():
whattypes = config.get('behavior.check-for-update-types')
if sys.version_info[0] < 3:
from urllib2 import urlopen
else:
from urllib.request import urlopen
LOG.debug("Checking for updated addons...")
langs = []
lang = locale.getlocale()[0] # not None
if lang:
langs.append(lang)
if "_" in lang:
lang, variation = lang.split("_", 1)
langs.append(lang)
langs.append("en")
# now we have a list of languages to try:
fp = None
for lang in langs:
URL = ("%s/listings/addons-%s.txt" %
(config.get("behavior.addons-url"), lang))
LOG.debug(" trying: %s" % URL)
try:
fp = urlopen(URL, timeout=10) # abort after 10 seconds
except:
try:
URL = ("%s/listings/addons-%s.txt" %
(config.get("behavior.addons-url"), lang[:2]))
fp = urlopen(URL, timeout=10)
except Exception as err: # some error
LOG.warn("Failed to open %s: %s" % (lang, err))
fp = None
if fp and fp.getcode() == 200: # ok
break
pmgr = BasePluginManager.get_instance()
addon_update_list = []
if fp and fp.getcode() == 200:
lines = list(fp.readlines())
count = 0
for line in lines:
line = line.decode('utf-8')
try:
plugin_dict = safe_eval(line)
if type(plugin_dict) != type({}):
raise TypeError("Line with addon metadata is not "
"a dictionary")
except:
LOG.warning("Skipped a line in the addon listing: " +
str(line))
continue
id = plugin_dict["i"]
plugin = pmgr.get_plugin(id)
if plugin:
LOG.debug("Comparing %s > %s" %
(version_str_to_tup(plugin_dict["v"], 3),
version_str_to_tup(plugin.version, 3)))
if (version_str_to_tup(plugin_dict["v"], 3) >
version_str_to_tup(plugin.version, 3)):
LOG.debug(" Downloading '%s'..." % plugin_dict["z"])
if "update" in whattypes:
if (not config.get('behavior.do-not-show-previously-seen-updates') or
plugin_dict["i"] not in config.get('behavior.previously-seen-updates')):
addon_update_list.append((_("Updated"),
"%s/download/%s" %
(config.get("behavior.addons-url"),
plugin_dict["z"]),
plugin_dict))
else:
LOG.debug(" '%s' is ok" % plugin_dict["n"])
else:
LOG.debug(" '%s' is not installed" % plugin_dict["n"])
if "new" in whattypes:
if (not config.get('behavior.do-not-show-previously-seen-updates') or
plugin_dict["i"] not in config.get('behavior.previously-seen-updates')):
addon_update_list.append((_("New"),
"%s/download/%s" %
(config.get("behavior.addons-url"),
plugin_dict["z"]),
plugin_dict))
config.set("behavior.last-check-for-updates",
datetime.date.today().strftime("%Y/%m/%d"))
count += 1
if fp:
fp.close()
else:
LOG.debug("Checking Addons Failed")
LOG.debug("Done checking!")
return addon_update_list
def load_addon_file(path, callback=None): def load_addon_file(path, callback=None):
""" """
Load an addon from a particular path (from URL or file system). Load an addon from a particular path (from URL or file system).

View File

@ -58,6 +58,9 @@ import ManagedWindow
from gui.widgets import MarkupLabel, BasicLabel from gui.widgets import MarkupLabel, BasicLabel
from QuestionDialog import ErrorDialog, QuestionDialog2, OkDialog from QuestionDialog import ErrorDialog, QuestionDialog2, OkDialog
from glade import Glade from glade import Glade
from gen.plug.utils import available_updates
from gui.plug import PluginWindows
from Errors import WindowActiveError
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
# #
@ -1142,12 +1145,39 @@ class GrampsPreferences(ConfigureDialog):
table.attach(checkbutton, 1, 2, 9, 10, yoptions=0) table.attach(checkbutton, 1, 2, 9, 10, yoptions=0)
button = gtk.Button(_("Check now")) button = gtk.Button(_("Check now"))
button.connect("clicked", lambda obj: \ button.connect("clicked", self.check_for_updates)
self.uistate.viewmanager.check_for_updates(force=True))
table.attach(button, 3, 4, 9, 10, yoptions=0) table.attach(button, 3, 4, 9, 10, yoptions=0)
return _('General'), table return _('General'), table
def check_for_updates(self, button):
try:
addon_update_list = available_updates()
except:
OkDialog(_("Checking Addons Failed"),
_("The addon repository appears to be unavailable. "
"Please try again later."),
self.window)
return
if len(addon_update_list) > 0:
try:
PluginWindows.UpdateAddons(self.uistate, [], addon_update_list)
except WindowActiveError:
pass
else:
check_types = config.get('behavior.check-for-update-types')
OkDialog(_("There are no available addons of this type"),
_("Checked for '%s'") %
_("' and '").join([_(t) for t in check_types]),
self.window)
# List of translated strings used here
# Dead code for l10n
_('new'), _('update')
self.uistate.viewmanager.do_reg_plugins(self.dbstate, self.uistate)
def add_famtree_panel(self, configdialog): def add_famtree_panel(self, configdialog):
table = gtk.Table(2, 2) table = gtk.Table(2, 2)
table.set_border_width(12) table.set_border_width(12)

View File

@ -32,6 +32,14 @@ import traceback
import os import os
import sys import sys
#-------------------------------------------------------------------------
#
# set up logging
#
#-------------------------------------------------------------------------
import logging
LOG = logging.getLogger(".gui.plug")
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
# #
# GTK modules # GTK modules
@ -50,14 +58,19 @@ import ManagedWindow
import Errors import Errors
from gen.plug import PluginRegister, PTYPE_STR, load_addon_file from gen.plug import PluginRegister, PTYPE_STR, load_addon_file
from gen.ggettext import gettext as _ from gen.ggettext import gettext as _
from gen.ggettext import ngettext
from gui.utils import open_file_with_default_application from gui.utils import open_file_with_default_application
from gui.pluginmanager import GuiPluginManager from gui.pluginmanager import GuiPluginManager
from gui.plug import tool, add_gui_options from gui.plug import tool, add_gui_options
from QuestionDialog import InfoDialog from QuestionDialog import InfoDialog, OkDialog
from gui.editors import EditPerson from gui.editors import EditPerson
from glade import Glade
from ListModel import ListModel, NOSORT, TOGGLE
import Utils import Utils
import const import const
import config import config
from gui.widgets.progressdialog import (LongOpStatus, ProgressMonitor,
GtkProgressDialog)
def display_message(message): def display_message(message):
""" """
@ -1041,3 +1054,176 @@ class ToolManagedWindow(tool.Tool, ToolManagedWindowBase):
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)
#-------------------------------------------------------------------------
#
# UpdateAddons
#
#-------------------------------------------------------------------------
class UpdateAddons(ManagedWindow.ManagedWindow):
def __init__(self, uistate, track, addon_update_list):
self.title = _('Available Gramps Updates for Addons')
ManagedWindow.ManagedWindow.__init__(self, uistate, track,
self.__class__)
glade = Glade("updateaddons.glade")
self.update_dialog = glade.toplevel
self.set_window(self.update_dialog, glade.get_object('title'),
self.title)
self.window.set_size_request(750, 400)
apply_button = glade.get_object('apply')
cancel_button = glade.get_object('cancel')
select_all = glade.get_object('select_all')
select_all.connect("clicked", self.select_all_clicked)
select_none = glade.get_object('select_none')
select_none.connect("clicked", self.select_none_clicked)
apply_button.connect("clicked", self.install_addons)
cancel_button.connect("clicked", self.close)
self.list = ListModel(glade.get_object("list"), [
# name, click?, width, toggle
{"name": _('Select'),
"width": 60,
"type": TOGGLE,
"visible_col": 6,
"editable": True}, # 0 selected?
(_('Type'), 1, 180), # 1 new gramplet
(_('Name'), 2, 200), # 2 name (version)
(_('Description'), 3, 200), # 3 description
('', NOSORT, 0), # 4 url
('', NOSORT, 0), # 5 id
{"name": '', "type": TOGGLE}, # 6 visible? bool
], list_mode="tree")
pos = None
addon_update_list.sort(key=lambda x: "%s %s" % (x[0], x[2]["t"]))
last_category = None
for (status,plugin_url,plugin_dict) in addon_update_list:
count = get_count(addon_update_list, plugin_dict["t"])
category = _("%(adjective)s: %(addon)s") % {
"adjective": status,
"addon": _(plugin_dict["t"])}
if last_category != category:
last_category = category
node = self.list.add([False, # initially selected?
category,
"",
"",
"",
"",
False]) # checkbox visible?
iter = self.list.add([False, # initially selected?
"%s %s" % (status, _(plugin_dict["t"])),
"%s (%s)" % (plugin_dict["n"],
plugin_dict["v"]),
plugin_dict["d"],
plugin_url,
plugin_dict["i"],
True], node=node)
if pos is None:
pos = iter
if pos:
self.list.selection.select_iter(pos)
self.update_dialog.run()
def build_menu_names(self, obj):
return (self.title, "")
def select_all_clicked(self, widget):
"""
Select all of the addons for download.
"""
self.list.model.foreach(update_rows, True)
self.list.tree.expand_all()
def select_none_clicked(self, widget):
"""
Select none of the addons for download.
"""
self.list.model.foreach(update_rows, False)
self.list.tree.expand_all()
def install_addons(self, obj):
"""
Process all of the selected addons.
"""
self.update_dialog.hide()
model = self.list.model
iter = model.get_iter_first()
length = 0
while iter:
iter = model.iter_next(iter)
if iter:
length += model.iter_n_children(iter)
longop = LongOpStatus(
_("Downloading and installing selected addons..."),
length, 1, # total, increment-by
can_cancel=True)
pm = ProgressMonitor(GtkProgressDialog,
("Title", self.window, gtk.DIALOG_MODAL))
pm.add_op(longop)
count = 0
if not config.get('behavior.do-not-show-previously-seen-updates'):
# reset list
config.get('behavior.previously-seen-updates')[:] = []
iter = model.get_iter_first()
while iter:
for rowcnt in range(model.iter_n_children(iter)):
child = model.iter_nth_child(iter, rowcnt)
row = [model.get_value(child, n) for n in range(6)]
if longop.should_cancel():
break
elif row[0]: # toggle on
load_addon_file(row[4], callback=LOG.debug)
count += 1
else: # add to list of previously seen, but not installed
if row[5] not in config.get('behavior.previously-seen-updates'):
config.get('behavior.previously-seen-updates').append(row[5])
longop.heartbeat()
pm._get_dlg()._process_events()
iter = model.iter_next(iter)
if not longop.was_cancelled():
longop.end()
if count:
OkDialog(_("Done downloading and installing addons"),
"%s %s" % (ngettext("%d addon was installed.",
"%d addons were installed.",
count) % count,
_("You need to restart Gramps to see new views.")),
self.window)
else:
OkDialog(_("Done downloading and installing addons"),
_("No addons were installed."),
self.window)
self.close()
#-------------------------------------------------------------------------
#
# Local Functions
#
#-------------------------------------------------------------------------
def update_rows(model, path, iter, user_data):
"""
Update the rows of a model.
"""
#path: (8,) iter: <GtkTreeIter at 0xbfa89fa0>
#path: (8, 0) iter: <GtkTreeIter at 0xbfa89f60>
if len(path) == 2:
row = model[path]
row[0] = user_data
model.row_changed(path, iter)
def get_count(addon_update_list, category):
"""
Get the count of matching category items.
"""
count = 0
for (status,plugin_url,plugin_dict) in addon_update_list:
if plugin_dict["t"] == category and plugin_url:
count += 1
return count

View File

@ -32,6 +32,7 @@ Utility functions that depend on GUI components or for GUI components
import os import os
import sys import sys
import subprocess import subprocess
import threading
from gen.ggettext import gettext as _ from gen.ggettext import gettext as _
import constfunc import constfunc
# gtk is not included here, because this file is currently imported # gtk is not included here, because this file is currently imported
@ -43,6 +44,7 @@ import constfunc
# GNOME/GTK # GNOME/GTK
# #
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
import gobject
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
# #
@ -52,6 +54,7 @@ import constfunc
import gen.lib import gen.lib
import Errors import Errors
import constfunc import constfunc
from gen.plug.utils import available_updates
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
# #
@ -391,3 +394,22 @@ def is_right_click(event):
if event.button == 3: if event.button == 3:
return True return True
#-------------------------------------------------------------------------
#
# AvailableUpdates
#
#-------------------------------------------------------------------------
class AvailableUpdates(threading.Thread):
def __init__(self, uistate):
threading.Thread.__init__(self)
self.uistate = uistate
self.addon_update_list = []
def emit_update_available(self):
self.uistate.emit('update-available', (self.addon_update_list, ))
def run(self):
self.addon_update_list = available_updates()
if len(self.addon_update_list) > 0:
gobject.idle_add(self.emit_update_available)

View File

@ -40,7 +40,6 @@ import os
import time import time
import datetime import datetime
from gen.ggettext import sgettext as _ from gen.ggettext import sgettext as _
from gen.ggettext import ngettext
from cStringIO import StringIO from cStringIO import StringIO
from collections import defaultdict from collections import defaultdict
import sys import sys
@ -73,7 +72,7 @@ from gen.plug import REPORT
from gen.plug.report._constants import standalone_categories from gen.plug.report._constants import standalone_categories
from gui.plug import (PluginWindows, ReportPluginDialog, ToolPluginDialog) from gui.plug import (PluginWindows, ReportPluginDialog, ToolPluginDialog)
from gui.plug.report import report from gui.plug.report import report
from gen.plug.utils import version_str_to_tup, load_addon_file from gui.utils import AvailableUpdates
from gui.pluginmanager import GuiPluginManager from gui.pluginmanager import GuiPluginManager
import Relationship import Relationship
import DisplayState import DisplayState
@ -95,7 +94,6 @@ from gen.db.exceptions import DbException
from gui.aboutdialog import GrampsAboutDialog from gui.aboutdialog import GrampsAboutDialog
from gui.navigator import Navigator from gui.navigator import Navigator
from gui.views.tags import Tags from gui.views.tags import Tags
from gen.utils.configmanager import safe_eval
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
# #
@ -228,32 +226,6 @@ WIKI_HELP_PAGE_FAQ = '%s_-_FAQ' % const.URL_MANUAL_PAGE
WIKI_HELP_PAGE_KEY = '%s_-_Keybindings' % const.URL_MANUAL_PAGE WIKI_HELP_PAGE_KEY = '%s_-_Keybindings' % const.URL_MANUAL_PAGE
WIKI_HELP_PAGE_MAN = '%s' % const.URL_MANUAL_PAGE WIKI_HELP_PAGE_MAN = '%s' % const.URL_MANUAL_PAGE
#-------------------------------------------------------------------------
#
# Local Functions
#
#-------------------------------------------------------------------------
def update_rows(model, path, iter, user_data):
"""
Update the rows of a model.
"""
#path: (8,) iter: <GtkTreeIter at 0xbfa89fa0>
#path: (8, 0) iter: <GtkTreeIter at 0xbfa89f60>
if len(path) == 2:
row = model[path]
row[0] = user_data
model.row_changed(path, iter)
def get_count(addon_update_list, category):
"""
Get the count of matching category items.
"""
count = 0
for (status,plugin_url,plugin_dict) in addon_update_list:
if plugin_dict["t"] == category and plugin_url:
count += 1
return count
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
# #
# ViewManager # ViewManager
@ -333,19 +305,18 @@ class ViewManager(CLIManager):
self.rel_class = Relationship.get_relationship_calculator() self.rel_class = Relationship.get_relationship_calculator()
self.uistate.set_relationship_class() self.uistate.set_relationship_class()
# Need to call after plugins have been registered # Need to call after plugins have been registered
self.uistate.connect('update-available', self.process_updates)
self.check_for_updates() self.check_for_updates()
def check_for_updates(self, force=False): def check_for_updates(self):
""" """
Check for add-on updates.
""" """
howoften = config.get("behavior.check-for-updates") howoften = config.get("behavior.check-for-updates")
whattypes = config.get('behavior.check-for-update-types')
update = False update = False
if force: if howoften != 0: # update never if zero
update = True y,m,d = list(map(int,
elif howoften != 0: # update never if zero config.get("behavior.last-check-for-updates").split("/")))
y,m,d = map(int,
config.get("behavior.last-check-for-updates").split("/"))
days = (datetime.date.today() - datetime.date(y, m, d)).days days = (datetime.date.today() - datetime.date(y, m, d)).days
if howoften == 1 and days >= 30: # once a month if howoften == 1 and days >= 30: # once a month
update = True update = True
@ -355,233 +326,20 @@ class ViewManager(CLIManager):
update = True update = True
elif howoften == 4: # always elif howoften == 4: # always
update = True update = True
if update: if update:
import urllib2, locale AvailableUpdates(self.uistate).start()
LOG.debug("Checking for updated addons...")
langs = []
lang = locale.getlocale()[0] # not None
if lang:
langs.append(lang)
if "_" in lang:
lang, variation = lang.split("_", 1)
langs.append(lang)
langs.append("en")
# now we have a list of languages to try:
fp = None
for lang in langs:
URL = "%s/listings/addons-%s.txt" % (config.get("behavior.addons-url"), lang)
LOG.debug(" trying: %s" % URL)
try:
fp = urllib2.urlopen(URL, timeout=10) # wait up to 10 seconds
except: # some error
LOG.debug(" IOError!")
fp = None
if fp and fp.getcode() == 200: # ok
break
addon_update_list = []
if fp and fp.getcode() == 200:
lines = list(fp.readlines())
count = 0
for line in lines:
try:
plugin_dict = safe_eval(line)
if type(plugin_dict) != type({}):
raise TypeError("Line with addon metadata is not "
"a dictionary")
except:
LOG.debug("Skipped a line in the addon listing: " +
str(line))
continue
id = plugin_dict["i"]
plugin = self._pmgr.get_plugin(id)
if plugin:
LOG.debug("Comparing %s > %s" %
(version_str_to_tup(plugin_dict["v"], 3),
version_str_to_tup(plugin.version, 3)))
if (version_str_to_tup(plugin_dict["v"], 3) >
version_str_to_tup(plugin.version, 3)):
LOG.debug(" Downloading '%s'..." % plugin_dict["z"])
if "update" in whattypes:
if (not config.get('behavior.do-not-show-previously-seen-updates') or
plugin_dict["i"] not in config.get('behavior.previously-seen-updates')):
addon_update_list.append((_("Updated"),
"%s/download/%s" %
(config.get("behavior.addons-url"),
plugin_dict["z"]),
plugin_dict))
else:
LOG.debug(" '%s' is ok" % plugin_dict["n"])
else:
LOG.debug(" '%s' is not installed" % plugin_dict["n"])
if "new" in whattypes:
if (not config.get('behavior.do-not-show-previously-seen-updates') or
plugin_dict["i"] not in config.get('behavior.previously-seen-updates')):
addon_update_list.append((_("New"),
"%s/download/%s" %
(config.get("behavior.addons-url"),
plugin_dict["z"]),
plugin_dict))
config.set("behavior.last-check-for-updates",
datetime.date.today().strftime("%Y/%m/%d"))
count += 1
else:
from QuestionDialog import OkDialog
OkDialog(_("Checking Addons Failed"),
_("The addon repository appears to be unavailable. Please try again later."),
self.window)
if fp:
fp.close()
return
LOG.debug("Done checking!")
# List of translated strings used here
# Dead code for l10n
_('new'), _('update')
if addon_update_list:
self.update_addons(addon_update_list)
elif force:
from QuestionDialog import OkDialog
OkDialog(_("There are no available addons of this type"),
_("Checked for '%s'") %
_("' and '").join([_(t) for t in config.get('behavior.check-for-update-types')]),
self.window)
def update_addons(self, addon_update_list): def process_updates(self, addon_update_list):
from glade import Glade
import ManagedWindow
from ListModel import ListModel, NOSORT, TOGGLE
glade = Glade("updateaddons.glade")
self.update_dialog = glade.toplevel
ManagedWindow.set_titles(self.update_dialog,
glade.get_object('title'),
_('Available Gramps Updates for Addons'))
apply_button = glade.get_object('apply')
cancel_button = glade.get_object('cancel')
select_all = glade.get_object('select_all')
select_all.connect("clicked", self.select_all_clicked)
select_none = glade.get_object('select_none')
select_none.connect("clicked", self.select_none_clicked)
apply_button.connect("clicked", self.install_addons)
cancel_button.connect("clicked",
lambda obj: self.update_dialog.destroy())
self.list = ListModel(glade.get_object("list"), [
# name, click?, width, toggle
{"name": _('Select'),
"width": 60,
"type": TOGGLE,
"visible_col": 6,
"editable": True}, # 0 selected?
(_('Type'), 1, 180), # 1 new gramplet
(_('Name'), 2, 200), # 2 name (version)
(_('Description'), 3, 200), # 3 description
('', NOSORT, 0), # 4 url
('', NOSORT, 0), # 5 id
{"name": '', "type": TOGGLE}, # 6 visible? bool
], list_mode="tree")
pos = None
addon_update_list.sort(key=lambda x: "%s %s" % (x[0], x[2]["t"]))
last_category = None
for (status,plugin_url,plugin_dict) in addon_update_list:
count = get_count(addon_update_list, plugin_dict["t"])
category = _("%(adjective)s: %(addon)s") % {
"adjective": status,
"addon": _(plugin_dict["t"])}
if last_category != category:
last_category = category
node = self.list.add([False, # initially selected?
category,
"",
"",
"",
"",
False]) # checkbox visible?
iter = self.list.add([False, # initially selected?
"%s %s" % (status, _(plugin_dict["t"])),
"%s (%s)" % (plugin_dict["n"],
plugin_dict["v"]),
plugin_dict["d"],
plugin_url,
plugin_dict["i"],
True], node=node)
if pos is None:
pos = iter
if pos:
self.list.selection.select_iter(pos)
self.update_dialog.run()
def select_all_clicked(self, widget):
""" """
Select all of the addons for download. Called when add-on updates are available.
""" """
self.list.model.foreach(update_rows, True) try:
self.list.tree.expand_all() PluginWindows.UpdateAddons(self.uistate, [], addon_update_list)
except WindowActiveError:
pass
def select_none_clicked(self, widget): self.do_reg_plugins(self.dbstate, self.uistate)
"""
Select none of the addons for download.
"""
self.list.model.foreach(update_rows, False)
self.list.tree.expand_all()
def install_addons(self, obj):
"""
Process all of the selected addons.
"""
from QuestionDialog import OkDialog
from gui.widgets.progressdialog import LongOpStatus
self.update_dialog.hide()
model = self.list.model
iter = model.get_iter_first()
length = 0
while iter:
iter = model.iter_next(iter)
if iter:
length += model.iter_n_children(iter)
longop = LongOpStatus(
_("Downloading and installing selected addons..."),
length, 1, # total, increment-by
can_cancel=True)
pm = ProgressMonitor(GtkProgressDialog,
("Title", self.window, gtk.DIALOG_MODAL))
pm.add_op(longop)
count = 0
if not config.get('behavior.do-not-show-previously-seen-updates'):
# reset list
config.get('behavior.previously-seen-updates')[:] = []
iter = model.get_iter_first()
while iter:
for rowcnt in range(model.iter_n_children(iter)):
child = model.iter_nth_child(iter, rowcnt)
row = [model.get_value(child, n) for n in range(6)]
if longop.should_cancel():
break
elif row[0]: # toggle on
load_addon_file(row[4], callback=LOG.debug)
count += 1
else: # add to list of previously seen, but not installed
if row[5] not in config.get('behavior.previously-seen-updates'):
config.get('behavior.previously-seen-updates').append(row[5])
longop.heartbeat()
pm._get_dlg()._process_events()
iter = model.iter_next(iter)
if not longop.was_cancelled():
longop.end()
if count:
self.do_reg_plugins(self.dbstate, self.uistate)
OkDialog(_("Done downloading and installing addons"),
"%s %s" % (ngettext("%d addon was installed.",
"%d addons were installed.",
count) % count,
_("You need to restart Gramps to see new views.")),
self.window)
else:
OkDialog(_("Done downloading and installing addons"),
_("No addons were installed."),
self.window)
self.update_dialog.destroy()
def _errordialog(self, title, errormessage): def _errordialog(self, title, errormessage):
""" """