sd/source/ui/inc/NotesPanelView.hxx  |   10 ---
 sd/source/ui/view/NotesPanelView.cxx |   91 ++++++++++-------------------------
 2 files changed, 29 insertions(+), 72 deletions(-)

New commits:
commit 53b834fc44abe04bbfd3cdfc844149e233acc645
Author:     Noel Grandin <[email protected]>
AuthorDate: Thu Jul 25 11:53:17 2024 +0200
Commit:     Noel Grandin <[email protected]>
CommitDate: Thu Aug 22 09:22:07 2024 +0200

    tdf#162004 crash after notes pane loses focus in impress
    
    I cannot reproduce this at all, but from the debugging traces
    supplied it looks like mpTextObj ends up pointing at something
    that has already been freed.
    
    To prevent that, instead of caching mpTextObj, fetch it every
    time we need it.
    
    Change-Id: Ia8000f8f0b65fbe7c4ac4850179708a025af3cd4
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/170970
    Tested-by: Jenkins
    Reviewed-by: Noel Grandin <[email protected]>

diff --git a/sd/source/ui/inc/NotesPanelView.hxx 
b/sd/source/ui/inc/NotesPanelView.hxx
index d6763b855a2c..685818a1c852 100644
--- a/sd/source/ui/inc/NotesPanelView.hxx
+++ b/sd/source/ui/inc/NotesPanelView.hxx
@@ -37,18 +37,11 @@ class NotesPanelView final : public ::sd::SimpleOutlinerView
 
     Idle aModifyIdle;
 
-    SdrTextObj* mpTextObj = nullptr;
-    bool mbIgnoreNotifications = false;
     bool mbInFocus = false;
 
-    void removeListener();
-    void addListener();
-
-    void setListenerIgnored(bool bIgnore);
-    bool isListenerIgnored();
-
     void getNotesFromDoc();
     void setNotesToDoc();
+    SdrTextObj* getNotesTextObj();
 
 public:
     NotesPanelView(DrawDocShell& rDocSh, vcl::Window* pWindow,
@@ -71,7 +64,6 @@ public:
 
     void SetLinks();
     void ResetLinks();
-    virtual void Notify(SfxBroadcaster& rBC, const SfxHint& rHint) override;
 
     virtual void GetAttributes(SfxItemSet& rTargetSet, bool bOnlyHardAttr = 
false) const override;
     virtual bool SetAttributes(const SfxItemSet& rSet, bool bReplaceAll = 
false,
diff --git a/sd/source/ui/view/NotesPanelView.cxx 
b/sd/source/ui/view/NotesPanelView.cxx
index 45c2c4117fa3..05ef63aeb3fd 100644
--- a/sd/source/ui/view/NotesPanelView.cxx
+++ b/sd/source/ui/view/NotesPanelView.cxx
@@ -77,75 +77,62 @@ void NotesPanelView::FillOutliner()
     maOutliner.GetUndoManager().Clear();
     maOutliner.EnableUndo(false);
     ResetLinks();
-    removeListener();
-    mpTextObj = nullptr;
     maOutliner.Clear();
 
-    SdPage* pNotesPage = mrNotesPanelViewShell.getCurrentPage();
-    if (!pNotesPage)
-        return;
-
-    SdrObject* pNotesObj = pNotesPage->GetPresObj(PresObjKind::Notes);
-    if (!pNotesObj)
+    SdrTextObj* pNotesTextObj = getNotesTextObj();
+    if (!pNotesTextObj)
         return;
 
-    mpTextObj = dynamic_cast<SdrTextObj*>(pNotesObj);
-    addListener();
     getNotesFromDoc();
     SetLinks();
     maOutliner.EnableUndo(true);
 }
 
-void NotesPanelView::SetLinks()
+SdrTextObj* NotesPanelView::getNotesTextObj()
 {
-    maOutliner.SetStatusEventHdl(LINK(this, NotesPanelView, StatusEventHdl));
-}
+    SdPage* pNotesPage = mrNotesPanelViewShell.getCurrentPage();
+    if (!pNotesPage)
+        return nullptr;
 
-void NotesPanelView::ResetLinks() { 
maOutliner.SetStatusEventHdl(Link<EditStatus&, void>()); }
+    SdrObject* pNotesObj = pNotesPage->GetPresObj(PresObjKind::Notes);
+    if (!pNotesObj)
+        return nullptr;
 
-void NotesPanelView::removeListener()
-{
-    if (mpTextObj)
-        mpTextObj->RemoveListener(*this);
+    return dynamic_cast<SdrTextObj*>(pNotesObj);
 }
-void NotesPanelView::addListener()
+
+void NotesPanelView::SetLinks()
 {
-    if (mpTextObj)
-        mpTextObj->AddListener(*this);
+    maOutliner.SetStatusEventHdl(LINK(this, NotesPanelView, StatusEventHdl));
 }
 
-void NotesPanelView::setListenerIgnored(bool bIgnore) { mbIgnoreNotifications 
= bIgnore; }
-bool NotesPanelView::isListenerIgnored() { return mbIgnoreNotifications; }
+void NotesPanelView::ResetLinks() { 
maOutliner.SetStatusEventHdl(Link<EditStatus&, void>()); }
 
 void NotesPanelView::getNotesFromDoc()
 {
-    if (!mpTextObj)
+    SdrTextObj* pNotesTextObj = getNotesTextObj();
+    if (!pNotesTextObj)
         return;
 
     // Ignore notifications that will rebound from updating the text
     maOutliner.SetModifyHdl(Link<LinkParamNone*, void>());
-    setListenerIgnored(true);
 
-    if (OutlinerParaObject* pPara = mpTextObj->GetOutlinerParaObject())
+    if (OutlinerParaObject* pPara = pNotesTextObj->GetOutlinerParaObject())
         maOutliner.SetText(*pPara);
 
-    setListenerIgnored(false);
     maOutliner.SetModifyHdl(LINK(this, NotesPanelView, EditModifiedHdl));
 }
 
 void NotesPanelView::setNotesToDoc()
 {
-    if (!mpTextObj)
+    SdrTextObj* pNotesTextObj = getNotesTextObj();
+    if (!pNotesTextObj)
         return;
 
-    setListenerIgnored(true);
-
     std::optional<OutlinerParaObject> pNewText = maOutliner.CreateParaObject();
-    mpTextObj->SetOutlinerParaObject(std::move(pNewText));
-    if (mpTextObj->IsEmptyPresObj())
-        mpTextObj->SetEmptyPresObj(false);
-
-    setListenerIgnored(false);
+    pNotesTextObj->SetOutlinerParaObject(std::move(pNewText));
+    if (pNotesTextObj->IsEmptyPresObj())
+        pNotesTextObj->SetEmptyPresObj(false);
 }
 
 void NotesPanelView::Paint(const ::tools::Rectangle& rRect, ::sd::Window 
const* /*pWin*/)
@@ -153,30 +140,6 @@ void NotesPanelView::Paint(const ::tools::Rectangle& 
rRect, ::sd::Window const*
     maOutlinerView.Paint(rRect);
 }
 
-void NotesPanelView::Notify(SfxBroadcaster&, const SfxHint& rHint)
-{
-    if (isListenerIgnored())
-        return;
-
-    if (rHint.GetId() == SfxHintId::ThisIsAnSdrHint)
-    {
-        const SdrHint& rSdrHint = reinterpret_cast<const SdrHint&>(rHint);
-        switch (rSdrHint.GetKind())
-        {
-            case SdrHintKind::ObjectRemoved:
-            case SdrHintKind::ModelCleared:
-                FillOutliner();
-                break;
-            case SdrHintKind::ObjectChange:
-            case SdrHintKind::EndEdit:
-                FillOutliner();
-                break;
-            default:
-                break;
-        }
-    }
-}
-
 OutlinerView* NotesPanelView::GetOutlinerView() { return &maOutlinerView; }
 
 void NotesPanelView::onUpdateStyleSettings()
@@ -233,7 +196,8 @@ void NotesPanelView::onGrabFocus()
         return;
     mbInFocus = true;
 
-    if (mpTextObj && mpTextObj->IsEmptyPresObj())
+    SdrTextObj* pNotesTextObj = getNotesTextObj();
+    if (pNotesTextObj && pNotesTextObj->IsEmptyPresObj())
     {
         // clear the "Click to add Notes" text on entering the window.
         maOutliner.SetToEmptyText();
@@ -247,14 +211,15 @@ void NotesPanelView::onLoseFocus()
     mbInFocus = false;
 
     aModifyIdle.Stop();
-    if (mpTextObj)
+    SdrTextObj* pNotesTextObj = getNotesTextObj();
+    if (pNotesTextObj)
     {
         if (maOutliner.GetEditEngine().GetText().getLength() == 0)
         {
             // if the notes are empty restore the placeholder text and state.
-            SdPage* pPage = 
dynamic_cast<SdPage*>(mpTextObj->getSdrPageFromSdrObject());
+            SdPage* pPage = 
dynamic_cast<SdPage*>(pNotesTextObj->getSdrPageFromSdrObject());
             if (pPage)
-                pPage->RestoreDefaultText(mpTextObj);
+                pPage->RestoreDefaultText(pNotesTextObj);
         }
         else
             setNotesToDoc();

Reply via email to