From 2662f20c096de0e2ce242e3bc11c2213165860e7 Mon Sep 17 00:00:00 2001 From: Alex Yatskov Date: Sun, 15 Feb 2015 15:03:46 +0900 Subject: [PATCH] Improved update checking Former-commit-id: 66d9959e9190f49c4d1bbc38261e847c846cae59 --- build_ui.sh | 1 + ui/updates.ui | 84 +++++++++++++++++++++++++++++++++ yomi_base/gen/about_ui.py | 2 +- yomi_base/gen/preferences_ui.py | 2 +- yomi_base/gen/reader_ui.py | 2 +- yomi_base/gen/resources_rc.py | 2 +- yomi_base/gen/updates_ui.py | 58 +++++++++++++++++++++++ yomi_base/reader.py | 20 ++++---- yomi_base/update.py | 40 ---------------- yomi_base/updates.py | 72 ++++++++++++++++++++++++++++ 10 files changed, 227 insertions(+), 56 deletions(-) create mode 100644 ui/updates.ui create mode 100644 yomi_base/gen/updates_ui.py delete mode 100644 yomi_base/update.py create mode 100644 yomi_base/updates.py diff --git a/build_ui.sh b/build_ui.sh index ad2085a..5830f81 100755 --- a/build_ui.sh +++ b/build_ui.sh @@ -2,4 +2,5 @@ pyuic4 ui/about.ui -o yomi_base/gen/about_ui.py pyuic4 ui/preferences.ui -o yomi_base/gen/preferences_ui.py pyuic4 ui/reader.ui -o yomi_base/gen/reader_ui.py +pyuic4 ui/updates.ui -o yomi_base/gen/updates_ui.py pyrcc4 ui/resources.qrc -o yomi_base/gen/resources_rc.py diff --git a/ui/updates.ui b/ui/updates.ui new file mode 100644 index 0000000..ca6b713 --- /dev/null +++ b/ui/updates.ui @@ -0,0 +1,84 @@ + + + DialogUpdates + + + + 0 + 0 + 500 + 400 + + + + Update Checker + + + + + + <p>A new version of Yomichan is available for download!</p> + +<p>You can download this update (version {0} to version {1}) from the add-ons section on <a href="https://ankiweb.net/shared/info/934748696">Anki Online</a> or directly from the <a href="http://foosoft.net/projects/yomichan">Yomichan homepage</a>.</p> + +<p>Changes from your version are listed below:</p> + + + true + + + true + + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Ok + + + + + + + + + buttonBox + accepted() + DialogUpdates + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + DialogUpdates + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/yomi_base/gen/about_ui.py b/yomi_base/gen/about_ui.py index c38e8fb..fed169d 100644 --- a/yomi_base/gen/about_ui.py +++ b/yomi_base/gen/about_ui.py @@ -2,7 +2,7 @@ # Form implementation generated from reading ui file 'ui/about.ui' # -# Created: Sun Feb 15 13:27:51 2015 +# Created: Sun Feb 15 15:01:20 2015 # by: PyQt4 UI code generator 4.10.4 # # WARNING! All changes made in this file will be lost! diff --git a/yomi_base/gen/preferences_ui.py b/yomi_base/gen/preferences_ui.py index 0bfcf62..47c41e1 100644 --- a/yomi_base/gen/preferences_ui.py +++ b/yomi_base/gen/preferences_ui.py @@ -2,7 +2,7 @@ # Form implementation generated from reading ui file 'ui/preferences.ui' # -# Created: Sun Feb 15 13:27:51 2015 +# Created: Sun Feb 15 15:01:20 2015 # by: PyQt4 UI code generator 4.10.4 # # WARNING! All changes made in this file will be lost! diff --git a/yomi_base/gen/reader_ui.py b/yomi_base/gen/reader_ui.py index 674188c..92c6c9c 100644 --- a/yomi_base/gen/reader_ui.py +++ b/yomi_base/gen/reader_ui.py @@ -2,7 +2,7 @@ # Form implementation generated from reading ui file 'ui/reader.ui' # -# Created: Sun Feb 15 13:27:51 2015 +# Created: Sun Feb 15 15:01:20 2015 # by: PyQt4 UI code generator 4.10.4 # # WARNING! All changes made in this file will be lost! diff --git a/yomi_base/gen/resources_rc.py b/yomi_base/gen/resources_rc.py index ff42cb6..1853ca5 100644 --- a/yomi_base/gen/resources_rc.py +++ b/yomi_base/gen/resources_rc.py @@ -2,7 +2,7 @@ # Resource object code # -# Created: Sun Feb 15 13:27:51 2015 +# Created: Sun Feb 15 15:01:20 2015 # by: The Resource Compiler for PyQt (Qt v4.8.6) # # WARNING! All changes made in this file will be lost! diff --git a/yomi_base/gen/updates_ui.py b/yomi_base/gen/updates_ui.py new file mode 100644 index 0000000..b01c08f --- /dev/null +++ b/yomi_base/gen/updates_ui.py @@ -0,0 +1,58 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file 'ui/updates.ui' +# +# Created: Sun Feb 15 15:01:20 2015 +# by: PyQt4 UI code generator 4.10.4 +# +# WARNING! All changes made in this file will be lost! + +from PyQt4 import QtCore, QtGui + +try: + _fromUtf8 = QtCore.QString.fromUtf8 +except AttributeError: + def _fromUtf8(s): + return s + +try: + _encoding = QtGui.QApplication.UnicodeUTF8 + def _translate(context, text, disambig): + return QtGui.QApplication.translate(context, text, disambig, _encoding) +except AttributeError: + def _translate(context, text, disambig): + return QtGui.QApplication.translate(context, text, disambig) + +class Ui_DialogUpdates(object): + def setupUi(self, DialogUpdates): + DialogUpdates.setObjectName(_fromUtf8("DialogUpdates")) + DialogUpdates.resize(500, 400) + self.verticalLayout = QtGui.QVBoxLayout(DialogUpdates) + self.verticalLayout.setObjectName(_fromUtf8("verticalLayout")) + self.labelUpdates = QtGui.QLabel(DialogUpdates) + self.labelUpdates.setWordWrap(True) + self.labelUpdates.setOpenExternalLinks(True) + self.labelUpdates.setObjectName(_fromUtf8("labelUpdates")) + self.verticalLayout.addWidget(self.labelUpdates) + self.textBrowser = QtGui.QTextBrowser(DialogUpdates) + self.textBrowser.setObjectName(_fromUtf8("textBrowser")) + self.verticalLayout.addWidget(self.textBrowser) + self.buttonBox = QtGui.QDialogButtonBox(DialogUpdates) + self.buttonBox.setOrientation(QtCore.Qt.Horizontal) + self.buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Ok) + self.buttonBox.setObjectName(_fromUtf8("buttonBox")) + self.verticalLayout.addWidget(self.buttonBox) + + self.retranslateUi(DialogUpdates) + QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(_fromUtf8("accepted()")), DialogUpdates.accept) + QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(_fromUtf8("rejected()")), DialogUpdates.reject) + QtCore.QMetaObject.connectSlotsByName(DialogUpdates) + + def retranslateUi(self, DialogUpdates): + DialogUpdates.setWindowTitle(_translate("DialogUpdates", "Update Checker", None)) + self.labelUpdates.setText(_translate("DialogUpdates", "

A new version of Yomichan is available for download!

\n" +"\n" +"

You can download this update (version {0} to version {1}) from the add-ons section on Anki Online or directly from the Yomichan homepage.

\n" +"\n" +"

Changes from your version are listed below:

", None)) + diff --git a/yomi_base/reader.py b/yomi_base/reader.py index fa8a9f3..1743988 100644 --- a/yomi_base/reader.py +++ b/yomi_base/reader.py @@ -24,7 +24,7 @@ import japanese.util import os import preferences import reader_util -import update +import updates class MainWindowReader(QtGui.QMainWindow, gen.reader_ui.Ui_MainWindowReader): @@ -52,7 +52,7 @@ class MainWindowReader(QtGui.QMainWindow, gen.reader_ui.Ui_MainWindowReader): self.language = language self.preferences = preferences self.state = self.State() - self.updater = update.UpdateFinder() + self.updates = updates.UpdateFinder() self.zoom = 0 self.applyPreferences() @@ -90,10 +90,10 @@ class MainWindowReader(QtGui.QMainWindow, gen.reader_ui.Ui_MainWindowReader): self.textKanjiSearch.returnPressed.connect(self.onKanjiDefSearchReturn) self.textVocabDefs.anchorClicked.connect(self.onVocabDefsAnchorClicked) self.textVocabSearch.returnPressed.connect(self.onVocabDefSearchReturn) - self.updater.updateResult.connect(self.onUpdaterSearchResult) + self.updates.updateResult.connect(self.onUpdaterSearchResult) if self.preferences['checkForUpdates']: - self.updater.start() + self.updates.start() def applyPreferences(self): @@ -323,14 +323,10 @@ class MainWindowReader(QtGui.QMainWindow, gen.reader_ui.Ui_MainWindowReader): self.actionToggleKanji.setChecked(self.dockKanji.isVisible()) - def onUpdaterSearchResult(self, result): - if result and unicode(result) > constants.c['appVersion']: - QtGui.QMessageBox.information( - self, - 'Yomichan', - 'A new version of Yomichan is available for download!\n\nYou can download this update ({0} > {1}) ' \ - 'from "Shared Plugins" in Anki or directly from the Yomichan homepage.'.format(constants.c['appVersion'], result) - ) + def onUpdaterSearchResult(self, versions): + if versions['latest'] > constants.c['appVersion']: + dialog = updates.DialogUpdates(self, versions) + dialog.exec_() def onContentMouseMove(self, event): diff --git a/yomi_base/update.py b/yomi_base/update.py deleted file mode 100644 index 1fc333f..0000000 --- a/yomi_base/update.py +++ /dev/null @@ -1,40 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright (C) 2013 Alex Yatskov -# -# 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 3 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, see . - - -from PyQt4 import QtCore -from xml.dom import minidom -import constants -import urllib2 - - -class UpdateFinder(QtCore.QThread): - updateResult = QtCore.pyqtSignal(str) - - def run(self): - latest = None - try: - fp = urllib2.urlopen('http://foosoft.net/pub/projects/yomichan/updates.xml') - data = fp.read() - doc = minidom.parseString(data) - root = doc.documentElement - if root.nodeName == 'updates': - latest = root.getAttribute('latest') or None - except: - pass - finally: - self.updateResult.emit(latest or constants.c['appVersion']) diff --git a/yomi_base/updates.py b/yomi_base/updates.py new file mode 100644 index 0000000..ac16a81 --- /dev/null +++ b/yomi_base/updates.py @@ -0,0 +1,72 @@ +# -*- coding: utf-8 -*- + +# Copyright (C) 2013 Alex Yatskov +# +# 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 3 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, see . + + +from PyQt4 import QtCore, QtGui +import constants +import gen.updates_ui +import json +import urllib2 + + +class DialogUpdates(QtGui.QDialog, gen.updates_ui.Ui_DialogUpdates): + def __init__(self, parent, versions): + QtGui.QDialog.__init__(self, parent) + self.setupUi(self) + + self.updateHtml(versions) + self.labelUpdates.setText( + unicode(self.labelUpdates.text()).format( + constants.c['appVersion'], + versions['latest'] + ) + ) + + + def updateHtml(self, versions): + html = '' + + for update in versions['updates']: + version = update.get('version') + if version > constants.c['appVersion']: + html += 'Version {0}'.format(version) + html += '
    ' + for feature in update['features']: + html += '
  • {0}
  • '.format(feature) + html += '
' + + self.textBrowser.setHtml(html) + + +class UpdateFinder(QtCore.QThread): + updateResult = QtCore.pyqtSignal(dict) + + def run(self): + latest = constants.c['appVersion'] + updates = list() + + try: + fp = urllib2.urlopen('http://foosoft.net/projects/yomichan/index/updates.json') + updates = json.loads(fp.read()) + fp.close() + + for update in updates: + latest = max(latest, update.get('version')) + except: + pass + finally: + self.updateResult.emit({ 'latest': latest, 'updates': updates })