774 lines
33 KiB
C++
774 lines
33 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
/*
|
|
* This file is part of the LibreOffice project.
|
|
*
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
*
|
|
* This file incorporates work covered by the following license notice:
|
|
*
|
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
* contributor license agreements. See the NOTICE file distributed
|
|
* with this work for additional information regarding copyright
|
|
* ownership. The ASF licenses this file to you under the Apache
|
|
* License, Version 2.0 (the "License"); you may not use this file
|
|
* except in compliance with the License. You may obtain a copy of
|
|
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
|
|
*/
|
|
|
|
#include <oox/ppt/pptshape.hxx>
|
|
#include <oox/core/xmlfilterbase.hxx>
|
|
#include <drawingml/customshapeproperties.hxx>
|
|
#include <drawingml/textbody.hxx>
|
|
#include <drawingml/textparagraph.hxx>
|
|
#include <drawingml/textfield.hxx>
|
|
#include <editeng/flditem.hxx>
|
|
|
|
#include <com/sun/star/text/XTextField.hpp>
|
|
#include <com/sun/star/container/XNamed.hpp>
|
|
#include <com/sun/star/frame/XModel.hpp>
|
|
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
|
|
#include <com/sun/star/drawing/XDrawPage.hpp>
|
|
#include <com/sun/star/drawing/XDrawPages.hpp>
|
|
#include <com/sun/star/drawing/XDrawPagesSupplier.hpp>
|
|
#include <com/sun/star/drawing/XShapes.hpp>
|
|
#include <com/sun/star/text/XText.hpp>
|
|
#include <com/sun/star/document/XEventsSupplier.hpp>
|
|
#include <com/sun/star/container/XNameReplace.hpp>
|
|
#include <com/sun/star/presentation/ClickAction.hpp>
|
|
#include <basegfx/matrix/b2dhommatrix.hxx>
|
|
#include <sal/log.hxx>
|
|
#include <oox/ppt/slidepersist.hxx>
|
|
#include <oox/token/tokens.hxx>
|
|
#include <oox/token/properties.hxx>
|
|
#include <o3tl/string_view.hxx>
|
|
|
|
using namespace ::oox::core;
|
|
using namespace ::oox::drawingml;
|
|
using namespace ::com::sun::star;
|
|
using namespace ::com::sun::star::awt;
|
|
using namespace ::com::sun::star::uno;
|
|
using namespace ::com::sun::star::beans;
|
|
using namespace ::com::sun::star::text;
|
|
using namespace ::com::sun::star::drawing;
|
|
using namespace ::com::sun::star::document;
|
|
using namespace ::com::sun::star::container;
|
|
using namespace ::com::sun::star::presentation;
|
|
|
|
namespace oox::ppt {
|
|
|
|
PPTShape::PPTShape( const oox::ppt::ShapeLocation eShapeLocation, const OUString& rServiceName )
|
|
: Shape( rServiceName )
|
|
, meShapeLocation( eShapeLocation )
|
|
, mbReferenced( false )
|
|
, mbHasNoninheritedShapeProperties( false )
|
|
{
|
|
}
|
|
|
|
PPTShape::~PPTShape()
|
|
{
|
|
}
|
|
|
|
static const char* lclDebugSubType( sal_Int32 nType )
|
|
{
|
|
switch (nType) {
|
|
case XML_ctrTitle :
|
|
return "ctrTitle";
|
|
case XML_title :
|
|
return "title";
|
|
case XML_subTitle :
|
|
return "subTitle";
|
|
case XML_obj :
|
|
return "obj";
|
|
case XML_body :
|
|
return "body";
|
|
case XML_dt :
|
|
return "dt";
|
|
case XML_hdr :
|
|
return "hdr";
|
|
case XML_ftr :
|
|
return "frt";
|
|
case XML_sldNum :
|
|
return "sldNum";
|
|
case XML_sldImg :
|
|
return "sldImg";
|
|
}
|
|
|
|
return "unknown - please extend lclDebugSubType";
|
|
}
|
|
|
|
namespace
|
|
{
|
|
bool ShapeHasNoVisualPropertiesOnImport(const oox::ppt::PPTShape& rPPTShape)
|
|
{
|
|
return !rPPTShape.hasNonInheritedShapeProperties()
|
|
&& !rPPTShape.hasShapeStyleRefs()
|
|
&& !rPPTShape.getTextBody()->hasVisualRunProperties()
|
|
&& !rPPTShape.getTextBody()->hasNoninheritedBodyProperties()
|
|
&& !rPPTShape.getTextBody()->hasListStyleOnImport()
|
|
&& !rPPTShape.getTextBody()->hasParagraphProperties();
|
|
}
|
|
}
|
|
|
|
oox::drawingml::TextListStylePtr PPTShape::getSubTypeTextListStyle( const SlidePersist& rSlidePersist, sal_Int32 nSubType )
|
|
{
|
|
oox::drawingml::TextListStylePtr pTextListStyle;
|
|
|
|
SAL_INFO("oox.ppt", "subtype style: " << lclDebugSubType( nSubType ) );
|
|
|
|
switch( nSubType )
|
|
{
|
|
case XML_ctrTitle :
|
|
case XML_title :
|
|
pTextListStyle = rSlidePersist.getMasterPersist() ? rSlidePersist.getMasterPersist()->getTitleTextStyle() : rSlidePersist.getTitleTextStyle();
|
|
break;
|
|
case XML_subTitle :
|
|
case XML_obj :
|
|
case XML_body :
|
|
if ( rSlidePersist.isNotesPage() )
|
|
pTextListStyle = rSlidePersist.getMasterPersist() ? rSlidePersist.getMasterPersist()->getNotesTextStyle() : rSlidePersist.getNotesTextStyle();
|
|
else
|
|
pTextListStyle = rSlidePersist.getMasterPersist() ? rSlidePersist.getMasterPersist()->getBodyTextStyle() : rSlidePersist.getBodyTextStyle();
|
|
break;
|
|
}
|
|
|
|
return pTextListStyle;
|
|
}
|
|
|
|
bool PPTShape::IsPlaceHolderCandidate(const SlidePersist& rSlidePersist) const
|
|
{
|
|
if (meShapeLocation != Slide)
|
|
return false;
|
|
if (rSlidePersist.isNotesPage())
|
|
return false;
|
|
auto pTextBody = getTextBody();
|
|
if (!pTextBody)
|
|
return false;
|
|
auto rParagraphs = pTextBody->getParagraphs();
|
|
if (rParagraphs.size() != 1)
|
|
return false;
|
|
if (rParagraphs.front()->getRuns().size() != 1)
|
|
return false;
|
|
// If the placeholder has a shape other than rectangle,
|
|
// we have to place it in the slide as a CustomShape.
|
|
if (!mpCustomShapePropertiesPtr->representsDefaultShape())
|
|
return false;
|
|
return ShapeHasNoVisualPropertiesOnImport(*this);
|
|
}
|
|
|
|
void PPTShape::addShape(
|
|
oox::core::XmlFilterBase& rFilterBase,
|
|
const SlidePersist& rSlidePersist,
|
|
const oox::drawingml::Theme* pTheme,
|
|
const Reference< XShapes >& rxShapes,
|
|
basegfx::B2DHomMatrix& aTransformation,
|
|
::oox::drawingml::ShapeIdMap* pShapeMap )
|
|
{
|
|
SAL_INFO("oox.ppt","add shape id: " << msId << " location: " << ((meShapeLocation == Master) ? "master" : ((meShapeLocation == Slide) ? "slide" : ((meShapeLocation == Layout) ? "layout" : "other"))) << " subtype: " << mnSubType << " service: " << msServiceName);
|
|
// only placeholder from layout are being inserted
|
|
if ( mnSubType && ( meShapeLocation == Master ) )
|
|
return;
|
|
|
|
OUString sServiceName( msServiceName );
|
|
if (sServiceName.isEmpty())
|
|
return;
|
|
try
|
|
{
|
|
oox::drawingml::TextListStylePtr aMasterTextListStyle;
|
|
Reference<lang::XMultiServiceFactory> xServiceFact(rFilterBase.getModel(), UNO_QUERY_THROW);
|
|
bool bClearText = false;
|
|
|
|
if (sServiceName != "com.sun.star.drawing.GraphicObjectShape" &&
|
|
sServiceName != "com.sun.star.drawing.OLE2Shape")
|
|
{
|
|
static constexpr OUString sOutlinerShapeService(u"com.sun.star.presentation.OutlinerShape"_ustr);
|
|
SAL_INFO("oox.ppt","has master: " << std::hex << rSlidePersist.getMasterPersist().get());
|
|
switch (mnSubType)
|
|
{
|
|
case XML_ctrTitle :
|
|
case XML_title :
|
|
{
|
|
sServiceName = "com.sun.star.presentation.TitleTextShape";
|
|
aMasterTextListStyle = rSlidePersist.getMasterPersist() ? rSlidePersist.getMasterPersist()->getTitleTextStyle() : rSlidePersist.getTitleTextStyle();
|
|
}
|
|
break;
|
|
case XML_subTitle :
|
|
{
|
|
if ((meShapeLocation == Master) || (meShapeLocation == Layout))
|
|
sServiceName = OUString();
|
|
else {
|
|
sServiceName = "com.sun.star.presentation.SubtitleShape";
|
|
aMasterTextListStyle = rSlidePersist.getMasterPersist() ? rSlidePersist.getMasterPersist()->getBodyTextStyle() : rSlidePersist.getBodyTextStyle();
|
|
}
|
|
}
|
|
break;
|
|
case XML_obj :
|
|
{
|
|
sServiceName = sOutlinerShapeService;
|
|
if (getSubTypeIndex().has_value())
|
|
aMasterTextListStyle = rSlidePersist.getMasterPersist() ? rSlidePersist.getMasterPersist()->getBodyTextStyle() : rSlidePersist.getBodyTextStyle();
|
|
}
|
|
break;
|
|
case XML_body :
|
|
{
|
|
if (rSlidePersist.isNotesPage())
|
|
{
|
|
sServiceName = "com.sun.star.presentation.NotesShape";
|
|
aMasterTextListStyle = rSlidePersist.getMasterPersist() ? rSlidePersist.getMasterPersist()->getNotesTextStyle() : rSlidePersist.getNotesTextStyle();
|
|
}
|
|
else
|
|
{
|
|
sServiceName = sOutlinerShapeService;
|
|
aMasterTextListStyle = rSlidePersist.getMasterPersist() ? rSlidePersist.getMasterPersist()->getBodyTextStyle() : rSlidePersist.getBodyTextStyle();
|
|
}
|
|
}
|
|
break;
|
|
case XML_dt :
|
|
if (IsPlaceHolderCandidate(rSlidePersist))
|
|
{
|
|
TextRunPtr& pTextRun = getTextBody()->getParagraphs().front()->getRuns().front();
|
|
oox::drawingml::TextField* pTextField = dynamic_cast<oox::drawingml::TextField*>(pTextRun.get());
|
|
if (pTextField)
|
|
{
|
|
OUString aType = pTextField->getType();
|
|
if ( aType.startsWith("datetime") )
|
|
{
|
|
SvxDateFormat eDateFormat = drawingml::TextField::getLODateFormat(aType);
|
|
SvxTimeFormat eTimeFormat = drawingml::TextField::getLOTimeFormat(aType);
|
|
Reference< XPropertySet > xPropertySet( rSlidePersist.getPage(), UNO_QUERY );
|
|
|
|
if( eDateFormat != SvxDateFormat::AppDefault
|
|
|| eTimeFormat != SvxTimeFormat::AppDefault )
|
|
{
|
|
// DateTimeFormat property looks for the date in 4 LSBs
|
|
// and looks for time format in the 4 bits after that
|
|
sal_Int32 nDateTimeFormat = static_cast<sal_Int32>(eDateFormat) |
|
|
static_cast<sal_Int32>(eTimeFormat) << 4;
|
|
xPropertySet->setPropertyValue( u"IsDateTimeVisible"_ustr, Any(true) );
|
|
xPropertySet->setPropertyValue( u"IsDateTimeFixed"_ustr, Any(false) );
|
|
xPropertySet->setPropertyValue( u"DateTimeFormat"_ustr, Any(nDateTimeFormat) );
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
sServiceName = "com.sun.star.presentation.DateTimeShape";
|
|
bClearText = true;
|
|
break;
|
|
case XML_hdr :
|
|
sServiceName = "com.sun.star.presentation.HeaderShape";
|
|
bClearText = true;
|
|
break;
|
|
case XML_ftr :
|
|
if (IsPlaceHolderCandidate(rSlidePersist))
|
|
{
|
|
const OUString aFooterText = getTextBody()->toString();
|
|
|
|
if( !aFooterText.isEmpty() )
|
|
{
|
|
// if it is possible to get the footer as a property the LO way,
|
|
// get it and discard the shape
|
|
Reference< XPropertySet > xPropertySet( rSlidePersist.getPage(), UNO_QUERY );
|
|
xPropertySet->setPropertyValue( u"IsFooterVisible"_ustr, Any( true ) );
|
|
xPropertySet->setPropertyValue( u"FooterText"_ustr, Any(aFooterText) );
|
|
return;
|
|
}
|
|
}
|
|
sServiceName = "com.sun.star.presentation.FooterShape";
|
|
bClearText = true;
|
|
break;
|
|
case XML_sldNum :
|
|
if (IsPlaceHolderCandidate(rSlidePersist))
|
|
{
|
|
TextRunPtr& pTextRun
|
|
= getTextBody()->getParagraphs().front()->getRuns().front();
|
|
oox::drawingml::TextField* pTextField
|
|
= dynamic_cast<oox::drawingml::TextField*>(pTextRun.get());
|
|
if (pTextField && pTextField->getType() == "slidenum")
|
|
{
|
|
// if it is possible to get the slidenum placeholder as a property
|
|
// do that and discard the shape
|
|
Reference<XPropertySet> xPropertySet(rSlidePersist.getPage(),
|
|
UNO_QUERY);
|
|
xPropertySet->setPropertyValue(u"IsPageNumberVisible"_ustr, Any(true));
|
|
return;
|
|
}
|
|
}
|
|
sServiceName = "com.sun.star.presentation.SlideNumberShape";
|
|
bClearText = true;
|
|
break;
|
|
case XML_sldImg :
|
|
sServiceName = "com.sun.star.presentation.PageShape";
|
|
break;
|
|
case XML_chart :
|
|
if (meShapeLocation == Layout)
|
|
sServiceName = sOutlinerShapeService;
|
|
else
|
|
sServiceName = "com.sun.star.presentation.ChartShape";
|
|
break;
|
|
case XML_tbl :
|
|
if (meShapeLocation == Layout)
|
|
sServiceName = sOutlinerShapeService;
|
|
else
|
|
sServiceName = "com.sun.star.presentation.TableShape";
|
|
break;
|
|
case XML_pic :
|
|
if (meShapeLocation == Layout)
|
|
sServiceName = sOutlinerShapeService;
|
|
else
|
|
sServiceName = "com.sun.star.presentation.GraphicObjectShape";
|
|
break;
|
|
case XML_media :
|
|
if (meShapeLocation == Layout)
|
|
sServiceName = sOutlinerShapeService;
|
|
else
|
|
sServiceName = "com.sun.star.presentation.MediaShape";
|
|
break;
|
|
default:
|
|
if (mnSubType && meShapeLocation == Layout)
|
|
sServiceName = sOutlinerShapeService;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Since it is not possible to represent custom shaped placeholders in Impress
|
|
// Need to use service name css.drawing.CustomShape if they have a non default shape.
|
|
// This workaround has the drawback of them not really being processed as placeholders
|
|
// so it is done for slide footers and obj placeholder
|
|
bool convertInSlideMode
|
|
= meShapeLocation == Slide
|
|
&& (mnSubType == XML_sldNum || mnSubType == XML_dt || mnSubType == XML_ftr
|
|
|| mnSubType == XML_body
|
|
|| (mnSubType == XML_obj
|
|
&& sServiceName != "com.sun.star.drawing.GraphicObjectShape"));
|
|
|
|
bool convertInLayoutMode = meShapeLocation == Layout && (mnSubType == XML_body);
|
|
if ((convertInSlideMode || convertInLayoutMode) && !mpCustomShapePropertiesPtr->representsDefaultShape())
|
|
{
|
|
sServiceName = "com.sun.star.drawing.CustomShape";
|
|
}
|
|
|
|
SAL_INFO("oox.ppt","shape service: " << sServiceName);
|
|
|
|
if (mnSubType && getSubTypeIndex().has_value() && meShapeLocation == Layout)
|
|
{
|
|
oox::drawingml::ShapePtr pPlaceholder = PPTShape::findPlaceholderByIndex( getSubTypeIndex().value(), rSlidePersist.getShapes()->getChildren(), true );
|
|
if (!pPlaceholder)
|
|
pPlaceholder = PPTShape::findPlaceholder( mnSubType, 0, getSubTypeIndex(), rSlidePersist.getShapes()->getChildren(), true );
|
|
|
|
if (pPlaceholder) {
|
|
if (maSize.Width == 0 || maSize.Height == 0) {
|
|
awt::Size aSize = maSize;
|
|
if (maSize.Width == 0)
|
|
aSize.Width = pPlaceholder->getSize().Width;
|
|
if (maSize.Height == 0)
|
|
aSize.Height = pPlaceholder->getSize().Height;
|
|
setSize( aSize );
|
|
if (maPosition.X == 0 || maPosition.Y == 0) {
|
|
awt::Point aPosition = maPosition;
|
|
if (maPosition.X == 0)
|
|
aPosition.X = pPlaceholder->getPosition().X;
|
|
if (maPosition.Y == 0)
|
|
aPosition.Y = pPlaceholder->getPosition().Y;
|
|
setPosition( aPosition );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// use placeholder index if possible
|
|
if (mnSubType && getSubTypeIndex().has_value() && rSlidePersist.getMasterPersist())
|
|
{
|
|
oox::drawingml::ShapePtr pPlaceholder = PPTShape::findPlaceholderByIndex(getSubTypeIndex().value(), rSlidePersist.getMasterPersist()->getShapes()->getChildren());
|
|
// TODO: Check if this is required for non-notes slides as well...
|
|
if (rSlidePersist.isNotesPage() && pPlaceholder && pPlaceholder->getSubType() != getSubType())
|
|
pPlaceholder.reset();
|
|
|
|
if (pPlaceholder) {
|
|
SAL_INFO("oox.ppt","found placeholder with index: " << getSubTypeIndex().value() << " and type: " << lclDebugSubType( mnSubType ));
|
|
PPTShape* pPPTPlaceholder = dynamic_cast< PPTShape* >( pPlaceholder.get() );
|
|
TextListStylePtr pNewTextListStyle = std::make_shared<TextListStyle>();
|
|
|
|
if (pPlaceholder->getTextBody()) {
|
|
|
|
pNewTextListStyle->apply( pPlaceholder->getTextBody()->getTextListStyle() );
|
|
if (pPlaceholder->getMasterTextListStyle())
|
|
pNewTextListStyle->apply( *pPlaceholder->getMasterTextListStyle() );
|
|
|
|
// SAL_INFO("oox.ppt","placeholder body style");
|
|
// pPlaceholder->getTextBody()->getTextListStyle().dump();
|
|
// SAL_INFO("oox.ppt","master text list style");
|
|
// pPlaceholder->getMasterTextListStyle()->dump();
|
|
|
|
aMasterTextListStyle = pNewTextListStyle;
|
|
// SAL_INFO("oox.ppt","combined master text list style");
|
|
// aMasterTextListStyle->dump();
|
|
}
|
|
if (pPPTPlaceholder && pPPTPlaceholder->mpPlaceholder) {
|
|
SAL_INFO("oox.ppt","placeholder has parent placeholder: " << pPPTPlaceholder->mpPlaceholder->getId() << " type: " << lclDebugSubType( pPPTPlaceholder->mpPlaceholder->getSubType() ) << " index: " << pPPTPlaceholder->mpPlaceholder->getSubTypeIndex().value() );
|
|
SAL_INFO("oox.ppt","has textbody " << (pPPTPlaceholder->mpPlaceholder->getTextBody() != nullptr) );
|
|
TextListStylePtr pPlaceholderStyle = getSubTypeTextListStyle( rSlidePersist, pPPTPlaceholder->mpPlaceholder->getSubType() );
|
|
if (pPPTPlaceholder->mpPlaceholder->getTextBody())
|
|
pNewTextListStyle->apply( pPPTPlaceholder->mpPlaceholder->getTextBody()->getTextListStyle() );
|
|
if (pPlaceholderStyle) {
|
|
pNewTextListStyle->apply( *pPlaceholderStyle );
|
|
//pPlaceholderStyle->dump();
|
|
}
|
|
}
|
|
} else if (!mpPlaceholder) {
|
|
aMasterTextListStyle.reset();
|
|
}
|
|
SAL_INFO("oox.ppt","placeholder id: " << (pPlaceholder ? pPlaceholder->getId() : u"not found"_ustr));
|
|
}
|
|
|
|
if (!sServiceName.isEmpty())
|
|
{
|
|
if (!aMasterTextListStyle)
|
|
{
|
|
bool isOther = !getTextBody() && sServiceName != "com.sun.star.drawing.GroupShape";
|
|
TextListStylePtr aSlideStyle = isOther ? rSlidePersist.getOtherTextStyle() : rSlidePersist.getDefaultTextStyle();
|
|
// Combine from MasterSlide details as well.
|
|
if (rSlidePersist.getMasterPersist())
|
|
{
|
|
aMasterTextListStyle = isOther ? rSlidePersist.getMasterPersist()->getOtherTextStyle() : rSlidePersist.getMasterPersist()->getDefaultTextStyle();
|
|
if (aSlideStyle)
|
|
aMasterTextListStyle->apply( *aSlideStyle );
|
|
}
|
|
else
|
|
{
|
|
aMasterTextListStyle = std::move(aSlideStyle);
|
|
}
|
|
}
|
|
|
|
if( aMasterTextListStyle && getTextBody() ) {
|
|
TextListStylePtr aCombinedTextListStyle = std::make_shared<TextListStyle>();
|
|
|
|
aCombinedTextListStyle->apply( *aMasterTextListStyle );
|
|
|
|
if( mpPlaceholder && mpPlaceholder->getTextBody() )
|
|
aCombinedTextListStyle->apply( mpPlaceholder->getTextBody()->getTextListStyle() );
|
|
aCombinedTextListStyle->apply( getTextBody()->getTextListStyle() );
|
|
|
|
setMasterTextListStyle( aCombinedTextListStyle );
|
|
} else
|
|
setMasterTextListStyle( aMasterTextListStyle );
|
|
|
|
Reference< XShape > xShape( createAndInsert( rFilterBase, sServiceName, pTheme, rxShapes, bClearText, bool(mpPlaceholder), aTransformation, getFillProperties() ) );
|
|
|
|
// Apply text properties on placeholder text inside this placeholder shape
|
|
if (meShapeLocation == Slide && mpPlaceholder && getTextBody() && getTextBody()->isEmpty())
|
|
{
|
|
Reference < XText > xText(mxShape, UNO_QUERY);
|
|
if (xText.is())
|
|
{
|
|
TextCharacterProperties aCharStyleProperties;
|
|
getTextBody()->ApplyStyleEmpty(rFilterBase, xText, aCharStyleProperties, mpMasterTextListStyle);
|
|
}
|
|
}
|
|
if (pShapeMap)
|
|
{
|
|
// bnc#705982 - if optional model id reference is
|
|
// there, use that to obtain target shape
|
|
if (!msModelId.isEmpty())
|
|
{
|
|
(*pShapeMap)[ msModelId ] = shared_from_this();
|
|
}
|
|
else if (!msId.isEmpty())
|
|
{
|
|
(*pShapeMap)[ msId ] = shared_from_this();
|
|
}
|
|
}
|
|
|
|
// we will be losing whatever information there is in the footer placeholder on master/layout slides
|
|
// since they should have the "<footer>" textfield in them in order to make LibreOffice process them as expected
|
|
// likewise DateTime placeholder data on master/layout slides will be lost and replaced
|
|
if( (mnSubType == XML_ftr || mnSubType == XML_dt) && meShapeLocation != Slide )
|
|
{
|
|
OUString aFieldType;
|
|
if( mnSubType == XML_ftr )
|
|
aFieldType = "com.sun.star.presentation.TextField.Footer";
|
|
else
|
|
aFieldType = "com.sun.star.presentation.TextField.DateTime";
|
|
Reference < XTextField > xField( xServiceFact->createInstance( aFieldType ), UNO_QUERY );
|
|
Reference < XText > xText(mxShape, UNO_QUERY);
|
|
if(xText.is())
|
|
{
|
|
xText->setString(u""_ustr);
|
|
Reference < XTextCursor > xTextCursor = xText->createTextCursor();
|
|
xText->insertTextContent( xTextCursor, xField, false);
|
|
}
|
|
}
|
|
|
|
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())
|
|
{
|
|
// temporarily remember setting
|
|
NamedShapePairs* pDiagramFontHeights(rFilterBase.getDiagramFontHeights());
|
|
|
|
// for shapes unequal to FRAMETYPE_DIAGRAM do
|
|
// disable DiagramFontHeights recording
|
|
if (meFrameType != FRAMETYPE_DIAGRAM)
|
|
rFilterBase.setDiagramFontHeights(nullptr);
|
|
|
|
addChildren( rFilterBase, *this, pTheme, xShapes, pShapeMap, aTransformation );
|
|
|
|
// restore remembered setting
|
|
rFilterBase.setDiagramFontHeights(pDiagramFontHeights);
|
|
|
|
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)
|
|
{
|
|
keepDiagramCompatibilityInfo();
|
|
}
|
|
|
|
// Support advanced DiagramHelper
|
|
if (FRAMETYPE_DIAGRAM == meFrameType)
|
|
{
|
|
propagateDiagramHelper();
|
|
}
|
|
|
|
getShapeProperties().getProperty(PROP_URL) >>= sURL;
|
|
if (!sURL.isEmpty() && !xShapes.is())
|
|
aURLShapes.push_back({ sURL, xShape });
|
|
|
|
if (!aURLShapes.empty())
|
|
{
|
|
for (auto const& URLShape : aURLShapes)
|
|
{
|
|
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 = OUString::Concat("page")
|
|
+ sURL.subView(sURL.lastIndexOf(' ') + 1);
|
|
}
|
|
nPropertyCount += 1;
|
|
}
|
|
|
|
aProperties.realloc(nPropertyCount);
|
|
beans::PropertyValue* pProperties = aProperties.getArray();
|
|
|
|
pProperties->Name = "EventType";
|
|
pProperties->Handle = -1;
|
|
pProperties->Value <<= u"Presentation"_ustr;
|
|
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;
|
|
}
|
|
|
|
sAPIEventName = "OnClick";
|
|
xEvents->replaceByName(sAPIEventName, uno::Any(aProperties));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch (const Exception&)
|
|
{
|
|
}
|
|
}
|
|
|
|
namespace
|
|
{
|
|
bool ShapeLocationIsMaster(oox::drawingml::Shape *pInShape)
|
|
{
|
|
PPTShape* pShape = dynamic_cast<PPTShape*>(pInShape);
|
|
return pShape && pShape->getShapeLocation() == Master;
|
|
}
|
|
}
|
|
|
|
// Function to find placeholder (ph) for a shape. No idea how MSO implements this, but
|
|
// this order seems to work quite well
|
|
// (probably it's unnecessary complicated / wrong. i.e. tdf#104202):
|
|
// 1. ph with nFirstSubType and the same oSubTypeIndex
|
|
// 2. ph with nFirstSubType
|
|
// 3. ph with nSecondSubType and the same oSubTypeIndex
|
|
// 4. ph with nSecondSubType
|
|
// 5. ph with the same oSubTypeIndex
|
|
|
|
oox::drawingml::ShapePtr PPTShape::findPlaceholder( sal_Int32 nFirstSubType, sal_Int32 nSecondSubType,
|
|
const std::optional< sal_Int32 >& oSubTypeIndex, std::vector< oox::drawingml::ShapePtr >& rShapes, bool bMasterOnly )
|
|
{
|
|
class Placeholders
|
|
{
|
|
public:
|
|
Placeholders()
|
|
: aChoice(5) // resize to 5
|
|
{
|
|
}
|
|
|
|
void add(const oox::drawingml::ShapePtr& aShape, sal_Int32 nFirstSubType, sal_Int32 nSecondSubType, const std::optional< sal_Int32 >& oSubTypeIndex)
|
|
{
|
|
if (!aShape)
|
|
return;
|
|
|
|
// get flags
|
|
const bool bSameFirstSubType = aShape->getSubType() == nFirstSubType;
|
|
const bool bSameSecondSubType = aShape->getSubType() == nSecondSubType;
|
|
const bool bSameIndex = aShape->getSubTypeIndex() == oSubTypeIndex;
|
|
|
|
// get prio
|
|
int aPrioIndex = -1;
|
|
if (bSameIndex && bSameFirstSubType)
|
|
aPrioIndex = 0;
|
|
else if (!bSameIndex && bSameFirstSubType)
|
|
aPrioIndex = 1;
|
|
else if (bSameIndex && bSameSecondSubType)
|
|
aPrioIndex = 2;
|
|
else if (!bSameIndex && bSameSecondSubType)
|
|
aPrioIndex = 3;
|
|
else if (bSameIndex)
|
|
aPrioIndex = 4;
|
|
|
|
// add
|
|
if (aPrioIndex != -1)
|
|
{
|
|
if (!aChoice.at(aPrioIndex))
|
|
{
|
|
aChoice.at(aPrioIndex) = aShape;
|
|
}
|
|
}
|
|
}
|
|
|
|
// return according to prio
|
|
oox::drawingml::ShapePtr getByPrio() const
|
|
{
|
|
for (const oox::drawingml::ShapePtr& aShape : aChoice)
|
|
{
|
|
if (aShape)
|
|
{
|
|
return aShape;
|
|
}
|
|
}
|
|
|
|
return oox::drawingml::ShapePtr();
|
|
}
|
|
|
|
bool hasByPrio(size_t aIndex) const
|
|
{
|
|
return bool(aChoice.at(aIndex));
|
|
}
|
|
|
|
private:
|
|
std::vector< oox::drawingml::ShapePtr > aChoice;
|
|
|
|
} aPlaceholders;
|
|
|
|
// check all shapes
|
|
std::vector< oox::drawingml::ShapePtr >::reverse_iterator aRevIter( rShapes.rbegin() );
|
|
for (; aRevIter != rShapes.rend(); ++aRevIter)
|
|
{
|
|
// check shape
|
|
if (!bMasterOnly || ShapeLocationIsMaster((*aRevIter).get()))
|
|
{
|
|
const oox::drawingml::ShapePtr& aShape = *aRevIter;
|
|
aPlaceholders.add(aShape, nFirstSubType, nSecondSubType, oSubTypeIndex);
|
|
}
|
|
|
|
// check children
|
|
std::vector< oox::drawingml::ShapePtr >& rChildren = (*aRevIter)->getChildren();
|
|
if (!rChildren.empty())
|
|
{
|
|
const oox::drawingml::ShapePtr aShape = findPlaceholder( nFirstSubType, nSecondSubType, oSubTypeIndex, rChildren, bMasterOnly );
|
|
if (aShape)
|
|
{
|
|
aPlaceholders.add(aShape, nFirstSubType, nSecondSubType, oSubTypeIndex);
|
|
}
|
|
}
|
|
|
|
if (aPlaceholders.hasByPrio(0))
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
// return something according to prio
|
|
return aPlaceholders.getByPrio();
|
|
}
|
|
|
|
oox::drawingml::ShapePtr PPTShape::findPlaceholderByIndex( const sal_Int32 nIdx, std::vector< oox::drawingml::ShapePtr >& rShapes, bool bMasterOnly )
|
|
{
|
|
oox::drawingml::ShapePtr aShapePtr;
|
|
|
|
std::vector< oox::drawingml::ShapePtr >::reverse_iterator aRevIter( rShapes.rbegin() );
|
|
while( aRevIter != rShapes.rend() )
|
|
{
|
|
if ( (*aRevIter)->getSubTypeIndex().has_value() && (*aRevIter)->getSubTypeIndex().value() == nIdx &&
|
|
( !bMasterOnly || ShapeLocationIsMaster((*aRevIter).get()) ) )
|
|
{
|
|
aShapePtr = *aRevIter;
|
|
break;
|
|
}
|
|
std::vector< oox::drawingml::ShapePtr >& rChildren = (*aRevIter)->getChildren();
|
|
aShapePtr = findPlaceholderByIndex( nIdx, rChildren, bMasterOnly );
|
|
if ( aShapePtr )
|
|
break;
|
|
++aRevIter;
|
|
}
|
|
return aShapePtr;
|
|
}
|
|
|
|
}
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|