include/svx/svdoole2.hxx                  |   17 ++++
 include/svx/unoshape.hxx                  |    2 
 sc/source/ui/docshell/documentlinkmgr.cxx |    9 ++
 svx/source/svdraw/svdoole2.cxx            |  104 ++++++++++++++++++++++++------
 svx/source/unodraw/shapeimpl.hxx          |    5 +
 svx/source/unodraw/unoshap4.cxx           |   18 ++++-
 xmloff/source/draw/ximpshap.cxx           |   16 ++++
 7 files changed, 147 insertions(+), 24 deletions(-)

New commits:
commit 07179a5a5bd00f34acfa8a3f260dd834ae003c63
Author:     Caolán McNamara <caol...@redhat.com>
AuthorDate: Tue Apr 18 09:00:42 2023 +0100
Commit:     Caolán McNamara <caol...@redhat.com>
CommitDate: Wed Apr 19 11:03:21 2023 +0200

    add a route to get calc Floating Frame links under 'manage links'
    
    much harder than writer because the organization and ordering
    of properties and object activation etc is different.
    
    This ended up ugly, but functions.
    
    We set FrameURL before AddShape, we have to do it again later because it
    gets cleared when the SdrOle2Obj is attached to the XShape.  But we want
    FrameURL to exist when AddShape triggers SetPersistName which itself
    triggers SdrOle2Obj::CheckFileLink_Impl and at that point we want to
    know what URL will end up being used. So bodge this by setting FrameURL
    to the temp pre-SdrOle2Obj attached properties and we can smuggle it
    eventually into SdrOle2Obj::SetPersistName at the right point after
    PersistName is set but before SdrOle2Obj::CheckFileLink_Impl is called
    in order to inform the link manager that this is an IFrame that links to
    a URL
    
    Change-Id: I67fc199fef9e67fa12ca7873f0fe12137aa16d8f
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/150539
    Tested-by: Jenkins
    Reviewed-by: Caolán McNamara <caol...@redhat.com>

diff --git a/include/svx/svdoole2.hxx b/include/svx/svdoole2.hxx
index 4bbe38e451d5..444c12348226 100644
--- a/include/svx/svdoole2.hxx
+++ b/include/svx/svdoole2.hxx
@@ -42,6 +42,7 @@ namespace io { class XInputStream; }
 namespace svt { class EmbeddedObjectRef; }
 
 class SdrOle2ObjImpl;
+class SvxOle2Shape;
 
 class SVXCORE_DLLPUBLIC SdrOle2Obj : public SdrRectObj
 {
@@ -49,7 +50,7 @@ private:
     std::unique_ptr<SdrOle2ObjImpl> mpImpl;
 
 private:
-    SVX_DLLPRIVATE void Connect_Impl();
+    SVX_DLLPRIVATE void Connect_Impl(SvxOle2Shape* pCreator = nullptr);
     SVX_DLLPRIVATE void Disconnect_Impl();
     SVX_DLLPRIVATE void AddListeners_Impl();
     SVX_DLLPRIVATE void RemoveListeners_Impl();
@@ -107,7 +108,7 @@ public:
     // OLE object has got a separate PersistName member now;
     // !!! use ::SetPersistName( ... ) only, if you know what you do !!!
     const OUString& GetPersistName() const;
-    void        SetPersistName( const OUString& rPersistName );
+    void        SetPersistName( const OUString& rPersistName, SvxOle2Shape* 
pCreator = nullptr );
 
     // One can add an application name to a SdrOle2Obj, which can be queried 
for
     // later on (SD needs this for presentation objects).
@@ -152,7 +153,7 @@ public:
                                          sal_Int64 nAspect );
     static bool Unload( const css::uno::Reference< css::embed::XEmbeddedObject 
>& xObj, sal_Int64 nAspect );
     bool Unload();
-    void Connect();
+    void Connect(SvxOle2Shape* pCreator = nullptr);
     void Disconnect();
     void ObjectLoaded();
 
@@ -199,4 +200,14 @@ public:
     void                Connect() { GetRealObject(); }
 };
 
+class SVXCORE_DLLPUBLIC SdrIFrameLink final : public sfx2::SvBaseLink
+{
+    SdrOle2Obj* m_pObject;
+
+public:
+    explicit SdrIFrameLink(SdrOle2Obj* pObject);
+    virtual ::sfx2::SvBaseLink::UpdateResult DataChanged(
+        const OUString& rMimeType, const css::uno::Any & rValue ) override;
+};
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/include/svx/unoshape.hxx b/include/svx/unoshape.hxx
index e2a5d47e22be..654c60bb3c5e 100644
--- a/include/svx/unoshape.hxx
+++ b/include/svx/unoshape.hxx
@@ -606,6 +606,8 @@ public:
     bool createObject( const SvGlobalName &aClassName );
 
     void createLink( const OUString& aLinkURL );
+
+    virtual OUString GetAndClearInitialFrameURL();
 };
 
 
diff --git a/sc/source/ui/docshell/documentlinkmgr.cxx 
b/sc/source/ui/docshell/documentlinkmgr.cxx
index 3652df5cca0a..79a86d08b438 100644
--- a/sc/source/ui/docshell/documentlinkmgr.cxx
+++ b/sc/source/ui/docshell/documentlinkmgr.cxx
@@ -144,7 +144,7 @@ bool DocumentLinkManager::hasDdeOrOleOrWebServiceLinks(bool 
bDde, bool bOle, boo
         sfx2::SvBaseLink* pBase = rLink.get();
         if (bDde && dynamic_cast<ScDdeLink*>(pBase))
             return true;
-        if (bOle && dynamic_cast<SdrEmbedObjectLink*>(pBase))
+        if (bOle && (dynamic_cast<SdrEmbedObjectLink*>(pBase) || 
dynamic_cast<SdrIFrameLink*>(pBase)))
             return true;
         if (bWebService && dynamic_cast<ScWebServiceLink*>(pBase))
             return true;
@@ -175,6 +175,13 @@ bool 
DocumentLinkManager::updateDdeOrOleOrWebServiceLinks(weld::Window* pWin)
             continue;
         }
 
+        SdrIFrameLink* pIFrameLink = dynamic_cast<SdrIFrameLink*>(pBase);
+        if (pIFrameLink)
+        {
+            pIFrameLink->Update();
+            continue;
+        }
+
         ScWebServiceLink* pWebserviceLink = 
dynamic_cast<ScWebServiceLink*>(pBase);
         if (pWebserviceLink)
         {
diff --git a/svx/source/svdraw/svdoole2.cxx b/svx/source/svdraw/svdoole2.cxx
index fc92248a658b..45235d8a9db3 100644
--- a/svx/source/svdraw/svdoole2.cxx
+++ b/svx/source/svdraw/svdoole2.cxx
@@ -69,6 +69,7 @@
 #include <sdr/contact/viewcontactofsdrole2obj.hxx>
 #include <svx/svdograf.hxx>
 #include <sdr/properties/oleproperties.hxx>
+#include <svx/unoshape.hxx>
 #include <svx/xlineit0.hxx>
 #include <svx/xlnclit.hxx>
 #include <svx/xbtmpit.hxx>
@@ -593,6 +594,35 @@ void SdrEmbedObjectLink::Closed()
     SvBaseLink::Closed();
 }
 
+SdrIFrameLink::SdrIFrameLink(SdrOle2Obj* pObject)
+    : ::sfx2::SvBaseLink(::SfxLinkUpdateMode::ONCALL, 
SotClipboardFormatId::SVXB)
+    , m_pObject(pObject)
+{
+    SetSynchron( false );
+}
+
+::sfx2::SvBaseLink::UpdateResult SdrIFrameLink::DataChanged(
+    const OUString&, const uno::Any& )
+{
+    uno::Reference<embed::XEmbeddedObject> xObject = m_pObject->GetObjRef();
+    uno::Reference<embed::XCommonEmbedPersist> xPersObj(xObject, 
uno::UNO_QUERY);
+    if (xPersObj.is())
+    {
+        // let the IFrameObject reload the link
+        try
+        {
+            xPersObj->reload(uno::Sequence<beans::PropertyValue>(), 
uno::Sequence<beans::PropertyValue>());
+        }
+        catch (const uno::Exception&)
+        {
+        }
+
+        m_pObject->SetChanged();
+    }
+
+    return SUCCESS;
+}
+
 class SdrOle2ObjImpl
 {
 public:
@@ -610,7 +640,7 @@ public:
     bool mbLoadingOLEObjectFailed:1; // New local var to avoid repeated 
loading if load of OLE2 fails
     bool mbConnected:1;
 
-    SdrEmbedObjectLink* mpObjectLink;
+    sfx2::SvBaseLink* mpObjectLink;
     OUString maLinkURL;
 
     rtl::Reference<SvxUnoShapeModifyListener> mxModifyListener;
@@ -856,7 +886,7 @@ bool SdrOle2Obj::IsEmpty() const
     return !mpImpl->mxObjRef.is();
 }
 
-void SdrOle2Obj::Connect()
+void SdrOle2Obj::Connect(SvxOle2Shape* pCreator)
 {
     if( IsEmptyPresObj() )
         return;
@@ -869,7 +899,7 @@ void SdrOle2Obj::Connect()
         return;
     }
 
-    Connect_Impl();
+    Connect_Impl(pCreator);
     AddListeners_Impl();
 }
 
@@ -968,24 +998,51 @@ void SdrOle2Obj::CheckFileLink_Impl()
 
     try
     {
-        uno::Reference< embed::XLinkageSupport > xLinkSupport( 
mpImpl->mxObjRef.GetObject(), uno::UNO_QUERY );
+        uno::Reference<embed::XEmbeddedObject> xObject = 
mpImpl->mxObjRef.GetObject();
+        if (!xObject)
+            return;
 
-        if ( xLinkSupport.is() && xLinkSupport->isLink() )
-        {
-            OUString aLinkURL = xLinkSupport->getLinkURL();
+        bool bIFrame = false;
 
-            if ( !aLinkURL.isEmpty() )
+        OUString aLinkURL;
+        uno::Reference<embed::XLinkageSupport> xLinkSupport(xObject, 
uno::UNO_QUERY);
+        if (xLinkSupport)
+        {
+            if (xLinkSupport->isLink())
+                aLinkURL = xLinkSupport->getLinkURL();
+        }
+        else
+        {
+            // get IFrame (Floating Frames) listed and updatable from the
+            // manage links dialog
+            SvGlobalName aClassId(xObject->getClassID());
+            if (aClassId == SvGlobalName(SO3_IFRAME_CLASSID))
             {
-                // this is a file link so the model link manager should handle 
it
-                sfx2::LinkManager* 
pLinkManager(getSdrModelFromSdrObject().GetLinkManager());
+                uno::Reference<beans::XPropertySet> 
xSet(xObject->getComponent(), uno::UNO_QUERY);
+                if (xSet.is())
+                    xSet->getPropertyValue("FrameURL") >>= aLinkURL;
+                bIFrame = true;
+            }
+        }
+
+        if (!aLinkURL.isEmpty()) // this is a file link so the model link 
manager should handle it
+        {
+            sfx2::LinkManager* 
pLinkManager(getSdrModelFromSdrObject().GetLinkManager());
 
-                if ( pLinkManager )
+            if ( pLinkManager )
+            {
+                SdrEmbedObjectLink* pEmbedObjectLink = nullptr;
+                if (!bIFrame)
                 {
-                    mpImpl->mpObjectLink = new SdrEmbedObjectLink( this );
-                    mpImpl->maLinkURL = aLinkURL;
-                    pLinkManager->InsertFileLink( *mpImpl->mpObjectLink, 
sfx2::SvBaseLinkObjectType::ClientOle, aLinkURL );
-                    mpImpl->mpObjectLink->Connect();
+                    pEmbedObjectLink = new SdrEmbedObjectLink(this);
+                    mpImpl->mpObjectLink = pEmbedObjectLink;
                 }
+                else
+                    mpImpl->mpObjectLink = new SdrIFrameLink(this);
+                mpImpl->maLinkURL = aLinkURL;
+                pLinkManager->InsertFileLink( *mpImpl->mpObjectLink, 
sfx2::SvBaseLinkObjectType::ClientOle, aLinkURL );
+                if (pEmbedObjectLink)
+                    pEmbedObjectLink->Connect();
             }
         }
     }
@@ -995,7 +1052,7 @@ void SdrOle2Obj::CheckFileLink_Impl()
     }
 }
 
-void SdrOle2Obj::Connect_Impl()
+void SdrOle2Obj::Connect_Impl(SvxOle2Shape* pCreator)
 {
     if(mpImpl->aPersistName.isEmpty() )
         return;
@@ -1036,6 +1093,17 @@ void SdrOle2Obj::Connect_Impl()
             }
         }
 
+        if (pCreator)
+        {
+            OUString sFrameURL(pCreator->GetAndClearInitialFrameURL());
+            if (!sFrameURL.isEmpty() && 
svt::EmbeddedObjectRef::TryRunningState(mpImpl->mxObjRef.GetObject()))
+            {
+                uno::Reference<beans::XPropertySet> 
xSet(mpImpl->mxObjRef->getComponent(), uno::UNO_QUERY);
+                if (xSet.is())
+                    xSet->setPropertyValue("FrameURL", uno::Any(sFrameURL));
+            }
+        }
+
         if ( mpImpl->mxObjRef.is() )
         {
             if ( !mpImpl->mxLightClient.is() )
@@ -1346,14 +1414,14 @@ rtl::Reference<SdrObject> 
SdrOle2Obj::getFullDragClone() const
     return createSdrGrafObjReplacement(false);
 }
 
-void SdrOle2Obj::SetPersistName( const OUString& rPersistName )
+void SdrOle2Obj::SetPersistName( const OUString& rPersistName, SvxOle2Shape* 
pCreator )
 {
     DBG_ASSERT( mpImpl->aPersistName.isEmpty(), "Persist name changed!");
 
     mpImpl->aPersistName = rPersistName;
     mpImpl->mbLoadingOLEObjectFailed = false;
 
-    Connect();
+    Connect(pCreator);
     SetChanged();
 }
 
diff --git a/svx/source/unodraw/shapeimpl.hxx b/svx/source/unodraw/shapeimpl.hxx
index 44b3bcdea0e2..68189814fe6a 100644
--- a/svx/source/unodraw/shapeimpl.hxx
+++ b/svx/source/unodraw/shapeimpl.hxx
@@ -64,8 +64,11 @@ public:
 
     virtual void Create( SdrObject* pNewOpj, SvxDrawPage* pNewPage ) override;
 };
+
 class SvxFrameShape : public SvxOle2Shape
 {
+private:
+    OUString m_sInitialFrameURL;
 protected:
     // override these for special property handling in subcasses. Return true 
if property is handled
     virtual bool setPropertyValueImpl( const OUString& rName, const 
SfxItemPropertyMapEntry* pProperty, const css::uno::Any& rValue ) override;
@@ -82,6 +85,8 @@ public:
     virtual void SAL_CALL setPropertyValues( const css::uno::Sequence< 
OUString >& aPropertyNames, const css::uno::Sequence< css::uno::Any >& aValues 
) override;
 
     virtual void Create( SdrObject* pNewOpj, SvxDrawPage* pNewPage ) override;
+
+    virtual OUString GetAndClearInitialFrameURL() override;
 };
 
 SvxUnoPropertyMapProvider& getSvxMapProvider();
diff --git a/svx/source/unodraw/unoshap4.cxx b/svx/source/unodraw/unoshap4.cxx
index bfde63a2bac1..02790b767084 100644
--- a/svx/source/unodraw/unoshap4.cxx
+++ b/svx/source/unodraw/unoshap4.cxx
@@ -178,7 +178,7 @@ bool SvxOle2Shape::setPropertyValueImpl( const OUString& 
rName, const SfxItemPro
 #else
             pOle = static_cast<SdrOle2Obj*>(GetSdrObject());
 #endif
-            pOle->SetPersistName( aPersistName );
+            pOle->SetPersistName( aPersistName, this );
             return true;
         }
         break;
@@ -553,6 +553,11 @@ SvGlobalName SvxOle2Shape::GetClassName_Impl(OUString& 
rHexCLSID)
     return aClassName;
 }
 
+OUString SvxOle2Shape::GetAndClearInitialFrameURL()
+{
+    return OUString();
+}
+
 SvxAppletShape::SvxAppletShape(SdrObject* pObject)
     : SvxOle2Shape( pObject, getSvxMapProvider().GetMap(SVXMAP_APPLET), 
getSvxMapProvider().GetPropertySet(SVXMAP_APPLET, 
SdrObject::GetGlobalDrawObjectItemPool())  )
 {
@@ -706,8 +711,19 @@ SvxFrameShape::~SvxFrameShape() noexcept
 {
 }
 
+OUString SvxFrameShape::GetAndClearInitialFrameURL()
+{
+    OUString sRet(m_sInitialFrameURL);
+    m_sInitialFrameURL.clear();
+    return sRet;
+}
+
 void SvxFrameShape::Create( SdrObject* pNewObj, SvxDrawPage* pNewPage )
 {
+    uno::Reference<beans::XPropertySet> xSet(static_cast<OWeakObject *>(this), 
uno::UNO_QUERY);
+    if (xSet)
+        xSet->getPropertyValue("FrameURL") >>= m_sInitialFrameURL;
+
     SvxShape::Create( pNewObj, pNewPage );
     const SvGlobalName aIFrameClassId( SO3_IFRAME_CLASSID );
     createObject(aIFrameClassId);
diff --git a/xmloff/source/draw/ximpshap.cxx b/xmloff/source/draw/ximpshap.cxx
index 552414b06c9a..74d5027e7c11 100644
--- a/xmloff/source/draw/ximpshap.cxx
+++ b/xmloff/source/draw/ximpshap.cxx
@@ -3147,6 +3147,21 @@ void SdXMLFloatingFrameShapeContext::startFastElement 
(sal_Int32 /*nElement*/,
     const css::uno::Reference< css::xml::sax::XFastAttributeList >& 
/*xAttrList*/)
 {
     uno::Reference<drawing::XShape> 
xShape(SdXMLFloatingFrameShapeContext::CreateFloatingFrameShape());
+
+    uno::Reference< beans::XPropertySet > xProps(xShape, uno::UNO_QUERY);
+    // set FrameURL before AddShape, we have to do it again later because it
+    // gets cleared when the SdrOle2Obj is attached to the XShape.  But we want
+    // FrameURL to exist when AddShape triggers SetPersistName which itself
+    // triggers SdrOle2Obj::CheckFileLink_Impl and at that point we want to
+    // know what URL will end up being used. So bodge this by setting FrameURL
+    // to the temp pre-SdrOle2Obj attached properties and we can smuggle it
+    // eventually into SdrOle2Obj::SetPersistName at the right point after
+    // PersistName is set but before SdrOle2Obj::CheckFileLink_Impl is called
+    // in order to inform the link manager that this is an IFrame that links to
+    // a URL
+    if (xProps && !maHref.isEmpty())
+        xProps->setPropertyValue("FrameURL", Any(maHref));
+
     AddShape(xShape);
 
     if( !mxShape.is() )
@@ -3157,7 +3172,6 @@ void SdXMLFloatingFrameShapeContext::startFastElement 
(sal_Int32 /*nElement*/,
     // set pos, size, shear and rotate
     SetTransformation();
 
-    uno::Reference< beans::XPropertySet > xProps( mxShape, uno::UNO_QUERY );
     if( xProps.is() )
     {
         if( !maFrameName.isEmpty() )

Reply via email to