[plugin_installer] Add plugin auto update
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Generated with glade 3.20.0 -->
|
||||
<!-- Generated with glade 3.20.2 -->
|
||||
<interface>
|
||||
<requires lib="gtk+" version="3.14"/>
|
||||
<object class="GtkWindow" id="ConfigWindow">
|
||||
@@ -14,7 +14,7 @@
|
||||
<property name="margin_bottom">12</property>
|
||||
<child>
|
||||
<object class="GtkCheckButton" id="check_update">
|
||||
<property name="label" translatable="yes">Check update after start</property>
|
||||
<property name="label" translatable="yes">Check for updates after start</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="focus_on_click">False</property>
|
||||
@@ -27,6 +27,38 @@
|
||||
<property name="top_attach">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkCheckButton" id="auto_update">
|
||||
<property name="label" translatable="yes">Update plugins automatically</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="sensitive">False</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="focus_on_click">False</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
<signal name="toggled" handler="on_auto_update_toggled" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkCheckButton" id="auto_update_feedback">
|
||||
<property name="label" translatable="yes">Show message when auto update was successful</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="sensitive">False</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="focus_on_click">False</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
<signal name="toggled" handler="on_auto_update_feedback_toggled" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
@@ -171,6 +203,7 @@ Upgrade</property>
|
||||
<object class="GtkButton" id="install_button">
|
||||
<property name="label" translatable="yes">Install/Upgrade</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="sensitive">False</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="valign">start</property>
|
||||
|
||||
@@ -44,14 +44,16 @@ try:
|
||||
from plugins import GajimPlugin
|
||||
from plugins.gui import GajimPluginConfigDialog
|
||||
from htmltextview import HtmlTextView
|
||||
from dialogs import WarningDialog, HigDialog, YesNoDialog
|
||||
from dialogs import WarningDialog, HigDialog, YesNoDialog, \
|
||||
ConfirmationDialogCheck
|
||||
from gtkgui_helpers import get_action
|
||||
except ImportError:
|
||||
from gajim.common import app
|
||||
from gajim.plugins import GajimPlugin
|
||||
from gajim.plugins.gui import GajimPluginConfigDialog
|
||||
from gajim.htmltextview import HtmlTextView
|
||||
from gajim.dialogs import WarningDialog, HigDialog, YesNoDialog
|
||||
from gajim.dialogs import WarningDialog, HigDialog, YesNoDialog, \
|
||||
ConfirmationDialogCheck
|
||||
from gajim.gtkgui_helpers import get_action
|
||||
|
||||
log = logging.getLogger('gajim.plugin_system.plugin_installer')
|
||||
@@ -113,7 +115,9 @@ class PluginInstaller(GajimPlugin):
|
||||
def init(self):
|
||||
self.description = _('Install and Upgrade Plugins')
|
||||
self.config_dialog = PluginInstallerPluginConfigDialog(self)
|
||||
self.config_default_values = {'check_update': (True, '')}
|
||||
self.config_default_values = {'check_update': (True, ''),
|
||||
'auto_update': (False, ''),
|
||||
'auto_update_feedback': (True, '')}
|
||||
self.gui_extension_points = {'plugin_window': (self.on_activate, None)}
|
||||
self.window = None
|
||||
self.progressbar = None
|
||||
@@ -128,17 +132,20 @@ class PluginInstaller(GajimPlugin):
|
||||
self.on_activate(app.interface.instances['plugins'])
|
||||
|
||||
def warn_update(self, plugins):
|
||||
def open_update(dummy):
|
||||
def open_update(checked):
|
||||
if checked:
|
||||
self.config['auto_update'] = True
|
||||
get_action('plugins').activate()
|
||||
page = self.notebook.page_num(self.paned)
|
||||
self.notebook.set_current_page(page)
|
||||
if plugins:
|
||||
plugins_str = '\n' + '\n'.join(plugins)
|
||||
YesNoDialog(
|
||||
_('Plugins updates'),
|
||||
_('Some updates are available for your installer plugins. '
|
||||
'Do you want to update those plugins:\n%s')
|
||||
% plugins_str, on_response_yes=open_update)
|
||||
_('Plugin updates'),
|
||||
_('There are updates available for plugins you have installed.\n'
|
||||
'Do you want to update those plugins:\n%s') % plugins_str,
|
||||
checktext=_('_Update plugins automatically next time'),
|
||||
on_response_yes=open_update)
|
||||
else:
|
||||
log.info('No updates found')
|
||||
if hasattr(self, 'thread'):
|
||||
@@ -148,7 +155,8 @@ class PluginInstaller(GajimPlugin):
|
||||
if hasattr(self, 'thread'):
|
||||
return
|
||||
log.info('Checking for Updates...')
|
||||
self.start_download(check_update=True)
|
||||
auto_update = self.config['auto_update']
|
||||
self.start_download(check_update=True, auto_update=auto_update)
|
||||
self.timeout_id = 0
|
||||
|
||||
def deactivate(self):
|
||||
@@ -243,7 +251,7 @@ class PluginInstaller(GajimPlugin):
|
||||
if self.available_plugins_model[i][Column.UPGRADE]:
|
||||
dir_list.append(self.available_plugins_model[i][Column.DIR])
|
||||
|
||||
self.start_download(remote_dirs=dir_list)
|
||||
self.start_download(remote_dirs=dir_list, auto_update=False)
|
||||
|
||||
def on_error(self, reason):
|
||||
if reason == 'CERTIFICATE_VERIFY_FAILED':
|
||||
@@ -269,18 +277,20 @@ class PluginInstaller(GajimPlugin):
|
||||
_('An error occurred when downloading\n\n'
|
||||
'<tt>[%s]</tt>' % (str(text))), self.window)
|
||||
|
||||
def start_download(self, secure=True, remote_dirs=False,
|
||||
upgrading=False, check_update=False):
|
||||
def start_download(self, secure=True, remote_dirs=False, upgrading=False,
|
||||
check_update=False, auto_update=False):
|
||||
log.info('Start Download...')
|
||||
log.debug(
|
||||
'secure: %s, remote_dirs: %s, upgrading: %s, check_update: %s',
|
||||
secure, remote_dirs, upgrading, check_update)
|
||||
'secure: %s, remote_dirs: %s, upgrading: %s, '
|
||||
'check_update: %s, auto_update: %s',
|
||||
secure, remote_dirs, upgrading, check_update, auto_update)
|
||||
self.thread = DownloadAsync(
|
||||
self, secure=secure, remote_dirs=remote_dirs,
|
||||
upgrading=upgrading, check_update=check_update)
|
||||
upgrading=upgrading, check_update=check_update,
|
||||
auto_update=auto_update)
|
||||
self.thread.start()
|
||||
|
||||
def on_plugin_downloaded(self, plugin_dirs):
|
||||
def on_plugin_downloaded(self, plugin_dirs, auto_update):
|
||||
for _dir in plugin_dirs:
|
||||
is_active = False
|
||||
plugins = None
|
||||
@@ -293,11 +303,12 @@ class PluginInstaller(GajimPlugin):
|
||||
app.plugin_manager.deactivate_plugin(plugin)
|
||||
app.plugin_manager.plugins.remove(plugin)
|
||||
|
||||
model = self.installed_plugins_model
|
||||
for row in range(len(model)):
|
||||
if plugin == model[row][0]:
|
||||
model.remove(model.get_iter((row, 0)))
|
||||
break
|
||||
if not auto_update:
|
||||
model = self.installed_plugins_model
|
||||
for row in range(len(model)):
|
||||
if plugin == model[row][0]:
|
||||
model.remove(model.get_iter((row, 0)))
|
||||
break
|
||||
|
||||
log.info('Load Plugin from: %s', plugin_dir)
|
||||
plugins = app.plugin_manager.scan_dir_for_plugins(
|
||||
@@ -308,28 +319,42 @@ class PluginInstaller(GajimPlugin):
|
||||
app.plugin_manager.add_plugin(plugins[0])
|
||||
plugin = app.plugin_manager.plugins[-1]
|
||||
log.info('Loading successful')
|
||||
for row in range(len(self.available_plugins_model)):
|
||||
model_row = self.available_plugins_model[row]
|
||||
if plugin.name == model_row[Column.NAME]:
|
||||
model_row[Column.LOCAL_VERSION] = plugin.version
|
||||
model_row[Column.UPGRADE] = False
|
||||
if not auto_update:
|
||||
for row in range(len(self.available_plugins_model)):
|
||||
model_row = self.available_plugins_model[row]
|
||||
if plugin.name == model_row[Column.NAME]:
|
||||
model_row[Column.LOCAL_VERSION] = plugin.version
|
||||
model_row[Column.UPGRADE] = False
|
||||
if is_active:
|
||||
log.info('Activate Plugin: %s', plugin)
|
||||
app.plugin_manager.activate_plugin(plugin)
|
||||
# get plugin icon
|
||||
icon_file = os.path.join(plugin.__path__, os.path.split(
|
||||
plugin.__path__)[1]) + '.png'
|
||||
icon = FALLBACK_ICON
|
||||
if os.path.isfile(icon_file):
|
||||
icon = GdkPixbuf.Pixbuf.new_from_file_at_size(icon_file, 16, 16)
|
||||
row = [plugin, plugin.name, is_active, plugin.activatable, icon]
|
||||
self.installed_plugins_model.append(row)
|
||||
if not auto_update:
|
||||
# get plugin icon
|
||||
icon_file = os.path.join(plugin.__path__, os.path.split(
|
||||
plugin.__path__)[1]) + '.png'
|
||||
icon = FALLBACK_ICON
|
||||
if os.path.isfile(icon_file):
|
||||
icon = GdkPixbuf.Pixbuf.new_from_file_at_size(icon_file, 16, 16)
|
||||
row = [plugin, plugin.name, is_active, plugin.activatable, icon]
|
||||
self.installed_plugins_model.append(row)
|
||||
|
||||
dialog = HigDialog(
|
||||
self.window, Gtk.MessageType.INFO, Gtk.ButtonsType.OK,
|
||||
'', _('All selected plugins downloaded'))
|
||||
dialog.set_modal(False)
|
||||
dialog.popup()
|
||||
if not auto_update:
|
||||
dialog = HigDialog(
|
||||
self.window, Gtk.MessageType.INFO, Gtk.ButtonsType.OK,
|
||||
'', _('All selected plugins downloaded'))
|
||||
dialog.set_modal(False)
|
||||
dialog.popup()
|
||||
|
||||
if auto_update and self.config['auto_update_feedback']:
|
||||
def on_ok(checked):
|
||||
if checked:
|
||||
self.config['auto_update_feedback'] = False
|
||||
# Hide cancel button to mimic InfoDialogCheck
|
||||
ConfirmationDialogCheck(_('Plugins updated'),
|
||||
_('Plugins were updated successfully'),
|
||||
_('_Do not show this message again'),
|
||||
on_response_ok=on_ok).get_widget_for_response(
|
||||
Gtk.ResponseType.CANCEL).hide()
|
||||
|
||||
def available_plugins_treeview_selection_changed(self, treeview_selection):
|
||||
model, iter_ = treeview_selection.get_selected()
|
||||
@@ -373,7 +398,8 @@ class PluginInstaller(GajimPlugin):
|
||||
|
||||
|
||||
class DownloadAsync(threading.Thread):
|
||||
def __init__(self, plugin, secure, remote_dirs, upgrading, check_update):
|
||||
def __init__(self, plugin, secure, remote_dirs,
|
||||
upgrading, check_update, auto_update):
|
||||
threading.Thread.__init__(self)
|
||||
self.plugin = plugin
|
||||
self.window = plugin.window
|
||||
@@ -383,6 +409,7 @@ class DownloadAsync(threading.Thread):
|
||||
self.upgrading = upgrading
|
||||
self.secure = secure
|
||||
self.check_update = check_update
|
||||
self.auto_update = auto_update
|
||||
self.pulse = None
|
||||
|
||||
def model_append(self, row):
|
||||
@@ -403,9 +430,10 @@ class DownloadAsync(threading.Thread):
|
||||
if self.check_update:
|
||||
self.run_check_update()
|
||||
else:
|
||||
GLib.idle_add(self.progressbar.show)
|
||||
self.pulse = GLib.timeout_add(150, self.progressbar_pulse)
|
||||
self.run_download_plugin_list()
|
||||
if not self.auto_update:
|
||||
GLib.idle_add(self.progressbar.show)
|
||||
self.pulse = GLib.timeout_add(150, self.progressbar_pulse)
|
||||
self.run_download_plugin_list()
|
||||
except urllib.error.URLError as exc:
|
||||
if isinstance(exc.reason, ssl.SSLError):
|
||||
ssl_reason = exc.reason.reason
|
||||
@@ -495,6 +523,7 @@ class DownloadAsync(threading.Thread):
|
||||
|
||||
def run_check_update(self):
|
||||
to_update = []
|
||||
auto_update_list = []
|
||||
zipbuf = self.download_url(MANIFEST_URL)
|
||||
plugin_list = self.parse_manifest(zipbuf)
|
||||
for plugin in plugin_list:
|
||||
@@ -508,7 +537,17 @@ class DownloadAsync(threading.Thread):
|
||||
if (V(plugin['version']) > V(local_version)) and \
|
||||
(gajim_v >= min_v) and (gajim_v <= max_v):
|
||||
to_update.append(plugin['name'])
|
||||
GLib.idle_add(self.plugin.warn_update, to_update)
|
||||
auto_update_list.append(plugin['remote_dir'])
|
||||
if not self.auto_update:
|
||||
GLib.idle_add(self.plugin.warn_update, to_update)
|
||||
else:
|
||||
if auto_update_list:
|
||||
self.remote_dirs = auto_update_list
|
||||
GLib.idle_add(self.download_plugin)
|
||||
else:
|
||||
log.info('No updates found')
|
||||
if hasattr(self.plugin, 'thread'):
|
||||
del self.plugin.thread
|
||||
|
||||
def run_download_plugin_list(self):
|
||||
if not self.remote_dirs:
|
||||
@@ -549,7 +588,8 @@ class DownloadAsync(threading.Thread):
|
||||
continue
|
||||
with ZipFile(buf) as zip_file:
|
||||
zip_file.extractall(local_dir)
|
||||
GLib.idle_add(self.plugin.on_plugin_downloaded, self.remote_dirs)
|
||||
GLib.idle_add(self.plugin.on_plugin_downloaded,
|
||||
self.remote_dirs, self.auto_update)
|
||||
|
||||
|
||||
class PluginInstallerPluginConfigDialog(GajimPluginConfigDialog):
|
||||
@@ -566,6 +606,29 @@ class PluginInstallerPluginConfigDialog(GajimPluginConfigDialog):
|
||||
def on_run(self):
|
||||
self.xml.get_object('check_update').set_active(
|
||||
self.plugin.config['check_update'])
|
||||
if self.plugin.config['check_update']:
|
||||
self.xml.get_object('auto_update').set_sensitive(True)
|
||||
self.xml.get_object('auto_update').set_active(
|
||||
self.plugin.config['auto_update'])
|
||||
self.xml.get_object('auto_update_feedback').set_sensitive(True)
|
||||
self.xml.get_object('auto_update_feedback').set_active(
|
||||
self.plugin.config['auto_update_feedback'])
|
||||
|
||||
def on_check_update_toggled(self, widget):
|
||||
self.plugin.config['check_update'] = widget.get_active()
|
||||
if widget.get_active():
|
||||
self.xml.get_object('auto_update').set_sensitive(True)
|
||||
self.xml.get_object('auto_update').set_active(
|
||||
self.plugin.config['auto_update'])
|
||||
self.xml.get_object('auto_update_feedback').set_sensitive(True)
|
||||
self.xml.get_object('auto_update_feedback').set_active(
|
||||
self.plugin.config['auto_update_feedback'])
|
||||
else:
|
||||
self.xml.get_object('auto_update').set_sensitive(False)
|
||||
self.xml.get_object('auto_update_feedback').set_sensitive(False)
|
||||
|
||||
def on_auto_update_toggled(self, widget):
|
||||
self.plugin.config['auto_update'] = widget.get_active()
|
||||
|
||||
def on_auto_update_feedback_toggled(self, widget):
|
||||
self.plugin.config['auto_update_feedback'] = widget.get_active()
|
||||
|
||||
Reference in New Issue
Block a user