diff --git a/addons/fastwq/gui/base.py b/addons/fastwq/gui/base.py index 292c849..41f2023 100644 --- a/addons/fastwq/gui/base.py +++ b/addons/fastwq/gui/base.py @@ -55,7 +55,7 @@ class WidgetSize(object): ''' constant values ''' - dialog_width = 730 + dialog_width = 850 dialog_height_margin = 146 map_min_height = 0 map_max_height = 30 diff --git a/addons/fastwq/gui/options.py b/addons/fastwq/gui/options.py index 663f9f1..047ff25 100644 --- a/addons/fastwq/gui/options.py +++ b/addons/fastwq/gui/options.py @@ -407,9 +407,10 @@ class TabContent(QScrollArea): kwargs.get('dcit_fld_ord', 0) #对应字典的字段编号 ) - ignore, skip = ( + ignore, skip, cloze = ( kwargs.get('ignore', True), #忽略标志 kwargs.get('skip_valued', True), #略过有值项标志 + kwargs.get('cloze_word', False), #单词填空 ) # check @@ -451,6 +452,11 @@ class TabContent(QScrollArea): 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(): @@ -503,6 +509,7 @@ class TabContent(QScrollArea): self.dicts_layout.addWidget(dict_combo, i + 1, 2) self.dicts_layout.addWidget(field_combo, i + 1, 3) self.dicts_layout.addWidget(skip_check_btn, i + 1, 4) + self.dicts_layout.addWidget(cloze_check_btn, i + 1, 5) self._options.append({ 'model': {'fld_name': fld_name, 'fld_ord': fld_ord}, @@ -510,7 +517,8 @@ class TabContent(QScrollArea): 'dict_combo': dict_combo, 'field_combo': field_combo, 'ignore_check_btn': ignore_check_btn, - 'skip_check_btn': skip_check_btn + 'skip_check_btn': skip_check_btn, + 'cloze_check_btn': cloze_check_btn }) def fill_dict_combo_options(self, dict_combo, current_unique, services): @@ -578,7 +586,8 @@ class TabContent(QScrollArea): '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() + 'skip_valued': row['skip_check_btn'].isChecked(), + 'cloze_word': row['cloze_check_btn'].isChecked() }) return maps diff --git a/addons/fastwq/lang.py b/addons/fastwq/lang.py index 8d7b331..49bf1d4 100644 --- a/addons/fastwq/lang.py +++ b/addons/fastwq/lang.py @@ -77,6 +77,7 @@ _arr = [ ['ALL_FIELDS', u'所有字段', u'All Fields'], ['CURRENT_FIELDS', u'当前字段', u'Current Fields'], ['OPTIONS', u'选项', u'Options'], + ['CLOZE_WORD', u'单词填空', u'Cloze word'], ['BRE_PRON', u'英式发音', u'British Pronunciation'], ['AME_PRON', u'美式发音', u'American Pronunciation'], diff --git a/addons/fastwq/query/common.py b/addons/fastwq/query/common.py index 0a48b03..f055486 100644 --- a/addons/fastwq/query/common.py +++ b/addons/fastwq/query/common.py @@ -17,12 +17,15 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -from collections import defaultdict + import os +import re import io import shutil import unicodedata -from PyQt4 import QtGui + +from collections import defaultdict +from aqt.qt import * from aqt.utils import showInfo from ..constants import Template @@ -130,7 +133,7 @@ def promot_choose_css(missed_css): try: filepath = css['dict_path'][:css['dict_path'].rindex( os.path.sep)+1] - filepath = QtGui.QFileDialog.getOpenFileName( + filepath = QFileDialog.getOpenFileName( directory=filepath, caption=u'Choose css file', filter=u'CSS (*.css)' @@ -207,6 +210,8 @@ def query_flds(note, fileds=None): skip = each.get('skip_valued', False) if skip and len(note.fields[i]) != 0: continue + #cloze + cloze = each.get('cloze_word', False) #normal dict_unique = each.get('dict_unique', '').strip() dict_fld_ord = each.get('dict_fld_ord', -1) @@ -219,8 +224,13 @@ def query_flds(note, fileds=None): if s and s.support: services[dict_unique] = s if s and s.support: - tasks.append({'k': dict_unique, 'w': word, - 'f': dict_fld_ord, 'i': fld_ord}) + tasks.append({ + 'k': dict_unique, + 'w': word, + 'f': dict_fld_ord, + 'i': fld_ord, + 'cloze': cloze, + }) success_num = 0 result = defaultdict(QueryResult) @@ -229,6 +239,8 @@ def query_flds(note, fileds=None): service = services.get(task['k'], None) qr = service.active(task['f'], task['w']) if qr: + if task['cloze']: + qr['result'] = cloze_deletion(qr['result'], word) result.update({task['i']: qr}) success_num += 1 #except: @@ -247,3 +259,18 @@ def query_flds(note, fileds=None): service_pool.put(service) return result, -1 if len(tasks) == 0 else success_num, missed_css + + +def cloze_deletion(text, term): + '''create cloze deletion text''' + result = text + words = re.finditer(r"\b" + re.escape(term) + r"\b", text, flags=re.IGNORECASE) + words = [m.start() for m in words][::-1] + index = 1 + for word in words: + if not text[word - 1].isalnum() or text[word + len(term)].isalnum(): + if not "{{" in text[word:word + len(term)] or "}}" in text[word:word + len(term)]: + result = result[:word + len(term)] + "}}" + result[word + len(term):] + result = result[:word] + "{{c" + str(index) + "::" + result[word:] + index += 1 + return result diff --git a/addons21/fastwq/gui/base.py b/addons21/fastwq/gui/base.py index 292c849..41f2023 100644 --- a/addons21/fastwq/gui/base.py +++ b/addons21/fastwq/gui/base.py @@ -55,7 +55,7 @@ class WidgetSize(object): ''' constant values ''' - dialog_width = 730 + dialog_width = 850 dialog_height_margin = 146 map_min_height = 0 map_max_height = 30 diff --git a/addons21/fastwq/gui/options.py b/addons21/fastwq/gui/options.py index 663f9f1..047ff25 100644 --- a/addons21/fastwq/gui/options.py +++ b/addons21/fastwq/gui/options.py @@ -407,9 +407,10 @@ class TabContent(QScrollArea): kwargs.get('dcit_fld_ord', 0) #对应字典的字段编号 ) - ignore, skip = ( + ignore, skip, cloze = ( kwargs.get('ignore', True), #忽略标志 kwargs.get('skip_valued', True), #略过有值项标志 + kwargs.get('cloze_word', False), #单词填空 ) # check @@ -451,6 +452,11 @@ class TabContent(QScrollArea): 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(): @@ -503,6 +509,7 @@ class TabContent(QScrollArea): self.dicts_layout.addWidget(dict_combo, i + 1, 2) self.dicts_layout.addWidget(field_combo, i + 1, 3) self.dicts_layout.addWidget(skip_check_btn, i + 1, 4) + self.dicts_layout.addWidget(cloze_check_btn, i + 1, 5) self._options.append({ 'model': {'fld_name': fld_name, 'fld_ord': fld_ord}, @@ -510,7 +517,8 @@ class TabContent(QScrollArea): 'dict_combo': dict_combo, 'field_combo': field_combo, 'ignore_check_btn': ignore_check_btn, - 'skip_check_btn': skip_check_btn + 'skip_check_btn': skip_check_btn, + 'cloze_check_btn': cloze_check_btn }) def fill_dict_combo_options(self, dict_combo, current_unique, services): @@ -578,7 +586,8 @@ class TabContent(QScrollArea): '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() + 'skip_valued': row['skip_check_btn'].isChecked(), + 'cloze_word': row['cloze_check_btn'].isChecked() }) return maps diff --git a/addons21/fastwq/lang.py b/addons21/fastwq/lang.py index 8d7b331..49bf1d4 100644 --- a/addons21/fastwq/lang.py +++ b/addons21/fastwq/lang.py @@ -77,6 +77,7 @@ _arr = [ ['ALL_FIELDS', u'所有字段', u'All Fields'], ['CURRENT_FIELDS', u'当前字段', u'Current Fields'], ['OPTIONS', u'选项', u'Options'], + ['CLOZE_WORD', u'单词填空', u'Cloze word'], ['BRE_PRON', u'英式发音', u'British Pronunciation'], ['AME_PRON', u'美式发音', u'American Pronunciation'], diff --git a/addons21/fastwq/query/common.py b/addons21/fastwq/query/common.py index 18b08f4..fc2c66b 100644 --- a/addons21/fastwq/query/common.py +++ b/addons21/fastwq/query/common.py @@ -17,10 +17,14 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -from collections import defaultdict + import os +import re +import io import shutil import unicodedata + +from collections import defaultdict from aqt.qt import * from aqt.utils import showInfo @@ -207,6 +211,8 @@ def query_flds(note, fileds=None): skip = each.get('skip_valued', False) if skip and len(note.fields[i]) != 0: continue + #cloze + cloze = each.get('cloze_word', False) #normal dict_unique = each.get('dict_unique', '').strip() dict_fld_ord = each.get('dict_fld_ord', -1) @@ -219,8 +225,13 @@ def query_flds(note, fileds=None): if s and s.support: services[dict_unique] = s if s and s.support: - tasks.append({'k': dict_unique, 'w': word, - 'f': dict_fld_ord, 'i': fld_ord}) + tasks.append({ + 'k': dict_unique, + 'w': word, + 'f': dict_fld_ord, + 'i': fld_ord, + 'cloze': cloze, + }) success_num = 0 result = defaultdict(QueryResult) @@ -229,6 +240,8 @@ def query_flds(note, fileds=None): service = services.get(task['k'], None) qr = service.active(task['f'], task['w']) if qr: + if task['cloze']: + qr['result'] = cloze_deletion(qr['result'], word) result.update({task['i']: qr}) success_num += 1 #except: @@ -247,3 +260,18 @@ def query_flds(note, fileds=None): service_pool.put(service) return result, -1 if len(tasks) == 0 else success_num, missed_css + + +def cloze_deletion(text, term): + '''create cloze deletion text''' + result = text + words = re.finditer(r"\b" + re.escape(term) + r"\b", text, flags=re.IGNORECASE) + words = [m.start() for m in words][::-1] + index = 1 + for word in words: + if not text[word - 1].isalnum() or text[word + len(term)].isalnum(): + if not "{{" in text[word:word + len(term)] or "}}" in text[word:word + len(term)]: + result = result[:word + len(term)] + "}}" + result[word + len(term):] + result = result[:word] + "{{c" + str(index) + "::" + result[word:] + index += 1 + return result