diff options
Diffstat (limited to 'rpms/sugar/0072-Remove-AC-microformat-updater-files.patch')
-rw-r--r-- | rpms/sugar/0072-Remove-AC-microformat-updater-files.patch | 1153 |
1 files changed, 1153 insertions, 0 deletions
diff --git a/rpms/sugar/0072-Remove-AC-microformat-updater-files.patch b/rpms/sugar/0072-Remove-AC-microformat-updater-files.patch new file mode 100644 index 0000000..018234f --- /dev/null +++ b/rpms/sugar/0072-Remove-AC-microformat-updater-files.patch @@ -0,0 +1,1153 @@ +From 62e7e4dbb3c0e2fc4b1eccbd163bc4ca779399f0 Mon Sep 17 00:00:00 2001 +From: Anish Mangal <anish@activitycentral.com> +Date: Wed, 14 Dec 2011 18:31:30 +0530 +Subject: [PATCH sugar 72/74] Remove AC microformat updater files + +Dextrose now uses the out-of-tree microformat updater from OLPC. +--- + data/icons/Makefile.am | 1 - + data/icons/module-updater.svg | 16 - + extensions/cpsection/Makefile.am | 1 - + extensions/cpsection/updater/Makefile.am | 8 - + extensions/cpsection/updater/__init__.py | 22 -- + extensions/cpsection/updater/backends/Makefile.am | 5 - + extensions/cpsection/updater/backends/__init__.py | 16 - + .../cpsection/updater/backends/microformat.py | 203 ---------- + extensions/cpsection/updater/model.py | 383 ------------------- + extensions/cpsection/updater/view.py | 398 -------------------- + 10 files changed, 0 insertions(+), 1053 deletions(-) + delete mode 100644 data/icons/module-updater.svg + delete mode 100644 extensions/cpsection/updater/Makefile.am + delete mode 100644 extensions/cpsection/updater/__init__.py + delete mode 100644 extensions/cpsection/updater/backends/Makefile.am + delete mode 100644 extensions/cpsection/updater/backends/__init__.py + delete mode 100644 extensions/cpsection/updater/backends/microformat.py + delete mode 100755 extensions/cpsection/updater/model.py + delete mode 100644 extensions/cpsection/updater/view.py + +diff --git a/data/icons/Makefile.am b/data/icons/Makefile.am +index 2582c31..8e01626 100644 +--- a/data/icons/Makefile.am ++++ b/data/icons/Makefile.am +@@ -11,7 +11,6 @@ sugar_DATA = \ + module-modemconfiguration.svg \ + module-network.svg \ + module-power.svg \ +- module-updater.svg \ + module-proxy.svg + + EXTRA_DIST = $(sugar_DATA) +diff --git a/data/icons/module-updater.svg b/data/icons/module-updater.svg +deleted file mode 100644 +index a521f61..0000000 +--- a/data/icons/module-updater.svg ++++ /dev/null +@@ -1,16 +0,0 @@ +-<?xml version="1.0" ?><!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd' [ +- <!ENTITY stroke_color "#000"> +- <!ENTITY fill_color "#fff"> +-]><svg height="55px" viewBox="0 0 55 55" width="55px" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> +- <g> +- <g> +- <path d="M 31.752 7.088 C 41.935 9.118 49.609 18.107 49.609 28.887 C 49.609 41.173 39.65 51.129 27.374 51.129 C 15.086 51.129 5.133 41.173 5.133 28.887 C 5.133 19.648 10.768 11.723 18.801 8.365 " fill="none" stroke="&fill_color;" stroke-linecap="round" stroke-linejoin="round" stroke-width="3.5" /> +- <path d="M 36.134 15.154 L 31.752 7.088 L 40.439 4.13 " fill="none" stroke="&fill_color;" stroke-linecap="round" stroke-linejoin="round" stroke-width="3.5" /> +- </g> +- <g> +- <g> +- <path d="M 38.57 25.886 C 37.597 25.886 36.718 26.282 36.082 26.918 L 31.021 31.979 L 31.02 17.022 C 31.018 16.124 30.675 15.221 29.99 14.533 C 28.613 13.159 26.383 13.159 25.01 14.533 C 24.321 15.222 23.98 16.122 23.979 17.023 L 23.977 31.978 L 18.918 26.918 C 18.281 26.281 17.4 25.886 16.429 25.887 C 14.484 25.885 12.908 27.465 12.908 29.408 C 12.907 30.381 13.304 31.263 13.936 31.899 L 27.5 45.463 L 41.062 31.898 C 41.697 31.262 42.09 30.382 42.093 29.41 C 42.094 27.463 40.516 25.885 38.57 25.886 Z " fill="&fill_color;" stroke="none" /> +- </g> +- </g> +- </g> +-</svg> +diff --git a/extensions/cpsection/Makefile.am b/extensions/cpsection/Makefile.am +index 78d548b..2074d11 100644 +--- a/extensions/cpsection/Makefile.am ++++ b/extensions/cpsection/Makefile.am +@@ -9,7 +9,6 @@ SUBDIRS = \ + modemconfiguration \ + network \ + power \ +- updater \ + proxy \ + # + +diff --git a/extensions/cpsection/updater/Makefile.am b/extensions/cpsection/updater/Makefile.am +deleted file mode 100644 +index 897dbf3..0000000 +--- a/extensions/cpsection/updater/Makefile.am ++++ /dev/null +@@ -1,8 +0,0 @@ +-SUBDIRS = backends +- +-sugardir = $(pkgdatadir)/extensions/cpsection/updater +- +-sugar_PYTHON = \ +- __init__.py \ +- model.py \ +- view.py +diff --git a/extensions/cpsection/updater/__init__.py b/extensions/cpsection/updater/__init__.py +deleted file mode 100644 +index 6010615..0000000 +--- a/extensions/cpsection/updater/__init__.py ++++ /dev/null +@@ -1,22 +0,0 @@ +-# Copyright (C) 2008, OLPC +-# +-# This program is free software; you can redistribute it and/or modify +-# it under the terms of the GNU General Public License as published by +-# the Free Software Foundation; either version 2 of the License, or +-# (at your option) any later version. +-# +-# This program is distributed in the hope that it will be useful, +-# but WITHOUT ANY WARRANTY; without even the implied warranty of +-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-# GNU General Public License for more details. +-# +-# You should have received a copy of the GNU General Public License +-# along with this program; if not, write to the Free Software +-# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +- +-from gettext import gettext as _ +- +-CLASS = 'ActivityUpdater' +-ICON = 'module-updater' +-TITLE = _('Software update') +-KEYWORDS = ['software', 'activity', 'update'] +diff --git a/extensions/cpsection/updater/backends/Makefile.am b/extensions/cpsection/updater/backends/Makefile.am +deleted file mode 100644 +index e9c1284..0000000 +--- a/extensions/cpsection/updater/backends/Makefile.am ++++ /dev/null +@@ -1,5 +0,0 @@ +-sugardir = $(pkgdatadir)/extensions/cpsection/updater/backends +- +-sugar_PYTHON = \ +- microformat.py \ +- __init__.py +diff --git a/extensions/cpsection/updater/backends/__init__.py b/extensions/cpsection/updater/backends/__init__.py +deleted file mode 100644 +index 0dd0174..0000000 +--- a/extensions/cpsection/updater/backends/__init__.py ++++ /dev/null +@@ -1,16 +0,0 @@ +-#!/usr/bin/python +-# Copyright (C) 2009, Sugar Labs +-# +-# This program is free software; you can redistribute it and/or modify +-# it under the terms of the GNU General Public License as published by +-# the Free Software Foundation; either version 2 of the License, or +-# (at your option) any later version. +-# +-# This program is distributed in the hope that it will be useful, +-# but WITHOUT ANY WARRANTY; without even the implied warranty of +-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-# GNU General Public License for more details. +-# +-# You should have received a copy of the GNU General Public License +-# along with this program; if not, write to the Free Software +-# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +diff --git a/extensions/cpsection/updater/backends/microformat.py b/extensions/cpsection/updater/backends/microformat.py +deleted file mode 100644 +index ca4f1d5..0000000 +--- a/extensions/cpsection/updater/backends/microformat.py ++++ /dev/null +@@ -1,203 +0,0 @@ +-#!/usr/bin/python +-# +-# Copyright (C) 2011, Anish Mangal <anish@sugarlabs.org> +-# +-# This program is free software; you can redistribute it and/or modify +-# it under the terms of the GNU General Public License as published by +-# the Free Software Foundation; either version 2 of the License, or +-# (at your option) any later version. +-# +-# This program is distributed in the hope that it will be useful, +-# but WITHOUT ANY WARRANTY; without even the implied warranty of +-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-# GNU General Public License for more details. +-# +-# You should have received a copy of the GNU General Public License +-# along with this program; if not, write to the Free Software +-# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +- +-import logging +-from HTMLParser import HTMLParser +-import urllib +-import re +- +-import gio +-import gobject +-import gconf +- +-from jarabe import config +- +-client = gconf.client_get_default() +-_UPDATE_PATH = client.get_string('/desktop/sugar/updater_url') +-_ACTIVITIES_LIST = {} +-ACTION_CHECKING = 0 +-ACTION_UPDATING = 1 +-ACTION_DOWNLOADING = 2 +- +-class MicroformatParser(HTMLParser): +- +- def __init__(self, data, completion_cb): +- HTMLParser.__init__(self) +- self.reset() +- self._data_to_parse = data +- self._activity_id = '' +- self._activity_url = '' +- self._activity_version = '' +- self._activity_size = 1 +- self._activity_name = '' +- self._inside_activity_block = False +- self._inside_activity_version = False +- self._inside_activity_id = False +- self._inside_activity_url = False +- self._inside_activity_size = False +- self._inside_activity_name = False +- self._activity_block_tag = '' +- self._completion_cb = completion_cb +- +- def parse(self): +- self.feed(self._data_to_parse) +- +- def handle_endtag(self, tag): +- if tag == self._activity_block_tag and self._inside_activity_block: +- self._inside_activity_block = False +- +- _ACTIVITIES_LIST[self._activity_id] = \ +- {'version':self._activity_version, +- 'url':self._activity_url, +- 'size':self._activity_size, +- 'name':self._activity_name} +- +- elif tag == 'a': +- if self._inside_activity_url: +- self._inside_activity_url = False +- +- elif tag == 'body': +- num_bundles = len(_ACTIVITIES_LIST) +- progress = num_bundles +- for bundle, info in _ACTIVITIES_LIST.items(): +- progress = progress + 1 +- if _ACTIVITIES_LIST[bundle]['size'] == 1: +- try: +- _ACTIVITIES_LIST[bundle]['size'] = \ +- gio.File(_ACTIVITIES_LIST[bundle]['url']).\ +- query_info('*').get_size() +- +- except Exception, e: +- logging.exception(e) +- +- if _ACTIVITIES_LIST[bundle]['size'] == 0: +- logging.error('Size of activity %s reported as ' +- '0 bytes. Excluding from update list' % bundle) +- del _ACTIVITIES_LIST[bundle] +- +- elif _ACTIVITIES_LIST[bundle]['name'] == '': +- # Do some regex magic to get the 'probable' +- # activity name. +- activity_name = re.split('\.', +- bundle)[-1] +- activity_name = re.sub('^[\s|\t]*', '', +- activity_name) +- activity_name = re.sub('[\s|\t]*$', '', +- activity_name) +- activity_name = re.sub('[A|a]ctivity$', '', +- activity_name) +- _ACTIVITIES_LIST[bundle]['name'] = \ +- activity_name +- +- self._completion_cb(_ACTIVITIES_LIST, None) +- +- def handle_starttag(self, tag, attrs): +- for attribute, value in attrs: +- if value == 'olpc-activity-info': +- self._inside_activity_block = True +- self._activity_block_tag = tag +- +- if tag == 'span': +- for attribute, value in attrs: +- if value == 'olpc-activity-id': +- self._inside_activity_id = True +- elif value == 'olpc-activity-version': +- self._inside_activity_version = True +- elif value == 'olpc-activity-name': +- self._inside_activity_name = True +- elif value == 'olpc-activity-size': +- self._inside_activity_size = True +- elif value == 'olpc-activity-url': +- self._inside_activity_url = True +- +- elif tag == 'a': +- if self._inside_activity_url: +- for attribute, value in attrs: +- if attribute == 'href': +- self._activity_url = value +- +- def handle_data(self, data): +- if self._inside_activity_version: +- self._activity_version = str(data) +- self._inside_activity_version = False +- +- elif self._inside_activity_id: +- self._activity_id = data +- self._inside_activity_id = False +- +- elif self._inside_activity_name: +- self._activity_name = data +- self._inside_activity_name = False +- +- elif self._inside_activity_size: +- self._activity_size = int(data) +- self._inside_activity_size = False +- +-class _UpdateFetcher(gobject.GObject): +- +- __gsignals__ = { +- 'progress': (gobject.SIGNAL_RUN_FIRST, +- gobject.TYPE_NONE, +- ([int, str, float, int])), +- } +- +- def __init__(self, completion_cb): +- gobject.GObject.__init__(self) +- # ASLO knows only about stable SP releases +- major, minor = config.version.split('.')[0:2] +- sp_version = '%s.%s' % (major, int(minor) + int(minor) % 2) +- self._data = '' +- self._completion_cb = completion_cb +- +- def download_bundle_updates(self): +- self.emit('progress', ACTION_CHECKING, 'Fetching update ' +- 'information', 1, 3) +- self._url = _UPDATE_PATH +- self._file = gio.File(self._url) +- logging.debug('Fetch %s', self._url) +- self._file.read_async(self.__read_async_cb) +- +- def __read_async_cb(self, gfile, result): +- try: +- stream = gfile.read_finish(result) +- except gio.Error, e: +- self.stop() +- logging.exception('Error while fetching content from %s' % +- self._url) +- return +- stream.read_async(4096, self.__stream_read_cb) +- +- def __stream_read_cb(self, stream, result): +- data = stream.read_finish(result) +- if not data: +- self._data_finished() +- return +- self._data_read(data) +- stream.read_async(4096, self.__stream_read_cb) +- +- def _data_read(self, data): +- self._data += data +- +- def read_finish(self): +- pass +- +- def _data_finished(self): +- self.emit('progress', ACTION_CHECKING, 'Fetching update ' +- 'information', 2, 3) +- parser = MicroformatParser(self._data, self._completion_cb) +- gobject.idle_add(parser.parse) +diff --git a/extensions/cpsection/updater/model.py b/extensions/cpsection/updater/model.py +deleted file mode 100755 +index 1a3941c..0000000 +--- a/extensions/cpsection/updater/model.py ++++ /dev/null +@@ -1,383 +0,0 @@ +-# Copyright (C) 2009, Sugar Labs +-# Copyright (C) 2009, Tomeu Vizoso +-# +-# This program is free software; you can redistribute it and/or modify +-# it under the terms of the GNU General Public License as published by +-# the Free Software Foundation; either version 2 of the License, or +-# (at your option) any later version. +-# +-# This program is distributed in the hope that it will be useful, +-# but WITHOUT ANY WARRANTY; without even the implied warranty of +-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-# GNU General Public License for more details. +-# +-# You should have received a copy of the GNU General Public License +-# along with this program; if not, write to the Free Software +-# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +-"""Sugar bundle updater: model. +- +-This module implements the non-GUI portions of the bundle updater, including +-list of installed bundls, whether updates are needed, and the URL at which to +-find the bundle updated. +-""" +- +-import os +-import logging +-import tempfile +-from urlparse import urlparse +-import traceback +- +-import gobject +-import gio +- +-from sugar import env +-from sugar.datastore import datastore +-from sugar.bundle.activitybundle import ActivityBundle +-from sugar.bundle.bundleversion import NormalizedVersion +- +-from jarabe.model import bundleregistry +- +-from backends import microformat +- +-class MetaBundle(): +- +- def __init__(self, bundle_id, version, name): +- self._bundle_id = bundle_id +- self._version = version +- self._name = name +- +- def get_name(self): +- return self._name +- +- def get_bundle_id(self): +- return self._bundle_id +- +- def get_icon(self): +- pass +- +- def get_activity_version(self): +- return self._version +- +-class UpdateModel(gobject.GObject): +- __gtype_name__ = 'SugarUpdateModel' +- +- __gsignals__ = { +- 'progress': (gobject.SIGNAL_RUN_FIRST, +- gobject.TYPE_NONE, +- ([int, str, float, int])), +- } +- +- ACTION_CHECKING = 0 +- ACTION_UPDATING = 1 +- ACTION_DOWNLOADING = 2 +- +- def __init__(self): +- gobject.GObject.__init__(self) +- +- self.updates = None +- self._bundles_to_check = None +- self._bundles_to_update = None +- self._total_bundles_to_update = 0 +- self._downloader = None +- self._cancelling = False +- +- def __progress_cb(self, model, action, description, current, total): +- self.emit('progress', action, description, current, total) +- +- def check_updates(self): +- self.updates = [] +- self._current_bundles = {} +- for bundle in bundleregistry.get_registry(): +- self._current_bundles[bundle.get_bundle_id()] =\ +- {'version':bundle.get_activity_version(), +- 'bundle': bundle} +- self._bundles_to_check = list(bundleregistry.get_registry()) +- self._fetcher = microformat._UpdateFetcher(self.__bundle_info_fetched_cb) +- self._fetcher.connect('progress', self.__progress_cb) +- gobject.idle_add(self._fetcher.download_bundle_updates) +- +- def __bundle_info_fetched_cb(self, new_bundles, error_message): +- if error_message is not None: +- logging.error('Error getting update information from server:\n' +- '%s' % error_message) +- +- if self._cancelling: +- self._cancel_checking() +- else: +- for bundle_id, info in new_bundles.items(): +- if bundle_id in self._current_bundles: +- old_version = self._current_bundles[bundle_id]['version'] +- new_version = new_bundles[bundle_id]['version'] +- if NormalizedVersion(old_version) < \ +- NormalizedVersion(new_version): +- self.updates.append(BundleUpdate( +- self._current_bundles[bundle_id]['bundle'], +- new_bundles[bundle_id]['version'], +- new_bundles[bundle_id]['url'], +- new_bundles[bundle_id]['size'], +- 'update')) +- else: +- bundle = MetaBundle(bundle_id, +- new_bundles[bundle_id]['version'], +- new_bundles[bundle_id]['name']) +- self.updates.append(BundleUpdate(bundle, +- new_bundles[bundle_id]['version'], +- new_bundles[bundle_id]['url'], +- new_bundles[bundle_id]['size'], +- 'new')) +- +- self.emit('progress', UpdateModel.ACTION_CHECKING, 'Fetching update ' +- 'information', 3, 3) +- +- def update(self, bundle_ids): +- self._bundles_to_update = [] +- for bundle_update in self.updates: +- if bundle_update.bundle.get_bundle_id() in bundle_ids: +- self._bundles_to_update.append(bundle_update) +- +- self._total_bundles_to_update = len(self._bundles_to_update) +- self._download_next_update() +- +- def _download_next_update(self): +- if self._cancelling: +- self._cancel_updating() +- return +- +- bundle_update = self._bundles_to_update.pop() +- +- total = self._total_bundles_to_update * 2 +- current = total - len(self._bundles_to_update) * 2 - 2 +- +- self.emit('progress', UpdateModel.ACTION_DOWNLOADING, +- bundle_update.bundle.get_name(), current, total) +- +- self._downloader = _Downloader(bundle_update) +- self._downloader.connect('progress', self.__downloader_progress_cb) +- self._downloader.connect('error', self.__downloader_error_cb) +- +- def __downloader_progress_cb(self, downloader, progress): +- logging.debug('__downloader_progress_cb %r', progress) +- +- if self._cancelling: +- self._cancel_updating() +- return +- +- total = self._total_bundles_to_update * 2 +- current = total - len(self._bundles_to_update) * 2 - 2 + progress +- +- self.emit('progress', UpdateModel.ACTION_DOWNLOADING, +- self._downloader.bundle_update.bundle.get_name(), +- current, total) +- +- if progress == 1: +- self._install_update(self._downloader.bundle_update, +- self._downloader.get_local_file_path()) +- self._downloader = None +- +- def __downloader_error_cb(self, downloader, error_message): +- logging.error('Error downloading update:\n%s', error_message) +- +- if self._cancelling: +- self._cancel_updating() +- return +- +- total = self._total_bundles_to_update +- current = total - len(self._bundles_to_update) +- self.emit('progress', UpdateModel.ACTION_UPDATING, '', current, total) +- +- if self._bundles_to_update: +- # do it in idle so the UI has a chance to refresh +- gobject.idle_add(self._download_next_update) +- +- def _install_update(self, bundle_update, local_file_path): +- +- total = self._total_bundles_to_update +- current = total - len(self._bundles_to_update) - 0.5 +- +- self.emit('progress', UpdateModel.ACTION_UPDATING, +- bundle_update.bundle.get_name(), +- current, total) +- +- # TODO: Should we first expand the zip async so we can provide progress +- # and only then copy to the journal? +- jobject = datastore.create() +- try: +- title = '%s-%s' % (bundle_update.bundle.get_name(), +- bundle_update.version) +- jobject.metadata['title'] = title +- jobject.metadata['mime_type'] = ActivityBundle.MIME_TYPE +- jobject.file_path = local_file_path +- datastore.write(jobject, transfer_ownership=True) +- finally: +- jobject.destroy() +- +- self.emit('progress', UpdateModel.ACTION_UPDATING, +- bundle_update.bundle.get_name(), +- current + 0.5, total) +- +- if self._bundles_to_update: +- # do it in idle so the UI has a chance to refresh +- gobject.idle_add(self._download_next_update) +- +- def cancel(self): +- self._cancelling = True +- +- def _cancel_checking(self): +- logging.debug('UpdateModel._cancel_checking') +- total = len(bundleregistry.get_registry()) +- current = total - len(self._bundles_to_check) +- self.emit('progress', UpdateModel.ACTION_CHECKING, '', current, +- current) +- self._bundles_to_check = None +- self._cancelling = False +- +- def _cancel_updating(self): +- logging.debug('UpdateModel._cancel_updating') +- current = (self._total_bundles_to_update - +- len(self._bundles_to_update) - 1) +- self.emit('progress', UpdateModel.ACTION_UPDATING, '', current, +- current) +- +- if self._downloader is not None: +- self._downloader.cancel() +- file_path = self._downloader.get_local_file_path() +- if file_path is not None and os.path.exists(file_path): +- os.unlink(file_path) +- self._downloader = None +- +- self._total_bundles_to_update = 0 +- self._bundles_to_update = None +- self._cancelling = False +- +- +-class BundleUpdate(object): +- +- def __init__(self, bundle, version, link, size, package_type = None): +- self.bundle = bundle +- self.version = version +- self.link = link +- self.size = size +- +- # Specify whether installing a new bundle or updating an +- # existing one +- self.package_type = package_type +- +-class _Downloader(gobject.GObject): +- _CHUNK_SIZE = 10240 # 10K +- __gsignals__ = { +- 'progress': (gobject.SIGNAL_RUN_FIRST, +- gobject.TYPE_NONE, +- ([float])), +- 'error': (gobject.SIGNAL_RUN_FIRST, +- gobject.TYPE_NONE, +- ([str])), +- } +- +- def __init__(self, bundle_update): +- gobject.GObject.__init__(self) +- +- self.bundle_update = bundle_update +- self._input_stream = None +- self._output_stream = None +- self._pending_buffers = [] +- self._input_file = gio.File(bundle_update.link) +- self._output_file = None +- self._downloaded_size = 0 +- self._cancelling = False +- +- self._input_file.read_async(self.__file_read_async_cb) +- +- def cancel(self): +- self._cancelling = True +- +- def __file_read_async_cb(self, gfile, result): +- if self._cancelling: +- return +- +- try: +- self._input_stream = self._input_file.read_finish(result) +- except: +- self.emit('error', traceback.format_exc()) +- return +- +- temp_file_path = self._get_temp_file_path(self.bundle_update.link) +- self._output_file = gio.File(temp_file_path) +- self._output_stream = self._output_file.create() +- +- self._input_stream.read_async(self._CHUNK_SIZE, self.__read_async_cb, +- gobject.PRIORITY_LOW) +- +- def __read_async_cb(self, input_stream, result): +- if self._cancelling: +- return +- +- data = input_stream.read_finish(result) +- +- if data is None: +- # TODO +- pass +- elif not data: +- logging.debug('closing input stream') +- self._input_stream.close() +- self._check_if_finished_writing() +- else: +- self._pending_buffers.append(data) +- self._input_stream.read_async(self._CHUNK_SIZE, +- self.__read_async_cb, +- gobject.PRIORITY_LOW) +- +- self._write_next_buffer() +- +- def __write_async_cb(self, output_stream, result, user_data): +- if self._cancelling: +- return +- +- count = output_stream.write_finish(result) +- +- self._downloaded_size += count +- progress = self._downloaded_size / float(self.bundle_update.size) +- self.emit('progress', progress) +- +- self._check_if_finished_writing() +- +- if self._pending_buffers: +- self._write_next_buffer() +- +- def _write_next_buffer(self): +- if self._pending_buffers and not self._output_stream.has_pending(): +- data = self._pending_buffers.pop(0) +- # TODO: we pass the buffer as user_data because of +- # http://bugzilla.gnome.org/show_bug.cgi?id=564102 +- self._output_stream.write_async(data, self.__write_async_cb, +- gobject.PRIORITY_LOW, +- user_data=data) +- +- def _get_temp_file_path(self, uri): +- # TODO: Should we use the HTTP headers for the file name? +- scheme_, netloc_, path, params_, query_, fragment_ = \ +- urlparse(uri) +- path = os.path.basename(path) +- +- if not os.path.exists(env.get_user_activities_path()): +- os.makedirs(env.get_user_activities_path()) +- +- base_name, extension_ = os.path.splitext(path) +- fd, file_path = tempfile.mkstemp(dir=env.get_user_activities_path(), +- prefix=base_name, suffix='.xo') +- os.close(fd) +- os.unlink(file_path) +- +- return file_path +- +- def get_local_file_path(self): +- return self._output_file.get_path() +- +- def _check_if_finished_writing(self): +- if not self._pending_buffers and \ +- not self._output_stream.has_pending() and \ +- self._input_stream.is_closed(): +- +- logging.debug('closing output stream') +- self._output_stream.close() +- +- self.emit('progress', 1.0) +diff --git a/extensions/cpsection/updater/view.py b/extensions/cpsection/updater/view.py +deleted file mode 100644 +index 891f552..0000000 +--- a/extensions/cpsection/updater/view.py ++++ /dev/null +@@ -1,398 +0,0 @@ +-# Copyright (C) 2008, One Laptop Per Child +-# Copyright (C) 2009, Tomeu Vizoso +-# +-# This program is free software; you can redistribute it and/or modify +-# it under the terms of the GNU General Public License as published by +-# the Free Software Foundation; either version 2 of the License, or +-# (at your option) any later version. +-# +-# This program is distributed in the hope that it will be useful, +-# but WITHOUT ANY WARRANTY; without even the implied warranty of +-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-# GNU General Public License for more details. +-# +-# You should have received a copy of the GNU General Public License +-# along with this program; if not, write to the Free Software +-# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +- +-from gettext import gettext as _ +-from gettext import ngettext +-import locale +-import logging +- +-import gobject +-import gtk +- +-from sugar.graphics import style +-from sugar.graphics.icon import Icon, CellRendererIcon +- +-from jarabe.controlpanel.sectionview import SectionView +- +-from model import UpdateModel +- +-_DEBUG_VIEW_ALL = True +- +- +-class ActivityUpdater(SectionView): +- +- def __init__(self, model, alerts): +- SectionView.__init__(self) +- +- self._model = UpdateModel() +- self._model.connect('progress', self.__progress_cb) +- +- self.set_spacing(style.DEFAULT_SPACING) +- self.set_border_width(style.DEFAULT_SPACING * 2) +- +- self._top_label = gtk.Label() +- self._top_label.set_line_wrap(True) +- self._top_label.set_justify(gtk.JUSTIFY_LEFT) +- self._top_label.props.xalign = 0 +- self.pack_start(self._top_label, expand=False) +- self._top_label.show() +- +- separator = gtk.HSeparator() +- self.pack_start(separator, expand=False) +- separator.show() +- +- bottom_label = gtk.Label() +- bottom_label.set_line_wrap(True) +- bottom_label.set_justify(gtk.JUSTIFY_LEFT) +- bottom_label.props.xalign = 0 +- bottom_label.set_markup( +- _('Software updates correct errors, eliminate security ' \ +- 'vulnerabilities, and provide new features.')) +- self.pack_start(bottom_label, expand=False) +- bottom_label.show() +- +- self._update_box = None +- self._progress_pane = None +- +- self._refresh() +- +- def _switch_to_update_box(self): +- if self._update_box in self.get_children(): +- return +- +- if self._progress_pane in self.get_children(): +- self.remove(self._progress_pane) +- self._progress_pane = None +- +- if self._update_box is None: +- self._update_box = UpdateBox(self._model) +- self._update_box.refresh_button.connect('clicked', +- self.__refresh_button_clicked_cb) +- self._update_box.install_button.connect('clicked', +- self.__install_button_clicked_cb) +- +- self.pack_start(self._update_box, expand=True, fill=True) +- self._update_box.show() +- +- def _switch_to_progress_pane(self): +- if self._progress_pane in self.get_children(): +- return +- +- if self._update_box in self.get_children(): +- self.remove(self._update_box) +- self._update_box = None +- +- if self._progress_pane is None: +- self._progress_pane = ProgressPane() +- self._progress_pane.cancel_button.connect('clicked', +- self.__cancel_button_clicked_cb) +- +- self.pack_start(self._progress_pane, expand=True, fill=False) +- self._progress_pane.show() +- +- def _clear_center(self): +- if self._progress_pane in self.get_children(): +- self.remove(self._progress_pane) +- self._progress_pane = None +- +- if self._update_box in self.get_children(): +- self.remove(self._update_box) +- self._update_box = None +- +- def __progress_cb(self, model, action, bundle_name, current, total): +- if current == total and action == UpdateModel.ACTION_CHECKING: +- self._finished_checking() +- return +- elif current == total: +- self._finished_updating(int(current)) +- return +- +- if action == UpdateModel.ACTION_CHECKING: +- message = _('%s...') % bundle_name +- elif action == UpdateModel.ACTION_DOWNLOADING: +- message = _('Downloading %s...') % bundle_name +- elif action == UpdateModel.ACTION_UPDATING: +- message = _('Updating %s...') % bundle_name +- +- self._switch_to_progress_pane() +- self._progress_pane.set_message(message) +- self._progress_pane.set_progress(current / float(total)) +- +- def _finished_checking(self): +- logging.debug('ActivityUpdater._finished_checking') +- available_updates = len(self._model.updates) +- if not available_updates: +- top_message = _('Your software is up-to-date') +- else: +- top_message = ngettext('You can install %s update', +- 'You can install %s updates', +- available_updates) +- top_message = top_message % available_updates +- top_message = gobject.markup_escape_text(top_message) +- +- self._top_label.set_markup('<big>%s</big>' % top_message) +- +- if not available_updates: +- self._clear_center() +- else: +- self._switch_to_update_box() +- self._update_box.refresh() +- +- def __refresh_button_clicked_cb(self, button): +- self._refresh() +- +- def _refresh(self): +- top_message = _('Checking for updates...') +- self._top_label.set_markup('<big>%s</big>' % top_message) +- self._model.check_updates() +- +- def __install_button_clicked_cb(self, button): +- text = '<big>%s</big>' % _('Installing updates...') +- self._top_label.set_markup(text) +- self._model.update(self._update_box.get_bundles_to_update()) +- +- def __cancel_button_clicked_cb(self, button): +- self._model.cancel() +- +- def _finished_updating(self, installed_updates): +- logging.debug('ActivityUpdater._finished_updating') +- top_message = ngettext('%s update was installed', +- '%s updates were installed', installed_updates) +- top_message = top_message % installed_updates +- top_message = gobject.markup_escape_text(top_message) +- self._top_label.set_markup('<big>%s</big>' % top_message) +- self._clear_center() +- +- def undo(self): +- self._model.cancel() +- +- +-class ProgressPane(gtk.VBox): +- """Container which replaces the `ActivityPane` during refresh or +- install.""" +- +- def __init__(self): +- gtk.VBox.__init__(self) +- self.set_spacing(style.DEFAULT_PADDING) +- self.set_border_width(style.DEFAULT_SPACING * 2) +- +- self._progress = gtk.ProgressBar() +- self.pack_start(self._progress) +- self._progress.show() +- +- self._label = gtk.Label() +- self._label.set_line_wrap(True) +- self._label.set_property('xalign', 0.5) +- self._label.modify_fg(gtk.STATE_NORMAL, +- style.COLOR_BUTTON_GREY.get_gdk_color()) +- self.pack_start(self._label) +- self._label.show() +- +- alignment_box = gtk.Alignment(xalign=0.5, yalign=0.5) +- self.pack_start(alignment_box) +- alignment_box.show() +- +- self.cancel_button = gtk.Button(stock=gtk.STOCK_CANCEL) +- alignment_box.add(self.cancel_button) +- self.cancel_button.show() +- +- def set_message(self, message): +- self._label.set_text(message) +- +- def set_progress(self, fraction): +- self._progress.props.fraction = fraction +- +- +-class UpdateBox(gtk.VBox): +- +- def __init__(self, model): +- gtk.VBox.__init__(self) +- +- self._model = model +- +- self.set_spacing(style.DEFAULT_PADDING) +- +- scrolled_window = gtk.ScrolledWindow() +- scrolled_window.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) +- self.pack_start(scrolled_window) +- scrolled_window.show() +- +- self._update_list = UpdateList(model) +- self._update_list.props.model.connect('row-changed', +- self.__row_changed_cb) +- scrolled_window.add(self._update_list) +- self._update_list.show() +- +- bottom_box = gtk.HBox() +- bottom_box.set_spacing(style.DEFAULT_SPACING) +- self.pack_start(bottom_box, expand=False) +- bottom_box.show() +- +- self._size_label = gtk.Label() +- self._size_label.props.xalign = 0 +- self._size_label.set_justify(gtk.JUSTIFY_LEFT) +- bottom_box.pack_start(self._size_label, expand=True) +- self._size_label.show() +- +- self.refresh_button = gtk.Button(stock=gtk.STOCK_REFRESH) +- bottom_box.pack_start(self.refresh_button, expand=False) +- self.refresh_button.show() +- +- self.install_button = gtk.Button(_('Install selected')) +- self.install_button.props.image = Icon(icon_name='emblem-downloads', +- icon_size=gtk.ICON_SIZE_BUTTON) +- bottom_box.pack_start(self.install_button, expand=False) +- self.install_button.show() +- +- self._update_total_size_label() +- +- def refresh(self): +- self._update_list.refresh() +- +- def __row_changed_cb(self, list_model, path, iterator): +- self._update_total_size_label() +- self._update_install_button() +- +- def _update_total_size_label(self): +- total_size = 0 +- for row in self._update_list.props.model: +- if row[UpdateListModel.SELECTED]: +- total_size += row[UpdateListModel.SIZE] +- +- markup = _('Download size: %s') % _format_size(total_size) +- self._size_label.set_markup(markup) +- +- def _update_install_button(self): +- for row in self._update_list.props.model: +- if row[UpdateListModel.SELECTED]: +- self.install_button.props.sensitive = True +- return +- self.install_button.props.sensitive = False +- +- def get_bundles_to_update(self): +- bundles_to_update = [] +- for row in self._update_list.props.model: +- if row[UpdateListModel.SELECTED]: +- bundles_to_update.append(row[UpdateListModel.BUNDLE_ID]) +- return bundles_to_update +- +- +-class UpdateList(gtk.TreeView): +- +- def __init__(self, model): +- list_model = UpdateListModel(model) +- gtk.TreeView.__init__(self, list_model) +- +- self.set_reorderable(False) +- self.set_enable_search(False) +- self.set_headers_visible(False) +- +- toggle_renderer = gtk.CellRendererToggle() +- toggle_renderer.props.activatable = True +- toggle_renderer.props.xpad = style.DEFAULT_PADDING +- toggle_renderer.props.indicator_size = style.zoom(26) +- toggle_renderer.connect('toggled', self.__toggled_cb) +- +- toggle_column = gtk.TreeViewColumn() +- toggle_column.pack_start(toggle_renderer) +- toggle_column.add_attribute(toggle_renderer, 'active', +- UpdateListModel.SELECTED) +- self.append_column(toggle_column) +- +- icon_renderer = CellRendererIcon(self) +- icon_renderer.props.width = style.STANDARD_ICON_SIZE +- icon_renderer.props.height = style.STANDARD_ICON_SIZE +- icon_renderer.props.size = style.STANDARD_ICON_SIZE +- icon_renderer.props.xpad = style.DEFAULT_PADDING +- icon_renderer.props.ypad = style.DEFAULT_PADDING +- icon_renderer.props.stroke_color = style.COLOR_TOOLBAR_GREY.get_svg() +- icon_renderer.props.fill_color = style.COLOR_TRANSPARENT.get_svg() +- +- icon_column = gtk.TreeViewColumn() +- icon_column.pack_start(icon_renderer) +- icon_column.add_attribute(icon_renderer, 'file-name', +- UpdateListModel.ICON_FILE_NAME) +- self.append_column(icon_column) +- +- text_renderer = gtk.CellRendererText() +- +- description_column = gtk.TreeViewColumn() +- description_column.pack_start(text_renderer) +- description_column.add_attribute(text_renderer, 'markup', +- UpdateListModel.DESCRIPTION) +- self.append_column(description_column) +- +- def __toggled_cb(self, cell_renderer, path): +- row = self.props.model[path] +- row[UpdateListModel.SELECTED] = not row[UpdateListModel.SELECTED] +- +- def refresh(self): +- pass +- +- +-class UpdateListModel(gtk.ListStore): +- +- BUNDLE_ID = 0 +- SELECTED = 1 +- ICON_FILE_NAME = 2 +- DESCRIPTION = 3 +- SIZE = 4 +- +- def __init__(self, model): +- gtk.ListStore.__init__(self, str, bool, str, str, int) +- +- for bundle_update in model.updates: +- row = [None] * 5 +- row[self.BUNDLE_ID] = bundle_update.bundle.get_bundle_id() +- row[self.SELECTED] = False +- row[self.ICON_FILE_NAME] = bundle_update.bundle.get_icon() +- +- if bundle_update.package_type == 'update': +- row[self.SELECTED] = True +- details = _('From version %(current)s to %(new)s (Size: %(size)s)') +- details = details % \ +- {'current': bundle_update.bundle.get_activity_version(), +- 'new': bundle_update.version, +- 'size': _format_size(bundle_update.size)} +- elif bundle_update.package_type == 'new': +- details = _('Install new activity version %(new)s (Size: %(size)s)') +- details = details % \ +- {'new': bundle_update.version, +- 'size': _format_size(bundle_update.size)} +- +- row[self.DESCRIPTION] = '<b>%s</b>\n%s' % \ +- (bundle_update.bundle.get_name(), details) +- +- row[self.SIZE] = bundle_update.size +- +- self.append(row) +- +- +-def _format_size(size): +- """Convert a given size in bytes to a nicer better readable unit""" +- if size == 0: +- # TRANS: download size is 0 +- return _('None') +- elif size < 1024: +- # TRANS: download size of very small updates +- return _('1 KB') +- elif size < 1024 * 1024: +- # TRANS: download size of small updates, e.g. '250 KB' +- return locale.format_string(_('%.0f KB'), size / 1024.0) +- else: +- # TRANS: download size of updates, e.g. '2.3 MB' +- return locale.format_string(_('%.1f MB'), size / 1024.0 / 1024) +-- +1.7.6 + |