summaryrefslogtreecommitdiff
path: root/sw/source/uibase
diff options
context:
space:
mode:
authorPranam Lashkari <lpranam@collabora.com>2024-10-30 05:11:49 +0530
committerPranam Lashkari <lpranam@collabora.com>2024-10-30 18:02:01 +0100
commit86422743e6a4fa67de3b0049bd4ea40e1aca17ad (patch)
treed636a6ca8e25823ed3a9a81ef0b7d9f283783711 /sw/source/uibase
parent1f4009e98caf9ea878b89ae1d93934540a91e753 (diff)
sw: redline changes may try to set broadcast on non PostIt fields
broadcast was set from sw::UpdateFramesForRemoveDeleteRedline which triggered SwPostItMgr::Notify in that case SwFormatFieldHintWhich::INSERTED may have pField which maybe different from SwPostIt fixed regression from 0b7a9c231f66b5c2659ab3aa6a0f3c7991b9e721 problem:(in LOK) with tracked changed on delete a merge field then reject the changes LOK will crash Change-Id: Ic1fafa1408d7a238133f5b3d18bf948d539aa991 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/175808 Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice@gmail.com> Reviewed-by: Caolán McNamara <caolan.mcnamara@collabora.com>
Diffstat (limited to 'sw/source/uibase')
-rw-r--r--sw/source/uibase/docvw/PostItMgr.cxx337
1 files changed, 168 insertions, 169 deletions
diff --git a/sw/source/uibase/docvw/PostItMgr.cxx b/sw/source/uibase/docvw/PostItMgr.cxx
index 8e67e94ef3f1..21a498e8dd56 100644
--- a/sw/source/uibase/docvw/PostItMgr.cxx
+++ b/sw/source/uibase/docvw/PostItMgr.cxx
@@ -194,6 +194,171 @@ namespace {
}
}
+ class FilterFunctor
+ {
+ public:
+ virtual bool operator()(const SwFormatField* pField) const = 0;
+ virtual ~FilterFunctor() {}
+ };
+
+ class IsPostitField : public FilterFunctor
+ {
+ public:
+ bool operator()(const SwFormatField* pField) const override
+ {
+ return pField->GetField()->GetTyp()->Which() == SwFieldIds::Postit;
+ }
+ };
+
+ class IsPostitFieldWithAuthorOf : public FilterFunctor
+ {
+ OUString m_sAuthor;
+ public:
+ explicit IsPostitFieldWithAuthorOf(OUString aAuthor)
+ : m_sAuthor(std::move(aAuthor))
+ {
+ }
+ bool operator()(const SwFormatField* pField) const override
+ {
+ if (pField->GetField()->GetTyp()->Which() != SwFieldIds::Postit)
+ return false;
+ return static_cast<const SwPostItField*>(pField->GetField())->GetPar1() == m_sAuthor;
+ }
+ };
+
+ class IsPostitFieldWithPostitId : public FilterFunctor
+ {
+ sal_uInt32 m_nPostItId;
+ public:
+ explicit IsPostitFieldWithPostitId(sal_uInt32 nPostItId)
+ : m_nPostItId(nPostItId)
+ {}
+
+ bool operator()(const SwFormatField* pField) const override
+ {
+ if (pField->GetField()->GetTyp()->Which() != SwFieldIds::Postit)
+ return false;
+ return static_cast<const SwPostItField*>(pField->GetField())->GetPostItId() == m_nPostItId;
+ }
+ };
+
+ class IsFieldNotDeleted : public FilterFunctor
+ {
+ private:
+ IDocumentRedlineAccess const& m_rIDRA;
+ FilterFunctor const& m_rNext;
+
+ public:
+ IsFieldNotDeleted(IDocumentRedlineAccess const& rIDRA,
+ const 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
+ //functor.
+ //
+ //This will completely refill in the case of a "anonymous" NULL pField stating
+ //rather unhelpfully that "something changed" so you may process the same
+ //Fields more than once.
+ class FieldDocWatchingStack : public SfxListener
+ {
+ std::vector<std::unique_ptr<SwSidebarItem>>& m_aSidebarItems;
+ std::vector<const SwFormatField*> m_aFormatFields;
+ SwDocShell& m_rDocShell;
+ FilterFunctor& m_rFilter;
+
+ virtual void Notify(SfxBroadcaster&, const SfxHint& rHint) override
+ {
+ const SwFormatFieldHint* pHint = dynamic_cast<const SwFormatFieldHint*>(&rHint);
+ if (!pHint)
+ return;
+
+ bool bAllInvalidated = false;
+ if (pHint->Which() == SwFormatFieldHintWhich::REMOVED)
+ {
+ const SwFormatField* pField = pHint->GetField();
+ bAllInvalidated = pField == nullptr;
+ if (!bAllInvalidated && m_rFilter(pField))
+ {
+ EndListening(const_cast<SwFormatField&>(*pField));
+ std::erase(m_aFormatFields, pField);
+ }
+ }
+ else if (pHint->Which() == SwFormatFieldHintWhich::INSERTED)
+ {
+ const SwFormatField* pField = pHint->GetField();
+ bAllInvalidated = pField == nullptr;
+ if (!bAllInvalidated && m_rFilter(pField))
+ {
+ StartListening(const_cast<SwFormatField&>(*pField));
+ m_aFormatFields.push_back(pField);
+ }
+ }
+
+ if (bAllInvalidated)
+ FillVector();
+
+ return;
+ }
+
+ public:
+ FieldDocWatchingStack(std::vector<std::unique_ptr<SwSidebarItem>>& in, SwDocShell &rDocShell, FilterFunctor& rFilter)
+ : m_aSidebarItems(in)
+ , m_rDocShell(rDocShell)
+ , m_rFilter(rFilter)
+ {
+ FillVector();
+ StartListening(m_rDocShell);
+ }
+ void FillVector()
+ {
+ EndListeningToAllFields();
+ m_aFormatFields.clear();
+ m_aFormatFields.reserve(m_aSidebarItems.size());
+ for (auto const& p : m_aSidebarItems)
+ {
+ const SwFormatField& rField = p->GetFormatField();
+ if (!m_rFilter(&rField))
+ continue;
+ StartListening(const_cast<SwFormatField&>(rField));
+ m_aFormatFields.push_back(&rField);
+ }
+ }
+ void EndListeningToAllFields()
+ {
+ for (auto const& pField : m_aFormatFields)
+ {
+ EndListening(const_cast<SwFormatField&>(*pField));
+ }
+ }
+ virtual ~FieldDocWatchingStack() override
+ {
+ EndListeningToAllFields();
+ EndListening(m_rDocShell);
+ }
+ const SwFormatField* pop()
+ {
+ if (m_aFormatFields.empty())
+ return nullptr;
+ const SwFormatField* p = m_aFormatFields.back();
+ EndListening(const_cast<SwFormatField&>(*p));
+ m_aFormatFields.pop_back();
+ return p;
+ }
+ };
+
} // anonymous namespace
SwPostItMgr::SwPostItMgr(SwView* pView)
@@ -317,6 +482,9 @@ SwSidebarItem* SwPostItMgr::InsertItem(SfxBroadcaster* pItem, bool bCheckExisten
SwSidebarItem* pAnnotationItem = nullptr;
if (auto pSwFormatField = dynamic_cast< SwFormatField *>( pItem ))
{
+ IsPostitField isPostitField;
+ if (!isPostitField(pSwFormatField))
+ return nullptr;
mvPostItFields.push_back(std::make_unique<SwAnnotationItem>(*pSwFormatField, bFocus));
pAnnotationItem = mvPostItFields.back().get();
}
@@ -1387,175 +1555,6 @@ void SwPostItMgr::RemoveSidebarWin()
PreparePageContainer();
}
-namespace {
-
-class FilterFunctor
-{
-public:
- virtual bool operator()(const SwFormatField* pField) const = 0;
- virtual ~FilterFunctor() {}
-};
-
-class IsPostitField : public FilterFunctor
-{
-public:
- bool operator()(const SwFormatField* pField) const override
- {
- return pField->GetField()->GetTyp()->Which() == SwFieldIds::Postit;
- }
-};
-
-class IsPostitFieldWithAuthorOf : public FilterFunctor
-{
- OUString m_sAuthor;
-public:
- explicit IsPostitFieldWithAuthorOf(OUString aAuthor)
- : m_sAuthor(std::move(aAuthor))
- {
- }
- bool operator()(const SwFormatField* pField) const override
- {
- if (pField->GetField()->GetTyp()->Which() != SwFieldIds::Postit)
- return false;
- return static_cast<const SwPostItField*>(pField->GetField())->GetPar1() == m_sAuthor;
- }
-};
-
-class IsPostitFieldWithPostitId : public FilterFunctor
-{
- sal_uInt32 m_nPostItId;
-public:
- explicit IsPostitFieldWithPostitId(sal_uInt32 nPostItId)
- : m_nPostItId(nPostItId)
- {}
-
- bool operator()(const SwFormatField* pField) const override
- {
- if (pField->GetField()->GetTyp()->Which() != SwFieldIds::Postit)
- return false;
- return static_cast<const SwPostItField*>(pField->GetField())->GetPostItId() == m_nPostItId;
- }
-};
-
-class IsFieldNotDeleted : public FilterFunctor
-{
-private:
- IDocumentRedlineAccess const& m_rIDRA;
- FilterFunctor const& m_rNext;
-
-public:
- IsFieldNotDeleted(IDocumentRedlineAccess const& rIDRA,
- const 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
-//functor.
-//
-//This will completely refill in the case of a "anonymous" NULL pField stating
-//rather unhelpfully that "something changed" so you may process the same
-//Fields more than once.
-class FieldDocWatchingStack : public SfxListener
-{
- std::vector<std::unique_ptr<SwSidebarItem>>& m_aSidebarItems;
- std::vector<const SwFormatField*> m_aFormatFields;
- SwDocShell& m_rDocShell;
- FilterFunctor& m_rFilter;
-
- virtual void Notify(SfxBroadcaster&, const SfxHint& rHint) override
- {
- const SwFormatFieldHint* pHint = dynamic_cast<const SwFormatFieldHint*>(&rHint);
- if (!pHint)
- return;
-
- bool bAllInvalidated = false;
- if (pHint->Which() == SwFormatFieldHintWhich::REMOVED)
- {
- const SwFormatField* pField = pHint->GetField();
- bAllInvalidated = pField == nullptr;
- if (!bAllInvalidated && m_rFilter(pField))
- {
- EndListening(const_cast<SwFormatField&>(*pField));
- std::erase(m_aFormatFields, pField);
- }
- }
- else if (pHint->Which() == SwFormatFieldHintWhich::INSERTED)
- {
- const SwFormatField* pField = pHint->GetField();
- bAllInvalidated = pField == nullptr;
- if (!bAllInvalidated && m_rFilter(pField))
- {
- StartListening(const_cast<SwFormatField&>(*pField));
- m_aFormatFields.push_back(pField);
- }
- }
-
- if (bAllInvalidated)
- FillVector();
-
- return;
- }
-
-public:
- FieldDocWatchingStack(std::vector<std::unique_ptr<SwSidebarItem>>& in, SwDocShell &rDocShell, FilterFunctor& rFilter)
- : m_aSidebarItems(in)
- , m_rDocShell(rDocShell)
- , m_rFilter(rFilter)
- {
- FillVector();
- StartListening(m_rDocShell);
- }
- void FillVector()
- {
- EndListeningToAllFields();
- m_aFormatFields.clear();
- m_aFormatFields.reserve(m_aSidebarItems.size());
- for (auto const& p : m_aSidebarItems)
- {
- const SwFormatField& rField = p->GetFormatField();
- if (!m_rFilter(&rField))
- continue;
- StartListening(const_cast<SwFormatField&>(rField));
- m_aFormatFields.push_back(&rField);
- }
- }
- void EndListeningToAllFields()
- {
- for (auto const& pField : m_aFormatFields)
- {
- EndListening(const_cast<SwFormatField&>(*pField));
- }
- }
- virtual ~FieldDocWatchingStack() override
- {
- EndListeningToAllFields();
- EndListening(m_rDocShell);
- }
- const SwFormatField* pop()
- {
- if (m_aFormatFields.empty())
- return nullptr;
- const SwFormatField* p = m_aFormatFields.back();
- EndListening(const_cast<SwFormatField&>(*p));
- m_aFormatFields.pop_back();
- return p;
- }
-};
-
-}
-
// copy to new vector, otherwise RemoveItem would operate and delete stuff on mvPostItFields as well
// RemoveItem will clean up the core field and visible postit if necessary
// we cannot just delete everything as before, as postits could move into change tracking