1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <sal/config.h>
21 #include <sal/log.hxx>
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/compatflags.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 <sfx2/infobar.hxx>
42 #include <svx/svdotext.hxx>
43 #include <sfx2/printer.hxx>
44 #include <svtools/ctrltool.hxx>
45 #include <comphelper/classids.hxx>
46 #include <comphelper/scopeguard.hxx>
47 #include <sot/formats.hxx>
48 #include <sfx2/viewfrm.hxx>
49 #include <vcl/syswin.hxx>
50 #include <com/sun/star/drawing/XDrawPage.hpp>
51 #include <com/sun/star/drawing/XDrawView.hpp>
54 #include <strings.hrc>
55 #include <FrameView.hxx>
56 #include <optsitem.hxx>
57 #include <Outliner.hxx>
59 #include <drawdoc.hxx>
60 #include <ViewShell.hxx>
63 #include <EffectMigration.hxx>
64 #include <CustomAnimationEffect.hxx>
66 #include <sdresid.hxx>
67 #include <DrawViewShell.hxx>
68 #include <ViewShellBase.hxx>
69 #include <OutlineView.hxx>
70 #include <OutlineViewShell.hxx>
71 #include <sdxmlwrp.hxx>
72 #include <sdpptwrp.hxx>
73 #include <sdcgmfilter.hxx>
74 #include <sdgrffilter.hxx>
75 #include <sdhtmlfilter.hxx>
76 #include <sdpdffilter.hxx>
77 #include <framework/FrameworkHelper.hxx>
78 #include <o3tl/string_view.hxx>
81 #include <svl/intitem.hxx>
82 #include <DrawController.hxx>
84 using namespace ::com::sun::star
;
85 using namespace ::com::sun::star::uno
;
86 using ::sd::framework::FrameworkHelper
;
89 constexpr OUStringLiteral
pFilterPowerPoint97( u
"MS PowerPoint 97" );
90 constexpr OUStringLiteral
pFilterPowerPoint97Template( u
"MS PowerPoint 97 Vorlage" );
91 constexpr OUStringLiteral
pFilterPowerPoint97AutoPlay( u
"MS PowerPoint 97 AutoPlay" );
96 * Creates (if necessary) and returns a SfxPrinter
98 SfxPrinter
* DrawDocShell::GetPrinter(bool bCreate
)
100 if (bCreate
&& !mpPrinter
)
102 // create ItemSet with special pool area
103 auto pSet
= std::make_unique
<SfxItemSetFixed
<
104 SID_PRINTER_NOTFOUND_WARN
, SID_PRINTER_NOTFOUND_WARN
,
105 SID_PRINTER_CHANGESTODOC
, SID_PRINTER_CHANGESTODOC
,
106 ATTR_OPTIONS_PRINT
, ATTR_OPTIONS_PRINT
>>( GetPool() );
107 // set PrintOptionsSet
108 SdOptionsPrintItem
aPrintItem(SdModule::get()->GetSdOptions(mpDoc
->GetDocumentType()));
109 SfxFlagItem
aFlagItem( SID_PRINTER_CHANGESTODOC
);
110 SfxPrinterChangeFlags nFlags
=
111 (aPrintItem
.GetOptionsPrint().IsWarningSize() ? SfxPrinterChangeFlags::CHG_SIZE
: SfxPrinterChangeFlags::NONE
) |
112 (aPrintItem
.GetOptionsPrint().IsWarningOrientation() ? SfxPrinterChangeFlags::CHG_ORIENTATION
: SfxPrinterChangeFlags::NONE
);
113 aFlagItem
.SetValue( static_cast<int>(nFlags
) );
115 pSet
->Put( aPrintItem
);
116 pSet
->Put( SfxBoolItem( SID_PRINTER_NOTFOUND_WARN
, aPrintItem
.GetOptionsPrint().IsWarningPrinter() ) );
117 pSet
->Put( aFlagItem
);
119 mpPrinter
= VclPtr
<SfxPrinter
>::Create(std::move(pSet
));
122 // set output quality
123 sal_uInt16 nQuality
= aPrintItem
.GetOptionsPrint().GetOutputQuality();
125 DrawModeFlags nMode
= DrawModeFlags::Default
;
126 // 1 == Grayscale, 2 == Black & White (with grayscale images)
128 nMode
= DrawModeFlags::GrayLine
| DrawModeFlags::GrayFill
| DrawModeFlags::GrayText
| DrawModeFlags::GrayBitmap
| DrawModeFlags::GrayGradient
;
129 else if( nQuality
== 2 )
130 nMode
= DrawModeFlags::BlackLine
| DrawModeFlags::WhiteFill
| DrawModeFlags::BlackText
| DrawModeFlags::GrayBitmap
| DrawModeFlags::WhiteGradient
;
132 mpPrinter
->SetDrawMode( nMode
);
134 MapMode
aMM (mpPrinter
->GetMapMode());
135 aMM
.SetMapUnit(MapUnit::Map100thMM
);
136 mpPrinter
->SetMapMode(aMM
);
143 * Set new SfxPrinter (transfer of ownership)
145 void DrawDocShell::SetPrinter(SfxPrinter
*pNewPrinter
)
149 ::sd::View
* pView
= mpViewShell
->GetView();
150 if ( pView
->IsTextEdit() )
151 pView
->SdrEndTextEdit();
154 if ( mpPrinter
&& mbOwnPrinter
&& (mpPrinter
.get() != pNewPrinter
) )
155 mpPrinter
.disposeAndClear();
157 mpPrinter
= pNewPrinter
;
159 if ( mpDoc
->GetPrinterIndependentLayout() == css::document::PrinterIndependentLayout::DISABLED
)
164 void DrawDocShell::UpdateFontList()
167 OutputDevice
* pRefDevice
= nullptr;
168 if ( mpDoc
->GetPrinterIndependentLayout() == css::document::PrinterIndependentLayout::DISABLED
)
169 pRefDevice
= GetPrinter(true);
171 pRefDevice
= SdModule::get()->GetVirtualRefDevice();
172 mpFontList
.reset( new FontList(pRefDevice
, nullptr) );
173 SvxFontListItem
aFontListItem( mpFontList
.get(), SID_ATTR_CHAR_FONTLIST
);
174 PutItem( aFontListItem
);
177 Printer
* DrawDocShell::GetDocumentPrinter()
179 return GetPrinter(false);
182 void DrawDocShell::OnDocumentPrinterChanged(Printer
* pNewPrinter
)
184 // if we already have a printer, see if it's the same
188 if( mpPrinter
== pNewPrinter
)
191 // compare if it's the same printer with the same job setup
192 if( (mpPrinter
->GetName() == pNewPrinter
->GetName()) &&
193 (mpPrinter
->GetJobSetup() == pNewPrinter
->GetJobSetup()))
197 SfxPrinter
* const pSfxPrinter
= dynamic_cast<SfxPrinter
*>(pNewPrinter
);
200 SetPrinter(pSfxPrinter
);
202 // container owns printer
203 mbOwnPrinter
= false;
207 void DrawDocShell::UpdateRefDevice()
212 // Determine the device for which the output will be formatted.
213 VclPtr
< OutputDevice
> pRefDevice
;
214 switch (mpDoc
->GetPrinterIndependentLayout())
216 case css::document::PrinterIndependentLayout::DISABLED
:
217 pRefDevice
= mpPrinter
.get();
220 case css::document::PrinterIndependentLayout::ENABLED
:
221 pRefDevice
= SdModule::get()->GetVirtualRefDevice();
225 // We are confronted with an invalid or un-implemented
226 // layout mode. Use the printer as formatting device
228 SAL_WARN( "sd", "DrawDocShell::UpdateRefDevice(): Unexpected printer layout mode");
230 pRefDevice
= mpPrinter
.get();
233 mpDoc
->SetRefDevice( pRefDevice
.get() );
235 SdOutliner
* pOutl
= mpDoc
->GetOutliner( false );
238 pOutl
->SetRefDevice( pRefDevice
);
240 SdOutliner
* pInternalOutl
= mpDoc
->GetInternalOutliner( false );
243 pInternalOutl
->SetRefDevice( pRefDevice
);
247 * Creates new document, opens streams
249 bool DrawDocShell::InitNew( const css::uno::Reference
< css::embed::XStorage
>& xStorage
)
251 bool bRet
= SfxObjectShell::InitNew( xStorage
);
253 ::tools::Rectangle
aVisArea( Point(0, 0), Size(14100, 10000) );
254 SetVisArea(aVisArea
);
259 mpDoc
->NewOrLoadCompleted(DocCreationMode::New
); // otherwise calling
260 // NewOrLoadCompleted(NEW_LOADED) in
261 // SdDrawDocument::AllocModel()
267 * loads pools and document
269 bool DrawDocShell::Load( SfxMedium
& rMedium
)
271 // If this is an ODF file being loaded, then by default, use legacy processing
272 // (if required, it will be overridden in *::ReadUserDataSequence())
273 if (IsOwnStorageFormat(rMedium
))
275 mpDoc
->SetCompatibilityFlag(SdrCompatibilityFlag::AnchoredTextOverflowLegacy
, true); // for tdf#99729
276 mpDoc
->SetCompatibilityFlag(SdrCompatibilityFlag::LegacyFontwork
, true); // for tdf#148000
280 bool bStartPresentation
= false;
281 ErrCode nError
= ERRCODE_NONE
;
283 SfxItemSet
& rSet
= rMedium
.GetItemSet();
285 if( ( SfxItemState::SET
== rSet
.GetItemState(SID_PREVIEW
) ) && rSet
.Get( SID_PREVIEW
).GetValue() )
287 mpDoc
->SetStarDrawPreviewMode( true );
290 bRet
= SfxObjectShell::Load( rMedium
);
293 comphelper::EmbeddedObjectContainer
& rEmbeddedObjectContainer
= getEmbeddedObjectContainer();
294 rEmbeddedObjectContainer
.setUserAllowsLinkUpdate(false);
295 bRet
= SdXMLFilter( rMedium
, *this, SdXMLFilterMode::Normal
, SotStorage::GetVersion( rMedium
.GetStorage() ) ).Import( nError
);
300 SdDrawDocument
* pDoc
= GetDoc();
302 // for legacy markup in OOoXML filter, convert the animations now
303 EffectMigration::DocumentLoaded(*pDoc
);
304 UpdateTablePointers();
306 // If we're an embedded OLE object, use tight bounds
307 // for our visArea. No point in showing the user lots of empty
308 // space. Had to remove the check for empty VisArea below,
309 // since XML load always sets a VisArea before.
310 //TODO/LATER: looks a little bit strange!
311 if( ( GetCreateMode() == SfxObjectCreateMode::EMBEDDED
) && SfxObjectShell::GetVisArea( ASPECT_CONTENT
).IsEmpty() )
313 SdPage
* pPage
= mpDoc
->GetSdPage( 0, PageKind::Standard
);
316 SetVisArea( pPage
->GetAllObjBoundRect() );
321 const INetURLObject aUrl
;
322 SfxObjectShell::SetAutoLoad( aUrl
, 0, false );
324 const sal_uInt16 nMasterPages
= pDoc
->GetMasterSdPageCount(PageKind::Standard
);
325 if (nMasterPages
> 100)
327 const LocaleDataWrapper
& rLocaleData
= Application::GetSettings().GetLocaleDataWrapper();
328 OUString sMasterPages
= rLocaleData
.getNum(nMasterPages
, 0, true, false);
329 AppendInfoBarWhenReady(u
"toomanymasterpages"_ustr
, SdResId(STR_MANY_MASTER_PAGES
).replaceFirst("%n", sMasterPages
),
330 SdResId(STR_MANY_MASTER_PAGES_DETAIL
), InfobarType::INFO
);
335 if( nError
== ERRCODE_IO_BROKENPACKAGE
)
336 SetError(ERRCODE_IO_BROKENPACKAGE
);
338 // TODO/LATER: correct error handling?!
339 //pStore->SetError(SVSTREAM_WRONGVERSION);
341 SetError(ERRCODE_ABORT
);
344 if (SfxItemState::SET
== rSet
.GetItemState(SID_DOC_STARTPRESENTATION
))
346 sal_uInt16 nStartingSlide
= rSet
.Get(SID_DOC_STARTPRESENTATION
).GetValue();
347 if (nStartingSlide
== 0)
349 OUString sStartPage
= mpDoc
->getPresentationSettings().maPresPage
;
350 if (!sStartPage
.isEmpty())
352 bool bIsMasterPage
= false;
353 sal_uInt16 nPageNumb
= mpDoc
->GetPageByName(sStartPage
, bIsMasterPage
);
354 nStartingSlide
= (nPageNumb
+ 1) / 2;
359 bStartPresentation
= nStartingSlide
;
360 mpDoc
->SetStartWithPresentation(nStartingSlide
);
363 // tell SFX to change viewshell when in preview mode
364 if( IsPreview() || bStartPresentation
)
366 GetMedium()->GetItemSet().Put( SfxUInt16Item( SID_VIEW_ID
, bStartPresentation
? 1 : 5 ) );
373 * loads content for organizer
375 bool DrawDocShell::LoadFrom( SfxMedium
& rMedium
)
377 std::unique_ptr
<weld::WaitObject
> pWait
;
379 pWait
.reset(new weld::WaitObject(mpViewShell
->GetFrameWeld()));
381 mpDoc
->NewOrLoadCompleted( DocCreationMode::New
);
382 mpDoc
->CreateFirstPages();
383 mpDoc
->StopWorkStartupDelay();
385 // TODO/LATER: nobody is interested in the error code?!
386 ErrCode nError
= ERRCODE_NONE
;
387 bool bRet
= SdXMLFilter( rMedium
, *this, SdXMLFilterMode::Organizer
, SotStorage::GetVersion( rMedium
.GetStorage() ) ).Import( nError
);
389 // tell SFX to change viewshell when in preview mode
392 GetMedium()->GetItemSet().Put( SfxUInt16Item( SID_VIEW_ID
, 5 ) );
399 * load from 3rd party format
401 bool DrawDocShell::ImportFrom(SfxMedium
&rMedium
,
402 uno::Reference
<text::XTextRange
> const& xInsertPosition
)
404 const OUString
aFilterName( rMedium
.GetFilter()->GetFilterName() );
405 if (aFilterName
== "Impress MS PowerPoint 2007 XML" ||
406 aFilterName
== "Impress MS PowerPoint 2007 XML AutoPlay" ||
407 aFilterName
== "Impress MS PowerPoint 2007 XML VBA")
409 // As this is a MSFT format, we should use the "MS Compat"
410 // mode for spacing before and after paragraphs.
412 // This is copied from what is done for .ppt import in
413 // ImplSdPPTImport::Import() in sd/source/filter/ppt/pptin.cxx
414 // in. We need to tell both the edit engine of the draw outliner,
415 // and the document, to do "summation of paragraphs".
416 SdrOutliner
& rOutl
= mpDoc
->GetDrawOutliner();
417 EEControlBits nControlWord
= rOutl
.GetEditEngine().GetControlWord();
418 nControlWord
|= EEControlBits::ULSPACESUMMATION
;
419 const_cast<EditEngine
&>(rOutl
.GetEditEngine()).SetControlWord( nControlWord
);
421 mpDoc
->SetSummationOfParagraphs();
424 if (aFilterName
== "Impress MS PowerPoint 2007 XML")
426 // This is a "MS Compact" mode for connectors.
427 // The Libreoffice uses bounding rectangle of connected shapes but
428 // MSO uses snap rectangle when calculate the edge track.
429 mpDoc
->SetCompatibilityFlag(SdrCompatibilityFlag::ConnectorUseSnapRect
, true);
431 // compatibility flag for tdf#148966
432 mpDoc
->SetCompatibilityFlag(SdrCompatibilityFlag::IgnoreBreakAfterMultilineField
, true);
435 if (aFilterName
== "Impress MS PowerPoint 2007 XML" ||
436 aFilterName
== "Impress MS PowerPoint 2007 XML AutoPlay" ||
437 aFilterName
== "Impress MS PowerPoint 2007 XML VBA" ||
438 aFilterName
== "Impress Office Open XML")
440 // We need to be able to set the default tab size for each text object.
441 // This is possible at the moment only for the whole document. See
442 // TextParagraphPropertiesContext constructor. So default tab width
443 // of the LibreOffice is 1270 but MSO is 2540 on general settings.
444 mpDoc
->SetDefaultTabulator( 2540 );
447 comphelper::ScopeGuard
undoGuard([this, wasUndo
= mpDoc
->IsUndoEnabled()]
448 { mpDoc
->EnableUndo(wasUndo
); });
449 if (xInsertPosition
) // insert mode
453 else // initial loading of the document
455 mpDoc
->EnableUndo(false);
458 const bool bRet
= SfxObjectShell::ImportFrom(rMedium
, xInsertPosition
);
460 SfxItemSet
& rSet
= rMedium
.GetItemSet();
461 if (SfxItemState::SET
== rSet
.GetItemState(SID_DOC_STARTPRESENTATION
))
463 sal_uInt16 nStartingSlide
= rSet
.Get(SID_DOC_STARTPRESENTATION
).GetValue();
464 if (nStartingSlide
== 0)
466 OUString sStartPage
= mpDoc
->getPresentationSettings().maPresPage
;
467 if (!sStartPage
.isEmpty())
469 bool bIsMasterPage
= false;
470 sal_uInt16 nPageNumb
= mpDoc
->GetPageByName(sStartPage
, bIsMasterPage
);
471 nStartingSlide
= (nPageNumb
+ 1) / 2;
476 mpDoc
->SetStartWithPresentation(nStartingSlide
);
478 // tell SFX to change viewshell when in preview mode
481 GetMedium()->GetItemSet().Put(SfxUInt16Item(SID_VIEW_ID
, 1));
489 * load from a foreign format
491 bool DrawDocShell::ConvertFrom( SfxMedium
& rMedium
)
493 const OUString
aFilterName( rMedium
.GetFilter()->GetFilterName() );
495 bool bStartPresentation
= false;
497 SetWaitCursor( true );
499 SfxItemSet
& rSet
= rMedium
.GetItemSet();
500 if( ( SfxItemState::SET
== rSet
.GetItemState(SID_PREVIEW
) ) && rSet
.Get( SID_PREVIEW
).GetValue() )
502 mpDoc
->SetStarDrawPreviewMode( true );
505 if (SfxItemState::SET
== rSet
.GetItemState(SID_DOC_STARTPRESENTATION
))
507 sal_uInt16 nStartingSlide
= rSet
.Get(SID_DOC_STARTPRESENTATION
).GetValue();
508 if (nStartingSlide
== 0)
510 OUString sStartPage
= mpDoc
->getPresentationSettings().maPresPage
;
511 if (!sStartPage
.isEmpty())
513 bool bIsMasterPage
= false;
514 sal_uInt16 nPageNumb
= mpDoc
->GetPageByName(sStartPage
, bIsMasterPage
);
515 nStartingSlide
= (nPageNumb
+ 1) / 2;
520 bStartPresentation
= nStartingSlide
;
521 mpDoc
->SetStartWithPresentation(nStartingSlide
);
524 if( aFilterName
== pFilterPowerPoint97
525 || aFilterName
== pFilterPowerPoint97Template
526 || aFilterName
== pFilterPowerPoint97AutoPlay
)
528 mpDoc
->StopWorkStartupDelay();
529 bRet
= SdPPTFilter( rMedium
, *this ).Import();
531 else if (aFilterName
.indexOf("impress8") >= 0 ||
532 aFilterName
.indexOf("draw8") >= 0)
534 // TODO/LATER: nobody is interested in the error code?!
535 mpDoc
->CreateFirstPages();
536 mpDoc
->StopWorkStartupDelay();
537 ErrCode nError
= ERRCODE_NONE
;
538 bRet
= SdXMLFilter( rMedium
, *this ).Import( nError
);
541 else if (aFilterName
.indexOf("StarOffice XML (Draw)") >= 0 ||
542 aFilterName
.indexOf("StarOffice XML (Impress)") >= 0)
544 // TODO/LATER: nobody is interested in the error code?!
545 mpDoc
->CreateFirstPages();
546 mpDoc
->StopWorkStartupDelay();
547 ErrCode nError
= ERRCODE_NONE
;
548 bRet
= SdXMLFilter( rMedium
, *this, SdXMLFilterMode::Normal
, SOFFICE_FILEFORMAT_60
).Import( nError
);
550 else if (aFilterName
== "CGM - Computer Graphics Metafile")
552 mpDoc
->CreateFirstPages();
553 mpDoc
->StopWorkStartupDelay();
554 bRet
= SdCGMFilter( rMedium
, *this ).Import();
556 else if (aFilterName
== "draw_pdf_import")
558 mpDoc
->CreateFirstPages();
559 mpDoc
->StopWorkStartupDelay();
560 bRet
= SdPdfFilter(rMedium
, *this).Import();
564 mpDoc
->CreateFirstPages();
565 mpDoc
->StopWorkStartupDelay();
566 bRet
= SdGRFFilter( rMedium
, *this ).Import();
571 // tell SFX to change viewshell when in preview mode
574 GetMedium()->GetItemSet().Put( SfxUInt16Item( SID_VIEW_ID
, 5 ) );
576 SetWaitCursor( false );
578 // tell SFX to change viewshell when in preview mode
579 if( IsPreview() || bStartPresentation
)
581 GetMedium()->GetItemSet().Put( SfxUInt16Item( SID_VIEW_ID
, bStartPresentation
? 1 : 5 ) );
588 * Writes pools and document to the open streams
590 bool DrawDocShell::Save()
592 mpDoc
->StopWorkStartupDelay();
594 //TODO/LATER: why this?!
595 if( GetCreateMode() == SfxObjectCreateMode::STANDARD
)
596 SfxObjectShell::SetVisArea( ::tools::Rectangle() );
598 bool bRet
= SfxObjectShell::Save();
601 bRet
= SdXMLFilter( *GetMedium(), *this, SdXMLFilterMode::Normal
, SotStorage::GetVersion( GetMedium()->GetStorage() ) ).Export();
607 * Writes pools and document to the provided storage
609 bool DrawDocShell::SaveAs( SfxMedium
& rMedium
)
611 mpDoc
->setDocAccTitle(OUString());
612 if (SfxViewFrame
* pFrame1
= SfxViewFrame::GetFirst(this))
614 if (vcl::Window
* pSysWin
= pFrame1
->GetWindow().GetSystemWindow())
616 pSysWin
->SetAccessibleName(OUString());
619 mpDoc
->StopWorkStartupDelay();
621 //With custom animation, if Outliner is modified, update text before saving
624 SdPage
* pPage
= mpViewShell
->getCurrentPage();
625 if( pPage
&& pPage
->getMainSequence()->getCount() )
627 SdrObject
* pObj
= mpViewShell
->GetView()->GetTextEditObject();
628 SdrOutliner
* pOutl
= mpViewShell
->GetView()->GetTextEditOutliner();
629 if( pObj
&& pOutl
&& pOutl
->IsModified() )
631 std::optional
<OutlinerParaObject
> pNewText
= pOutl
->CreateParaObject( 0, pOutl
->GetParagraphCount() );
632 pObj
->SetOutlinerParaObject( std::move(pNewText
) );
633 pOutl
->ClearModifyFlag();
638 //TODO/LATER: why this?!
639 if( GetCreateMode() == SfxObjectCreateMode::STANDARD
)
640 SfxObjectShell::SetVisArea( ::tools::Rectangle() );
642 bool bRet
= SfxObjectShell::SaveAs( rMedium
);
645 bRet
= SdXMLFilter( rMedium
, *this, SdXMLFilterMode::Normal
, SotStorage::GetVersion( rMedium
.GetStorage() ) ).Export();
647 if( GetErrorIgnoreWarning() == ERRCODE_NONE
)
648 SetError(ERRCODE_NONE
);
654 * save to foreign format
656 bool DrawDocShell::ConvertTo( SfxMedium
& rMedium
)
660 if( mpDoc
->GetPageCount() )
662 std::shared_ptr
<const SfxFilter
> pMediumFilter
= rMedium
.GetFilter();
663 const OUString
aTypeName( pMediumFilter
->GetTypeName() );
664 std::unique_ptr
<SdFilter
> xFilter
;
666 if( aTypeName
.indexOf( "graphic_HTML" ) >= 0 )
668 xFilter
= std::make_unique
<SdHTMLFilter
>(rMedium
, *this);
670 else if( aTypeName
.indexOf( "MS_PowerPoint_97" ) >= 0 )
672 xFilter
= std::make_unique
<SdPPTFilter
>(rMedium
, *this);
673 static_cast<SdPPTFilter
*>(xFilter
.get())->PreSaveBasic();
675 else if ( aTypeName
.indexOf( "CGM_Computer_Graphics_Metafile" ) >= 0 )
677 xFilter
= std::make_unique
<SdCGMFilter
>(rMedium
, *this);
679 else if( aTypeName
.indexOf( "draw8" ) >= 0 ||
680 aTypeName
.indexOf( "impress8" ) >= 0 )
682 xFilter
= std::make_unique
<SdXMLFilter
>(rMedium
, *this);
684 else if( aTypeName
.indexOf( "StarOffice_XML_Impress" ) >= 0 ||
685 aTypeName
.indexOf( "StarOffice_XML_Draw" ) >= 0 )
687 xFilter
= std::make_unique
<SdXMLFilter
>(rMedium
, *this, SdXMLFilterMode::Normal
, SOFFICE_FILEFORMAT_60
);
691 xFilter
= std::make_unique
<SdGRFFilter
>(rMedium
, *this);
698 ::sd::View
* pView
= mpViewShell
->GetView();
699 if ( pView
->IsTextEdit() )
700 pView
->SdrEndTextEdit();
703 bRet
= xFilter
->Export();
711 * Reopen own streams to ensure that nobody else can prevent use from opening
714 bool DrawDocShell::SaveCompleted( const css::uno::Reference
< css::embed::XStorage
>& xStorage
)
718 if( SfxObjectShell::SaveCompleted(xStorage
) )
720 mpDoc
->NbcSetChanged( false );
724 if( dynamic_cast< OutlineViewShell
*>( mpViewShell
) != nullptr )
725 static_cast<OutlineView
*>(mpViewShell
->GetView())
726 ->GetOutliner().ClearModifyFlag();
728 SdrOutliner
* pOutl
= mpViewShell
->GetView()->GetTextEditOutliner();
731 SdrObject
* pObj
= mpViewShell
->GetView()->GetTextEditObject();
733 pObj
->NbcSetOutlinerParaObject( pOutl
->CreateParaObject() );
735 pOutl
->ClearModifyFlag();
741 SfxViewFrame
* pFrame
= ( mpViewShell
&& mpViewShell
->GetViewFrame() ) ?
742 mpViewShell
->GetViewFrame() :
743 SfxViewFrame::Current();
746 pFrame
->GetBindings().Invalidate( SID_NAVIGATOR_STATE
, true );
751 SfxStyleSheetBasePool
* DrawDocShell::GetStyleSheetPool()
753 return mpDoc
->GetStyleSheetPool();
756 void DrawDocShell::GotoBookmark(std::u16string_view rBookmark
)
758 auto pDrawViewShell
= dynamic_cast<DrawViewShell
*>( mpViewShell
);
762 ViewShellBase
& rBase (mpViewShell
->GetViewShellBase());
764 bool bIsMasterPage
= false;
765 sal_uInt16 nPageNumber
= SDRPAGE_NOTFOUND
;
766 SdrObject
* pObj
= nullptr;
768 static constexpr std::u16string_view
sInteraction( u
"action?" );
769 if ( o3tl::starts_with(rBookmark
, sInteraction
) )
771 static constexpr std::u16string_view
sJump( u
"jump=" );
772 if ( o3tl::starts_with(rBookmark
.substr( sInteraction
.size() ), sJump
) )
774 std::u16string_view
aDestination( rBookmark
.substr( sInteraction
.size() + sJump
.size() ) );
775 if ( o3tl::starts_with(aDestination
, u
"firstslide" ) )
779 else if ( o3tl::starts_with(aDestination
, u
"lastslide" ) )
781 nPageNumber
= mpDoc
->GetPageCount() - 2;
783 else if ( o3tl::starts_with(aDestination
, u
"previousslide" ) )
785 SdPage
* pPage
= pDrawViewShell
->GetActualPage();
786 nPageNumber
= pPage
->GetPageNum();
787 nPageNumber
= nPageNumber
> 2 ? nPageNumber
- 2 : SDRPAGE_NOTFOUND
;
789 else if ( o3tl::starts_with(aDestination
, u
"nextslide" ) )
791 SdPage
* pPage
= pDrawViewShell
->GetActualPage();
792 nPageNumber
= pPage
->GetPageNum() + 2;
793 if ( nPageNumber
>= mpDoc
->GetPageCount() )
794 nPageNumber
= SDRPAGE_NOTFOUND
;
800 // Is the bookmark a page?
801 nPageNumber
= mpDoc
->GetPageByName( rBookmark
, bIsMasterPage
);
803 if (nPageNumber
== SDRPAGE_NOTFOUND
)
805 // Is the bookmark an object?
806 pObj
= mpDoc
->GetObj(rBookmark
);
810 nPageNumber
= pObj
->getSdrPageFromSdrObject()->GetPageNum();
814 if (nPageNumber
!= SDRPAGE_NOTFOUND
)
816 // Jump to the bookmarked page. This is done in three steps.
820 pPage
= static_cast<SdPage
*>( mpDoc
->GetMasterPage(nPageNumber
) );
822 pPage
= static_cast<SdPage
*>( mpDoc
->GetPage(nPageNumber
) );
824 // 1.) Change the view shell to the edit view, the notes view,
825 // or the handout view.
826 PageKind eNewPageKind
= pPage
->GetPageKind();
828 if( (eNewPageKind
!= PageKind::Standard
) && (mpDoc
->GetDocumentType() == DocumentType::Draw
) )
831 if (eNewPageKind
!= pDrawViewShell
->GetPageKind())
834 GetFrameView()->SetPageKind(eNewPageKind
);
836 switch (eNewPageKind
)
838 case PageKind::Standard
:
839 sViewURL
= FrameworkHelper::msImpressViewURL
;
841 case PageKind::Notes
:
842 sViewURL
= FrameworkHelper::msNotesViewURL
;
844 case PageKind::Handout
:
845 sViewURL
= FrameworkHelper::msHandoutViewURL
;
850 if (!sViewURL
.isEmpty())
852 std::shared_ptr
<FrameworkHelper
> pHelper (
853 FrameworkHelper::Instance(rBase
));
854 pHelper
->RequestView(
856 FrameworkHelper::msCenterPaneURL
);
857 pHelper
->WaitForUpdate();
859 // Get the new DrawViewShell.
860 mpViewShell
= pHelper
->GetViewShell(FrameworkHelper::msCenterPaneURL
).get();
861 pDrawViewShell
= dynamic_cast<sd::DrawViewShell
*>(mpViewShell
);
865 pDrawViewShell
= nullptr;
869 if (pDrawViewShell
!= nullptr)
871 setEditMode(pDrawViewShell
, bIsMasterPage
);
873 // Make the bookmarked page the current page. This is done
874 // by using the API because this takes care of all the
875 // little things to be done. Especially writing the view
876 // data to the frame view.
877 sal_uInt16 nSdPgNum
= (nPageNumber
- 1) / 2;
878 DrawController
* pDrawController
= rBase
.GetDrawController();
881 Reference
<drawing::XDrawPage
> xDrawPage (pPage
->getUnoPage(), UNO_QUERY
);
882 pDrawController
->setCurrentPage (xDrawPage
);
886 // As a fall back switch to the page via the core.
887 DBG_ASSERT (pDrawController
,
888 "DrawDocShell::GotoBookmark: can't switch page via API");
889 pDrawViewShell
->SwitchPage(nSdPgNum
);
892 // Do UnmarkAll here to stop the Navigator from reselecting the previously marked
893 // entry when a slide entry is selected.
894 pDrawViewShell
->GetView()->UnmarkAll();
897 // show and select object
898 if (vcl::Window
* pWindow
= pDrawViewShell
->GetActiveWindow())
899 pDrawViewShell
->MakeVisible(pObj
->GetSnapRect(), *pWindow
);
900 pDrawViewShell
->GetView()->MarkObj(
902 pDrawViewShell
->GetView()->GetSdrPageView());
907 if (SfxViewFrame
* pViewFrame
= (pDrawViewShell
&& pDrawViewShell
->GetViewFrame())
908 ? pDrawViewShell
->GetViewFrame()
909 : SfxViewFrame::Current())
911 SfxBindings
& rBindings
= pViewFrame
->GetBindings();
912 rBindings
.Invalidate(SID_NAVIGATOR_STATE
, true);
913 rBindings
.Invalidate(SID_NAVIGATOR_PAGENAME
);
918 * If it should become a document template.
920 bool DrawDocShell::SaveAsOwnFormat( SfxMedium
& rMedium
)
923 std::shared_ptr
<const SfxFilter
> pFilter
= rMedium
.GetFilter();
925 if (pFilter
->IsOwnTemplateFormat())
927 /* now the StarDraw specialty:
928 we assign known layout names to the layout template of the first
929 page, we set the layout names of the affected masterpages and pages.
930 We inform all text objects of the affected standard, note and
931 masterpages about the name change.
934 OUString aLayoutName
;
936 SfxStringItem
const * pLayoutItem
= rMedium
.GetItemSet().GetItemIfSet(SID_TEMPLATE_NAME
, false);
939 aLayoutName
= pLayoutItem
->GetValue();
943 INetURLObject
aURL( rMedium
.GetName() );
944 aURL
.removeExtension();
945 aLayoutName
= aURL
.getName();
948 if (aLayoutName
.isEmpty())
950 sal_uInt32 nCount
= mpDoc
->GetMasterSdPageCount(PageKind::Standard
);
951 for (sal_uInt32 i
= 0; i
< nCount
; ++i
)
953 OUString aOldPageLayoutName
= mpDoc
->GetMasterSdPage(i
, PageKind::Standard
)->GetLayoutName();
954 OUString aNewLayoutName
= aLayoutName
;
955 // Don't add suffix for the first master page
957 aNewLayoutName
+= OUString::number(i
);
959 mpDoc
->RenameLayoutTemplate(aOldPageLayoutName
, aNewLayoutName
);
964 return SfxObjectShell::SaveAsOwnFormat(rMedium
);
967 void DrawDocShell::FillClass(SvGlobalName
* pClassName
,
968 SotClipboardFormatId
* pFormat
,
969 OUString
* pFullTypeName
,
970 sal_Int32 nFileFormat
,
971 bool bTemplate
/* = false */) const
973 if (nFileFormat
== SOFFICE_FILEFORMAT_60
)
975 if ( meDocType
== DocumentType::Draw
)
977 *pClassName
= SvGlobalName(SO3_SDRAW_CLASSID_60
);
978 *pFormat
= SotClipboardFormatId::STARDRAW_60
;
979 *pFullTypeName
= SdResId(STR_GRAPHIC_DOCUMENT_FULLTYPE_60
);
983 *pClassName
= SvGlobalName(SO3_SIMPRESS_CLASSID_60
);
984 *pFormat
= SotClipboardFormatId::STARIMPRESS_60
;
985 *pFullTypeName
= SdResId(STR_IMPRESS_DOCUMENT_FULLTYPE_60
);
988 else if (nFileFormat
== SOFFICE_FILEFORMAT_8
)
990 if ( meDocType
== DocumentType::Draw
)
992 *pClassName
= SvGlobalName(SO3_SDRAW_CLASSID_60
);
993 *pFormat
= bTemplate
? SotClipboardFormatId::STARDRAW_8_TEMPLATE
: SotClipboardFormatId::STARDRAW_8
;
994 *pFullTypeName
= SdResId(STR_GRAPHIC_DOCUMENT_FULLTYPE_80
); // HACK: method will be removed with new storage API
998 *pClassName
= SvGlobalName(SO3_SIMPRESS_CLASSID_60
);
999 *pFormat
= bTemplate
? SotClipboardFormatId::STARIMPRESS_8_TEMPLATE
: SotClipboardFormatId::STARIMPRESS_8
;
1000 *pFullTypeName
= SdResId(STR_IMPRESS_DOCUMENT_FULLTYPE_80
); // HACK: method will be removed with new storage API
1005 OutputDevice
* DrawDocShell::GetDocumentRefDev()
1007 OutputDevice
* pReferenceDevice
= SfxObjectShell::GetDocumentRefDev ();
1008 // Only when our parent does not have a reference device then we return
1010 if (pReferenceDevice
== nullptr && mpDoc
!= nullptr)
1011 pReferenceDevice
= mpDoc
->GetRefDevice ();
1012 return pReferenceDevice
;
1015 /** executes the SID_OPENDOC slot to let the framework open a document
1016 with the given URL and this document as a referer */
1017 void DrawDocShell::OpenBookmark( const OUString
& rBookmarkURL
)
1019 SfxStringItem
aStrItem( SID_FILE_NAME
, rBookmarkURL
);
1020 SfxStringItem
aReferer( SID_REFERER
, GetMedium()->GetName() );
1021 SfxUInt16Item
aPresentation( SID_DOC_STARTPRESENTATION
);
1022 const SfxPoolItem
* ppArgs
[] = { &aStrItem
, &aReferer
, &aPresentation
, nullptr };
1024 if (SfxViewFrame
* pFrame
= mpViewShell
? mpViewShell
->GetViewFrame() : SfxViewFrame::Current())
1025 pFrame
->GetBindings().Execute( SID_OPENHYPERLINK
, ppArgs
);
1028 std::shared_ptr
<SfxDocumentInfoDialog
> DrawDocShell::CreateDocumentInfoDialog(weld::Window
* pParent
, const SfxItemSet
&rSet
)
1030 std::shared_ptr
<SfxDocumentInfoDialog
> xDlg
= std::make_shared
<SfxDocumentInfoDialog
>(pParent
, rSet
);
1031 DrawDocShell
* pDocSh
= dynamic_cast<DrawDocShell
*>(SfxObjectShell::Current());
1032 if( pDocSh
== this )
1034 xDlg
->AddFontTabPage();
1039 void DrawDocShell::setEditMode(DrawViewShell
* pDrawViewShell
, bool isMasterPage
)
1041 // Set the edit mode to either the normal edit mode or the
1042 // master page mode.
1043 EditMode eNewEditMode
= EditMode::Page
;
1046 eNewEditMode
= EditMode::MasterPage
;
1049 if (eNewEditMode
!= pDrawViewShell
->GetEditMode())
1052 pDrawViewShell
->ChangeEditMode(eNewEditMode
, false);
1055 } // end of namespace sd
1057 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */