Skip to content

Commit

Permalink
Edit book: Spell check: Add options to exclude words in ALL CAPS or w…
Browse files Browse the repository at this point in the history
…ith numbers or in camelCase/snake_case from the list of words
  • Loading branch information
kovidgoyal committed Apr 29, 2024
1 parent 6c0edaf commit 275d670
Showing 1 changed file with 51 additions and 4 deletions.
55 changes: 51 additions & 4 deletions src/calibre/gui2/tweak_book/spell.py
Expand Up @@ -11,6 +11,7 @@
from itertools import chain
from threading import Thread

import regex
from qt.core import (
QT_VERSION_STR,
QAbstractItemView,
Expand Down Expand Up @@ -75,7 +76,7 @@
)
from calibre.spell.import_from import import_from_online, import_from_oxt
from calibre.startup import connect_lambda
from calibre.utils.icu import contains, primary_contains, primary_sort_key, sort_key
from calibre.utils.icu import contains, primary_contains, primary_sort_key, sort_key, upper
from calibre.utils.localization import calibre_langcode_to_name, canonicalize_lang, get_lang, get_language
from calibre.utils.resources import get_path as P
from calibre_extensions.progress_indicator import set_no_activate_on_click
Expand Down Expand Up @@ -726,6 +727,7 @@ class WordsModel(QAbstractTableModel):
def __init__(self, parent=None):
QAbstractTableModel.__init__(self, parent)
self.counts = (0, 0)
self.all_caps = self.with_numbers = self.camel_case = self.snake_case = False
self.words = {} # Map of (word, locale) to location data for the word
self.spell_map = {} # Map of (word, locale) to dictionaries.recognized(word, locale)
self.sort_on = (0, False)
Expand All @@ -734,6 +736,9 @@ def __init__(self, parent=None):
self.show_only_misspelt = True
self.headers = (_('Word'), _('Count'), _('Language'), _('Misspelled?'))
self.alignments = Qt.AlignmentFlag.AlignLeft, Qt.AlignmentFlag.AlignRight, Qt.AlignmentFlag.AlignLeft, Qt.AlignmentFlag.AlignHCenter
self.num_pat = regex.compile(r'\d', flags=regex.UNICODE)
self.camel_case_pat = regex.compile(r'[a-z][A-Z]', flags=regex.UNICODE)
self.snake_case_pat = regex.compile(r'\w_\w', flags=regex.UNICODE)

def rowCount(self, parent=QModelIndex()):
return len(self.items)
Expand Down Expand Up @@ -794,8 +799,10 @@ def sort(self, column, order=Qt.SortOrder.AscendingOrder):
self.do_sort()
self.endResetModel()

def filter(self, filter_text):
def filter(self, filter_text, *, all_caps=False, with_numbers=False, camel_case=False, snake_case=False):
self.filter_expression = filter_text or None
self.all_caps, self.with_numbers = all_caps, with_numbers
self.camel_case, self.snake_case = camel_case, snake_case
self.beginResetModel()
self.do_filter()
self.do_sort()
Expand Down Expand Up @@ -839,7 +846,16 @@ def filter_item(self, x):
if self.show_only_misspelt and self.spell_map[x]:
return False
func = contains if tprefs['spell_check_case_sensitive_search'] else primary_contains
if self.filter_expression is not None and not func(self.filter_expression, x[0]):
word = x[0]
if self.filter_expression is not None and not func(self.filter_expression, word):
return False
if self.all_caps and upper(word) == word:
return False
if self.with_numbers and self.num_pat.search(word) is not None:
return False
if self.camel_case and self.camel_case_pat.search(word) is not None:
return False
if self.snake_case and self.snake_case_pat.search(word) is not None:
return False
return True

Expand Down Expand Up @@ -1149,6 +1165,27 @@ def setup_ui(self):
t.textChanged.connect(self.do_filter)
t.setClearButtonEnabled(True)
l.addWidget(t)
h = QHBoxLayout()
l.addLayout(h)
h.addWidget(QLabel(_('Also hide words:')))
any_hide_checked = False
def hw(name, title, tooltip):
nonlocal any_hide_checked
ac = QCheckBox(title)
pref_name = f'spell-check-hide-words-{name}'
ac.setObjectName(pref_name)
ac.setChecked(tprefs.get(pref_name, False))
if ac.isChecked():
any_hide_checked = True
ac.toggled.connect(self.hide_words_toggled)
ac.setToolTip(tooltip)
h.addWidget(ac)
return ac
self.all_caps = hw('all-caps', _('ALL CAPS'), _('Hide words with all capital letters'))
self.with_numbers = hw('with-numbers', _('with numbers'), _('Hide words that contain numbers'))
self.camel_case = hw('camel-case', _('camelCase'), _('Hide words in camelCase'))
self.snake_case = hw('snake-case', _('snake_case'), _('Hide words in snake_case'))
h.addStretch(10)

m.h2 = h = QHBoxLayout()
l.addLayout(h)
Expand Down Expand Up @@ -1252,6 +1289,14 @@ def button_action(sc, tt, button):

self.action_change_word = button_action('ctrl+right', _('Change all occurrences of this word'), self.change_button)
self.action_show_next_occurrence = button_action('alt+right', _('Show next occurrence of this word in the book'), self.next_occurrence)
if any_hide_checked:
QTimer.singleShot(0, self.do_filter)

def hide_words_toggled(self, checked):
cb = self.sender()
pref_name = cb.objectName()
tprefs.set(pref_name, checked)
self.do_filter()

def next_word(self):
v = self.suggested_list if self.focusWidget() is self.suggested_list else self.words_view
Expand Down Expand Up @@ -1465,7 +1510,9 @@ def __exit__(self, *args):
def do_filter(self):
text = str(self.filter_text.text()).strip()
with self:
self.words_model.filter(text)
self.words_model.filter(
text, all_caps=self.all_caps.isChecked(), with_numbers=self.with_numbers.isChecked(),
camel_case=self.camel_case.isChecked(), snake_case=self.snake_case.isChecked())

def refresh(self, change_request=None):
if not self.isVisible():
Expand Down

0 comments on commit 275d670

Please sign in to comment.