[Libreoffice-commits] core.git: Branch 'libreoffice-6-0' - sc/inc sc/Library_sc.mk sc/source

Caolán McNamara caolanm at redhat.com
Tue Jan 16 12:05:51 UTC 2018


 sc/Library_sc.mk                          |    1 
 sc/inc/document.hxx                       |    2 
 sc/inc/documentlinkmgr.hxx                |    6 -
 sc/source/core/data/formulacell.cxx       |    4 -
 sc/source/core/inc/webservicelink.hxx     |   49 +++++++++++++
 sc/source/core/tool/interpr7.cxx          |  105 ++++++++++++++++++++---------
 sc/source/core/tool/webservicelink.cxx    |  106 ++++++++++++++++++++++++++++++
 sc/source/ui/docshell/docsh4.cxx          |    2 
 sc/source/ui/docshell/documentlinkmgr.cxx |   20 ++++-
 sc/source/ui/view/tabvwsh4.cxx            |    2 
 10 files changed, 252 insertions(+), 45 deletions(-)

New commits:
commit 462113d4f712c5acf18ecfb0be6a86aa891d7b97
Author: Caolán McNamara <caolanm at redhat.com>
Date:   Thu Jan 11 20:43:28 2018 +0000

    handle ocWebservice similarly to ocDde
    
    might have too much in here seeing as we don't need to worry about
    ocWebservice calling into itself
    
    Change-Id: I0145f38cc1c1f9ff514a496f7101d81cde9e7c67
    Reviewed-on: https://gerrit.libreoffice.org/47816
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Eike Rathke <erack at redhat.com>

diff --git a/sc/Library_sc.mk b/sc/Library_sc.mk
index 890cafe689c2..9e1432c0a8c3 100644
--- a/sc/Library_sc.mk
+++ b/sc/Library_sc.mk
@@ -277,6 +277,7 @@ $(eval $(call gb_Library_add_exception_objects,sc,\
     sc/source/core/tool/unitconv \
     sc/source/core/tool/userlist \
     sc/source/core/tool/viewopti \
+    sc/source/core/tool/webservicelink \
     sc/source/core/tool/zforauto \
     sc/source/filter/xml/datastreamimport \
     sc/source/filter/xml/XMLCalculationSettingsContext \
diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx
index 4b419fa9f4ef..6bce61522184 100644
--- a/sc/inc/document.hxx
+++ b/sc/inc/document.hxx
@@ -501,7 +501,7 @@ private:
     // for detective update, is set for each change of a formula
     bool                bDetectiveDirty;
 
-    bool                bLinkFormulaNeedingCheck; // valid only after loading, for ocDde
+    bool                bLinkFormulaNeedingCheck; // valid only after loading, for ocDde and ocWebservice
 
     CharCompressType    nAsianCompression;
     sal_uInt8           nAsianKerning;
diff --git a/sc/inc/documentlinkmgr.hxx b/sc/inc/documentlinkmgr.hxx
index d5d801a4aeb2..86dba66f2d3d 100644
--- a/sc/inc/documentlinkmgr.hxx
+++ b/sc/inc/documentlinkmgr.hxx
@@ -55,9 +55,9 @@ public:
     bool idleCheckLinks();
 
     bool hasDdeLinks() const;
-    bool hasDdeOrOleLinks() const;
+    bool hasDdeOrOleOrWebServiceLinks() const;
 
-    bool updateDdeOrOleLinks(vcl::Window* pWin);
+    bool updateDdeOrOleOrWebServiceLinks(vcl::Window* pWin);
 
     void updateDdeLink( const OUString& rAppl, const OUString& rTopic, const OUString& rItem );
 
@@ -65,7 +65,7 @@ public:
 
     void disconnectDdeLinks();
 private:
-    bool hasDdeOrOleLinks(bool bDde, bool bOle) const;
+    bool hasDdeOrOleOrWebServiceLinks(bool bDde, bool bOle, bool bWebService) const;
 };
 
 }
diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx
index 8af5c6bc4028..e7e4d09f5a47 100644
--- a/sc/source/core/data/formulacell.cxx
+++ b/sc/source/core/data/formulacell.cxx
@@ -1358,9 +1358,9 @@ void ScFormulaCell::CompileXML( sc::CompileFormulaContext& rCxt, ScProgress& rPr
             bChanged = true;
     }
 
-    //  After loading, it must be known if ocDde is in any formula
+    //  After loading, it must be known if ocDde/ocWebservice is in any formula
     //  (for external links warning, CompileXML is called at the end of loading XML file)
-    if (!pDocument->HasLinkFormulaNeedingCheck() && pCode->HasOpCodeRPN(ocDde))
+    if (!pDocument->HasLinkFormulaNeedingCheck() && (pCode->HasOpCodeRPN(ocDde) || pCode->HasOpCodeRPN(ocWebservice)))
         pDocument->SetLinkFormulaNeedingCheck(true);
 
     //volatile cells must be added here for import
diff --git a/sc/source/core/inc/webservicelink.hxx b/sc/source/core/inc/webservicelink.hxx
new file mode 100644
index 000000000000..e61ebfdb4347
--- /dev/null
+++ b/sc/source/core/inc/webservicelink.hxx
@@ -0,0 +1,49 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDED_SC_SOURCE_CORE_INC_WEBSERVICE_HXX
+#define INCLUDED_SC_SOURCE_CORE_INC_WEBSERVICE_HXX
+
+#include <address.hxx>
+#include <sfx2/lnkbase.hxx>
+#include <svl/broadcast.hxx>
+#include <types.hxx>
+
+class ScDocument;
+
+class ScWebServiceLink : public ::sfx2::SvBaseLink, public SvtBroadcaster
+{
+private:
+    ScDocument* pDoc;
+    OUString aURL; // connection/ link data
+    bool bHasResult; // is set aResult is useful
+    OUString aResult;
+
+public:
+    ScWebServiceLink(ScDocument* pD, const OUString& rURL);
+    virtual ~ScWebServiceLink() override;
+
+    // SvBaseLink override:
+    virtual ::sfx2::SvBaseLink::UpdateResult DataChanged(const OUString& rMimeType,
+                                                         const css::uno::Any& rValue) override;
+
+    // SvtBroadcaster override:
+    virtual void ListenersGone() override;
+
+    // for interpreter:
+
+    const OUString& GetResult() const { return aResult; }
+    bool HasResult() const { return bHasResult; }
+
+    const OUString& GetURL() const { return aURL; }
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/sc/source/core/tool/interpr7.cxx b/sc/source/core/tool/interpr7.cxx
index 863664cc5309..9bb77db8b577 100644
--- a/sc/source/core/tool/interpr7.cxx
+++ b/sc/source/core/tool/interpr7.cxx
@@ -13,6 +13,7 @@
 #include <scmatrix.hxx>
 #include <rtl/strbuf.hxx>
 #include <formula/errorcodes.hxx>
+#include <sfx2/bindings.hxx>
 #include <svtools/miscopt.hxx>
 #include <tools/urlobj.hxx>
 
@@ -24,6 +25,10 @@
 #include <datastreamgettime.hxx>
 #include <dpobject.hxx>
 #include <document.hxx>
+#include <tokenarray.hxx>
+#include <webservicelink.hxx>
+
+#include <sc.hrc>
 
 #include <cstring>
 #include <memory>
@@ -235,6 +240,22 @@ void ScInterpreter::ScFilterXML()
     }
 }
 
+static ScWebServiceLink* lcl_GetWebServiceLink(const sfx2::LinkManager* pLinkMgr, const OUString& rURL)
+{
+    size_t nCount = pLinkMgr->GetLinks().size();
+    for (size_t i=0; i<nCount; ++i)
+    {
+        ::sfx2::SvBaseLink* pBase = pLinkMgr->GetLinks()[i].get();
+        if (ScWebServiceLink* pLink = dynamic_cast<ScWebServiceLink*>(pBase))
+        {
+            if (pLink->GetURL() == rURL)
+                return pLink;
+        }
+    }
+
+    return nullptr;
+}
+
 void ScInterpreter::ScWebservice()
 {
     sal_uInt8 nParamCount = GetByte();
@@ -242,7 +263,7 @@ void ScInterpreter::ScWebservice()
     {
         OUString aURI = GetString().getString();
 
-        if(aURI.isEmpty())
+        if (aURI.isEmpty())
         {
             PushError( FormulaError::NoValue );
             return;
@@ -252,52 +273,72 @@ void ScInterpreter::ScWebservice()
         INetProtocol eProtocol = aObj.GetProtocol();
         if (eProtocol != INetProtocol::Http && eProtocol != INetProtocol::Https)
         {
-            PushError( FormulaError::NoValue );
+            PushError(FormulaError::NoValue);
             return;
         }
 
-        uno::Reference< ucb::XSimpleFileAccess3 > xFileAccess( ucb::SimpleFileAccess::create( comphelper::getProcessComponentContext() ), uno::UNO_QUERY );
-        if(!xFileAccess.is())
+        if (!mpLinkManager)
         {
-            PushError( FormulaError::NoValue );
+            PushError(FormulaError::NoValue);
             return;
         }
 
-        uno::Reference< io::XInputStream > xStream;
-        try {
-            xStream = xFileAccess->openFileRead( aURI );
-        }
-        catch (...)
-        {
-            // don't let any exceptions pass
-            PushError( FormulaError::NoValue );
-            return;
-        }
-        if ( !xStream.is() )
-        {
-            PushError( FormulaError::NoValue );
-            return;
-        }
+        // Need to reinterpret after loading (build links)
+        if (rArr.IsRecalcModeNormal())
+            rArr.SetExclusiveRecalcModeOnLoad();
 
-        const sal_Int32 BUF_LEN = 8000;
-        uno::Sequence< sal_Int8 > buffer( BUF_LEN );
-        OStringBuffer aBuffer( 64000 );
+        //  while the link is not evaluated, idle must be disabled (to avoid circular references)
+        bool bOldEnabled = pDok->IsIdleEnabled();
+        pDok->EnableIdle(false);
 
-        sal_Int32 nRead = 0;
-        while ( ( nRead = xStream->readBytes( buffer, BUF_LEN ) ) == BUF_LEN )
+        // Get/ Create link object
+        ScWebServiceLink* pLink = lcl_GetWebServiceLink(mpLinkManager, aURI);
+
+        bool bWasError = (pMyFormulaCell && pMyFormulaCell->GetRawError() != FormulaError::NONE);
+
+        if (!pLink)
         {
-            aBuffer.append( reinterpret_cast< const char* >( buffer.getConstArray() ), nRead );
-        }
+            pLink = new ScWebServiceLink(pDok, aURI);
+            mpLinkManager->InsertFileLink(*pLink, OBJECT_CLIENT_FILE, aURI);
+            if ( mpLinkManager->GetLinks().size() == 1 )                    // the first one?
+            {
+                SfxBindings* pBindings = pDok->GetViewBindings();
+                if (pBindings)
+                    pBindings->Invalidate( SID_LINKS );             // Link-Manager enabled
+            }
+
+            //if the document was just loaded, but the ScDdeLink entry was missing, then
+            //don't update this link until the links are updated in response to the users
+            //decision
+            if (!pDok->HasLinkFormulaNeedingCheck())
+            {
+                pLink->Update();
+            }
 
-        if ( nRead > 0 )
+            if (pMyFormulaCell)
+            {
+                // StartListening after the Update to avoid circular references
+                pMyFormulaCell->StartListening(*pLink);
+            }
+        }
+        else
         {
-            aBuffer.append( reinterpret_cast< const char* >( buffer.getConstArray() ), nRead );
+            if (pMyFormulaCell)
+                pMyFormulaCell->StartListening(*pLink);
         }
 
-        xStream->closeInput();
+        //  If an new Error from Reschedule appears when the link is executed then reset the errorflag
+        if (pMyFormulaCell && pMyFormulaCell->GetRawError() != FormulaError::NONE && !bWasError)
+            pMyFormulaCell->SetErrCode(FormulaError::NONE);
+
+        //  check the value
+        if (pLink->HasResult())
+            PushString(pLink->GetResult());
+        else
+            PushError(FormulaError::NoValue);
 
-        OUString aContent = OStringToOUString( aBuffer.makeStringAndClear(), RTL_TEXTENCODING_UTF8 );
-        PushString( aContent );
+        pDok->EnableIdle(bOldEnabled);
+        mpLinkManager->CloseCachedComps();
     }
 }
 
diff --git a/sc/source/core/tool/webservicelink.cxx b/sc/source/core/tool/webservicelink.cxx
new file mode 100644
index 000000000000..9dd5fa7007b8
--- /dev/null
+++ b/sc/source/core/tool/webservicelink.cxx
@@ -0,0 +1,106 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <comphelper/fileformat.h>
+#include <comphelper/string.hxx>
+#include <osl/thread.h>
+#include <sfx2/linkmgr.hxx>
+#include <sfx2/bindings.hxx>
+
+#include <com/sun/star/ucb/XSimpleFileAccess3.hpp>
+#include <com/sun/star/ucb/SimpleFileAccess.hpp>
+#include <com/sun/star/io/XInputStream.hpp>
+
+#include <webservicelink.hxx>
+#include <brdcst.hxx>
+#include <document.hxx>
+#include <scmatrix.hxx>
+#include <patattr.hxx>
+#include <rechead.hxx>
+#include <rangeseq.hxx>
+#include <sc.hrc>
+#include <hints.hxx>
+
+ScWebServiceLink::ScWebServiceLink(ScDocument* pD, const OUString& rURL)
+    : ::sfx2::SvBaseLink(SfxLinkUpdateMode::ALWAYS, SotClipboardFormatId::STRING)
+    , pDoc(pD)
+    , aURL(rURL)
+    , bHasResult(false)
+{
+}
+
+ScWebServiceLink::~ScWebServiceLink() {}
+
+sfx2::SvBaseLink::UpdateResult ScWebServiceLink::DataChanged(const OUString&, const css::uno::Any&)
+{
+    aResult.clear();
+    bHasResult = false;
+
+    css::uno::Reference<css::ucb::XSimpleFileAccess3> xFileAccess(
+        css::ucb::SimpleFileAccess::create(comphelper::getProcessComponentContext()),
+        css::uno::UNO_QUERY);
+    if (!xFileAccess.is())
+        return ERROR_GENERAL;
+
+    css::uno::Reference<css::io::XInputStream> xStream;
+    try
+    {
+        xStream = xFileAccess->openFileRead(aURL);
+    }
+    catch (...)
+    {
+        // don't let any exceptions pass
+        return ERROR_GENERAL;
+    }
+    if (!xStream.is())
+        return ERROR_GENERAL;
+
+    const sal_Int32 BUF_LEN = 8000;
+    css::uno::Sequence<sal_Int8> buffer(BUF_LEN);
+    OStringBuffer aBuffer(64000);
+
+    sal_Int32 nRead = 0;
+    while ((nRead = xStream->readBytes(buffer, BUF_LEN)) == BUF_LEN)
+        aBuffer.append(reinterpret_cast<const char*>(buffer.getConstArray()), nRead);
+
+    if (nRead > 0)
+        aBuffer.append(reinterpret_cast<const char*>(buffer.getConstArray()), nRead);
+
+    xStream->closeInput();
+
+    aResult = OStringToOUString(aBuffer.makeStringAndClear(), RTL_TEXTENCODING_UTF8);
+    bHasResult = true;
+
+    //  Something happened...
+    if (HasListeners())
+    {
+        Broadcast(ScHint(SfxHintId::ScDataChanged, ScAddress()));
+        pDoc->TrackFormulas(); // must happen immediately
+        pDoc->StartTrackTimer();
+    }
+
+    return SUCCESS;
+}
+
+void ScWebServiceLink::ListenersGone()
+{
+    ScDocument* pStackDoc = pDoc; // member pDoc can't be used after removing the link
+
+    sfx2::LinkManager* pLinkMgr = pDoc->GetLinkManager();
+    pLinkMgr->Remove(this); // deletes this
+
+    if (pLinkMgr->GetLinks().empty()) // deleted the last one ?
+    {
+        SfxBindings* pBindings = pStackDoc->GetViewBindings(); // don't use member pDoc!
+        if (pBindings)
+            pBindings->Invalidate(SID_LINKS);
+    }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/sc/source/ui/docshell/docsh4.cxx b/sc/source/ui/docshell/docsh4.cxx
index 19b836ffca47..598b6d8f77bb 100644
--- a/sc/source/ui/docshell/docsh4.cxx
+++ b/sc/source/ui/docshell/docsh4.cxx
@@ -454,7 +454,7 @@ void ScDocShell::Execute( SfxRequest& rReq )
                     ReloadTabLinks();
                     aDocument.UpdateExternalRefLinks(GetActiveDialogParent());
 
-                    bool bAnyDde = aDocument.GetDocLinkManager().updateDdeOrOleLinks(GetActiveDialogParent());
+                    bool bAnyDde = aDocument.GetDocLinkManager().updateDdeOrOleOrWebServiceLinks(GetActiveDialogParent());
 
                     if (bAnyDde)
                     {
diff --git a/sc/source/ui/docshell/documentlinkmgr.cxx b/sc/source/ui/docshell/documentlinkmgr.cxx
index aa508dca8ef0..f71fe99d1bb3 100644
--- a/sc/source/ui/docshell/documentlinkmgr.cxx
+++ b/sc/source/ui/docshell/documentlinkmgr.cxx
@@ -20,6 +20,7 @@
 #include <documentlinkmgr.hxx>
 #include <datastream.hxx>
 #include <ddelink.hxx>
+#include <webservicelink.hxx>
 #include <strings.hrc>
 #include <scresid.hxx>
 #include <o3tl/deleter.hxx>
@@ -115,15 +116,15 @@ bool DocumentLinkManager::idleCheckLinks()
 
 bool DocumentLinkManager::hasDdeLinks() const
 {
-    return hasDdeOrOleLinks(true, false);
+    return hasDdeOrOleOrWebServiceLinks(true, false, false);
 }
 
-bool DocumentLinkManager::hasDdeOrOleLinks() const
+bool DocumentLinkManager::hasDdeOrOleOrWebServiceLinks() const
 {
-    return hasDdeOrOleLinks(true, true);
+    return hasDdeOrOleOrWebServiceLinks(true, true, true);
 }
 
-bool DocumentLinkManager::hasDdeOrOleLinks(bool bDde, bool bOle) const
+bool DocumentLinkManager::hasDdeOrOleOrWebServiceLinks(bool bDde, bool bOle, bool bWebService) const
 {
     if (!mpImpl->mpLinkManager)
         return false;
@@ -136,12 +137,14 @@ bool DocumentLinkManager::hasDdeOrOleLinks(bool bDde, bool bOle) const
             return true;
         if (bOle && dynamic_cast<SdrEmbedObjectLink*>(pBase))
             return true;
+        if (bWebService && dynamic_cast<ScWebServiceLink*>(pBase))
+            return true;
     }
 
     return false;
 }
 
-bool DocumentLinkManager::updateDdeOrOleLinks( vcl::Window* pWin )
+bool DocumentLinkManager::updateDdeOrOleOrWebServiceLinks(vcl::Window* pWin)
 {
     if (!mpImpl->mpLinkManager)
         return false;
@@ -163,6 +166,13 @@ bool DocumentLinkManager::updateDdeOrOleLinks( vcl::Window* pWin )
             continue;
         }
 
+        ScWebServiceLink* pWebserviceLink = dynamic_cast<ScWebServiceLink*>(pBase);
+        if (pWebserviceLink)
+        {
+            pWebserviceLink->Update();
+            continue;
+        }
+
         ScDdeLink* pDdeLink = dynamic_cast<ScDdeLink*>(pBase);
         if (!pDdeLink)
             continue;
diff --git a/sc/source/ui/view/tabvwsh4.cxx b/sc/source/ui/view/tabvwsh4.cxx
index 969dfb7efd8b..5c0b1e8ab594 100644
--- a/sc/source/ui/view/tabvwsh4.cxx
+++ b/sc/source/ui/view/tabvwsh4.cxx
@@ -1567,7 +1567,7 @@ void ScTabViewShell::Construct( TriState nForceDesignMode )
             if (!bLink)
             {
                 const sc::DocumentLinkManager& rMgr = rDoc.GetDocLinkManager();
-                if (rMgr.hasDdeOrOleLinks() || rDoc.HasAreaLinks() || rDoc.HasLinkFormulaNeedingCheck())
+                if (rDoc.HasLinkFormulaNeedingCheck() || rDoc.HasAreaLinks() || rMgr.hasDdeOrOleOrWebServiceLinks())
                     bLink = true;
             }
             if (bLink)


More information about the Libreoffice-commits mailing list