Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAnish Mangal <anish@activitycentral.com>2011-12-14 13:01:30 (GMT)
committer Anish Mangal <anish@activitycentral.com>2012-02-01 12:33:31 (GMT)
commitfa1d1835b6a9f600cd0dc8e3cf29690441e9456f (patch)
tree4e7425c76f415d4b39545e8b2902c13300414e96
parent6040b52e606548f3becdf6b228c231b6faa188c9 (diff)
Remove AC microformat updater files
Dextrose now uses the out-of-tree microformat updater from OLPC.
-rw-r--r--data/icons/Makefile.am1
-rw-r--r--data/icons/module-updater.svg16
-rw-r--r--extensions/cpsection/Makefile.am1
-rw-r--r--extensions/cpsection/updater/Makefile.am8
-rw-r--r--extensions/cpsection/updater/__init__.py22
-rw-r--r--extensions/cpsection/updater/backends/Makefile.am5
-rw-r--r--extensions/cpsection/updater/backends/__init__.py16
-rw-r--r--extensions/cpsection/updater/backends/microformat.py203
-rwxr-xr-xextensions/cpsection/updater/model.py383
-rw-r--r--extensions/cpsection/updater/view.py398
10 files changed, 0 insertions, 1053 deletions
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)