Edit book: Spell check: Add an exclude files button

This commit is contained in:
Kovid Goyal 2021-12-16 21:26:44 +05:30
parent a507bb01ce
commit d350a121d8
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
4 changed files with 67 additions and 5 deletions

View File

@ -680,8 +680,8 @@ common in your book and to run a simple search and replace on individual words.
.. note::
To exclude an individual file from being spell checked when running the
spell check tool, you can add the following comment just under the first
opening tag in the file::
spell check tool, you can use the :guilabel:`Exclude files` button or
and the following comment just under the opening tag in the file::
<!-- calibre-no-spell-check -->

View File

@ -283,12 +283,12 @@ def root_is_excluded_from_spell_check(root):
return False
def get_all_words(container, book_locale, get_word_count=False):
def get_all_words(container, book_locale, get_word_count=False, excluded_files=()):
words = defaultdict(list)
words[None] = 0
file_names, ncx_toc = get_checkable_file_names(container)
for file_name in file_names:
if not container.exists(file_name):
if not container.exists(file_name) or file_name in excluded_files:
continue
root = container.parsed(file_name)
if root_is_excluded_from_spell_check(root):

View File

@ -360,6 +360,7 @@ class Boss(QObject):
if cn:
self.save_manager.clear_notify_data()
self.gui.check_book.clear_at_startup()
self.gui.spell_check.clear_caches()
dictionaries.clear_ignored(), dictionaries.clear_caches()
parse_worker.clear()
container = job.result

View File

@ -21,6 +21,7 @@ from qt.core import (
from threading import Thread
from calibre.constants import __appname__
from calibre.ebooks.oeb.base import OEB_DOCS, NCX_MIME, OPF_MIME
from calibre.ebooks.oeb.polish.spell import (
get_all_words, get_checkable_file_names, merge_locations, replace_word,
undo_replace_word
@ -912,6 +913,41 @@ class WordsView(QTableView):
return self.model().word_for_row(self.currentIndex().row())
class ManageExcludedFiles(Dialog):
def __init__(self, parent, excluded_files):
self.orig_excluded_files = frozenset(excluded_files)
super().__init__(_('Exclude files from spell check'), 'spell-check-exclude-files2', parent)
def sizeHint(self):
return QSize(500, 600)
def setup_ui(self):
self.la = la = QLabel(_(
'Choose the files to exclude below. In addition to this list any file'
' can be permanently excluded by adding the comment {} just under its opening tag.').format(
'<!-- calibre-no-spell-check -->'))
la.setWordWrap(True)
la.setTextFormat(Qt.TextFormat.PlainText)
self.l = l = QVBoxLayout(self)
l.addWidget(la)
self.files = QListWidget(self)
self.files.setSelectionMode(QAbstractItemView.SelectionMode.MultiSelection)
cc = current_container()
for name, mt in cc.mime_map.items():
if mt in OEB_DOCS or mt in (NCX_MIME, OPF_MIME):
i = QListWidgetItem(self.files)
i.setText(name)
if name in self.orig_excluded_files:
i.setSelected(True)
l.addWidget(self.files)
l.addWidget(self.bb)
@property
def excluded_files(self):
return {item.text() for item in self.files.selectedItems()}
class SpellCheck(Dialog):
work_finished = pyqtSignal(object, object, object)
@ -929,6 +965,7 @@ class SpellCheck(Dialog):
self.current_word_changed_timer = t = QTimer()
t.timeout.connect(self.do_current_word_changed)
t.setSingleShot(True), t.setInterval(100)
self.excluded_files = set()
Dialog.__init__(self, _('Check spelling'), 'spell-check', parent)
self.work_finished.connect(self.work_done, type=Qt.ConnectionType.QueuedConnection)
self.setAttribute(Qt.WidgetAttribute.WA_DeleteOnClose, False)
@ -952,6 +989,11 @@ class SpellCheck(Dialog):
b.setToolTip('<p>' + _('Undo the last spell check word replacement, if any'))
b.setIcon(QIcon(I('edit-undo.png')))
b.clicked.connect(self.undo_last_change)
b = self.exclude_button = self.bb.addButton('', QDialogButtonBox.ButtonRole.ActionRole)
b.setToolTip('<p>' + _('Exclude some files in the book from spell check'))
b.setIcon(QIcon(I('chapters.png')))
b.clicked.connect(self.change_excluded_files)
self.update_exclude_button()
self.progress = p = QWidget(self)
s.addWidget(p)
@ -1062,6 +1104,25 @@ class SpellCheck(Dialog):
return
return Dialog.keyPressEvent(self, ev)
def change_excluded_files(self):
d = ManageExcludedFiles(self, self.excluded_files)
if d.exec_() == QDialog.DialogCode.Accepted:
new = d.excluded_files
if new != self.excluded_files:
self.excluded_files = new
self.update_exclude_button()
self.refresh()
def clear_caches(self):
self.excluded_files = set()
self.update_exclude_button()
def update_exclude_button(self):
t = _('E&xclude files')
if self.excluded_files:
t += f' ({len(self.excluded_files)})'
self.exclude_button.setText(t)
def sort_type_changed(self):
tprefs['spell_check_case_sensitive_sort'] = bool(self.case_sensitive_sort.isChecked())
if self.words_model.sort_on[0] == 0:
@ -1257,7 +1318,7 @@ class SpellCheck(Dialog):
def get_words(self, change_request=None):
try:
words = get_all_words(current_container(), dictionaries.default_locale)
words = get_all_words(current_container(), dictionaries.default_locale, excluded_files=self.excluded_files)
spell_map = {w:dictionaries.recognized(*w) for w in words}
except:
import traceback