sc/qa/unit/data/ods/two-col-shape.ods |binary sc/qa/unit/helper/qahelper.cxx | 18 +++++--- sc/qa/unit/helper/qahelper.hxx | 2 sc/qa/unit/subsequent_export-test.cxx | 74 ++++++++++++++++++++++++++++++++++ sc/source/filter/xml/xmlexprt.cxx | 7 ++- 5 files changed, 94 insertions(+), 7 deletions(-)
New commits: commit 09fd7bba57a2e31b3d5df38fb2d2eef2aeae34c0 Author: Mike Kaganski <mike.kagan...@collabora.com> AuthorDate: Tue Aug 24 19:40:34 2021 +0300 Commit: Miklos Vajna <vmik...@collabora.com> CommitDate: Fri Aug 27 08:37:54 2021 +0200 tdf#143929: chain XMLTextExportPropertySetMapper to sc's shape export This allows to export editengine columns to ODS. Alternatively, we could re-introduce chaining text attributes in XMLShapeExport ctor, which was commented out in commit d5b1e4827f8e6e0661563ec856cd80d926ba7b58 without explanation; but that would affect export from other modules as well (e.g., SdXMLExport::setSourceDocument sets up respective chaining in sd), so to be on the safe side, I do it only for ScXMLShapeExport. Change-Id: Iafee77b2b57e95031cfe1bbd2d43d7361a3e8469 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/120958 Tested-by: Mike Kaganski <mike.kagan...@collabora.com> Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com> (cherry picked from commit cfa931784082d38bb6b98058c5acccbaf9870710) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/121076 Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com> Reviewed-by: Miklos Vajna <vmik...@collabora.com> diff --git a/sc/qa/unit/data/ods/two-col-shape.ods b/sc/qa/unit/data/ods/two-col-shape.ods new file mode 100644 index 000000000000..3829546b1c27 Binary files /dev/null and b/sc/qa/unit/data/ods/two-col-shape.ods differ diff --git a/sc/qa/unit/helper/qahelper.cxx b/sc/qa/unit/helper/qahelper.cxx index c481260378c7..29e8b165df63 100644 --- a/sc/qa/unit/helper/qahelper.cxx +++ b/sc/qa/unit/helper/qahelper.cxx @@ -612,20 +612,26 @@ ScDocShellRef ScBootstrapFixture::load( return load( false, rURL, rFilter, rUserData, rTypeName, nFilterFlags, nClipboardID, nFilterVersion, pPassword ); } -ScDocShellRef ScBootstrapFixture::loadDoc( - const OUString& rFileName, sal_Int32 nFormat, bool bReadWrite ) +ScDocShellRef ScBootstrapFixture::load(const OUString& rURL, sal_Int32 nFormat, bool bReadWrite) { - OUString aFileExtension(aFileFormats[nFormat].pName, strlen(aFileFormats[nFormat].pName), RTL_TEXTENCODING_UTF8 ); OUString aFilterName(aFileFormats[nFormat].pFilterName, strlen(aFileFormats[nFormat].pFilterName), RTL_TEXTENCODING_UTF8) ; - OUString aFileName; - createFileURL( rFileName, aFileExtension, aFileName ); OUString aFilterType(aFileFormats[nFormat].pTypeName, strlen(aFileFormats[nFormat].pTypeName), RTL_TEXTENCODING_UTF8); SfxFilterFlags nFormatType = aFileFormats[nFormat].nFormatType; SotClipboardFormatId nClipboardId = SotClipboardFormatId::NONE; if (nFormatType != SfxFilterFlags::NONE) nClipboardId = SotClipboardFormatId::STARCALC_8; - return load(bReadWrite, aFileName, aFilterName, OUString(), aFilterType, nFormatType, nClipboardId, static_cast<sal_uIntPtr>(nFormatType)); + return load(bReadWrite, rURL, aFilterName, OUString(), aFilterType, nFormatType, nClipboardId, static_cast<sal_uIntPtr>(nFormatType)); +} + +ScDocShellRef ScBootstrapFixture::loadDoc( + const OUString& rFileName, sal_Int32 nFormat, bool bReadWrite ) +{ + OUString aFileExtension = OUString::fromUtf8(aFileFormats[nFormat].pName); + OUString aFileName; + createFileURL( rFileName, aFileExtension, aFileName ); + + return load(aFileName, nFormat, bReadWrite); } ScBootstrapFixture::ScBootstrapFixture( const OUString& rsBaseString ) : m_aBaseString( rsBaseString ) {} diff --git a/sc/qa/unit/helper/qahelper.hxx b/sc/qa/unit/helper/qahelper.hxx index ad518d160f18..17c73364b55c 100644 --- a/sc/qa/unit/helper/qahelper.hxx +++ b/sc/qa/unit/helper/qahelper.hxx @@ -177,6 +177,8 @@ protected: const OUString& rTypeName, SfxFilterFlags nFilterFlags, SotClipboardFormatId nClipboardID, sal_uIntPtr nFilterVersion = SOFFICE_FILEFORMAT_CURRENT, const OUString* pPassword = nullptr ); + ScDocShellRef load(const OUString& rURL, sal_Int32 nFormat, bool bReadWrite = false); + ScDocShellRef loadDoc(const OUString& rFileName, sal_Int32 nFormat, bool bReadWrite = false ); public: diff --git a/sc/qa/unit/subsequent_export-test.cxx b/sc/qa/unit/subsequent_export-test.cxx index c5f64eadafa3..c23d545e1a95 100644 --- a/sc/qa/unit/subsequent_export-test.cxx +++ b/sc/qa/unit/subsequent_export-test.cxx @@ -80,6 +80,7 @@ #include <com/sun/star/frame/Desktop.hpp> #include <com/sun/star/graphic/GraphicType.hpp> #include <com/sun/star/sheet/GlobalSheetSettings.hpp> +#include <com/sun/star/text/XTextColumns.hpp> using namespace ::com::sun::star; using namespace ::com::sun::star::uno; @@ -292,6 +293,7 @@ public: void testInvalidNamedRange(); void testTdf140431(); void testTdf142264ManyChartsToXLSX(); + void testTdf143929MultiColumnToODS(); CPPUNIT_TEST_SUITE(ScExportTest); @@ -477,6 +479,7 @@ public: CPPUNIT_TEST(testInvalidNamedRange); CPPUNIT_TEST(testTdf140431); CPPUNIT_TEST(testTdf142264ManyChartsToXLSX); + CPPUNIT_TEST(testTdf143929MultiColumnToODS); CPPUNIT_TEST_SUITE_END(); @@ -6028,6 +6031,77 @@ void ScExportTest::testTdf142264ManyChartsToXLSX() xDocSh->DoClose(); } +void ScExportTest::testTdf143929MultiColumnToODS() +{ + ScDocShellRef xDocSh = loadDoc(u"two-col-shape.", FORMAT_ODS); + CPPUNIT_ASSERT(xDocSh); + + { + css::uno::Reference<css::drawing::XDrawPagesSupplier> xSupplier(xDocSh->GetModel(), + css::uno::UNO_QUERY_THROW); + css::uno::Reference<css::drawing::XDrawPage> xPage(xSupplier->getDrawPages()->getByIndex(0), + css::uno::UNO_QUERY_THROW); + css::uno::Reference<css::container::XIndexAccess> xIndexAccess(xPage, + css::uno::UNO_QUERY_THROW); + css::uno::Reference<css::drawing::XShape> xShape(xIndexAccess->getByIndex(0), + css::uno::UNO_QUERY_THROW); + css::uno::Reference<css::beans::XPropertySet> xProps(xShape, css::uno::UNO_QUERY_THROW); + css::uno::Reference<css::text::XTextColumns> xCols(xProps->getPropertyValue("TextColumns"), + css::uno::UNO_QUERY_THROW); + CPPUNIT_ASSERT_EQUAL(sal_Int16(2), xCols->getColumnCount()); + css::uno::Reference<css::beans::XPropertySet> xColProps(xCols, css::uno::UNO_QUERY_THROW); + CPPUNIT_ASSERT_EQUAL(css::uno::Any(sal_Int32(1000)), + xColProps->getPropertyValue("AutomaticDistance")); + } + + auto tempFile = exportTo(xDocSh.get(), FORMAT_ODS); + xDocSh = load(tempFile->GetURL(), FORMAT_ODS); + CPPUNIT_ASSERT(xDocSh); + + { + css::uno::Reference<css::drawing::XDrawPagesSupplier> xSupplier(xDocSh->GetModel(), + css::uno::UNO_QUERY_THROW); + css::uno::Reference<css::drawing::XDrawPage> xPage(xSupplier->getDrawPages()->getByIndex(0), + css::uno::UNO_QUERY_THROW); + css::uno::Reference<css::container::XIndexAccess> xIndexAccess(xPage, + css::uno::UNO_QUERY_THROW); + css::uno::Reference<css::drawing::XShape> xShape(xIndexAccess->getByIndex(0), + css::uno::UNO_QUERY_THROW); + css::uno::Reference<css::beans::XPropertySet> xProps(xShape, css::uno::UNO_QUERY_THROW); + + // Without the fix in place, this would have failed with: + // An uncaught exception of type com.sun.star.uno.RuntimeException + // - unsatisfied query for interface of type com.sun.star.text.XTextColumns! + css::uno::Reference<css::text::XTextColumns> xCols(xProps->getPropertyValue("TextColumns"), + css::uno::UNO_QUERY_THROW); + CPPUNIT_ASSERT_EQUAL(sal_Int16(2), xCols->getColumnCount()); + css::uno::Reference<css::beans::XPropertySet> xColProps(xCols, css::uno::UNO_QUERY_THROW); + CPPUNIT_ASSERT_EQUAL(css::uno::Any(sal_Int32(1000)), + xColProps->getPropertyValue("AutomaticDistance")); + } + + xDocSh->DoClose(); + + xmlDocUniquePtr pXmlDoc = XPathHelper::parseExport(tempFile, m_xSFactory, "content.xml"); + CPPUNIT_ASSERT(pXmlDoc); + // Without the fix in place, this would have failed with: + // - Expected: 1 + // - Actual : 0 + // - In <>, XPath '/office:document-content/office:automatic-styles/style:style[@style:family='graphic']/ + // style:graphic-properties/style:columns' number of nodes is incorrect + assertXPath( + pXmlDoc, + "/office:document-content/office:automatic-styles/style:style[@style:family='graphic']/" + "style:graphic-properties/style:columns", + "column-count", "2"); + // Only test that "column-gap" attribute exists, not its value that depends on locale (cm, in) + getXPath( + pXmlDoc, + "/office:document-content/office:automatic-styles/style:style[@style:family='graphic']/" + "style:graphic-properties/style:columns", + "column-gap"); +} + CPPUNIT_TEST_SUITE_REGISTRATION(ScExportTest); CPPUNIT_PLUGIN_IMPLEMENT(); diff --git a/sc/source/filter/xml/xmlexprt.cxx b/sc/source/filter/xml/xmlexprt.cxx index 0b060dc132e7..1ee3886e2a2c 100644 --- a/sc/source/filter/xml/xmlexprt.cxx +++ b/sc/source/filter/xml/xmlexprt.cxx @@ -313,7 +313,12 @@ namespace { class ScXMLShapeExport : public XMLShapeExport { public: - explicit ScXMLShapeExport(SvXMLExport& rExp) : XMLShapeExport(rExp) {} + explicit ScXMLShapeExport(SvXMLExport& rExp) + : XMLShapeExport(rExp, + // chain text attributes + XMLTextParagraphExport::CreateParaExtPropMapper(rExp)) + { + } /** is called before a shape element for the given XShape is exported */ virtual void onExport( const uno::Reference < drawing::XShape >& xShape ) override;