From 7796aaf4d53e008677f31a57395f3dcdc499ce54 Mon Sep 17 00:00:00 2001 From: Damien Elmes Date: Tue, 24 Jul 2012 17:00:25 +0900 Subject: [PATCH] refactor addon downloading into separate file --- aqt/addons.py | 69 +++++-------------------------------------- aqt/downloader.py | 74 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+), 62 deletions(-) create mode 100644 aqt/downloader.py diff --git a/aqt/addons.py b/aqt/addons.py index e0d428f7e..470b2ca3f 100644 --- a/aqt/addons.py +++ b/aqt/addons.py @@ -14,6 +14,7 @@ import aqt.forms import aqt from anki.sync import httpCon import aqt.sync # monkey-patches httplib2 +from aqt.downloader import download # in the future, it would be nice to save the addon id and unzippped file list # to the config so that we can clear up all files and check for updates @@ -149,68 +150,12 @@ class GetAddons(QDialog): openLink(aqt.appShared + "addons/") def accept(self): - try: - code = int(self.form.code.text()) - except ValueError: - showWarning(_("Invalid code.")) - return QDialog.accept(self) # create downloader thread - self.thread = AddonDownloader(code) - self.connect(self.thread, SIGNAL("recv"), self.onRecv) - self.recvBytes = 0 - self.thread.start() - self.mw.progress.start(immediate=True) - while not self.thread.isFinished(): - self.mw.app.processEvents() - self.thread.wait(100) - if not self.thread.error: - # success - self.mw.addonManager.install(self.thread.data, self.thread.fname) - self.mw.progress.finish() - showInfo(_("Download successful. Please restart Anki.")) - else: - self.mw.progress.finish() - showWarning(_("Download failed: %s") % self.thread.error) - - def onRecv(self, total): - self.mw.progress.update(label="%dKB downloaded" % (total/1024)) - -class AddonDownloader(QThread): - - def __init__(self, code): - QThread.__init__(self) - self.code = code - self.error = None - - def run(self): - # setup progress handler - self.byteUpdate = time.time() - self.recvTotal = 0 - def canPost(): - if (time.time() - self.byteUpdate) > 0.1: - self.byteUpdate = time.time() - return True - def recvEvent(bytes): - self.recvTotal += bytes - if canPost(): - self.emit(SIGNAL("recv"), self.recvTotal) - addHook("httpRecv", recvEvent) - con = httpCon() - try: - resp, cont = con.request( - aqt.appShared + "download/%d" % self.code) - except Exception, e: - self.error = unicode(e[0], "utf8", "ignore") + ret = download(self.mw, self.form.code.text()) + if not ret: return - finally: - remHook("httpRecv", recvEvent) - if resp['status'] == '200': - self.error = None - self.fname = re.match("attachment; filename=(.+)", - resp['content-disposition']).group(1) - self.data = cont - elif resp['status'] == '403': - self.error = _("Invalid code.") - else: - self.error = _("Error downloading: %s") % resp['status'] + data, fname = ret + self.mw.addonManager.install(data, fname) + self.mw.progress.finish() + showInfo(_("Download successful. Please restart Anki.")) diff --git a/aqt/downloader.py b/aqt/downloader.py new file mode 100644 index 000000000..d393f977b --- /dev/null +++ b/aqt/downloader.py @@ -0,0 +1,74 @@ +# Copyright: Damien Elmes +# -*- coding: utf-8 -*- +# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html + +import time, re +from aqt.qt import * +from anki.sync import httpCon +from aqt.utils import showWarning +from anki.hooks import addHook, remHook +import aqt.sync # monkey-patches httplib2 + +def download(mw, code): + "Download addon/deck from AnkiWeb. On success caller must stop progress diag." + # check code is valid + try: + code = int(code) + except ValueError: + showWarning(_("Invalid code.")) + return + # create downloading thread + thread = Downloader(code) + def onRecv(): + mw.progress.update(label="%dKB downloaded" % (thread.recvTotal/1024)) + mw.connect(thread, SIGNAL("recv"), onRecv) + thread.start() + mw.progress.start(immediate=True) + while not thread.isFinished(): + mw.app.processEvents() + thread.wait(100) + if not thread.error: + # success + return thread.data, thread.fname + else: + mw.progress.finish() + showWarning(_("Download failed: %s") % thread.error) + +class Downloader(QThread): + + def __init__(self, code): + QThread.__init__(self) + self.code = code + self.error = None + + def run(self): + # setup progress handler + self.byteUpdate = time.time() + self.recvTotal = 0 + def canPost(): + if (time.time() - self.byteUpdate) > 0.1: + self.byteUpdate = time.time() + return True + def recvEvent(bytes): + self.recvTotal += bytes + if canPost(): + self.emit(SIGNAL("recv")) + addHook("httpRecv", recvEvent) + con = httpCon() + try: + resp, cont = con.request( + aqt.appShared + "download/%d" % self.code) + except Exception, e: + self.error = unicode(e[0], "utf8", "ignore") + return + finally: + remHook("httpRecv", recvEvent) + if resp['status'] == '200': + self.error = None + self.fname = re.match("attachment; filename=(.+)", + resp['content-disposition']).group(1) + self.data = cont + elif resp['status'] == '403': + self.error = _("Invalid code.") + else: + self.error = _("Error downloading: %s") % resp['status']