Edit Book: When using the spell check dialog to change words, detect any changes made to open files outside the spell check dialog and automatically integrate them, to prevent those changes from being lost.

This commit is contained in:
Kovid Goyal 2014-07-08 09:44:20 +05:30
parent 046d9bb4d0
commit cdef0f3acf
2 changed files with 30 additions and 8 deletions

View File

@ -117,6 +117,7 @@ class Boss(QObject):
self.gui.spell_check.refresh_requested.connect(self.commit_all_editors_to_container) self.gui.spell_check.refresh_requested.connect(self.commit_all_editors_to_container)
self.gui.spell_check.word_replaced.connect(self.word_replaced) self.gui.spell_check.word_replaced.connect(self.word_replaced)
self.gui.spell_check.word_ignored.connect(self.word_ignored) self.gui.spell_check.word_ignored.connect(self.word_ignored)
self.gui.spell_check.change_requested.connect(self.word_change_requested)
self.gui.live_css.goto_declaration.connect(self.goto_style_declaration) self.gui.live_css.goto_declaration.connect(self.goto_style_declaration)
self.gui.manage_fonts.container_changed.connect(self.apply_container_update_to_gui) self.gui.manage_fonts.container_changed.connect(self.apply_container_update_to_gui)
self.gui.manage_fonts.embed_all_fonts.connect(self.manage_fonts_embed) self.gui.manage_fonts.embed_all_fonts.connect(self.manage_fonts_embed)
@ -769,6 +770,12 @@ class Boss(QObject):
name = editor_name(ed) name = editor_name(ed)
find_next_error(ed, name, self.gui, self.show_editor, self.edit_file) find_next_error(ed, name, self.gui, self.show_editor, self.edit_file)
def word_change_requested(self, w, new_word):
if self.commit_all_editors_to_container():
self.gui.spell_check.change_word_after_update(w, new_word)
else:
self.gui.spell_check.do_change_word(w, new_word)
def word_replaced(self, changed_names): def word_replaced(self, changed_names):
self.set_modified() self.set_modified()
self.update_editors_from_container(names=set(changed_names)) self.update_editors_from_container(names=set(changed_names))
@ -822,11 +829,14 @@ class Boss(QObject):
self.gui.file_list.build(container) self.gui.file_list.build(container)
def commit_all_editors_to_container(self): def commit_all_editors_to_container(self):
changed = False
with BusyCursor(): with BusyCursor():
for name, ed in editors.iteritems(): for name, ed in editors.iteritems():
if not ed.is_synced_to_container: if not ed.is_synced_to_container:
self.commit_editor_to_container(name) self.commit_editor_to_container(name)
ed.is_synced_to_container = True ed.is_synced_to_container = True
changed = True
return changed
def save_book(self): def save_book(self):
c = current_container() c = current_container()

View File

@ -858,11 +858,12 @@ class WordsView(QTableView):
class SpellCheck(Dialog): class SpellCheck(Dialog):
work_finished = pyqtSignal(object, object) work_finished = pyqtSignal(object, object, object)
find_word = pyqtSignal(object, object) find_word = pyqtSignal(object, object)
refresh_requested = pyqtSignal() refresh_requested = pyqtSignal()
word_replaced = pyqtSignal(object) word_replaced = pyqtSignal(object)
word_ignored = pyqtSignal(object, object) word_ignored = pyqtSignal(object, object)
change_requested = pyqtSignal(object, object)
def __init__(self, parent=None): def __init__(self, parent=None):
self.__current_word = None self.__current_word = None
@ -1088,14 +1089,17 @@ class SpellCheck(Dialog):
if w is None: if w is None:
return return
new_word = unicode(self.suggested_word.text()) new_word = unicode(self.suggested_word.text())
self.do_change_word(w, new_word) self.change_requested.emit(w, new_word)
def change_word_after_update(self, w, new_word):
self.refresh(change_request=(w, new_word))
def change_to(self, w, new_word): def change_to(self, w, new_word):
if new_word is None: if new_word is None:
self.suggested_word.setFocus(Qt.OtherFocusReason) self.suggested_word.setFocus(Qt.OtherFocusReason)
self.suggested_word.clear() self.suggested_word.clear()
return return
self.do_change_word(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]) changed_files = replace_word(current_container(), new_word, self.words_model.words[w], w[1])
@ -1153,7 +1157,7 @@ class SpellCheck(Dialog):
with self: with self:
self.words_model.filter(text) self.words_model.filter(text)
def refresh(self): def refresh(self, change_request=None):
if not self.isVisible(): if not self.isVisible():
return return
self.cancel = True self.cancel = True
@ -1162,12 +1166,12 @@ class SpellCheck(Dialog):
self.stack.setCurrentIndex(0) self.stack.setCurrentIndex(0)
self.progress_indicator.startAnimation() self.progress_indicator.startAnimation()
self.refresh_requested.emit() self.refresh_requested.emit()
self.thread = Thread(target=self.get_words) self.thread = Thread(target=partial(self.get_words, change_request=change_request))
self.thread.daemon = True self.thread.daemon = True
self.cancel = False self.cancel = False
self.thread.start() self.thread.start()
def get_words(self): def get_words(self, change_request=None):
try: try:
words = get_all_words(current_container(), dictionaries.default_locale) words = get_all_words(current_container(), dictionaries.default_locale)
spell_map = {w:dictionaries.recognized(*w) for w in words} spell_map = {w:dictionaries.recognized(*w) for w in words}
@ -1180,14 +1184,14 @@ class SpellCheck(Dialog):
if self.cancel: if self.cancel:
self.end_work() self.end_work()
else: else:
self.work_finished.emit(words, spell_map) self.work_finished.emit(words, spell_map, change_request)
def end_work(self): def end_work(self):
self.stack.setCurrentIndex(1) self.stack.setCurrentIndex(1)
self.progress_indicator.stopAnimation() self.progress_indicator.stopAnimation()
self.words_model.clear() self.words_model.clear()
def work_done(self, words, spell_map): def work_done(self, words, spell_map, change_request):
self.end_work() self.end_work()
if not isinstance(words, dict): if not isinstance(words, dict):
return error_dialog(self, _('Failed to check spelling'), _( return error_dialog(self, _('Failed to check spelling'), _(
@ -1205,6 +1209,14 @@ class SpellCheck(Dialog):
if self.words_model.rowCount() > 0: if self.words_model.rowCount() > 0:
self.words_view.resizeRowToContents(0) self.words_view.resizeRowToContents(0)
self.words_view.verticalHeader().setDefaultSectionSize(self.words_view.rowHeight(0)) self.words_view.verticalHeader().setDefaultSectionSize(self.words_view.rowHeight(0))
if change_request is not None:
w, new_word = change_request
if w in self.words_model.words:
self.do_change_word(w, new_word)
else:
error_dialog(self, _('Files edited'), _(
'The files in the editor were edited outside the spell check dialog,'
' and the word %s no longer exists.') % w[0], show=True)
def update_summary(self): def update_summary(self):
self.summary.setText(_('Misspelled words: {0} Total words: {1}').format(*self.words_model.counts)) self.summary.setText(_('Misspelled words: {0} Total words: {1}').format(*self.words_model.counts))