tdf#148965 PPTX import: fix internal hyperlinks on shapes

Locale dependent code path resulted broken hyperlinks
on shapes in a non-English build.

Change-Id: I045bbe4246ab5336e2b967bf252b5fbca5b17706
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/134266
Tested-by: László Németh <nemeth@numbertext.org>
Reviewed-by: László Németh <nemeth@numbertext.org>
This commit is contained in:
Tibor Nagy 2022-05-13 08:12:17 +02:00 committed by László Németh
parent b3c965ccaa
commit 855a56fea4
7 changed files with 100 additions and 18 deletions

View file

@ -140,6 +140,9 @@ public:
void setConnectorShape(bool bConnector) { mbConnector = bConnector; }
bool isConnectorShape() const { return mbConnector; }
void setBookmark(bool bBookmark) { mbHasBookmark = bBookmark; }
bool hasBookmark() const { return mbHasBookmark; }
Shape3DProperties& get3DProperties() { return *mp3DPropertiesPtr; }
const Shape3DProperties& get3DProperties() const { return *mp3DPropertiesPtr; }
@ -410,6 +413,9 @@ private:
// Is this a connector shape?
bool mbConnector = false;
// Is shape has bookmark?
bool mbHasBookmark = false;
// temporary space for DiagramHelper in preparation for collecting data
// Note: I tried to use a unique_ptr here, but existing constructor func does not allow that
svx::diagram::IDiagramHelper* mpDiagramHelper;

View file

@ -127,6 +127,9 @@ public:
void createConnectorShapeConnection();
void addURLShapeId(const OUString& rShapeId) { maURLShapeId.push_back(rShapeId); }
std::vector<OUString>& getURLShapeId() { return maURLShapeId; }
private:
OUString maPath;
OUString maLayoutPath;
@ -160,6 +163,7 @@ private:
CommentAuthorList maCommentAuthors;
std::vector<OUString> maConnectorShapeId;
std::vector<OUString> maURLShapeId;
};
}

View file

@ -613,27 +613,14 @@ void PPTShape::addShape(
// so check here if it's a bookmark or a document
if (meClickAction == ClickAction_BOOKMARK)
{
sal_Int32 nSplitPos;
if (!sURL.startsWith("#"))
meClickAction = ClickAction_DOCUMENT;
else
else if (-1 != (nSplitPos = sURL.indexOf( ' ' )))
{
sURL = sURL.copy(1);
sal_Int32 nPageNumber = 0;
static const OUStringLiteral sSlide = u"Slide ";
if (sURL.match(sSlide))
nPageNumber = o3tl::toInt32(sURL.subView(sSlide.getLength()));
Reference<drawing::XDrawPagesSupplier> xDPS(rFilterBase.getModel(),
uno::UNO_QUERY_THROW);
Reference<drawing::XDrawPages> xDrawPages(xDPS->getDrawPages(),
uno::UNO_SET_THROW);
sal_Int32 nMaxPages = xDrawPages->getCount();
if (nPageNumber && nPageNumber <= nMaxPages)
{
Reference<XDrawPage> xDrawPage;
xDrawPages->getByIndex(nPageNumber - 1) >>= xDrawPage;
Reference<container::XNamed> xNamed(xDrawPage, UNO_QUERY);
sURL = xNamed->getName();
}
setBookmark(true);
// reuse slide number from '#Slide [Num]' or "#Notes [Num]"
sURL = OUString::Concat("#page") + sURL.subView(nSplitPos);
}
nPropertyCount += 1;
}

View file

@ -106,6 +106,51 @@ PresentationFragmentHandler::~PresentationFragmentHandler() noexcept
{
}
static void lcl_setBookmark(uno::Reference<drawing::XShape>& rShape,
std::vector<SlidePersistPtr>& rSlidePersist)
{
OUString aBookmark;
sal_Int32 nPageNumber;
static const OUStringLiteral sSlideName = u"#page";
uno::Reference<beans::XPropertySet> xPropSet(rShape, uno::UNO_QUERY);
xPropSet->getPropertyValue("Bookmark") >>= aBookmark;
nPageNumber = o3tl::toInt32(aBookmark.subView(sSlideName.getLength()));
Reference<XDrawPage> xDrawPage(rSlidePersist[nPageNumber - 1]->getPage());
Reference<container::XNamed> xNamed(xDrawPage, UNO_QUERY_THROW);
aBookmark = xNamed->getName();
xPropSet->setPropertyValue("Bookmark", Any(aBookmark));
}
static void ResolveShapeBookmark(std::vector<SlidePersistPtr>& rSlidePersist)
{
sal_Int32 nPageCount = rSlidePersist.size();
for (sal_Int32 nPage = 0; nPage < nPageCount; ++nPage)
{
if (!rSlidePersist[nPage]->getURLShapeId().empty())
{
auto aShapeMap = rSlidePersist[nPage]->getShapeMap();
sal_Int32 nCount = rSlidePersist[nPage]->getURLShapeId().size();
for (sal_Int32 i = 0; i < nCount; i++)
{
OUString sId = rSlidePersist[nPage]->getURLShapeId()[i];
uno::Reference<drawing::XShape> xShape(aShapeMap[sId]->getXShape(), uno::UNO_QUERY);
Reference<XShapes> xShapes(xShape, UNO_QUERY);
if (xShapes.is()) // group shape
{
for (sal_Int32 j = 0; j < xShapes->getCount(); j++)
{
uno::Reference<drawing::XShape> xGroupedShape(xShapes->getByIndex(j),
uno::UNO_QUERY);
lcl_setBookmark(xGroupedShape, rSlidePersist);
}
}
else
lcl_setBookmark(xShape, rSlidePersist);
}
}
}
}
static void ResolveTextFields( XmlFilterBase const & rFilter )
{
const oox::core::TextFieldStack& rTextFields = rFilter.getTextFieldStack();
@ -551,6 +596,7 @@ void PresentationFragmentHandler::finalizeImport()
nPagesImported++;
}
ResolveTextFields( rFilter );
ResolveShapeBookmark(rFilter.getDrawPages());
if (!maCustomShowList.empty())
importCustomSlideShow(maCustomShowList);
}

View file

@ -158,6 +158,8 @@ void SlidePersist::createXShapes( XmlFilterBase& rFilterBase )
maConnectorShapeId.push_back(pPPTShape->getChildren()[i]->getId());
}
}
if (pPPTShape->hasBookmark())
addURLShapeId(pPPTShape->getId());
}
else
child->addShape( rFilterBase, getTheme().get(), xShapes, aTransformation, maShapesPtr->getFillProperties(), &getShapeMap() );

Binary file not shown.

View file

@ -55,6 +55,8 @@
#include <com/sun/star/drawing/ConnectorType.hpp>
#include <stlpool.hxx>
#include <unotools/syslocaleoptions.hxx>
#include <comphelper/scopeguard.hxx>
#include <comphelper/sequenceashashmap.hxx>
#include <comphelper/lok.hxx>
#include <svx/svdograf.hxx>
@ -82,6 +84,7 @@ public:
void testDocumentLayout();
void testTdf149124();
void testTdf148965();
void testTdf89449();
void testTdf147459();
void testTdf146223();
@ -151,6 +154,7 @@ public:
CPPUNIT_TEST(testDocumentLayout);
CPPUNIT_TEST(testTdf149124);
CPPUNIT_TEST(testTdf148965);
CPPUNIT_TEST(testTdf89449);
CPPUNIT_TEST(testTdf147459);
CPPUNIT_TEST(testTdf146223);
@ -309,7 +313,40 @@ void SdImportTest::testTdf149124()
CPPUNIT_ASSERT_EQUAL(sal_Int32(2), nStartGlueId);
sal_Int32 nEndGlueId = xStandardConnector->getPropertyValue("EndGluePointIndex").get<sal_Int32>();
CPPUNIT_ASSERT_EQUAL(sal_Int32(0), nEndGlueId);
}
void SdImportTest::testTdf148965()
{
// Set the system user interface to Hungarian
SvtSysLocaleOptions aOptions;
OUString sUIConfigString = aOptions.GetLanguageTag().getBcp47();
aOptions.SetUILocaleConfigString("hu-HU");
aOptions.Commit();
comphelper::ScopeGuard g([&aOptions, &sUIConfigString] {
aOptions.SetUILocaleConfigString(sUIConfigString);
aOptions.Commit();
});
sd::DrawDocShellRef xDocShRef
= loadURL(m_directories.getURLFromSrc(u"sd/qa/unit/data/pptx/tdf148965.pptx"), PPTX);
uno::Reference<beans::XPropertySet> xShape1(getShapeFromPage(0, 1, xDocShRef));
uno::Reference<document::XEventsSupplier> xEventsSupplier1(xShape1, uno::UNO_QUERY);
uno::Reference<container::XNameAccess> xEvents1(xEventsSupplier1->getEvents());
uno::Sequence<beans::PropertyValue> props1;
xEvents1->getByName("OnClick") >>= props1;
comphelper::SequenceAsHashMap map1(props1);
auto iter1(map1.find("Bookmark"));
CPPUNIT_ASSERT_EQUAL(OUString("page1"), iter1->second.get<OUString>());
uno::Reference<beans::XPropertySet> xShape2(getShapeFromPage(1, 1, xDocShRef));
uno::Reference<document::XEventsSupplier> xEventsSupplier2(xShape2, uno::UNO_QUERY);
uno::Reference<container::XNameAccess> xEvents2(xEventsSupplier2->getEvents());
uno::Sequence<beans::PropertyValue> props2;
xEvents2->getByName("OnClick") >>= props2;
comphelper::SequenceAsHashMap map2(props2);
auto iter2(map2.find("Bookmark"));
CPPUNIT_ASSERT_EQUAL(OUString("page3"), iter2->second.get<OUString>());
xDocShRef->DoClose();
}