mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Edit Book: Spell check dialog: Add a button to undo the last spelling change
This commit is contained in:
parent
155c35f765
commit
02b8f775cb
@ -221,7 +221,7 @@ def replace(text, original_word, new_word, lang):
|
|||||||
text = text[:idx] + new_word + text[idx+len(original_word):]
|
text = text[:idx] + new_word + text[idx+len(original_word):]
|
||||||
return text, bool(indices)
|
return text, bool(indices)
|
||||||
|
|
||||||
def replace_word(container, new_word, locations, locale):
|
def replace_word(container, new_word, locations, locale, undo_cache=None):
|
||||||
changed = set()
|
changed = set()
|
||||||
for loc in locations:
|
for loc in locations:
|
||||||
node = loc.location_node
|
node = loc.location_node
|
||||||
@ -231,16 +231,26 @@ def replace_word(container, new_word, locations, locale):
|
|||||||
else:
|
else:
|
||||||
text = getattr(node, attr)
|
text = getattr(node, attr)
|
||||||
replacement = loc.elided_prefix + new_word
|
replacement = loc.elided_prefix + new_word
|
||||||
text, replaced = replace(text, loc.original_word, replacement, locale.langcode)
|
rtext, replaced = replace(text, loc.original_word, replacement, locale.langcode)
|
||||||
if replaced:
|
if replaced:
|
||||||
|
if undo_cache is not None:
|
||||||
|
undo_cache[(loc.file_name, node, is_attr, attr)] = text
|
||||||
if is_attr:
|
if is_attr:
|
||||||
node.set(attr, text)
|
node.set(attr, rtext)
|
||||||
else:
|
else:
|
||||||
setattr(node, attr, text)
|
setattr(node, attr, rtext)
|
||||||
container.replace(loc.file_name, node.getroottree().getroot())
|
container.replace(loc.file_name, node.getroottree().getroot())
|
||||||
changed.add(loc.file_name)
|
changed.add(loc.file_name)
|
||||||
return changed
|
return changed
|
||||||
|
|
||||||
|
def undo_replace_word(container, undo_cache):
|
||||||
|
changed = set()
|
||||||
|
for (file_name, node, is_attr, attr), text in undo_cache.iteritems():
|
||||||
|
node.set(attr, text) if is_attr else setattr(node, attr, text)
|
||||||
|
container.replace(file_name, node.getroottree().getroot())
|
||||||
|
changed.add(file_name)
|
||||||
|
return changed
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
import pprint
|
import pprint
|
||||||
from calibre.gui2.tweak_book import set_book_locale, dictionaries
|
from calibre.gui2.tweak_book import set_book_locale, dictionaries
|
||||||
|
@ -20,7 +20,7 @@ from PyQt5.Qt import (
|
|||||||
QT_VERSION_STR)
|
QT_VERSION_STR)
|
||||||
|
|
||||||
from calibre.constants import __appname__, plugins
|
from calibre.constants import __appname__, plugins
|
||||||
from calibre.ebooks.oeb.polish.spell import replace_word, get_all_words, merge_locations, get_checkable_file_names
|
from calibre.ebooks.oeb.polish.spell import replace_word, get_all_words, merge_locations, get_checkable_file_names, undo_replace_word
|
||||||
from calibre.gui2 import choose_files, error_dialog
|
from calibre.gui2 import choose_files, error_dialog
|
||||||
from calibre.gui2.complete2 import LineEdit
|
from calibre.gui2.complete2 import LineEdit
|
||||||
from calibre.gui2.languages import LanguagesEdit
|
from calibre.gui2.languages import LanguagesEdit
|
||||||
@ -883,6 +883,7 @@ class SpellCheck(Dialog):
|
|||||||
Dialog.__init__(self, _('Check spelling'), 'spell-check', parent)
|
Dialog.__init__(self, _('Check spelling'), 'spell-check', parent)
|
||||||
self.work_finished.connect(self.work_done, type=Qt.QueuedConnection)
|
self.work_finished.connect(self.work_done, type=Qt.QueuedConnection)
|
||||||
self.setAttribute(Qt.WA_DeleteOnClose, False)
|
self.setAttribute(Qt.WA_DeleteOnClose, False)
|
||||||
|
self.undo_cache = {}
|
||||||
|
|
||||||
def setup_ui(self):
|
def setup_ui(self):
|
||||||
self.state_name = 'spell-check-table-state-' + QT_VERSION_STR.partition('.')[0]
|
self.state_name = 'spell-check-table-state-' + QT_VERSION_STR.partition('.')[0]
|
||||||
@ -899,6 +900,10 @@ class SpellCheck(Dialog):
|
|||||||
b.setToolTip('<p>' + _('Re-scan the book for words, useful if you have edited the book since opening this dialog'))
|
b.setToolTip('<p>' + _('Re-scan the book for words, useful if you have edited the book since opening this dialog'))
|
||||||
b.setIcon(QIcon(I('view-refresh.png')))
|
b.setIcon(QIcon(I('view-refresh.png')))
|
||||||
b.clicked.connect(partial(self.refresh, change_request=None))
|
b.clicked.connect(partial(self.refresh, change_request=None))
|
||||||
|
b = self.bb.addButton(_('&Undo last change'), self.bb.ActionRole)
|
||||||
|
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)
|
||||||
|
|
||||||
self.progress = p = QWidget(self)
|
self.progress = p = QWidget(self)
|
||||||
s.addWidget(p)
|
s.addWidget(p)
|
||||||
@ -1110,7 +1115,8 @@ class SpellCheck(Dialog):
|
|||||||
self.change_requested.emit(w, new_word)
|
self.change_requested.emit(w, new_word)
|
||||||
|
|
||||||
def do_change_word(self, w, new_word):
|
def do_change_word(self, w, new_word):
|
||||||
changed_files = replace_word(current_container(), new_word, self.words_model.words[w], w[1])
|
self.undo_cache.clear()
|
||||||
|
changed_files = replace_word(current_container(), new_word, self.words_model.words[w], w[1], undo_cache=self.undo_cache)
|
||||||
if changed_files:
|
if changed_files:
|
||||||
self.word_replaced.emit(changed_files)
|
self.word_replaced.emit(changed_files)
|
||||||
w = self.words_model.replace_word(w, new_word)
|
w = self.words_model.replace_word(w, new_word)
|
||||||
@ -1118,6 +1124,16 @@ class SpellCheck(Dialog):
|
|||||||
if row > -1:
|
if row > -1:
|
||||||
self.words_view.highlight_row(row)
|
self.words_view.highlight_row(row)
|
||||||
|
|
||||||
|
def undo_last_change(self):
|
||||||
|
if not self.undo_cache:
|
||||||
|
return error_dialog(self, _('No changed word'), _(
|
||||||
|
'There is no spelling replacement to undo'), show=True)
|
||||||
|
changed_files = undo_replace_word(current_container(), self.undo_cache)
|
||||||
|
self.undo_cache.clear()
|
||||||
|
if changed_files:
|
||||||
|
self.word_replaced.emit(changed_files)
|
||||||
|
self.refresh()
|
||||||
|
|
||||||
def toggle_ignore(self):
|
def toggle_ignore(self):
|
||||||
current = self.words_view.currentIndex()
|
current = self.words_view.currentIndex()
|
||||||
if current.isValid():
|
if current.isValid():
|
||||||
|
Loading…
x
Reference in New Issue
Block a user