From b0a230536890caf36db6a6079e57efac98a0686c Mon Sep 17 00:00:00 2001 From: megachweng Date: Mon, 24 Dec 2018 20:53:22 +0800 Subject: [PATCH] add pronunciation downloader add version checker change log --- src/addonWindow.py | 39 +++++++++++++++++++++++++++++++++------ src/api.py | 35 ++++++++++++++++++++++++++++++++++- src/cardManager.py | 12 +++++++++--- src/notifier.py | 5 +++-- src/signals.py | 7 +++++++ 5 files changed, 86 insertions(+), 12 deletions(-) diff --git a/src/addonWindow.py b/src/addonWindow.py index 9eae2c8..11e18ca 100644 --- a/src/addonWindow.py +++ b/src/addonWindow.py @@ -12,7 +12,7 @@ import time import json -__VERSION__ = 'v5.0.1' +__VERSION__ = 'v5.0.2' MODELNAME = 'Dict2Anki_NEW' DICTIONARYLIST = ['Youdao', 'Eudict'] @@ -36,9 +36,9 @@ def __init__(self): def checkVersion(self): - @pyqtSlot(object) - def haveNewVersion(version): - if askUser(f'有新版本:{version}是否更新?'): + @pyqtSlot(object, object) + def haveNewVersion(version, change_log): + if askUser(f'有新版本:{version}是否更新?\n\n{change_log.strip()}'): openLink('https://github.com/megachweng/Dict2Anki/releases') self.versionCheckingThread = Version(__VERSION__) @@ -232,13 +232,40 @@ def addNote(self, words): 'BrEPhonetic': self.ui.BrEPhoneticCheckBox.isChecked(), 'AmEPhonetic': self.ui.AmEPhoneticCheckBox.isChecked(), } + audios = [] for word in words: self.log(f'添加卡片:{word["term"]}') - note = cardManager.processNote(word, options) + note, BrEPron, AmEPron = cardManager.processNote(word, options) mw.col.addNote(note) + for pron in [BrEPron, AmEPron]: + if pron[1]: # 只下载有发音的单词 + audios.append(pron) mw.app.processEvents() mw.col.reset() mw.reset() - self.ui.startSyncBtn.setEnabled(True) tooltip(f'添加{len(words)}个笔记') + + if audios: + self.log('下载发音') + self.downloadAudio(audios) + else: + self.ui.startSyncBtn.setEnabled(True) + + def downloadAudio(self, audios): + def done(): + for _, t in self.threadList: + t.terminate() + self.ui.startSyncBtn.setEnabled(True) + tooltip(f'发音下载完成!') + + downloadThread = QThread() + downloadWorker = api.AudioDownloader(audios) + self.threadList.append((downloadWorker, downloadThread)) + downloadWorker.SIG.progress.connect(self.updateProgress) + downloadWorker.SIG.totalTasks.connect(self.ui.progressBar.setMaximum) + downloadWorker.SIG.log.connect(self.log) + downloadWorker.moveToThread(downloadThread) + downloadThread.started.connect(downloadWorker.run) + downloadThread.start() + downloadWorker.SIG.downloadFinished.connect(done) diff --git a/src/api.py b/src/api.py index 167a21a..76e72cb 100644 --- a/src/api.py +++ b/src/api.py @@ -4,7 +4,7 @@ from PyQt5.QtCore import QObject, pyqtSlot from .pool import ThreadPool -from .signals import APISIG +from .signals import APISIG, AudioDownloaderSIG class YoudaoParser: @@ -103,3 +103,36 @@ def run(self): TP.add_task(self.query, word) queryResults = TP.wait_complete() self.SIG.wordsReady.emit(queryResults) + + +class AudioDownloader(QObject): + timeout = 15 + s = requests.Session() + + def __init__(self, audios): + super().__init__() + self.SIG = AudioDownloaderSIG() + self.audios = audios + self.SIG.log.emit(f'待下载任务{audios}') + + def _download(self, file_name, url): + try: + r = self.s.get(url, stream=True) + with open(f'{file_name}.mp3', 'wb') as f: + for chunk in r.iter_content(chunk_size=1024): + if chunk: + f.write(chunk) + self.SIG.log.emit(f'{file_name} 下载完成') + except Exception as e: + self.SIG.log.emit(f'下载{file_name}:{url}异常: {e}') + finally: + self.SIG.progress.emit() + + @pyqtSlot() + def run(self): + self.SIG.totalTasks.emit(len(self.audios)) + TP = ThreadPool(2) + for file_name, url in self.audios: + TP.add_task(self._download, file_name, url) + TP.wait_complete() + self.SIG.downloadFinished.emit() diff --git a/src/cardManager.py b/src/cardManager.py index bdeb610..fb96c84 100644 --- a/src/cardManager.py +++ b/src/cardManager.py @@ -35,7 +35,7 @@ def createDeck(deckName, modelName): mw.col.models.save(model) -def processNote(term, options): +def processNote(term, options) -> (object, str, str): note = mw.col.newNote() note["term"] = term["term"].strip() note["image"] = (term["image"] or '') if options['image'] else '' @@ -45,13 +45,17 @@ def processNote(term, options): note["AmEPhonetic"] = (term["pronunciations"]['us_phonetic'] or '') if options["AmEPhonetic"] else '' note["definitions"] = ' '.join(term['definitions']) note["samples"] = f'''''' if options['samples'] else '' - return note + note["pron"] = f'[sound:bre_{term["term"]}.mp3] [sound:ame_{term["term"]}.mp3]' + return note, (f'bre_{term["term"]}', note["BrEPron"]), (f'ame_{term["term"]}', note["AmEPron"]) def __createModel(modelName): md = mw.col.models existing = md.byName(modelName) if existing: + if 'pron' not in md.fieldNames(existing): + md.addField(existing, md.newField('pron')) + md.update(existing) return existing m = md.new(modelName) @@ -64,6 +68,7 @@ def __createModel(modelName): md.addField(m, md.newField("BrEPhonetic")) md.addField(m, md.newField("AmEPhonetic")) md.addField(m, md.newField("samples")) + md.addField(m, md.newField("pron")) t = md.newTemplate("Normal") @@ -79,6 +84,7 @@ def __createModel(modelName):
{{samples}} + {{pron}} ''' t['afmt'] = ''' {{term}}
@@ -96,7 +102,7 @@ def __createModel(modelName): .card { font-family: arial; font-size: 20px; - text-align: right; + text-align: left; color: black; background-color: white; } diff --git a/src/notifier.py b/src/notifier.py index 13da7ee..9a1018d 100644 --- a/src/notifier.py +++ b/src/notifier.py @@ -3,7 +3,7 @@ class Version(QThread): - hasNewVersion = pyqtSignal(object) + hasNewVersion = pyqtSignal(object, object) log = pyqtSignal(str) url = 'https://api.github.com/repos/megachweng/Dict2Anki/releases/latest' @@ -16,8 +16,9 @@ def run(self): self.log.emit('检查新版本') rsp = requests.get(self.url, timeout=10) version = rsp.json()['tag_name'] + change_log = rsp.json()['body'] if self.currentVersion.startswith('v') and version != self.currentVersion: - self.hasNewVersion.emit(version) + self.hasNewVersion.emit(version, change_log) else: self.log.emit(f'当前为最新版本:{self.currentVersion}') except Exception as e: diff --git a/src/signals.py b/src/signals.py index d399d1a..5a9be01 100644 --- a/src/signals.py +++ b/src/signals.py @@ -17,3 +17,10 @@ class APISIG(QObject): totalTasks = pyqtSignal(int) log = pyqtSignal(str) + +class AudioDownloaderSIG(QObject): + exceptionOccurred = pyqtSignal(object) + downloadFinished = pyqtSignal() + progress = pyqtSignal() + totalTasks = pyqtSignal(int) + log = pyqtSignal(str)