[Libreoffice-commits] core.git: include/svx sc/source sd/source svx/source sw/source

Michael Stahl mstahl at redhat.com
Fri Jan 16 16:10:17 PST 2015


 include/svx/extedit.hxx            |   41 +++++++++++----
 sc/source/ui/drawfunc/graphsh.cxx  |   31 +----------
 sc/source/ui/inc/graphsh.hxx       |    3 +
 sd/source/ui/inc/DrawViewShell.hxx |    3 +
 sd/source/ui/view/drviews2.cxx     |   33 +-----------
 sd/source/ui/view/drviewsa.cxx     |    1 
 svx/source/core/extedit.cxx        |   97 +++++++++++++++++++++++++++++--------
 sw/source/uibase/inc/grfsh.hxx     |    4 +
 sw/source/uibase/shells/grfsh.cxx  |   49 ++++++++++++------
 9 files changed, 159 insertions(+), 103 deletions(-)

New commits:
commit 5f6bdce0c0ac687f418821ce328f2987bf340cda
Author: Michael Stahl <mstahl at redhat.com>
Date:   Fri Jan 16 23:56:09 2015 +0100

    rhbz#1136013: svx: try to make the ExternalToolEdit not crash all the time
    
    This thing was starting a timer that re-starts itself forever, and when
    the file it was watching changed, it would just assume the drawing
    objects were still there (and the document, for that matter...)
    
    Change-Id: I35f187f0828097a05618dc1733dce819fc6bffc6

diff --git a/include/svx/extedit.hxx b/include/svx/extedit.hxx
index dc0c489..65e178d 100644
--- a/include/svx/extedit.hxx
+++ b/include/svx/extedit.hxx
@@ -10,30 +10,51 @@
 #ifndef INCLUDED_SVX_EXTEDIT_HXX
 #define INCLUDED_SVX_EXTEDIT_HXX
 
-#include <svtools/grfmgr.hxx>
-#include <osl/file.hxx>
-#include <osl/process.h>
-#include <vcl/graph.hxx>
-#include <vcl/timer.hxx>
 #include <svx/svxdllapi.h>
+#include <svl/lstner.hxx>
+#include <rtl/ustring.hxx>
+#include <memory>
+
+class Graphic;
+class GraphicObject;
+class FileChangedChecker;
 
 class SVX_DLLPUBLIC ExternalToolEdit
 {
-public:
-    GraphicObject* m_pGraphicObject;
+protected:
     OUString m_aFileName;
 
+    ::std::unique_ptr<FileChangedChecker> m_pChecker;
+
+public:
+
     ExternalToolEdit();
     virtual ~ExternalToolEdit();
 
     virtual void Update( Graphic& aGraphic ) = 0;
-    void Edit( GraphicObject *pGraphic );
+    void Edit(GraphicObject const*const pGraphic);
 
-    DECL_LINK( StartListeningEvent, void *pEvent );
+    void StartListeningEvent();
 
-    static void threadWorker( void *pThreadData );
     static void HandleCloseEvent( ExternalToolEdit* pData );
 };
 
+class FmFormView;
+class SdrObject;
+
+class SVX_DLLPUBLIC SdrExternalToolEdit
+    : public ExternalToolEdit
+    , public SfxListener
+{
+private:
+    FmFormView * m_pView;
+    SdrObject *  m_pObj;
+
+    SAL_DLLPRIVATE virtual void Update(Graphic&) SAL_OVERRIDE;
+    SAL_DLLPRIVATE virtual void Notify(SfxBroadcaster&, const SfxHint&) SAL_OVERRIDE;
+
+public:
+    SdrExternalToolEdit(FmFormView * pView, SdrObject * pObj);
+};
 
 #endif
diff --git a/sc/source/ui/drawfunc/graphsh.cxx b/sc/source/ui/drawfunc/graphsh.cxx
index 5284efb..b98f92b 100644
--- a/sc/source/ui/drawfunc/graphsh.cxx
+++ b/sc/source/ui/drawfunc/graphsh.cxx
@@ -38,32 +38,6 @@
 #define ScGraphicShell
 #include "scslots.hxx"
 
-class ScExternalToolEdit : public ExternalToolEdit
-{
-    FmFormView* m_pView;
-    SdrObject*  m_pObj;
-
-public:
-    ScExternalToolEdit ( FmFormView* pView, SdrObject* pObj ) :
-        m_pView   (pView),
-        m_pObj (pObj)
-    {}
-
-    virtual void Update( Graphic& aGraphic ) SAL_OVERRIDE
-    {
-        SdrPageView* pPageView = m_pView->GetSdrPageView();
-        if( pPageView )
-        {
-            SdrGrafObj* pNewObj = static_cast<SdrGrafObj*>(m_pObj->Clone());
-            OUString    aStr = m_pView->GetDescriptionOfMarkedObjects() + " External Edit";
-            m_pView->BegUndo( aStr );
-            pNewObj->SetGraphicObject( aGraphic );
-            m_pView->ReplaceObjectAtView( m_pObj, *pPageView, pNewObj );
-            m_pView->EndUndo();
-        }
-    }
-};
-
 SFX_IMPL_INTERFACE(ScGraphicShell, ScDrawShell)
 
 void ScGraphicShell::InitInterface_Impl()
@@ -188,8 +162,9 @@ void ScGraphicShell::ExecuteExternalEdit( SfxRequest& )
         if( pObj && pObj->ISA( SdrGrafObj ) && static_cast<SdrGrafObj*>(pObj)->GetGraphicType() == GRAPHIC_BITMAP )
         {
             GraphicObject aGraphicObject( static_cast<SdrGrafObj*>(pObj)->GetGraphicObject() );
-            ScExternalToolEdit* aExternalToolEdit = new ScExternalToolEdit( pView, pObj );
-            aExternalToolEdit->Edit( &aGraphicObject );
+            m_ExternalEdits.push_back( std::unique_ptr<SdrExternalToolEdit>(
+                        new SdrExternalToolEdit(pView, pObj)));
+            m_ExternalEdits.back()->Edit( &aGraphicObject );
         }
     }
 
diff --git a/sc/source/ui/inc/graphsh.hxx b/sc/source/ui/inc/graphsh.hxx
index 866d527..59bd4a4 100644
--- a/sc/source/ui/inc/graphsh.hxx
+++ b/sc/source/ui/inc/graphsh.hxx
@@ -25,6 +25,7 @@
 #include <sfx2/module.hxx>
 #include <svx/svdmark.hxx>
 
+class SdrExternalToolEdit;
 class ScViewData;
 
 #include "drawsh.hxx"
@@ -36,6 +37,8 @@ public:
     SFX_DECL_INTERFACE(SCID_GRAPHIC_SHELL)
 
 private:
+    std::vector<std::unique_ptr<SdrExternalToolEdit>> m_ExternalEdits;
+
     /// SfxInterface initializer.
     static void InitInterface_Impl();
 
diff --git a/sd/source/ui/inc/DrawViewShell.hxx b/sd/source/ui/inc/DrawViewShell.hxx
index 4110907..8a92f42 100644
--- a/sd/source/ui/inc/DrawViewShell.hxx
+++ b/sd/source/ui/inc/DrawViewShell.hxx
@@ -33,6 +33,7 @@
 
 class Outliner;
 class SdPage;
+class SdrExternalToolEdit;
 class DrawDocShell;
 class TabBar;
 class SdrObject;
@@ -507,6 +508,8 @@ private:
 
     ::std::unique_ptr< AnnotationManager > mpAnnotationManager;
     ::std::unique_ptr< ViewOverlayManager > mpViewOverlayManager;
+
+    std::vector<std::unique_ptr<SdrExternalToolEdit>> m_ExternalEdits;
 };
 
 } // end of namespace sd
diff --git a/sd/source/ui/view/drviews2.cxx b/sd/source/ui/view/drviews2.cxx
index 5b4517e..f30b974 100644
--- a/sd/source/ui/view/drviews2.cxx
+++ b/sd/source/ui/view/drviews2.cxx
@@ -185,33 +185,6 @@ using namespace ::com::sun::star::uno;
 
 namespace sd {
 
-class SdExternalToolEdit : public ExternalToolEdit
-{
-    FmFormView* m_pView;
-    SdrObject*  m_pObj;
-
-public:
-    SdExternalToolEdit ( FmFormView* pView, SdrObject* pObj ) :
-        m_pView   (pView),
-        m_pObj (pObj)
-    {}
-
-    virtual void Update( Graphic& aGraphic ) SAL_OVERRIDE
-    {
-        SdrPageView* pPageView = m_pView->GetSdrPageView();
-        if( pPageView )
-        {
-            SdrGrafObj* pNewObj = static_cast<SdrGrafObj*>( m_pObj->Clone() );
-            OUString    aStr = m_pView->GetDescriptionOfMarkedObjects();
-            aStr += " External Edit";
-            m_pView->BegUndo( aStr );
-            pNewObj->SetGraphicObject( aGraphic );
-            m_pView->ReplaceObjectAtView( m_pObj, *pPageView, pNewObj );
-            m_pView->EndUndo();
-        }
-    }
-};
-
 /**
  * SfxRequests for temporary actions
  */
@@ -999,8 +972,10 @@ void DrawViewShell::FuTemporary(SfxRequest& rReq)
                 if( pObj && pObj->ISA( SdrGrafObj ) && static_cast<SdrGrafObj*>(pObj)->GetGraphicType() == GRAPHIC_BITMAP )
                 {
                     GraphicObject aGraphicObject( static_cast<SdrGrafObj*>(pObj)->GetGraphicObject() );
-                    SdExternalToolEdit* aExternalToolEdit = new SdExternalToolEdit( mpDrawView, pObj );
-                    aExternalToolEdit->Edit( &aGraphicObject );
+                    m_ExternalEdits.push_back(
+                        std::unique_ptr<SdrExternalToolEdit>(
+                            new SdrExternalToolEdit(mpDrawView, pObj)));
+                    m_ExternalEdits.back()->Edit( &aGraphicObject );
                 }
             }
             Cancel();
diff --git a/sd/source/ui/view/drviewsa.cxx b/sd/source/ui/view/drviewsa.cxx
index eb4a084..0ab56de 100644
--- a/sd/source/ui/view/drviewsa.cxx
+++ b/sd/source/ui/view/drviewsa.cxx
@@ -43,6 +43,7 @@
 #include <svx/fmshell.hxx>
 #include <svtools/cliplistener.hxx>
 #include <svx/float3d.hxx>
+#include <svx/extedit.hxx>
 #include <svx/sidebar/SelectionAnalyzer.hxx>
 #include "helpids.h"
 
diff --git a/svx/source/core/extedit.cxx b/svx/source/core/extedit.cxx
index 83cbbec..7cc8b5f 100644
--- a/svx/source/core/extedit.cxx
+++ b/svx/source/core/extedit.cxx
@@ -7,15 +7,21 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
  */
 
+#include <svx/extedit.hxx>
+
 #include <vcl/svapp.hxx>
 #include <vcl/graph.hxx>
 #include <vcl/cvtgrf.hxx>
 #include <vcl/graphicfilter.hxx>
 #include <svx/xoutbmp.hxx>
-#include <svx/extedit.hxx>
 #include <svx/graphichelper.hxx>
+#include <svx/svdpagv.hxx>
+#include <svx/svdograf.hxx>
+#include <svx/fmview.hxx>
+#include <svtools/grfmgr.hxx>
 #include <sfx2/viewfrm.hxx>
 #include <sfx2/bindings.hxx>
+#include <salhelper/thread.hxx>
 #include <osl/file.hxx>
 #include <osl/thread.hxx>
 #include <osl/process.h>
@@ -33,7 +39,6 @@ using namespace css::uno;
 using namespace css::system;
 
 ExternalToolEdit::ExternalToolEdit()
-    : m_pGraphicObject(NULL)
 {
 }
 
@@ -56,35 +61,40 @@ void ExternalToolEdit::HandleCloseEvent(ExternalToolEdit* pData)
     }
 }
 
-IMPL_LINK (ExternalToolEdit, StartListeningEvent, void*, pEvent)
+void ExternalToolEdit::StartListeningEvent()
 {
     //Start an event listener implemented via VCL timeout
-    ExternalToolEdit* pData = ( ExternalToolEdit* )pEvent;
-
-    new FileChangedChecker(pData->m_aFileName, ::boost::bind(&HandleCloseEvent, pData));
-
-    return 0;
+    assert(!m_pChecker.get());
+    m_pChecker.reset(new FileChangedChecker(
+            m_aFileName, ::boost::bind(&HandleCloseEvent, this)));
 }
 
-void ExternalToolEdit::threadWorker(void* pThreadData)
+// self-destructing thread to make shell execute async
+class ExternalToolEditThread
+    : public ::salhelper::Thread
 {
-    osl_setThreadName("ExternalToolEdit");
+private:
+    OUString const m_aFileName;
 
-    ExternalToolEdit* pData = (ExternalToolEdit*) pThreadData;
+    virtual void execute() SAL_OVERRIDE;
 
-    // Make an asynchronous call to listen to the event of temporary image file
-    // getting changed
-    Application::PostUserEvent( LINK( NULL, ExternalToolEdit, StartListeningEvent ), pThreadData);
+public:
+    ExternalToolEditThread(OUString const& rFileName)
+        : ::salhelper::Thread("ExternalToolEdit")
+        , m_aFileName(rFileName)
+    {}
+};
 
+void ExternalToolEditThread::execute()
+{
     Reference<XSystemShellExecute> xSystemShellExecute(
         SystemShellExecute::create( ::comphelper::getProcessComponentContext() ) );
-    xSystemShellExecute->execute( pData->m_aFileName, OUString(), SystemShellExecuteFlags::URIS_ONLY );
+    xSystemShellExecute->execute(m_aFileName, OUString(), SystemShellExecuteFlags::URIS_ONLY);
 }
 
-void ExternalToolEdit::Edit( GraphicObject* pGraphicObject )
+void ExternalToolEdit::Edit(GraphicObject const*const pGraphicObject)
 {
     //Get the graphic from the GraphicObject
-    m_pGraphicObject = pGraphicObject;
     const Graphic aGraphic = pGraphicObject->GetGraphic();
 
     //get the Preferred File Extension for this graphic
@@ -117,8 +127,57 @@ void ExternalToolEdit::Edit( GraphicObject* pGraphicObject )
 
     //Create a thread
 
-    // Create the data that is needed by the thread later
-    osl_createThread(ExternalToolEdit::threadWorker, this);
+    rtl::Reference<ExternalToolEditThread> const pThread(
+            new ExternalToolEditThread(m_aFileName));
+    pThread->launch();
+
+    StartListeningEvent();
+}
+
+SdrExternalToolEdit::SdrExternalToolEdit(
+        FmFormView *const pView, SdrObject *const pObj)
+    : m_pView(pView)
+    , m_pObj(pObj)
+{
+    assert(m_pObj && m_pView);
+    StartListening(*m_pObj->GetModel());
+}
+
+
+void SdrExternalToolEdit::Notify(SfxBroadcaster & rBC, SfxHint const& rHint)
+{
+    SdrHint const*const pSdrHint(dynamic_cast<SdrHint const*>(&rHint));
+    if (pSdrHint
+        && (HINT_MODELCLEARED == pSdrHint->GetKind()
+            || (pSdrHint->GetObject() == m_pObj
+                && HINT_OBJREMOVED == pSdrHint->GetKind())))
+    {
+        m_pView = 0;
+        m_pObj = 0;
+        m_pChecker.reset(); // avoid modifying deleted object
+        EndListening(rBC);
+    }
+}
+
+void SdrExternalToolEdit::Update(Graphic & rGraphic)
+{
+    assert(m_pObj && m_pView); // timer should be deleted by Notify() too
+    SdrPageView *const pPageView = m_pView->GetSdrPageView();
+    if (pPageView)
+    {
+        SdrGrafObj *const pNewObj(static_cast<SdrGrafObj*>(m_pObj->Clone()));
+        assert(pNewObj);
+        OUString const description =
+            m_pView->GetDescriptionOfMarkedObjects() + " External Edit";
+        m_pView->BegUndo(description);
+        pNewObj->SetGraphicObject(rGraphic);
+        // set to new object before ReplaceObjectAtView() so that Notify() will
+        // not delete the running timer and crash
+        SdrObject *const pOldObj = m_pObj;
+        m_pObj = pNewObj;
+        m_pView->ReplaceObjectAtView(pOldObj, *pPageView, pNewObj);
+        m_pView->EndUndo();
+    }
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/grfsh.hxx b/sw/source/uibase/inc/grfsh.hxx
index 75c1ab0..5a74c46 100644
--- a/sw/source/uibase/inc/grfsh.hxx
+++ b/sw/source/uibase/inc/grfsh.hxx
@@ -23,6 +23,9 @@
 
 class SwGrfShell: public SwBaseShell
 {
+    class SwExternalToolEdit;
+    std::vector<std::unique_ptr<SwExternalToolEdit>> m_ExternalEdits;
+
 public:
     SFX_DECL_INTERFACE(SW_GRFSHELL)
 
@@ -39,6 +42,7 @@ public:
     void GetAttrStateForRotation(SfxItemSet& rRequest);
 
     SwGrfShell(SwView &rView);
+    virtual ~SwGrfShell();
 };
 
 #endif
diff --git a/sw/source/uibase/shells/grfsh.cxx b/sw/source/uibase/shells/grfsh.cxx
index b6714ce..b261adc 100644
--- a/sw/source/uibase/shells/grfsh.cxx
+++ b/sw/source/uibase/shells/grfsh.cxx
@@ -75,27 +75,37 @@
 #include <sfx2/msg.hxx>
 #include "swslots.hxx"
 #include "swabstdlg.hxx"
+#include <unocrsr.hxx>
 #include <boost/scoped_ptr.hpp>
 
 #define TOOLBOX_NAME "colorbar"
 
-namespace
+class SwGrfShell::SwExternalToolEdit
+    : public ExternalToolEdit
 {
-    class SwExternalToolEdit : public ExternalToolEdit
+private:
+    SwWrtShell *const m_pShell;
+    ::std::unique_ptr<SwUnoCrsr> const m_pCursor;
+
+public:
+    SwExternalToolEdit(SwWrtShell *const pShell)
+        : m_pShell(pShell)
+        , m_pCursor( // need only Point, must point to SwGrfNode
+            pShell->GetDoc()->CreateUnoCrsr(
+                *pShell->GetCurrentShellCursor().GetPoint()))
     {
-        SwWrtShell*  m_pShell;
-
-    public:
-        SwExternalToolEdit ( SwWrtShell* pShell ) :
-            m_pShell  (pShell)
-        {}
+    }
 
-        virtual void Update( Graphic& aGraphic ) SAL_OVERRIDE
-        {
-            m_pShell->ReRead(OUString(), OUString(), (const Graphic*) &aGraphic);
-        }
-    };
-}
+    virtual void Update(Graphic & rGraphic) SAL_OVERRIDE
+    {
+        DBG_TESTSOLARMUTEX();
+        m_pShell->Push();
+        m_pShell->GetCurrentShellCursor().DeleteMark();
+        *m_pShell->GetCurrentShellCursor().GetPoint() = *m_pCursor->GetPoint();
+        m_pShell->ReRead(OUString(), OUString(), &rGraphic);
+        m_pShell->Pop();
+    }
+};
 
 SFX_IMPL_INTERFACE(SwGrfShell, SwBaseShell)
 
@@ -180,11 +190,12 @@ void SwGrfShell::Execute(SfxRequest &rReq)
         {
             // When the graphic is selected to be opened via some external tool
             // for advanced editing
-            GraphicObject *pGraphicObject = (GraphicObject *) rSh.GetGraphicObj();
+            GraphicObject const*const pGraphicObject(rSh.GetGraphicObj());
             if(0 != pGraphicObject)
             {
-                SwExternalToolEdit* externalToolEdit = new SwExternalToolEdit( &rSh );
-                externalToolEdit->Edit ( pGraphicObject );
+                m_ExternalEdits.push_back(std::unique_ptr<SwExternalToolEdit>(
+                            new SwExternalToolEdit(&rSh)));
+                m_ExternalEdits.back()->Edit(pGraphicObject);
             }
         }
         break;
@@ -905,6 +916,10 @@ void SwGrfShell::GetAttrStateForRotation(SfxItemSet &rSet)
     SetGetStateSet( 0 );
 }
 
+SwGrfShell::~SwGrfShell()
+{
+}
+
 SwGrfShell::SwGrfShell(SwView &_rView) :
     SwBaseShell(_rView)
 {


More information about the Libreoffice-commits mailing list