File: | home/maarten/src/libreoffice/core/sd/source/core/drawdoc3.cxx |
Warning: | line 741, column 57 Called C++ object pointer is null |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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 | |||||
21 | #include <memory> | ||||
22 | |||||
23 | #include <sfx2/docfile.hxx> | ||||
24 | #include <sfx2/docfilt.hxx> | ||||
25 | #include <sfx2/app.hxx> | ||||
26 | #include <svl/itemset.hxx> | ||||
27 | #include <tools/debug.hxx> | ||||
28 | |||||
29 | #include <sfx2/fcontnr.hxx> | ||||
30 | #include <svl/style.hxx> | ||||
31 | #include <svx/svdpagv.hxx> | ||||
32 | #include <svx/svdundo.hxx> | ||||
33 | #include <vcl/stdtext.hxx> | ||||
34 | #include <vcl/svapp.hxx> | ||||
35 | #include <vcl/weld.hxx> | ||||
36 | #include <xmloff/autolayout.hxx> | ||||
37 | |||||
38 | #include <strings.hrc> | ||||
39 | #include <drawdoc.hxx> | ||||
40 | #include <sdmod.hxx> | ||||
41 | #include <sdpage.hxx> | ||||
42 | #include <stlpool.hxx> | ||||
43 | #include <sdresid.hxx> | ||||
44 | #include <customshowlist.hxx> | ||||
45 | #include <sdxfer.hxx> | ||||
46 | |||||
47 | #include <unmovss.hxx> | ||||
48 | #include <unchss.hxx> | ||||
49 | #include <unprlout.hxx> | ||||
50 | #include <DrawDocShell.hxx> | ||||
51 | #include <GraphicDocShell.hxx> | ||||
52 | #include <ViewShell.hxx> | ||||
53 | #include <View.hxx> | ||||
54 | #include <ViewShellBase.hxx> | ||||
55 | #include <strings.hxx> | ||||
56 | |||||
57 | using namespace ::com::sun::star; | ||||
58 | |||||
59 | /** Concrete incarnations get called by lcl_IterateBookmarkPages, for | ||||
60 | every page in the bookmark document/list | ||||
61 | */ | ||||
62 | |||||
63 | namespace { | ||||
64 | |||||
65 | class InsertBookmarkAsPage_FindDuplicateLayouts | ||||
66 | { | ||||
67 | public: | ||||
68 | explicit InsertBookmarkAsPage_FindDuplicateLayouts( std::vector<OUString> &rLayoutsToTransfer ) | ||||
69 | : mrLayoutsToTransfer(rLayoutsToTransfer) {} | ||||
70 | void operator()( SdDrawDocument&, SdPage const *, bool, SdDrawDocument* ); | ||||
71 | private: | ||||
72 | std::vector<OUString> &mrLayoutsToTransfer; | ||||
73 | }; | ||||
74 | |||||
75 | } | ||||
76 | |||||
77 | void InsertBookmarkAsPage_FindDuplicateLayouts::operator()( SdDrawDocument& rDoc, SdPage const * pBMMPage, bool bRenameDuplicates, SdDrawDocument* pBookmarkDoc ) | ||||
78 | { | ||||
79 | // now check for duplicate masterpage and layout names | ||||
80 | |||||
81 | OUString aLayout( pBMMPage->GetLayoutName() ); | ||||
82 | sal_Int32 nIndex = aLayout.indexOf( SD_LT_SEPARATOR"~LT~" ); | ||||
83 | if( nIndex != -1 ) | ||||
84 | aLayout = aLayout.copy(0, nIndex); | ||||
85 | |||||
86 | std::vector<OUString>::const_iterator pIter = | ||||
87 | find(mrLayoutsToTransfer.begin(),mrLayoutsToTransfer.end(),aLayout); | ||||
88 | |||||
89 | bool bFound = pIter != mrLayoutsToTransfer.end(); | ||||
90 | |||||
91 | const sal_uInt16 nMPageCount = rDoc.GetMasterPageCount(); | ||||
92 | for (sal_uInt16 nMPage = 0; nMPage < nMPageCount && !bFound; nMPage++) | ||||
93 | { | ||||
94 | // Do the layouts already exist within the document? | ||||
95 | SdPage* pTestPage = static_cast<SdPage*>( rDoc.GetMasterPage(nMPage) ); | ||||
96 | OUString aTest(pTestPage->GetLayoutName()); | ||||
97 | sal_Int32 nIndex2 = aTest.indexOf( SD_LT_SEPARATOR"~LT~" ); | ||||
98 | if( nIndex2 != -1 ) | ||||
99 | aTest = aTest.copy(0, nIndex2); | ||||
100 | |||||
101 | if (aTest == aLayout && pBMMPage->GetPageKind() == pTestPage->GetPageKind()) | ||||
102 | { | ||||
103 | // Ignore Layouts with "Default" these seem to be special - in the sense that there are lot of assumption all over Impress | ||||
104 | // about this | ||||
105 | if( bRenameDuplicates && aTest != SdResId( STR_LAYOUT_DEFAULT_NAMEreinterpret_cast<char const *>("STR_LAYOUT_DEFAULT_NAME" "\004" u8"Default") ) && !(pTestPage->Equals(*pBMMPage)) ) | ||||
106 | { | ||||
107 | pBookmarkDoc->RenameLayoutTemplate( | ||||
108 | pBMMPage->GetLayoutName(), pBMMPage->GetName() + "_"); | ||||
109 | aLayout = pBMMPage->GetName(); | ||||
110 | |||||
111 | break; | ||||
112 | } | ||||
113 | else | ||||
114 | bFound = true; | ||||
115 | } | ||||
116 | } | ||||
117 | |||||
118 | if (!bFound) | ||||
119 | mrLayoutsToTransfer.push_back(aLayout); | ||||
120 | } | ||||
121 | |||||
122 | // Inserts a bookmark as a page | ||||
123 | static void lcl_IterateBookmarkPages( SdDrawDocument &rDoc, SdDrawDocument* pBookmarkDoc, | ||||
124 | const std::vector<OUString> &rBookmarkList, sal_uInt16 nBMSdPageCount, | ||||
125 | InsertBookmarkAsPage_FindDuplicateLayouts& rPageIterator, bool bRenameDuplicates ) | ||||
126 | { | ||||
127 | |||||
128 | // Refactored copy'n'pasted layout name collection from InsertBookmarkAsPage | ||||
129 | |||||
130 | int nPos, nEndPos; | ||||
131 | |||||
132 | if( rBookmarkList.empty() ) | ||||
133 | { | ||||
134 | // no list? whole source document | ||||
135 | nEndPos = nBMSdPageCount; | ||||
136 | } | ||||
137 | else | ||||
138 | { | ||||
139 | // bookmark list? number of entries | ||||
140 | nEndPos = rBookmarkList.size(); | ||||
141 | } | ||||
142 | |||||
143 | SdPage* pBMPage; | ||||
144 | |||||
145 | // iterate over number of pages to insert | ||||
146 | for (nPos = 0; nPos < nEndPos; ++nPos) | ||||
147 | { | ||||
148 | // the master page associated to the nPos'th page to insert | ||||
149 | SdPage* pBMMPage = nullptr; | ||||
150 | |||||
151 | if( rBookmarkList.empty() ) | ||||
152 | { | ||||
153 | // simply take master page of nPos'th page in source document | ||||
154 | pBMMPage = static_cast<SdPage*>(&(pBookmarkDoc->GetSdPage(static_cast<sal_uInt16>(nPos), PageKind::Standard)->TRG_GetMasterPage())); | ||||
155 | } | ||||
156 | else | ||||
157 | { | ||||
158 | // fetch nPos'th entry from bookmark list, and determine master page | ||||
159 | OUString aBMPgName(rBookmarkList[nPos]); | ||||
160 | bool bIsMasterPage; | ||||
161 | |||||
162 | sal_uInt16 nBMPage = pBookmarkDoc->GetPageByName( aBMPgName, bIsMasterPage ); | ||||
163 | |||||
164 | if (nBMPage != SDRPAGE_NOTFOUND0xFFFF) | ||||
165 | { | ||||
166 | pBMPage = static_cast<SdPage*>( pBookmarkDoc->GetPage(nBMPage) ); | ||||
167 | } | ||||
168 | else | ||||
169 | { | ||||
170 | pBMPage = nullptr; | ||||
171 | } | ||||
172 | |||||
173 | // enforce that bookmarked page is a standard page and not already a master page | ||||
174 | if (pBMPage && pBMPage->GetPageKind()==PageKind::Standard && !pBMPage->IsMasterPage()) | ||||
175 | { | ||||
176 | const sal_uInt16 nBMSdPage = (nBMPage - 1) / 2; | ||||
177 | pBMMPage = static_cast<SdPage*> (&(pBookmarkDoc->GetSdPage(nBMSdPage, PageKind::Standard)->TRG_GetMasterPage())); | ||||
178 | } | ||||
179 | } | ||||
180 | |||||
181 | // successfully determined valid (bookmarked) page? | ||||
182 | if( pBMMPage ) | ||||
183 | { | ||||
184 | // yes, call functor | ||||
185 | rPageIterator( rDoc, pBMMPage, bRenameDuplicates, pBookmarkDoc ); | ||||
186 | } | ||||
187 | } | ||||
188 | } | ||||
189 | |||||
190 | // Opens a bookmark document | ||||
191 | SdDrawDocument* SdDrawDocument::OpenBookmarkDoc(SfxMedium* pMedium) | ||||
192 | { | ||||
193 | bool bOK = true; | ||||
194 | SdDrawDocument* pBookmarkDoc = nullptr; | ||||
195 | OUString aBookmarkName = pMedium->GetName(); | ||||
196 | std::shared_ptr<const SfxFilter> pFilter = pMedium->GetFilter(); | ||||
197 | if ( !pFilter ) | ||||
198 | { | ||||
199 | pMedium->UseInteractionHandler( true ); | ||||
200 | SfxGetpApp()->GetFilterMatcher().GuessFilter(*pMedium, pFilter); | ||||
201 | } | ||||
202 | |||||
203 | if ( !pFilter ) | ||||
204 | { | ||||
205 | bOK = false; | ||||
206 | } | ||||
207 | else if ( !aBookmarkName.isEmpty() && maBookmarkFile != aBookmarkName ) | ||||
208 | { | ||||
209 | bool bCreateGraphicShell = pFilter->GetServiceName() == "com.sun.star.drawing.DrawingDocument"; | ||||
210 | bool bCreateImpressShell = pFilter->GetServiceName() == "com.sun.star.presentation.PresentationDocument"; | ||||
211 | if ( bCreateGraphicShell || bCreateImpressShell ) | ||||
212 | { | ||||
213 | CloseBookmarkDoc(); | ||||
214 | |||||
215 | // Create a DocShell, as OLE objects might be contained in the | ||||
216 | // document. (Persist) | ||||
217 | // If that wasn't the case, we could load the model directly. | ||||
218 | if ( bCreateGraphicShell ) | ||||
219 | // Draw | ||||
220 | mxBookmarkDocShRef = new ::sd::GraphicDocShell(SfxObjectCreateMode::STANDARD); | ||||
221 | else | ||||
222 | // Impress | ||||
223 | mxBookmarkDocShRef = new ::sd::DrawDocShell(SfxObjectCreateMode::STANDARD, true, DocumentType::Impress); | ||||
224 | |||||
225 | bOK = mxBookmarkDocShRef->DoLoad(pMedium); | ||||
226 | if( bOK ) | ||||
227 | { | ||||
228 | maBookmarkFile = aBookmarkName; | ||||
229 | pBookmarkDoc = mxBookmarkDocShRef->GetDoc(); | ||||
230 | } | ||||
231 | } | ||||
232 | } | ||||
233 | |||||
234 | DBG_ASSERT(!aBookmarkName.isEmpty(), "Empty document name!")do { if (true && (!(!aBookmarkName.isEmpty()))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/sd/source/core/drawdoc3.cxx" ":" "234" ": "), "%s", "Empty document name!"); } } while (false ); | ||||
235 | |||||
236 | if (!bOK) | ||||
237 | { | ||||
238 | std::unique_ptr<weld::MessageDialog> xErrorBox(Application::CreateMessageDialog(nullptr, | ||||
239 | VclMessageType::Warning, VclButtonsType::Ok, SdResId(STR_READ_DATA_ERRORreinterpret_cast<char const *>("STR_READ_DATA_ERROR" "\004" u8"The file could not be loaded!")))); | ||||
240 | xErrorBox->run(); | ||||
241 | |||||
242 | CloseBookmarkDoc(); | ||||
243 | pBookmarkDoc = nullptr; | ||||
244 | } | ||||
245 | else if (mxBookmarkDocShRef.is()) | ||||
246 | { | ||||
247 | pBookmarkDoc = mxBookmarkDocShRef->GetDoc(); | ||||
248 | } | ||||
249 | |||||
250 | return pBookmarkDoc; | ||||
251 | } | ||||
252 | |||||
253 | // Opens a bookmark document | ||||
254 | SdDrawDocument* SdDrawDocument::OpenBookmarkDoc(const OUString& rBookmarkFile) | ||||
255 | { | ||||
256 | SdDrawDocument* pBookmarkDoc = nullptr; | ||||
257 | |||||
258 | if (!rBookmarkFile.isEmpty() && maBookmarkFile != rBookmarkFile) | ||||
259 | { | ||||
260 | std::unique_ptr<SfxMedium> xMedium(new SfxMedium(rBookmarkFile, StreamMode::READ)); | ||||
261 | pBookmarkDoc = OpenBookmarkDoc(xMedium.release()); | ||||
262 | } | ||||
263 | else if (mxBookmarkDocShRef.is()) | ||||
264 | { | ||||
265 | pBookmarkDoc = mxBookmarkDocShRef->GetDoc(); | ||||
266 | } | ||||
267 | |||||
268 | return pBookmarkDoc; | ||||
269 | } | ||||
270 | |||||
271 | // Inserts a bookmark (page or object) | ||||
272 | void SdDrawDocument::InsertBookmark( | ||||
273 | const std::vector<OUString> &rBookmarkList, // List of names of the bookmarks to be inserted | ||||
274 | std::vector<OUString> &rExchangeList, // List of the names to be used | ||||
275 | bool bLink, // Insert bookmarks as links? | ||||
276 | sal_uInt16 nInsertPos, // Insertion position of pages | ||||
277 | ::sd::DrawDocShell* pBookmarkDocSh, // If set, this is the source document | ||||
278 | Point const * pObjPos) // Insertion position of objects | ||||
279 | { | ||||
280 | bool bOK = true; | ||||
281 | bool bInsertPages = false; | ||||
282 | |||||
283 | if (rBookmarkList.empty()) | ||||
284 | { | ||||
285 | // Insert all pages | ||||
286 | bInsertPages = true; | ||||
287 | } | ||||
288 | else | ||||
289 | { | ||||
290 | SdDrawDocument* pBookmarkDoc = nullptr; | ||||
291 | |||||
292 | if (pBookmarkDocSh) | ||||
293 | { | ||||
294 | pBookmarkDoc = pBookmarkDocSh->GetDoc(); | ||||
295 | } | ||||
296 | else if ( mxBookmarkDocShRef.is() ) | ||||
297 | { | ||||
298 | pBookmarkDoc = mxBookmarkDocShRef->GetDoc(); | ||||
299 | } | ||||
300 | else | ||||
301 | bOK = false; | ||||
302 | |||||
303 | bInsertPages = bOK && std::any_of(rBookmarkList.begin(), rBookmarkList.end(), | ||||
304 | [&pBookmarkDoc](const OUString& rBookmark) { | ||||
305 | // Is there a page name in the bookmark list? | ||||
306 | bool bIsMasterPage; | ||||
307 | return pBookmarkDoc->GetPageByName(rBookmark, bIsMasterPage) != SDRPAGE_NOTFOUND0xFFFF; | ||||
308 | }); | ||||
309 | } | ||||
310 | |||||
311 | bool bCalcObjCount = !rExchangeList.empty(); | ||||
312 | |||||
313 | if ( bOK && bInsertPages ) | ||||
314 | { | ||||
315 | // Insert all page bookmarks | ||||
316 | bOK = InsertBookmarkAsPage(rBookmarkList, &rExchangeList, bLink, false/*bReplace*/, | ||||
317 | nInsertPos, false/*bNoDialogs*/, pBookmarkDocSh, true/*bCopy*/, true, false); | ||||
318 | } | ||||
319 | |||||
320 | if ( bOK && !rBookmarkList.empty() ) | ||||
321 | { | ||||
322 | // Insert all object bookmarks | ||||
323 | InsertBookmarkAsObject(rBookmarkList, rExchangeList, | ||||
324 | pBookmarkDocSh, pObjPos, bCalcObjCount); | ||||
325 | } | ||||
326 | } | ||||
327 | |||||
328 | namespace | ||||
329 | { | ||||
330 | |||||
331 | void | ||||
332 | lcl_removeUnusedStyles(SfxStyleSheetBasePool* const pStyleSheetPool, StyleSheetCopyResultVector& rStyles) | ||||
333 | { | ||||
334 | StyleSheetCopyResultVector aUsedStyles; | ||||
335 | aUsedStyles.reserve(rStyles.size()); | ||||
336 | for (const auto& a : rStyles) | ||||
337 | { | ||||
338 | if (a.m_xStyleSheet->IsUsed()) | ||||
339 | aUsedStyles.push_back(a); | ||||
340 | else | ||||
341 | pStyleSheetPool->Remove(a.m_xStyleSheet.get()); | ||||
342 | } | ||||
343 | rStyles = aUsedStyles; | ||||
344 | } | ||||
345 | |||||
346 | SfxStyleSheet *lcl_findStyle(StyleSheetCopyResultVector& rStyles, const OUString& aStyleName) | ||||
347 | { | ||||
348 | for (const auto& a : rStyles) | ||||
349 | { | ||||
350 | if (a.m_xStyleSheet->GetName().startsWith(aStyleName)) | ||||
351 | return a.m_xStyleSheet.get(); | ||||
352 | } | ||||
353 | return nullptr; | ||||
354 | } | ||||
355 | |||||
356 | } | ||||
357 | |||||
358 | bool SdDrawDocument::InsertBookmarkAsPage( | ||||
359 | const std::vector<OUString> &rBookmarkList, | ||||
360 | std::vector<OUString> *pExchangeList, // List of names to be used | ||||
361 | bool bLink, | ||||
362 | bool bReplace, | ||||
363 | sal_uInt16 nInsertPos, | ||||
364 | bool bNoDialogs, | ||||
365 | ::sd::DrawDocShell* pBookmarkDocSh, | ||||
366 | bool bCopy, | ||||
367 | bool bMergeMasterPages, | ||||
368 | bool bPreservePageNames) | ||||
369 | { | ||||
370 | bool bContinue = true; | ||||
371 | bool bScaleObjects = false; | ||||
372 | sal_uInt16 nReplacedStandardPages = 0; | ||||
373 | |||||
374 | SdDrawDocument* pBookmarkDoc = nullptr; | ||||
375 | OUString aBookmarkName; | ||||
376 | |||||
377 | if (pBookmarkDocSh) | ||||
| |||||
378 | { | ||||
379 | pBookmarkDoc = pBookmarkDocSh->GetDoc(); | ||||
380 | |||||
381 | if (pBookmarkDocSh->GetMedium()) | ||||
382 | { | ||||
383 | aBookmarkName = pBookmarkDocSh->GetMedium()->GetName(); | ||||
384 | } | ||||
385 | } | ||||
386 | else if ( mxBookmarkDocShRef.is() ) | ||||
387 | { | ||||
388 | pBookmarkDoc = mxBookmarkDocShRef->GetDoc(); | ||||
389 | aBookmarkName = maBookmarkFile; | ||||
390 | } | ||||
391 | else | ||||
392 | { | ||||
393 | return false; | ||||
394 | } | ||||
395 | |||||
396 | const sal_uInt16 nSdPageCount = GetSdPageCount(PageKind::Standard); | ||||
397 | const sal_uInt16 nBMSdPageCount = pBookmarkDoc->GetSdPageCount(PageKind::Standard); | ||||
398 | const sal_uInt16 nMPageCount = GetMasterPageCount(); | ||||
399 | |||||
400 | if (nSdPageCount==0 || nBMSdPageCount==0 || nMPageCount==0) | ||||
401 | { | ||||
402 | return false; | ||||
403 | } | ||||
404 | |||||
405 | // Store the size and some other properties of the first page and notes | ||||
406 | // page so that inserted pages can be properly scaled even when inserted | ||||
407 | // before the first page. | ||||
408 | // Note that the pointers are used later on as general page pointers. | ||||
409 | SdPage* pRefPage = GetSdPage(0, PageKind::Standard); | ||||
410 | Size aSize(pRefPage->GetSize()); | ||||
411 | sal_Int32 nLeft = pRefPage->GetLeftBorder(); | ||||
412 | sal_Int32 nRight = pRefPage->GetRightBorder(); | ||||
413 | sal_Int32 nUpper = pRefPage->GetUpperBorder(); | ||||
414 | sal_Int32 nLower = pRefPage->GetLowerBorder(); | ||||
415 | Orientation eOrient = pRefPage->GetOrientation(); | ||||
416 | |||||
417 | SdPage* pNPage = GetSdPage(0, PageKind::Notes); | ||||
418 | Size aNSize(pNPage->GetSize()); | ||||
419 | sal_Int32 nNLeft = pNPage->GetLeftBorder(); | ||||
420 | sal_Int32 nNRight = pNPage->GetRightBorder(); | ||||
421 | sal_Int32 nNUpper = pNPage->GetUpperBorder(); | ||||
422 | sal_Int32 nNLower = pNPage->GetLowerBorder(); | ||||
423 | Orientation eNOrient = pNPage->GetOrientation(); | ||||
424 | |||||
425 | // Adapt page size and margins to those of the later pages? | ||||
426 | pRefPage = GetSdPage(nSdPageCount - 1, PageKind::Standard); | ||||
427 | |||||
428 | if( bNoDialogs ) | ||||
429 | { | ||||
430 | // If this is clipboard, then no need to scale objects: | ||||
431 | // this will make copied masters to differ from the originals, | ||||
432 | // and thus InsertBookmarkAsPage_FindDuplicateLayouts will | ||||
433 | // duplicate masters on insert to same document | ||||
434 | m_bTransportContainer = (SD_MOD()( static_cast<SdModule*>(SfxApplication::GetModule(SfxToolsModule ::Draw)) )->pTransferClip && | ||||
435 | SD_MOD()( static_cast<SdModule*>(SfxApplication::GetModule(SfxToolsModule ::Draw)) )->pTransferClip->GetWorkDocument() == this); | ||||
436 | if (!m_bTransportContainer) | ||||
437 | { | ||||
438 | if (rBookmarkList.empty()) | ||||
439 | bScaleObjects = pRefPage->IsScaleObjects(); | ||||
440 | else | ||||
441 | bScaleObjects = true; | ||||
442 | } | ||||
443 | } | ||||
444 | else | ||||
445 | { | ||||
446 | SdPage* pBMPage = pBookmarkDoc->GetSdPage(0,PageKind::Standard); | ||||
447 | |||||
448 | if (pBMPage->GetSize() != pRefPage->GetSize() || | ||||
449 | pBMPage->GetLeftBorder() != pRefPage->GetLeftBorder() || | ||||
450 | pBMPage->GetRightBorder() != pRefPage->GetRightBorder() || | ||||
451 | pBMPage->GetUpperBorder() != pRefPage->GetUpperBorder() || | ||||
452 | pBMPage->GetLowerBorder() != pRefPage->GetLowerBorder()) | ||||
453 | { | ||||
454 | OUString aStr(SdResId(STR_SCALE_OBJECTSreinterpret_cast<char const *>("STR_SCALE_OBJECTS" "\004" u8"The page size of the target document is different than the source document.\n\nDo you want to scale the copied objects to fit the new page size?" ))); | ||||
455 | std::unique_ptr<weld::MessageDialog> xQueryBox(Application::CreateMessageDialog(nullptr, | ||||
456 | VclMessageType::Question, VclButtonsType::YesNo, | ||||
457 | aStr)); | ||||
458 | xQueryBox->add_button(GetStandardText(StandardButtonType::Cancel), RET_CANCEL); | ||||
459 | sal_uInt16 nBut = xQueryBox->run(); | ||||
460 | |||||
461 | bScaleObjects = nBut == RET_YES; | ||||
462 | bContinue = nBut != RET_CANCEL; | ||||
463 | |||||
464 | if (!bContinue
| ||||
465 | { | ||||
466 | return bContinue; | ||||
467 | } | ||||
468 | } | ||||
469 | } | ||||
470 | |||||
471 | // Get the necessary presentation stylesheets and transfer them before | ||||
472 | // the pages, else, the text objects won't reference their styles anymore. | ||||
473 | SfxUndoManager* pUndoMgr = nullptr; | ||||
474 | if( mpDocSh ) | ||||
475 | { | ||||
476 | pUndoMgr = mpDocSh->GetUndoManager(); | ||||
477 | ViewShellId nViewShellId(-1); | ||||
478 | if (sd::ViewShell* pViewShell = mpDocSh->GetViewShell()) | ||||
479 | nViewShellId = pViewShell->GetViewShellBase().GetViewShellId(); | ||||
480 | pUndoMgr->EnterListAction(SdResId(STR_UNDO_INSERTPAGESreinterpret_cast<char const *>("STR_UNDO_INSERTPAGES" "\004" u8"Insert slides")), "", 0, nViewShellId); | ||||
481 | } | ||||
482 | |||||
483 | // Refactored copy'n'pasted layout name collection into IterateBookmarkPages | ||||
484 | |||||
485 | std::vector<OUString> aLayoutsToTransfer; | ||||
486 | InsertBookmarkAsPage_FindDuplicateLayouts aSearchFunctor( aLayoutsToTransfer ); | ||||
487 | lcl_IterateBookmarkPages( *this, pBookmarkDoc, rBookmarkList, nBMSdPageCount, aSearchFunctor, ( rBookmarkList.empty() && pBookmarkDoc != this ) ); | ||||
488 | |||||
489 | // Copy the style that we actually need. | ||||
490 | SdStyleSheetPool& rBookmarkStyleSheetPool = dynamic_cast<SdStyleSheetPool&>(*pBookmarkDoc->GetStyleSheetPool()); | ||||
491 | SdStyleSheetPool& rStyleSheetPool = dynamic_cast<SdStyleSheetPool&>(*GetStyleSheetPool()); | ||||
492 | |||||
493 | // When copying styles, also copy the master pages! | ||||
494 | if( !aLayoutsToTransfer.empty() ) | ||||
495 | bMergeMasterPages = true; | ||||
496 | |||||
497 | for ( const OUString& layoutName : aLayoutsToTransfer ) | ||||
498 | { | ||||
499 | StyleSheetCopyResultVector aCreatedStyles; | ||||
500 | |||||
501 | rStyleSheetPool.CopyLayoutSheets(layoutName, rBookmarkStyleSheetPool,aCreatedStyles); | ||||
502 | |||||
503 | if(!aCreatedStyles.empty()) | ||||
504 | { | ||||
505 | if( pUndoMgr ) | ||||
506 | { | ||||
507 | pUndoMgr->AddUndoAction(std::make_unique<SdMoveStyleSheetsUndoAction>(this, aCreatedStyles, true)); | ||||
508 | } | ||||
509 | } | ||||
510 | } | ||||
511 | |||||
512 | // Copy styles. This unconditionally copies all styles, even those | ||||
513 | // that are not used in any of the inserted pages. The unused styles | ||||
514 | // are then removed at the end of the function, where we also create | ||||
515 | // undo records for the inserted styles. | ||||
516 | StyleSheetCopyResultVector aNewGraphicStyles; | ||||
517 | OUString aRenameStr; | ||||
518 | if(!bReplace && !bNoDialogs) | ||||
519 | aRenameStr = "_"; | ||||
520 | rStyleSheetPool.RenameAndCopyGraphicSheets(rBookmarkStyleSheetPool, aNewGraphicStyles, aRenameStr); | ||||
521 | StyleSheetCopyResultVector aNewCellStyles; | ||||
522 | rStyleSheetPool.CopyCellSheets(rBookmarkStyleSheetPool, aNewCellStyles); | ||||
523 | |||||
524 | // TODO handle undo of table styles too | ||||
525 | rStyleSheetPool.CopyTableStyles(rBookmarkStyleSheetPool); | ||||
526 | |||||
527 | // Insert document | ||||
528 | |||||
529 | const bool bUndo = IsUndoEnabled(); | ||||
530 | |||||
531 | if( bUndo ) | ||||
532 | BegUndo(SdResId(STR_UNDO_INSERTPAGESreinterpret_cast<char const *>("STR_UNDO_INSERTPAGES" "\004" u8"Insert slides"))); | ||||
533 | |||||
534 | if (rBookmarkList.empty()) | ||||
535 | { | ||||
536 | if (nInsertPos >= GetPageCount()) | ||||
537 | { | ||||
538 | // Add pages to the end | ||||
539 | nInsertPos = GetPageCount(); | ||||
540 | } | ||||
541 | |||||
542 | sal_uInt16 nActualInsertPos = nInsertPos; | ||||
543 | |||||
544 | sal_uInt16 nBMSdPage; | ||||
545 | std::set<sal_uInt16> aRenameSet; | ||||
546 | std::map<sal_uInt16,OUString> aNameMap; | ||||
547 | |||||
548 | for (nBMSdPage=0; nBMSdPage < nBMSdPageCount; nBMSdPage++) | ||||
549 | { | ||||
550 | SdPage* pBMPage = pBookmarkDoc->GetSdPage(nBMSdPage, PageKind::Standard); | ||||
551 | OUString sName(pBMPage->GetName()); | ||||
552 | bool bIsMasterPage; | ||||
553 | |||||
554 | if (bLink) | ||||
555 | { | ||||
556 | // Remember the names of all pages | ||||
557 | aNameMap.insert(std::make_pair(nBMSdPage,sName)); | ||||
558 | } | ||||
559 | |||||
560 | // Have to check for duplicate names here, too | ||||
561 | // don't change name if source and dest model are the same! | ||||
562 | if( pBookmarkDoc != this && | ||||
563 | GetPageByName(sName, bIsMasterPage ) != SDRPAGE_NOTFOUND0xFFFF ) | ||||
564 | { | ||||
565 | // delay renaming *after* pages are copied (might destroy source otherwise) | ||||
566 | aRenameSet.insert(nBMSdPage); | ||||
567 | } | ||||
568 | } | ||||
569 | |||||
570 | Merge(*pBookmarkDoc, | ||||
571 | 1, // Not the handout page | ||||
572 | 0xFFFF, // But all others | ||||
573 | nActualInsertPos, // Insert at position ... | ||||
574 | bMergeMasterPages, // Move master pages? | ||||
575 | false, // But only the master pages used | ||||
576 | true, // Create an undo action | ||||
577 | bCopy); // Copy (or merge) pages? | ||||
578 | |||||
579 | for (nBMSdPage=0; nBMSdPage < nBMSdPageCount; nBMSdPage++) | ||||
580 | { | ||||
581 | SdPage* pPage = static_cast<SdPage*>( GetPage(nActualInsertPos) ); | ||||
582 | SdPage* pNotesPage = static_cast<SdPage*>( GetPage(nActualInsertPos+1) ); | ||||
583 | |||||
584 | // delay renaming *after* pages are copied (might destroy source otherwise) | ||||
585 | if( aRenameSet.find(nBMSdPage) != aRenameSet.end() ) | ||||
586 | { | ||||
587 | // Page name already in use -> Use default name for default and | ||||
588 | // notes page | ||||
589 | pPage->SetName(OUString()); | ||||
590 | pNotesPage->SetName(OUString()); | ||||
591 | } | ||||
592 | |||||
593 | if (bLink) | ||||
594 | { | ||||
595 | OUString aName(aNameMap[nBMSdPage]); | ||||
596 | |||||
597 | // Assemble all link names | ||||
598 | pPage->SetFileName(aBookmarkName); | ||||
599 | pPage->SetBookmarkName(aName); | ||||
600 | } | ||||
601 | |||||
602 | nActualInsertPos += 2; | ||||
603 | } | ||||
604 | } | ||||
605 | else | ||||
606 | { | ||||
607 | // Insert selected pages | ||||
608 | SdPage* pBMPage; | ||||
609 | |||||
610 | if (nInsertPos >= GetPageCount()) | ||||
611 | { | ||||
612 | // Add pages to the end | ||||
613 | bReplace = false; | ||||
614 | nInsertPos = GetPageCount(); | ||||
615 | } | ||||
616 | |||||
617 | sal_uInt16 nActualInsertPos = nInsertPos; | ||||
618 | |||||
619 | // Collect the bookmarked pages | ||||
620 | ::std::vector<SdPage*> aBookmarkedPages (rBookmarkList.size(), nullptr); | ||||
621 | for ( size_t nPos = 0, n = rBookmarkList.size(); nPos < n; ++nPos) | ||||
622 | { | ||||
623 | OUString aPgName(rBookmarkList[nPos]); | ||||
624 | bool bIsMasterPage; | ||||
625 | sal_uInt16 nBMPage = pBookmarkDoc->GetPageByName( aPgName, bIsMasterPage ); | ||||
626 | |||||
627 | if (nBMPage != SDRPAGE_NOTFOUND0xFFFF) | ||||
628 | { | ||||
629 | aBookmarkedPages[nPos] = dynamic_cast<SdPage*>(pBookmarkDoc->GetPage(nBMPage)); | ||||
630 | } | ||||
631 | } | ||||
632 | |||||
633 | for ( size_t nPos = 0, n = rBookmarkList.size(); nPos < n; ++nPos) | ||||
634 | { | ||||
635 | pBMPage = aBookmarkedPages[nPos]; | ||||
636 | sal_uInt16 nBMPage = pBMPage!=nullptr ? pBMPage->GetPageNum() : SDRPAGE_NOTFOUND0xFFFF; | ||||
637 | |||||
638 | if (pBMPage
| ||||
639 | { | ||||
640 | // It has to be a default page | ||||
641 | bool bMustRename = false; | ||||
642 | |||||
643 | // delay renaming *after* pages are copied (might destroy source otherwise) | ||||
644 | // don't change name if source and dest model are the same! | ||||
645 | // avoid renaming if replacing the same page | ||||
646 | OUString aPgName(rBookmarkList[nPos]); | ||||
647 | bool bIsMasterPage; | ||||
648 | sal_uInt16 nPageSameName = GetPageByName(aPgName, bIsMasterPage); | ||||
649 | if( pBookmarkDoc != this && | ||||
650 | nPageSameName != SDRPAGE_NOTFOUND0xFFFF && | ||||
651 | ( !bReplace || | ||||
652 | nPageSameName != nActualInsertPos ) ) | ||||
653 | { | ||||
654 | bMustRename = true; | ||||
655 | } | ||||
656 | |||||
657 | SdPage* pBookmarkPage = pBMPage; | ||||
658 | if (bReplace
| ||||
659 | { | ||||
660 | ReplacePageInCustomShows( dynamic_cast< SdPage* >( GetPage( nActualInsertPos ) ), pBookmarkPage ); | ||||
661 | } | ||||
662 | |||||
663 | Merge(*pBookmarkDoc, | ||||
664 | nBMPage, // From page (default page) | ||||
665 | nBMPage+1, // To page (notes page) | ||||
666 | nActualInsertPos, // Insert at position | ||||
667 | bMergeMasterPages, // Move master pages? | ||||
668 | false, // But only the master pages used | ||||
669 | true, // Create undo action | ||||
670 | bCopy); // Copy (or merge) pages? | ||||
671 | |||||
672 | if( bReplace
| ||||
673 | { | ||||
674 | if( GetPage( nActualInsertPos ) != pBookmarkPage ) | ||||
675 | { | ||||
676 | // bookmark page was not moved but cloned, so update custom shows again | ||||
677 | ReplacePageInCustomShows( pBookmarkPage, dynamic_cast< SdPage* >( GetPage( nActualInsertPos ) ) ); | ||||
678 | } | ||||
679 | } | ||||
680 | |||||
681 | if( bMustRename
| ||||
682 | { | ||||
683 | // Page name already in use -> use default name for default and | ||||
684 | // notes page | ||||
685 | SdPage* pPage = static_cast<SdPage*>( GetPage(nActualInsertPos) ); | ||||
686 | pPage->SetName(OUString()); | ||||
687 | SdPage* pNotesPage = static_cast<SdPage*>( GetPage(nActualInsertPos+1) ); | ||||
688 | pNotesPage->SetName(OUString()); | ||||
689 | } | ||||
690 | |||||
691 | if (bLink) | ||||
692 | { | ||||
693 | SdPage* pPage = static_cast<SdPage*>( GetPage(nActualInsertPos) ); | ||||
694 | pPage->SetFileName(aBookmarkName); | ||||
695 | pPage->SetBookmarkName(aPgName); | ||||
696 | } | ||||
697 | |||||
698 | if (bReplace
| ||||
699 | { | ||||
700 | // Remove page and notes page. | ||||
701 | const sal_uInt16 nDestPageNum(nActualInsertPos + 2); | ||||
702 | SdPage* pStandardPage = nullptr; | ||||
703 | |||||
704 | if(nDestPageNum < GetPageCount()) | ||||
705 | { | ||||
706 | pStandardPage = static_cast<SdPage*>(GetPage(nDestPageNum)); | ||||
707 | } | ||||
708 | |||||
709 | if (pStandardPage
| ||||
710 | { | ||||
711 | if( bPreservePageNames ) | ||||
712 | { | ||||
713 | // Take old slide names for inserted pages | ||||
714 | SdPage* pPage = static_cast<SdPage*>( GetPage(nActualInsertPos) ); | ||||
715 | pPage->SetName( pStandardPage->GetRealName() ); | ||||
716 | } | ||||
717 | |||||
718 | if( bUndo ) | ||||
719 | AddUndo(GetSdrUndoFactory().CreateUndoDeletePage(*pStandardPage)); | ||||
720 | |||||
721 | RemovePage(nDestPageNum); | ||||
722 | |||||
723 | if( !bUndo ) | ||||
724 | delete pStandardPage; | ||||
725 | } | ||||
726 | |||||
727 | SdPage* pNotesPage = nullptr; | ||||
728 | |||||
729 | if(nDestPageNum < GetPageCount()) | ||||
730 | { | ||||
731 | pNotesPage = static_cast<SdPage*>(GetPage(nDestPageNum)); | ||||
732 | } | ||||
733 | |||||
734 | if (pNotesPage) | ||||
735 | { | ||||
736 | if( bPreservePageNames ) | ||||
737 | { | ||||
738 | // Take old slide names for inserted pages | ||||
739 | SdPage* pNewNotesPage = static_cast<SdPage*>( GetPage(nActualInsertPos+1)); | ||||
740 | if( pNewNotesPage ) | ||||
741 | pNewNotesPage->SetName( pStandardPage->GetRealName() ); | ||||
| |||||
742 | } | ||||
743 | |||||
744 | if( bUndo ) | ||||
745 | AddUndo(GetSdrUndoFactory().CreateUndoDeletePage(*pNotesPage)); | ||||
746 | |||||
747 | RemovePage(nDestPageNum); | ||||
748 | |||||
749 | if( !bUndo ) | ||||
750 | delete pNotesPage; | ||||
751 | } | ||||
752 | |||||
753 | nReplacedStandardPages++; | ||||
754 | } | ||||
755 | |||||
756 | nActualInsertPos += 2; | ||||
757 | } | ||||
758 | } | ||||
759 | } | ||||
760 | |||||
761 | // We might have duplicate master pages now, as the drawing engine does not | ||||
762 | // recognize duplicates. Remove these now. | ||||
763 | sal_uInt16 nNewMPageCount = GetMasterPageCount(); | ||||
764 | |||||
765 | // Go backwards, so the numbers don't become messed up | ||||
766 | for (sal_uInt16 nPage = nNewMPageCount - 1; nPage >= nMPageCount; nPage--) | ||||
767 | { | ||||
768 | pRefPage = static_cast<SdPage*>( GetMasterPage(nPage) ); | ||||
769 | OUString aMPLayout(pRefPage->GetLayoutName()); | ||||
770 | PageKind eKind = pRefPage->GetPageKind(); | ||||
771 | |||||
772 | // Does this already exist? | ||||
773 | for (sal_uInt16 nTest = 0; nTest < nMPageCount; nTest++) | ||||
774 | { | ||||
775 | SdPage* pTest = static_cast<SdPage*>( GetMasterPage(nTest) ); | ||||
776 | OUString aTest(pTest->GetLayoutName()); | ||||
777 | |||||
778 | // nInsertPos > 2 is always true when inserting into non-empty models | ||||
779 | if ( nInsertPos > 2 && | ||||
780 | aTest == aMPLayout && | ||||
781 | eKind == pTest->GetPageKind() ) | ||||
782 | { | ||||
783 | if( bUndo ) | ||||
784 | AddUndo(GetSdrUndoFactory().CreateUndoDeletePage(*pRefPage)); | ||||
785 | |||||
786 | RemoveMasterPage(nPage); | ||||
787 | |||||
788 | if( !bUndo ) | ||||
789 | delete pRefPage; | ||||
790 | nNewMPageCount--; | ||||
791 | break; | ||||
792 | } | ||||
793 | } | ||||
794 | } | ||||
795 | |||||
796 | // nInsertPos > 2 is always true when inserting into non-empty models | ||||
797 | if (nInsertPos > 0) | ||||
798 | { | ||||
799 | sal_uInt16 nSdPageStart = (nInsertPos - 1) / 2; | ||||
800 | sal_uInt16 nSdPageEnd = bReplace | ||||
801 | ? nSdPageStart + nReplacedStandardPages - 1 | ||||
802 | : GetSdPageCount(PageKind::Standard) - nSdPageCount + nSdPageStart - 1; | ||||
803 | const bool bRemoveEmptyPresObj = | ||||
804 | (pBookmarkDoc->GetDocumentType() == DocumentType::Impress) && | ||||
805 | (GetDocumentType() == DocumentType::Draw); | ||||
806 | |||||
807 | std::vector<OUString>::iterator pExchangeIter; | ||||
808 | |||||
809 | if (pExchangeList) | ||||
810 | pExchangeIter = pExchangeList->begin(); | ||||
811 | |||||
812 | for (sal_uInt16 nSdPage = nSdPageStart; nSdPage <= nSdPageEnd; nSdPage++) | ||||
813 | { | ||||
814 | pRefPage = GetSdPage(nSdPage, PageKind::Standard); | ||||
815 | |||||
816 | if (pExchangeList && pExchangeIter != pExchangeList->end()) | ||||
817 | { | ||||
818 | // Get the name to use from Exchange list | ||||
819 | OUString aExchangeName(*pExchangeIter); | ||||
820 | pRefPage->SetName(aExchangeName); | ||||
821 | Broadcast(SdrHint(SdrHintKind::PageOrderChange, pRefPage)); | ||||
822 | |||||
823 | SdPage* pNewNotesPage = GetSdPage(nSdPage, PageKind::Notes); | ||||
824 | pNewNotesPage->SetName(aExchangeName); | ||||
825 | Broadcast(SdrHint(SdrHintKind::PageOrderChange, pNewNotesPage)); | ||||
826 | |||||
827 | ++pExchangeIter; | ||||
828 | } | ||||
829 | |||||
830 | OUString aLayout(pRefPage->GetLayoutName()); | ||||
831 | sal_Int32 nIndex = aLayout.indexOf( SD_LT_SEPARATOR"~LT~" ); | ||||
832 | if( nIndex != -1 ) | ||||
833 | aLayout = aLayout.copy(0, nIndex); | ||||
834 | |||||
835 | // update layout and referred master page | ||||
836 | pRefPage->SetPresentationLayout(aLayout); | ||||
837 | if( bUndo ) | ||||
838 | AddUndo( GetSdrUndoFactory().CreateUndoPageChangeMasterPage( *pRefPage ) ); | ||||
839 | |||||
840 | if (bScaleObjects) | ||||
841 | { | ||||
842 | ::tools::Rectangle aBorderRect(nLeft, nUpper, nRight, nLower); | ||||
843 | pRefPage->ScaleObjects(aSize, aBorderRect, true); | ||||
844 | } | ||||
845 | pRefPage->SetSize(aSize); | ||||
846 | pRefPage->SetBorder(nLeft, nUpper, nRight, nLower); | ||||
847 | pRefPage->SetOrientation( eOrient ); | ||||
848 | |||||
849 | if( bRemoveEmptyPresObj ) | ||||
850 | pRefPage->RemoveEmptyPresentationObjects(); | ||||
851 | |||||
852 | pRefPage = GetSdPage(nSdPage, PageKind::Notes); | ||||
853 | |||||
854 | // update layout and referred master page | ||||
855 | pRefPage->SetPresentationLayout(aLayout); | ||||
856 | if( bUndo ) | ||||
857 | AddUndo( GetSdrUndoFactory().CreateUndoPageChangeMasterPage( *pRefPage ) ); | ||||
858 | |||||
859 | if (bScaleObjects) | ||||
860 | { | ||||
861 | ::tools::Rectangle aBorderRect(nNLeft, nNUpper, nNRight, nNLower); | ||||
862 | pRefPage->ScaleObjects(aNSize, aBorderRect, true); | ||||
863 | } | ||||
864 | |||||
865 | pRefPage->SetSize(aNSize); | ||||
866 | pRefPage->SetBorder(nNLeft, nNUpper, nNRight, nNLower); | ||||
867 | pRefPage->SetOrientation( eNOrient ); | ||||
868 | |||||
869 | if( bRemoveEmptyPresObj ) | ||||
870 | pRefPage->RemoveEmptyPresentationObjects(); | ||||
871 | } | ||||
872 | |||||
873 | ///Remove processed elements, to avoid doing hacks in InsertBookmarkAsObject | ||||
874 | if ( pExchangeList ) | ||||
875 | pExchangeList->erase(pExchangeList->begin(),pExchangeIter); | ||||
876 | |||||
877 | for (sal_uInt16 nPage = nMPageCount; nPage < nNewMPageCount; nPage++) | ||||
878 | { | ||||
879 | pRefPage = static_cast<SdPage*>( GetMasterPage(nPage) ); | ||||
880 | if (pRefPage->GetPageKind() == PageKind::Standard) | ||||
881 | { | ||||
882 | if (bScaleObjects) | ||||
883 | { | ||||
884 | ::tools::Rectangle aBorderRect(nLeft, nUpper, nRight, nLower); | ||||
885 | pRefPage->ScaleObjects(aSize, aBorderRect, true); | ||||
886 | } | ||||
887 | pRefPage->SetSize(aSize); | ||||
888 | pRefPage->SetBorder(nLeft, nUpper, nRight, nLower); | ||||
889 | pRefPage->SetOrientation( eOrient ); | ||||
890 | } | ||||
891 | else // Can only be notes | ||||
892 | { | ||||
893 | if (bScaleObjects) | ||||
894 | { | ||||
895 | ::tools::Rectangle aBorderRect(nNLeft, nNUpper, nNRight, nNLower); | ||||
896 | pRefPage->ScaleObjects(aNSize, aBorderRect, true); | ||||
897 | } | ||||
898 | pRefPage->SetSize(aNSize); | ||||
899 | pRefPage->SetBorder(nNLeft, nNUpper, nNRight, nNLower); | ||||
900 | pRefPage->SetOrientation( eNOrient ); | ||||
901 | } | ||||
902 | |||||
903 | if( bRemoveEmptyPresObj ) | ||||
904 | pRefPage->RemoveEmptyPresentationObjects(); | ||||
905 | } | ||||
906 | } | ||||
907 | |||||
908 | // Make absolutely sure no double masterpages are there | ||||
909 | RemoveUnnecessaryMasterPages(nullptr, true); | ||||
910 | |||||
911 | // Rename object styles if necessary | ||||
912 | if(!aRenameStr.isEmpty()) | ||||
913 | { | ||||
914 | try | ||||
915 | { | ||||
916 | for(sal_uInt32 p = nInsertPos; p < sal_uInt32(nInsertPos) + sal_uInt32(nBMSdPageCount); p++) | ||||
917 | { | ||||
918 | SdPage *pPg = static_cast<SdPage *>( GetPage(p) ); | ||||
919 | for(size_t i = 0; pPg && (i < pPg->GetObjCount()); ++i) | ||||
920 | { | ||||
921 | if(pPg->GetObj(i)->GetStyleSheet()) | ||||
922 | { | ||||
923 | OUString aStyleName = pPg->GetObj(i)->GetStyleSheet()->GetName(); | ||||
924 | SfxStyleSheet *pSheet = lcl_findStyle(aNewGraphicStyles, aStyleName + aRenameStr); | ||||
925 | if(pSheet != nullptr) | ||||
926 | pPg->GetObj(i)->SetStyleSheet(pSheet, true); | ||||
927 | } | ||||
928 | } | ||||
929 | } | ||||
930 | } | ||||
931 | catch(...) | ||||
932 | { | ||||
933 | OSL_FAIL("Exception while renaming styles @ SdDrawDocument::InsertBookmarkAsPage")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sd/source/core/drawdoc3.cxx" ":" "933" ": "), "%s", "Exception while renaming styles @ SdDrawDocument::InsertBookmarkAsPage" ); } } while (false); | ||||
934 | } | ||||
935 | } | ||||
936 | // remove copied styles not used on any inserted page and create | ||||
937 | // undo records | ||||
938 | // WARNING: SdMoveStyleSheetsUndoAction clears the passed list of | ||||
939 | // styles, so it cannot be used after this point | ||||
940 | lcl_removeUnusedStyles(GetStyleSheetPool(), aNewGraphicStyles); | ||||
941 | if (!aNewGraphicStyles.empty() && pUndoMgr) | ||||
942 | pUndoMgr->AddUndoAction(std::make_unique<SdMoveStyleSheetsUndoAction>(this, aNewGraphicStyles, true)); | ||||
943 | lcl_removeUnusedStyles(GetStyleSheetPool(), aNewCellStyles); | ||||
944 | if (!aNewCellStyles.empty() && pUndoMgr) | ||||
945 | pUndoMgr->AddUndoAction(std::make_unique<SdMoveStyleSheetsUndoAction>(this, aNewCellStyles, true)); | ||||
946 | |||||
947 | if( bUndo ) | ||||
948 | EndUndo(); | ||||
949 | |||||
950 | if (pUndoMgr) | ||||
951 | pUndoMgr->LeaveListAction(); | ||||
952 | |||||
953 | return bContinue; | ||||
954 | } | ||||
955 | |||||
956 | // Inserts a bookmark as an object | ||||
957 | bool SdDrawDocument::InsertBookmarkAsObject( | ||||
958 | const std::vector<OUString> &rBookmarkList, | ||||
959 | const std::vector<OUString> &rExchangeList, // List of names to use | ||||
960 | ::sd::DrawDocShell* pBookmarkDocSh, | ||||
961 | Point const * pObjPos, | ||||
962 | bool bCalcObjCount) | ||||
963 | { | ||||
964 | bool bOK = true; | ||||
965 | bool bOLEObjFound = false; | ||||
966 | std::unique_ptr<::sd::View> pBMView; | ||||
967 | |||||
968 | SdDrawDocument* pBookmarkDoc = nullptr; | ||||
969 | |||||
970 | if (pBookmarkDocSh) | ||||
971 | { | ||||
972 | pBookmarkDoc = pBookmarkDocSh->GetDoc(); | ||||
973 | } | ||||
974 | else if ( mxBookmarkDocShRef.is() ) | ||||
975 | { | ||||
976 | pBookmarkDoc = mxBookmarkDocShRef->GetDoc(); | ||||
977 | } | ||||
978 | else | ||||
979 | { | ||||
980 | return false; | ||||
981 | } | ||||
982 | |||||
983 | if (rBookmarkList.empty()) | ||||
984 | { | ||||
985 | pBMView.reset(new ::sd::View(*pBookmarkDoc, nullptr)); | ||||
986 | pBMView->EndListening(*pBookmarkDoc); | ||||
987 | pBMView->MarkAll(); | ||||
988 | } | ||||
989 | else | ||||
990 | { | ||||
991 | SdrPage* pPage; | ||||
992 | SdrPageView* pPV; | ||||
993 | |||||
994 | for ( const auto& rBookmark : rBookmarkList ) | ||||
995 | { | ||||
996 | // Get names of bookmarks from the list | ||||
997 | SdrObject* pObj = pBookmarkDoc->GetObj(rBookmark); | ||||
998 | |||||
999 | if (pObj) | ||||
1000 | { | ||||
1001 | // Found an object | ||||
1002 | if (pObj->GetObjInventor() == SdrInventor::Default && | ||||
1003 | pObj->GetObjIdentifier() == OBJ_OLE2) | ||||
1004 | { | ||||
1005 | bOLEObjFound = true; | ||||
1006 | } | ||||
1007 | |||||
1008 | if (!pBMView) | ||||
1009 | { | ||||
1010 | // Create View for the first time | ||||
1011 | pBMView.reset(new ::sd::View(*pBookmarkDoc, nullptr)); | ||||
1012 | pBMView->EndListening(*pBookmarkDoc); | ||||
1013 | } | ||||
1014 | |||||
1015 | pPage = pObj->getSdrPageFromSdrObject(); | ||||
1016 | |||||
1017 | if (pPage->IsMasterPage()) | ||||
1018 | { | ||||
1019 | pPV = pBMView->ShowSdrPage(pBMView->GetModel()->GetMasterPage(pPage->GetPageNum())); | ||||
1020 | } | ||||
1021 | else | ||||
1022 | { | ||||
1023 | pPV = pBMView->GetSdrPageView(); | ||||
1024 | if( !pPV || (pPV->GetPage() != pPage)) | ||||
1025 | pPV = pBMView->ShowSdrPage(pPage); | ||||
1026 | } | ||||
1027 | |||||
1028 | pBMView->MarkObj(pObj, pPV); | ||||
1029 | } | ||||
1030 | } | ||||
1031 | } | ||||
1032 | |||||
1033 | if (pBMView) | ||||
1034 | { | ||||
1035 | // Insert selected objects | ||||
1036 | std::unique_ptr<::sd::View> pView(new ::sd::View(*this, nullptr)); | ||||
1037 | pView->EndListening(*this); | ||||
1038 | |||||
1039 | // Look for the page into which the objects are supposed to be inserted | ||||
1040 | SdrPage* pPage = GetSdPage(0, PageKind::Standard); | ||||
1041 | |||||
1042 | if (mpDocSh) | ||||
1043 | { | ||||
1044 | ::sd::ViewShell* pViewSh = mpDocSh->GetViewShell(); | ||||
1045 | |||||
1046 | if (pViewSh) | ||||
1047 | { | ||||
1048 | // Which page is currently in view? | ||||
1049 | SdrPageView* pPV = pViewSh->GetView()->GetSdrPageView(); | ||||
1050 | |||||
1051 | if (pPV) | ||||
1052 | { | ||||
1053 | pPage = pPV->GetPage(); | ||||
1054 | } | ||||
1055 | else if (pViewSh->GetActualPage()) | ||||
1056 | { | ||||
1057 | pPage = pViewSh->GetActualPage(); | ||||
1058 | } | ||||
1059 | } | ||||
1060 | } | ||||
1061 | |||||
1062 | Point aObjPos; | ||||
1063 | |||||
1064 | if (pObjPos) | ||||
1065 | { | ||||
1066 | aObjPos = *pObjPos; | ||||
1067 | } | ||||
1068 | else | ||||
1069 | { | ||||
1070 | aObjPos = ::tools::Rectangle(Point(), pPage->GetSize()).Center(); | ||||
1071 | } | ||||
1072 | |||||
1073 | size_t nCountBefore = 0; | ||||
1074 | |||||
1075 | if (!rExchangeList.empty() || bCalcObjCount) | ||||
1076 | { | ||||
1077 | // Sort OrdNums and get the number of objects before inserting | ||||
1078 | pPage->RecalcObjOrdNums(); | ||||
1079 | nCountBefore = pPage->GetObjCount(); | ||||
1080 | } | ||||
1081 | |||||
1082 | if (bOLEObjFound) | ||||
1083 | pBMView->GetDoc().SetAllocDocSh(true); | ||||
1084 | |||||
1085 | SdDrawDocument* pTmpDoc = static_cast<SdDrawDocument*>( pBMView->CreateMarkedObjModel().release() ); | ||||
1086 | bOK = pView->Paste(*pTmpDoc, aObjPos, pPage, SdrInsertFlags::NONE); | ||||
1087 | |||||
1088 | if (bOLEObjFound) | ||||
1089 | pBMView->GetDoc().SetAllocDocSh(false); | ||||
1090 | |||||
1091 | if (!bOLEObjFound) | ||||
1092 | delete pTmpDoc; // Would otherwise be destroyed by DocShell | ||||
1093 | |||||
1094 | pView.reset(); | ||||
1095 | |||||
1096 | // Get number of objects after inserting. | ||||
1097 | const size_t nCount = pPage->GetObjCount(); | ||||
1098 | if (nCountBefore < nCount) | ||||
1099 | { | ||||
1100 | size_t nObj = nCountBefore; | ||||
1101 | for (const auto& rExchange : rExchangeList) | ||||
1102 | { | ||||
1103 | // Get the name to use from the Exchange list | ||||
1104 | if (pPage->GetObj(nObj)) | ||||
1105 | { | ||||
1106 | pPage->GetObj(nObj)->SetName(rExchange); | ||||
1107 | } | ||||
1108 | |||||
1109 | ++nObj; | ||||
1110 | if (nObj >= nCount) | ||||
1111 | break; | ||||
1112 | } | ||||
1113 | } | ||||
1114 | } | ||||
1115 | |||||
1116 | return bOK; | ||||
1117 | } | ||||
1118 | |||||
1119 | // Stops the bookmark insertion | ||||
1120 | void SdDrawDocument::CloseBookmarkDoc() | ||||
1121 | { | ||||
1122 | if (mxBookmarkDocShRef.is()) | ||||
1123 | { | ||||
1124 | mxBookmarkDocShRef->DoClose(); | ||||
1125 | } | ||||
1126 | |||||
1127 | mxBookmarkDocShRef.clear(); | ||||
1128 | maBookmarkFile.clear(); | ||||
1129 | } | ||||
1130 | |||||
1131 | // Is this document read-only? | ||||
1132 | bool SdDrawDocument::IsReadOnly() const | ||||
1133 | { | ||||
1134 | return false; | ||||
1135 | } | ||||
1136 | |||||
1137 | // In the subsequent AllocModel() a DocShell (xAllocedDocShRef) is created. | ||||
1138 | // Any pre-existing DocShell is deleted | ||||
1139 | void SdDrawDocument::SetAllocDocSh(bool bAlloc) | ||||
1140 | { | ||||
1141 | mbAllocDocSh = bAlloc; | ||||
1142 | |||||
1143 | if(mxAllocedDocShRef.is()) | ||||
1144 | { | ||||
1145 | mxAllocedDocShRef->DoClose(); | ||||
1146 | } | ||||
1147 | |||||
1148 | mxAllocedDocShRef.clear(); | ||||
1149 | } | ||||
1150 | |||||
1151 | // Return list of CustomShows (create it, too, if necessary) | ||||
1152 | SdCustomShowList* SdDrawDocument::GetCustomShowList(bool bCreate) | ||||
1153 | { | ||||
1154 | if (!mpCustomShowList && bCreate) | ||||
1155 | { | ||||
1156 | mpCustomShowList.reset(new SdCustomShowList); | ||||
1157 | } | ||||
1158 | |||||
1159 | return mpCustomShowList.get(); | ||||
1160 | } | ||||
1161 | |||||
1162 | // Remove unused master pages and layouts | ||||
1163 | void SdDrawDocument::RemoveUnnecessaryMasterPages(SdPage* pMasterPage, bool bOnlyDuplicatePages, bool bUndo) | ||||
1164 | { | ||||
1165 | ::sd::View* pView = nullptr; | ||||
1166 | SfxUndoManager* pUndoMgr = nullptr; | ||||
1167 | |||||
1168 | if( bUndo && !IsUndoEnabled() ) | ||||
1169 | bUndo = false; | ||||
1170 | |||||
1171 | if (mpDocSh) | ||||
1172 | { | ||||
1173 | pUndoMgr = mpDocSh->GetUndoManager(); | ||||
1174 | |||||
1175 | if (mpDocSh->GetViewShell()) | ||||
1176 | pView = mpDocSh->GetViewShell()->GetView(); | ||||
1177 | } | ||||
1178 | |||||
1179 | // Check all master pages | ||||
1180 | sal_uInt16 nSdMasterPageCount = GetMasterSdPageCount( PageKind::Standard ); | ||||
1181 | for (sal_Int32 nMPage = nSdMasterPageCount - 1; nMPage >= 0; nMPage--) | ||||
1182 | { | ||||
1183 | SdPage* pMaster = pMasterPage; | ||||
1184 | SdPage* pNotesMaster = nullptr; | ||||
1185 | |||||
1186 | if (!pMaster) | ||||
1187 | { | ||||
1188 | pMaster = GetMasterSdPage( static_cast<sal_uInt16>(nMPage), PageKind::Standard ); | ||||
1189 | pNotesMaster = GetMasterSdPage( static_cast<sal_uInt16>(nMPage), PageKind::Notes ); | ||||
1190 | } | ||||
1191 | else | ||||
1192 | { | ||||
1193 | for ( sal_uInt16 nMPg = 0; nMPg < GetMasterPageCount(); nMPg++ ) | ||||
1194 | { | ||||
1195 | if ( pMaster == GetMasterPage( nMPg ) ) | ||||
1196 | { | ||||
1197 | pNotesMaster = static_cast<SdPage*>( GetMasterPage( ++nMPg ) ); | ||||
1198 | break; | ||||
1199 | } | ||||
1200 | } | ||||
1201 | } | ||||
1202 | |||||
1203 | DBG_ASSERT( pMaster->GetPageKind() == PageKind::Standard, "wrong page kind" )do { if (true && (!(pMaster->GetPageKind() == PageKind ::Standard))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN ), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/sd/source/core/drawdoc3.cxx" ":" "1203" ": "), "%s", "wrong page kind"); } } while (false ); | ||||
1204 | |||||
1205 | if ( pMaster->GetPageKind() == PageKind::Standard && | ||||
1206 | GetMasterPageUserCount( pMaster ) == 0 && | ||||
1207 | pNotesMaster ) | ||||
1208 | { | ||||
1209 | // Do not delete master pages that have their precious flag set | ||||
1210 | bool bDeleteMaster = !pMaster->IsPrecious(); | ||||
1211 | OUString aLayoutName = pMaster->GetLayoutName(); | ||||
1212 | |||||
1213 | if(bOnlyDuplicatePages ) | ||||
1214 | { | ||||
1215 | // remove only duplicate pages | ||||
1216 | bDeleteMaster = false; | ||||
1217 | for (sal_uInt16 i = 0; i < GetMasterSdPageCount( PageKind::Standard ); i++) | ||||
1218 | { | ||||
1219 | SdPage* pMPg = GetMasterSdPage( i, PageKind::Standard ); | ||||
1220 | if( pMPg != pMaster && | ||||
1221 | pMPg->GetLayoutName() == aLayoutName ) | ||||
1222 | { | ||||
1223 | // duplicate page found -> remove it | ||||
1224 | bDeleteMaster = true; | ||||
1225 | } | ||||
1226 | } | ||||
1227 | } | ||||
1228 | |||||
1229 | if( bDeleteMaster ) | ||||
1230 | { | ||||
1231 | if (pView) | ||||
1232 | { | ||||
1233 | // if MasterPage is visible hide on pageview | ||||
1234 | SdrPageView* pPgView = pView->GetSdrPageView(); | ||||
1235 | if (pPgView) | ||||
1236 | { | ||||
1237 | SdrPage* pShownPage = pPgView->GetPage(); | ||||
1238 | if( (pShownPage == pMaster) || (pShownPage == pNotesMaster) ) | ||||
1239 | { | ||||
1240 | pView->HideSdrPage(); | ||||
1241 | pView->ShowSdrPage( GetSdPage( 0, PageKind::Standard ) ); | ||||
1242 | } | ||||
1243 | } | ||||
1244 | } | ||||
1245 | |||||
1246 | if( bUndo ) | ||||
1247 | { | ||||
1248 | BegUndo(); | ||||
1249 | AddUndo( GetSdrUndoFactory().CreateUndoDeletePage( *pNotesMaster ) ); | ||||
1250 | } | ||||
1251 | |||||
1252 | RemoveMasterPage( pNotesMaster->GetPageNum() ); | ||||
1253 | |||||
1254 | if( !bUndo ) | ||||
1255 | delete pNotesMaster; | ||||
1256 | |||||
1257 | if( bUndo ) | ||||
1258 | AddUndo(GetSdrUndoFactory().CreateUndoDeletePage(*pMaster)); | ||||
1259 | |||||
1260 | RemoveMasterPage( pMaster->GetPageNum() ); | ||||
1261 | |||||
1262 | if( !bUndo ) | ||||
1263 | delete pMaster; | ||||
1264 | |||||
1265 | if( bUndo ) | ||||
1266 | EndUndo(); // do this here already, so Joe's actions happen _between_ our own | ||||
1267 | |||||
1268 | // Delete old, unused layout stylesheets | ||||
1269 | bool bDeleteOldStyleSheets = true; | ||||
1270 | for ( sal_uInt16 nMPg = 0; | ||||
1271 | nMPg < GetMasterPageCount() && bDeleteOldStyleSheets; | ||||
1272 | nMPg++ ) | ||||
1273 | { | ||||
1274 | SdPage* pMPg = static_cast<SdPage*>( GetMasterPage(nMPg) ); | ||||
1275 | if (pMPg->GetLayoutName() == aLayoutName) | ||||
1276 | { | ||||
1277 | bDeleteOldStyleSheets = false; | ||||
1278 | } | ||||
1279 | } | ||||
1280 | |||||
1281 | if (bDeleteOldStyleSheets) | ||||
1282 | { | ||||
1283 | SdStyleSheetVector aRemove; | ||||
1284 | static_cast<SdStyleSheetPool*>( mxStyleSheetPool.get())->CreateLayoutSheetList( aLayoutName, aRemove ); | ||||
1285 | |||||
1286 | if( bUndo ) | ||||
1287 | { | ||||
1288 | StyleSheetCopyResultVector aUndoRemove; | ||||
1289 | aUndoRemove.reserve(aRemove.size()); | ||||
1290 | for (const auto& a : aRemove) | ||||
1291 | aUndoRemove.emplace_back(a.get(), true); | ||||
1292 | |||||
1293 | if (pUndoMgr) | ||||
1294 | pUndoMgr->AddUndoAction(std::make_unique<SdMoveStyleSheetsUndoAction>(this, aUndoRemove, false)); | ||||
1295 | } | ||||
1296 | |||||
1297 | for( const auto& a : aRemove ) | ||||
1298 | static_cast<SdStyleSheetPool*>( mxStyleSheetPool.get())->Remove(a.get()); | ||||
1299 | } | ||||
1300 | } | ||||
1301 | } | ||||
1302 | |||||
1303 | if (pMasterPage) | ||||
1304 | break; // Just this one master page! | ||||
1305 | } | ||||
1306 | } | ||||
1307 | |||||
1308 | /** Exchange master page | ||||
1309 | * | ||||
1310 | * Either the nSdPageNum gets a new, own master page or the master page is | ||||
1311 | * exchanged completely (which then applies to all pages). | ||||
1312 | * | ||||
1313 | * nSdPageNum : page number that the new master page should get. | ||||
1314 | * rLayoutName : LayoutName of the new master page | ||||
1315 | * pSourceDoc : document (template) to get the master page from | ||||
1316 | * bMaster : exchange the master page of nSdPageNum | ||||
1317 | * bCheckMasters: remove unused master pages | ||||
1318 | * | ||||
1319 | * If pSourceDoc == NULL, an empty master page is applied. | ||||
1320 | * If rLayoutName is empty, the first master page is used. | ||||
1321 | */ | ||||
1322 | // #i121863# factored out functionality | ||||
1323 | static bool isMasterPageLayoutNameUnique(const SdDrawDocument& rDoc, const OUString& rCandidate) | ||||
1324 | { | ||||
1325 | if (rCandidate.isEmpty()) | ||||
1326 | { | ||||
1327 | return false; | ||||
1328 | } | ||||
1329 | |||||
1330 | const sal_uInt16 nPageCount(rDoc.GetMasterPageCount()); | ||||
1331 | |||||
1332 | for(sal_uInt16 a(0); a < nPageCount; a++) | ||||
1333 | { | ||||
1334 | const SdrPage* pCandidate = rDoc.GetMasterPage(a); | ||||
1335 | OUString aPageLayoutName(pCandidate->GetLayoutName()); | ||||
1336 | sal_Int32 nIndex = aPageLayoutName.indexOf(SD_LT_SEPARATOR"~LT~"); | ||||
1337 | if( nIndex != -1 ) | ||||
1338 | aPageLayoutName = aPageLayoutName.copy(0, nIndex); | ||||
1339 | |||||
1340 | if(aPageLayoutName == rCandidate) | ||||
1341 | { | ||||
1342 | return false; | ||||
1343 | } | ||||
1344 | } | ||||
1345 | |||||
1346 | return true; | ||||
1347 | } | ||||
1348 | |||||
1349 | // #i121863# factored out functionality | ||||
1350 | static OUString createNewMasterPageLayoutName(const SdDrawDocument& rDoc) | ||||
1351 | { | ||||
1352 | const OUString aBaseName(SdResId(STR_LAYOUT_DEFAULT_NAMEreinterpret_cast<char const *>("STR_LAYOUT_DEFAULT_NAME" "\004" u8"Default"))); | ||||
1353 | sal_uInt16 nCount(0); | ||||
1354 | for (;;) | ||||
1355 | { | ||||
1356 | OUString aRetval = aBaseName; | ||||
1357 | if(nCount) | ||||
1358 | { | ||||
1359 | aRetval += OUString::number(nCount); | ||||
1360 | } | ||||
1361 | if (isMasterPageLayoutNameUnique(rDoc, aRetval)) | ||||
1362 | return aRetval; | ||||
1363 | nCount++; | ||||
1364 | } | ||||
1365 | } | ||||
1366 | |||||
1367 | void SdDrawDocument::SetMasterPage(sal_uInt16 nSdPageNum, | ||||
1368 | const OUString& rLayoutName, | ||||
1369 | SdDrawDocument* pSourceDoc, | ||||
1370 | bool bMaster, | ||||
1371 | bool bCheckMasters) | ||||
1372 | { | ||||
1373 | SfxUndoManager* pUndoMgr = nullptr; | ||||
1374 | |||||
1375 | if( mpDocSh ) | ||||
1376 | { | ||||
1377 | mpDocSh->SetWaitCursor( true ); | ||||
1378 | pUndoMgr = mpDocSh->GetUndoManager(); | ||||
1379 | } | ||||
1380 | |||||
1381 | const bool bUndo = pUndoMgr && IsUndoEnabled(); | ||||
1382 | |||||
1383 | if (bUndo) | ||||
1384 | { | ||||
1385 | ViewShellId nViewShellId(-1); | ||||
1386 | if (sd::ViewShell* pViewShell = mpDocSh->GetViewShell()) | ||||
1387 | nViewShellId = pViewShell->GetViewShellBase().GetViewShellId(); | ||||
1388 | pUndoMgr->EnterListAction(SdResId(STR_UNDO_SET_PRESLAYOUTreinterpret_cast<char const *>("STR_UNDO_SET_PRESLAYOUT" "\004" u8"Apply presentation layout")), OUString(), 0, nViewShellId); | ||||
1389 | } | ||||
1390 | |||||
1391 | SdPage* pSelectedPage = GetSdPage(nSdPageNum, PageKind::Standard); | ||||
1392 | SdPage* pNotes = static_cast<SdPage*>( GetPage(pSelectedPage->GetPageNum()+1) ); | ||||
1393 | SdPage& rOldMaster = static_cast<SdPage&>(pSelectedPage->TRG_GetMasterPage()); | ||||
1394 | SdPage& rOldNotesMaster = static_cast<SdPage&>(pNotes->TRG_GetMasterPage()); | ||||
1395 | SdPage* pMaster = nullptr; | ||||
1396 | SdPage* pNotesMaster = nullptr; | ||||
1397 | OUString aOldPageLayoutName(pSelectedPage->GetLayoutName()); | ||||
1398 | OUString aOldLayoutName(aOldPageLayoutName); | ||||
1399 | sal_Int32 nIndex = aOldLayoutName.indexOf( SD_LT_SEPARATOR"~LT~" ); | ||||
1400 | if( nIndex != -1 ) | ||||
1401 | aOldLayoutName = aOldLayoutName.copy(0, nIndex); | ||||
1402 | |||||
1403 | if (pSourceDoc) | ||||
1404 | { | ||||
1405 | std::vector<StyleReplaceData> aReplList; // List of replaced stylesheets | ||||
1406 | bool bLayoutReloaded = false; // Was ex. layout reloaded? | ||||
1407 | |||||
1408 | // LayoutName, Page and Notes page | ||||
1409 | if (rLayoutName.isEmpty()) | ||||
1410 | { | ||||
1411 | // No LayoutName: take first MasterPage | ||||
1412 | pMaster = pSourceDoc->GetMasterSdPage(0, PageKind::Standard); | ||||
1413 | pNotesMaster = pSourceDoc->GetMasterSdPage(0, PageKind::Notes); | ||||
1414 | } | ||||
1415 | else | ||||
1416 | { | ||||
1417 | OUString aSearchFor = rLayoutName + SD_LT_SEPARATOR"~LT~" STR_LAYOUT_OUTLINE"Gliederung"; | ||||
1418 | |||||
1419 | for (sal_uInt16 nMP = 0; nMP < pSourceDoc->GetMasterPageCount(); ++nMP) | ||||
1420 | { | ||||
1421 | SdPage* pMP = static_cast<SdPage*>( pSourceDoc->GetMasterPage(nMP) ); | ||||
1422 | |||||
1423 | if (pMP->GetLayoutName() == aSearchFor) | ||||
1424 | { | ||||
1425 | if (pMP->GetPageKind() == PageKind::Standard) | ||||
1426 | pMaster = pMP; | ||||
1427 | if (pMP->GetPageKind() == PageKind::Notes) | ||||
1428 | pNotesMaster = pMP; | ||||
1429 | } | ||||
1430 | if (pMaster && pNotesMaster) | ||||
1431 | break; | ||||
1432 | } | ||||
1433 | DBG_ASSERT(pMaster, "MasterPage (Standard page) not found")do { if (true && (!(pMaster))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/sd/source/core/drawdoc3.cxx" ":" "1433" ": "), "%s", "MasterPage (Standard page) not found" ); } } while (false); | ||||
1434 | DBG_ASSERT(pNotesMaster, "MasterPage (Notes page) not found")do { if (true && (!(pNotesMaster))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/sd/source/core/drawdoc3.cxx" ":" "1434" ": "), "%s", "MasterPage (Notes page) not found") ; } } while (false); | ||||
1435 | |||||
1436 | // this should not happen, but looking at crash reports, it does | ||||
1437 | if( (pMaster == nullptr) || (pNotesMaster == nullptr) ) | ||||
1438 | { | ||||
1439 | // so take the first MasterPage | ||||
1440 | pMaster = pSourceDoc->GetMasterSdPage(0, PageKind::Standard); | ||||
1441 | pNotesMaster = pSourceDoc->GetMasterSdPage(0, PageKind::Notes); | ||||
1442 | } | ||||
1443 | } | ||||
1444 | |||||
1445 | // we should never reach this, but one never knows... | ||||
1446 | if( (pMaster == nullptr) || (pNotesMaster == nullptr) ) | ||||
1447 | { | ||||
1448 | if (bUndo) | ||||
1449 | pUndoMgr->LeaveListAction(); | ||||
1450 | |||||
1451 | if( mpDocSh ) | ||||
1452 | mpDocSh->SetWaitCursor( false ); | ||||
1453 | |||||
1454 | OSL_FAIL( "SdDrawDocument::SetMasterPage() failed!" )do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sd/source/core/drawdoc3.cxx" ":" "1454" ": "), "%s", "SdDrawDocument::SetMasterPage() failed!" ); } } while (false); | ||||
1455 | |||||
1456 | return; | ||||
1457 | } | ||||
1458 | |||||
1459 | const OUString aOriginalNewLayoutName( pMaster->GetName() ); | ||||
1460 | OUString aTargetNewLayoutName(aOriginalNewLayoutName); | ||||
1461 | |||||
1462 | if (pSourceDoc != this) | ||||
1463 | { | ||||
1464 | // #i121863# clone masterpages, they are from another model (!) | ||||
1465 | std::unique_ptr<SdPage> pNewNotesMaster(dynamic_cast< SdPage* >(pNotesMaster->CloneSdrPage(*this))); | ||||
1466 | std::unique_ptr<SdPage> pNewMaster(dynamic_cast< SdPage* >(pMaster->CloneSdrPage(*this))); | ||||
1467 | |||||
1468 | if(!pNewNotesMaster || !pNewMaster) | ||||
1469 | { | ||||
1470 | OSL_FAIL("SdDrawDocument::SetMasterPage() cloning of MasterPage/NoteAmsterPage failed!" )do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sd/source/core/drawdoc3.cxx" ":" "1470" ": "), "%s", "SdDrawDocument::SetMasterPage() cloning of MasterPage/NoteAmsterPage failed!" ); } } while (false); | ||||
1471 | return; | ||||
1472 | } | ||||
1473 | |||||
1474 | pNotesMaster = pNewNotesMaster.release(); | ||||
1475 | pMaster = pNewMaster.release(); | ||||
1476 | |||||
1477 | // layout name needs to be unique | ||||
1478 | aTargetNewLayoutName = pMaster->GetLayoutName(); | ||||
1479 | sal_Int32 nIndex2 = aTargetNewLayoutName.indexOf(SD_LT_SEPARATOR"~LT~"); | ||||
1480 | if( nIndex2 != -1 ) | ||||
1481 | aTargetNewLayoutName = aTargetNewLayoutName.copy(0, nIndex2); | ||||
1482 | |||||
1483 | if(!isMasterPageLayoutNameUnique(*this, aTargetNewLayoutName)) | ||||
1484 | { | ||||
1485 | aTargetNewLayoutName = createNewMasterPageLayoutName(*this); | ||||
1486 | |||||
1487 | OUString aTemp = aTargetNewLayoutName + SD_LT_SEPARATOR"~LT~" STR_LAYOUT_OUTLINE"Gliederung"; | ||||
1488 | |||||
1489 | pMaster->SetName(aTargetNewLayoutName); | ||||
1490 | pMaster->SetLayoutName(aTemp); | ||||
1491 | |||||
1492 | pNotesMaster->SetName(aTargetNewLayoutName); | ||||
1493 | pNotesMaster->SetLayoutName(aTemp); | ||||
1494 | } | ||||
1495 | } | ||||
1496 | |||||
1497 | if (pSourceDoc != this) | ||||
1498 | { | ||||
1499 | const sal_uInt16 nMasterPageCount = GetMasterPageCount(); | ||||
1500 | for ( sal_uInt16 nMPage = 0; nMPage < nMasterPageCount; nMPage++ ) | ||||
1501 | { | ||||
1502 | SdPage* pCheckMaster = static_cast<SdPage*>(GetMasterPage(nMPage)); | ||||
1503 | if( pCheckMaster->GetName() == aTargetNewLayoutName ) | ||||
1504 | { | ||||
1505 | bLayoutReloaded = true; | ||||
1506 | break; | ||||
1507 | } | ||||
1508 | } | ||||
1509 | |||||
1510 | // Correct or create presentation templates -- | ||||
1511 | // only worry about presentation templates | ||||
1512 | OUString aName; | ||||
1513 | SdStyleSheetPool* pSourceStyleSheetPool = static_cast<SdStyleSheetPool*>( pSourceDoc->GetStyleSheetPool() ); | ||||
1514 | |||||
1515 | StyleSheetCopyResultVector aCreatedStyles; // List of created stylesheets | ||||
1516 | SfxStyleSheetBase* pHisSheet = pSourceStyleSheetPool->First(SfxStyleFamily::Page); | ||||
1517 | |||||
1518 | while (pHisSheet) | ||||
1519 | { | ||||
1520 | aName = pHisSheet->GetName(); | ||||
1521 | |||||
1522 | // #i121863# search in source styles with original style name from source of | ||||
1523 | // evtl. cloned master (not-cloned, renamed for uniqueness) | ||||
1524 | if( aName.startsWith( aOriginalNewLayoutName ) ) | ||||
1525 | { | ||||
1526 | // #i121863# build name of evtl. cloned master style to search for | ||||
1527 | if(aOriginalNewLayoutName != aTargetNewLayoutName) | ||||
1528 | { | ||||
1529 | const sal_Int32 nPos(aName.indexOf(SD_LT_SEPARATOR"~LT~")); | ||||
1530 | aName = aTargetNewLayoutName + aName.copy(nPos); | ||||
1531 | } | ||||
1532 | |||||
1533 | SfxStyleSheet* pMySheet = static_cast<SfxStyleSheet*>( mxStyleSheetPool->Find(aName, SfxStyleFamily::Page) ); | ||||
1534 | |||||
1535 | if (pMySheet) | ||||
1536 | { | ||||
1537 | // A stylesheet of the same name already exists -> overwrite contents | ||||
1538 | bool bTest = pMySheet->SetName(pHisSheet->GetName()); | ||||
1539 | DBG_ASSERT(bTest, "Renaming StyleSheet failed.")do { if (true && (!(bTest))) { sal_detail_logFormat(( SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/sd/source/core/drawdoc3.cxx" ":" "1539" ": "), "%s", "Renaming StyleSheet failed."); } } while (false); | ||||
1540 | pMySheet->GetItemSet().ClearItem(); // Delete all | ||||
1541 | |||||
1542 | if (bUndo) | ||||
1543 | { | ||||
1544 | pUndoMgr->AddUndoAction(std::make_unique<StyleSheetUndoAction>(this, | ||||
1545 | pMySheet, &pHisSheet->GetItemSet())); | ||||
1546 | } | ||||
1547 | pMySheet->GetItemSet().Put(pHisSheet->GetItemSet()); | ||||
1548 | pMySheet->Broadcast(SfxHint(SfxHintId::DataChanged)); | ||||
1549 | } | ||||
1550 | else | ||||
1551 | { | ||||
1552 | // create new style | ||||
1553 | OUString aHelpFile; | ||||
1554 | pMySheet = static_cast<SfxStyleSheet*>( &mxStyleSheetPool->Make(aName, SfxStyleFamily::Page, pHisSheet->GetMask()) ); | ||||
1555 | pMySheet->SetHelpId( aHelpFile, pHisSheet->GetHelpId(aHelpFile) ); | ||||
1556 | pMySheet->GetItemSet().ClearItem(); // Delete all | ||||
1557 | pMySheet->GetItemSet().Put(pHisSheet->GetItemSet()); | ||||
1558 | |||||
1559 | aCreatedStyles.emplace_back(static_cast<SdStyleSheet*>(pMySheet), true); | ||||
1560 | } | ||||
1561 | |||||
1562 | StyleReplaceData aReplData; | ||||
1563 | aReplData.nNewFamily = pMySheet->GetFamily(); | ||||
1564 | aReplData.nFamily = pMySheet->GetFamily(); | ||||
1565 | aReplData.aNewName = pMySheet->GetName(); | ||||
1566 | |||||
1567 | // #i121863# re-create original name of style used at page where to replace with | ||||
1568 | // this new style | ||||
1569 | OUString aTemp(pMySheet->GetName()); | ||||
1570 | const sal_Int32 nPos(aTemp.indexOf(SD_LT_SEPARATOR"~LT~")); | ||||
1571 | aTemp = aOldLayoutName + aTemp.copy(nPos); | ||||
1572 | aReplData.aName = aTemp; | ||||
1573 | aReplList.push_back(aReplData); | ||||
1574 | } | ||||
1575 | |||||
1576 | pHisSheet = pSourceStyleSheetPool->Next(); | ||||
1577 | } | ||||
1578 | |||||
1579 | // If new styles were created: re-create parent chaining of the item | ||||
1580 | // sets in the styles. | ||||
1581 | if(!aCreatedStyles.empty()) | ||||
1582 | { | ||||
1583 | for ( const auto& rRData : aReplList ) | ||||
1584 | { | ||||
1585 | SfxStyleSheetBase* pSOld = mxStyleSheetPool->Find(rRData.aName, SfxStyleFamily::Page); | ||||
1586 | SfxStyleSheetBase* pSNew = mxStyleSheetPool->Find(rRData.aNewName, SfxStyleFamily::Page); | ||||
1587 | |||||
1588 | if (pSOld && pSNew) | ||||
1589 | { | ||||
1590 | const OUString& rParentOfOld = pSOld->GetParent(); | ||||
1591 | const OUString& rParentOfNew = pSNew->GetParent(); | ||||
1592 | |||||
1593 | if (!rParentOfOld.isEmpty() && rParentOfNew.isEmpty()) | ||||
1594 | { | ||||
1595 | std::vector<StyleReplaceData>::iterator pRDIter = std::find_if(aReplList.begin(), aReplList.end(), | ||||
1596 | [&rParentOfOld](const StyleReplaceData& rRD) { return (rRD.aName == rParentOfOld) && (rRD.aName != rRD.aNewName); }); | ||||
1597 | if (pRDIter != aReplList.end()) | ||||
1598 | { | ||||
1599 | OUString aParentOfNew(pRDIter->aNewName); | ||||
1600 | pSNew->SetParent(aParentOfNew); | ||||
1601 | } | ||||
1602 | } | ||||
1603 | } | ||||
1604 | } | ||||
1605 | } | ||||
1606 | |||||
1607 | if (bUndo && !aCreatedStyles.empty()) | ||||
1608 | { | ||||
1609 | // Add UndoAction for creating and inserting the stylesheets to | ||||
1610 | // the top of the UndoManager | ||||
1611 | pUndoMgr->AddUndoAction(std::make_unique<SdMoveStyleSheetsUndoAction>( this, aCreatedStyles, true)); | ||||
1612 | } | ||||
1613 | } | ||||
1614 | |||||
1615 | // Create layout name based upon the name of the page layout of the | ||||
1616 | // master page | ||||
1617 | OUString aPageLayoutName(pMaster->GetLayoutName()); | ||||
1618 | OUString aLayoutName = aPageLayoutName; | ||||
1619 | sal_Int32 nIndex2 = aLayoutName.indexOf( SD_LT_SEPARATOR"~LT~" ); | ||||
1620 | if( nIndex2 != -1 ) | ||||
1621 | aLayoutName = aLayoutName.copy( 0, nIndex2); | ||||
1622 | |||||
1623 | // #i121863# Do *not* remove from original document any longer, it is potentially used there | ||||
1624 | // and would lead to crashes. Rely on the automatic process of removing unused masterpages | ||||
1625 | // (see RemoveUnnecessaryMasterPages) | ||||
1626 | //if (pSourceDoc != this) | ||||
1627 | //{ | ||||
1628 | // // Remove from the source document | ||||
1629 | // pSourceDoc->RemoveMasterPage(pNotesMaster->GetPageNum()); | ||||
1630 | // pSourceDoc->RemoveMasterPage(pMaster->GetPageNum()); | ||||
1631 | //} | ||||
1632 | |||||
1633 | // Register the new master pages with the document and then use | ||||
1634 | // the new presentation layout for the default and notes pages | ||||
1635 | if (pSourceDoc != this) | ||||
1636 | { | ||||
1637 | // Insert the master pages: | ||||
1638 | // Insert master pages from new layouts at the end. | ||||
1639 | // If a layout is being replaced, however, insert them before the | ||||
1640 | // position of the old master page, so from now on the new master | ||||
1641 | // page will be found when searching (e.g. | ||||
1642 | // SdPage::SetPresentationLayout). | ||||
1643 | sal_uInt16 nInsertPos = rOldMaster.GetPageNum(); | ||||
1644 | BegUndo(); | ||||
1645 | |||||
1646 | if (!bLayoutReloaded) | ||||
1647 | nInsertPos = 0xFFFF; | ||||
1648 | InsertMasterPage(pMaster, nInsertPos); | ||||
1649 | if( bUndo ) | ||||
1650 | AddUndo(GetSdrUndoFactory().CreateUndoNewPage(*pMaster)); | ||||
1651 | |||||
1652 | nInsertPos++; | ||||
1653 | if (!bLayoutReloaded) | ||||
1654 | nInsertPos = 0xFFFF; | ||||
1655 | InsertMasterPage(pNotesMaster, nInsertPos); | ||||
1656 | if( bUndo ) | ||||
1657 | { | ||||
1658 | AddUndo(GetSdrUndoFactory().CreateUndoNewPage(*pNotesMaster)); | ||||
1659 | |||||
1660 | EndUndo(); // do this here already, so Joe's actions happen _between_ our own. | ||||
1661 | } | ||||
1662 | } | ||||
1663 | |||||
1664 | // Fill list with pages | ||||
1665 | std::vector<SdPage*> aPageList; | ||||
1666 | |||||
1667 | // #98456, this has to be removed according to CL (KA 07/08/2002) | ||||
1668 | // #109884# but we need them again to restore the styles of the presentation objects while undo | ||||
1669 | aPageList.push_back(pMaster); | ||||
1670 | aPageList.push_back(pNotesMaster); | ||||
1671 | |||||
1672 | if (bMaster || bLayoutReloaded) | ||||
1673 | { | ||||
1674 | for (sal_uInt16 nPage = 1; nPage < GetPageCount(); nPage++) | ||||
1675 | { | ||||
1676 | SdPage* pPage = static_cast<SdPage*>( GetPage(nPage) ); | ||||
1677 | OUString aTest = pPage->GetLayoutName(); | ||||
1678 | if (aTest == aOldPageLayoutName) | ||||
1679 | { | ||||
1680 | aPageList.push_back(pPage); | ||||
1681 | } | ||||
1682 | } | ||||
1683 | |||||
1684 | } | ||||
1685 | else | ||||
1686 | { | ||||
1687 | aPageList.push_back(pSelectedPage); | ||||
1688 | aPageList.push_back(pNotes); | ||||
1689 | } | ||||
1690 | |||||
1691 | for (SdPage* pPage : aPageList) | ||||
1692 | { | ||||
1693 | AutoLayout eAutoLayout = pPage->GetAutoLayout(); | ||||
1694 | |||||
1695 | if( bUndo ) | ||||
1696 | { | ||||
1697 | pUndoMgr->AddUndoAction(std::make_unique<SdPresentationLayoutUndoAction> | ||||
1698 | (this, | ||||
1699 | pPage->IsMasterPage() ? aLayoutName : aOldLayoutName, | ||||
1700 | aLayoutName, | ||||
1701 | eAutoLayout, eAutoLayout, false, pPage)); | ||||
1702 | } | ||||
1703 | pPage->SetPresentationLayout(aLayoutName); | ||||
1704 | pPage->SetAutoLayout(eAutoLayout); | ||||
1705 | } | ||||
1706 | |||||
1707 | // Adapt new master pages | ||||
1708 | if (pSourceDoc != this) | ||||
1709 | { | ||||
1710 | Size aSize(rOldMaster.GetSize()); | ||||
1711 | ::tools::Rectangle aBorderRect(rOldMaster.GetLeftBorder(), | ||||
1712 | rOldMaster.GetUpperBorder(), | ||||
1713 | rOldMaster.GetRightBorder(), | ||||
1714 | rOldMaster.GetLowerBorder()); | ||||
1715 | pMaster->ScaleObjects(aSize, aBorderRect, true); | ||||
1716 | pMaster->SetSize(aSize); | ||||
1717 | pMaster->SetBorder(rOldMaster.GetLeftBorder(), | ||||
1718 | rOldMaster.GetUpperBorder(), | ||||
1719 | rOldMaster.GetRightBorder(), | ||||
1720 | rOldMaster.GetLowerBorder()); | ||||
1721 | pMaster->SetOrientation( rOldMaster.GetOrientation() ); | ||||
1722 | pMaster->SetAutoLayout(pMaster->GetAutoLayout()); | ||||
1723 | |||||
1724 | aSize = rOldNotesMaster.GetSize(); | ||||
1725 | ::tools::Rectangle aNotesBorderRect(rOldNotesMaster.GetLeftBorder(), | ||||
1726 | rOldNotesMaster.GetUpperBorder(), | ||||
1727 | rOldNotesMaster.GetRightBorder(), | ||||
1728 | rOldNotesMaster.GetLowerBorder()); | ||||
1729 | pNotesMaster->ScaleObjects(aSize, aNotesBorderRect, true); | ||||
1730 | pNotesMaster->SetSize(aSize); | ||||
1731 | pNotesMaster->SetBorder(rOldNotesMaster.GetLeftBorder(), | ||||
1732 | rOldNotesMaster.GetUpperBorder(), | ||||
1733 | rOldNotesMaster.GetRightBorder(), | ||||
1734 | rOldNotesMaster.GetLowerBorder()); | ||||
1735 | pNotesMaster->SetOrientation( rOldNotesMaster.GetOrientation() ); | ||||
1736 | pNotesMaster->SetAutoLayout(pNotesMaster->GetAutoLayout()); | ||||
1737 | |||||
1738 | if( (pSourceDoc->GetDocumentType() == DocumentType::Impress) && | ||||
1739 | (GetDocumentType() == DocumentType::Draw) ) | ||||
1740 | { | ||||
1741 | pMaster->RemoveEmptyPresentationObjects(); | ||||
1742 | pNotesMaster->RemoveEmptyPresentationObjects(); | ||||
1743 | } | ||||
1744 | } | ||||
1745 | } | ||||
1746 | else | ||||
1747 | { | ||||
1748 | // Find a new name for the layout | ||||
1749 | OUString aName(createNewMasterPageLayoutName(*this)); | ||||
1750 | OUString aPageLayoutName(aName + SD_LT_SEPARATOR"~LT~" STR_LAYOUT_OUTLINE"Gliederung"); | ||||
1751 | |||||
1752 | // Generate new stylesheets | ||||
1753 | static_cast<SdStyleSheetPool*>( mxStyleSheetPool.get())->CreateLayoutStyleSheets(aName); | ||||
1754 | SdStyleSheetVector aCreatedStyles; | ||||
1755 | static_cast<SdStyleSheetPool*>( mxStyleSheetPool.get())->CreateLayoutSheetList(aName, aCreatedStyles); | ||||
1756 | |||||
1757 | if( bUndo ) | ||||
1758 | { | ||||
1759 | StyleSheetCopyResultVector aUndoInsert; | ||||
1760 | aUndoInsert.reserve(aCreatedStyles.size()); | ||||
1761 | for (const auto& a : aCreatedStyles) | ||||
1762 | aUndoInsert.emplace_back(a.get(), true); | ||||
1763 | pUndoMgr->AddUndoAction(std::make_unique<SdMoveStyleSheetsUndoAction>(this, aUndoInsert, true)); | ||||
1764 | // Generate new master pages and register them with the document | ||||
1765 | BegUndo(); | ||||
1766 | } | ||||
1767 | |||||
1768 | pMaster = AllocSdPage(true); | ||||
1769 | pMaster->SetSize(pSelectedPage->GetSize()); | ||||
1770 | pMaster->SetBorder(pSelectedPage->GetLeftBorder(), | ||||
1771 | pSelectedPage->GetUpperBorder(), | ||||
1772 | pSelectedPage->GetRightBorder(), | ||||
1773 | pSelectedPage->GetLowerBorder() ); | ||||
1774 | pMaster->SetName(aName); | ||||
1775 | pMaster->SetLayoutName(aPageLayoutName); | ||||
1776 | InsertMasterPage(pMaster); | ||||
1777 | |||||
1778 | if( bUndo ) | ||||
1779 | AddUndo(GetSdrUndoFactory().CreateUndoNewPage(*pMaster)); | ||||
1780 | |||||
1781 | pMaster->SetAutoLayout(AUTOLAYOUT_NONE, true, true); | ||||
1782 | |||||
1783 | pNotesMaster = AllocSdPage(true); | ||||
1784 | pNotesMaster->SetPageKind(PageKind::Notes); | ||||
1785 | pNotesMaster->SetSize(pNotes->GetSize()); | ||||
1786 | pNotesMaster->SetBorder(pNotes->GetLeftBorder(), | ||||
1787 | pNotes->GetUpperBorder(), | ||||
1788 | pNotes->GetRightBorder(), | ||||
1789 | pNotes->GetLowerBorder() ); | ||||
1790 | pNotesMaster->SetName(aName); | ||||
1791 | pNotesMaster->SetLayoutName(aPageLayoutName); | ||||
1792 | InsertMasterPage(pNotesMaster); | ||||
1793 | |||||
1794 | if( bUndo ) | ||||
1795 | AddUndo(GetSdrUndoFactory().CreateUndoNewPage(*pNotesMaster)); | ||||
1796 | |||||
1797 | pNotesMaster->SetAutoLayout(AUTOLAYOUT_NOTES, true, true); | ||||
1798 | |||||
1799 | if( bUndo ) | ||||
1800 | EndUndo(); | ||||
1801 | |||||
1802 | // Create a list of affected default and notes pages | ||||
1803 | std::vector<SdPage*> aPageList; | ||||
1804 | if (bMaster) | ||||
1805 | { | ||||
1806 | for (sal_uInt16 nPage = 1; nPage < GetPageCount(); nPage++) | ||||
1807 | { | ||||
1808 | SdPage* pPage = static_cast<SdPage*>( GetPage(nPage) ); | ||||
1809 | if (pPage->GetLayoutName() == aOldPageLayoutName) | ||||
1810 | { | ||||
1811 | aPageList.push_back(pPage); | ||||
1812 | } | ||||
1813 | } | ||||
1814 | } | ||||
1815 | else | ||||
1816 | { | ||||
1817 | aPageList.push_back(pSelectedPage); | ||||
1818 | aPageList.push_back(pNotes); | ||||
1819 | } | ||||
1820 | |||||
1821 | // Set presentation layout and AutoLayout for the affected pages | ||||
1822 | for ( auto& rpPage : aPageList ) | ||||
1823 | { | ||||
1824 | AutoLayout eOldAutoLayout = rpPage->GetAutoLayout(); | ||||
1825 | AutoLayout eNewAutoLayout = | ||||
1826 | rpPage->GetPageKind() == PageKind::Standard ? AUTOLAYOUT_NONE : AUTOLAYOUT_NOTES; | ||||
1827 | |||||
1828 | if( bUndo ) | ||||
1829 | { | ||||
1830 | pUndoMgr->AddUndoAction(std::make_unique<SdPresentationLayoutUndoAction> | ||||
1831 | (this, aOldLayoutName, aName, | ||||
1832 | eOldAutoLayout, eNewAutoLayout, true, | ||||
1833 | rpPage)); | ||||
1834 | } | ||||
1835 | |||||
1836 | rpPage->SetPresentationLayout(aName); | ||||
1837 | rpPage->SetAutoLayout(eNewAutoLayout); | ||||
1838 | } | ||||
1839 | } | ||||
1840 | |||||
1841 | // If the old master pages aren't used anymore, they and their styles have | ||||
1842 | // to be removed. | ||||
1843 | if (bCheckMasters) | ||||
1844 | { | ||||
1845 | // Check all | ||||
1846 | RemoveUnnecessaryMasterPages(); | ||||
1847 | } | ||||
1848 | else | ||||
1849 | { | ||||
1850 | // Check only the master page that was replaced | ||||
1851 | RemoveUnnecessaryMasterPages(&rOldMaster); | ||||
1852 | } | ||||
1853 | |||||
1854 | if( bUndo ) | ||||
1855 | pUndoMgr->LeaveListAction(); | ||||
1856 | |||||
1857 | if( mpDocSh ) | ||||
1858 | mpDocSh->SetWaitCursor( false ); | ||||
1859 | } | ||||
1860 | |||||
1861 | void SdDrawDocument::Merge(SdrModel& rSourceModel, | ||||
1862 | sal_uInt16 nFirstPageNum, sal_uInt16 nLastPageNum, | ||||
1863 | sal_uInt16 nDestPos, | ||||
1864 | bool bMergeMasterPages, bool bAllMasterPages, | ||||
1865 | bool bUndo, bool bTreadSourceAsConst) | ||||
1866 | { | ||||
1867 | sal_uInt16 nMasterPageCount = GetMasterPageCount(); | ||||
1868 | SdrModel::Merge( rSourceModel, nFirstPageNum, nLastPageNum, nDestPos, bMergeMasterPages, bAllMasterPages, bUndo, bTreadSourceAsConst ); | ||||
1869 | |||||
1870 | // add style family for each new master page | ||||
1871 | for( sal_uInt16 nMaster = nMasterPageCount; nMaster < GetMasterPageCount(); nMaster++ ) | ||||
1872 | { | ||||
1873 | SdPage* pPage = static_cast< SdPage* >( GetMasterPage( nMaster ) ); | ||||
1874 | if( pPage && pPage->IsMasterPage() && (pPage->GetPageKind() == PageKind::Standard) ) | ||||
1875 | { | ||||
1876 | // new master page created, add its style family | ||||
1877 | SdStyleSheetPool* pStylePool = static_cast<SdStyleSheetPool*>( GetStyleSheetPool() ); | ||||
1878 | if( pStylePool ) | ||||
1879 | pStylePool->AddStyleFamily( pPage ); | ||||
1880 | } | ||||
1881 | } | ||||
1882 | } | ||||
1883 | |||||
1884 | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |
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 | #ifndef INCLUDED_TOOLS_REF_HXX |
20 | #define INCLUDED_TOOLS_REF_HXX |
21 | |
22 | #include <sal/config.h> |
23 | #include <cassert> |
24 | #include <tools/toolsdllapi.h> |
25 | #include <utility> |
26 | |
27 | /** |
28 | This implements similar functionality to boost::intrusive_ptr |
29 | */ |
30 | |
31 | namespace tools { |
32 | |
33 | /** T must be a class that extends SvRefBase */ |
34 | template<typename T> class SAL_DLLPUBLIC_RTTI__attribute__ ((type_visibility("default"))) SvRef final { |
35 | public: |
36 | SvRef(): pObj(nullptr) {} |
37 | |
38 | SvRef(SvRef&& rObj) noexcept |
39 | { |
40 | pObj = rObj.pObj; |
41 | rObj.pObj = nullptr; |
42 | } |
43 | |
44 | SvRef(SvRef const & rObj): pObj(rObj.pObj) |
45 | { |
46 | if (pObj != nullptr) pObj->AddNextRef(); |
47 | } |
48 | |
49 | SvRef(T * pObjP): pObj(pObjP) |
50 | { |
51 | if (pObj != nullptr) pObj->AddFirstRef(); |
52 | } |
53 | |
54 | ~SvRef() |
55 | { |
56 | if (pObj != nullptr) pObj->ReleaseRef(); |
57 | } |
58 | |
59 | void clear() |
60 | { |
61 | if (pObj != nullptr) { |
62 | T * pRefObj = pObj; |
63 | pObj = nullptr; |
64 | pRefObj->ReleaseRef(); |
65 | } |
66 | } |
67 | |
68 | SvRef & operator =(SvRef const & rObj) |
69 | { |
70 | if (rObj.pObj != nullptr) { |
71 | rObj.pObj->AddNextRef(); |
72 | } |
73 | T * pRefObj = pObj; |
74 | pObj = rObj.pObj; |
75 | if (pRefObj != nullptr) { |
76 | pRefObj->ReleaseRef(); |
77 | } |
78 | return *this; |
79 | } |
80 | |
81 | SvRef & operator =(SvRef && rObj) |
82 | { |
83 | if (pObj != nullptr) { |
84 | pObj->ReleaseRef(); |
85 | } |
86 | pObj = rObj.pObj; |
87 | rObj.pObj = nullptr; |
88 | return *this; |
89 | } |
90 | |
91 | bool is() const { return pObj != nullptr; } |
92 | |
93 | explicit operator bool() const { return is(); } |
94 | |
95 | T * get() const { return pObj; } |
96 | |
97 | T * operator ->() const { assert(pObj != nullptr)(static_cast <bool> (pObj != nullptr) ? void (0) : __assert_fail ("pObj != nullptr", "/home/maarten/src/libreoffice/core/include/tools/ref.hxx" , 97, __extension__ __PRETTY_FUNCTION__)); return pObj; } |
98 | |
99 | T & operator *() const { assert(pObj != nullptr)(static_cast <bool> (pObj != nullptr) ? void (0) : __assert_fail ("pObj != nullptr", "/home/maarten/src/libreoffice/core/include/tools/ref.hxx" , 99, __extension__ __PRETTY_FUNCTION__)); return *pObj; } |
100 | |
101 | bool operator ==(const SvRef<T> &rhs) const { return pObj == rhs.pObj; } |
102 | bool operator !=(const SvRef<T> &rhs) const { return !(*this == rhs); } |
103 | |
104 | private: |
105 | T * pObj; |
106 | }; |
107 | |
108 | /** |
109 | * This implements similar functionality to std::make_shared. |
110 | */ |
111 | template<typename T, typename... Args> |
112 | SvRef<T> make_ref(Args&& ... args) |
113 | { |
114 | return SvRef<T>(new T(std::forward<Args>(args)...)); |
115 | } |
116 | |
117 | } |
118 | |
119 | /** Classes that want to be referenced-counted via SvRef<T>, should extend this base class */ |
120 | class TOOLS_DLLPUBLIC__attribute__ ((visibility("default"))) SvRefBase |
121 | { |
122 | // work around a clang 3.5 optimization bug: if the bNoDelete is *first* |
123 | // it mis-compiles "if (--nRefCount == 0)" and never deletes any object |
124 | unsigned int nRefCount : 31; |
125 | // the only reason this is not bool is because MSVC cannot handle mixed type bitfields |
126 | unsigned int bNoDelete : 1; |
127 | |
128 | protected: |
129 | virtual ~SvRefBase() COVERITY_NOEXCEPT_FALSE; |
130 | |
131 | public: |
132 | SvRefBase() : nRefCount(0), bNoDelete(1) {} |
133 | SvRefBase(const SvRefBase &) : nRefCount(0), bNoDelete(1) {} |
134 | |
135 | SvRefBase & operator=(const SvRefBase &) { return *this; } |
136 | |
137 | void RestoreNoDelete() |
138 | { bNoDelete = 1; } |
139 | |
140 | void AddNextRef() |
141 | { |
142 | assert( nRefCount < (1 << 30) && "Do not add refs to dead objects" )(static_cast <bool> (nRefCount < (1 << 30) && "Do not add refs to dead objects") ? void (0) : __assert_fail ("nRefCount < (1 << 30) && \"Do not add refs to dead objects\"" , "/home/maarten/src/libreoffice/core/include/tools/ref.hxx", 142, __extension__ __PRETTY_FUNCTION__)); |
143 | ++nRefCount; |
144 | } |
145 | |
146 | void AddFirstRef() |
147 | { |
148 | assert( nRefCount < (1 << 30) && "Do not add refs to dead objects" )(static_cast <bool> (nRefCount < (1 << 30) && "Do not add refs to dead objects") ? void (0) : __assert_fail ("nRefCount < (1 << 30) && \"Do not add refs to dead objects\"" , "/home/maarten/src/libreoffice/core/include/tools/ref.hxx", 148, __extension__ __PRETTY_FUNCTION__)); |
149 | if( bNoDelete ) |
150 | bNoDelete = 0; |
151 | ++nRefCount; |
152 | } |
153 | |
154 | void ReleaseRef() |
155 | { |
156 | assert( nRefCount >= 1)(static_cast <bool> (nRefCount >= 1) ? void (0) : __assert_fail ("nRefCount >= 1", "/home/maarten/src/libreoffice/core/include/tools/ref.hxx" , 156, __extension__ __PRETTY_FUNCTION__)); |
157 | if( --nRefCount == 0 && !bNoDelete) |
158 | { |
159 | // I'm not sure about the original purpose of this line, but right now |
160 | // it serves the purpose that anything that attempts to do an AddRef() |
161 | // after an object is deleted will trip an assert. |
162 | nRefCount = 1 << 30; |
163 | delete this; |
164 | } |
165 | } |
166 | |
167 | unsigned int GetRefCount() const |
168 | { return nRefCount; } |
169 | }; |
170 | |
171 | template<typename T> |
172 | class SvCompatWeakBase; |
173 | |
174 | /** SvCompatWeakHdl acts as an intermediary between SvCompatWeakRef<T> and T. |
175 | */ |
176 | template<typename T> |
177 | class SvCompatWeakHdl final : public SvRefBase |
178 | { |
179 | friend class SvCompatWeakBase<T>; |
180 | T* _pObj; |
181 | |
182 | SvCompatWeakHdl( T* pObj ) : _pObj( pObj ) {} |
183 | |
184 | public: |
185 | void ResetWeakBase( ) { _pObj = nullptr; } |
186 | T* GetObj() { return _pObj; } |
187 | }; |
188 | |
189 | /** We only have one place that extends this, in include/sfx2/frame.hxx, class SfxFrame. |
190 | Its function is to notify the SvCompatWeakHdl when an SfxFrame object is deleted. |
191 | */ |
192 | template<typename T> |
193 | class SvCompatWeakBase |
194 | { |
195 | tools::SvRef< SvCompatWeakHdl<T> > _xHdl; |
196 | |
197 | public: |
198 | /** Does not use initializer due to compiler warnings, |
199 | because the lifetime of the _xHdl object can exceed the lifetime of this class. |
200 | */ |
201 | SvCompatWeakBase( T* pObj ) { _xHdl = new SvCompatWeakHdl<T>( pObj ); } |
202 | |
203 | ~SvCompatWeakBase() { _xHdl->ResetWeakBase(); } |
204 | |
205 | SvCompatWeakHdl<T>* GetHdl() { return _xHdl.get(); } |
206 | }; |
207 | |
208 | /** We only have one weak reference in LO, in include/sfx2/frame.hxx, class SfxFrameWeak. |
209 | */ |
210 | template<typename T> |
211 | class SAL_WARN_UNUSED__attribute__((warn_unused)) SvCompatWeakRef |
212 | { |
213 | tools::SvRef< SvCompatWeakHdl<T> > _xHdl; |
214 | public: |
215 | SvCompatWeakRef( ) {} |
216 | SvCompatWeakRef( T* pObj ) |
217 | { if( pObj ) _xHdl = pObj->GetHdl(); } |
218 | #if defined(__COVERITY__) |
219 | ~SvCompatWeakRef() COVERITY_NOEXCEPT_FALSE {} |
220 | #endif |
221 | SvCompatWeakRef& operator = ( T * pObj ) |
222 | { _xHdl = pObj ? pObj->GetHdl() : nullptr; return *this; } |
223 | bool is() const |
224 | { return _xHdl.is() && _xHdl->GetObj(); } |
225 | explicit operator bool() const { return is(); } |
226 | T* operator -> () const |
227 | { return _xHdl.is() ? _xHdl->GetObj() : nullptr; } |
228 | operator T* () const |
229 | { return _xHdl.is() ? _xHdl->GetObj() : nullptr; } |
230 | }; |
231 | |
232 | #endif |
233 | |
234 | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |