Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/downloadmanager.py
diff options
context:
space:
mode:
Diffstat (limited to 'downloadmanager.py')
-rw-r--r--downloadmanager.py133
1 files changed, 78 insertions, 55 deletions
diff --git a/downloadmanager.py b/downloadmanager.py
index a190d75..d9ccfac 100644
--- a/downloadmanager.py
+++ b/downloadmanager.py
@@ -19,6 +19,7 @@ import logging
import tempfile
from gettext import gettext as _
import time
+import gtk
from xpcom.nsError import *
from xpcom import components
@@ -27,9 +28,11 @@ from xpcom.server.factory import Factory
import dbus
from sugar.datastore import datastore
-from sugar.clipboard import clipboardservice
from sugar import profile
from sugar import objects
+from sugar.graphics.alert import Alert, TimeoutAlert
+from sugar.graphics import style
+from sugar.graphics.icon import Icon
# #3903 - this constant can be removed and assumed to be 1 when dbus-python
# 0.82.3 is the only version used
@@ -47,21 +50,28 @@ DS_DBUS_PATH = '/org/laptop/sugar/DataStore'
_browser = None
_temp_path = '/tmp'
-def init(browser, temp_path):
+def init(browser, activity, temp_path):
global _browser
_browser = browser
+ global _activity
+ _activity = activity
+
global _temp_path
_temp_path = temp_path
-_active_ds_writes = 0
-_quit_callback = None
+_active_downloads = []
def can_quit():
- return _active_ds_writes == 0
+ return len(_active_downloads) == 0
-def set_quit_callback(callback):
- _quit_callback = callback
+def remove_all_downloads():
+ for download in _active_downloads:
+ download._cancelable.cancel(NS_ERROR_FAILURE)
+ if download._dl_jobject is not None:
+ download._datastore_deleted_handler.remove()
+ datastore.delete(download._dl_jobject.object_id)
+ download._cleanup_datastore_write()
class DownloadManager:
_com_interfaces_ = interfaces.nsIHelperAppLauncherDialog
@@ -97,15 +107,15 @@ components.registrar.registerFactory('{64355793-988d-40a5-ba8e-fcde78cac631}"',
class Download:
_com_interfaces_ = interfaces.nsITransfer
-
- def init(self, source, target, display_name, mime_info, start_time, temp_file,
- cancelable):
+
+ def init(self, source, target, display_name, mime_info, start_time,
+ temp_file, cancelable):
self._source = source
self._mime_type = mime_info.MIMEType
self._temp_file = temp_file
self._target_file = target.queryInterface(interfaces.nsIFileURL).file
self._dl_jobject = None
- self._cb_object_id = None
+ self._object_id = None
self._last_update_time = 0
self._last_update_percent = 0
self._cancelable = cancelable
@@ -114,17 +124,33 @@ class Download:
def onStateChange(self, web_progress, request, state_flags, status):
if state_flags == interfaces.nsIWebProgressListener.STATE_START:
- self._create_journal_object()
- self._create_clipboard_object()
+ self._create_journal_object()
+ alert = TimeoutAlert(9)
+ alert.props.title = _('Download started')
+ path, file_name = os.path.split(self._target_file.path)
+ alert.props.msg = _('%s'%(file_name))
+ _activity.add_alert(alert)
+ alert.connect('response', self.__start_response_cb)
+ alert.show()
+ global _active_downloads
+ _active_downloads.append(self)
elif state_flags == interfaces.nsIWebProgressListener.STATE_STOP:
if NS_FAILED(status): # download cancelled
return
-
- cb_service = clipboardservice.get_instance()
- # Test if the object still exists in the clipboard as it could have
- # been removed.
- if cb_service.get_object(self._cb_object_id):
- cb_service.set_object_percent(self._cb_object_id, 100)
+ alert = Alert()
+ alert.props.title = _('Download completed')
+ path, file_name = os.path.split(self._target_file.path)
+ alert.props.msg = _('%s'%(file_name))
+ open_icon = Icon(icon_name='zoom-activity')
+ alert.add_button(gtk.RESPONSE_APPLY, _('Open'), open_icon)
+ open_icon.show()
+ ok_icon = Icon(icon_name='dialog-ok')
+ alert.add_button(gtk.RESPONSE_OK, _('Ok'), ok_icon)
+ ok_icon.show()
+ _activity.add_alert(alert)
+ alert.connect('response', self.__stop_response_cb)
+ alert.show()
+ self._object_id = self._dl_jobject.object_id
path, file_name = os.path.split(self._target_file.path)
@@ -137,25 +163,46 @@ class Download:
sniffed_mime_type = objects.mime.get_for_file(self._target_file.path)
self._dl_jobject.metadata['mime_type'] = sniffed_mime_type
- global _active_ds_writes
- _active_ds_writes = _active_ds_writes + 1
datastore.write(self._dl_jobject,
reply_handler=self._internal_save_cb,
error_handler=self._internal_save_error_cb,
timeout=360 * DBUS_PYTHON_TIMEOUT_UNITS_PER_SECOND)
+ def __start_response_cb(self, alert, response_id):
+ if response_id is gtk.RESPONSE_CANCEL:
+ logging.debug('Download Canceled')
+ self._cancelable.cancel(NS_ERROR_FAILURE)
+ if self._dl_jobject is not None:
+ self._datastore_deleted_handler.remove()
+ datastore.delete(self._dl_jobject.object_id)
+ self._cleanup_datastore_write()
+ _activity.remove_alert(alert)
+
+ def __stop_response_cb(self, alert, response_id):
+ if response_id is gtk.RESPONSE_APPLY:
+ logging.debug('Start application with downloaded object')
+ from sugar.activity import activityfactory
+ from sugar import activity
+ activities_info = activity.get_registry().get_activities_for_type(
+ self._mime_type)
+ activities = []
+ for activity_info in activities_info:
+ activities.append(activity_info)
+ logging.debug('--> act=%s mime=%s'%(activities, self._mime_type))
+ bundle_id = activities[0].bundle_id
+ logging.debug('--> bundle_id=%s'%bundle_id)
+ activityfactory.create_with_object_id(bundle_id, self._object_id)
+ _activity.remove_alert(alert)
+
def _cleanup_datastore_write(self):
- global _active_ds_writes
- _active_ds_writes = _active_ds_writes - 1
+ global _active_downloads
+ _active_downloads.remove(self)
- os.remove(self._dl_jobject.file_path)
+ if os.path.isfile(self._dl_jobject.file_path):
+ os.remove(self._dl_jobject.file_path)
self._dl_jobject.destroy()
self._dl_jobject = None
- global _quit_callback
- if _active_ds_writes == 0 and not _quit_callback is None:
- _quit_callback()
-
def _internal_save_cb(self):
self._cleanup_datastore_write()
@@ -180,12 +227,6 @@ class Download:
self._dl_jobject.metadata['progress'] = str(percent)
datastore.write(self._dl_jobject)
- cb_service = clipboardservice.get_instance()
- # Test if the object still exists in the clipboard as it could have
- # been removed.
- if cb_service.get_object(self._cb_object_id):
- cb_service.set_object_percent(self._cb_object_id, percent)
-
def _create_journal_object(self):
path, file_name = os.path.split(self._target_file.path)
@@ -205,33 +246,15 @@ class Download:
bus = dbus.SessionBus()
obj = bus.get_object(DS_DBUS_SERVICE, DS_DBUS_PATH)
datastore_dbus = dbus.Interface(obj, DS_DBUS_INTERFACE)
- datastore_dbus.connect_to_signal('Deleted', self.__datastore_deleted_cb,
- arg0=self._dl_jobject.object_id)
+ self._datastore_deleted_handler = datastore_dbus.connect_to_signal(
+ 'Deleted', self.__datastore_deleted_cb,
+ arg0=self._dl_jobject.object_id)
def __datastore_deleted_cb(self, uid):
logging.debug('Downloaded entry has been deleted from the datastore: %r' % uid)
# TODO: Use NS_BINDING_ABORTED instead of NS_ERROR_FAILURE.
self._cancelable.cancel(NS_ERROR_FAILURE) #NS_BINDING_ABORTED)
- def _create_clipboard_object(self):
- path, file_name = os.path.split(self._target_file.path)
-
- cb_service = clipboardservice.get_instance()
- self._cb_object_id = cb_service.add_object(file_name)
-
- # TODO: avoid by now adding two formats, as they would create two
- # identical files in /tmp
- #cb_service.add_object_format(self._cb_object_id,
- # self._mime_type,
- # 'file://' + self._target_file.path.encode('utf8'),
- # on_disk = True)
-
- # Also add the 'text/uri-list' target for the same file path.
- cb_service.add_object_format(self._cb_object_id,
- 'text/uri-list',
- 'file://' + self._target_file.path.encode('utf8'),
- on_disk = True)
-
components.registrar.registerFactory('{23c51569-e9a1-4a92-adeb-3723db82ef7c}"',
'Sugar Download',
'@mozilla.org/transfer;1',