sw/source/uibase/docvw/PostItMgr.cxx |  337 +++++++++++++++++------------------
 1 file changed, 168 insertions(+), 169 deletions(-)

New commits:
commit ce4ae4f082d8fe80da242836c57d55a456eac5e0
Author:     Pranam Lashkari <lpra...@collabora.com>
AuthorDate: Wed Oct 30 05:11:49 2024 +0530
Commit:     Pranam Lashkari <lpra...@collabora.com>
CommitDate: Wed Oct 30 21:34:31 2024 +0100

    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 <jenkinscollaboraoff...@gmail.com>
    Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/175833
    Reviewed-by: Pranam Lashkari <lpra...@collabora.com>
    Tested-by: Jenkins

diff --git a/sw/source/uibase/docvw/PostItMgr.cxx 
b/sw/source/uibase/docvw/PostItMgr.cxx
index 447731267b40..bf1b56082fba 100644
--- a/sw/source/uibase/docvw/PostItMgr.cxx
+++ b/sw/source/uibase/docvw/PostItMgr.cxx
@@ -196,6 +196,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
+        {
+            if ( rHint.GetId() != SfxHintId::SwFormatField )
+                return;
+            const SwFormatFieldHint* pHint = static_cast<const 
SwFormatFieldHint*>(&rHint);
+
+            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)
@@ -315,6 +480,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();
     }
@@ -1410,175 +1578,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
-    {
-        if ( rHint.GetId() != SfxHintId::SwFormatField )
-            return;
-        const SwFormatFieldHint* pHint = static_cast<const 
SwFormatFieldHint*>(&rHint);
-
-        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

Reply via email to