LibreOffice Module oox (master)  1
pptshape.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  * Licensed to the Apache Software Foundation (ASF) under one or more
12  * contributor license agreements. See the NOTICE file distributed
13  * with this work for additional information regarding copyright
14  * ownership. The ASF licenses this file to you under the Apache
15  * License, Version 2.0 (the "License"); you may not use this file
16  * except in compliance with the License. You may obtain a copy of
17  * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #include <oox/ppt/pptshape.hxx>
22 #include <drawingml/textbody.hxx>
24 #include <drawingml/textfield.hxx>
26 #include <editeng/flditem.hxx>
27 
28 #include <com/sun/star/text/XTextField.hpp>
29 #include <com/sun/star/container/XNamed.hpp>
30 #include <com/sun/star/frame/XModel.hpp>
31 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
32 #include <com/sun/star/drawing/XDrawPage.hpp>
33 #include <com/sun/star/drawing/XDrawPages.hpp>
34 #include <com/sun/star/drawing/XDrawPagesSupplier.hpp>
35 #include <com/sun/star/drawing/XShapes.hpp>
36 #include <com/sun/star/text/XText.hpp>
37 #include <com/sun/star/document/XEventsSupplier.hpp>
38 #include <com/sun/star/container/XNameReplace.hpp>
39 #include <com/sun/star/presentation/ClickAction.hpp>
41 #include <sal/log.hxx>
42 #include <oox/ppt/slidepersist.hxx>
43 #include <oox/token/tokens.hxx>
44 #include <oox/token/properties.hxx>
45 
46 using namespace ::oox::core;
47 using namespace ::oox::drawingml;
48 using namespace ::com::sun::star;
49 using namespace ::com::sun::star::awt;
50 using namespace ::com::sun::star::uno;
51 using namespace ::com::sun::star::beans;
52 using namespace ::com::sun::star::text;
53 using namespace ::com::sun::star::drawing;
54 using namespace ::com::sun::star::document;
55 using namespace ::com::sun::star::container;
56 using namespace ::com::sun::star::presentation;
57 
58 namespace oox::ppt {
59 
60 PPTShape::PPTShape( const oox::ppt::ShapeLocation eShapeLocation, const char* pServiceName )
61 : Shape( pServiceName )
62 , meShapeLocation( eShapeLocation )
63 , mbReferenced( false )
64 , mbHasNoninheritedShapeProperties( false )
65 {
66 }
67 
69 {
70 }
71 
72 static const char* lclDebugSubType( sal_Int32 nType )
73 {
74  switch (nType) {
75  case XML_ctrTitle :
76  return "ctrTitle";
77  case XML_title :
78  return "title";
79  case XML_subTitle :
80  return "subTitle";
81  case XML_obj :
82  return "obj";
83  case XML_body :
84  return "body";
85  case XML_dt :
86  return "dt";
87  case XML_hdr :
88  return "hdr";
89  case XML_ftr :
90  return "frt";
91  case XML_sldNum :
92  return "sldNum";
93  case XML_sldImg :
94  return "sldImg";
95  }
96 
97  return "unknown - please extend lclDebugSubType";
98 }
99 
100 namespace
101 {
102 bool ShapeHasNoVisualPropertiesOnImport(const oox::ppt::PPTShape& rPPTShape)
103 {
104  return !rPPTShape.hasNonInheritedShapeProperties()
105  && !rPPTShape.hasShapeStyleRefs()
106  && !rPPTShape.getTextBody()->hasVisualRunProperties()
107  && !rPPTShape.getTextBody()->hasNoninheritedBodyProperties()
108  && !rPPTShape.getTextBody()->hasListStyleOnImport()
109  && !rPPTShape.getTextBody()->hasParagraphProperties();
110 }
111 }
112 
114 {
115  oox::drawingml::TextListStylePtr pTextListStyle;
116 
117  SAL_INFO("oox.ppt", "subtype style: " << lclDebugSubType( nSubType ) );
118 
119  switch( nSubType )
120  {
121  case XML_ctrTitle :
122  case XML_title :
123  pTextListStyle = rSlidePersist.getMasterPersist() ? rSlidePersist.getMasterPersist()->getTitleTextStyle() : rSlidePersist.getTitleTextStyle();
124  break;
125  case XML_subTitle :
126  case XML_obj :
127  case XML_body :
128  if ( rSlidePersist.isNotesPage() )
129  pTextListStyle = rSlidePersist.getMasterPersist() ? rSlidePersist.getMasterPersist()->getNotesTextStyle() : rSlidePersist.getNotesTextStyle();
130  else
131  pTextListStyle = rSlidePersist.getMasterPersist() ? rSlidePersist.getMasterPersist()->getBodyTextStyle() : rSlidePersist.getBodyTextStyle();
132  break;
133  }
134 
135  return pTextListStyle;
136 }
137 
138 bool PPTShape::IsPlaceHolderCandidate(const SlidePersist& rSlidePersist) const
139 {
140  if (meShapeLocation != Slide)
141  return false;
142  if (rSlidePersist.isNotesPage())
143  return false;
144  auto pTextBody = getTextBody();
145  if (!pTextBody)
146  return false;
147  auto rParagraphs = pTextBody->getParagraphs();
148  if (rParagraphs.size() != 1)
149  return false;
150  if (rParagraphs.front()->getRuns().size() != 1)
151  return false;
152  return ShapeHasNoVisualPropertiesOnImport(*this);
153 }
154 
156  oox::core::XmlFilterBase& rFilterBase,
157  const SlidePersist& rSlidePersist,
158  const oox::drawingml::Theme* pTheme,
159  const Reference< XShapes >& rxShapes,
160  basegfx::B2DHomMatrix& aTransformation,
161  ::oox::drawingml::ShapeIdMap* pShapeMap )
162 {
163  SAL_INFO("oox.ppt","add shape id: " << msId << " location: " << ((meShapeLocation == Master) ? "master" : ((meShapeLocation == Slide) ? "slide" : ((meShapeLocation == Layout) ? "layout" : "other"))) << " subtype: " << mnSubType << " service: " << msServiceName);
164  // only placeholder from layout are being inserted
165  if ( mnSubType && ( meShapeLocation == Master ) )
166  return;
167 
168  OUString sServiceName( msServiceName );
169  if (sServiceName.isEmpty())
170  return;
171  try
172  {
173  oox::drawingml::TextListStylePtr aMasterTextListStyle;
174  Reference<lang::XMultiServiceFactory> xServiceFact(rFilterBase.getModel(), UNO_QUERY_THROW);
175  bool bClearText = false;
176 
177  if (sServiceName != "com.sun.star.drawing.GraphicObjectShape" &&
178  sServiceName != "com.sun.star.drawing.OLE2Shape")
179  {
180  static const OUStringLiteral sOutlinerShapeService(u"com.sun.star.presentation.OutlinerShape");
181  SAL_INFO("oox.ppt","has master: " << std::hex << rSlidePersist.getMasterPersist().get());
182  switch (mnSubType)
183  {
184  case XML_ctrTitle :
185  case XML_title :
186  {
187  sServiceName = "com.sun.star.presentation.TitleTextShape";
188  aMasterTextListStyle = rSlidePersist.getMasterPersist() ? rSlidePersist.getMasterPersist()->getTitleTextStyle() : rSlidePersist.getTitleTextStyle();
189  }
190  break;
191  case XML_subTitle :
192  {
193  if ((meShapeLocation == Master) || (meShapeLocation == Layout))
194  sServiceName = OUString();
195  else {
196  sServiceName = "com.sun.star.presentation.SubtitleShape";
197  aMasterTextListStyle = rSlidePersist.getMasterPersist() ? rSlidePersist.getMasterPersist()->getBodyTextStyle() : rSlidePersist.getBodyTextStyle();
198  }
199  }
200  break;
201  case XML_obj :
202  {
203  sServiceName = sOutlinerShapeService;
204  aMasterTextListStyle = rSlidePersist.getMasterPersist() ? rSlidePersist.getMasterPersist()->getBodyTextStyle() : rSlidePersist.getBodyTextStyle();
205  }
206  break;
207  case XML_body :
208  {
209  if (rSlidePersist.isNotesPage())
210  {
211  sServiceName = "com.sun.star.presentation.NotesShape";
212  aMasterTextListStyle = rSlidePersist.getMasterPersist() ? rSlidePersist.getMasterPersist()->getNotesTextStyle() : rSlidePersist.getNotesTextStyle();
213  }
214  else
215  {
216  sServiceName = sOutlinerShapeService;
217  aMasterTextListStyle = rSlidePersist.getMasterPersist() ? rSlidePersist.getMasterPersist()->getBodyTextStyle() : rSlidePersist.getBodyTextStyle();
218  }
219  }
220  break;
221  case XML_dt :
222  if (IsPlaceHolderCandidate(rSlidePersist))
223  {
224  TextRunPtr& pTextRun = getTextBody()->getParagraphs().front()->getRuns().front();
225  oox::drawingml::TextField* pTextField = dynamic_cast<oox::drawingml::TextField*>(pTextRun.get());
226  if (pTextField)
227  {
228  OUString aType = pTextField->getType();
229  if ( aType.startsWith("datetime") )
230  {
233  Reference< XPropertySet > xPropertySet( rSlidePersist.getPage(), UNO_QUERY );
234 
235  if( eDateFormat != SvxDateFormat::AppDefault
236  || eTimeFormat != SvxTimeFormat::AppDefault )
237  {
238  // DateTimeFormat property looks for the date in 4 LSBs
239  // and looks for time format in the 4 bits after that
240  sal_Int32 nDateTimeFormat = static_cast<sal_Int32>(eDateFormat) |
241  static_cast<sal_Int32>(eTimeFormat) << 4;
242  xPropertySet->setPropertyValue( "IsDateTimeVisible", Any(true) );
243  xPropertySet->setPropertyValue( "IsDateTimeFixed", Any(false) );
244  xPropertySet->setPropertyValue( "DateTimeFormat", Any(nDateTimeFormat) );
245  return;
246  }
247  }
248  }
249  }
250  sServiceName = "com.sun.star.presentation.DateTimeShape";
251  bClearText = true;
252  break;
253  case XML_hdr :
254  sServiceName = "com.sun.star.presentation.HeaderShape";
255  bClearText = true;
256  break;
257  case XML_ftr :
258  if (IsPlaceHolderCandidate(rSlidePersist))
259  {
260  const OUString& rFooterText = getTextBody()->toString();
261 
262  if( !rFooterText.isEmpty() )
263  {
264  // if it is possible to get the footer as a property the LO way,
265  // get it and discard the shape
266  Reference< XPropertySet > xPropertySet( rSlidePersist.getPage(), UNO_QUERY );
267  xPropertySet->setPropertyValue( "IsFooterVisible", Any( true ) );
268  xPropertySet->setPropertyValue( "FooterText", Any(rFooterText) );
269  return;
270  }
271  }
272  sServiceName = "com.sun.star.presentation.FooterShape";
273  bClearText = true;
274  break;
275  case XML_sldNum :
276  if (IsPlaceHolderCandidate(rSlidePersist))
277  {
278  TextRunPtr& pTextRun
279  = getTextBody()->getParagraphs().front()->getRuns().front();
280  oox::drawingml::TextField* pTextField
281  = dynamic_cast<oox::drawingml::TextField*>(pTextRun.get());
282  if (pTextField && pTextField->getType() == "slidenum")
283  {
284  // if it is possible to get the slidenum placeholder as a property
285  // do that and discard the shape
286  Reference<XPropertySet> xPropertySet(rSlidePersist.getPage(),
287  UNO_QUERY);
288  xPropertySet->setPropertyValue("IsPageNumberVisible", Any(true));
289  return;
290  }
291  }
292  sServiceName = "com.sun.star.presentation.SlideNumberShape";
293  bClearText = true;
294  break;
295  case XML_sldImg :
296  sServiceName = "com.sun.star.presentation.PageShape";
297  break;
298  case XML_chart :
299  if (meShapeLocation == Layout)
300  sServiceName = sOutlinerShapeService;
301  else
302  sServiceName = "com.sun.star.presentation.ChartShape";
303  break;
304  case XML_tbl :
305  if (meShapeLocation == Layout)
306  sServiceName = sOutlinerShapeService;
307  else
308  sServiceName = "com.sun.star.presentation.TableShape";
309  break;
310  case XML_pic :
311  if (meShapeLocation == Layout)
312  sServiceName = sOutlinerShapeService;
313  else
314  sServiceName = "com.sun.star.presentation.GraphicObjectShape";
315  break;
316  case XML_media :
317  if (meShapeLocation == Layout)
318  sServiceName = sOutlinerShapeService;
319  else
320  sServiceName = "com.sun.star.presentation.MediaShape";
321  break;
322  default:
323  if (mnSubType && meShapeLocation == Layout)
324  sServiceName = sOutlinerShapeService;
325  break;
326  }
327  }
328 
329  SAL_INFO("oox.ppt","shape service: " << sServiceName);
330 
331  if (mnSubType && getSubTypeIndex().has() && meShapeLocation == Layout)
332  {
333  oox::drawingml::ShapePtr pPlaceholder = PPTShape::findPlaceholderByIndex( getSubTypeIndex().get(), rSlidePersist.getShapes()->getChildren(), true );
334  if (!pPlaceholder)
335  pPlaceholder = PPTShape::findPlaceholder( mnSubType, 0, getSubTypeIndex(), rSlidePersist.getShapes()->getChildren(), true );
336 
337  if (pPlaceholder) {
338  if (maSize.Width == 0 || maSize.Height == 0) {
339  awt::Size aSize = maSize;
340  if (maSize.Width == 0)
341  aSize.Width = pPlaceholder->getSize().Width;
342  if (maSize.Height == 0)
343  aSize.Height = pPlaceholder->getSize().Height;
344  setSize( aSize );
345  if (maPosition.X == 0 || maPosition.Y == 0) {
346  awt::Point aPosition = maPosition;
347  if (maPosition.X == 0)
348  aPosition.X = pPlaceholder->getPosition().X;
349  if (maPosition.Y == 0)
350  aPosition.Y = pPlaceholder->getPosition().Y;
351  setPosition( aPosition );
352  }
353  }
354  }
355  }
356 
357  // use placeholder index if possible
358  if (mnSubType && getSubTypeIndex().has() && rSlidePersist.getMasterPersist())
359  {
360  oox::drawingml::ShapePtr pPlaceholder = PPTShape::findPlaceholderByIndex(getSubTypeIndex().get(), rSlidePersist.getMasterPersist()->getShapes()->getChildren());
361  // TODO: Check if this is required for non-notes slides as well...
362  if (rSlidePersist.isNotesPage() && pPlaceholder && pPlaceholder->getSubType() != getSubType())
363  pPlaceholder.reset();
364 
365  if (pPlaceholder) {
366  SAL_INFO("oox.ppt","found placeholder with index: " << getSubTypeIndex().get() << " and type: " << lclDebugSubType( mnSubType ));
367  PPTShape* pPPTPlaceholder = dynamic_cast< PPTShape* >( pPlaceholder.get() );
368  TextListStylePtr pNewTextListStyle = std::make_shared<TextListStyle>();
369 
370  if (pPlaceholder->getTextBody()) {
371 
372  pNewTextListStyle->apply( pPlaceholder->getTextBody()->getTextListStyle() );
373  if (pPlaceholder->getMasterTextListStyle())
374  pNewTextListStyle->apply( *pPlaceholder->getMasterTextListStyle() );
375 
376  // SAL_INFO("oox.ppt","placeholder body style");
377  // pPlaceholder->getTextBody()->getTextListStyle().dump();
378  // SAL_INFO("oox.ppt","master text list style");
379  // pPlaceholder->getMasterTextListStyle()->dump();
380 
381  aMasterTextListStyle = pNewTextListStyle;
382  // SAL_INFO("oox.ppt","combined master text list style");
383  // aMasterTextListStyle->dump();
384  }
385  if (pPPTPlaceholder && pPPTPlaceholder->mpPlaceholder) {
386  SAL_INFO("oox.ppt","placeholder has parent placeholder: " << pPPTPlaceholder->mpPlaceholder->getId() << " type: " << lclDebugSubType( pPPTPlaceholder->mpPlaceholder->getSubType() ) << " index: " << pPPTPlaceholder->mpPlaceholder->getSubTypeIndex().get() );
387  SAL_INFO("oox.ppt","has textbody " << (pPPTPlaceholder->mpPlaceholder->getTextBody() != nullptr) );
388  TextListStylePtr pPlaceholderStyle = getSubTypeTextListStyle( rSlidePersist, pPPTPlaceholder->mpPlaceholder->getSubType() );
389  if (pPPTPlaceholder->mpPlaceholder->getTextBody())
390  pNewTextListStyle->apply( pPPTPlaceholder->mpPlaceholder->getTextBody()->getTextListStyle() );
391  if (pPlaceholderStyle) {
392  pNewTextListStyle->apply( *pPlaceholderStyle );
393  //pPlaceholderStyle->dump();
394  }
395  }
396  } else if (!mpPlaceholder) {
397  aMasterTextListStyle.reset();
398  }
399  SAL_INFO("oox.ppt","placeholder id: " << (pPlaceholder ? pPlaceholder->getId() : "not found"));
400  }
401 
402  if (!sServiceName.isEmpty())
403  {
404  if (!aMasterTextListStyle)
405  {
406  bool isOther = !getTextBody() && sServiceName != "com.sun.star.drawing.GroupShape";
407  TextListStylePtr aSlideStyle = isOther ? rSlidePersist.getOtherTextStyle() : rSlidePersist.getDefaultTextStyle();
408  // Combine from MasterSlide details as well.
409  if (rSlidePersist.getMasterPersist())
410  {
411  aMasterTextListStyle = isOther ? rSlidePersist.getMasterPersist()->getOtherTextStyle() : rSlidePersist.getMasterPersist()->getDefaultTextStyle();
412  if (aSlideStyle)
413  aMasterTextListStyle->apply( *aSlideStyle );
414  }
415  else
416  {
417  aMasterTextListStyle = aSlideStyle;
418  }
419  }
420 
421  if( aMasterTextListStyle && getTextBody() ) {
422  TextListStylePtr aCombinedTextListStyle = std::make_shared<TextListStyle>();
423 
424  aCombinedTextListStyle->apply( *aMasterTextListStyle );
425 
426  if( mpPlaceholder && mpPlaceholder->getTextBody() )
427  aCombinedTextListStyle->apply( mpPlaceholder->getTextBody()->getTextListStyle() );
428  aCombinedTextListStyle->apply( getTextBody()->getTextListStyle() );
429 
430  setMasterTextListStyle( aCombinedTextListStyle );
431  } else
432  setMasterTextListStyle( aMasterTextListStyle );
433 
434  Reference< XShape > xShape( createAndInsert( rFilterBase, sServiceName, pTheme, rxShapes, bClearText, bool(mpPlaceholder), aTransformation, getFillProperties() ) );
435  // if exists and not duplicated, try to use the title text as slide name to help its re-use on UI
436  if (!rSlidePersist.isMasterPage() && rSlidePersist.getPage().is() && (mnSubType == XML_title || mnSubType == XML_ctrTitle))
437  {
438  try
439  {
440  sal_Int32 nCount = 1;
441  OUString aTitleText;
442  Reference<XTextRange> xText(xShape, UNO_QUERY_THROW);
443  aTitleText = xText->getString();
444  Reference<drawing::XDrawPagesSupplier> xDPS(rFilterBase.getModel(), uno::UNO_QUERY_THROW);
445  Reference<drawing::XDrawPages> xDrawPages(xDPS->getDrawPages(), uno::UNO_SET_THROW);
446  sal_uInt32 nMaxPages = xDrawPages->getCount();
447  // just a magic value but we don't want to drop out slide names which are too long
448  if (aTitleText.getLength() > 63)
449  aTitleText = aTitleText.copy(0, 63);
450  bool bUseTitleAsSlideName = !aTitleText.isEmpty();
451  // check duplicated title name
452  if (bUseTitleAsSlideName)
453  {
454  for (sal_uInt32 nPage = 0; nPage < nMaxPages; ++nPage)
455  {
456  Reference<XDrawPage> xDrawPage(xDrawPages->getByIndex(nPage), uno::UNO_QUERY);
457  Reference<container::XNamed> xNamed(xDrawPage, UNO_QUERY_THROW);
458  OUString sRest;
459  if (xNamed->getName().startsWith(aTitleText, &sRest)
460  && (sRest.isEmpty()
461  || (sRest.startsWith(" (") && sRest.endsWith(")")
462  && sRest.copy(2, sRest.getLength() - 3).toInt32() > 0)))
463  nCount++;
464  }
465  Reference<container::XNamed> xName(rSlidePersist.getPage(), UNO_QUERY_THROW);
466  xName->setName(
467  aTitleText
468  + (nCount == 1 ? OUString("") : " (" + OUString::number(nCount) + ")"));
469  }
470  }
471  catch (uno::Exception&)
472  {
473 
474  }
475  }
476 
477  // Apply text properties on placeholder text inside this placeholder shape
478  if (meShapeLocation == Slide && mpPlaceholder && getTextBody() && getTextBody()->isEmpty())
479  {
480  Reference < XText > xText(mxShape, UNO_QUERY);
481  if (xText.is())
482  {
483  TextCharacterProperties aCharStyleProperties;
484  getTextBody()->ApplyStyleEmpty(rFilterBase, xText, aCharStyleProperties, mpMasterTextListStyle);
485  }
486  }
487  if (pShapeMap)
488  {
489  // bnc#705982 - if optional model id reference is
490  // there, use that to obtain target shape
491  if (!msModelId.isEmpty())
492  {
493  (*pShapeMap)[ msModelId ] = shared_from_this();
494  }
495  else if (!msId.isEmpty())
496  {
497  (*pShapeMap)[ msId ] = shared_from_this();
498  }
499  }
500 
501  // we will be losing whatever information there is in the footer placeholder on master/layout slides
502  // since they should have the "<footer>" textfield in them in order to make LibreOffice process them as expected
503  // likewise DateTime placeholder data on master/layout slides will be lost and replaced
504  if( (mnSubType == XML_ftr || mnSubType == XML_dt) && meShapeLocation != Slide )
505  {
506  OUString aFieldType;
507  if( mnSubType == XML_ftr )
508  aFieldType = "com.sun.star.presentation.TextField.Footer";
509  else
510  aFieldType = "com.sun.star.presentation.TextField.DateTime";
511  Reference < XTextField > xField( xServiceFact->createInstance( aFieldType ), UNO_QUERY );
512  Reference < XText > xText(mxShape, UNO_QUERY);
513  if(xText.is())
514  {
515  xText->setString("");
516  Reference < XTextCursor > xTextCursor = xText->createTextCursor();
517  xText->insertTextContent( xTextCursor, xField, false);
518  }
519  }
520 
521  // if this is a group shape, we have to add also each child shape
522  Reference<XShapes> xShapes(xShape, UNO_QUERY);
523  if (xShapes.is())
524  {
526  {
528  }
529  addChildren( rFilterBase, *this, pTheme, xShapes, pShapeMap, aTransformation );
531  {
532  rFilterBase.setDiagramFontHeights(nullptr);
533  }
534  }
535 
537  {
540  }
541 
542  OUString sURL;
543  getShapeProperties().getProperty(PROP_URL) >>= sURL;
544  if (!sURL.isEmpty())
545  {
546  Reference<XEventsSupplier> xEventsSupplier(xShape, UNO_QUERY);
547  if (!xEventsSupplier.is())
548  return;
549 
550  Reference<XNameReplace> xEvents(xEventsSupplier->getEvents());
551  if (!xEvents.is())
552  return;
553 
554  OUString sAPIEventName;
555  sal_Int32 nPropertyCount = 2;
556  css::presentation::ClickAction meClickAction;
557  uno::Sequence<beans::PropertyValue> aProperties;
558 
559  std::map<OUString, css::presentation::ClickAction> ActionMap = {
560  { "#action?jump=nextslide", ClickAction_NEXTPAGE },
561  { "#action?jump=previousslide", ClickAction_PREVPAGE },
562  { "#action?jump=firstslide", ClickAction_FIRSTPAGE },
563  { "#action?jump=lastslide", ClickAction_LASTPAGE },
564  { "#action?jump=endshow", ClickAction_STOPPRESENTATION },
565  };
566 
567  std::map<OUString, css::presentation::ClickAction>::const_iterator aIt
568  = ActionMap.find(sURL);
569  aIt != ActionMap.end() ? meClickAction = aIt->second
570  : meClickAction = ClickAction_BOOKMARK;
571 
572  // ClickAction_BOOKMARK and ClickAction_DOCUMENT share the same event
573  // so check here if it's a bookmark or a document
574  if (meClickAction == ClickAction_BOOKMARK)
575  {
576  if (!sURL.startsWith("#"))
577  meClickAction = ClickAction_DOCUMENT;
578  else
579  sURL = sURL.copy(1);
580  nPropertyCount += 1;
581  }
582 
583  aProperties.realloc(nPropertyCount);
584  beans::PropertyValue* pProperties = aProperties.getArray();
585 
586  pProperties->Name = "EventType";
587  pProperties->Handle = -1;
588  pProperties->Value <<= OUString("Presentation");
589  pProperties->State = beans::PropertyState_DIRECT_VALUE;
590  pProperties++;
591 
592  pProperties->Name = "ClickAction";
593  pProperties->Handle = -1;
594  pProperties->Value <<= meClickAction;
595  pProperties->State = beans::PropertyState_DIRECT_VALUE;
596  pProperties++;
597 
598  switch (meClickAction)
599  {
600  case ClickAction_BOOKMARK:
601  case ClickAction_DOCUMENT:
602  pProperties->Name = "Bookmark";
603  pProperties->Handle = -1;
604  pProperties->Value <<= sURL;
605  pProperties->State = beans::PropertyState_DIRECT_VALUE;
606  break;
607  default:
608  break;
609  }
610 
611  sAPIEventName = "OnClick";
612  xEvents->replaceByName(sAPIEventName, uno::Any(aProperties));
613  }
614  }
615  }
616  catch (const Exception&)
617  {
618  }
619 }
620 
621 namespace
622 {
623  bool ShapeLocationIsMaster(oox::drawingml::Shape *pInShape)
624  {
625  PPTShape* pShape = dynamic_cast<PPTShape*>(pInShape);
626  return pShape && pShape->getShapeLocation() == Master;
627  }
628 }
629 
630 // Function to find placeholder (ph) for a shape. No idea how MSO implements this, but
631 // this order seems to work quite well (probably it's unnecessary complicated / wrong):
632 // 1. ph with nFirstSubType and the same oSubTypeIndex
633 // 2. ph with nFirstSubType
634 // 3. ph with nSecondSubType and the same oSubTypeIndex
635 // 4. ph with nSecondSubType
636 // 5. ph with the same oSubTypeIndex
637 
638 oox::drawingml::ShapePtr PPTShape::findPlaceholder( sal_Int32 nFirstSubType, sal_Int32 nSecondSubType,
639  const OptValue< sal_Int32 >& oSubTypeIndex, std::vector< oox::drawingml::ShapePtr >& rShapes, bool bMasterOnly )
640 {
641  class Placeholders
642  {
643  public:
644  Placeholders()
645  : aChoice(5) // resize to 5
646  {
647  }
648 
649  void add(const oox::drawingml::ShapePtr& aShape, sal_Int32 nFirstSubType, sal_Int32 nSecondSubType, const OptValue< sal_Int32 >& oSubTypeIndex)
650  {
651  if (!aShape)
652  return;
653 
654  // get flags
655  const bool bSameFirstSubType = aShape->getSubType() == nFirstSubType;
656  const bool bSameSecondSubType = aShape->getSubType() == nSecondSubType;
657  const bool bSameIndex = aShape->getSubTypeIndex() == oSubTypeIndex;
658 
659  // get prio
660  int aPrioIndex = -1;
661  if (bSameIndex && bSameFirstSubType)
662  aPrioIndex = 0;
663  else if (!bSameIndex && bSameFirstSubType)
664  aPrioIndex = 1;
665  else if (bSameIndex && bSameSecondSubType)
666  aPrioIndex = 2;
667  else if (!bSameIndex && bSameSecondSubType)
668  aPrioIndex = 3;
669  else if (bSameIndex)
670  aPrioIndex = 4;
671 
672  // add
673  if (aPrioIndex != -1)
674  {
675  if (!aChoice.at(aPrioIndex))
676  {
677  aChoice.at(aPrioIndex) = aShape;
678  }
679  }
680  }
681 
682  // return according to prio
683  oox::drawingml::ShapePtr getByPrio() const
684  {
685  for (const oox::drawingml::ShapePtr& aShape : aChoice)
686  {
687  if (aShape)
688  {
689  return aShape;
690  }
691  }
692 
693  return oox::drawingml::ShapePtr();
694  }
695 
696  bool hasByPrio(size_t aIndex) const
697  {
698  return bool(aChoice.at(aIndex));
699  }
700 
701  private:
702  std::vector< oox::drawingml::ShapePtr > aChoice;
703 
704  } aPlaceholders;
705 
706  // check all shapes
707  std::vector< oox::drawingml::ShapePtr >::reverse_iterator aRevIter( rShapes.rbegin() );
708  for (; aRevIter != rShapes.rend(); ++aRevIter)
709  {
710  // check shape
711  if (!bMasterOnly || ShapeLocationIsMaster((*aRevIter).get()))
712  {
713  const oox::drawingml::ShapePtr& aShape = *aRevIter;
714  aPlaceholders.add(aShape, nFirstSubType, nSecondSubType, oSubTypeIndex);
715  }
716 
717  // check children
718  std::vector< oox::drawingml::ShapePtr >& rChildren = (*aRevIter)->getChildren();
719  if (!rChildren.empty())
720  {
721  const oox::drawingml::ShapePtr aShape = findPlaceholder( nFirstSubType, nSecondSubType, oSubTypeIndex, rChildren, bMasterOnly );
722  if (aShape)
723  {
724  aPlaceholders.add(aShape, nFirstSubType, nSecondSubType, oSubTypeIndex);
725  }
726  }
727 
728  if (aPlaceholders.hasByPrio(0))
729  {
730  break;
731  }
732  }
733 
734  // return something according to prio
735  return aPlaceholders.getByPrio();
736 }
737 
738 oox::drawingml::ShapePtr PPTShape::findPlaceholderByIndex( const sal_Int32 nIdx, std::vector< oox::drawingml::ShapePtr >& rShapes, bool bMasterOnly )
739 {
740  oox::drawingml::ShapePtr aShapePtr;
741 
742  std::vector< oox::drawingml::ShapePtr >::reverse_iterator aRevIter( rShapes.rbegin() );
743  while( aRevIter != rShapes.rend() )
744  {
745  if ( (*aRevIter)->getSubTypeIndex().has() && (*aRevIter)->getSubTypeIndex().get() == nIdx &&
746  ( !bMasterOnly || ShapeLocationIsMaster((*aRevIter).get()) ) )
747  {
748  aShapePtr = *aRevIter;
749  break;
750  }
751  std::vector< oox::drawingml::ShapePtr >& rChildren = (*aRevIter)->getChildren();
752  aShapePtr = findPlaceholderByIndex( nIdx, rChildren, bMasterOnly );
753  if ( aShapePtr )
754  break;
755  ++aRevIter;
756  }
757  return aShapePtr;
758 }
759 
760 }
761 
762 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
void setPosition(css::awt::Point nPosition)
Definition: shape.hxx:138
sal_Int32 getSubType() const
Definition: shape.hxx:162
FrameType meFrameType
Type for graphic frame shapes.
Definition: shape.hxx:342
void setDiagramFontHeights(NamedShapePairs *pDiagramFontHeights)
OUString msServiceName
Definition: shape.hxx:327
void addChildren(::oox::core::XmlFilterBase &rFilterBase, Shape &rMaster, const Theme *pTheme, const css::uno::Reference< css::drawing::XShapes > &rxShapes, ShapeIdMap *pShapeMap, const basegfx::B2DHomMatrix &aTransformation)
Definition: shape.cxx:391
PropertyMap & getShapeProperties()
Definition: shape.hxx:115
bool isNotesPage() const
sal_Int32 mnSubType
Definition: shape.hxx:332
sal_Int32 toInt32(OUString const &rStr)
void setMasterTextListStyle(const TextListStylePtr &pMasterTextListStyle)
Definition: shape.cxx:1853
oox::core::NamedShapePairs & getDiagramFontHeights()
Definition: shape.hxx:246
std::shared_ptr< TextRun > TextRunPtr
Definition: textrun.hxx:65
void syncDiagramFontHeights()
Definition: shape.cxx:1716
static SvxDateFormat getLODateFormat(std::u16string_view rDateTimeType)
Gets the corresponding LO Date format for given OOXML datetime field type.
Definition: textfield.cxx:214
PropertiesInfo aProperties
constexpr OUStringLiteral sServiceName
int nCount
Shape
css::awt::Point maPosition
Definition: shape.hxx:338
bool hasNonInheritedShapeProperties() const
Returns whether or not the shape had a non-empty spPr tag.
Definition: pptshape.hxx:83
css::uno::Reference< css::drawing::XShape > mxShape
Definition: shape.hxx:325
const css::uno::Reference< css::drawing::XDrawPage > & getPage() const
ShapeLocation getShapeLocation() const
Definition: pptshape.hxx:75
const oox::drawingml::TextListStylePtr & getOtherTextStyle() const
static oox::drawingml::ShapePtr findPlaceholder(const sal_Int32 nFirstSubType, const sal_Int32 nSecondSubType, const OptValue< sal_Int32 > &oSubTypeIndex, std::vector< oox::drawingml::ShapePtr > &rShapes, bool bMasterOnly=false)
Definition: pptshape.cxx:638
const OptValue< sal_Int32 > & getSubTypeIndex() const
Definition: shape.hxx:164
css::awt::Size maSize
Definition: shape.hxx:337
static const char * lclDebugSubType(sal_Int32 nType)
Definition: pptshape.cxx:72
bool isMasterPage() const
static oox::drawingml::TextListStylePtr getSubTypeTextListStyle(const SlidePersist &rSlidePersist, sal_Int32 nSubType)
Definition: pptshape.cxx:113
const oox::drawingml::TextListStylePtr & getTitleTextStyle() const
float u
SvxDateFormat
void setSize(css::awt::Size aSize)
Definition: shape.hxx:141
const oox::drawingml::TextListStylePtr & getBodyTextStyle() const
static SvxTimeFormat getLOTimeFormat(std::u16string_view rDateTimeType)
Gets the corresponding LO Time format for given OOXML datetime field type.
Definition: textfield.cxx:247
const css::uno::Reference< css::frame::XModel > & getModel() const
Returns the document model (always existing).
Definition: filterbase.cxx:217
virtual ~PPTShape() override
Definition: pptshape.cxx:68
const TextBodyPtr & getTextBody() const
Definition: shape.hxx:175
std::shared_ptr< TextListStyle > TextListStylePtr
static oox::drawingml::ShapePtr findPlaceholderByIndex(const sal_Int32 nIdx, std::vector< oox::drawingml::ShapePtr > &rShapes, bool bMasterOnly=false)
Definition: pptshape.cxx:738
std::deque< AttacherIndex_Impl > aIndex
OUString msModelId
Definition: pptshape.hxx:49
TextListStylePtr mpMasterTextListStyle
Definition: shape.hxx:324
#define SAL_INFO(area, stream)
::std::map< OUString, ShapePtr > ShapeIdMap
Definition: shape.hxx:72
const OUString & getType() const
Definition: textfield.hxx:43
void keepDiagramCompatibilityInfo()
Definition: shape.cxx:1679
const oox::drawingml::TextListStylePtr & getNotesTextStyle() const
bool hasShapeStyleRefs() const
Definition: shape.hxx:182
const oox::drawingml::ShapePtr & getShapes() const
const oox::drawingml::TextListStylePtr & getDefaultTextStyle() const
const SlidePersistPtr & getMasterPersist() const
PPTShape(const oox::ppt::ShapeLocation eShapeLocation, const char *pServiceType)
Definition: pptshape.cxx:60
bool IsPlaceHolderCandidate(const SlidePersist &rSlidePersist) const
Definition: pptshape.cxx:138
css::uno::Any getProperty(sal_Int32 nPropId)
std::shared_ptr< Shape > ShapePtr
SvxTimeFormat
ShapeLocation meShapeLocation
Definition: pptshape.hxx:50
FillProperties & getFillProperties()
Definition: shape.hxx:120
Complex diagram drawing shape.
Definition: shape.hxx:255
void addShape(oox::core::XmlFilterBase &rFilterBase, const SlidePersist &rPersist, const oox::drawingml::Theme *pTheme, const css::uno::Reference< css::drawing::XShapes > &rxShapes, basegfx::B2DHomMatrix &aTransformation,::oox::drawingml::ShapeIdMap *pShapeMap)
Definition: pptshape.cxx:155
css::uno::Reference< css::drawing::XShape > const & createAndInsert(::oox::core::XmlFilterBase &rFilterBase, const OUString &rServiceName, const Theme *pTheme, const css::uno::Reference< css::drawing::XShapes > &rxShapes, bool bClearText, bool bDoNotInsertEmptyTextBody, basegfx::B2DHomMatrix &aTransformation, const FillProperties &rShapeOrParentShapeFillProps, oox::drawingml::ShapePtr pParentGroupShape=nullptr)
Definition: shape.cxx:674
oox::drawingml::ShapePtr mpPlaceholder
Definition: pptshape.hxx:53