oox/source/export/shapes.cxx | 88 ++++++++++++++++++++++++++++++++++--- sd/qa/unit/export-tests-ooxml1.cxx | 44 ++++++++++++++++++ 2 files changed, 127 insertions(+), 5 deletions(-)
New commits: commit 73f26b73aaf562bf934249460480b4a60937a438 Author: Tibor Nagy <nagy.tib...@nisz.hu> AuthorDate: Mon Sep 27 16:48:14 2021 +0200 Commit: László Németh <nem...@numbertext.org> CommitDate: Wed Oct 13 16:40:05 2021 +0200 tdf#124232 PPTX export: fix interactions and hyperlinks on images Follow-up to commit 9bb91441b46d677860530d8bf9597c96561a1b0a "tdf#141704 PPTX import: fix hyperlinks on images" Change-Id: If29241ea06253e503dae27f8dc762574a5a634de Reviewed-on: https://gerrit.libreoffice.org/c/core/+/122717 Tested-by: László Németh <nem...@numbertext.org> Reviewed-by: László Németh <nem...@numbertext.org> diff --git a/oox/source/export/shapes.cxx b/oox/source/export/shapes.cxx index dca1775112bb..1dd77a34b2ab 100644 --- a/oox/source/export/shapes.cxx +++ b/oox/source/export/shapes.cxx @@ -58,6 +58,10 @@ #include <com/sun/star/chart2/XChartDocument.hpp> #include <com/sun/star/frame/XModel.hpp> #include <com/sun/star/uno/XComponentContext.hpp> +#include <com/sun/star/drawing/XDrawPages.hpp> +#include <com/sun/star/drawing/XDrawPagesSupplier.hpp> +#include <com/sun/star/document/XEventsSupplier.hpp> +#include <com/sun/star/presentation/ClickAction.hpp> #include <tools/globname.hxx> #include <comphelper/classids.hxx> #include <comphelper/propertysequence.hxx> @@ -696,6 +700,32 @@ static sal_Int32 lcl_CircleAngle2CustomShapeEllipseAngleOOX(const sal_Int32 nInt return 0; } +static OUString lcl_GetTarget(const css::uno::Reference<css::frame::XModel>& xModel, + std::u16string_view rURL) +{ + Reference<drawing::XDrawPagesSupplier> xDPS(xModel, uno::UNO_QUERY_THROW); + Reference<drawing::XDrawPages> xDrawPages(xDPS->getDrawPages(), uno::UNO_SET_THROW); + sal_uInt32 nPageCount = xDrawPages->getCount(); + OUString sTarget; + + for (sal_uInt32 i = 0; i < nPageCount; ++i) + { + Reference<XDrawPage> xDrawPage; + xDrawPages->getByIndex(i) >>= xDrawPage; + Reference<container::XNamed> xNamed(xDrawPage, UNO_QUERY); + if (!xNamed) + continue; + OUString sSlideName = "#" + xNamed->getName(); + if (rURL == sSlideName) + { + sTarget = "slide" + OUString::number(i + 1) + ".xml"; + break; + } + } + + return sTarget; +} + ShapeExport& ShapeExport::WriteCustomShape( const Reference< XShape >& xShape ) { SAL_INFO("oox.shape", "write custom shape"); @@ -1195,24 +1225,55 @@ void ShapeExport::WriteGraphicObjectShapePart( const Reference< XShape >& xShape pFS->startElementNS(mnXmlNamespace, XML_nvPicPr); - OUString sDescr, sURL; + presentation::ClickAction eClickAction = presentation::ClickAction_NONE; + OUString sDescr, sURL, sBookmark, sPPAction; bool bHaveDesc; if ( ( bHaveDesc = GetProperty( xShapeProps, "Description" ) ) ) mAny >>= sDescr; if ( GetProperty( xShapeProps, "URL" ) ) mAny >>= sURL; + if (GetProperty(xShapeProps, "Bookmark")) + mAny >>= sBookmark; + if (GetProperty(xShapeProps, "OnClick")) + mAny >>= eClickAction; pFS->startElementNS( mnXmlNamespace, XML_cNvPr, XML_id, OString::number(GetNewShapeID(xShape)), XML_name, GetShapeName(xShape), XML_descr, sax_fastparser::UseIf(sDescr, bHaveDesc)); + if (eClickAction != presentation::ClickAction_NONE) + { + switch (eClickAction) + { + case presentation::ClickAction_STOPPRESENTATION: + sPPAction = "ppaction://hlinkshowjump?jump=endshow"; + break; + case presentation::ClickAction_NEXTPAGE: + sPPAction = "ppaction://hlinkshowjump?jump=nextslide"; + break; + case presentation::ClickAction_LASTPAGE: + sPPAction = "ppaction://hlinkshowjump?jump=lastslide"; + break; + case presentation::ClickAction_PREVPAGE: + sPPAction = "ppaction://hlinkshowjump?jump=previousslide"; + break; + case presentation::ClickAction_FIRSTPAGE: + sPPAction = "ppaction://hlinkshowjump?jump=firstslide"; + break; + case presentation::ClickAction_BOOKMARK: + sBookmark = "#" + sBookmark; + break; + default: + break; + } + } + // OOXTODO: //cNvPr children: XML_extLst, XML_hlinkHover - if (bHasMediaURL) - pFS->singleElementNS(XML_a, XML_hlinkClick, - FSNS(XML_r, XML_id), "", - XML_action, "ppaction://media"); + if (bHasMediaURL || !sPPAction.isEmpty()) + pFS->singleElementNS(XML_a, XML_hlinkClick, FSNS(XML_r, XML_id), "", XML_action, + bHasMediaURL ? "ppaction://media" : sPPAction); if( !sURL.isEmpty() ) { OUString sRelId = mpFB->addRelation( mpFS->getOutputStream(), @@ -1222,6 +1283,23 @@ void ShapeExport::WriteGraphicObjectShapePart( const Reference< XShape >& xShape mpFS->singleElementNS(XML_a, XML_hlinkClick, FSNS(XML_r, XML_id), sRelId); } + + if (!sBookmark.isEmpty()) + { + bool bExtURL = URLTransformer().isExternalURL(sBookmark); + sBookmark = bExtURL ? sBookmark : lcl_GetTarget(GetFB()->getModel(), sBookmark); + + OUString sRelId = mpFB->addRelation(mpFS->getOutputStream(), + bExtURL ? oox::getRelationship(Relationship::HYPERLINK) + : oox::getRelationship(Relationship::SLIDE), + sBookmark, bExtURL); + + if (bExtURL) + mpFS->singleElementNS(XML_a, XML_hlinkClick, FSNS(XML_r, XML_id), sRelId); + else + mpFS->singleElementNS(XML_a, XML_hlinkClick, FSNS(XML_r, XML_id), sRelId, XML_action, + "ppaction://hlinksldjump"); + } pFS->endElementNS(mnXmlNamespace, XML_cNvPr); pFS->singleElementNS(mnXmlNamespace, XML_cNvPicPr diff --git a/sd/qa/unit/export-tests-ooxml1.cxx b/sd/qa/unit/export-tests-ooxml1.cxx index 9aa12ffb4a3d..84c7ed4bb596 100644 --- a/sd/qa/unit/export-tests-ooxml1.cxx +++ b/sd/qa/unit/export-tests-ooxml1.cxx @@ -61,6 +61,7 @@ using namespace css; class SdOOXMLExportTest1 : public SdModelTestBaseXML { public: + void testTdf124232(); void testTdf143624(); void testTdf142648(); void testTdf47365(); @@ -124,6 +125,7 @@ public: CPPUNIT_TEST_SUITE(SdOOXMLExportTest1); + CPPUNIT_TEST(testTdf124232); CPPUNIT_TEST(testTdf143624); CPPUNIT_TEST(testTdf142648); CPPUNIT_TEST(testTdf47365); @@ -214,6 +216,48 @@ void checkFontAttributes( const SdrTextObj* pObj, ItemValue nVal, sal_uInt32 nId } +void SdOOXMLExportTest1::testTdf124232() +{ + sd::DrawDocShellRef xDocShRef = loadURL(m_directories.getURLFromSrc(u"/sd/qa/unit/data/pptx/tdf141704.pptx"), PPTX); + utl::TempFile tempFile; + xDocShRef = saveAndReload(xDocShRef.get(), PPTX, &tempFile); + xDocShRef->DoClose(); + + xmlDocUniquePtr pXmlDoc1 = parseExport(tempFile, "ppt/slides/slide1.xml"); + assertXPath(pXmlDoc1, "/p:sld/p:cSld/p:spTree/p:pic/p:nvPicPr/p:cNvPr/a:hlinkClick", "action", + "ppaction://hlinkshowjump?jump=lastslide"); + + xmlDocUniquePtr pXmlDoc2 = parseExport(tempFile, "ppt/slides/slide2.xml"); + assertXPath(pXmlDoc2, "/p:sld/p:cSld/p:spTree/p:pic/p:nvPicPr/p:cNvPr/a:hlinkClick", "action", + "ppaction://hlinkshowjump?jump=nextslide"); + + xmlDocUniquePtr pXmlDoc3 = parseExport(tempFile, "ppt/slides/slide3.xml"); + assertXPath(pXmlDoc3, "/p:sld/p:cSld/p:spTree/p:pic/p:nvPicPr/p:cNvPr/a:hlinkClick", "action", + "ppaction://hlinkshowjump?jump=previousslide"); + + xmlDocUniquePtr pXmlDoc4 = parseExport(tempFile, "ppt/slides/slide4.xml"); + assertXPath(pXmlDoc4, "/p:sld/p:cSld/p:spTree/p:pic/p:nvPicPr/p:cNvPr/a:hlinkClick", + "id", "rId1"); + xmlDocUniquePtr pRelsDoc4 = parseExport(tempFile, "ppt/slides/_rels/slide4.xml.rels"); + assertXPath(pRelsDoc4, "/rels:Relationships/rels:Relationship[@Id='rId1']", "Target", + "http://www.example.com/"); + + xmlDocUniquePtr pXmlDoc5 = parseExport(tempFile, "ppt/slides/slide5.xml"); + assertXPath(pXmlDoc5, "/p:sld/p:cSld/p:spTree/p:pic/p:nvPicPr/p:cNvPr/a:hlinkClick", + "action", "ppaction://hlinksldjump"); + xmlDocUniquePtr pRelsDoc5 = parseExport(tempFile, "ppt/slides/_rels/slide5.xml.rels"); + assertXPath(pRelsDoc5, "/rels:Relationships/rels:Relationship[@Id='rId1']", "Target", + "slide6.xml"); + + xmlDocUniquePtr pXmlDoc6 = parseExport(tempFile, "ppt/slides/slide6.xml"); + assertXPath(pXmlDoc6, "/p:sld/p:cSld/p:spTree/p:pic/p:nvPicPr/p:cNvPr/a:hlinkClick", + "action", "ppaction://hlinkshowjump?jump=endshow"); + + xmlDocUniquePtr pXmlDoc7 = parseExport(tempFile, "ppt/slides/slide7.xml"); + assertXPath(pXmlDoc7, "/p:sld/p:cSld/p:spTree/p:pic/p:nvPicPr/p:cNvPr/a:hlinkClick", + "action", "ppaction://hlinkshowjump?jump=firstslide"); +} + void SdOOXMLExportTest1::testTdf143624() { sd::DrawDocShellRef xDocShRef = loadURL( m_directories.getURLFromSrc(u"/sd/qa/unit/data/pptx/tdf143624.pptx"), PPTX );