Skip to content

Commit

Permalink
Edit Book: Spell check dialog: Add a button to undo the last spelling…
Browse files Browse the repository at this point in the history
… change
  • Loading branch information
kovidgoyal committed Oct 19, 2015
1 parent 155c35f commit 02b8f77
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 6 deletions.
18 changes: 14 additions & 4 deletions src/calibre/ebooks/oeb/polish/spell.py
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ def replace(text, original_word, new_word, lang):
text = text[:idx] + new_word + text[idx+len(original_word):]
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()
for loc in locations:
node = loc.location_node
Expand All @@ -231,16 +231,26 @@ def replace_word(container, new_word, locations, locale):
else:
text = getattr(node, attr)
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 undo_cache is not None:
undo_cache[(loc.file_name, node, is_attr, attr)] = text
if is_attr:
node.set(attr, text)
node.set(attr, rtext)
else:
setattr(node, attr, text)
setattr(node, attr, rtext)
container.replace(loc.file_name, node.getroottree().getroot())
changed.add(loc.file_name)
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__':
import pprint
from calibre.gui2.tweak_book import set_book_locale, dictionaries
Expand Down
20 changes: 18 additions & 2 deletions src/calibre/gui2/tweak_book/spell.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
QT_VERSION_STR)

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.complete2 import LineEdit
from calibre.gui2.languages import LanguagesEdit
Expand Down Expand Up @@ -883,6 +883,7 @@ def __init__(self, parent=None):
Dialog.__init__(self, _('Check spelling'), 'spell-check', parent)
self.work_finished.connect(self.work_done, type=Qt.QueuedConnection)
self.setAttribute(Qt.WA_DeleteOnClose, False)
self.undo_cache = {}

def setup_ui(self):
self.state_name = 'spell-check-table-state-' + QT_VERSION_STR.partition('.')[0]
Expand All @@ -899,6 +900,10 @@ def setup_ui(self):
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.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)
s.addWidget(p)
Expand Down Expand Up @@ -1110,14 +1115,25 @@ def change_to(self, w, new_word):
self.change_requested.emit(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:
self.word_replaced.emit(changed_files)
w = self.words_model.replace_word(w, new_word)
row = self.words_model.row_for_word(w)
if row > -1:
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):
current = self.words_view.currentIndex()
if current.isValid():
Expand Down

0 comments on commit 02b8f77

Please sign in to comment.