oox/source/ppt/pptshape.cxx | 143 ++++++++++++++++++++---------------- sd/qa/unit/data/pptx/tdf144917.pptx |binary sd/qa/unit/import-tests.cxx | 21 +++++ 3 files changed, 101 insertions(+), 63 deletions(-)
New commits: commit 378e8396223a80b96262d7b638a066eb83ba88d6 Author: Tibor Nagy <nagy.tib...@nisz.hu> AuthorDate: Wed Oct 6 09:31:37 2021 +0200 Commit: László Németh <nem...@numbertext.org> CommitDate: Wed Oct 20 12:30:21 2021 +0200 tdf#144917 PPTX import: fix hyperlinks on grouped shapes Hyperlinks on the shapes of a group shape weren't imported. Now all of them are imported correctly. Change-Id: Ic42892650a3492958600232bd7038585f9aa6ae1 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/123127 Tested-by: László Németh <nem...@numbertext.org> Reviewed-by: László Németh <nem...@numbertext.org> diff --git a/oox/source/ppt/pptshape.cxx b/oox/source/ppt/pptshape.cxx index bbc7d2585fd8..2a134ada4a0c 100644 --- a/oox/source/ppt/pptshape.cxx +++ b/oox/source/ppt/pptshape.cxx @@ -518,6 +518,8 @@ void PPTShape::addShape( } } + OUString sURL; + std::vector<std::pair<OUString, Reference<XShape>>> aURLShapes; // if this is a group shape, we have to add also each child shape Reference<XShapes> xShapes(xShape, UNO_QUERY); if (xShapes.is()) @@ -531,6 +533,15 @@ void PPTShape::addShape( { rFilterBase.setDiagramFontHeights(nullptr); } + for (size_t i = 0; i < this->getChildren().size(); i++) + { + this->getChildren()[i]->getShapeProperties().getProperty(PROP_URL) >>= sURL; + if (!sURL.isEmpty()) + { + Reference<XShape> xChild = this->getChildren()[i]->getXShape(); + aURLShapes.push_back({ sURL, xChild }); + } + } } if (meFrameType == FRAMETYPE_DIAGRAM) @@ -539,77 +550,83 @@ void PPTShape::addShape( syncDiagramFontHeights(); } - OUString sURL; getShapeProperties().getProperty(PROP_URL) >>= sURL; - if (!sURL.isEmpty()) + if (!sURL.isEmpty() && !xShapes.is()) + aURLShapes.push_back({ sURL, xShape }); + + if (!aURLShapes.empty()) { - Reference<XEventsSupplier> xEventsSupplier(xShape, UNO_QUERY); - if (!xEventsSupplier.is()) - return; - - Reference<XNameReplace> xEvents(xEventsSupplier->getEvents()); - if (!xEvents.is()) - return; - - OUString sAPIEventName; - sal_Int32 nPropertyCount = 2; - css::presentation::ClickAction meClickAction; - uno::Sequence<beans::PropertyValue> aProperties; - - std::map<OUString, css::presentation::ClickAction> ActionMap = { - { "#action?jump=nextslide", ClickAction_NEXTPAGE }, - { "#action?jump=previousslide", ClickAction_PREVPAGE }, - { "#action?jump=firstslide", ClickAction_FIRSTPAGE }, - { "#action?jump=lastslide", ClickAction_LASTPAGE }, - { "#action?jump=endshow", ClickAction_STOPPRESENTATION }, - }; - - std::map<OUString, css::presentation::ClickAction>::const_iterator aIt - = ActionMap.find(sURL); - aIt != ActionMap.end() ? meClickAction = aIt->second - : meClickAction = ClickAction_BOOKMARK; - - // ClickAction_BOOKMARK and ClickAction_DOCUMENT share the same event - // so check here if it's a bookmark or a document - if (meClickAction == ClickAction_BOOKMARK) + for (auto const& URLShape : aURLShapes) { - if (!sURL.startsWith("#")) - meClickAction = ClickAction_DOCUMENT; - else - sURL = sURL.copy(1); - nPropertyCount += 1; - } + Reference<XEventsSupplier> xEventsSupplier(URLShape.second, UNO_QUERY); + if (!xEventsSupplier.is()) + return; + + Reference<XNameReplace> xEvents(xEventsSupplier->getEvents()); + if (!xEvents.is()) + return; + + OUString sAPIEventName; + sal_Int32 nPropertyCount = 2; + css::presentation::ClickAction meClickAction; + uno::Sequence<beans::PropertyValue> aProperties; + + std::map<OUString, css::presentation::ClickAction> ActionMap = { + { "#action?jump=nextslide", ClickAction_NEXTPAGE }, + { "#action?jump=previousslide", ClickAction_PREVPAGE }, + { "#action?jump=firstslide", ClickAction_FIRSTPAGE }, + { "#action?jump=lastslide", ClickAction_LASTPAGE }, + { "#action?jump=endshow", ClickAction_STOPPRESENTATION }, + }; + + sURL = URLShape.first; + std::map<OUString, css::presentation::ClickAction>::const_iterator aIt + = ActionMap.find(sURL); + aIt != ActionMap.end() ? meClickAction = aIt->second + : meClickAction = ClickAction_BOOKMARK; + + // ClickAction_BOOKMARK and ClickAction_DOCUMENT share the same event + // so check here if it's a bookmark or a document + if (meClickAction == ClickAction_BOOKMARK) + { + if (!sURL.startsWith("#")) + meClickAction = ClickAction_DOCUMENT; + else + sURL = sURL.copy(1); + nPropertyCount += 1; + } - aProperties.realloc(nPropertyCount); - beans::PropertyValue* pProperties = aProperties.getArray(); + aProperties.realloc(nPropertyCount); + beans::PropertyValue* pProperties = aProperties.getArray(); - pProperties->Name = "EventType"; - pProperties->Handle = -1; - pProperties->Value <<= OUString("Presentation"); - pProperties->State = beans::PropertyState_DIRECT_VALUE; - pProperties++; + pProperties->Name = "EventType"; + pProperties->Handle = -1; + pProperties->Value <<= OUString("Presentation"); + pProperties->State = beans::PropertyState_DIRECT_VALUE; + pProperties++; - pProperties->Name = "ClickAction"; - pProperties->Handle = -1; - pProperties->Value <<= meClickAction; - pProperties->State = beans::PropertyState_DIRECT_VALUE; - pProperties++; + pProperties->Name = "ClickAction"; + pProperties->Handle = -1; + pProperties->Value <<= meClickAction; + pProperties->State = beans::PropertyState_DIRECT_VALUE; + pProperties++; - switch (meClickAction) - { - case ClickAction_BOOKMARK: - case ClickAction_DOCUMENT: - pProperties->Name = "Bookmark"; - pProperties->Handle = -1; - pProperties->Value <<= sURL; - pProperties->State = beans::PropertyState_DIRECT_VALUE; - break; - default: - break; - } + switch (meClickAction) + { + case ClickAction_BOOKMARK: + case ClickAction_DOCUMENT: + pProperties->Name = "Bookmark"; + pProperties->Handle = -1; + pProperties->Value <<= sURL; + pProperties->State = beans::PropertyState_DIRECT_VALUE; + break; + default: + break; + } - sAPIEventName = "OnClick"; - xEvents->replaceByName(sAPIEventName, uno::Any(aProperties)); + sAPIEventName = "OnClick"; + xEvents->replaceByName(sAPIEventName, uno::Any(aProperties)); + } } } } diff --git a/sd/qa/unit/data/pptx/tdf144917.pptx b/sd/qa/unit/data/pptx/tdf144917.pptx new file mode 100644 index 000000000000..654b17a432cd Binary files /dev/null and b/sd/qa/unit/data/pptx/tdf144917.pptx differ diff --git a/sd/qa/unit/import-tests.cxx b/sd/qa/unit/import-tests.cxx index 36b3886d852f..580cb527e85f 100644 --- a/sd/qa/unit/import-tests.cxx +++ b/sd/qa/unit/import-tests.cxx @@ -122,6 +122,7 @@ public: virtual void setUp() override; void testDocumentLayout(); + void testTdf144917(); void testHyperlinkOnImage(); void testTdf142645(); void testTdf141704(); @@ -248,6 +249,7 @@ public: CPPUNIT_TEST_SUITE(SdImportTest); CPPUNIT_TEST(testDocumentLayout); + CPPUNIT_TEST(testTdf144917); CPPUNIT_TEST(testHyperlinkOnImage); CPPUNIT_TEST(testTdf142645); CPPUNIT_TEST(testTdf141704); @@ -450,6 +452,25 @@ void SdImportTest::testDocumentLayout() } } +void SdImportTest::testTdf144917() +{ + sd::DrawDocShellRef xDocShRef + = loadURL(m_directories.getURLFromSrc(u"/sd/qa/unit/data/pptx/tdf144917.pptx"), PPTX); + + uno::Reference<container::XIndexAccess> xGroupShape(getShapeFromPage(0, 0, xDocShRef), + uno::UNO_QUERY_THROW); + uno::Reference<beans::XPropertySet> xShape(xGroupShape->getByIndex(1), uno::UNO_QUERY_THROW); + uno::Reference<document::XEventsSupplier> xEventsSupplier(xShape, uno::UNO_QUERY); + uno::Reference<container::XNameAccess> xEvents(xEventsSupplier->getEvents()); + uno::Sequence<beans::PropertyValue> props; + xEvents->getByName("OnClick") >>= props; + comphelper::SequenceAsHashMap map(props); + auto iter(map.find("Bookmark")); + CPPUNIT_ASSERT_EQUAL(OUString("http://www.example.com/"), iter->second.get<OUString>()); + + xDocShRef->DoClose(); +} + void SdImportTest::testHyperlinkOnImage() { sd::DrawDocShellRef xDocShRef