anki-word-query/addons/fastwq/gui/options.py

692 lines
26 KiB
Python
Raw Normal View History

2018-07-01 10:55:30 +08:00
#-*- coding:utf-8 -*-
#
2018-07-27 17:57:00 +08:00
# Copyright (C) 2018 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/>.
2018-08-28 20:29:40 +08:00
import sys
2018-07-01 10:55:30 +08:00
import anki
import aqt
import aqt.models
2018-07-31 02:21:35 +08:00
import sip
2018-07-01 10:55:30 +08:00
from aqt import mw
2018-07-31 02:21:35 +08:00
from aqt.qt import *
2018-07-01 10:55:30 +08:00
from aqt.studydeck import StudyDeck
2018-08-27 13:53:04 +08:00
from anki.utils import isMac
2018-07-14 15:24:21 +08:00
from .base import Dialog, WIDGET_SIZE
from .setting import SettingDialog
from ..context import config
from ..lang import _, _sl
from ..service import service_manager, service_pool
2018-08-12 23:17:45 +08:00
from ..utils import get_model_byId, get_icon
2018-07-14 15:24:21 +08:00
from ..constants import Endpoint
2018-07-01 10:55:30 +08:00
2018-07-14 15:24:21 +08:00
__all__ = ['OptionsDialog']
2018-07-01 10:55:30 +08:00
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__ = [
2021-03-06 00:46:42 +08:00
'before_build',
2018-07-13 00:57:53 +08:00
'after_build'
]
2018-07-31 02:21:35 +08:00
_signal = pyqtSignal(str)
2018-07-13 00:57:53 +08:00
2018-08-12 23:17:45 +08:00
_NULL_ICON = get_icon('null.png')
_OK_ICON = get_icon('ok.png')
2018-07-14 10:22:45 +08:00
def __init__(self, parent, title=u'Options', model_id = -1):
2018-07-13 00:57:53 +08:00
super(OptionsDialog, self).__init__(parent, title)
2018-07-31 02:21:35 +08:00
self._signal.connect(self._before_build)
self._signal.connect(self._after_build)
# initlizing info
2018-07-31 02:21:35 +08:00
self.main_layout = QVBoxLayout()
self.loading_label = QLabel(_('INITLIZING_DICT'))
self.main_layout.addWidget(self.loading_label, 0, Qt.AlignCenter)
#self.loading_layout.addLayout(models_layout)
self.setLayout(self.main_layout)
#initlize properties
2018-07-14 10:22:45 +08:00
self.model_id = model_id if model_id != -1 else config.last_model_id
2018-07-14 15:24:21 +08:00
self.current_model = None
2018-08-09 19:34:49 +08:00
self.tabs = []
2018-08-10 12:05:03 +08:00
self.dict_services = None
# 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)
2018-07-31 02:21:35 +08:00
self._signal.emit('before_build')
2018-07-31 02:21:35 +08:00
def _before_build(self, s):
if s != 'before_build':
return
2018-08-10 12:05:03 +08:00
# dict service list
2018-08-15 00:46:46 +08:00
dicts = config.dicts
2018-08-10 12:05:03 +08:00
self.dict_services = {
'local': [], #本地词典
'web': [] #网络词典
}
2018-08-12 11:26:57 +08:00
for clazz in service_manager.local_services:
2018-08-15 01:52:12 +08:00
if dicts.get(clazz.__unique__, dict()).get('enabled', True):
service = service_pool.get(clazz.__unique__)
if service and service.support:
self.dict_services['local'].append({
'title': service.title,
'unique': service.unique
})
service_pool.put(service)
2018-08-12 11:26:57 +08:00
for clazz in service_manager.web_services:
2018-08-15 00:46:46 +08:00
if dicts.get(clazz.__unique__, dict()).get('enabled', True):
service = service_pool.get(clazz.__unique__)
if service and service.support:
self.dict_services['web'].append({
'title': service.title,
'unique': service.unique
})
service_pool.put(service)
2018-08-10 12:05:03 +08:00
# emit finished
2018-07-31 02:21:35 +08:00
self._signal.emit('after_build')
def _after_build(self, s):
if s != 'after_build':
return
if self.loading_label:
self.main_layout.removeWidget(self.loading_label)
sip.delete(self.loading_label)
self.loading_label = None
models_layout = QHBoxLayout()
2018-07-01 10:55:30 +08:00
# add buttons
2018-07-31 02:21:35 +08:00
mdx_button = QPushButton(_('DICTS_FOLDERS'))
2018-07-01 10:55:30 +08:00
mdx_button.clicked.connect(self.show_fm_dialog)
2018-07-31 02:21:35 +08:00
self.models_button = 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)
2018-08-09 19:34:49 +08:00
# tabs
self.tab_widget = QTabWidget()
2018-09-10 02:47:15 +08:00
self.tab_widget.setTabBar(CTabBar())
2018-08-09 21:33:29 +08:00
self.tab_widget.setStyleSheet(
"""
QTabWidget::pane { /* The tab widget frame */
border: 1px solid #c3c3c3;
}
"""
)
2018-08-15 00:46:46 +08:00
tab_corner = QWidget()
tab_corner_layout = QHBoxLayout()
tab_corner_layout.setSpacing(1)
tab_corner_layout.setSizeConstraint(QLayout.SetMinAndMaxSize)
tab_corner_layout.setContentsMargins(0, 0, 0, 0)
tab_corner.setLayout(tab_corner_layout)
2018-08-10 12:05:03 +08:00
tab_add_button = QToolButton(self)
2018-08-15 00:46:46 +08:00
tab_add_button.setIcon(get_icon('add.png'))
tab_set_button = QToolButton(self)
2018-08-28 20:29:40 +08:00
if isMac and sys.hexversion < 0x03000000:
2018-08-27 13:53:04 +08:00
tab_set_button.setMaximumSize(20, 20)
tab_add_button.setMaximumSize(20, 20)
2018-08-15 00:46:46 +08:00
tab_set_button.setIcon(get_icon('setting.png'))
tab_corner_layout.addWidget(tab_set_button)
tab_corner_layout.addWidget(tab_add_button)
self.tab_widget.setCornerWidget(tab_corner)
2018-08-09 19:34:49 +08:00
# signals
2018-08-15 00:46:46 +08:00
tab_set_button.clicked.connect(self.show_dm_dialog)
2018-08-10 12:05:03 +08:00
tab_add_button.clicked.connect(self.addTab)
2018-08-09 19:34:49 +08:00
self.tab_widget.tabCloseRequested.connect(self.removeTab)
# layout
self.main_layout.addWidget(self.tab_widget)
2018-07-01 10:55:30 +08:00
# add description of radio buttons AND ok button
2018-07-31 02:21:35 +08:00
bottom_layout = QHBoxLayout()
paras_btn = QPushButton(_('SETTINGS'))
2018-07-01 10:55:30 +08:00
paras_btn.clicked.connect(self.show_paras)
2018-07-31 02:21:35 +08:00
about_btn = QPushButton(_('ABOUT'))
2018-07-01 10:55:30 +08:00
about_btn.clicked.connect(self.show_about)
# about_btn.clicked.connect(self.show_paras)
2019-01-27 09:46:54 +08:00
# chk_update_btn = QPushButton(_('UPDATE'))
# chk_update_btn.clicked.connect(self.check_updates)
2018-07-31 02:21:35 +08:00
home_label = QLabel(
2018-08-09 19:34:49 +08:00
'<a href="{url}">User Guide</a>'.format(url=Endpoint.user_guide)
)
2018-07-01 10:55:30 +08:00
home_label.setOpenExternalLinks(True)
2018-08-09 19:34:49 +08:00
# buttons
2018-07-31 02:21:35 +08:00
btnbox = QDialogButtonBox(QDialogButtonBox.Ok, Qt.Horizontal, self)
2018-07-01 10:55:30 +08:00
btnbox.accepted.connect(self.accept)
bottom_layout.addWidget(paras_btn)
2019-01-27 09:46:54 +08:00
# bottom_layout.addWidget(chk_update_btn)
2018-07-01 10:55:30 +08:00
bottom_layout.addWidget(about_btn)
bottom_layout.addWidget(home_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
2018-07-14 10:22:45 +08:00
if self.model_id:
self.current_model = get_model_byId(mw.col.models, self.model_id)
if self.current_model:
self.models_button.setText(
u'%s [%s]' % (_('CHOOSE_NOTE_TYPES'), self.current_model['name']))
# build fields -- dicts layout
2018-08-10 12:05:03 +08:00
self.build_tabs_layout()
2018-07-01 10:55:30 +08:00
def show_paras(self):
2018-07-14 15:24:21 +08:00
'''open setting dialog'''
dialog = SettingDialog(self, u'Setting')
2018-07-01 10:55:30 +08:00
dialog.exec_()
2018-07-31 02:30:38 +08:00
dialog.destroy()
2018-07-01 10:55:30 +08:00
2019-01-27 09:46:54 +08:00
# def check_updates(self):
# '''check addon version'''
# from .common import check_updates
# check_updates(parent=self)
2018-07-14 15:24:21 +08:00
def show_fm_dialog(self):
2018-07-14 15:24:21 +08:00
'''open folder manager dialog'''
2018-08-15 00:46:46 +08:00
self.accept()
self.setResult(1001)
def show_dm_dialog(self):
'''open dictionary manager dialog'''
self.accept()
self.setResult(1002)
2018-07-01 10:55:30 +08:00
def show_about(self):
2018-07-14 15:24:21 +08:00
'''open about dialog'''
from .common import show_about_dialog
show_about_dialog(self)
2018-07-01 10:55:30 +08:00
def accept(self):
2018-07-14 15:24:21 +08:00
'''on button was clicked'''
2018-07-01 10:55:30 +08:00
self.save()
2018-07-14 10:22:45 +08:00
super(OptionsDialog, self).accept()
2018-07-01 10:55:30 +08:00
def btn_models_pressed(self):
2018-07-14 15:24:21 +08:00
'''on choose model button was clicker'''
2018-07-01 10:55:30 +08:00
self.save()
self.current_model = self.show_models()
if self.current_model:
2018-08-10 12:05:03 +08:00
self.build_tabs_layout()
2018-08-09 19:34:49 +08:00
2018-08-10 12:05:03 +08:00
def build_tabs_layout(self):
2018-08-09 19:34:49 +08:00
'''
build dictionaryfields etc
'''
try: self.tab_widget.currentChanged.disconnect()
except Exception: pass
while len(self.tabs) > 0:
self.removeTab(0, True)
2018-08-27 20:59:15 +08:00
# tabs
2018-08-10 12:05:03 +08:00
conf = config.get_maps(self.current_model['id'])
2018-08-09 19:34:49 +08:00
maps_list = {'list': [conf], 'def': 0} if isinstance(conf, list) else conf
2018-08-10 12:05:03 +08:00
for maps in maps_list['list']:
self.addTab(maps, False)
2018-08-09 19:34:49 +08:00
self.tab_widget.currentChanged.connect(self.changedTab)
2018-08-27 20:59:15 +08:00
# value
self.changedTab(maps_list['def'])
self.tab_widget.setCurrentIndex(maps_list['def'])
2018-08-09 19:34:49 +08:00
# size
2018-08-27 15:37:27 +08:00
self.resize(
2018-08-27 20:59:15 +08:00
WIDGET_SIZE.dialog_width,
2018-08-27 15:37:27 +08:00
min(max(3, len(self.current_model['flds'])+1), 14) * WIDGET_SIZE.map_max_height + WIDGET_SIZE.dialog_height_margin
)
2018-08-09 19:34:49 +08:00
self.save()
2018-08-10 12:05:03 +08:00
def addTab(self, maps=None, forcus=True):
2018-08-09 19:34:49 +08:00
i = len(self.tabs)
2018-09-10 02:47:15 +08:00
if isinstance(maps, list):
maps = {
'fields': maps,
'name': _('CONFIG_INDEX') % (i+1)
}
tab = TabContent(
self.current_model,
maps['fields'] if maps else None,
self.dict_services
)
2018-08-09 19:34:49 +08:00
self.tabs.append(tab)
2018-09-10 02:47:15 +08:00
self.tab_widget.addTab(
tab,
maps['name'] if maps else _('CONFIG_INDEX') % (i+1)
)
2018-08-10 12:05:03 +08:00
if forcus:
self.tab_widget.setCurrentIndex(i)
2018-08-09 19:34:49 +08:00
def removeTab(self, i, forcus=False):
# less than one config
if not forcus and len(self.tabs) <= 1:
return
tab = self.tabs[i]
del self.tabs[i]
self.tab_widget.removeTab(i)
tab.destroy()
2018-09-10 02:47:15 +08:00
#for k in range(0, len(self.tabs)):
# self.tab_widget.setTabText(k, _('CONFIG_INDEX') % (k+1))
2018-08-09 19:34:49 +08:00
def changedTab(self, i):
2018-08-28 20:29:40 +08:00
if not isMac or sys.hexversion >= 0x03000000:
2018-08-27 13:53:04 +08:00
# restore
for k in range(0, len(self.tabs)):
self.tab_widget.setTabIcon(k, self._NULL_ICON)
# add flag
self.tab_widget.setTabIcon(i, self._OK_ICON)
2018-08-27 20:59:15 +08:00
self.tabs[i].build_layout()
2018-08-09 19:34:49 +08:00
def show_models(self):
'''
show choose note type window
'''
edit = QPushButton(anki.lang._("Manage"),
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
def save(self):
'''save config to file'''
if not self.current_model:
return
data = dict()
maps_list = {
'list': [],
'def': self.tab_widget.currentIndex()
}
2018-09-10 02:47:15 +08:00
for i, tab in enumerate(self.tabs):
maps_list['list'].append({
'fields': tab.data,
'name': self.tab_widget.tabBar().tabText(i)
})
2018-08-09 19:34:49 +08:00
current_model_id = str(self.current_model['id'])
data[current_model_id] = maps_list
data['last_model'] = self.current_model['id']
config.update(data)
2018-07-01 10:55:30 +08:00
2018-08-27 15:37:27 +08:00
class TabContent(QScrollArea):
2018-08-09 19:34:49 +08:00
'''Options tab content'''
2018-08-10 12:05:03 +08:00
def __init__(self, model, conf, services):
2018-08-09 19:34:49 +08:00
super(TabContent, self).__init__()
self._conf = conf
self._model = model
2018-08-10 12:05:03 +08:00
self._services = services
self._last_checkeds = None
self._options = list()
self._was_built = False
2018-08-27 20:59:15 +08:00
# dicts mapping
dicts = QWidget(self)
dicts.setLayout(QGridLayout())
2018-08-27 15:37:27 +08:00
self.setFrameShape(QFrame.NoFrame)
self.setWidgetResizable(True)
2018-08-27 20:59:15 +08:00
self.setWidget(dicts)
self.dicts_layout = dicts.layout()
#self.dicts_layout.setSizeConstraint(QLayout.SetFixedSize)
2018-08-09 19:34:49 +08:00
2018-08-27 20:59:15 +08:00
def build_layout(self):
2018-07-13 22:09:07 +08:00
'''
build dictionaryfields etc
'''
2018-08-10 12:05:03 +08:00
if self._was_built:
2018-08-09 19:34:49 +08:00
return
2018-08-10 12:05:03 +08:00
del self._options[:]
self._last_checkeds = None
self._was_built = True
2018-07-01 10:55:30 +08:00
2018-08-09 19:34:49 +08:00
model = self._model
maps = self._conf
2018-07-01 10:55:30 +08:00
2018-08-10 15:08:01 +08:00
# labels
f = QFont()
f.setBold(True)
labels = [u'', '', 'DICTS', 'DICT_FIELDS', '']
for i, s in enumerate(labels):
if s:
label = QLabel(_(s))
label.setFont(f)
label.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Fixed)
self.dicts_layout.addWidget(label, 0, i)
# ignore all
self.ignore_all_check_btn = QCheckBox(_('SELECT_ALL'))
self.ignore_all_check_btn.setFont(f)
self.ignore_all_check_btn.setEnabled(True)
self.ignore_all_check_btn.setChecked(True)
self.dicts_layout.addWidget(self.ignore_all_check_btn, 0, 1)
self.ignore_all_check_btn.clicked.connect(self.ignore_all_check_changed)
# Skip valued all
self.skip_all_check_btn = QCheckBox(_('SELECT_ALL'))
self.skip_all_check_btn.setFont(f)
self.skip_all_check_btn.setEnabled(True)
self.skip_all_check_btn.setChecked(True)
self.dicts_layout.addWidget(self.skip_all_check_btn, 0, 4)
self.skip_all_check_btn.clicked.connect(self.skip_all_check_changed)
2018-08-27 20:59:15 +08:00
2018-08-10 15:08:01 +08:00
# dict & fields
2018-07-31 02:21:35 +08:00
self.radio_group = 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-31 02:21:35 +08:00
self.add_dict_layout(i, fld_name=name, fld_ord=ord, word_checked=i==0)
2018-07-01 10:55:30 +08:00
else:
2018-07-31 02:21:35 +08:00
self.add_dict_layout(i, fld_name=name, fld_ord=ord, word_checked=i==0)
2018-08-10 15:08:01 +08:00
# update
self.ignore_all_update()
self.skip_all_update()
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
"""
2018-07-31 02:21:35 +08:00
word_checked = kwargs.get('word_checked', False)
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, cloze = (
kwargs.get('ignore', True), #忽略标志
kwargs.get('skip_valued', True), #略过有值项标志
kwargs.get('cloze_word', False), #单词填空
)
2018-08-10 12:05:03 +08:00
# check
2018-07-31 02:21:35 +08:00
word_check_btn = QRadioButton(fld_name)
word_check_btn.setSizePolicy(QSizePolicy.Fixed, 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-31 02:21:35 +08:00
dict_combo = QComboBox()
2018-08-10 15:08:01 +08:00
dict_combo.setMinimumSize(WIDGET_SIZE.map_dict_width, 0)
dict_combo.setMaximumSize(
WIDGET_SIZE.map_dict_width,
WIDGET_SIZE.map_max_height
)
2018-07-01 10:55:30 +08:00
dict_combo.setFocusPolicy(
2018-07-31 02:21:35 +08:00
Qt.TabFocus | Qt.ClickFocus | Qt.StrongFocus | Qt.WheelFocus
)
2018-08-15 00:46:46 +08:00
ignore = not self.fill_dict_combo_options(dict_combo, dict_unique, self._services) or ignore
2018-07-13 00:57:53 +08:00
dict_unique = dict_combo.itemData(dict_combo.currentIndex())
2018-08-15 00:46:46 +08:00
dict_combo.setEnabled(not word_checked and not ignore)
# field combox
2018-07-31 02:21:35 +08:00
field_combo = QComboBox()
2018-08-10 15:08:01 +08:00
field_combo.setMinimumSize(WIDGET_SIZE.map_field_width, 0)
field_combo.setMaximumSize(
WIDGET_SIZE.map_field_width,
WIDGET_SIZE.map_max_height
)
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)
2018-08-27 20:59:15 +08:00
# ignore
2018-07-31 02:21:35 +08:00
ignore_check_btn = QCheckBox(_("NOT_DICT_FIELD"))
2018-07-13 22:09:07 +08:00
ignore_check_btn.setEnabled(not word_checked)
ignore_check_btn.setChecked(ignore)
# Skip valued
2018-07-31 02:21:35 +08:00
skip_check_btn = QCheckBox(_("SKIP_VALUED"))
2018-07-13 22:09:07 +08:00
skip_check_btn.setEnabled(not word_checked and not ignore)
skip_check_btn.setChecked(skip)
# Skip valued
cloze_check_btn = QCheckBox(_("CLOZE_WORD"))
cloze_check_btn.setEnabled(not word_checked and not ignore)
cloze_check_btn.setChecked(cloze)
# events
# word
def radio_btn_checked():
2018-08-10 12:05:03 +08:00
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)
2018-08-28 21:49:33 +08:00
cloze_check_btn.setEnabled(not word_checked and not ignore)
if word_checked:
2018-08-10 12:05:03 +08:00
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:
2018-08-10 12:05:03 +08:00
self._last_checkeds = None
radio_btn_checked()
# ignor
def ignore_check_changed():
2018-08-10 15:08:01 +08:00
word_checked = word_check_btn.isChecked()
ignore = ignore_check_btn.isChecked()
dict_combo.setEnabled(not word_checked and not ignore)
field_combo.setEnabled(not word_checked and not ignore)
skip_check_btn.setEnabled(not word_checked and not ignore)
2018-08-28 21:49:33 +08:00
cloze_check_btn.setEnabled(not word_checked and not ignore)
2018-08-10 15:08:01 +08:00
ignore_check_btn.stateChanged.connect(ignore_check_changed)
ignore_check_btn.clicked.connect(self.ignore_all_update)
# skip
skip_check_btn.clicked.connect(self.skip_all_update)
# 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-08-27 20:59:15 +08:00
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)
self.dicts_layout.addWidget(cloze_check_btn, i + 1, 5)
2018-08-27 20:59:15 +08:00
2018-08-10 12:05:03 +08:00
self._options.append({
2018-07-13 22:09:07 +08:00
'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,
'cloze_check_btn': cloze_check_btn
2018-07-13 22:09:07 +08:00
})
2018-07-01 10:55:30 +08:00
2018-08-10 12:05:03 +08:00
def fill_dict_combo_options(self, dict_combo, current_unique, services):
2018-08-09 19:34:49 +08:00
'''setup dict combo box'''
dict_combo.clear()
# local dict service
2018-08-10 12:05:03 +08:00
for service in services['local']:
2018-08-12 11:26:57 +08:00
dict_combo.addItem(service['title'], userData=service['unique'])
2018-08-09 19:34:49 +08:00
# hr
2018-08-10 12:05:03 +08:00
if len(services['local']) > 0:
2018-08-09 19:34:49 +08:00
dict_combo.insertSeparator(dict_combo.count())
# web dict service
2018-08-10 12:05:03 +08:00
for service in services['web']:
2018-08-12 11:26:57 +08:00
dict_combo.addItem(service['title'], userData=service['unique'])
2018-08-09 19:34:49 +08:00
def set_dict_combo_index():
dict_combo.setCurrentIndex(0)
if current_unique:
for i in range(dict_combo.count()):
if dict_combo.itemData(i) == current_unique:
dict_combo.setCurrentIndex(i)
2018-08-15 00:46:46 +08:00
return True
return False
return set_dict_combo_index()
2018-08-09 19:34:49 +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'''
field_combo.clear()
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'):
text = dict_fld_name if dict_fld_name else 'http://'
field_combo.setEditable(True)
field_combo.setEditText(text)
field_combo.setFocus(Qt.MouseFocusReason) # MouseFocusReason
else:
unique = dict_combo_itemdata
service = service_pool.get(unique)
# problem
field_combo.setCurrentIndex(0)
if service and service.support and service.fields:
for i, each in enumerate(service.fields):
field_combo.addItem(each, userData=i)
if each == dict_fld_name or i == dict_fld_ord:
field_combo.setCurrentIndex(i)
service_pool.put(service)
@property
def data(self):
2018-08-10 12:05:03 +08:00
if not self._was_built:
2018-08-09 19:34:49 +08:00
return self._conf
2018-07-13 22:09:07 +08:00
maps = []
2018-08-10 12:05:03 +08:00
for row in self._options:
2018-07-13 22:09:07 +08:00
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(),
'cloze_word': row['cloze_check_btn'].isChecked()
2018-07-13 22:09:07 +08:00
})
2018-08-09 19:34:49 +08:00
return maps
2018-08-10 15:08:01 +08:00
def ignore_all_check_changed(self):
b = self.ignore_all_check_btn.isChecked()
for row in self._options:
row['ignore_check_btn'].setChecked(b)
def skip_all_check_changed(self):
b = self.skip_all_check_btn.isChecked()
for row in self._options:
row['skip_check_btn'].setChecked(b)
def ignore_all_update(self):
b = True
for row in self._options:
if not row['ignore_check_btn'].isChecked():
b = False
break
self.ignore_all_check_btn.setChecked(b)
def skip_all_update(self):
b = True
for row in self._options:
if not row['skip_check_btn'].isChecked():
b = False
break
self.skip_all_check_btn.setChecked(b)
2018-09-10 02:47:15 +08:00
class CTabBar(QTabBar):
def __init__(self, parent = None):
super(CTabBar, self).__init__(parent)
# style
self.setTabsClosable(True)
self.setMovable(False)
self.setExpanding(False)
self.setDrawBase(False)
# edit
self._editor = QLineEdit(self)
self._editor.setWindowFlags(Qt.Popup)
self._editor.setMaxLength(20)
self._editor.editingFinished.connect(self.handleEditingFinished)
self._editor.installEventFilter(self)
def eventFilter(self, widget, event):
if ((event.type() == QEvent.MouseButtonPress and \
not self._editor.geometry().contains(event.globalPos()) \
) or \
(event.type() == QEvent.KeyPress and \
event.key() == Qt.Key_Escape)
):
self.hideEditor()
return True
return QTabBar.eventFilter(self, widget, event)
def mouseDoubleClickEvent(self, event):
index = self.tabAt(event.pos())
if index >= 0:
self.editTab(index)
def editTab(self, index):
rect = self.tabRect(index)
self._editor.setFixedSize(rect.size())
self._editor.move(self.parent().mapToGlobal(rect.topLeft()))
self._editor.setText(self.tabText(index))
if not self._editor.isVisible():
self._editor.show()
self._editor.selectAll()
self._editor.setEnabled(True)
self._editor.setFocus()
def hideEditor(self):
if self._editor.isVisible():
self._editor.setEnabled(False)
self._editor.clearFocus()
self._editor.hide()
def handleEditingFinished(self):
index = self.currentIndex()
if index >= 0:
self.hideEditor()
if self._editor.text():
self.setTabText(index, self._editor.text())