diff options
Diffstat (limited to 'cui/source/dialogs/SpellDialog.cxx')
-rw-r--r-- | cui/source/dialogs/SpellDialog.cxx | 58 |
1 files changed, 39 insertions, 19 deletions
diff --git a/cui/source/dialogs/SpellDialog.cxx b/cui/source/dialogs/SpellDialog.cxx index 64a1b0270589..8c55ee12a72f 100644 --- a/cui/source/dialogs/SpellDialog.cxx +++ b/cui/source/dialogs/SpellDialog.cxx @@ -344,14 +344,14 @@ void SpellDialog::UpdateBoxes_Impl(bool bCallFromSelectHdl) m_xDialog->resize_to_request(); } -void SpellDialog::SpellContinue_Impl(bool bUseSavedSentence, bool bIgnoreCurrentError ) +void SpellDialog::SpellContinue_Impl(std::unique_ptr<UndoChangeGroupGuard>* pGuard, bool bUseSavedSentence, bool bIgnoreCurrentError) { //initially or after the last error of a sentence MarkNextError will fail //then GetNextSentence() has to be called followed again by MarkNextError() //MarkNextError is not initially called if the UndoEdit mode is active bool bNextSentence = false; if((!m_xSentenceED->IsUndoEditMode() && m_xSentenceED->MarkNextError( bIgnoreCurrentError, xSpell )) || - ( bNextSentence = GetNextSentence_Impl(bUseSavedSentence, m_xSentenceED->IsUndoEditMode()) && m_xSentenceED->MarkNextError( false, xSpell ))) + ( bNextSentence = GetNextSentence_Impl(pGuard, bUseSavedSentence, m_xSentenceED->IsUndoEditMode()) && m_xSentenceED->MarkNextError( false, xSpell ))) { SpellErrorDescription aSpellErrorDescription; bool bSpellErrorDescription = m_xSentenceED->GetAlternatives(aSpellErrorDescription); @@ -389,7 +389,7 @@ IMPL_LINK_NOARG( SpellDialog, InitHdl, void*, void) m_xDialog->freeze(); //show or hide AutoCorrect depending on the modules abilities m_xAutoCorrPB->set_visible(rParent.HasAutoCorrection()); - SpellContinue_Impl(); + SpellContinue_Impl(nullptr); m_xSentenceED->ResetUndo(); m_xUndoPB->set_sensitive(false); @@ -506,6 +506,27 @@ IMPL_LINK_NOARG(SpellDialog, DoubleClickChangeHdl, weld::TreeView&, bool) return true; } +/* tdf#132822 start an undo group in ctor and close it in the dtor. This can + then be passed to SpellContinue_Impl which can delete it in advance of its + natural scope to force closing the undo group if SpellContinue_Impl needs to + fetch a new paragraph and discard all undo information which can only be + done properly if there are no open undo groups */ +class UndoChangeGroupGuard +{ +private: + SentenceEditWindow_Impl& m_rSentenceED; +public: + UndoChangeGroupGuard(SentenceEditWindow_Impl& rSentenceED) + : m_rSentenceED(rSentenceED) + { + m_rSentenceED.UndoActionStart(SPELLUNDO_CHANGE_GROUP); + } + ~UndoChangeGroupGuard() + { + m_rSentenceED.UndoActionEnd(); + } +}; + IMPL_LINK_NOARG(SpellDialog, ChangeHdl, weld::Button&, void) { if (m_xSentenceED->IsUndoEditMode()) @@ -514,11 +535,10 @@ IMPL_LINK_NOARG(SpellDialog, ChangeHdl, weld::Button&, void) } else { - m_xSentenceED->UndoActionStart( SPELLUNDO_CHANGE_GROUP ); + auto xGuard(std::make_unique<UndoChangeGroupGuard>(*m_xSentenceED)); OUString aString = getReplacementString(); m_xSentenceED->ChangeMarkedWord(aString, GetSelectedLang_Impl()); - SpellContinue_Impl(); - m_xSentenceED->UndoActionEnd(); + SpellContinue_Impl(&xGuard); } if(!m_xChangePB->get_sensitive()) m_xIgnorePB->grab_focus(); @@ -526,7 +546,7 @@ IMPL_LINK_NOARG(SpellDialog, ChangeHdl, weld::Button&, void) IMPL_LINK_NOARG(SpellDialog, ChangeAllHdl, weld::Button&, void) { - m_xSentenceED->UndoActionStart( SPELLUNDO_CHANGE_GROUP ); + auto xGuard(std::make_unique<UndoChangeGroupGuard>(*m_xSentenceED)); OUString aString = getReplacementString(); LanguageType eLang = GetSelectedLang_Impl(); @@ -548,13 +568,12 @@ IMPL_LINK_NOARG(SpellDialog, ChangeAllHdl, weld::Button&, void) } m_xSentenceED->ChangeMarkedWord(aString, eLang); - SpellContinue_Impl(); - m_xSentenceED->UndoActionEnd(); + SpellContinue_Impl(&xGuard); } IMPL_LINK( SpellDialog, IgnoreAllHdl, weld::Button&, rButton, void ) { - m_xSentenceED->UndoActionStart( SPELLUNDO_CHANGE_GROUP ); + auto xGuard(std::make_unique<UndoChangeGroupGuard>(*m_xSentenceED)); // add word to IgnoreAll list Reference< XDictionary > aXDictionary = LinguMgr::GetIgnoreAllList(); //in case the error has been changed manually it has to be restored @@ -594,8 +613,7 @@ IMPL_LINK( SpellDialog, IgnoreAllHdl, weld::Button&, rButton, void ) } } - SpellContinue_Impl(); - m_xSentenceED->UndoActionEnd(); + SpellContinue_Impl(&xGuard); } IMPL_LINK_NOARG(SpellDialog, UndoHdl, weld::Button&, void) @@ -644,7 +662,7 @@ IMPL_LINK( SpellDialog, DialogUndoHdl, SpellUndoAction_Impl&, rAction, void ) case SPELLUNDO_UNDO_EDIT_MODE : { //refill the dialog with the currently spelled sentence - throw away all changes - SpellContinue_Impl(true); + SpellContinue_Impl(nullptr, true); } break; case SPELLUNDO_ADD_IGNORE_RULE: @@ -661,7 +679,7 @@ void SpellDialog::Impl_Restore(bool bUseSavedSentence) m_xSentenceED->SetText(OUString()); m_xSentenceED->ResetModified(); //Resolves: fdo#39348 refill the dialog with the currently spelled sentence - SpellContinue_Impl(bUseSavedSentence); + SpellContinue_Impl(nullptr, bUseSavedSentence); m_xIgnorePB->set_label(m_sIgnoreOnceST); } @@ -678,7 +696,7 @@ IMPL_LINK_NOARG(SpellDialog, IgnoreHdl, weld::Button&, void) m_xSentenceED->RestoreCurrentError(); // the word is being ignored - SpellContinue_Impl( false, true ); + SpellContinue_Impl(nullptr, false, true); } } @@ -817,7 +835,7 @@ IMPL_LINK(SpellDialog, AddToDictSelectHdl, const OString&, rIdent, void) void SpellDialog::AddToDictionaryExecute(const OString& rItemId) { - m_xSentenceED->UndoActionStart( SPELLUNDO_CHANGE_GROUP ); + auto xGuard(std::make_unique<UndoChangeGroupGuard>(*m_xSentenceED)); //GetErrorText() returns the current error even if the text is already //manually changed @@ -858,8 +876,7 @@ void SpellDialog::AddToDictionaryExecute(const OString& rItemId) } // go on - SpellContinue_Impl(); - m_xSentenceED->UndoActionEnd(); + SpellContinue_Impl(&xGuard); } IMPL_LINK_NOARG(SpellDialog, ModifyHdl, LinkParamNone*, void) @@ -958,7 +975,7 @@ void SpellDialog::InvalidateDialog() SfxModelessDialogController::Deactivate(); } -bool SpellDialog::GetNextSentence_Impl(bool bUseSavedSentence, bool bRecheck) +bool SpellDialog::GetNextSentence_Impl(std::unique_ptr<UndoChangeGroupGuard>* pGuard, bool bUseSavedSentence, bool bRecheck) { bool bRet = false; if(!bUseSavedSentence) @@ -995,6 +1012,9 @@ bool SpellDialog::GetNextSentence_Impl(bool bUseSavedSentence, bool bRecheck) if(!elem.bIsHidden) sText.append(elem.sText); } + // tdf#132822 fire undo-stack UndoActionEnd to close undo stack because we're about to throw away the paragraph entirely + if (pGuard) + pGuard->reset(); m_xSentenceED->SetText(sText.makeStringAndClear()); sal_Int32 nStartPosition = 0; sal_Int32 nEndPosition = 0; |