Coverage Report

Created: 2025-12-31 10:39

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/oox/source/ppt/presentationfragmenthandler.cxx
Line
Count
Source
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 <comphelper/anytostring.hxx>
21
#include <comphelper/propertyvalue.hxx>
22
#include <comphelper/sequence.hxx>
23
#include <comphelper/sequenceashashmap.hxx>
24
#include <o3tl/string_view.hxx>
25
#include <sal/log.hxx>
26
#include <tools/multisel.hxx>
27
#include <comphelper/diagnose_ex.hxx>
28
29
#include <frozen/bits/defines.h>
30
#include <frozen/bits/elsa_std.h>
31
#include <frozen/unordered_map.h>
32
33
#include <com/sun/star/container/XNamed.hpp>
34
#include <com/sun/star/drawing/XMasterPagesSupplier.hpp>
35
#include <com/sun/star/drawing/XDrawPages.hpp>
36
#include <com/sun/star/drawing/XDrawPagesSupplier.hpp>
37
#include <com/sun/star/drawing/XMasterPageTarget.hpp>
38
#include <com/sun/star/frame/XModel.hpp>
39
#include <com/sun/star/io/XInputStream.hpp>
40
#include <com/sun/star/text/XTextField.hpp>
41
#include <com/sun/star/xml/dom/XDocument.hpp>
42
#include <com/sun/star/xml/sax/XFastSAXSerializable.hpp>
43
#include <com/sun/star/presentation/XPresentationPage.hpp>
44
#include <com/sun/star/task/XStatusIndicator.hpp>
45
#include <com/sun/star/presentation/XCustomPresentationSupplier.hpp>
46
#include <com/sun/star/container/XIndexContainer.hpp>
47
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
48
#include <com/sun/star/lang/XSingleServiceFactory.hpp>
49
#include <com/sun/star/container/XNameContainer.hpp>
50
51
#include <oox/drawingml/theme.hxx>
52
#include <oox/drawingml/drawingmltypes.hxx>
53
#include <oox/drawingml/themefragmenthandler.hxx>
54
#include <drawingml/textliststylecontext.hxx>
55
#include <oox/helper/attributelist.hxx>
56
#include <oox/ole/olestorage.hxx>
57
#include <oox/ole/vbaproject.hxx>
58
#include <oox/ppt/pptshape.hxx>
59
#include <oox/ppt/presentationfragmenthandler.hxx>
60
#include <oox/ppt/slidefragmenthandler.hxx>
61
#include <oox/ppt/layoutfragmenthandler.hxx>
62
#include <oox/ppt/pptimport.hxx>
63
#include <oox/token/namespaces.hxx>
64
#include <oox/token/tokens.hxx>
65
#include <sax/fastattribs.hxx>
66
67
#include <com/sun/star/office/XAnnotation.hpp>
68
#include <com/sun/star/office/XAnnotationAccess.hpp>
69
#include <ooxresid.hxx>
70
#include <strings.hrc>
71
72
#include "EmbeddedFontListContext.hxx"
73
74
using namespace ::com::sun::star;
75
using namespace ::oox::core;
76
using namespace ::oox::drawingml;
77
using namespace ::com::sun::star::uno;
78
using namespace ::com::sun::star::beans;
79
using namespace ::com::sun::star::drawing;
80
using namespace ::com::sun::star::presentation;
81
using namespace ::com::sun::star::xml::sax;
82
83
namespace oox::ppt
84
{
85
86
namespace
87
{
88
constexpr auto constPredefinedClrTokens = frozen::make_unordered_map<PredefinedClrSchemeId, sal_Int32>
89
({
90
    { dk1, XML_dk1 },
91
    { lt1, XML_lt1 },
92
    { dk2, XML_dk2 },
93
    { lt2, XML_lt2 },
94
    { accent1, XML_accent1 },
95
    { accent2, XML_accent2 },
96
    { accent3, XML_accent3 },
97
    { accent4, XML_accent4 },
98
    { accent5, XML_accent5 },
99
    { accent6, XML_accent6 },
100
    { hlink, XML_hlink },
101
    { folHlink, XML_folHlink }
102
});
103
104
sal_Int32 getPredefinedClrTokens(PredefinedClrSchemeId eID)
105
22.7k
{
106
22.7k
    auto iterator = constPredefinedClrTokens.find(eID);
107
22.7k
    if (iterator == constPredefinedClrTokens.end())
108
0
        return XML_TOKEN_INVALID;
109
22.7k
    return iterator->second;
110
22.7k
}
111
} // end anonymous ns
112
113
PresentationFragmentHandler::PresentationFragmentHandler(XmlFilterBase& rFilter, const OUString& rFragmentPath)
114
2.57k
    : FragmentHandler2( rFilter, rFragmentPath )
115
2.57k
    , mpTextListStyle( std::make_shared<TextListStyle>() )
116
2.57k
    , mbCommentAuthorsRead(false)
117
2.57k
{
118
2.57k
    TextParagraphPropertiesArray& rParagraphDefaultsVector( mpTextListStyle->getListStyle() );
119
2.57k
    for (auto & elem : rParagraphDefaultsVector)
120
23.1k
    {
121
        // ppt is having zero bottom margin per default, whereas OOo is 0,5cm,
122
        // so this attribute needs to be set always
123
23.1k
        elem.getParaBottomMargin() = TextSpacing( 0 );
124
23.1k
    }
125
2.57k
}
126
127
PresentationFragmentHandler::~PresentationFragmentHandler() noexcept
128
2.57k
{
129
2.57k
}
130
131
void PresentationFragmentHandler::importSlideNames(const XmlFilterBase& rFilter, const std::vector<SlidePersistPtr>& rSlidePersist)
132
2.54k
{
133
2.54k
    sal_Int32 nMaxPages = rSlidePersist.size();
134
7.66k
    for (sal_Int32 nPage = 0; nPage < nMaxPages; nPage++)
135
5.11k
    {
136
5.11k
        auto aShapeMap = rSlidePersist[nPage]->getShapeMap();
137
5.11k
        auto aIter = std::find_if(aShapeMap.begin(), aShapeMap.end(),
138
5.95k
                                  [](const std::pair<OUString, ShapePtr>& element) {
139
5.95k
                                      auto pShapePtr = element.second;
140
5.95k
                                      return (pShapePtr
141
5.95k
                                              && (pShapePtr->getSubType() == XML_title
142
5.86k
                                                  || pShapePtr->getSubType() == XML_ctrTitle));
143
5.95k
                                  });
144
5.11k
        if (aIter != aShapeMap.end())
145
366
        {
146
366
            OUString aTitleText;
147
366
            Reference<text::XTextRange> xText(aIter->second->getXShape(), UNO_QUERY_THROW);
148
366
            aTitleText = xText->getString();
149
            // just a magic value but we don't want to drop out slide names which are too long
150
366
            if (aTitleText.getLength() > 63)
151
8
                aTitleText = aTitleText.copy(0, 63);
152
366
            bool bUseTitleAsSlideName = !aTitleText.isEmpty();
153
            // check duplicated title name
154
366
            if (bUseTitleAsSlideName)
155
181
            {
156
181
                sal_Int32 nCount = 1;
157
181
                Reference<XDrawPagesSupplier> xDPS(rFilter.getModel(), UNO_QUERY_THROW);
158
181
                Reference<XDrawPages> xDrawPages(xDPS->getDrawPages(), UNO_SET_THROW);
159
198
                for (sal_Int32 i = 0; i < nPage; ++i)
160
17
                {
161
17
                    Reference<XDrawPage> xDrawPage(xDrawPages->getByIndex(i), UNO_QUERY);
162
17
                    Reference<container::XNamed> xNamed(xDrawPage, UNO_QUERY_THROW);
163
17
                    std::u16string_view sRest;
164
17
                    if (o3tl::starts_with(xNamed->getName(), aTitleText, &sRest)
165
12
                        && (sRest.empty()
166
0
                            || (o3tl::starts_with(sRest, u" (") && o3tl::ends_with(sRest, u")")
167
0
                                && o3tl::toInt32(sRest.substr(2, sRest.size() - 3)) > 0)))
168
12
                        nCount++;
169
17
                }
170
181
                Reference<container::XNamed> xName(rSlidePersist[nPage]->getPage(), UNO_QUERY_THROW);
171
181
                xName->setName(
172
181
                    aTitleText
173
181
                    + (nCount == 1 ? u""_ustr : " (" + OUString::number(nCount) + ")"));
174
181
            }
175
366
        }
176
5.11k
    }
177
2.54k
}
178
179
void PresentationFragmentHandler::importCustomSlideShow(std::vector<CustomShow>& rCustomShowList)
180
0
{
181
0
    PowerPointImport& rFilter = dynamic_cast<PowerPointImport&>(getFilter());
182
0
    Reference<frame::XModel> xModel(rFilter.getModel());
183
0
    Reference<XDrawPagesSupplier> xDrawPagesSupplier(xModel, UNO_QUERY_THROW);
184
0
    Reference<XDrawPages> xDrawPages(xDrawPagesSupplier->getDrawPages(), UNO_SET_THROW);
185
186
0
    Reference<css::lang::XSingleServiceFactory> mxShowFactory;
187
0
    Reference<css::container::XNameContainer> mxShows;
188
0
    Reference<XCustomPresentationSupplier> xShowsSupplier(xModel, UNO_QUERY);
189
0
    if (xShowsSupplier.is())
190
0
    {
191
0
        mxShows = xShowsSupplier->getCustomPresentations();
192
0
        mxShowFactory.set(mxShows, UNO_QUERY);
193
0
    }
194
195
0
    for (size_t i = 0; i < rCustomShowList.size(); ++i)
196
0
    {
197
0
        Reference<css::container::XIndexContainer> xShow(mxShowFactory->createInstance(),
198
0
                                                                    UNO_QUERY);
199
0
        if (xShow.is())
200
0
        {
201
0
            static constexpr OUString sSlide = u"slides/slide"_ustr;
202
0
            for (size_t j = 0; j < rCustomShowList[i].maSldLst.size(); ++j)
203
0
            {
204
0
                OUString sCustomSlide = rCustomShowList[i].maSldLst[j];
205
0
                sal_Int32 nPageNumber = 0;
206
0
                if (sCustomSlide.match(sSlide))
207
0
                    nPageNumber = o3tl::toInt32(sCustomSlide.subView(sSlide.getLength()));
208
209
0
                Reference<XDrawPage> xPage;
210
0
                xDrawPages->getByIndex(nPageNumber - 1) >>= xPage;
211
0
                if (xPage.is())
212
0
                    xShow->insertByIndex(xShow->getCount(), Any(xPage));
213
0
            }
214
215
0
            Any aAny;
216
0
            aAny <<= xShow;
217
0
            mxShows->insertByName(rCustomShowList[i].maCustomShowName, aAny);
218
0
        }
219
0
    }
220
0
}
221
222
void PresentationFragmentHandler::importMasterSlide(const Reference<frame::XModel>& xModel,
223
                                                    PowerPointImport& rFilter,
224
                                                    const OUString& rMasterFragmentPath)
225
2.66k
{
226
2.66k
    OUString aLayoutFragmentPath;
227
2.66k
    SlidePersistPtr pMasterPersistPtr;
228
2.66k
    Reference< drawing::XDrawPage > xMasterPage;
229
2.66k
    Reference< drawing::XMasterPagesSupplier > xMPS( xModel, uno::UNO_QUERY_THROW );
230
2.66k
    Reference< drawing::XDrawPages > xMasterPages( xMPS->getMasterPages(), uno::UNO_SET_THROW );
231
2.66k
    RelationsRef xMasterRelations = rFilter.importRelations( rMasterFragmentPath );
232
233
2.66k
    for (const auto& rEntry : *xMasterRelations)
234
21.2k
    {
235
21.2k
        if (!rEntry.second.maType.endsWith("relationships/slideLayout"))
236
2.53k
            continue;
237
238
18.6k
        aLayoutFragmentPath = xMasterRelations->getFragmentPathFromRelation(rEntry.second);
239
240
18.6k
        sal_Int32 nIndex;
241
18.6k
        if( rFilter.getMasterPages().empty() )
242
2.37k
        {
243
2.37k
            nIndex = 0;
244
2.37k
            xMasterPages->getByIndex( nIndex ) >>= xMasterPage;
245
2.37k
        }
246
16.3k
        else
247
16.3k
        {
248
16.3k
            nIndex = xMasterPages->getCount();
249
16.3k
            xMasterPage = xMasterPages->insertNewByIndex( nIndex );
250
16.3k
        }
251
252
18.6k
        pMasterPersistPtr = std::make_shared<SlidePersist>( rFilter, true, false, xMasterPage,
253
18.6k
                                                            std::make_shared<PPTShape>( Master, u"com.sun.star.drawing.GroupShape"_ustr ), mpTextListStyle );
254
18.6k
        pMasterPersistPtr->setLayoutPath( aLayoutFragmentPath );
255
18.6k
        rFilter.getMasterPages().push_back( pMasterPersistPtr );
256
18.6k
        rFilter.setActualSlidePersist( pMasterPersistPtr );
257
18.6k
        FragmentHandlerRef xMasterFragmentHandler( new SlideFragmentHandler( rFilter, rMasterFragmentPath, pMasterPersistPtr, Master ) );
258
259
        // set the correct theme
260
18.6k
        OUString aThemeFragmentPath = xMasterFragmentHandler->getFragmentPathFromFirstTypeFromOfficeDoc( u"theme" );
261
18.6k
        if( !aThemeFragmentPath.isEmpty() )
262
18.6k
        {
263
18.6k
            std::map< OUString, oox::drawingml::ThemePtr >& rThemes( rFilter.getThemes() );
264
18.6k
            std::map< OUString, oox::drawingml::ThemePtr >::iterator aIter2( rThemes.find( aThemeFragmentPath ) );
265
18.6k
            if( aIter2 == rThemes.end() )
266
2.47k
            {
267
2.47k
                oox::drawingml::ThemePtr pThemePtr = std::make_shared<oox::drawingml::Theme>();
268
2.47k
                pMasterPersistPtr->setTheme( pThemePtr );
269
2.47k
                Reference<xml::dom::XDocument> xDoc=
270
2.47k
                    rFilter.importFragment(aThemeFragmentPath);
271
272
2.47k
                auto pTheme = std::make_shared<model::Theme>();
273
2.47k
                pThemePtr->setTheme(pTheme);
274
275
2.47k
                rFilter.importFragment(
276
2.47k
                    new ThemeFragmentHandler(rFilter, aThemeFragmentPath, *pThemePtr, *pTheme),
277
2.47k
                    Reference<xml::sax::XFastSAXSerializable>(
278
2.47k
                        xDoc,
279
2.47k
                        UNO_QUERY_THROW));
280
2.47k
                rThemes[ aThemeFragmentPath ] = pThemePtr;
281
2.47k
                pThemePtr->setFragment(xDoc);
282
2.47k
                saveThemeToGrabBag(pThemePtr, nIndex + 1);
283
2.47k
            }
284
16.2k
            else
285
16.2k
            {
286
16.2k
                pMasterPersistPtr->setTheme( (*aIter2).second );
287
16.2k
            }
288
18.6k
        }
289
18.6k
        importSlide( xMasterFragmentHandler, pMasterPersistPtr );
290
18.6k
        rFilter.importFragment( new LayoutFragmentHandler( rFilter, aLayoutFragmentPath, pMasterPersistPtr ) );
291
18.6k
        pMasterPersistPtr->createBackground( rFilter );
292
18.6k
        pMasterPersistPtr->createXShapes( rFilter );
293
294
18.6k
        saveColorMapToGrabBag(pMasterPersistPtr->getClrMap());
295
296
18.6k
        uno::Reference< beans::XPropertySet > xSet(pMasterPersistPtr->getPage(), uno::UNO_QUERY_THROW);
297
18.6k
        xSet->setPropertyValue(u"SlideLayout"_ustr, Any(pMasterPersistPtr->getLayoutFromValueToken()));
298
299
18.6k
        oox::drawingml::ThemePtr pTheme = pMasterPersistPtr->getTheme();
300
18.6k
        if (pTheme)
301
18.5k
        {
302
18.5k
            pTheme->addTheme(pMasterPersistPtr->getPage());
303
18.5k
        }
304
18.6k
    }
305
2.66k
}
306
307
void PresentationFragmentHandler::saveThemeToGrabBag(const oox::drawingml::ThemePtr& pThemePtr,
308
                                                     sal_Int32 nThemeIdx)
309
2.27k
{
310
2.27k
    if (!pThemePtr)
311
0
        return;
312
313
2.27k
    try
314
2.27k
    {
315
2.27k
        uno::Reference<beans::XPropertySet> xDocProps(getFilter().getModel(), uno::UNO_QUERY);
316
2.27k
        if (xDocProps.is())
317
2.27k
        {
318
2.27k
            uno::Reference<beans::XPropertySetInfo> xPropsInfo = xDocProps->getPropertySetInfo();
319
320
2.27k
            static constexpr OUString aGrabBagPropName = u"InteropGrabBag"_ustr;
321
2.27k
            if (xPropsInfo.is() && xPropsInfo->hasPropertyByName(aGrabBagPropName))
322
2.27k
            {
323
                // get existing grab bag
324
2.27k
                comphelper::SequenceAsHashMap aGrabBag(xDocProps->getPropertyValue(aGrabBagPropName));
325
326
2.27k
                comphelper::SequenceAsHashMap aThemesHashMap;
327
328
                // create current theme
329
2.27k
                uno::Sequence<beans::PropertyValue> aCurrentTheme(PredefinedClrSchemeId::Count);
330
2.27k
                auto pCurrentTheme = aCurrentTheme.getArray();
331
332
2.27k
                ClrScheme rClrScheme = pThemePtr->getClrScheme();
333
25.0k
                for (int nId = PredefinedClrSchemeId::dk2; nId != PredefinedClrSchemeId::Count; nId++)
334
22.7k
                {
335
22.7k
                    auto eID = static_cast<PredefinedClrSchemeId>(nId);
336
22.7k
                    sal_uInt32 nToken = getPredefinedClrTokens(eID);
337
22.7k
                    OUString sName(getPredefinedClrNames(eID));
338
22.7k
                    ::Color nColor;
339
340
22.7k
                    rClrScheme.getColor(nToken, nColor);
341
342
22.7k
                    pCurrentTheme[nId].Name = sName;
343
22.7k
                    pCurrentTheme[nId].Value <<= nColor;
344
22.7k
                }
345
346
347
2.27k
                uno::Sequence<beans::PropertyValue> aTheme{
348
                    // add new theme to the sequence
349
                    // Export code uses the master slide's index to find the right theme
350
                    // so use the same index in the grabbag.
351
2.27k
                    comphelper::makePropertyValue(
352
2.27k
                        "ppt/theme/theme" + OUString::number(nThemeIdx) + ".xml", aCurrentTheme),
353
                    // store DOM fragment for SmartArt re-generation
354
2.27k
                    comphelper::makePropertyValue(u"OOXTheme"_ustr, pThemePtr->getFragment())
355
2.27k
                };
356
357
2.27k
                aThemesHashMap << aTheme;
358
359
                // put the new items
360
2.27k
                aGrabBag.update(aThemesHashMap);
361
362
                // put it back to the document
363
2.27k
                xDocProps->setPropertyValue(aGrabBagPropName, uno::Any(aGrabBag.getAsConstPropertyValueList()));
364
2.27k
            }
365
2.27k
        }
366
2.27k
    }
367
2.27k
    catch (const uno::Exception&)
368
2.27k
    {
369
0
        SAL_WARN("oox", "oox::ppt::PresentationFragmentHandler::saveThemeToGrabBag, Failed to save grab bag");
370
0
    }
371
2.27k
}
372
373
void PresentationFragmentHandler::saveColorMapToGrabBag(const oox::drawingml::ClrMapPtr& pClrMapPtr)
374
18.5k
{
375
18.5k
    if (!pClrMapPtr)
376
8.68k
        return;
377
378
9.81k
    try
379
9.81k
    {
380
9.81k
        uno::Reference<beans::XPropertySet> xDocProps(getFilter().getModel(), uno::UNO_QUERY);
381
9.81k
        if (xDocProps.is())
382
9.81k
        {
383
9.81k
            uno::Reference<beans::XPropertySetInfo> xPropsInfo = xDocProps->getPropertySetInfo();
384
385
9.81k
            static constexpr OUString aGrabBagPropName = u"InteropGrabBag"_ustr;
386
9.81k
            if (xPropsInfo.is() && xPropsInfo->hasPropertyByName(aGrabBagPropName))
387
9.81k
            {
388
9.81k
                static constexpr auto constTokenArray = std::to_array<sal_Int32>({
389
9.81k
                        XML_bg1,     XML_tx1,     XML_bg2,     XML_tx2,
390
9.81k
                        XML_accent1, XML_accent2, XML_accent3, XML_accent4,
391
9.81k
                        XML_accent5, XML_accent6, XML_hlink,   XML_folHlink
392
9.81k
                });
393
394
9.81k
                comphelper::SequenceAsHashMap aClrMapHashMap;
395
9.81k
                comphelper::SequenceAsHashMap aGrabBag(
396
9.81k
                    xDocProps->getPropertyValue(aGrabBagPropName));
397
398
9.81k
                std::vector<beans::PropertyValue> aClrMapList;
399
9.81k
                size_t nColorMapSize = constTokenArray.size();
400
9.81k
                aClrMapList.reserve(nColorMapSize);
401
127k
                for (size_t i = 0; i < nColorMapSize; ++i)
402
117k
                {
403
117k
                    sal_Int32 nToken = constTokenArray[i];
404
117k
                    pClrMapPtr->getColorMap(nToken);
405
117k
                    aClrMapList.push_back(
406
117k
                        comphelper::makePropertyValue(OUString::number(i), nToken));
407
117k
                }
408
409
9.81k
                uno::Sequence<beans::PropertyValue> aClrMapPropValue{ comphelper::makePropertyValue(
410
9.81k
                    u"OOXColorMap"_ustr,
411
9.81k
                    uno::Any(comphelper::containerToSequence(aClrMapList))) };
412
413
9.81k
                aClrMapHashMap << aClrMapPropValue;
414
9.81k
                aGrabBag.update(aClrMapHashMap);
415
416
9.81k
                xDocProps->setPropertyValue(aGrabBagPropName,
417
9.81k
                                            uno::Any(aGrabBag.getAsConstPropertyValueList()));
418
9.81k
            }
419
9.81k
        }
420
9.81k
    }
421
9.81k
    catch (const uno::Exception&)
422
9.81k
    {
423
0
        SAL_WARN("oox", "oox::ppt::PresentationFragmentHandler::saveColorMapToGrabBag, Failed to save grab bag");
424
0
    }
425
9.81k
}
426
427
void PresentationFragmentHandler::importMasterSlides()
428
2.54k
{
429
2.54k
    OUString aMasterFragmentPath;
430
2.54k
    PowerPointImport& rFilter = dynamic_cast<PowerPointImport&>(getFilter());
431
2.54k
    Reference<frame::XModel> xModel(rFilter.getModel());
432
433
5.21k
    for (size_t nMaster = 0; nMaster < maSlideMasterVector.size(); ++nMaster)
434
2.66k
    {
435
2.66k
        aMasterFragmentPath = getFragmentPathFromRelId(maSlideMasterVector[nMaster]);
436
2.66k
        importMasterSlide(xModel, rFilter, aMasterFragmentPath);
437
2.66k
    }
438
2.54k
}
439
440
void PresentationFragmentHandler::importSlide(sal_uInt32 nSlide, bool bFirstPage, bool bImportNotesPage)
441
5.34k
{
442
5.34k
    PowerPointImport& rFilter = dynamic_cast< PowerPointImport& >( getFilter() );
443
444
5.34k
    Reference< frame::XModel > xModel( rFilter.getModel() );
445
5.34k
    Reference< drawing::XDrawPage > xSlide;
446
447
    // importing slide pages and its corresponding notes page
448
5.34k
    Reference< drawing::XDrawPagesSupplier > xDPS( xModel, uno::UNO_QUERY_THROW );
449
5.34k
    Reference< drawing::XDrawPages > xDrawPages( xDPS->getDrawPages(), uno::UNO_SET_THROW );
450
451
5.34k
    try {
452
453
5.34k
        if( bFirstPage )
454
2.54k
        {
455
2.54k
            xDrawPages->getByIndex( 0 ) >>= xSlide;
456
2.54k
            importMasterSlides();
457
2.54k
        }
458
2.80k
        else
459
2.80k
            xSlide = xDrawPages->insertNewByIndex( xDrawPages->getCount() );
460
461
5.34k
        OUString aSlideFragmentPath = getFragmentPathFromRelId( maSlidesVector[ nSlide ] );
462
5.34k
        if( !aSlideFragmentPath.isEmpty() )
463
5.11k
        {
464
5.11k
            SlidePersistPtr pMasterPersistPtr;
465
5.11k
            SlidePersistPtr pSlidePersistPtr = std::make_shared<SlidePersist>( rFilter, false, false, xSlide,
466
5.11k
                                std::make_shared<PPTShape>( Slide, u"com.sun.star.drawing.GroupShape"_ustr ), mpTextListStyle );
467
468
5.11k
            FragmentHandlerRef xSlideFragmentHandler( new SlideFragmentHandler( rFilter, aSlideFragmentPath, pSlidePersistPtr, Slide ) );
469
470
            // importing the corresponding masterpage/layout
471
5.11k
            OUString aLayoutFragmentPath = xSlideFragmentHandler->getFragmentPathFromFirstTypeFromOfficeDoc( u"slideLayout" );
472
5.11k
            OUString aCommentFragmentPath = xSlideFragmentHandler->getFragmentPathFromFirstTypeFromOfficeDoc( u"comments" );
473
5.11k
            if ( !aLayoutFragmentPath.isEmpty() )
474
3.76k
            {
475
                // importing layout
476
3.76k
                RelationsRef xLayoutRelations = rFilter.importRelations( aLayoutFragmentPath );
477
3.76k
                OUString aMasterFragmentPath = xLayoutRelations->getFragmentPathFromFirstTypeFromOfficeDoc( u"slideMaster" );
478
3.76k
                if( !aMasterFragmentPath.isEmpty() )
479
3.22k
                {
480
                    // check if the corresponding masterpage+layout has already been imported
481
3.22k
                    std::vector< SlidePersistPtr >& rMasterPages( rFilter.getMasterPages() );
482
3.22k
                    for (auto const& masterPage : rMasterPages)
483
7.20k
                    {
484
7.20k
                        if ( ( masterPage->getPath() == aMasterFragmentPath ) && ( masterPage->getLayoutPath() == aLayoutFragmentPath ) )
485
2.84k
                        {
486
2.84k
                            pMasterPersistPtr = masterPage;
487
2.84k
                            break;
488
2.84k
                        }
489
7.20k
                    }
490
3.22k
                }
491
3.76k
            }
492
493
            // importing slide page
494
5.11k
            if (pMasterPersistPtr) {
495
2.84k
                pSlidePersistPtr->setMasterPersist( pMasterPersistPtr );
496
2.84k
                pSlidePersistPtr->setTheme( pMasterPersistPtr->getTheme() );
497
2.84k
                Reference< drawing::XMasterPageTarget > xMasterPageTarget( pSlidePersistPtr->getPage(), UNO_QUERY );
498
2.84k
                if( xMasterPageTarget.is() )
499
2.84k
                    xMasterPageTarget->setMasterPage( pMasterPersistPtr->getPage() );
500
2.84k
            }
501
5.11k
            rFilter.getDrawPages().push_back( pSlidePersistPtr );
502
5.11k
            rFilter.setActualSlidePersist( pSlidePersistPtr );
503
5.11k
            importSlide( xSlideFragmentHandler, pSlidePersistPtr );
504
5.11k
            pSlidePersistPtr->createBackground( rFilter );
505
5.11k
            pSlidePersistPtr->createXShapes( rFilter );
506
507
5.11k
            if(bImportNotesPage) {
508
509
                // now importing the notes page
510
5.11k
                OUString aNotesFragmentPath = xSlideFragmentHandler->getFragmentPathFromFirstTypeFromOfficeDoc( u"notesSlide" );
511
5.11k
                if( !aNotesFragmentPath.isEmpty() )
512
104
                {
513
104
                    Reference< XPresentationPage > xPresentationPage( xSlide, UNO_QUERY );
514
104
                    if ( xPresentationPage.is() )
515
104
                    {
516
104
                        Reference< XDrawPage > xNotesPage( xPresentationPage->getNotesPage() );
517
104
                        if ( xNotesPage.is() )
518
104
                        {
519
104
                            SlidePersistPtr pNotesPersistPtr = std::make_shared<SlidePersist>( rFilter, false, true, xNotesPage,
520
104
                                std::make_shared<PPTShape>( Slide, u"com.sun.star.drawing.GroupShape"_ustr ), mpTextListStyle );
521
104
                            FragmentHandlerRef xNotesFragmentHandler( new SlideFragmentHandler( getFilter(), aNotesFragmentPath, pNotesPersistPtr, Slide ) );
522
104
                            rFilter.getNotesPages().push_back( pNotesPersistPtr );
523
104
                            rFilter.setActualSlidePersist( pNotesPersistPtr );
524
104
                            importSlide( xNotesFragmentHandler, pNotesPersistPtr );
525
104
                            pNotesPersistPtr->createBackground( rFilter );
526
104
                            pNotesPersistPtr->createXShapes( rFilter );
527
104
                        }
528
104
                    }
529
104
                }
530
5.11k
            }
531
532
5.11k
            if( !mbCommentAuthorsRead && !aCommentFragmentPath.isEmpty() )
533
23
            {
534
                // Comments are present and commentAuthors.xml has still not been read
535
23
                mbCommentAuthorsRead = true;
536
23
                Reference< XPresentationPage > xPresentationPage( xSlide, UNO_QUERY );
537
23
                Reference< XDrawPage > xCommentAuthorsPage( xPresentationPage->getNotesPage() );
538
23
                SlidePersistPtr pCommentAuthorsPersistPtr =
539
23
                    std::make_shared<SlidePersist>( rFilter, false, true, xCommentAuthorsPage,
540
23
                                      std::make_shared<PPTShape>(
541
23
                                              Slide, u"com.sun.star.drawing.GroupShape"_ustr ),
542
23
                                      mpTextListStyle );
543
23
                FragmentHandlerRef xCommentAuthorsFragmentHandler(
544
23
                    new SlideFragmentHandler( getFilter(),
545
23
                                              u"ppt/commentAuthors.xml"_ustr,
546
23
                                              pCommentAuthorsPersistPtr,
547
23
                                              Slide ) );
548
549
23
                getFilter().importFragment( xCommentAuthorsFragmentHandler );
550
23
                maAuthorList.setValues( pCommentAuthorsPersistPtr->getCommentAuthors() );
551
23
            }
552
5.11k
            if( !aCommentFragmentPath.isEmpty() )
553
36
            {
554
36
                Reference< XPresentationPage > xPresentationPage( xSlide, UNO_QUERY );
555
36
                Reference< XDrawPage > xCommentsPage( xPresentationPage->getNotesPage() );
556
36
                SlidePersistPtr pCommentsPersistPtr =
557
36
                    std::make_shared<SlidePersist>(
558
36
                        rFilter, false, true, xCommentsPage,
559
36
                        std::make_shared<PPTShape>(
560
36
                                Slide, u"com.sun.star.drawing.GroupShape"_ustr ),
561
36
                        mpTextListStyle );
562
563
36
                FragmentHandlerRef xCommentsFragmentHandler(
564
36
                    new SlideFragmentHandler(
565
36
                        getFilter(),
566
36
                        aCommentFragmentPath,
567
36
                        pCommentsPersistPtr,
568
36
                        Slide ) );
569
36
                pCommentsPersistPtr->getCommentsList().cmLst.clear();
570
36
                getFilter().importFragment( xCommentsFragmentHandler );
571
572
36
                if (!pCommentsPersistPtr->getCommentsList().cmLst.empty())
573
30
                {
574
                    //set comment chars for last comment on slide
575
30
                    SlideFragmentHandler* comment_handler =
576
30
                        dynamic_cast<SlideFragmentHandler*>(xCommentsFragmentHandler.get());
577
30
                    assert(comment_handler);
578
                    // some comments have no text -> set empty string as text to avoid
579
                    // crash (back() on empty vector is undefined) and losing other
580
                    // comment data that might be there (author, position, timestamp etc.)
581
30
                    pCommentsPersistPtr->getCommentsList().cmLst.back().setText(
582
30
                            comment_handler->getCharVector().empty() ? u""_ustr :
583
30
                            comment_handler->getCharVector().back() );
584
30
                }
585
36
                pCommentsPersistPtr->getCommentAuthors().setValues(maAuthorList);
586
587
                //insert all comments from commentsList
588
104
                for(int i=0; i<pCommentsPersistPtr->getCommentsList().getSize(); i++)
589
68
                {
590
68
                    try {
591
68
                        Comment aComment = pCommentsPersistPtr->getCommentsList().getCommentAtIndex(i);
592
68
                        uno::Reference< office::XAnnotationAccess > xAnnotationAccess( xSlide, UNO_QUERY_THROW );
593
68
                        uno::Reference< office::XAnnotation > xAnnotation( xAnnotationAccess->createAndInsertAnnotation() );
594
68
                        int nPosX = aComment.getIntX();
595
68
                        int nPosY = aComment.getIntY();
596
68
                        xAnnotation->setPosition(
597
68
                            geometry::RealPoint2D(
598
68
                                ::oox::drawingml::convertEmuToHmm( nPosX ) * 15.87,
599
68
                                ::oox::drawingml::convertEmuToHmm( nPosY ) * 15.87 ) );
600
68
                        xAnnotation->setAuthor( aComment.getAuthor(maAuthorList) );
601
68
                        xAnnotation->setInitials( aComment.getInitials(maAuthorList) );
602
68
                        xAnnotation->setDateTime( aComment.getDateTime() );
603
68
                        uno::Reference< text::XText > xText( xAnnotation->getTextRange() );
604
68
                        xText->setString( aComment.get_text());
605
68
                    } catch( css::lang::IllegalArgumentException& ) {}
606
68
                }
607
36
            }
608
5.11k
        }
609
5.34k
    }
610
5.34k
    catch( uno::Exception& )
611
5.34k
    {
612
194
        TOOLS_WARN_EXCEPTION( "oox", "oox::ppt::PresentationFragmentHandler::EndDocument()" );
613
194
    }
614
5.34k
}
615
616
void PresentationFragmentHandler::finalizeImport()
617
2.55k
{
618
2.55k
    PowerPointImport& rFilter = dynamic_cast< PowerPointImport& >( getFilter() );
619
620
2.55k
    sal_Int32 nPageCount = maSlidesVector.size();
621
622
    // we will take the FilterData property "PageRange" if available, otherwise full range is used
623
2.55k
    comphelper::SequenceAsHashMap& rFilterData = rFilter.getFilterData();
624
625
    // writing back the original PageCount of this document, it can be accessed from the XModel
626
    // via getArgs after the import.
627
2.55k
    rFilterData[u"OriginalPageCount"_ustr] <<= nPageCount;
628
2.55k
    bool bImportNotesPages = rFilterData.getUnpackedValueOrDefault(u"ImportNotesPages"_ustr, true);
629
2.55k
    OUString aPageRange = rFilterData.getUnpackedValueOrDefault(u"PageRange"_ustr, OUString());
630
631
2.55k
    if( !aPageRange.getLength() )
632
2.55k
    {
633
2.55k
        aPageRange = "1-" + OUString::number( nPageCount );
634
2.55k
    }
635
636
2.55k
    StringRangeEnumerator aRangeEnumerator( aPageRange, 0, nPageCount - 1 );
637
2.55k
    if (aRangeEnumerator.size())
638
2.54k
    {
639
        // todo: localized progress bar text
640
2.54k
        const Reference< task::XStatusIndicator >& rxStatusIndicator( getFilter().getStatusIndicator() );
641
2.54k
        if ( rxStatusIndicator.is() )
642
0
            rxStatusIndicator->start( OUString(), 10000 );
643
644
2.54k
        try
645
2.54k
        {
646
2.54k
            int nPagesImported = 0;
647
2.54k
            for (sal_Int32 elem : aRangeEnumerator)
648
5.34k
            {
649
5.34k
                if ( rxStatusIndicator.is() )
650
0
                    rxStatusIndicator->setValue((nPagesImported * 10000) / aRangeEnumerator.size());
651
652
5.34k
                importSlide(elem, !nPagesImported, bImportNotesPages);
653
5.34k
                nPagesImported++;
654
5.34k
            }
655
2.54k
            importSlideNames( rFilter, rFilter.getDrawPages());
656
2.54k
            if (!maCustomShowList.empty())
657
0
                importCustomSlideShow(maCustomShowList);
658
2.54k
        }
659
2.54k
        catch( uno::Exception& )
660
2.54k
        {
661
0
            TOOLS_WARN_EXCEPTION( "oox", "oox::ppt::PresentationFragmentHandler::finalizeImport()" );
662
0
        }
663
        // todo error handling;
664
2.54k
        if ( rxStatusIndicator.is() )
665
0
            rxStatusIndicator->end();
666
2.54k
    }
667
668
    // open the VBA project storage
669
2.55k
    OUString aVbaFragmentPath = getFragmentPathFromFirstType(CREATE_MSOFFICE_RELATION_TYPE("vbaProject"));
670
2.55k
    if (!aVbaFragmentPath.isEmpty())
671
0
    {
672
0
        uno::Reference<io::XInputStream> xInStrm = getFilter().openInputStream(aVbaFragmentPath);
673
0
        if (xInStrm.is())
674
0
        {
675
0
            StorageRef xPrjStrg = std::make_shared<oox::ole::OleStorage>(getFilter().getComponentContext(), xInStrm, false);
676
0
            getFilter().getVbaProject().importVbaProject(*xPrjStrg);
677
0
        }
678
0
    }
679
2.55k
}
680
681
// CT_Presentation
682
::oox::core::ContextHandlerRef PresentationFragmentHandler::onCreateContext( sal_Int32 aElementToken, const AttributeList& rAttribs )
683
23.3k
{
684
23.3k
    switch( aElementToken )
685
23.3k
    {
686
2.54k
    case PPT_TOKEN( presentation ):
687
2.54k
        mbEmbedTrueTypeFonts = rAttribs.getBool(XML_embedTrueTypeFonts, false);
688
2.54k
        return this;
689
2.54k
    case PPT_TOKEN( sldMasterIdLst ):
690
2.81k
    case PPT_TOKEN( notesMasterIdLst ):
691
5.35k
    case PPT_TOKEN( sldIdLst ):
692
5.35k
        return this;
693
2.66k
    case PPT_TOKEN( sldMasterId ):
694
2.66k
        maSlideMasterVector.push_back( rAttribs.getStringDefaulted( R_TOKEN( id )) );
695
2.66k
        return this;
696
5.34k
    case PPT_TOKEN( sldId ):
697
5.34k
        maSlidesVector.push_back( rAttribs.getStringDefaulted( R_TOKEN( id )) );
698
5.34k
        return this;
699
262
    case PPT_TOKEN( notesMasterId ):
700
262
        maNotesMasterVector.push_back( rAttribs.getStringDefaulted( R_TOKEN( id )) );
701
262
        return this;
702
2.54k
    case PPT_TOKEN( sldSz ):
703
2.54k
        maSlideSize = GetSize2D( rAttribs.getFastAttributeList() );
704
2.54k
        return this;
705
2.54k
    case PPT_TOKEN( notesSz ):
706
2.54k
        maNotesSize = GetSize2D( rAttribs.getFastAttributeList() );
707
2.54k
        return this;
708
29
    case PPT_TOKEN( custShowLst ):
709
29
        return new CustomShowListContext( *this, maCustomShowList );
710
1.04k
    case PPT_TOKEN( defaultTextStyle ):
711
1.04k
        return new TextListStyleContext( *this, *mpTextListStyle );
712
0
    case PPT_TOKEN(embeddedFontLst):
713
0
    {
714
0
        uno::Reference<beans::XPropertySet> xDocSettings(getFilter().getModelFactory()->createInstance(u"com.sun.star.document.Settings"_ustr), uno::UNO_QUERY);
715
0
        return new EmbeddedFontListContext(*this, mbEmbedTrueTypeFonts, xDocSettings);
716
2.81k
    }
717
0
    case PPT_TOKEN( modifyVerifier ):
718
0
        OUString sAlgorithmClass = rAttribs.getStringDefaulted(XML_cryptAlgorithmClass);
719
0
        OUString sAlgorithmType = rAttribs.getStringDefaulted(XML_cryptAlgorithmType);
720
0
        sal_Int32 nAlgorithmSid = rAttribs.getInteger(XML_cryptAlgorithmSid, 0);
721
0
        sal_Int32 nSpinCount = rAttribs.getInteger(XML_spinCount, 0);
722
0
        OUString sSalt = rAttribs.getStringDefaulted(XML_saltData);
723
0
        OUString sHash = rAttribs.getStringDefaulted(XML_hashData);
724
0
        if (sAlgorithmClass == "hash" && sAlgorithmType == "typeAny" && nAlgorithmSid != 0
725
0
            && !sSalt.isEmpty() && !sHash.isEmpty())
726
0
        {
727
0
            OUString sAlgorithmName;
728
0
            switch (nAlgorithmSid)
729
0
            {
730
0
                case 1:
731
0
                    sAlgorithmName = "MD2";
732
0
                    break;
733
0
                case 2:
734
0
                    sAlgorithmName = "MD4";
735
0
                    break;
736
0
                case 3:
737
0
                    sAlgorithmName = "MD5";
738
0
                    break;
739
0
                case 4:
740
0
                    sAlgorithmName = "SHA-1";
741
0
                    break;
742
0
                case 5:
743
0
                    sAlgorithmName = "MAC";
744
0
                    break;
745
0
                case 6:
746
0
                    sAlgorithmName = "RIPEMD";
747
0
                    break;
748
0
                case 7:
749
0
                    sAlgorithmName = "RIPEMD-160";
750
0
                    break;
751
0
                case 9:
752
0
                    sAlgorithmName = "HMAC";
753
0
                    break;
754
0
                case 12:
755
0
                    sAlgorithmName = "SHA-256";
756
0
                    break;
757
0
                case 13:
758
0
                    sAlgorithmName = "SHA-384";
759
0
                    break;
760
0
                case 14:
761
0
                    sAlgorithmName = "SHA-512";
762
0
                    break;
763
0
                default:; // 8, 10, 11, any other value: Undefined.
764
0
            }
765
766
0
            if (!sAlgorithmName.isEmpty())
767
0
            {
768
0
                uno::Sequence<beans::PropertyValue> aResult{
769
0
                    comphelper::makePropertyValue(u"algorithm-name"_ustr, sAlgorithmName),
770
0
                    comphelper::makePropertyValue(u"salt"_ustr, sSalt),
771
0
                    comphelper::makePropertyValue(u"iteration-count"_ustr, nSpinCount),
772
0
                    comphelper::makePropertyValue(u"hash"_ustr, sHash)
773
0
                };
774
0
                try
775
0
                {
776
0
                    uno::Reference<beans::XPropertySet> xDocSettings(
777
0
                        getFilter().getModelFactory()->createInstance(
778
0
                            u"com.sun.star.document.Settings"_ustr),
779
0
                        uno::UNO_QUERY);
780
0
                    xDocSettings->setPropertyValue(u"ModifyPasswordInfo"_ustr, uno::Any(aResult));
781
0
                }
782
0
                catch (const uno::Exception&)
783
0
                {
784
0
                }
785
0
            }
786
0
        }
787
0
        return this;
788
23.3k
    }
789
1.01k
    return this;
790
23.3k
}
791
792
void PresentationFragmentHandler::importSlide( const FragmentHandlerRef& rxSlideFragmentHandler,
793
        const SlidePersistPtr& rSlidePersistPtr )
794
23.7k
{
795
23.7k
    Reference< drawing::XDrawPage > xSlide( rSlidePersistPtr->getPage() );
796
23.7k
    SlidePersistPtr pMasterPersistPtr( rSlidePersistPtr->getMasterPersist() );
797
23.7k
    if ( pMasterPersistPtr )
798
2.84k
    {
799
        // Setting "Layout" property adds extra title and outliner preset shapes to the master slide
800
2.84k
        Reference< drawing::XDrawPage > xMasterSlide(pMasterPersistPtr->getPage());
801
2.84k
        const int nCount = xMasterSlide->getCount();
802
803
2.84k
        uno::Reference< beans::XPropertySet > xSet( xSlide, uno::UNO_QUERY_THROW );
804
2.84k
        xSet->setPropertyValue( u"Layout"_ustr, Any( pMasterPersistPtr->getLayoutFromValueToken() ) );
805
806
5.27k
        while( nCount < xMasterSlide->getCount())
807
2.43k
        {
808
2.43k
            Reference< drawing::XShape > xShape;
809
2.43k
            xMasterSlide->getByIndex(xMasterSlide->getCount()-1) >>= xShape;
810
2.43k
            xMasterSlide->remove(xShape);
811
2.43k
        }
812
2.84k
    }
813
40.4k
    while( xSlide->getCount() )
814
16.7k
    {
815
16.7k
        Reference< drawing::XShape > xShape;
816
16.7k
        xSlide->getByIndex(0) >>= xShape;
817
16.7k
        xSlide->remove( xShape );
818
16.7k
    }
819
820
23.7k
    Reference< XPropertySet > xPropertySet( xSlide, UNO_QUERY );
821
23.7k
    if ( xPropertySet.is() )
822
23.7k
    {
823
23.7k
        awt::Size& rPageSize( rSlidePersistPtr->isNotesPage() ? maNotesSize : maSlideSize );
824
23.7k
        xPropertySet->setPropertyValue( u"Width"_ustr, Any( rPageSize.Width ) );
825
23.7k
        xPropertySet->setPropertyValue( u"Height"_ustr, Any( rPageSize.Height ) );
826
827
23.7k
        oox::ppt::HeaderFooter aHeaderFooter( rSlidePersistPtr->getHeaderFooter() );
828
23.7k
        if ( !rSlidePersistPtr->isMasterPage() )
829
5.22k
            aHeaderFooter.mbSlideNumber = aHeaderFooter.mbHeader = aHeaderFooter.mbFooter = aHeaderFooter.mbDateTime = false;
830
23.7k
        try
831
23.7k
        {
832
23.7k
            if ( rSlidePersistPtr->isNotesPage() )
833
104
                xPropertySet->setPropertyValue( u"IsHeaderVisible"_ustr, Any( aHeaderFooter.mbHeader ) );
834
23.7k
            xPropertySet->setPropertyValue( u"IsFooterVisible"_ustr, Any( aHeaderFooter.mbFooter ) );
835
23.7k
            xPropertySet->setPropertyValue( u"IsDateTimeVisible"_ustr, Any( aHeaderFooter.mbDateTime ) );
836
23.7k
            xPropertySet->setPropertyValue( u"IsPageNumberVisible"_ustr, Any( aHeaderFooter.mbSlideNumber ) );
837
23.7k
        }
838
23.7k
        catch( uno::Exception& )
839
23.7k
        {
840
18.5k
        }
841
23.7k
    }
842
23.7k
    rSlidePersistPtr->setPath( rxSlideFragmentHandler->getFragmentPath() );
843
23.7k
    getFilter().importFragment( rxSlideFragmentHandler );
844
23.7k
}
845
846
}
847
848
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */