oox/source/export/drawingml.cxx |   39 +++++++++++++++++++++++++++++++--------
 oox/source/export/shapes.cxx    |   19 +++++++++++++++++++
 2 files changed, 50 insertions(+), 8 deletions(-)

New commits:
commit b93d0eca0f7bdb5aabbc2abf4fada51342f5ba42
Author:     Karthik Godha <[email protected]>
AuthorDate: Thu Dec 11 18:27:12 2025 +0530
Commit:     Xisco Fauli <[email protected]>
CommitDate: Thu Jan 8 22:21:33 2026 +0100

    tdf#169941: ODP->PPTX exporting shape hyperlinks
    
    LO supports hyperlinks to shapes within the document. PowerPoint doesn't
    have this feature. Export of these shape hyperlinks is not handled.
    
    Now hyperlinks to shapes are converted to slides in which thy are
    present.
    
    Change-Id: I53f971c35a4f0f58532048b4041b0f35814b2715
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/195465
    Reviewed-by: Michael Stahl <[email protected]>
    Tested-by: Jenkins CollaboraOffice <[email protected]>
    (cherry picked from commit ef58ed0184cfd362175d880f4efb3d297a3d2641)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/196540
    Tested-by: Jenkins
    Signed-off-by: Xisco Fauli <[email protected]>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/196665

diff --git a/oox/source/export/drawingml.cxx b/oox/source/export/drawingml.cxx
index 4039ffae545a..d5b0e761b356 100644
--- a/oox/source/export/drawingml.cxx
+++ b/oox/source/export/drawingml.cxx
@@ -2484,6 +2484,25 @@ static OUString lcl_GetTarget(const 
css::uno::Reference<css::frame::XModel>& xMo
             sTarget = "slide" + OUString::number(i + 1) + ".xml";
             break;
         }
+        else // If URL is linked to a shape, assign it's slide as target
+        {
+            Reference<XShapes> xShapes = xDrawPage;
+            sal_uInt32 nShapes = xShapes->getCount();
+            for (sal_uInt32 j = 0; j < nShapes; j++)
+            {
+                Reference<XShape> xShape;
+                xShapes->getByIndex(j) >>= xShape;
+                Reference<container::XNamed> xName(xShape, UNO_QUERY);
+                if (!xName)
+                    continue;
+                OUString sShapeName = "#" + xName->getName();
+                if (rURL == sShapeName)
+                {
+                    sTarget = "slide" + OUString::number(i + 1) + ".xml";
+                    break;
+                }
+            }
+        }
     }
     if (sTarget.isEmpty())
     {
@@ -2896,17 +2915,21 @@ void DrawingML::WriteRunProperties(const 
Reference<XPropertySet>& rRun, sal_Int3
                 bool bExtURL = URLTransformer().isExternalURL(sURL);
                 sURL = bExtURL ? sURL : lcl_GetTarget(GetFB()->getModel(), 
sURL);
 
-                OUString sRelId
-                    = mpFB->addRelation(mpFS->getOutputStream(),
-                                        bExtURL ? 
oox::getRelationship(Relationship::HYPERLINK)
-                                                : 
oox::getRelationship(Relationship::SLIDE),
-                                        sURL, bExtURL);
-
+                OUString sRelId;
+                if (!sURL.isEmpty())
+                {
+                    sRelId
+                        = mpFB->addRelation(mpFS->getOutputStream(),
+                                            bExtURL ? 
oox::getRelationship(Relationship::HYPERLINK)
+                                                    : 
oox::getRelationship(Relationship::SLIDE),
+                                            sURL, 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");
+                    mpFS->singleElementNS(
+                        XML_a, XML_hlinkClick, FSNS(XML_r, XML_id), sRelId, 
XML_action,
+                        sURL.isEmpty() ? "ppaction://noaction" : 
"ppaction://hlinksldjump");
             }
             else
             {
diff --git a/oox/source/export/shapes.cxx b/oox/source/export/shapes.cxx
index b75732cdb293..30e08d2a9720 100644
--- a/oox/source/export/shapes.cxx
+++ b/oox/source/export/shapes.cxx
@@ -751,6 +751,25 @@ static OUString lcl_GetTarget(const 
css::uno::Reference<css::frame::XModel>& xMo
             sTarget = "slide" + OUString::number(i + 1) + ".xml";
             break;
         }
+        else // If URL is linked to a shape, assign it's slide as target
+        {
+            Reference<XShapes> xShapes = xDrawPage;
+            sal_uInt32 nShapes = xShapes->getCount();
+            for (sal_uInt32 j = 0; j < nShapes; j++)
+            {
+                Reference<XShape> xShape;
+                xShapes->getByIndex(j) >>= xShape;
+                Reference<container::XNamed> xName(xShape, UNO_QUERY);
+                if (!xName)
+                    continue;
+                OUString sShapeName = "#" + xName->getName();
+                if (rURL == sShapeName)
+                {
+                    sTarget = "slide" + OUString::number(i + 1) + ".xml";
+                    break;
+                }
+            }
+        }
     }
 
     return sTarget;

Reply via email to