add a reset button in the settings dialog
This commit is contained in:
parent
2358cc247f
commit
a3f3d8eb95
@ -19,16 +19,17 @@
|
||||
|
||||
import json
|
||||
import os
|
||||
from aqt import mw
|
||||
|
||||
from anki.hooks import runHook
|
||||
from aqt import mw
|
||||
|
||||
from .constants import VERSION
|
||||
from .utils import get_icon
|
||||
|
||||
|
||||
__all__ = ['APP_ICON', 'config']
|
||||
|
||||
|
||||
APP_ICON = get_icon('wqicon.png') #Addon Icon
|
||||
APP_ICON = get_icon('wqicon.png') # Addon Icon
|
||||
|
||||
|
||||
class Config(object):
|
||||
@ -37,7 +38,7 @@ class Config(object):
|
||||
Addon Config
|
||||
"""
|
||||
|
||||
_CONFIG_FILENAME = 'fastwqcfg.json' #Config File Path
|
||||
_CONFIG_FILENAME = 'fastwqcfg.json' # Config File Path
|
||||
|
||||
def __init__(self, window):
|
||||
self.path = u'_' + self._CONFIG_FILENAME
|
||||
@ -122,7 +123,7 @@ class Config(object):
|
||||
@property
|
||||
def last_folder(self):
|
||||
"""
|
||||
last file dialog open path
|
||||
last file dialog open path
|
||||
"""
|
||||
return self.data.get('last_folder', '')
|
||||
|
||||
@ -131,15 +132,12 @@ class Config(object):
|
||||
'''ignore accents of field in querying'''
|
||||
return self.data.get('ignore_accents', False)
|
||||
|
||||
@property
|
||||
def auto_update(self):
|
||||
'''auto check new version'''
|
||||
return self.data.get('auto_update', True)
|
||||
|
||||
@property
|
||||
def cloze_str(self):
|
||||
'''cloze formater string'''
|
||||
return self.data.get('cloze_str', '{{c1::%s}}')
|
||||
|
||||
tmpstr = self.data.get('cloze_str', '{{c1::%s}}')
|
||||
if len(tmpstr.split('%s')) != 2:
|
||||
tmpstr = '{{c1::%s}}'
|
||||
return tmpstr
|
||||
|
||||
config = Config(mw)
|
||||
|
||||
@ -18,38 +18,22 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import types
|
||||
|
||||
from aqt import mw
|
||||
from aqt.qt import *
|
||||
from aqt.utils import showInfo
|
||||
from .options import OptionsDialog
|
||||
from .foldermanager import FoldersManageDialog
|
||||
from .dictmanager import DictManageDialog
|
||||
from ..libs import ankihub
|
||||
|
||||
from ..constants import Template
|
||||
from ..context import config
|
||||
from ..lang import _
|
||||
from ..constants import Endpoint, Template
|
||||
from ..service import service_manager, service_pool
|
||||
from .dictmanager import DictManageDialog
|
||||
from .foldermanager import FoldersManageDialog
|
||||
from .options import OptionsDialog
|
||||
|
||||
__all__ = ['show_options', 'show_fm_dialog', 'show_about_dialog']
|
||||
|
||||
|
||||
__all__ = ['show_options', 'show_fm_dialog', 'show_about_dialog'] #'check_updates',
|
||||
|
||||
|
||||
# def check_updates(background=False, parent=None):
|
||||
# '''check add-on last version'''
|
||||
# try:
|
||||
# parent = mw if parent is None else parent
|
||||
# state = ankihub.update([Endpoint.check_version], Endpoint.version, background, parent)
|
||||
# if not background:
|
||||
# if state == 0:
|
||||
# showInfo(_('LATEST_VERSION'))
|
||||
# elif state == -1:
|
||||
# showInfo(_('CHECK_FAILURE'))
|
||||
# except:
|
||||
# if not background:
|
||||
# showInfo(_('CHECK_FAILURE'))
|
||||
|
||||
|
||||
def show_fm_dialog(browser = None):
|
||||
def show_fm_dialog(browser=None):
|
||||
'''open dictionary folder manager window'''
|
||||
parent = mw if browser is None else browser
|
||||
fm_dialog = FoldersManageDialog(parent, u'Dictionary Folder Manager')
|
||||
@ -64,7 +48,7 @@ def show_fm_dialog(browser = None):
|
||||
show_options(browser)
|
||||
|
||||
|
||||
def show_dm_dialog(browser = None):
|
||||
def show_dm_dialog(browser=None):
|
||||
parent = mw if browser is None else browser
|
||||
dm_dialog = DictManageDialog(parent, u'Dictionary Manager')
|
||||
dm_dialog.activateWindow()
|
||||
@ -78,7 +62,7 @@ def show_dm_dialog(browser = None):
|
||||
show_options(browser)
|
||||
|
||||
|
||||
def show_options(browser = None, model_id = -1, callback = None, *args, **kwargs):
|
||||
def show_options(browser=None, model_id=-1, callback=None, *args, **kwargs):
|
||||
'''open options window'''
|
||||
parent = mw if browser is None else browser
|
||||
config.read()
|
||||
|
||||
@ -18,10 +18,10 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from aqt.qt import *
|
||||
from .base import Dialog, WIDGET_SIZE
|
||||
|
||||
from ..context import config
|
||||
from ..lang import _
|
||||
|
||||
from .base import WIDGET_SIZE, Dialog
|
||||
|
||||
__all__ = ['SettingDialog']
|
||||
|
||||
@ -36,7 +36,6 @@ class SettingDialog(Dialog):
|
||||
self.setFixedWidth(400)
|
||||
self.check_force_update = None
|
||||
self.check_ignore_accents = None
|
||||
# self.check_auto_update = None
|
||||
self.input_thread_number = None
|
||||
self.build()
|
||||
|
||||
@ -53,11 +52,6 @@ class SettingDialog(Dialog):
|
||||
layout.addWidget(check_ignore_accents)
|
||||
layout.addSpacing(10)
|
||||
|
||||
# check_auto_update = QCheckBox(_("AUTO_UPDATE"))
|
||||
# check_auto_update.setChecked(config.auto_update)
|
||||
# layout.addWidget(check_auto_update)
|
||||
# layout.addSpacing(10)
|
||||
|
||||
check_ighore_mdx_wordcase = QCheckBox(_("IGNORE_MDX_WORDCASE"))
|
||||
check_ighore_mdx_wordcase.setChecked(config.ignore_mdx_wordcase)
|
||||
layout.addWidget(check_ighore_mdx_wordcase)
|
||||
@ -84,16 +78,23 @@ class SettingDialog(Dialog):
|
||||
hbox.setStretchFactor(input_cloze_str, 2)
|
||||
layout.addLayout(hbox)
|
||||
|
||||
buttonBox = QDialogButtonBox(parent=self)
|
||||
buttonBox.setStandardButtons(QDialogButtonBox.Ok)
|
||||
buttonBox.accepted.connect(self.accept) # 确定
|
||||
hbox = QHBoxLayout()
|
||||
okbtn = QDialogButtonBox(parent=self)
|
||||
okbtn.setStandardButtons(QDialogButtonBox.Ok)
|
||||
okbtn.clicked.connect(self.accept)
|
||||
resetbtn = QDialogButtonBox(parent=self)
|
||||
resetbtn.setStandardButtons(QDialogButtonBox.Reset)
|
||||
resetbtn.clicked.connect(self.reset)
|
||||
hbox.setAlignment(Qt.AlignRight)
|
||||
hbox.addSpacing(300)
|
||||
hbox.addWidget(resetbtn)
|
||||
hbox.addWidget(okbtn)
|
||||
|
||||
layout.addSpacing(48)
|
||||
layout.addWidget(buttonBox)
|
||||
layout.addLayout(hbox)
|
||||
|
||||
self.check_force_update = check_force_update
|
||||
self.check_ignore_accents = check_ignore_accents
|
||||
# self.check_auto_update = check_auto_update
|
||||
self.check_ighore_mdx_wordcase = check_ighore_mdx_wordcase
|
||||
self.input_thread_number = input_thread_number
|
||||
self.input_cloze_str = input_cloze_str
|
||||
@ -105,14 +106,27 @@ class SettingDialog(Dialog):
|
||||
self.save()
|
||||
super(SettingDialog, self).accept()
|
||||
|
||||
def reset(self):
|
||||
data = {
|
||||
'force_update': False,
|
||||
'ignore_accents': False,
|
||||
'ignore_mdx_wordcase': False,
|
||||
'thread_number': 16,
|
||||
'cloze_str': '{{c1::%s}}'
|
||||
}
|
||||
config.update(data)
|
||||
self.check_force_update.setChecked(config.force_update)
|
||||
self.check_ignore_accents.setChecked(config.ignore_accents)
|
||||
self.check_ighore_mdx_wordcase.setChecked(config.ignore_mdx_wordcase)
|
||||
self.input_thread_number.setValue(config.thread_number)
|
||||
self.input_cloze_str.setText(config.cloze_str)
|
||||
|
||||
def save(self):
|
||||
data = {
|
||||
'force_update': self.check_force_update.isChecked(),
|
||||
'ignore_accents': self.check_ignore_accents.isChecked(),
|
||||
# 'auto_update': self.check_auto_update.isChecked(),
|
||||
'ignore_mdx_wordcase': self.check_ighore_mdx_wordcase.isChecked(),
|
||||
'thread_number': self.input_thread_number.value(),
|
||||
'cloze_str': self.input_cloze_str.text()
|
||||
}
|
||||
config.update(data)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,48 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from aqt.qt import *
|
||||
|
||||
try:
|
||||
_encoding = QApplication.UnicodeUTF8
|
||||
def _translate(context, text, disambig):
|
||||
return QApplication.translate(context, text, disambig, _encoding)
|
||||
except AttributeError:
|
||||
def _translate(context, text, disambig):
|
||||
return QApplication.translate(context, text, disambig)
|
||||
|
||||
class Ui_DialogUpdates(object):
|
||||
def setupUi(self, DialogUpdates):
|
||||
DialogUpdates.setObjectName(u"DialogUpdates")
|
||||
DialogUpdates.resize(500, 400)
|
||||
self.verticalLayout = QVBoxLayout(DialogUpdates)
|
||||
self.verticalLayout.setObjectName(u"verticalLayout")
|
||||
self.labelUpdates = QLabel(DialogUpdates)
|
||||
self.labelUpdates.setWordWrap(True)
|
||||
self.labelUpdates.setOpenExternalLinks(True)
|
||||
self.labelUpdates.setObjectName(u"labelUpdates")
|
||||
self.verticalLayout.addWidget(self.labelUpdates)
|
||||
self.textBrowser = QTextBrowser(DialogUpdates)
|
||||
self.textBrowser.setObjectName(u"textBrowser")
|
||||
self.verticalLayout.addWidget(self.textBrowser)
|
||||
self.horizontalLayout = QHBoxLayout()
|
||||
self.horizontalLayout.setObjectName(u"horizontalLayout")
|
||||
self.update = QPushButton(DialogUpdates)
|
||||
self.update.setObjectName(u"update")
|
||||
self.horizontalLayout.addWidget(self.update, 0, Qt.AlignCenter)
|
||||
self.verticalLayout.addLayout(self.horizontalLayout)
|
||||
|
||||
self.retranslateUi(DialogUpdates)
|
||||
QMetaObject.connectSlotsByName(DialogUpdates)
|
||||
|
||||
def retranslateUi(self, DialogUpdates):
|
||||
DialogUpdates.setWindowTitle(_translate("DialogUpdates", "FastWQ - Updater", None))
|
||||
self.labelUpdates.setText(_translate(
|
||||
"DialogUpdates",
|
||||
"<html><head/><body>\
|
||||
<p>A new version of {0} is available for download! </p>\
|
||||
<p>Do you want to update {1}to version {2}?</p>\
|
||||
<p>Changes from your version are listed below:</p>\
|
||||
</body></html>",
|
||||
None
|
||||
))
|
||||
self.update.setText(_translate("DialogUpdates", "Update", None))
|
||||
@ -1,311 +0,0 @@
|
||||
try:
|
||||
import httplib
|
||||
except:
|
||||
import http.client as httplib
|
||||
try:
|
||||
import urllib2
|
||||
except:
|
||||
import urllib.request as urllib2
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
import zipfile
|
||||
import traceback
|
||||
import io
|
||||
import aqt
|
||||
from aqt import mw
|
||||
from aqt.qt import *
|
||||
from aqt.utils import showInfo
|
||||
from anki.hooks import addHook
|
||||
from anki.utils import isMac, isWin
|
||||
from ..context import APP_ICON
|
||||
from .AnkiHub.updates import Ui_DialogUpdates
|
||||
from .AnkiHub.markdown2 import markdown
|
||||
|
||||
|
||||
__all__ = ['update']
|
||||
|
||||
|
||||
# taken from Anki's aqt/profiles.py
|
||||
def defaultBase():
|
||||
path = mw.pm.addonFolder()
|
||||
return os.path.dirname(os.path.abspath(path))
|
||||
|
||||
|
||||
headers = {"User-Agent": "AnkiHub"}
|
||||
dataPath = os.path.join(defaultBase(),'.fastwq_2.1.x_ankihub.json')
|
||||
|
||||
|
||||
class DialogUpdates(QDialog, Ui_DialogUpdates):
|
||||
|
||||
def __init__(self, parent, data, oldData, callback):
|
||||
parent = parent if parent else mw
|
||||
QDialog.__init__(self, parent)
|
||||
self.setModal(True)
|
||||
self.setWindowFlags(
|
||||
self.windowFlags() &
|
||||
~Qt.WindowContextHelpButtonHint
|
||||
)
|
||||
self.setWindowIcon(APP_ICON)
|
||||
self.setupUi(self)
|
||||
totalSize = sum(map(lambda x:x['size'],data['assets']))
|
||||
def answer():
|
||||
self.update.setEnabled(False)
|
||||
callback(self.appendHtml, self.finish)
|
||||
|
||||
self.html = u''
|
||||
self.appendHtml(markdown(data['body']))
|
||||
|
||||
#if not automaticAnswer:
|
||||
self.update.clicked.connect(lambda:answer())
|
||||
|
||||
fromVersion = ''
|
||||
if 'tag_name' in oldData:
|
||||
fromVersion = u'from {0} '.format(oldData['tag_name'])
|
||||
self.labelUpdates.setText(
|
||||
str(self.labelUpdates.text()).format(
|
||||
data['name'],
|
||||
fromVersion,
|
||||
data['tag_name']))
|
||||
|
||||
def appendHtml(self,html='',temp=''):
|
||||
self.html += html
|
||||
self.textBrowser.setHtml(u'<html><body>{0}{1}{2}</body></html>'.format(self.html, temp, u'<div id="text_bottom"></div>'))
|
||||
self.textBrowser.scrollToAnchor('text_bottom')
|
||||
|
||||
def finish(self):
|
||||
self.hide()
|
||||
self.destroy()
|
||||
showInfo('Updated. Please restart Anki.')
|
||||
pass
|
||||
|
||||
|
||||
def installZipFile(data, fname):
|
||||
#base = os.path.join(mw.pm.addonFolder(), 'fastwq')
|
||||
base = os.path.realpath(os.path.join(os.path.dirname(os.path.realpath(__file__)), '../'))
|
||||
if fname.endswith(".py"):
|
||||
path = os.path.join(base, fname)
|
||||
with open(path, "wb") as file:
|
||||
file.write(data)
|
||||
file.close()
|
||||
return True
|
||||
# .zip file
|
||||
try:
|
||||
z = zipfile.ZipFile(io.BytesIO(data))
|
||||
except zipfile.BadZipfile:
|
||||
return False
|
||||
for n in z.namelist():
|
||||
if n.endswith("/"):
|
||||
# folder; ignore
|
||||
continue
|
||||
# write
|
||||
try:
|
||||
z.extract(n, base)
|
||||
except:
|
||||
print(n)
|
||||
return True
|
||||
|
||||
|
||||
def asset(a):
|
||||
return {
|
||||
'url': a['browser_download_url'],
|
||||
'size': a['size']
|
||||
}
|
||||
|
||||
|
||||
def updateSingle(repositories, path, data):
|
||||
def callback(appendHtml, onReady):
|
||||
for asset in data['assets']:
|
||||
code = asset['url']
|
||||
p, fname = os.path.split(code)
|
||||
appendHtml(temp='<br />Downloading {1}: {0}%<br/>'.format(0,fname))
|
||||
try:
|
||||
urlthread = UrlThread(code)
|
||||
urlthread.start()
|
||||
urlthread.join()
|
||||
response = urlthread.response#urllib2.urlopen(code)
|
||||
meta = response.info()
|
||||
file_size = int(meta.get("Content-Length"))
|
||||
except:
|
||||
appendHtml('Downloading file error!<br/>')
|
||||
return
|
||||
d = b''
|
||||
dl = 0
|
||||
i = 0
|
||||
lastPercent = None
|
||||
while True:
|
||||
dkb = response.read(1024)
|
||||
if not dkb:
|
||||
break
|
||||
dl += len(dkb)
|
||||
d += dkb
|
||||
if dl*100/file_size>i:
|
||||
lastPercent = int(dl*100/file_size)
|
||||
i = lastPercent+1
|
||||
appendHtml(temp='<br />Downloading {1}: {0}%<br/>'.format(lastPercent,fname))
|
||||
QApplication.instance().processEvents()
|
||||
appendHtml('<br />Downloading {1}: 100%<br/>'.format(int(dl*100/file_size),fname))
|
||||
appendHtml('Installing ...<br/>')
|
||||
if not installZipFile(d, fname):
|
||||
appendHtml('Corrupt file<br/>')
|
||||
else:
|
||||
repositories[path] = data
|
||||
repositories[path]['update'] = 'ask'
|
||||
with open(dataPath,'w') as f:
|
||||
json.dump(repositories,f,indent=2)
|
||||
f.close()
|
||||
appendHtml('Done.<br/>')
|
||||
onReady() # close the AnkiHub update window
|
||||
|
||||
return callback
|
||||
|
||||
|
||||
def update(add=[], VERSION='v0.0.0', background=False, parent=None):
|
||||
parent = parent if parent else mw
|
||||
# progress win
|
||||
if not background:
|
||||
progresswin = QProgressDialog('Update Checking...', '', 0, 0, parent)
|
||||
progresswin.setWindowModality(Qt.ApplicationModal)
|
||||
progresswin.setCancelButton(None)
|
||||
progresswin.setWindowFlags(
|
||||
progresswin.windowFlags() &
|
||||
~Qt.WindowContextHelpButtonHint
|
||||
)
|
||||
progresswin.setWindowTitle('FastWQ - Updater')
|
||||
progresswin.setWindowIcon(APP_ICON)
|
||||
progresswin.resize(280, 60)
|
||||
progresswin.show()
|
||||
else:
|
||||
progresswin = None
|
||||
#
|
||||
conn = httplib.HTTPSConnection("api.github.com")
|
||||
try:
|
||||
with open(dataPath,'r') as f:
|
||||
repositories = json.load(f)
|
||||
f.close()
|
||||
except:
|
||||
repositories = {}
|
||||
|
||||
for a in add:
|
||||
if a not in repositories:
|
||||
repositories[a] = {
|
||||
'id': 0,
|
||||
'update': 'ask'
|
||||
}
|
||||
|
||||
for path,repository in repositories.items():
|
||||
username,repositoryName = path.split('/')
|
||||
try:
|
||||
urlthread = UrlThread("https://api.github.com/repos/{0}/releases/latest".format(path))
|
||||
urlthread.start()
|
||||
urlthread.join()
|
||||
release = json.loads(urlthread.response.read())
|
||||
except Exception as e:
|
||||
release = {}
|
||||
|
||||
if 'id' in release:
|
||||
if release['id'] != repository['id']:
|
||||
data = {
|
||||
'id': release['id'],
|
||||
'name': repositoryName,
|
||||
'tag_name': release['tag_name'],
|
||||
'body': '### {0}\n'.format(release['name']) + release['body'],
|
||||
'assets': [asset(release['assets'][1])],
|
||||
'update': 'ask'
|
||||
}
|
||||
if 'tag_name' in repository:
|
||||
oldVersion = map(int,repository['tag_name'][1:].split('.'))
|
||||
oldVersion = [x for x in oldVersion]
|
||||
while len(oldVersion)<3:
|
||||
oldVersion.append(0)
|
||||
else:
|
||||
oldVersion = map(int,VERSION[1:].split('.'))#[0,0,0]
|
||||
oldVersion = [x for x in oldVersion]
|
||||
newVersion = map(int,data['tag_name'][1:].split('.'))
|
||||
newVersion = [x for x in newVersion]
|
||||
isMinor = len(newVersion)>2 and newVersion[2]>0
|
||||
while len(newVersion)<3:
|
||||
newVersion.append(0)
|
||||
i = oldVersion[2]+1
|
||||
if oldVersion[0]<newVersion[0] or oldVersion[1]<newVersion[1]:
|
||||
if isMinor:
|
||||
i = 1
|
||||
while i<newVersion[2]:
|
||||
if progresswin and progresswin.wasCanceled():
|
||||
break
|
||||
try:
|
||||
minorTagName = 'v{0}.{1}.{2}'.format(newVersion[0],oldVersion[1],i)
|
||||
urlthread = UrlThread("https://api.github.com/repos/{0}/releases/tags/{1}".format(path,minorTagName))
|
||||
urlthread.start()
|
||||
urlthread.join()
|
||||
responseData = urlthread.response.read()
|
||||
minor = json.loads(responseData)
|
||||
data['body'] += '\n\n### {0}\n'.format(minor['name']) + minor['body']
|
||||
except:
|
||||
pass
|
||||
i += 1
|
||||
if oldVersion[0]<newVersion[0] or oldVersion[1]<newVersion[1]:
|
||||
# new major release necessary!
|
||||
# if the newest version is minor, fetch the additional assets from the major
|
||||
if isMinor and (background or not progresswin.wasCanceled()):
|
||||
try:
|
||||
majorTagName = 'v{0}.{1}'.format(newVersion[0],newVersion[1])
|
||||
urlthread = UrlThread(
|
||||
"https://api.github.com/repos/{0}/releases/tags/{1}".format(path,majorTagName),
|
||||
"https://api.github.com/repos/{0}/releases/tags/{1}.0".format(path,majorTagName)
|
||||
)
|
||||
urlthread.start()
|
||||
urlthread.join()
|
||||
responseData = urlthread.response.read()
|
||||
major = json.loads(responseData)
|
||||
data['body'] += '\n\n### {0}\n'.format(major['name']) + major['body']
|
||||
except:
|
||||
pass
|
||||
|
||||
if background or not progresswin.wasCanceled():
|
||||
if progresswin:
|
||||
progresswin.hide()
|
||||
progresswin.destroy()
|
||||
dialog = DialogUpdates(parent, data, repository, updateSingle(repositories, path, data))
|
||||
dialog.exec_()
|
||||
dialog.destroy()
|
||||
else:
|
||||
if progresswin:
|
||||
progresswin.hide()
|
||||
progresswin.destroy()
|
||||
return 1
|
||||
else:
|
||||
if progresswin:
|
||||
progresswin.hide()
|
||||
progresswin.destroy()
|
||||
return 0
|
||||
if progresswin:
|
||||
progresswin.hide()
|
||||
progresswin.destroy()
|
||||
return -1
|
||||
|
||||
|
||||
class UrlThread(QThread):
|
||||
|
||||
def __init__(self, url, backurl=None):
|
||||
super(UrlThread, self).__init__()
|
||||
self.response = None
|
||||
self.url = url
|
||||
self.backurl = backurl
|
||||
self.finished = False
|
||||
|
||||
def run(self):
|
||||
try:
|
||||
self.response = urllib2.urlopen(self.url)
|
||||
except:
|
||||
if self.backurl:
|
||||
try:
|
||||
self.response = urllib2.urlopen(self.backurl)
|
||||
except:
|
||||
pass
|
||||
self.finished = True
|
||||
|
||||
def join(self):
|
||||
while not self.finished:
|
||||
QApplication.instance().processEvents()
|
||||
self.wait(30)
|
||||
Loading…
Reference in New Issue
Block a user