Support cloze deletion words option. fix #46

This commit is contained in:
St.Huang 2018-08-28 16:59:57 +08:00
parent a0757644e8
commit 12f6b1e8c9
8 changed files with 91 additions and 16 deletions

View File

@ -55,7 +55,7 @@ class WidgetSize(object):
''' '''
constant values constant values
''' '''
dialog_width = 730 dialog_width = 850
dialog_height_margin = 146 dialog_height_margin = 146
map_min_height = 0 map_min_height = 0
map_max_height = 30 map_max_height = 30

View File

@ -407,9 +407,10 @@ class TabContent(QScrollArea):
kwargs.get('dcit_fld_ord', 0) #对应字典的字段编号 kwargs.get('dcit_fld_ord', 0) #对应字典的字段编号
) )
ignore, skip = ( ignore, skip, cloze = (
kwargs.get('ignore', True), #忽略标志 kwargs.get('ignore', True), #忽略标志
kwargs.get('skip_valued', True), #略过有值项标志 kwargs.get('skip_valued', True), #略过有值项标志
kwargs.get('cloze_word', False), #单词填空
) )
# check # check
@ -451,6 +452,11 @@ class TabContent(QScrollArea):
skip_check_btn.setEnabled(not word_checked and not ignore) skip_check_btn.setEnabled(not word_checked and not ignore)
skip_check_btn.setChecked(skip) 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 # events
# word # word
def radio_btn_checked(): def radio_btn_checked():
@ -503,6 +509,7 @@ class TabContent(QScrollArea):
self.dicts_layout.addWidget(dict_combo, i + 1, 2) self.dicts_layout.addWidget(dict_combo, i + 1, 2)
self.dicts_layout.addWidget(field_combo, i + 1, 3) self.dicts_layout.addWidget(field_combo, i + 1, 3)
self.dicts_layout.addWidget(skip_check_btn, i + 1, 4) self.dicts_layout.addWidget(skip_check_btn, i + 1, 4)
self.dicts_layout.addWidget(cloze_check_btn, i + 1, 5)
self._options.append({ self._options.append({
'model': {'fld_name': fld_name, 'fld_ord': fld_ord}, 'model': {'fld_name': fld_name, 'fld_ord': fld_ord},
@ -510,7 +517,8 @@ class TabContent(QScrollArea):
'dict_combo': dict_combo, 'dict_combo': dict_combo,
'field_combo': field_combo, 'field_combo': field_combo,
'ignore_check_btn': ignore_check_btn, '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): 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_name': row['field_combo'].currentText().strip(),
'dict_fld_ord': row['field_combo'].itemData(row['field_combo'].currentIndex()), 'dict_fld_ord': row['field_combo'].itemData(row['field_combo'].currentIndex()),
'ignore': row['ignore_check_btn'].isChecked(), '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 return maps

View File

@ -77,6 +77,7 @@ _arr = [
['ALL_FIELDS', u'所有字段', u'All Fields'], ['ALL_FIELDS', u'所有字段', u'All Fields'],
['CURRENT_FIELDS', u'当前字段', u'Current Fields'], ['CURRENT_FIELDS', u'当前字段', u'Current Fields'],
['OPTIONS', u'选项', u'Options'], ['OPTIONS', u'选项', u'Options'],
['CLOZE_WORD', u'单词填空', u'Cloze word'],
['BRE_PRON', u'英式发音', u'British Pronunciation'], ['BRE_PRON', u'英式发音', u'British Pronunciation'],
['AME_PRON', u'美式发音', u'American Pronunciation'], ['AME_PRON', u'美式发音', u'American Pronunciation'],

View File

@ -17,12 +17,15 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
from collections import defaultdict
import os import os
import re
import io import io
import shutil import shutil
import unicodedata import unicodedata
from PyQt4 import QtGui
from collections import defaultdict
from aqt.qt import *
from aqt.utils import showInfo from aqt.utils import showInfo
from ..constants import Template from ..constants import Template
@ -130,7 +133,7 @@ def promot_choose_css(missed_css):
try: try:
filepath = css['dict_path'][:css['dict_path'].rindex( filepath = css['dict_path'][:css['dict_path'].rindex(
os.path.sep)+1] os.path.sep)+1]
filepath = QtGui.QFileDialog.getOpenFileName( filepath = QFileDialog.getOpenFileName(
directory=filepath, directory=filepath,
caption=u'Choose css file', caption=u'Choose css file',
filter=u'CSS (*.css)' filter=u'CSS (*.css)'
@ -207,6 +210,8 @@ def query_flds(note, fileds=None):
skip = each.get('skip_valued', False) skip = each.get('skip_valued', False)
if skip and len(note.fields[i]) != 0: if skip and len(note.fields[i]) != 0:
continue continue
#cloze
cloze = each.get('cloze_word', False)
#normal #normal
dict_unique = each.get('dict_unique', '').strip() dict_unique = each.get('dict_unique', '').strip()
dict_fld_ord = each.get('dict_fld_ord', -1) dict_fld_ord = each.get('dict_fld_ord', -1)
@ -219,8 +224,13 @@ def query_flds(note, fileds=None):
if s and s.support: if s and s.support:
services[dict_unique] = s services[dict_unique] = s
if s and s.support: if s and s.support:
tasks.append({'k': dict_unique, 'w': word, tasks.append({
'f': dict_fld_ord, 'i': fld_ord}) 'k': dict_unique,
'w': word,
'f': dict_fld_ord,
'i': fld_ord,
'cloze': cloze,
})
success_num = 0 success_num = 0
result = defaultdict(QueryResult) result = defaultdict(QueryResult)
@ -229,6 +239,8 @@ def query_flds(note, fileds=None):
service = services.get(task['k'], None) service = services.get(task['k'], None)
qr = service.active(task['f'], task['w']) qr = service.active(task['f'], task['w'])
if qr: if qr:
if task['cloze']:
qr['result'] = cloze_deletion(qr['result'], word)
result.update({task['i']: qr}) result.update({task['i']: qr})
success_num += 1 success_num += 1
#except: #except:
@ -247,3 +259,18 @@ def query_flds(note, fileds=None):
service_pool.put(service) service_pool.put(service)
return result, -1 if len(tasks) == 0 else success_num, missed_css 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

View File

@ -55,7 +55,7 @@ class WidgetSize(object):
''' '''
constant values constant values
''' '''
dialog_width = 730 dialog_width = 850
dialog_height_margin = 146 dialog_height_margin = 146
map_min_height = 0 map_min_height = 0
map_max_height = 30 map_max_height = 30

View File

@ -407,9 +407,10 @@ class TabContent(QScrollArea):
kwargs.get('dcit_fld_ord', 0) #对应字典的字段编号 kwargs.get('dcit_fld_ord', 0) #对应字典的字段编号
) )
ignore, skip = ( ignore, skip, cloze = (
kwargs.get('ignore', True), #忽略标志 kwargs.get('ignore', True), #忽略标志
kwargs.get('skip_valued', True), #略过有值项标志 kwargs.get('skip_valued', True), #略过有值项标志
kwargs.get('cloze_word', False), #单词填空
) )
# check # check
@ -451,6 +452,11 @@ class TabContent(QScrollArea):
skip_check_btn.setEnabled(not word_checked and not ignore) skip_check_btn.setEnabled(not word_checked and not ignore)
skip_check_btn.setChecked(skip) 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 # events
# word # word
def radio_btn_checked(): def radio_btn_checked():
@ -503,6 +509,7 @@ class TabContent(QScrollArea):
self.dicts_layout.addWidget(dict_combo, i + 1, 2) self.dicts_layout.addWidget(dict_combo, i + 1, 2)
self.dicts_layout.addWidget(field_combo, i + 1, 3) self.dicts_layout.addWidget(field_combo, i + 1, 3)
self.dicts_layout.addWidget(skip_check_btn, i + 1, 4) self.dicts_layout.addWidget(skip_check_btn, i + 1, 4)
self.dicts_layout.addWidget(cloze_check_btn, i + 1, 5)
self._options.append({ self._options.append({
'model': {'fld_name': fld_name, 'fld_ord': fld_ord}, 'model': {'fld_name': fld_name, 'fld_ord': fld_ord},
@ -510,7 +517,8 @@ class TabContent(QScrollArea):
'dict_combo': dict_combo, 'dict_combo': dict_combo,
'field_combo': field_combo, 'field_combo': field_combo,
'ignore_check_btn': ignore_check_btn, '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): 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_name': row['field_combo'].currentText().strip(),
'dict_fld_ord': row['field_combo'].itemData(row['field_combo'].currentIndex()), 'dict_fld_ord': row['field_combo'].itemData(row['field_combo'].currentIndex()),
'ignore': row['ignore_check_btn'].isChecked(), '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 return maps

View File

@ -77,6 +77,7 @@ _arr = [
['ALL_FIELDS', u'所有字段', u'All Fields'], ['ALL_FIELDS', u'所有字段', u'All Fields'],
['CURRENT_FIELDS', u'当前字段', u'Current Fields'], ['CURRENT_FIELDS', u'当前字段', u'Current Fields'],
['OPTIONS', u'选项', u'Options'], ['OPTIONS', u'选项', u'Options'],
['CLOZE_WORD', u'单词填空', u'Cloze word'],
['BRE_PRON', u'英式发音', u'British Pronunciation'], ['BRE_PRON', u'英式发音', u'British Pronunciation'],
['AME_PRON', u'美式发音', u'American Pronunciation'], ['AME_PRON', u'美式发音', u'American Pronunciation'],

View File

@ -17,10 +17,14 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
from collections import defaultdict
import os import os
import re
import io
import shutil import shutil
import unicodedata import unicodedata
from collections import defaultdict
from aqt.qt import * from aqt.qt import *
from aqt.utils import showInfo from aqt.utils import showInfo
@ -207,6 +211,8 @@ def query_flds(note, fileds=None):
skip = each.get('skip_valued', False) skip = each.get('skip_valued', False)
if skip and len(note.fields[i]) != 0: if skip and len(note.fields[i]) != 0:
continue continue
#cloze
cloze = each.get('cloze_word', False)
#normal #normal
dict_unique = each.get('dict_unique', '').strip() dict_unique = each.get('dict_unique', '').strip()
dict_fld_ord = each.get('dict_fld_ord', -1) dict_fld_ord = each.get('dict_fld_ord', -1)
@ -219,8 +225,13 @@ def query_flds(note, fileds=None):
if s and s.support: if s and s.support:
services[dict_unique] = s services[dict_unique] = s
if s and s.support: if s and s.support:
tasks.append({'k': dict_unique, 'w': word, tasks.append({
'f': dict_fld_ord, 'i': fld_ord}) 'k': dict_unique,
'w': word,
'f': dict_fld_ord,
'i': fld_ord,
'cloze': cloze,
})
success_num = 0 success_num = 0
result = defaultdict(QueryResult) result = defaultdict(QueryResult)
@ -229,6 +240,8 @@ def query_flds(note, fileds=None):
service = services.get(task['k'], None) service = services.get(task['k'], None)
qr = service.active(task['f'], task['w']) qr = service.active(task['f'], task['w'])
if qr: if qr:
if task['cloze']:
qr['result'] = cloze_deletion(qr['result'], word)
result.update({task['i']: qr}) result.update({task['i']: qr})
success_num += 1 success_num += 1
#except: #except:
@ -247,3 +260,18 @@ def query_flds(note, fileds=None):
service_pool.put(service) service_pool.put(service)
return result, -1 if len(tasks) == 0 else success_num, missed_css 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