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 );

Reply via email to