put calc external data mappings under link update control
register each mapping as a LinkManager link, so its refresh goes through the same update control as sheet links and area links. Wait until after the infobar-controlled update mode is known to update. Signed-off-by: Caolán McNamara <caolan.mcnamara@collabora.com> Change-Id: I6710d4bdf3de6e002365d75c911b69076a054da8 Reviewed-on: https://gerrit.collaboraoffice.com/c/core/+/7058 Tested-by: Jenkins CPCI <releng@collaboraoffice.com> Reviewed-by: Miklos Vajna <vmiklos@collabora.com> (cherry picked from commit b72d760465c857eb5dd10cdc45b107c49bb0caec) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/208319 Reviewed-by: Xisco Fauli <xiscofauli@libreoffice.org> Tested-by: Jenkins
This commit is contained in:
committed by
Xisco Fauli
parent
a435d56867
commit
4aba7e41c1
@@ -94,7 +94,7 @@ public:
|
||||
|
||||
class SC_DLLPUBLIC ExternalDataMapper
|
||||
{
|
||||
//ScDocument& mrDoc;
|
||||
ScDocument& mrDoc;
|
||||
std::vector<ExternalDataSource> maDataSources;
|
||||
|
||||
public:
|
||||
|
||||
@@ -954,6 +954,10 @@ public:
|
||||
SCROW nRow2, SCTAB nTab) const;
|
||||
void RefreshDirtyTableColumnNames();
|
||||
SC_DLLPUBLIC sc::ExternalDataMapper& GetExternalDataMapper();
|
||||
/** True when the document holds at least one external data mapping. Checks
|
||||
without creating the mapper, so it stays cheap for documents that have
|
||||
none. */
|
||||
SC_DLLPUBLIC bool HasDataProviderMappings() const;
|
||||
|
||||
SC_DLLPUBLIC const ScRangeData* GetRangeAtBlock( const ScRange& rBlock, OUString& rName,
|
||||
bool* pSheetLocal = nullptr ) const;
|
||||
|
||||
@@ -150,6 +150,8 @@ class DataProvider(UITestCase):
|
||||
xFileName.executeAction('TYPE', mkPropertyValues({'TEXT': xFilePath}))
|
||||
|
||||
with self.ui_test.load_file(systemPathToFileUrl(xFilePath)) as doc2:
|
||||
xAllow = self.ui_test.wait_until_child_is_available("allowupdating")
|
||||
xAllow.executeAction("CLICK", tuple())
|
||||
# Without the fix in place, this test would have failed with
|
||||
# AssertionError: 'Rank' != 'Rank|Males|Females\r'
|
||||
self.assertEqual("Rank", get_cell_by_position(doc2, 0, 0, 0).getString())
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
changed
|
||||
|
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<office:document xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:calcext="urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0" office:version="1.3" office:mimetype="application/vnd.oasis.opendocument.spreadsheet">
|
||||
<office:body>
|
||||
<office:spreadsheet>
|
||||
<table:table table:name="Sheet1">
|
||||
<table:table-column/>
|
||||
<table:table-row>
|
||||
<table:table-cell office:value-type="string"><text:p>unchanged</text:p></table:table-cell>
|
||||
</table:table-row>
|
||||
</table:table>
|
||||
<table:database-ranges>
|
||||
<table:database-range table:name="myImport" table:target-range-address="Sheet1.A1:Sheet1.A1"/>
|
||||
</table:database-ranges>
|
||||
<calcext:data-mappings>
|
||||
<calcext:data-mapping xlink:href="dummy.csv" calcext:provider="org.libreoffice.calc.csv" calcext:frequency="0" calcext:id="" calcext:database-name="myImport"/>
|
||||
</calcext:data-mappings>
|
||||
</office:spreadsheet>
|
||||
</office:body>
|
||||
</office:document>
|
||||
@@ -10,6 +10,7 @@
|
||||
|
||||
#include "helper/qahelper.hxx"
|
||||
#include <document.hxx>
|
||||
#include <docsh.hxx>
|
||||
#include <address.hxx>
|
||||
#include <dbdata.hxx>
|
||||
#include <datamapper.hxx>
|
||||
@@ -17,6 +18,8 @@
|
||||
#include <orcusxml.hxx>
|
||||
#include <sortparam.hxx>
|
||||
#include <datatransformation.hxx>
|
||||
#include <comphelper/embeddedobjectcontainer.hxx>
|
||||
#include <sfx2/linkmgr.hxx>
|
||||
|
||||
#include <memory>
|
||||
|
||||
@@ -34,6 +37,7 @@ public:
|
||||
void testBaseImport();
|
||||
void testTdf169541_TwoDataMapping();
|
||||
void testTdf169610_SortTransform();
|
||||
void testLinkUpdateGate();
|
||||
|
||||
CPPUNIT_TEST_SUITE(ScDataProvidersTest);
|
||||
CPPUNIT_TEST(testCSVImport);
|
||||
@@ -43,6 +47,7 @@ public:
|
||||
CPPUNIT_TEST(testBaseImport);
|
||||
CPPUNIT_TEST(testTdf169541_TwoDataMapping);
|
||||
CPPUNIT_TEST(testTdf169610_SortTransform);
|
||||
CPPUNIT_TEST(testLinkUpdateGate);
|
||||
CPPUNIT_TEST_SUITE_END();
|
||||
};
|
||||
|
||||
@@ -305,6 +310,41 @@ void ScDataProvidersTest::testTdf169610_SortTransform()
|
||||
CPPUNIT_ASSERT_EQUAL(14.0, pDoc->GetValue(5, 11, 0));
|
||||
}
|
||||
|
||||
void ScDataProvidersTest::testLinkUpdateGate()
|
||||
{
|
||||
// A data mapping loaded from a document is an external link. Its data must
|
||||
// not refresh from the source file until the user allows link updating,
|
||||
// the same gate that governs sheet links and area links.
|
||||
createScDoc("mappinggate.fods");
|
||||
ScDocument* pDoc = getScDoc();
|
||||
CPPUNIT_ASSERT(pDoc);
|
||||
ScDocShell* pDocShell = getScDocShell();
|
||||
CPPUNIT_ASSERT(pDocShell);
|
||||
|
||||
// Loading the mapping registered it as a link in the LinkManager.
|
||||
auto& rDataSources = pDoc->GetExternalDataMapper().getDataSources();
|
||||
CPPUNIT_ASSERT_EQUAL(size_t(1), rDataSources.size());
|
||||
sfx2::LinkManager* pLinkManager = pDoc->GetLinkManager();
|
||||
CPPUNIT_ASSERT(pLinkManager);
|
||||
CPPUNIT_ASSERT_EQUAL(size_t(1), pLinkManager->GetLinks().size());
|
||||
|
||||
// The saved document holds "unchanged" in A1; the source file holds
|
||||
// "changed". The href stored in the document is not portable, so point the
|
||||
// source at the real test file before asking for an update.
|
||||
rDataSources[0].setURL(createFileURL(u"csv/mappinggate.csv"));
|
||||
CPPUNIT_ASSERT_EQUAL(u"unchanged"_ustr, pDoc->GetString(0, 0, 0));
|
||||
|
||||
// With updating not allowed, updating the links leaves the saved value.
|
||||
pDocShell->GetEmbeddedObjectContainer().setUserAllowsLinkUpdate(false);
|
||||
pLinkManager->UpdateAllLinks(false, nullptr, OUString());
|
||||
CPPUNIT_ASSERT_EQUAL(u"unchanged"_ustr, pDoc->GetString(0, 0, 0));
|
||||
|
||||
// Once the user allows updating, the same update brings in the live value.
|
||||
pDocShell->GetEmbeddedObjectContainer().setUserAllowsLinkUpdate(true);
|
||||
pLinkManager->UpdateAllLinks(false, nullptr, OUString());
|
||||
CPPUNIT_ASSERT_EQUAL(u"changed"_ustr, pDoc->GetString(0, 0, 0));
|
||||
}
|
||||
|
||||
ScDataProvidersTest::ScDataProvidersTest()
|
||||
: ScModelTestBase(u"sc/qa/unit/data/dataprovider"_ustr)
|
||||
{
|
||||
|
||||
@@ -1042,6 +1042,11 @@ sc::ExternalDataMapper& ScDocument::GetExternalDataMapper()
|
||||
return *mpDataMapper;
|
||||
}
|
||||
|
||||
bool ScDocument::HasDataProviderMappings() const
|
||||
{
|
||||
return mpDataMapper && !mpDataMapper->getDataSources().empty();
|
||||
}
|
||||
|
||||
void ScDocument::StoreTabToCache(SCTAB nTab, SvStream& rStrm) const
|
||||
{
|
||||
const ScTable* pTab = FetchTable(nTab);
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
|
||||
*/
|
||||
|
||||
#include <comphelper/embeddedobjectcontainer.hxx>
|
||||
#include <comphelper/fileformat.h>
|
||||
#include <comphelper/string.hxx>
|
||||
#include <osl/thread.h>
|
||||
@@ -29,6 +30,7 @@
|
||||
|
||||
#include <ddelink.hxx>
|
||||
#include <brdcst.hxx>
|
||||
#include <docsh.hxx>
|
||||
#include <document.hxx>
|
||||
#include <scmatrix.hxx>
|
||||
#include <patattr.hxx>
|
||||
@@ -123,6 +125,10 @@ void ScDdeLink::Store( SvStream& rStream, ScMultipleWriteHeader& rHdr ) const
|
||||
sfx2::SvBaseLink::UpdateResult ScDdeLink::DataChanged(
|
||||
const OUString& rMimeType, const css::uno::Any & rValue )
|
||||
{
|
||||
if (rDoc.GetDocumentShell()
|
||||
&& !rDoc.GetDocumentShell()->GetEmbeddedObjectContainer().getUserAllowsLinkUpdate())
|
||||
return SUCCESS;
|
||||
|
||||
// we only master strings...
|
||||
if ( SotClipboardFormatId::STRING != SotExchange::GetFormatIdFromMimeType( rMimeType ))
|
||||
return SUCCESS;
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#include <comphelper/embeddedobjectcontainer.hxx>
|
||||
#include <comphelper/processfactory.hxx>
|
||||
#include <sfx2/linkmgr.hxx>
|
||||
#include <sfx2/bindings.hxx>
|
||||
@@ -21,6 +22,7 @@
|
||||
#include <utility>
|
||||
#include <webservicelink.hxx>
|
||||
#include <brdcst.hxx>
|
||||
#include <docsh.hxx>
|
||||
#include <document.hxx>
|
||||
#include <sc.hrc>
|
||||
|
||||
@@ -36,6 +38,10 @@ ScWebServiceLink::~ScWebServiceLink() {}
|
||||
|
||||
sfx2::SvBaseLink::UpdateResult ScWebServiceLink::DataChanged(const OUString&, const css::uno::Any&)
|
||||
{
|
||||
if (pDoc && pDoc->GetDocumentShell()
|
||||
&& !pDoc->GetDocumentShell()->GetEmbeddedObjectContainer().getUserAllowsLinkUpdate())
|
||||
return SUCCESS;
|
||||
|
||||
aResult.clear();
|
||||
bHasResult = false;
|
||||
|
||||
|
||||
@@ -122,16 +122,6 @@ ScXMLMappingContext::ScXMLMappingContext( ScXMLImport& rImport,
|
||||
}
|
||||
}
|
||||
|
||||
ScXMLMappingContext::~ScXMLMappingContext()
|
||||
{
|
||||
ScDocument* pDoc = GetScImport().GetDocument();
|
||||
auto& rDataMapper = pDoc->GetExternalDataMapper();
|
||||
auto& rDataSources = rDataMapper.getDataSources();
|
||||
if(!rDataSources.empty())
|
||||
rDataSources.back().refresh(pDoc, true);
|
||||
|
||||
}
|
||||
|
||||
uno::Reference<xml::sax::XFastContextHandler>
|
||||
SAL_CALL ScXMLMappingContext::createFastChildContext(
|
||||
sal_Int32 nElement, const uno::Reference<xml::sax::XFastAttributeList>& /*xAttrList*/)
|
||||
|
||||
@@ -34,8 +34,6 @@ public:
|
||||
ScXMLMappingContext( ScXMLImport& rImport,
|
||||
const rtl::Reference<sax_fastparser::FastAttributeList>& rAttrList );
|
||||
|
||||
virtual ~ScXMLMappingContext() override;
|
||||
|
||||
virtual css::uno::Reference<css::xml::sax::XFastContextHandler> SAL_CALL createFastChildContext(
|
||||
sal_Int32 nElement,
|
||||
const css::uno::Reference<css::xml::sax::XFastAttributeList>& xAttrList) override;
|
||||
|
||||
@@ -26,6 +26,10 @@
|
||||
#include <datamapper.hxx>
|
||||
#include <dbdata.hxx>
|
||||
#include <docsh.hxx>
|
||||
#include <document.hxx>
|
||||
#include <comphelper/embeddedobjectcontainer.hxx>
|
||||
#include <sfx2/lnkbase.hxx>
|
||||
#include <sfx2/linkmgr.hxx>
|
||||
#include <utility>
|
||||
|
||||
using namespace com::sun::star;
|
||||
@@ -194,8 +198,46 @@ const std::vector<std::shared_ptr<sc::DataTransformation>>& ExternalDataSource::
|
||||
return maDataTransformations;
|
||||
}
|
||||
|
||||
ExternalDataMapper::ExternalDataMapper(ScDocument& /*rDoc*/)
|
||||
//mrDoc(rDoc)
|
||||
namespace {
|
||||
|
||||
// A data mapping fetches external data (CSV, HTML, XML) into a sheet. It is
|
||||
// registered in the LinkManager so it passes through the same link update
|
||||
// control as sheet links, area links, and external references. The link holds
|
||||
// the index of its data source in the mapper. That index is stable because
|
||||
// data sources are only ever appended, never removed.
|
||||
class ScDataProviderLink final : public sfx2::SvBaseLink
|
||||
{
|
||||
ScDocShell& mrDocShell;
|
||||
size_t mnSourceIndex;
|
||||
|
||||
public:
|
||||
ScDataProviderLink(ScDocShell& rDocShell, size_t nSourceIndex)
|
||||
: sfx2::SvBaseLink(SfxLinkUpdateMode::ONCALL, SotClipboardFormatId::SIMPLE_FILE)
|
||||
, mrDocShell(rDocShell)
|
||||
, mnSourceIndex(nSourceIndex)
|
||||
{
|
||||
}
|
||||
|
||||
virtual sfx2::SvBaseLink::UpdateResult DataChanged(const OUString&,
|
||||
const css::uno::Any&) override
|
||||
{
|
||||
if (!mrDocShell.GetEmbeddedObjectContainer().getUserAllowsLinkUpdate())
|
||||
return SUCCESS;
|
||||
|
||||
ScDocument& rDoc = mrDocShell.GetDocument();
|
||||
std::vector<sc::ExternalDataSource>& rSources
|
||||
= rDoc.GetExternalDataMapper().getDataSources();
|
||||
if (mnSourceIndex < rSources.size())
|
||||
rSources[mnSourceIndex].refresh(&rDoc, true);
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
ExternalDataMapper::ExternalDataMapper(ScDocument& rDoc)
|
||||
: mrDoc(rDoc)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -206,6 +248,19 @@ ExternalDataMapper::~ExternalDataMapper()
|
||||
void ExternalDataMapper::insertDataSource(const sc::ExternalDataSource& rSource)
|
||||
{
|
||||
maDataSources.push_back(rSource);
|
||||
|
||||
ScDocShell* pDocShell = mrDoc.GetDocumentShell();
|
||||
if (!pDocShell)
|
||||
return;
|
||||
|
||||
sfx2::LinkManager* pLinkManager = mrDoc.GetLinkManager();
|
||||
if (!pLinkManager)
|
||||
return;
|
||||
|
||||
ScDataProviderLink* pLink = new ScDataProviderLink(*pDocShell, maDataSources.size() - 1);
|
||||
const OUString& rProvider = rSource.getProvider();
|
||||
pLinkManager->InsertFileLink(*pLink, sfx2::SvBaseLinkObjectType::ClientFile,
|
||||
rSource.getURL(), &rProvider, nullptr);
|
||||
}
|
||||
|
||||
const std::vector<sc::ExternalDataSource>& ExternalDataMapper::getDataSources() const
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
#include <tools/urlobj.hxx>
|
||||
#include <unotools/transliterationwrapper.hxx>
|
||||
#include <comphelper/configuration.hxx>
|
||||
#include <comphelper/embeddedobjectcontainer.hxx>
|
||||
#include <comphelper/processfactory.hxx>
|
||||
|
||||
#include <tablink.hxx>
|
||||
@@ -140,6 +141,9 @@ bool ScTableLink::Refresh(const OUString& rNewFile, const OUString& rNewFilter,
|
||||
if (rNewFile.isEmpty() || rNewFilter.isEmpty())
|
||||
return false;
|
||||
|
||||
if (!m_rDocSh.GetEmbeddedObjectContainer().getUserAllowsLinkUpdate())
|
||||
return false;
|
||||
|
||||
OUString aNewUrl = ScGlobal::GetAbsDocName(rNewFile, &m_rDocSh);
|
||||
bool bNewUrlName = aFileName != aNewUrl;
|
||||
|
||||
|
||||
@@ -1695,7 +1695,7 @@ void ScTabViewShell::Construct( TriState nForceDesignMode )
|
||||
const sc::DocumentLinkManager& rMgr = rDoc.GetDocLinkManager();
|
||||
const ScDrawLayer* pDrawLayer = rDoc.GetDrawLayer();
|
||||
if (rDoc.HasLinkFormulaNeedingCheck() || rDoc.HasAreaLinks()
|
||||
|| rMgr.hasExternalLinks()
|
||||
|| rDoc.HasDataProviderMappings() || rMgr.hasExternalLinks()
|
||||
|| (pDrawLayer && hasDeferredFillBitmapLinks(pDrawLayer->GetItemPool()))
|
||||
|| !pDocSh->GetDeferredFormControlImages().empty())
|
||||
bLink = true;
|
||||
|
||||
@@ -1756,6 +1756,7 @@ void SfxObjectShell::ShowLinkUpdateInfobar()
|
||||
rHelpBtn.connect_clicked(LINK(nullptr, LinkUpdateHelp, DispatchHelpLinksHdl));
|
||||
|
||||
weld::Button& rBtn = pInfoBar->addButton();
|
||||
rBtn.set_buildable_name(u"allowupdating"_ustr);
|
||||
rBtn.set_label(SfxResId(STR_INFOBAR_ALLOW_UPDATING));
|
||||
rBtn.set_tooltip_text(SfxResId(STR_INFOBAR_ALLOW_UPDATING_TOOLTIP));
|
||||
rBtn.connect_clicked(LINK(this, SfxObjectShell, AllowLinksUpdateHdl));
|
||||
|
||||
Reference in New Issue
Block a user