From 484fb55168b18bbd8c6160e5a3958a5188987ab5 Mon Sep 17 00:00:00 2001 From: Michael Stahl Date: Fri, 11 Jan 2019 15:22:59 +0100 Subject: sw_redlinehide: fix infinite loop when deleting comments The problem is that sw::UpdateFramesForAddDeleteRedline() sends a SwFormatFieldHintWhich::REMOVED event in order to remove any comments that may have been deleted from the document view. Unfortunately there's another listener in class FieldDocWatchingStack that is used during various SwPostItMgr::Delete* functions, which will effectively start over from scratch if it receives this event, so it is an infinite loop. Avoid this by simply ignoring any redline-deleted fields; deleting them again won't provide any benefit anyway. This can be seen with UITest deleteAllComments.DeleteAllComments.test_comment_trackchanges. (regression from 9b67b6a6d4b912f1e515d3884fa02c1be8aa6921) Change-Id: Ie1d5676d1d79a51e2e4a01a3e282f8739ff08899 Reviewed-on: https://gerrit.libreoffice.org/66178 Tested-by: Jenkins Reviewed-by: Michael Stahl --- sw/source/uibase/docvw/PostItMgr.cxx | 34 +++++++++++++++++++++++++++++++--- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/sw/source/uibase/docvw/PostItMgr.cxx b/sw/source/uibase/docvw/PostItMgr.cxx index 1c6d410aac74..657d2d3b7c1d 100644 --- a/sw/source/uibase/docvw/PostItMgr.cxx +++ b/sw/source/uibase/docvw/PostItMgr.cxx @@ -1381,6 +1381,28 @@ public: } }; +class IsFieldNotDeleted : public FilterFunctor +{ +private: + IDocumentRedlineAccess const& m_rIDRA; + FilterFunctor const& m_rNext; + +public: + IsFieldNotDeleted(IDocumentRedlineAccess const& rIDRA, + FilterFunctor & rNext) + : m_rIDRA(rIDRA) + , m_rNext(rNext) + { + } + bool operator()(const SwFormatField* pField) const override + { + if (!m_rNext(pField)) + return false; + if (!pField->GetTextField()) + return false; + return !sw::IsFieldDeletedInModel(m_rIDRA, *pField->GetTextField()); + } +}; //Manages the passed in vector by automatically removing entries if they are deleted //and automatically adding entries if they appear in the document and match the @@ -1491,7 +1513,9 @@ void SwPostItMgr::Delete(const OUString& rAuthor) mpWrtShell->StartUndo( SwUndoId::DELETE, &aRewriter ); IsPostitFieldWithAuthorOf aFilter(rAuthor); - FieldDocWatchingStack aStack(mvPostItFields, *mpView->GetDocShell(), aFilter); + IDocumentRedlineAccess const& rIDRA(mpWrtShell->getIDocumentRedlineAccess()); + IsFieldNotDeleted aFilter2(rIDRA, aFilter); + FieldDocWatchingStack aStack(mvPostItFields, *mpView->GetDocShell(), aFilter2); while (const SwFormatField* pField = aStack.pop()) { if (mpWrtShell->GotoField(*pField)) @@ -1518,7 +1542,9 @@ void SwPostItMgr::Delete(sal_uInt32 nPostItId) mpWrtShell->StartUndo( SwUndoId::DELETE, &aRewriter ); IsPostitFieldWithPostitId aFilter(nPostItId); - FieldDocWatchingStack aStack(mvPostItFields, *mpView->GetDocShell(), aFilter); + IDocumentRedlineAccess const& rIDRA(mpWrtShell->getIDocumentRedlineAccess()); + IsFieldNotDeleted aFilter2(rIDRA, aFilter); + FieldDocWatchingStack aStack(mvPostItFields, *mpView->GetDocShell(), aFilter2); const SwFormatField* pField = aStack.pop(); if (pField && mpWrtShell->GotoField(*pField)) mpWrtShell->DelRight(); @@ -1539,8 +1565,10 @@ void SwPostItMgr::Delete() mpWrtShell->StartUndo( SwUndoId::DELETE, &aRewriter ); IsPostitField aFilter; + IDocumentRedlineAccess const& rIDRA(mpWrtShell->getIDocumentRedlineAccess()); + IsFieldNotDeleted aFilter2(rIDRA, aFilter); FieldDocWatchingStack aStack(mvPostItFields, *mpView->GetDocShell(), - aFilter); + aFilter2); while (const SwFormatField* pField = aStack.pop()) { if (mpWrtShell->GotoField(*pField)) -- cgit