anki-word-query/src/fastwq/ui.py

643 lines
24 KiB
Python
Raw Normal View History

2018-07-01 10:55:30 +08:00
#-*- coding:utf-8 -*-
#
2018-07-07 17:48:15 +08:00
# Copyright © 20162017 sthoo <sth201807@gmail.com>
2018-07-01 10:55:30 +08:00
#
# Support: Report an issue at https://github.com/sth2018/FastWordQuery/issues
#
# 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
# any later version; http://www.gnu.org/copyleft/gpl.html.
#
# 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 <http://www.gnu.org/licenses/>.
import os
import sys
2018-07-02 18:33:03 +08:00
import json
import types
2018-07-01 10:55:30 +08:00
from collections import namedtuple
import anki
import aqt
import aqt.models
from aqt import mw
2018-07-13 00:57:53 +08:00
from PyQt4 import QtCore, QtGui
2018-07-01 10:55:30 +08:00
from aqt.studydeck import StudyDeck
from aqt.utils import shortcut, showInfo
from .constants import VERSION, Endpoint, Template
from .context import APP_ICON, config
from .lang import _, _sl
2018-07-05 12:38:04 +08:00
from .service import service_manager, service_pool
2018-07-01 10:55:30 +08:00
from .utils import MapDict, get_icon, get_model_byId, get_ord_from_fldname
2018-07-13 00:57:53 +08:00
__all__ = ['WIDGET_SIZE', 'Dialog', 'ParasDialog',
'FoldersManageDialog', 'OptionsDialog', 'check_updates',
'show_options', 'show_fm_dialog'
]
2018-07-01 10:55:30 +08:00
2018-07-13 00:57:53 +08:00
class WIDGET_SIZE:
dialog_width = 700
2018-07-13 00:57:53 +08:00
dialog_height_margin = 120
map_min_height = 0
map_max_height = 31
map_fld_width = 100
map_dictname_width = 150
map_dictfield_width = 160
2018-07-13 00:57:53 +08:00
class Dialog(QtGui.QDialog):
'''
2018-07-13 00:57:53 +08:00
Base used for all dialog windows.
'''
2018-07-01 10:55:30 +08:00
2018-07-13 00:57:53 +08:00
def __init__(self, parent, title):
'''
Set the modal status for the dialog, sets its layout to the
return value of the _ui() method, and sets a default title.
'''
self._title = title
self._parent = parent
super(Dialog, self).__init__(parent)
2018-07-10 23:51:07 +08:00
self.setModal(True)
self.setWindowFlags(
self.windowFlags() &
2018-07-13 00:57:53 +08:00
~QtCore.Qt.WindowContextHelpButtonHint
2018-07-10 23:51:07 +08:00
)
2018-07-13 00:57:53 +08:00
self.setWindowIcon(APP_ICON)
self.setWindowTitle(
title if "FastWQ" in title
else "FastWQ - " + title
)
2018-07-01 10:55:30 +08:00
2018-07-13 00:57:53 +08:00
class ParasDialog(Dialog):
'''
Setting window, some golbal params for query function.
'''
def __init__(self, parent, title=u'Setting'):
super(ParasDialog, self).__init__(parent, title)
self.setFixedWidth(400)
2018-07-01 10:55:30 +08:00
self.check_force_update = None
self.input_thread_number = None
self.build()
def build(self):
2018-07-13 00:57:53 +08:00
layout = QtGui.QVBoxLayout()
2018-07-01 10:55:30 +08:00
2018-07-13 00:57:53 +08:00
check_force_update = QtGui.QCheckBox(_("FORCE_UPDATE"))
2018-07-01 10:55:30 +08:00
check_force_update.setChecked(config.force_update)
layout.addWidget(check_force_update)
layout.addSpacing(10)
2018-07-13 00:57:53 +08:00
check_ignore_accents = QtGui.QCheckBox(_("IGNORE_ACCENTS"))
2018-07-11 22:09:17 +08:00
check_ignore_accents.setChecked(config.ignore_accents)
layout.addWidget(check_ignore_accents)
layout.addSpacing(10)
2018-07-13 00:57:53 +08:00
hbox = QtGui.QHBoxLayout()
input_thread_number = QtGui.QSpinBox(parent=self)
2018-07-01 10:55:30 +08:00
input_thread_number.setRange(1, 120)
input_thread_number.setValue(config.thread_number)
2018-07-13 00:57:53 +08:00
input_label = QtGui.QLabel(_("THREAD_NUMBER") + ":", parent=self)
2018-07-01 10:55:30 +08:00
hbox.addWidget(input_label)
hbox.setStretchFactor(input_label, 1)
hbox.addWidget(input_thread_number)
hbox.setStretchFactor(input_thread_number, 2)
layout.addLayout(hbox)
2018-07-13 00:57:53 +08:00
buttonBox = QtGui.QDialogButtonBox(parent=self)
buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Ok)
2018-07-01 10:55:30 +08:00
buttonBox.accepted.connect(self.accept) # 确定
layout.addSpacing(48)
layout.addWidget(buttonBox)
self.check_force_update = check_force_update
2018-07-11 22:09:17 +08:00
self.check_ignore_accents = check_ignore_accents
2018-07-01 10:55:30 +08:00
self.input_thread_number = input_thread_number
2018-07-13 00:57:53 +08:00
layout.setAlignment(QtCore.Qt.AlignTop|QtCore.Qt.AlignLeft)
2018-07-01 10:55:30 +08:00
self.setLayout(layout)
def accept(self):
self.save()
self.close()
def save(self):
2018-07-11 22:09:17 +08:00
data = {
'force_update': self.check_force_update.isChecked(),
'ignore_accents': self.check_ignore_accents.isChecked(),
'thread_number': self.input_thread_number.value()
}
2018-07-01 10:55:30 +08:00
config.update(data)
2018-07-13 00:57:53 +08:00
class FoldersManageDialog(Dialog):
'''
Dictionary folder manager window. add or remove dictionary folders.
'''
2018-07-01 10:55:30 +08:00
2018-07-13 00:57:53 +08:00
def __init__(self, parent, title=u'Dictionary Folder Manager'):
super(FoldersManageDialog, self).__init__(parent, title)
2018-07-01 10:55:30 +08:00
self._dict_paths = []
self.build()
def build(self):
2018-07-13 00:57:53 +08:00
layout = QtGui.QVBoxLayout()
btn_layout = QtGui.QHBoxLayout()
add_btn = QtGui.QPushButton("+")
remove_btn = QtGui.QPushButton("-")
2018-07-01 10:55:30 +08:00
btn_layout.addWidget(add_btn)
btn_layout.addWidget(remove_btn)
add_btn.clicked.connect(self.add_folder)
remove_btn.clicked.connect(self.remove_folder)
2018-07-13 00:57:53 +08:00
self.folders_lst = QtGui.QListWidget()
2018-07-01 10:55:30 +08:00
self.folders_lst.addItems(config.dirs)
2018-07-13 00:57:53 +08:00
self.chk_use_filename = QtGui.QCheckBox(_('CHECK_FILENAME_LABEL'))
self.chk_export_media = QtGui.QCheckBox(_('EXPORT_MEDIA'))
2018-07-01 10:55:30 +08:00
self.chk_use_filename.setChecked(config.use_filename)
self.chk_export_media.setChecked(config.export_media)
2018-07-13 00:57:53 +08:00
chk_layout = QtGui.QHBoxLayout()
2018-07-01 10:55:30 +08:00
chk_layout.addWidget(self.chk_use_filename)
chk_layout.addWidget(self.chk_export_media)
2018-07-13 00:57:53 +08:00
btnbox = QtGui.QDialogButtonBox(QtGui.QDialogButtonBox.Ok, QtCore.Qt.Horizontal, self)
2018-07-01 10:55:30 +08:00
btnbox.accepted.connect(self.accept)
layout.addLayout(btn_layout)
layout.addWidget(self.folders_lst)
layout.addLayout(chk_layout)
layout.addWidget(btnbox)
self.setLayout(layout)
def add_folder(self):
2018-07-13 00:57:53 +08:00
dir_ = QtGui.QFileDialog.getExistingDirectory(
self,
caption=u"Select Folder",
directory=config.last_folder,
2018-07-13 00:57:53 +08:00
options=QtGui.QFileDialog.ShowDirsOnly | QtGui.QFileDialog.DontResolveSymlinks
)
2018-07-01 10:55:30 +08:00
if dir_:
self.folders_lst.addItem(dir_)
config.update({'last_folder': dir_})
2018-07-01 10:55:30 +08:00
def remove_folder(self):
item = self.folders_lst.takeItem(self.folders_lst.currentRow())
del item
def find_mdxes(self):
for each in self.dirs:
for dirpath, dirnames, filenames in os.walk(each):
self._dict_paths.extend([os.path.join(dirpath, filename)
for filename in filenames if filename.lower().endswith(u'.mdx')])
return list(set(self._dict_paths))
@property
def dict_paths(self):
return self.find_mdxes()
@property
def dirs(self):
return [self.folders_lst.item(i).text()
for i in range(self.folders_lst.count())]
def save(self):
data = {
'dirs': self.dirs,
'use_filename': self.chk_use_filename.isChecked(),
'export_media': self.chk_export_media.isChecked()
}
2018-07-01 10:55:30 +08:00
config.update(data)
2018-07-13 00:57:53 +08:00
class OptionsDialog(Dialog):
'''
query options window
setting query dictionary and fileds
'''
2018-07-01 10:55:30 +08:00
2018-07-13 00:57:53 +08:00
__slot__ = [
'begore_build',
'after_build'
]
def __init__(self, parent, browser=None, title=u'Options'):
super(OptionsDialog, self).__init__(parent, title)
self.browser = browser
2018-07-13 00:57:53 +08:00
self.connect(self, QtCore.SIGNAL('before_build'), self._before_build, QtCore.Qt.QueuedConnection)
self.connect(self, QtCore.SIGNAL('after_build'), self._after_build, QtCore.Qt.QueuedConnection)
# initlizing info
2018-07-13 00:57:53 +08:00
self.main_layout = QtGui.QVBoxLayout()
self.loading_label = QtGui.QLabel(_('INITLIZING_DICT'))
self.main_layout.addWidget(self.loading_label, 0, QtCore.Qt.AlignCenter)
#self.loading_layout.addLayout(models_layout)
self.setLayout(self.main_layout)
#initlize properties
self.___last_checkeds___ = None
self.___options___ = list()
# size and signal
2018-07-13 00:57:53 +08:00
self.resize(WIDGET_SIZE.dialog_width, 4 * WIDGET_SIZE.map_max_height + WIDGET_SIZE.dialog_height_margin)
self.emit(QtCore.SIGNAL('before_build'), self.browser)
def _before_build(self, browser=None):
for cls in service_manager.services:
service = service_pool.get(cls.__unique__)
2018-07-13 00:57:53 +08:00
self.emit(QtCore.SIGNAL('after_build'), browser)
def _after_build(self, browser=None):
self.main_layout.removeWidget(self.loading_label)
2018-07-13 00:57:53 +08:00
models_layout = QtGui.QHBoxLayout()
2018-07-01 10:55:30 +08:00
# add buttons
2018-07-13 00:57:53 +08:00
mdx_button = QtGui.QPushButton(_('DICTS_FOLDERS'))
2018-07-01 10:55:30 +08:00
mdx_button.clicked.connect(self.show_fm_dialog)
2018-07-13 00:57:53 +08:00
self.models_button = QtGui.QPushButton(_('CHOOSE_NOTE_TYPES'))
2018-07-01 10:55:30 +08:00
self.models_button.clicked.connect(self.btn_models_pressed)
models_layout.addWidget(mdx_button)
models_layout.addWidget(self.models_button)
self.main_layout.addLayout(models_layout)
# add dicts mapping
2018-07-13 00:57:53 +08:00
dicts_widget = QtGui.QWidget()
self.dicts_layout = QtGui.QGridLayout()
self.dicts_layout.setSizeConstraint(QtGui.QLayout.SetMinAndMaxSize)
2018-07-01 10:55:30 +08:00
dicts_widget.setLayout(self.dicts_layout)
2018-07-13 00:57:53 +08:00
scroll_area = QtGui.QScrollArea()
2018-07-01 10:55:30 +08:00
scroll_area.setWidgetResizable(True)
scroll_area.setWidget(dicts_widget)
self.main_layout.addWidget(scroll_area)
# add description of radio buttons AND ok button
2018-07-13 00:57:53 +08:00
bottom_layout = QtGui.QHBoxLayout()
paras_btn = QtGui.QPushButton(_('SETTINGS'))
2018-07-01 10:55:30 +08:00
paras_btn.clicked.connect(self.show_paras)
2018-07-13 00:57:53 +08:00
about_btn = QtGui.QPushButton(_('ABOUT'))
2018-07-01 10:55:30 +08:00
about_btn.clicked.connect(self.show_about)
# about_btn.clicked.connect(self.show_paras)
2018-07-13 00:57:53 +08:00
chk_update_btn = QtGui.QPushButton(_('UPDATE'))
2018-07-02 18:33:03 +08:00
chk_update_btn.clicked.connect(check_updates)
2018-07-13 00:57:53 +08:00
home_label = QtGui.QLabel(
2018-07-01 10:55:30 +08:00
'<a href="{url}">User Guide</a>'.format(url=Endpoint.user_guide))
home_label.setOpenExternalLinks(True)
# shop_label = QLabel(
# '<a href="{url}">Service Shop</a>'.format(url=Endpoint.service_shop))
# shop_label.setOpenExternalLinks(True)
2018-07-13 00:57:53 +08:00
btnbox = QtGui.QDialogButtonBox(QtGui.QDialogButtonBox.Ok, QtCore.Qt.Horizontal, self)
2018-07-01 10:55:30 +08:00
btnbox.accepted.connect(self.accept)
bottom_layout.addWidget(paras_btn)
bottom_layout.addWidget(chk_update_btn)
bottom_layout.addWidget(about_btn)
bottom_layout.addWidget(home_label)
# bottom_layout.addWidget(shop_label)
bottom_layout.addWidget(btnbox)
#self.setLayout(self.main_layout)
2018-07-01 10:55:30 +08:00
self.main_layout.addLayout(bottom_layout)
# init from saved data
self.current_model = None
model_id = config.last_model_id
if browser:
for note_id in browser.selectedNotes():
note = browser.mw.col.getNote(note_id)
model_id = note.model()['id']
break
if model_id:
self.current_model = get_model_byId(mw.col.models, model_id)
if self.current_model:
self.models_button.setText(
u'%s [%s]' % (_('CHOOSE_NOTE_TYPES'), self.current_model['name']))
# build fields -- dicts layout
self.build_mappings_layout(self.current_model)
2018-07-01 10:55:30 +08:00
def show_paras(self):
2018-07-13 00:57:53 +08:00
dialog = ParasDialog(self, u'Setting')
2018-07-01 10:55:30 +08:00
dialog.exec_()
def show_fm_dialog(self):
self.save()
self.close()
show_fm_dialog(self.browser)
2018-07-01 10:55:30 +08:00
def show_about(self):
2018-07-13 00:57:53 +08:00
QtGui.QMessageBox.about(self, _('ABOUT'), Template.tmpl_about)
2018-07-01 10:55:30 +08:00
def accept(self):
self.save()
self.close()
def btn_models_pressed(self):
self.save()
self.current_model = self.show_models()
if self.current_model:
self.build_mappings_layout(self.current_model)
def build_mappings_layout(self, model):
2018-07-13 22:09:07 +08:00
'''
build dictionaryfields etc
'''
2018-07-01 10:55:30 +08:00
def clear_layout(layout):
if layout is not None:
while layout.count():
item = layout.takeAt(0)
widget = item.widget()
if widget is not None:
widget.deleteLater()
else:
clear_layout(item.layout())
clear_layout(self.dicts_layout)
2018-07-13 00:57:53 +08:00
del self.___options___[:]
self.___last_checkeds___ = None
2018-07-01 10:55:30 +08:00
labels = ['', '', 'DICTS', 'DICT_FIELDS', '']
for i, s in enumerate(labels):
2018-07-13 00:57:53 +08:00
label = QtGui.QLabel(_(s))
label.setSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Fixed)
self.dicts_layout.addWidget(label, 0, i)
2018-07-01 10:55:30 +08:00
maps = config.get_maps(model['id'])
2018-07-13 00:57:53 +08:00
self.radio_group = QtGui.QButtonGroup()
2018-07-01 10:55:30 +08:00
for i, fld in enumerate(model['flds']):
ord = fld['ord']
name = fld['name']
if maps:
for j, each in enumerate(maps):
2018-07-13 22:09:07 +08:00
if each.get('fld_ord', -1) == ord or each.get('fld_name', '') == name:
each['fld_name'] = name
each['fld_ord'] = ord
self.add_dict_layout(j, **each)
2018-07-01 10:55:30 +08:00
break
else:
2018-07-13 22:09:07 +08:00
self.add_dict_layout(i, fld_name=name, fld_ord=ord)
2018-07-01 10:55:30 +08:00
else:
2018-07-13 22:09:07 +08:00
self.add_dict_layout(i, fld_name=name, fld_ord=ord)
2018-07-01 10:55:30 +08:00
#self.setLayout(self.main_layout)
2018-07-13 00:57:53 +08:00
self.resize(WIDGET_SIZE.dialog_width,
max(3, (i + 1)) * WIDGET_SIZE.map_max_height + WIDGET_SIZE.dialog_height_margin)
self.save()
2018-07-01 10:55:30 +08:00
def show_models(self):
2018-07-13 22:09:07 +08:00
'''
show choose note type window
'''
2018-07-13 00:57:53 +08:00
edit = QtGui.QPushButton(anki.lang._("Manage"),
2018-07-01 10:55:30 +08:00
clicked=lambda: aqt.models.Models(mw, self))
ret = StudyDeck(mw, names=lambda: sorted(mw.col.models.allNames()),
accept=anki.lang._("Choose"), title=anki.lang._("Choose Note Type"),
help="_notes", parent=self, buttons=[edit],
cancel=True, geomKey="selectModel")
if ret.name:
model = mw.col.models.byName(ret.name)
self.models_button.setText(
u'%s [%s]' % (_('CHOOSE_NOTE_TYPES'), ret.name))
return model
2018-07-13 22:09:07 +08:00
def fill_dict_combo_options(self, dict_combo, current_unique):
'''setup dict combo box'''
2018-07-01 10:55:30 +08:00
dict_combo.clear()
#dict_combo.addItem(_('NOT_DICT_FIELD'))
# local dict service
#dict_combo.insertSeparator(dict_combo.count())
has_local_service = False
2018-07-05 12:38:04 +08:00
for cls in service_manager.local_services:
2018-07-01 10:55:30 +08:00
# combo_data.insert("data", each.label)
2018-07-05 12:38:04 +08:00
service = service_pool.get(cls.__unique__)
if service and service.support:
dict_combo.addItem(
service.title, userData=service.unique)
service_pool.put(service)
has_local_service = True
2018-07-05 12:38:04 +08:00
# hr
if has_local_service:
dict_combo.insertSeparator(dict_combo.count())
# web dict service
2018-07-05 12:38:04 +08:00
for cls in service_manager.web_services:
service = service_pool.get(cls.__unique__)
if service and service.support:
dict_combo.addItem(
service.title, userData=service.unique)
service_pool.put(service)
2018-07-01 10:55:30 +08:00
def set_dict_combo_index():
#dict_combo.setCurrentIndex(-1)
dict_combo.setCurrentIndex(0)
2018-07-13 22:09:07 +08:00
if current_unique:
2018-07-13 00:57:53 +08:00
for i in range(dict_combo.count()):
2018-07-13 22:09:07 +08:00
if dict_combo.itemData(i) == current_unique:
2018-07-13 00:57:53 +08:00
dict_combo.setCurrentIndex(i)
break
set_dict_combo_index()
2018-07-01 10:55:30 +08:00
2018-07-13 22:09:07 +08:00
def fill_field_combo_options(self, field_combo, dict_combo_text, dict_combo_itemdata, dict_fld_name, dict_fld_ord):
'''setup field combobox'''
2018-07-01 10:55:30 +08:00
field_combo.clear()
2018-07-09 19:25:08 +08:00
field_combo.setEditable(False)
#if dict_combo_text in _sl('NOT_DICT_FIELD'):
# field_combo.setEnabled(False)
#el
if dict_combo_text in _sl('MDX_SERVER'):
2018-07-13 22:09:07 +08:00
text = dict_fld_name if dict_fld_name else 'http://'
2018-07-09 19:25:08 +08:00
field_combo.setEditable(True)
field_combo.setEditText(text)
2018-07-13 01:47:30 +08:00
field_combo.setFocus(QtCore.Qt.MouseFocusReason) # MouseFocusReason
2018-07-01 10:55:30 +08:00
else:
unique = dict_combo_itemdata
service = service_pool.get(unique)
2018-07-01 10:55:30 +08:00
# problem
field_combo.setCurrentIndex(0)
if service and service.support and service.fields:
for i, each in enumerate(service.fields):
2018-07-13 22:09:07 +08:00
field_combo.addItem(each, userData=i)
if each == dict_fld_name or i == dict_fld_ord:
field_combo.setCurrentIndex(i)
service_pool.put(service)
2018-07-01 10:55:30 +08:00
def add_dict_layout(self, i, **kwargs):
"""
2018-07-13 22:09:07 +08:00
add dictionary fields row
2018-07-01 10:55:30 +08:00
"""
word_checked = i == 0
2018-07-13 22:09:07 +08:00
fld_name, fld_ord = (
kwargs.get('fld_name', ''), #笔记类型的字段名
kwargs.get('fld_ord', ''), #笔记类型的字段编号
)
dict_name, dict_unique, dict_fld_name, dict_fld_ord = (
kwargs.get('dict_name', ''), #字典名
kwargs.get('dict_unique', ''), #字典ID
kwargs.get('dict_fld_name', ''), #对应字典的字段名
kwargs.get('dcit_fld_ord', 0) #对应字典的字段编号
)
ignore, skip = (
kwargs.get('ignore', True), #忽略标志
kwargs.get('skip_valued', True), #略过有值项标志
)
# check
2018-07-13 00:57:53 +08:00
word_check_btn = QtGui.QRadioButton(fld_name)
word_check_btn.setMinimumSize(WIDGET_SIZE.map_fld_width, 0)
word_check_btn.setMaximumSize(
2018-07-13 00:57:53 +08:00
WIDGET_SIZE.map_fld_width,
WIDGET_SIZE.map_max_height
)
2018-07-13 00:57:53 +08:00
word_check_btn.setSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
2018-07-01 10:55:30 +08:00
word_check_btn.setCheckable(True)
word_check_btn.setChecked(word_checked)
self.radio_group.addButton(word_check_btn)
# dict combox
2018-07-13 00:57:53 +08:00
dict_combo = QtGui.QComboBox()
dict_combo.setMinimumSize(WIDGET_SIZE.map_dictname_width, 0)
2018-07-01 10:55:30 +08:00
dict_combo.setFocusPolicy(
2018-07-13 00:57:53 +08:00
QtCore.Qt.TabFocus | QtCore.Qt.ClickFocus | QtCore.Qt.StrongFocus | QtCore.Qt.WheelFocus
)
dict_combo.setEnabled(not word_checked and not ignore)
2018-07-13 22:09:07 +08:00
self.fill_dict_combo_options(dict_combo, dict_unique)
2018-07-13 00:57:53 +08:00
dict_unique = dict_combo.itemData(dict_combo.currentIndex())
# field combox
2018-07-13 00:57:53 +08:00
field_combo = QtGui.QComboBox()
field_combo.setMinimumSize(WIDGET_SIZE.map_dictfield_width, 0)
field_combo.setEnabled(not word_checked and not ignore)
2018-07-13 22:09:07 +08:00
self.fill_field_combo_options(field_combo, dict_name, dict_unique, dict_fld_name, dict_fld_ord)
# ignore
2018-07-13 22:09:07 +08:00
ignore_check_btn = QtGui.QCheckBox(_("NOT_DICT_FIELD"))
ignore_check_btn.setEnabled(not word_checked)
ignore_check_btn.setChecked(ignore)
# Skip valued
2018-07-13 22:09:07 +08:00
skip_check_btn = QtGui.QCheckBox(_("SKIP_VALUED"))
skip_check_btn.setEnabled(not word_checked and not ignore)
skip_check_btn.setChecked(skip)
# events
# word
def radio_btn_checked():
if self.___last_checkeds___:
self.___last_checkeds___[0].setEnabled(True)
ignore = self.___last_checkeds___[0].isChecked()
for i in range(1, len(self.___last_checkeds___)):
self.___last_checkeds___[i].setEnabled(not ignore)
word_checked = word_check_btn.isChecked()
2018-07-13 22:09:07 +08:00
ignore_check_btn.setEnabled(not word_checked)
ignore = ignore_check_btn.isChecked()
dict_combo.setEnabled(not word_checked and not ignore)
field_combo.setEnabled(not word_checked and not ignore)
2018-07-13 22:09:07 +08:00
skip_check_btn.setEnabled(not word_checked and not ignore)
if word_checked:
self.___last_checkeds___ = [
2018-07-13 22:09:07 +08:00
ignore_check_btn, dict_combo,
field_combo, skip_check_btn
]
word_check_btn.clicked.connect(radio_btn_checked)
if word_checked:
self.___last_checkeds___ = None
radio_btn_checked()
# ignor
def ignore_check_changed():
2018-07-13 22:09:07 +08:00
ignore = not ignore_check_btn.isChecked()
dict_combo.setEnabled(ignore)
field_combo.setEnabled(ignore)
2018-07-13 22:09:07 +08:00
skip_check_btn.setEnabled(ignore)
ignore_check_btn.clicked.connect(ignore_check_changed)
# dict
def dict_combo_changed(index):
'''dict combo box index changed'''
self.fill_field_combo_options(
field_combo,
dict_combo.currentText(),
dict_combo.itemData(index),
2018-07-13 22:09:07 +08:00
field_combo.currentText(),
field_combo.itemData(field_combo.currentIndex())
)
dict_combo.currentIndexChanged.connect(dict_combo_changed)
2018-07-01 10:55:30 +08:00
self.dicts_layout.addWidget(word_check_btn, i + 1, 0)
2018-07-13 22:09:07 +08:00
self.dicts_layout.addWidget(ignore_check_btn, i + 1, 1)
self.dicts_layout.addWidget(dict_combo, i + 1, 2)
self.dicts_layout.addWidget(field_combo, i + 1, 3)
2018-07-13 22:09:07 +08:00
self.dicts_layout.addWidget(skip_check_btn, i + 1, 4)
2018-07-13 22:09:07 +08:00
self.___options___.append({
'model': {'fld_name': fld_name, 'fld_ord': fld_ord},
'word_check_btn': word_check_btn,
'dict_combo': dict_combo,
'field_combo': field_combo,
'ignore_check_btn': ignore_check_btn,
'skip_check_btn': skip_check_btn
})
2018-07-01 10:55:30 +08:00
def save(self):
2018-07-13 22:09:07 +08:00
'''save config to file'''
2018-07-01 10:55:30 +08:00
if not self.current_model:
return
data = dict()
2018-07-13 22:09:07 +08:00
maps = []
for row in self.___options___:
maps.append({
'fld_name': row['model']['fld_name'],
'fld_ord': row['model']['fld_ord'],
'word_checked': row['word_check_btn'].isChecked(),
'dict_name': row['dict_combo'].currentText().strip(),
'dict_unique': row['dict_combo'].itemData(row['dict_combo'].currentIndex()),
'dict_fld_name': row['field_combo'].currentText().strip(),
'dict_fld_ord': row['field_combo'].itemData(row['field_combo'].currentIndex()),
'ignore': row['ignore_check_btn'].isChecked(),
'skip_valued': row['skip_check_btn'].isChecked()
})
2018-07-01 10:55:30 +08:00
current_model_id = str(self.current_model['id'])
data[current_model_id] = maps
data['last_model'] = self.current_model['id']
config.update(data)
2018-07-02 18:33:03 +08:00
def check_updates():
'''check add-on last version'''
2018-07-02 18:33:03 +08:00
try:
2018-07-03 12:01:40 +08:00
import libs.ankihub
2018-07-09 16:23:17 +08:00
if not libs.ankihub.update([Endpoint.check_version], False, Endpoint.version):
2018-07-02 20:52:38 +08:00
showInfo(_('LATEST_VERSION'))
2018-07-02 18:33:03 +08:00
except:
2018-07-02 20:52:38 +08:00
showInfo(_('CHECK_FAILURE'))
2018-07-02 18:33:03 +08:00
pass
2018-07-01 10:55:30 +08:00
def show_options(browser = None, callback = None, *args, **kwargs):
'''open options window'''
2018-07-09 15:35:10 +08:00
parent = mw if browser is None else browser
2018-07-01 10:55:30 +08:00
config.read()
2018-07-13 00:57:53 +08:00
opt_dialog = OptionsDialog(parent, browser, u'Options')
2018-07-01 10:55:30 +08:00
opt_dialog.activateWindow()
opt_dialog.raise_()
opt_dialog.exec_()
if isinstance(callback, types.FunctionType):
callback(*args, **kwargs)
def show_fm_dialog(browser = None):
'''open dictionary folder manager window'''
parent = mw if browser is None else browser
2018-07-13 00:57:53 +08:00
fm_dialog = FoldersManageDialog(parent, u'Dictionary Folder Manager')
fm_dialog.activateWindow()
fm_dialog.raise_()
2018-07-13 00:57:53 +08:00
if fm_dialog.exec_() == QtGui.QDialog.Accepted:
dict_paths = fm_dialog.dict_paths
fm_dialog.save()
# update local services
service_manager.update_services()
# reshow options window
2018-07-09 15:35:10 +08:00
show_options(browser)