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 <sal/config.h>
21 #include <sal/log.hxx>
22
23 #include <memory>
24 #include <utility>
25
26 #include <DrawDocShell.hxx>
27 #include <com/sun/star/document/PrinterIndependentLayout.hpp>
28 #include <editeng/outlobj.hxx>
29 #include <tools/urlobj.hxx>
30 #include <vcl/waitobj.hxx>
31 #include <svx/svxids.hrc>
32 #include <editeng/editeng.hxx>
33 #include <editeng/editstat.hxx>
34 #include <editeng/flstitem.hxx>
35 #include <svl/flagitem.hxx>
36 #include <sot/storage.hxx>
37 #include <sfx2/dinfdlg.hxx>
38 #include <sfx2/docfile.hxx>
39 #include <sfx2/docfilt.hxx>
40 #include <sfx2/dispatch.hxx>
41 #include <svx/svdotext.hxx>
42 #include <sfx2/printer.hxx>
43 #include <svtools/ctrltool.hxx>
44 #include <comphelper/classids.hxx>
45 #include <sot/formats.hxx>
46 #include <sfx2/viewfrm.hxx>
47 #include <com/sun/star/drawing/XDrawPage.hpp>
48 #include <com/sun/star/drawing/XDrawView.hpp>
49
50 #include <app.hrc>
51 #include <strings.hrc>
52 #include <strmname.h>
53 #include <FrameView.hxx>
54 #include <optsitem.hxx>
55 #include <Outliner.hxx>
56 #include <sdattr.hrc>
57 #include <drawdoc.hxx>
58 #include <ViewShell.hxx>
59 #include <sdmod.hxx>
60 #include <View.hxx>
61 #include <EffectMigration.hxx>
62 #include <CustomAnimationEffect.hxx>
63 #include <sdpage.hxx>
64 #include <sdresid.hxx>
65 #include <DrawViewShell.hxx>
66 #include <ViewShellBase.hxx>
67 #include <Window.hxx>
68 #include <OutlineView.hxx>
69 #include <OutlineViewShell.hxx>
70 #include <sdxmlwrp.hxx>
71 #include <sdpptwrp.hxx>
72 #include <sdcgmfilter.hxx>
73 #include <sdgrffilter.hxx>
74 #include <sdhtmlfilter.hxx>
75 #include <sdpdffilter.hxx>
76 #include <framework/FrameworkHelper.hxx>
77
78 #include <sfx2/zoomitem.hxx>
79
80 using namespace ::com::sun::star;
81 using namespace ::com::sun::star::uno;
82 using ::sd::framework::FrameworkHelper;
83
84 namespace sd {
85
86 /**
87 * Creates (if necessary) and returns a SfxPrinter
88 */
GetPrinter(bool bCreate)89 SfxPrinter* DrawDocShell::GetPrinter(bool bCreate)
90 {
91 if (bCreate && !mpPrinter)
92 {
93 // create ItemSet with special pool area
94 auto pSet = std::make_unique<SfxItemSet>( GetPool(),
95 svl::Items<SID_PRINTER_NOTFOUND_WARN, SID_PRINTER_NOTFOUND_WARN,
96 SID_PRINTER_CHANGESTODOC, SID_PRINTER_CHANGESTODOC,
97 ATTR_OPTIONS_PRINT, ATTR_OPTIONS_PRINT>{} );
98 // set PrintOptionsSet
99 SdOptionsPrintItem aPrintItem( SD_MOD()->GetSdOptions(mpDoc->GetDocumentType()) );
100 SfxFlagItem aFlagItem( SID_PRINTER_CHANGESTODOC );
101 SfxPrinterChangeFlags nFlags =
102 (aPrintItem.GetOptionsPrint().IsWarningSize() ? SfxPrinterChangeFlags::CHG_SIZE : SfxPrinterChangeFlags::NONE) |
103 (aPrintItem.GetOptionsPrint().IsWarningOrientation() ? SfxPrinterChangeFlags::CHG_ORIENTATION : SfxPrinterChangeFlags::NONE);
104 aFlagItem.SetValue( static_cast<int>(nFlags) );
105
106 pSet->Put( aPrintItem );
107 pSet->Put( SfxBoolItem( SID_PRINTER_NOTFOUND_WARN, aPrintItem.GetOptionsPrint().IsWarningPrinter() ) );
108 pSet->Put( aFlagItem );
109
110 mpPrinter = VclPtr<SfxPrinter>::Create(std::move(pSet));
111 mbOwnPrinter = true;
112
113 // set output quality
114 sal_uInt16 nQuality = aPrintItem.GetOptionsPrint().GetOutputQuality();
115
116 DrawModeFlags nMode = DrawModeFlags::Default;
117 // 1 == Grayscale, 2 == Black & White (with grayscale images)
118 if( nQuality == 1 )
119 nMode = DrawModeFlags::GrayLine | DrawModeFlags::GrayFill | DrawModeFlags::GrayText | DrawModeFlags::GrayBitmap | DrawModeFlags::GrayGradient;
120 else if( nQuality == 2 )
121 nMode = DrawModeFlags::BlackLine | DrawModeFlags::WhiteFill | DrawModeFlags::BlackText | DrawModeFlags::GrayBitmap | DrawModeFlags::WhiteGradient;
122
123 mpPrinter->SetDrawMode( nMode );
124
125 MapMode aMM (mpPrinter->GetMapMode());
126 aMM.SetMapUnit(MapUnit::Map100thMM);
127 mpPrinter->SetMapMode(aMM);
128 UpdateRefDevice();
129 }
130 return mpPrinter;
131 }
132
133 /**
134 * Set new SfxPrinter (transfer of ownership)
135 */
SetPrinter(SfxPrinter * pNewPrinter)136 void DrawDocShell::SetPrinter(SfxPrinter *pNewPrinter)
137 {
138 if ( mpViewShell )
139 {
140 ::sd::View* pView = mpViewShell->GetView();
141 if ( pView->IsTextEdit() )
142 pView->SdrEndTextEdit();
143 }
144
145 if ( mpPrinter && mbOwnPrinter && (mpPrinter.get() != pNewPrinter) )
146 mpPrinter.disposeAndClear();
147
148 mpPrinter = pNewPrinter;
149 mbOwnPrinter = true;
150 if ( mpDoc->GetPrinterIndependentLayout() == css::document::PrinterIndependentLayout::DISABLED )
151 UpdateFontList();
152 UpdateRefDevice();
153 }
154
UpdateFontList()155 void DrawDocShell::UpdateFontList()
156 {
157 mpFontList.reset();
158 OutputDevice* pRefDevice = nullptr;
159 if ( mpDoc->GetPrinterIndependentLayout() == css::document::PrinterIndependentLayout::DISABLED )
160 pRefDevice = GetPrinter(true);
161 else
162 pRefDevice = SD_MOD()->GetVirtualRefDevice();
163 mpFontList.reset( new FontList(pRefDevice, nullptr) );
164 SvxFontListItem aFontListItem( mpFontList.get(), SID_ATTR_CHAR_FONTLIST );
165 PutItem( aFontListItem );
166 }
167
GetDocumentPrinter()168 Printer* DrawDocShell::GetDocumentPrinter()
169 {
170 return GetPrinter(false);
171 }
172
OnDocumentPrinterChanged(Printer * pNewPrinter)173 void DrawDocShell::OnDocumentPrinterChanged(Printer* pNewPrinter)
174 {
175 // if we already have a printer, see if it's the same
176 if( mpPrinter )
177 {
178 // easy case
179 if( mpPrinter == pNewPrinter )
180 return;
181
182 // compare if it's the same printer with the same job setup
183 if( (mpPrinter->GetName() == pNewPrinter->GetName()) &&
184 (mpPrinter->GetJobSetup() == pNewPrinter->GetJobSetup()))
185 return;
186 }
187
188 SfxPrinter* const pSfxPrinter = dynamic_cast<SfxPrinter*>(pNewPrinter);
189 if (pSfxPrinter)
190 {
191 SetPrinter(pSfxPrinter);
192
193 // container owns printer
194 mbOwnPrinter = false;
195 }
196 }
197
UpdateRefDevice()198 void DrawDocShell::UpdateRefDevice()
199 {
200 if( !mpDoc )
201 return;
202
203 // Determine the device for which the output will be formatted.
204 VclPtr< OutputDevice > pRefDevice;
205 switch (mpDoc->GetPrinterIndependentLayout())
206 {
207 case css::document::PrinterIndependentLayout::DISABLED:
208 pRefDevice = mpPrinter.get();
209 break;
210
211 case css::document::PrinterIndependentLayout::ENABLED:
212 pRefDevice = SD_MOD()->GetVirtualRefDevice();
213 break;
214
215 default:
216 // We are confronted with an invalid or un-implemented
217 // layout mode. Use the printer as formatting device
218 // as a fall-back.
219 SAL_WARN( "sd", "DrawDocShell::UpdateRefDevice(): Unexpected printer layout mode");
220
221 pRefDevice = mpPrinter.get();
222 break;
223 }
224 mpDoc->SetRefDevice( pRefDevice.get() );
225
226 SdOutliner* pOutl = mpDoc->GetOutliner( false );
227
228 if( pOutl )
229 pOutl->SetRefDevice( pRefDevice );
230
231 SdOutliner* pInternalOutl = mpDoc->GetInternalOutliner( false );
232
233 if( pInternalOutl )
234 pInternalOutl->SetRefDevice( pRefDevice );
235 }
236
237 /**
238 * Creates new document, opens streams
239 */
InitNew(const css::uno::Reference<css::embed::XStorage> & xStorage)240 bool DrawDocShell::InitNew( const css::uno::Reference< css::embed::XStorage >& xStorage )
241 {
242 bool bRet = SfxObjectShell::InitNew( xStorage );
243
244 ::tools::Rectangle aVisArea( Point(0, 0), Size(14100, 10000) );
245 SetVisArea(aVisArea);
246
247 if (bRet)
248 {
249 if( !mbSdDataObj )
250 mpDoc->NewOrLoadCompleted(NEW_DOC); // otherwise calling
251 // NewOrLoadCompleted(NEW_LOADED) in
252 // SdDrawDocument::AllocModel()
253 }
254 return bRet;
255 }
256
257 /**
258 * loads pools and document
259 */
Load(SfxMedium & rMedium)260 bool DrawDocShell::Load( SfxMedium& rMedium )
261 {
262 // If this is an ODF file being loaded, then by default, use legacy processing
263 // for tdf#99729 (if required, it will be overridden in *::ReadUserDataSequence())
264 if (IsOwnStorageFormat(rMedium))
265 {
266 mpDoc->SetAnchoredTextOverflowLegacy(true);
267 }
268
269 bool bRet = false;
270 bool bStartPresentation = false;
271 ErrCode nError = ERRCODE_NONE;
272
273 SfxItemSet* pSet = rMedium.GetItemSet();
274
275 if( pSet )
276 {
277 if( ( SfxItemState::SET == pSet->GetItemState(SID_PREVIEW ) ) && pSet->Get( SID_PREVIEW ).GetValue() )
278 {
279 mpDoc->SetStarDrawPreviewMode( true );
280 }
281
282 if( SfxItemState::SET == pSet->GetItemState(SID_DOC_STARTPRESENTATION)&&
283 pSet->Get( SID_DOC_STARTPRESENTATION ).GetValue() )
284 {
285 bStartPresentation = true;
286 mpDoc->SetStartWithPresentation( true );
287 }
288 }
289
290 bRet = SfxObjectShell::Load( rMedium );
291 if (bRet)
292 {
293 comphelper::EmbeddedObjectContainer& rEmbeddedObjectContainer = getEmbeddedObjectContainer();
294 rEmbeddedObjectContainer.setUserAllowsLinkUpdate(false);
295 bRet = SdXMLFilter( rMedium, *this, SDXMLMODE_Normal, SotStorage::GetVersion( rMedium.GetStorage() ) ).Import( nError );
296 }
297
298 if( bRet )
299 {
300 // for legacy markup in OOoXML filter, convert the animations now
301 EffectMigration::DocumentLoaded(*GetDoc());
302 UpdateTablePointers();
303
304 // If we're an embedded OLE object, use tight bounds
305 // for our visArea. No point in showing the user lots of empty
306 // space. Had to remove the check for empty VisArea below,
307 // since XML load always sets a VisArea before.
308 //TODO/LATER: looks a little bit strange!
309 if( ( GetCreateMode() == SfxObjectCreateMode::EMBEDDED ) && SfxObjectShell::GetVisArea( ASPECT_CONTENT ).IsEmpty() )
310 {
311 SdPage* pPage = mpDoc->GetSdPage( 0, PageKind::Standard );
312
313 if( pPage )
314 SetVisArea( pPage->GetAllObjBoundRect() );
315 }
316
317 FinishedLoading();
318
319 const INetURLObject aUrl;
320 SfxObjectShell::SetAutoLoad( aUrl, 0, false );
321 }
322 else
323 {
324 if( nError == ERRCODE_IO_BROKENPACKAGE )
325 SetError(ERRCODE_IO_BROKENPACKAGE);
326
327 // TODO/LATER: correct error handling?!
328 //pStore->SetError(SVSTREAM_WRONGVERSION);
329 else
330 SetError(ERRCODE_ABORT);
331 }
332
333 // tell SFX to change viewshell when in preview mode
334 if( IsPreview() || bStartPresentation )
335 {
336 SfxItemSet *pMediumSet = GetMedium()->GetItemSet();
337 if( pMediumSet )
338 pMediumSet->Put( SfxUInt16Item( SID_VIEW_ID, bStartPresentation ? 1 : 5 ) );
339 }
340
341 return bRet;
342 }
343
344 /**
345 * loads content for organizer
346 */
LoadFrom(SfxMedium & rMedium)347 bool DrawDocShell::LoadFrom( SfxMedium& rMedium )
348 {
349 std::unique_ptr<WaitObject> pWait;
350 if( mpViewShell )
351 pWait.reset(new WaitObject( static_cast<vcl::Window*>(mpViewShell->GetActiveWindow()) ));
352
353 mpDoc->NewOrLoadCompleted( NEW_DOC );
354 mpDoc->CreateFirstPages();
355 mpDoc->StopWorkStartupDelay();
356
357 // TODO/LATER: nobody is interested in the error code?!
358 ErrCode nError = ERRCODE_NONE;
359 bool bRet = SdXMLFilter( rMedium, *this, SDXMLMODE_Organizer, SotStorage::GetVersion( rMedium.GetStorage() ) ).Import( nError );
360
361 // tell SFX to change viewshell when in preview mode
362 if( IsPreview() )
363 {
364 SfxItemSet *pSet = GetMedium()->GetItemSet();
365
366 if( pSet )
367 pSet->Put( SfxUInt16Item( SID_VIEW_ID, 5 ) );
368 }
369
370 return bRet;
371 }
372
373 /**
374 * load from 3rd party format
375 */
ImportFrom(SfxMedium & rMedium,uno::Reference<text::XTextRange> const & xInsertPosition)376 bool DrawDocShell::ImportFrom(SfxMedium &rMedium,
377 uno::Reference<text::XTextRange> const& xInsertPosition)
378 {
379 const OUString aFilterName( rMedium.GetFilter()->GetFilterName() );
380 if (aFilterName == "Impress MS PowerPoint 2007 XML" ||
381 aFilterName == "Impress MS PowerPoint 2007 XML AutoPlay" ||
382 aFilterName == "Impress MS PowerPoint 2007 XML VBA")
383 {
384 // As this is a MSFT format, we should use the "MS Compat"
385 // mode for spacing before and after paragraphs.
386
387 // This is copied from what is done for .ppt import in
388 // ImplSdPPTImport::Import() in sd/source/filter/ppt/pptin.cxx
389 // in. We need to tell both the edit engine of the draw outliner,
390 // and the document, to do "summation of paragraphs".
391 SdrOutliner& rOutl = mpDoc->GetDrawOutliner();
392 EEControlBits nControlWord = rOutl.GetEditEngine().GetControlWord();
393 nControlWord |= EEControlBits::ULSPACESUMMATION;
394 const_cast<EditEngine&>(rOutl.GetEditEngine()).SetControlWord( nControlWord );
395
396 mpDoc->SetSummationOfParagraphs();
397 }
398
399 const bool bRet = SfxObjectShell::ImportFrom(rMedium, xInsertPosition);
400
401 SfxItemSet* pSet = rMedium.GetItemSet();
402 if( pSet )
403 {
404 if( SfxItemState::SET == pSet->GetItemState(SID_DOC_STARTPRESENTATION)&&
405 pSet->Get( SID_DOC_STARTPRESENTATION ).GetValue() )
406 {
407 mpDoc->SetStartWithPresentation( true );
408
409 // tell SFX to change viewshell when in preview mode
410 if( IsPreview() )
411 {
412 SfxItemSet *pMediumSet = GetMedium()->GetItemSet();
413 if( pMediumSet )
414 pMediumSet->Put( SfxUInt16Item( SID_VIEW_ID, 1 ) );
415 }
416 }
417 }
418
419 return bRet;
420 }
421
422 /**
423 * load from a foreign format
424 */
ConvertFrom(SfxMedium & rMedium)425 bool DrawDocShell::ConvertFrom( SfxMedium& rMedium )
426 {
427 const OUString aFilterName( rMedium.GetFilter()->GetFilterName() );
428 bool bRet = false;
429 bool bStartPresentation = false;
430
431 SetWaitCursor( true );
432
433 SfxItemSet* pSet = rMedium.GetItemSet();
434 if( pSet )
435 {
436 if( ( SfxItemState::SET == pSet->GetItemState(SID_PREVIEW ) ) && pSet->Get( SID_PREVIEW ).GetValue() )
437 {
438 mpDoc->SetStarDrawPreviewMode( true );
439 }
440
441 if( SfxItemState::SET == pSet->GetItemState(SID_DOC_STARTPRESENTATION)&&
442 pSet->Get( SID_DOC_STARTPRESENTATION ).GetValue() )
443 {
444 bStartPresentation = true;
445 mpDoc->SetStartWithPresentation( true );
446 }
447 }
448
449 if( aFilterName == pFilterPowerPoint97
450 || aFilterName == pFilterPowerPoint97Template
451 || aFilterName == pFilterPowerPoint97AutoPlay)
452 {
453 mpDoc->StopWorkStartupDelay();
454 bRet = SdPPTFilter( rMedium, *this ).Import();
455 }
456 else if (aFilterName.indexOf("impress8") >= 0 ||
457 aFilterName.indexOf("draw8") >= 0)
458 {
459 // TODO/LATER: nobody is interested in the error code?!
460 mpDoc->CreateFirstPages();
461 mpDoc->StopWorkStartupDelay();
462 ErrCode nError = ERRCODE_NONE;
463 bRet = SdXMLFilter( rMedium, *this ).Import( nError );
464
465 }
466 else if (aFilterName.indexOf("StarOffice XML (Draw)") >= 0 ||
467 aFilterName.indexOf("StarOffice XML (Impress)") >= 0)
468 {
469 // TODO/LATER: nobody is interested in the error code?!
470 mpDoc->CreateFirstPages();
471 mpDoc->StopWorkStartupDelay();
472 ErrCode nError = ERRCODE_NONE;
473 bRet = SdXMLFilter( rMedium, *this, SDXMLMODE_Normal, SOFFICE_FILEFORMAT_60 ).Import( nError );
474 }
475 else if (aFilterName == "CGM - Computer Graphics Metafile")
476 {
477 mpDoc->CreateFirstPages();
478 mpDoc->StopWorkStartupDelay();
479 bRet = SdCGMFilter( rMedium, *this ).Import();
480 }
481 else if (aFilterName == "draw_pdf_import")
482 {
483 mpDoc->CreateFirstPages();
484 mpDoc->StopWorkStartupDelay();
485 bRet = SdPdfFilter(rMedium, *this).Import();
486 }
487 else
488 {
489 mpDoc->CreateFirstPages();
490 mpDoc->StopWorkStartupDelay();
491 bRet = SdGRFFilter( rMedium, *this ).Import();
492 }
493
494 FinishedLoading();
495
496 // tell SFX to change viewshell when in preview mode
497 if( IsPreview() )
498 {
499 SfxItemSet *pMediumSet = GetMedium()->GetItemSet();
500
501 if( pMediumSet )
502 pMediumSet->Put( SfxUInt16Item( SID_VIEW_ID, 5 ) );
503 }
504 SetWaitCursor( false );
505
506 // tell SFX to change viewshell when in preview mode
507 if( IsPreview() || bStartPresentation )
508 {
509 SfxItemSet *pMediumSet = GetMedium()->GetItemSet();
510 if( pMediumSet )
511 pMediumSet->Put( SfxUInt16Item( SID_VIEW_ID, bStartPresentation ? 1 : 5 ) );
512 }
513
514 return bRet;
515 }
516
517 /**
518 * Writes pools and document to the open streams
519 */
Save()520 bool DrawDocShell::Save()
521 {
522 mpDoc->StopWorkStartupDelay();
523
524 //TODO/LATER: why this?!
525 if( GetCreateMode() == SfxObjectCreateMode::STANDARD )
526 SfxObjectShell::SetVisArea( ::tools::Rectangle() );
527
528 bool bRet = SfxObjectShell::Save();
529
530 if( bRet )
531 bRet = SdXMLFilter( *GetMedium(), *this, SDXMLMODE_Normal, SotStorage::GetVersion( GetMedium()->GetStorage() ) ).Export();
532
533 return bRet;
534 }
535
536 /**
537 * Writes pools and document to the provided storage
538 */
SaveAs(SfxMedium & rMedium)539 bool DrawDocShell::SaveAs( SfxMedium& rMedium )
540 {
541 mpDoc->setDocAccTitle(OUString());
542 if (SfxViewFrame* pFrame1 = SfxViewFrame::GetFirst(this))
543 {
544 if (vcl::Window* pSysWin = pFrame1->GetWindow().GetSystemWindow())
545 {
546 pSysWin->SetAccessibleName(OUString());
547 }
548 }
549 mpDoc->StopWorkStartupDelay();
550
551 //With custom animation, if Outliner is modified, update text before saving
552 if( mpViewShell )
553 {
554 SdPage* pPage = mpViewShell->getCurrentPage();
555 if( pPage && pPage->getMainSequence()->getCount() )
556 {
557 SdrObject* pObj = mpViewShell->GetView()->GetTextEditObject();
558 SdrOutliner* pOutl = mpViewShell->GetView()->GetTextEditOutliner();
559 if( pObj && pOutl && pOutl->IsModified() )
560 {
561 std::unique_ptr<OutlinerParaObject> pNewText = pOutl->CreateParaObject( 0, pOutl->GetParagraphCount() );
562 pObj->SetOutlinerParaObject( std::move(pNewText) );
563 pOutl->ClearModifyFlag();
564 }
565 }
566 }
567
568 //TODO/LATER: why this?!
569 if( GetCreateMode() == SfxObjectCreateMode::STANDARD )
570 SfxObjectShell::SetVisArea( ::tools::Rectangle() );
571
572 bool bRet = SfxObjectShell::SaveAs( rMedium );
573
574 if( bRet )
575 bRet = SdXMLFilter( rMedium, *this, SDXMLMODE_Normal, SotStorage::GetVersion( rMedium.GetStorage() ) ).Export();
576
577 if( GetError() == ERRCODE_NONE )
578 SetError(ERRCODE_NONE);
579
580 return bRet;
581 }
582
583 /**
584 * save to foreign format
585 */
ConvertTo(SfxMedium & rMedium)586 bool DrawDocShell::ConvertTo( SfxMedium& rMedium )
587 {
588 bool bRet = false;
589
590 if( mpDoc->GetPageCount() )
591 {
592 std::shared_ptr<const SfxFilter> pMediumFilter = rMedium.GetFilter();
593 const OUString aTypeName( pMediumFilter->GetTypeName() );
594 std::unique_ptr<SdFilter> xFilter;
595
596 if( aTypeName.indexOf( "graphic_HTML" ) >= 0 )
597 {
598 xFilter = std::make_unique<SdHTMLFilter>(rMedium, *this);
599 }
600 else if( aTypeName.indexOf( "MS_PowerPoint_97" ) >= 0 )
601 {
602 xFilter = std::make_unique<SdPPTFilter>(rMedium, *this);
603 static_cast<SdPPTFilter*>(xFilter.get())->PreSaveBasic();
604 }
605 else if ( aTypeName.indexOf( "CGM_Computer_Graphics_Metafile" ) >= 0 )
606 {
607 xFilter = std::make_unique<SdCGMFilter>(rMedium, *this);
608 }
609 else if( aTypeName.indexOf( "draw8" ) >= 0 ||
610 aTypeName.indexOf( "impress8" ) >= 0 )
611 {
612 xFilter = std::make_unique<SdXMLFilter>(rMedium, *this);
613 }
614 else if( aTypeName.indexOf( "StarOffice_XML_Impress" ) >= 0 ||
615 aTypeName.indexOf( "StarOffice_XML_Draw" ) >= 0 )
616 {
617 xFilter = std::make_unique<SdXMLFilter>(rMedium, *this, SDXMLMODE_Normal, SOFFICE_FILEFORMAT_60);
618 }
619 else
620 {
621 xFilter = std::make_unique<SdGRFFilter>(rMedium, *this);
622 }
623
624 if (xFilter)
625 {
626 if ( mpViewShell )
627 {
628 ::sd::View* pView = mpViewShell->GetView();
629 if ( pView->IsTextEdit() )
630 pView->SdrEndTextEdit();
631 }
632
633 bRet = xFilter->Export();
634 }
635 }
636
637 return bRet;
638 }
639
640 /**
641 * Reopen own streams to ensure that nobody else can prevent use from opening
642 * them.
643 */
SaveCompleted(const css::uno::Reference<css::embed::XStorage> & xStorage)644 bool DrawDocShell::SaveCompleted( const css::uno::Reference< css::embed::XStorage >& xStorage )
645 {
646 bool bRet = false;
647
648 if( SfxObjectShell::SaveCompleted(xStorage) )
649 {
650 mpDoc->NbcSetChanged( false );
651
652 if( mpViewShell )
653 {
654 if( dynamic_cast< OutlineViewShell *>( mpViewShell ) != nullptr )
655 static_cast<OutlineView*>(mpViewShell->GetView())
656 ->GetOutliner().ClearModifyFlag();
657
658 SdrOutliner* pOutl = mpViewShell->GetView()->GetTextEditOutliner();
659 if( pOutl )
660 {
661 SdrObject* pObj = mpViewShell->GetView()->GetTextEditObject();
662 if( pObj )
663 pObj->NbcSetOutlinerParaObject( pOutl->CreateParaObject() );
664
665 pOutl->ClearModifyFlag();
666 }
667 }
668
669 bRet = true;
670
671 SfxViewFrame* pFrame = ( mpViewShell && mpViewShell->GetViewFrame() ) ?
672 mpViewShell->GetViewFrame() :
673 SfxViewFrame::Current();
674
675 if( pFrame )
676 pFrame->GetBindings().Invalidate( SID_NAVIGATOR_STATE, true );
677 }
678 return bRet;
679 }
680
GetStyleSheetPool()681 SfxStyleSheetBasePool* DrawDocShell::GetStyleSheetPool()
682 {
683 return mpDoc->GetStyleSheetPool();
684 }
685
GotoBookmark(const OUString & rBookmark)686 void DrawDocShell::GotoBookmark(const OUString& rBookmark)
687 {
688 auto pDrawViewShell = dynamic_cast<DrawViewShell *>( mpViewShell );
689 if (!pDrawViewShell)
690 return;
691
692 ViewShellBase& rBase (mpViewShell->GetViewShellBase());
693
694 bool bIsMasterPage = false;
695 sal_uInt16 nPageNumber = SDRPAGE_NOTFOUND;
696 SdrObject* pObj = nullptr;
697
698 const OUString sInteraction( "action?" );
699 if ( rBookmark.match( sInteraction ) )
700 {
701 const OUString sJump( "jump=" );
702 if ( rBookmark.match( sJump, sInteraction.getLength() ) )
703 {
704 OUString aDestination( rBookmark.copy( sInteraction.getLength() + sJump.getLength() ) );
705 if ( aDestination.match( "firstslide" ) )
706 {
707 nPageNumber = 1;
708 }
709 else if ( aDestination.match( "lastslide" ) )
710 {
711 nPageNumber = mpDoc->GetPageCount() - 2;
712 }
713 else if ( aDestination.match( "previousslide" ) )
714 {
715 SdPage* pPage = pDrawViewShell->GetActualPage();
716 nPageNumber = pPage->GetPageNum();
717 nPageNumber = nPageNumber > 2 ? nPageNumber - 2 : SDRPAGE_NOTFOUND;
718 }
719 else if ( aDestination.match( "nextslide" ) )
720 {
721 SdPage* pPage = pDrawViewShell->GetActualPage();
722 nPageNumber = pPage->GetPageNum() + 2;
723 if ( nPageNumber >= mpDoc->GetPageCount() )
724 nPageNumber = SDRPAGE_NOTFOUND;
725 }
726 }
727 }
728 else
729 {
730 // Is the bookmark a page?
731 nPageNumber = mpDoc->GetPageByName( rBookmark, bIsMasterPage );
732
733 if (nPageNumber == SDRPAGE_NOTFOUND)
734 {
735 // Is the bookmark an object?
736 pObj = mpDoc->GetObj(rBookmark);
737
738 if (pObj)
739 {
740 nPageNumber = pObj->getSdrPageFromSdrObject()->GetPageNum();
741 }
742 }
743 }
744 if (nPageNumber != SDRPAGE_NOTFOUND)
745 {
746 // Jump to the bookmarked page. This is done in three steps.
747
748 SdPage* pPage;
749 if (bIsMasterPage)
750 pPage = static_cast<SdPage*>( mpDoc->GetMasterPage(nPageNumber) );
751 else
752 pPage = static_cast<SdPage*>( mpDoc->GetPage(nPageNumber) );
753
754 // 1.) Change the view shell to the edit view, the notes view,
755 // or the handout view.
756 PageKind eNewPageKind = pPage->GetPageKind();
757
758 if( (eNewPageKind != PageKind::Standard) && (mpDoc->GetDocumentType() == DocumentType::Draw) )
759 return;
760
761 if (eNewPageKind != pDrawViewShell->GetPageKind())
762 {
763 // change work area
764 GetFrameView()->SetPageKind(eNewPageKind);
765 OUString sViewURL;
766 switch (eNewPageKind)
767 {
768 case PageKind::Standard:
769 sViewURL = FrameworkHelper::msImpressViewURL;
770 break;
771 case PageKind::Notes:
772 sViewURL = FrameworkHelper::msNotesViewURL;
773 break;
774 case PageKind::Handout:
775 sViewURL = FrameworkHelper::msHandoutViewURL;
776 break;
777 default:
778 break;
779 }
780 if (!sViewURL.isEmpty())
781 {
782 std::shared_ptr<FrameworkHelper> pHelper (
783 FrameworkHelper::Instance(rBase));
784 pHelper->RequestView(
785 sViewURL,
786 FrameworkHelper::msCenterPaneURL);
787 pHelper->WaitForUpdate();
788
789 // Get the new DrawViewShell.
790 mpViewShell = pHelper->GetViewShell(FrameworkHelper::msCenterPaneURL).get();
791 pDrawViewShell = dynamic_cast<sd::DrawViewShell*>(mpViewShell);
792 }
793 else
794 {
795 pDrawViewShell = nullptr;
796 }
797 }
798
799 if (pDrawViewShell != nullptr)
800 {
801 setEditMode(pDrawViewShell, bIsMasterPage);
802
803 // Make the bookmarked page the current page. This is done
804 // by using the API because this takes care of all the
805 // little things to be done. Especially writing the view
806 // data to the frame view.
807 sal_uInt16 nSdPgNum = (nPageNumber - 1) / 2;
808 Reference<drawing::XDrawView> xController (rBase.GetController(), UNO_QUERY);
809 if (xController.is())
810 {
811 Reference<drawing::XDrawPage> xDrawPage (pPage->getUnoPage(), UNO_QUERY);
812 xController->setCurrentPage (xDrawPage);
813 }
814 else
815 {
816 // As a fall back switch to the page via the core.
817 DBG_ASSERT (xController.is(),
818 "DrawDocShell::GotoBookmark: can't switch page via API");
819 pDrawViewShell->SwitchPage(nSdPgNum);
820 }
821
822 if (pDrawViewShell->GetDispatcher())
823 {
824 // show page
825 SvxZoomItem aZoom;
826 aZoom.SetType( SvxZoomType::WHOLEPAGE );
827 pDrawViewShell->GetDispatcher()->ExecuteList(SID_ATTR_ZOOM, SfxCallMode::ASYNCHRON, { &aZoom });
828 }
829
830 if (pObj != nullptr)
831 {
832 // select object
833 pDrawViewShell->GetView()->UnmarkAll();
834 pDrawViewShell->GetView()->MarkObj(
835 pObj,
836 pDrawViewShell->GetView()->GetSdrPageView());
837 }
838 }
839 }
840
841 SfxBindings& rBindings = ((pDrawViewShell && pDrawViewShell->GetViewFrame()!=nullptr)
842 ? pDrawViewShell->GetViewFrame()
843 : SfxViewFrame::Current() )->GetBindings();
844
845 rBindings.Invalidate(SID_NAVIGATOR_STATE, true);
846 rBindings.Invalidate(SID_NAVIGATOR_PAGENAME);
847 }
848
849 /**
850 * If it should become a document template.
851 */
SaveAsOwnFormat(SfxMedium & rMedium)852 bool DrawDocShell::SaveAsOwnFormat( SfxMedium& rMedium )
853 {
854
855 std::shared_ptr<const SfxFilter> pFilter = rMedium.GetFilter();
856
857 if (pFilter->IsOwnTemplateFormat())
858 {
859 /* now the StarDraw specialty:
860 we assign known layout names to the layout template of the first
861 page, we set the layout names of the affected masterpages and pages.
862 We inform all text objects of the affected standard, note and
863 masterpages about the name change.
864 */
865
866 OUString aLayoutName;
867
868 SfxStringItem const * pLayoutItem;
869 if( rMedium.GetItemSet()->GetItemState(SID_TEMPLATE_NAME, false, reinterpret_cast<const SfxPoolItem**>(& pLayoutItem) ) == SfxItemState::SET )
870 {
871 aLayoutName = pLayoutItem->GetValue();
872 }
873 else
874 {
875 INetURLObject aURL( rMedium.GetName() );
876 aURL.removeExtension();
877 aLayoutName = aURL.getName();
878 }
879
880 if (aLayoutName.isEmpty())
881 {
882 sal_uInt32 nCount = mpDoc->GetMasterSdPageCount(PageKind::Standard);
883 for (sal_uInt32 i = 0; i < nCount; ++i)
884 {
885 OUString aOldPageLayoutName = mpDoc->GetMasterSdPage(i, PageKind::Standard)->GetLayoutName();
886 OUString aNewLayoutName = aLayoutName;
887 // Don't add suffix for the first master page
888 if( i > 0 )
889 aNewLayoutName += OUString::number(i);
890
891 mpDoc->RenameLayoutTemplate(aOldPageLayoutName, aNewLayoutName);
892 }
893 }
894 }
895
896 return SfxObjectShell::SaveAsOwnFormat(rMedium);
897 }
898
FillClass(SvGlobalName * pClassName,SotClipboardFormatId * pFormat,OUString * pFullTypeName,sal_Int32 nFileFormat,bool bTemplate) const899 void DrawDocShell::FillClass(SvGlobalName* pClassName,
900 SotClipboardFormatId* pFormat,
901 OUString* pFullTypeName,
902 sal_Int32 nFileFormat,
903 bool bTemplate /* = false */) const
904 {
905 if (nFileFormat == SOFFICE_FILEFORMAT_60)
906 {
907 if ( meDocType == DocumentType::Draw )
908 {
909 *pClassName = SvGlobalName(SO3_SDRAW_CLASSID_60);
910 *pFormat = SotClipboardFormatId::STARDRAW_60;
911 *pFullTypeName = SdResId(STR_GRAPHIC_DOCUMENT_FULLTYPE_60);
912 }
913 else
914 {
915 *pClassName = SvGlobalName(SO3_SIMPRESS_CLASSID_60);
916 *pFormat = SotClipboardFormatId::STARIMPRESS_60;
917 *pFullTypeName = SdResId(STR_IMPRESS_DOCUMENT_FULLTYPE_60);
918 }
919 }
920 else if (nFileFormat == SOFFICE_FILEFORMAT_8)
921 {
922 if ( meDocType == DocumentType::Draw )
923 {
924 *pClassName = SvGlobalName(SO3_SDRAW_CLASSID_60);
925 *pFormat = bTemplate ? SotClipboardFormatId::STARDRAW_8_TEMPLATE : SotClipboardFormatId::STARDRAW_8;
926 *pFullTypeName = SdResId(STR_GRAPHIC_DOCUMENT_FULLTYPE_80); // HACK: method will be removed with new storage API
927 }
928 else
929 {
930 *pClassName = SvGlobalName(SO3_SIMPRESS_CLASSID_60);
931 *pFormat = bTemplate ? SotClipboardFormatId::STARIMPRESS_8_TEMPLATE : SotClipboardFormatId::STARIMPRESS_8;
932 *pFullTypeName = SdResId(STR_IMPRESS_DOCUMENT_FULLTYPE_80); // HACK: method will be removed with new storage API
933 }
934 }
935 }
936
GetDocumentRefDev()937 OutputDevice* DrawDocShell::GetDocumentRefDev()
938 {
939 OutputDevice* pReferenceDevice = SfxObjectShell::GetDocumentRefDev ();
940 // Only when our parent does not have a reference device then we return
941 // our own.
942 if (pReferenceDevice == nullptr && mpDoc != nullptr)
943 pReferenceDevice = mpDoc->GetRefDevice ();
944 return pReferenceDevice;
945 }
946
947 /** executes the SID_OPENDOC slot to let the framework open a document
948 with the given URL and this document as a referer */
OpenBookmark(const OUString & rBookmarkURL)949 void DrawDocShell::OpenBookmark( const OUString& rBookmarkURL )
950 {
951 SfxStringItem aStrItem( SID_FILE_NAME, rBookmarkURL );
952 SfxStringItem aReferer( SID_REFERER, GetMedium()->GetName() );
953 const SfxPoolItem* ppArgs[] = { &aStrItem, &aReferer, nullptr };
954 ( mpViewShell ? mpViewShell->GetViewFrame() : SfxViewFrame::Current() )->GetBindings().Execute( SID_OPENHYPERLINK, ppArgs );
955 }
956
CreateDocumentInfoDialog(weld::Window * pParent,const SfxItemSet & rSet)957 std::unique_ptr<SfxDocumentInfoDialog> DrawDocShell::CreateDocumentInfoDialog(weld::Window* pParent, const SfxItemSet &rSet)
958 {
959 std::unique_ptr<SfxDocumentInfoDialog> xDlg = std::make_unique<SfxDocumentInfoDialog>(pParent, rSet);
960 DrawDocShell* pDocSh = dynamic_cast<DrawDocShell*>(SfxObjectShell::Current());
961 if( pDocSh == this )
962 {
963 xDlg->AddFontTabPage();
964 }
965 return xDlg;
966 }
967
setEditMode(DrawViewShell * pDrawViewShell,bool isMasterPage)968 void DrawDocShell::setEditMode(DrawViewShell* pDrawViewShell, bool isMasterPage)
969 {
970 // Set the edit mode to either the normal edit mode or the
971 // master page mode.
972 EditMode eNewEditMode = EditMode::Page;
973 if (isMasterPage)
974 {
975 eNewEditMode = EditMode::MasterPage;
976 }
977
978 if (eNewEditMode != pDrawViewShell->GetEditMode())
979 {
980 // Set EditMode
981 pDrawViewShell->ChangeEditMode(eNewEditMode, false);
982 }
983 }
984 } // end of namespace sd
985
986 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
987