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