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 <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 <vcl/syswin.hxx>
48 #include <com/sun/star/drawing/XDrawPage.hpp>
49 #include <com/sun/star/drawing/XDrawView.hpp>
52 #include <strings.hrc>
53 #include <FrameView.hxx>
54 #include <optsitem.hxx>
55 #include <Outliner.hxx>
57 #include <drawdoc.hxx>
58 #include <ViewShell.hxx>
61 #include <EffectMigration.hxx>
62 #include <CustomAnimationEffect.hxx>
64 #include <sdresid.hxx>
65 #include <DrawViewShell.hxx>
66 #include <ViewShellBase.hxx>
67 #include <OutlineView.hxx>
68 #include <OutlineViewShell.hxx>
69 #include <sdxmlwrp.hxx>
70 #include <sdpptwrp.hxx>
71 #include <sdcgmfilter.hxx>
72 #include <sdgrffilter.hxx>
73 #include <sdhtmlfilter.hxx>
74 #include <sdpdffilter.hxx>
75 #include <framework/FrameworkHelper.hxx>
76 #include <o3tl/string_view.hxx>
79 #include <svl/intitem.hxx>
81 using namespace ::com::sun::star
;
82 using namespace ::com::sun::star::uno
;
83 using ::sd::framework::FrameworkHelper
;
86 constexpr OUStringLiteral
pFilterPowerPoint97( u
"MS PowerPoint 97" );
87 constexpr OUStringLiteral
pFilterPowerPoint97Template( u
"MS PowerPoint 97 Vorlage" );
88 constexpr OUStringLiteral
pFilterPowerPoint97AutoPlay( u
"MS PowerPoint 97 AutoPlay" );
93 * Creates (if necessary) and returns a SfxPrinter
95 SfxPrinter
* DrawDocShell::GetPrinter(bool bCreate
)
97 if (bCreate
&& !mpPrinter
)
99 // create ItemSet with special pool area
100 auto pSet
= std::make_unique
<SfxItemSetFixed
<
101 SID_PRINTER_NOTFOUND_WARN
, SID_PRINTER_NOTFOUND_WARN
,
102 SID_PRINTER_CHANGESTODOC
, SID_PRINTER_CHANGESTODOC
,
103 ATTR_OPTIONS_PRINT
, ATTR_OPTIONS_PRINT
>>( GetPool() );
104 // set PrintOptionsSet
105 SdOptionsPrintItem
aPrintItem( SD_MOD()->GetSdOptions(mpDoc
->GetDocumentType()) );
106 SfxFlagItem
aFlagItem( SID_PRINTER_CHANGESTODOC
);
107 SfxPrinterChangeFlags nFlags
=
108 (aPrintItem
.GetOptionsPrint().IsWarningSize() ? SfxPrinterChangeFlags::CHG_SIZE
: SfxPrinterChangeFlags::NONE
) |
109 (aPrintItem
.GetOptionsPrint().IsWarningOrientation() ? SfxPrinterChangeFlags::CHG_ORIENTATION
: SfxPrinterChangeFlags::NONE
);
110 aFlagItem
.SetValue( static_cast<int>(nFlags
) );
112 pSet
->Put( aPrintItem
);
113 pSet
->Put( SfxBoolItem( SID_PRINTER_NOTFOUND_WARN
, aPrintItem
.GetOptionsPrint().IsWarningPrinter() ) );
114 pSet
->Put( aFlagItem
);
116 mpPrinter
= VclPtr
<SfxPrinter
>::Create(std::move(pSet
));
119 // set output quality
120 sal_uInt16 nQuality
= aPrintItem
.GetOptionsPrint().GetOutputQuality();
122 DrawModeFlags nMode
= DrawModeFlags::Default
;
123 // 1 == Grayscale, 2 == Black & White (with grayscale images)
125 nMode
= DrawModeFlags::GrayLine
| DrawModeFlags::GrayFill
| DrawModeFlags::GrayText
| DrawModeFlags::GrayBitmap
| DrawModeFlags::GrayGradient
;
126 else if( nQuality
== 2 )
127 nMode
= DrawModeFlags::BlackLine
| DrawModeFlags::WhiteFill
| DrawModeFlags::BlackText
| DrawModeFlags::GrayBitmap
| DrawModeFlags::WhiteGradient
;
129 mpPrinter
->SetDrawMode( nMode
);
131 MapMode
aMM (mpPrinter
->GetMapMode());
132 aMM
.SetMapUnit(MapUnit::Map100thMM
);
133 mpPrinter
->SetMapMode(aMM
);
140 * Set new SfxPrinter (transfer of ownership)
142 void DrawDocShell::SetPrinter(SfxPrinter
*pNewPrinter
)
146 ::sd::View
* pView
= mpViewShell
->GetView();
147 if ( pView
->IsTextEdit() )
148 pView
->SdrEndTextEdit();
151 if ( mpPrinter
&& mbOwnPrinter
&& (mpPrinter
.get() != pNewPrinter
) )
152 mpPrinter
.disposeAndClear();
154 mpPrinter
= pNewPrinter
;
156 if ( mpDoc
->GetPrinterIndependentLayout() == css::document::PrinterIndependentLayout::DISABLED
)
161 void DrawDocShell::UpdateFontList()
164 OutputDevice
* pRefDevice
= nullptr;
165 if ( mpDoc
->GetPrinterIndependentLayout() == css::document::PrinterIndependentLayout::DISABLED
)
166 pRefDevice
= GetPrinter(true);
168 pRefDevice
= SD_MOD()->GetVirtualRefDevice();
169 mpFontList
.reset( new FontList(pRefDevice
, nullptr) );
170 SvxFontListItem
aFontListItem( mpFontList
.get(), SID_ATTR_CHAR_FONTLIST
);
171 PutItem( aFontListItem
);
174 Printer
* DrawDocShell::GetDocumentPrinter()
176 return GetPrinter(false);
179 void DrawDocShell::OnDocumentPrinterChanged(Printer
* pNewPrinter
)
181 // if we already have a printer, see if it's the same
185 if( mpPrinter
== pNewPrinter
)
188 // compare if it's the same printer with the same job setup
189 if( (mpPrinter
->GetName() == pNewPrinter
->GetName()) &&
190 (mpPrinter
->GetJobSetup() == pNewPrinter
->GetJobSetup()))
194 SfxPrinter
* const pSfxPrinter
= dynamic_cast<SfxPrinter
*>(pNewPrinter
);
197 SetPrinter(pSfxPrinter
);
199 // container owns printer
200 mbOwnPrinter
= false;
204 void DrawDocShell::UpdateRefDevice()
209 // Determine the device for which the output will be formatted.
210 VclPtr
< OutputDevice
> pRefDevice
;
211 switch (mpDoc
->GetPrinterIndependentLayout())
213 case css::document::PrinterIndependentLayout::DISABLED
:
214 pRefDevice
= mpPrinter
.get();
217 case css::document::PrinterIndependentLayout::ENABLED
:
218 pRefDevice
= SD_MOD()->GetVirtualRefDevice();
222 // We are confronted with an invalid or un-implemented
223 // layout mode. Use the printer as formatting device
225 SAL_WARN( "sd", "DrawDocShell::UpdateRefDevice(): Unexpected printer layout mode");
227 pRefDevice
= mpPrinter
.get();
230 mpDoc
->SetRefDevice( pRefDevice
.get() );
232 SdOutliner
* pOutl
= mpDoc
->GetOutliner( false );
235 pOutl
->SetRefDevice( pRefDevice
);
237 SdOutliner
* pInternalOutl
= mpDoc
->GetInternalOutliner( false );
240 pInternalOutl
->SetRefDevice( pRefDevice
);
244 * Creates new document, opens streams
246 bool DrawDocShell::InitNew( const css::uno::Reference
< css::embed::XStorage
>& xStorage
)
248 bool bRet
= SfxObjectShell::InitNew( xStorage
);
250 ::tools::Rectangle
aVisArea( Point(0, 0), Size(14100, 10000) );
251 SetVisArea(aVisArea
);
256 mpDoc
->NewOrLoadCompleted(DocCreationMode::New
); // otherwise calling
257 // NewOrLoadCompleted(NEW_LOADED) in
258 // SdDrawDocument::AllocModel()
264 * loads pools and document
266 bool DrawDocShell::Load( SfxMedium
& rMedium
)
268 // If this is an ODF file being loaded, then by default, use legacy processing
269 // (if required, it will be overridden in *::ReadUserDataSequence())
270 if (IsOwnStorageFormat(rMedium
))
272 mpDoc
->SetCompatibilityFlag(SdrCompatibilityFlag::AnchoredTextOverflowLegacy
, true); // for tdf#99729
273 mpDoc
->SetCompatibilityFlag(SdrCompatibilityFlag::LegacySingleLineFontwork
, true); // for tdf#148000
277 bool bStartPresentation
= false;
278 ErrCode nError
= ERRCODE_NONE
;
280 SfxItemSet
* pSet
= rMedium
.GetItemSet();
284 if( ( SfxItemState::SET
== pSet
->GetItemState(SID_PREVIEW
) ) && pSet
->Get( SID_PREVIEW
).GetValue() )
286 mpDoc
->SetStarDrawPreviewMode( true );
289 if( SfxItemState::SET
== pSet
->GetItemState(SID_DOC_STARTPRESENTATION
)&&
290 pSet
->Get( SID_DOC_STARTPRESENTATION
).GetValue() )
292 bStartPresentation
= true;
293 mpDoc
->SetStartWithPresentation( true );
297 bRet
= SfxObjectShell::Load( rMedium
);
300 comphelper::EmbeddedObjectContainer
& rEmbeddedObjectContainer
= getEmbeddedObjectContainer();
301 rEmbeddedObjectContainer
.setUserAllowsLinkUpdate(false);
302 bRet
= SdXMLFilter( rMedium
, *this, SdXMLFilterMode::Normal
, SotStorage::GetVersion( rMedium
.GetStorage() ) ).Import( nError
);
307 // for legacy markup in OOoXML filter, convert the animations now
308 EffectMigration::DocumentLoaded(*GetDoc());
309 UpdateTablePointers();
311 // If we're an embedded OLE object, use tight bounds
312 // for our visArea. No point in showing the user lots of empty
313 // space. Had to remove the check for empty VisArea below,
314 // since XML load always sets a VisArea before.
315 //TODO/LATER: looks a little bit strange!
316 if( ( GetCreateMode() == SfxObjectCreateMode::EMBEDDED
) && SfxObjectShell::GetVisArea( ASPECT_CONTENT
).IsEmpty() )
318 SdPage
* pPage
= mpDoc
->GetSdPage( 0, PageKind::Standard
);
321 SetVisArea( pPage
->GetAllObjBoundRect() );
326 const INetURLObject aUrl
;
327 SfxObjectShell::SetAutoLoad( aUrl
, 0, false );
331 if( nError
== ERRCODE_IO_BROKENPACKAGE
)
332 SetError(ERRCODE_IO_BROKENPACKAGE
);
334 // TODO/LATER: correct error handling?!
335 //pStore->SetError(SVSTREAM_WRONGVERSION);
337 SetError(ERRCODE_ABORT
);
340 // tell SFX to change viewshell when in preview mode
341 if( IsPreview() || bStartPresentation
)
343 SfxItemSet
*pMediumSet
= GetMedium()->GetItemSet();
345 pMediumSet
->Put( SfxUInt16Item( SID_VIEW_ID
, bStartPresentation
? 1 : 5 ) );
352 * loads content for organizer
354 bool DrawDocShell::LoadFrom( SfxMedium
& rMedium
)
356 std::unique_ptr
<weld::WaitObject
> pWait
;
358 pWait
.reset(new weld::WaitObject(mpViewShell
->GetFrameWeld()));
360 mpDoc
->NewOrLoadCompleted( DocCreationMode::New
);
361 mpDoc
->CreateFirstPages();
362 mpDoc
->StopWorkStartupDelay();
364 // TODO/LATER: nobody is interested in the error code?!
365 ErrCode nError
= ERRCODE_NONE
;
366 bool bRet
= SdXMLFilter( rMedium
, *this, SdXMLFilterMode::Organizer
, SotStorage::GetVersion( rMedium
.GetStorage() ) ).Import( nError
);
368 // tell SFX to change viewshell when in preview mode
371 SfxItemSet
*pSet
= GetMedium()->GetItemSet();
374 pSet
->Put( SfxUInt16Item( SID_VIEW_ID
, 5 ) );
381 * load from 3rd party format
383 bool DrawDocShell::ImportFrom(SfxMedium
&rMedium
,
384 uno::Reference
<text::XTextRange
> const& xInsertPosition
)
386 const OUString
aFilterName( rMedium
.GetFilter()->GetFilterName() );
387 if (aFilterName
== "Impress MS PowerPoint 2007 XML" ||
388 aFilterName
== "Impress MS PowerPoint 2007 XML AutoPlay" ||
389 aFilterName
== "Impress MS PowerPoint 2007 XML VBA")
391 // As this is a MSFT format, we should use the "MS Compat"
392 // mode for spacing before and after paragraphs.
394 // This is copied from what is done for .ppt import in
395 // ImplSdPPTImport::Import() in sd/source/filter/ppt/pptin.cxx
396 // in. We need to tell both the edit engine of the draw outliner,
397 // and the document, to do "summation of paragraphs".
398 SdrOutliner
& rOutl
= mpDoc
->GetDrawOutliner();
399 EEControlBits nControlWord
= rOutl
.GetEditEngine().GetControlWord();
400 nControlWord
|= EEControlBits::ULSPACESUMMATION
;
401 const_cast<EditEngine
&>(rOutl
.GetEditEngine()).SetControlWord( nControlWord
);
403 mpDoc
->SetSummationOfParagraphs();
406 if (aFilterName
== "Impress MS PowerPoint 2007 XML")
408 // This is a "MS Compact" mode for connectors.
409 // The Libreoffice uses bounding rectangle of connected shapes but
410 // MSO uses snap rectangle when calculate the edge track.
411 mpDoc
->SetCompatibilityFlag(SdrCompatibilityFlag::ConnectorUseSnapRect
, true);
413 // compatibility flag for tdf#148966
414 mpDoc
->SetCompatibilityFlag(SdrCompatibilityFlag::IgnoreBreakAfterMultilineField
, true);
417 if (aFilterName
== "Impress MS PowerPoint 2007 XML" ||
418 aFilterName
== "Impress MS PowerPoint 2007 XML AutoPlay" ||
419 aFilterName
== "Impress MS PowerPoint 2007 XML VBA" ||
420 aFilterName
== "Impress Office Open XML")
422 // We need to be able to set the default tab size for each text object.
423 // This is possible at the moment only for the whole document. See
424 // TextParagraphPropertiesContext constructor. So default tab width
425 // of the LibreOffice is 1270 but MSO is 2540 on general settings.
426 mpDoc
->SetDefaultTabulator( 2540 );
429 const bool bRet
= SfxObjectShell::ImportFrom(rMedium
, xInsertPosition
);
431 SfxItemSet
* pSet
= rMedium
.GetItemSet();
434 if( SfxItemState::SET
== pSet
->GetItemState(SID_DOC_STARTPRESENTATION
)&&
435 pSet
->Get( SID_DOC_STARTPRESENTATION
).GetValue() )
437 mpDoc
->SetStartWithPresentation( true );
439 // tell SFX to change viewshell when in preview mode
442 SfxItemSet
*pMediumSet
= GetMedium()->GetItemSet();
444 pMediumSet
->Put( SfxUInt16Item( SID_VIEW_ID
, 1 ) );
453 * load from a foreign format
455 bool DrawDocShell::ConvertFrom( SfxMedium
& rMedium
)
457 const OUString
aFilterName( rMedium
.GetFilter()->GetFilterName() );
459 bool bStartPresentation
= false;
461 SetWaitCursor( true );
463 SfxItemSet
* pSet
= rMedium
.GetItemSet();
466 if( ( SfxItemState::SET
== pSet
->GetItemState(SID_PREVIEW
) ) && pSet
->Get( SID_PREVIEW
).GetValue() )
468 mpDoc
->SetStarDrawPreviewMode( true );
471 if( SfxItemState::SET
== pSet
->GetItemState(SID_DOC_STARTPRESENTATION
)&&
472 pSet
->Get( SID_DOC_STARTPRESENTATION
).GetValue() )
474 bStartPresentation
= true;
475 mpDoc
->SetStartWithPresentation( true );
479 if( aFilterName
== pFilterPowerPoint97
480 || aFilterName
== pFilterPowerPoint97Template
481 || aFilterName
== pFilterPowerPoint97AutoPlay
)
483 mpDoc
->StopWorkStartupDelay();
484 bRet
= SdPPTFilter( rMedium
, *this ).Import();
486 else if (aFilterName
.indexOf("impress8") >= 0 ||
487 aFilterName
.indexOf("draw8") >= 0)
489 // TODO/LATER: nobody is interested in the error code?!
490 mpDoc
->CreateFirstPages();
491 mpDoc
->StopWorkStartupDelay();
492 ErrCode nError
= ERRCODE_NONE
;
493 bRet
= SdXMLFilter( rMedium
, *this ).Import( nError
);
496 else if (aFilterName
.indexOf("StarOffice XML (Draw)") >= 0 ||
497 aFilterName
.indexOf("StarOffice XML (Impress)") >= 0)
499 // TODO/LATER: nobody is interested in the error code?!
500 mpDoc
->CreateFirstPages();
501 mpDoc
->StopWorkStartupDelay();
502 ErrCode nError
= ERRCODE_NONE
;
503 bRet
= SdXMLFilter( rMedium
, *this, SdXMLFilterMode::Normal
, SOFFICE_FILEFORMAT_60
).Import( nError
);
505 else if (aFilterName
== "CGM - Computer Graphics Metafile")
507 mpDoc
->CreateFirstPages();
508 mpDoc
->StopWorkStartupDelay();
509 bRet
= SdCGMFilter( rMedium
, *this ).Import();
511 else if (aFilterName
== "draw_pdf_import")
513 mpDoc
->CreateFirstPages();
514 mpDoc
->StopWorkStartupDelay();
515 bRet
= SdPdfFilter(rMedium
, *this).Import();
519 mpDoc
->CreateFirstPages();
520 mpDoc
->StopWorkStartupDelay();
521 bRet
= SdGRFFilter( rMedium
, *this ).Import();
526 // tell SFX to change viewshell when in preview mode
529 SfxItemSet
*pMediumSet
= GetMedium()->GetItemSet();
532 pMediumSet
->Put( SfxUInt16Item( SID_VIEW_ID
, 5 ) );
534 SetWaitCursor( false );
536 // tell SFX to change viewshell when in preview mode
537 if( IsPreview() || bStartPresentation
)
539 SfxItemSet
*pMediumSet
= GetMedium()->GetItemSet();
541 pMediumSet
->Put( SfxUInt16Item( SID_VIEW_ID
, bStartPresentation
? 1 : 5 ) );
548 * Writes pools and document to the open streams
550 bool DrawDocShell::Save()
552 mpDoc
->StopWorkStartupDelay();
554 //TODO/LATER: why this?!
555 if( GetCreateMode() == SfxObjectCreateMode::STANDARD
)
556 SfxObjectShell::SetVisArea( ::tools::Rectangle() );
558 bool bRet
= SfxObjectShell::Save();
561 bRet
= SdXMLFilter( *GetMedium(), *this, SdXMLFilterMode::Normal
, SotStorage::GetVersion( GetMedium()->GetStorage() ) ).Export();
567 * Writes pools and document to the provided storage
569 bool DrawDocShell::SaveAs( SfxMedium
& rMedium
)
571 mpDoc
->setDocAccTitle(OUString());
572 if (SfxViewFrame
* pFrame1
= SfxViewFrame::GetFirst(this))
574 if (vcl::Window
* pSysWin
= pFrame1
->GetWindow().GetSystemWindow())
576 pSysWin
->SetAccessibleName(OUString());
579 mpDoc
->StopWorkStartupDelay();
581 //With custom animation, if Outliner is modified, update text before saving
584 SdPage
* pPage
= mpViewShell
->getCurrentPage();
585 if( pPage
&& pPage
->getMainSequence()->getCount() )
587 SdrObject
* pObj
= mpViewShell
->GetView()->GetTextEditObject();
588 SdrOutliner
* pOutl
= mpViewShell
->GetView()->GetTextEditOutliner();
589 if( pObj
&& pOutl
&& pOutl
->IsModified() )
591 std::optional
<OutlinerParaObject
> pNewText
= pOutl
->CreateParaObject( 0, pOutl
->GetParagraphCount() );
592 pObj
->SetOutlinerParaObject( std::move(pNewText
) );
593 pOutl
->ClearModifyFlag();
598 //TODO/LATER: why this?!
599 if( GetCreateMode() == SfxObjectCreateMode::STANDARD
)
600 SfxObjectShell::SetVisArea( ::tools::Rectangle() );
602 bool bRet
= SfxObjectShell::SaveAs( rMedium
);
605 bRet
= SdXMLFilter( rMedium
, *this, SdXMLFilterMode::Normal
, SotStorage::GetVersion( rMedium
.GetStorage() ) ).Export();
607 if( GetError() == ERRCODE_NONE
)
608 SetError(ERRCODE_NONE
);
614 * save to foreign format
616 bool DrawDocShell::ConvertTo( SfxMedium
& rMedium
)
620 if( mpDoc
->GetPageCount() )
622 std::shared_ptr
<const SfxFilter
> pMediumFilter
= rMedium
.GetFilter();
623 const OUString
aTypeName( pMediumFilter
->GetTypeName() );
624 std::unique_ptr
<SdFilter
> xFilter
;
626 if( aTypeName
.indexOf( "graphic_HTML" ) >= 0 )
628 xFilter
= std::make_unique
<SdHTMLFilter
>(rMedium
, *this);
630 else if( aTypeName
.indexOf( "MS_PowerPoint_97" ) >= 0 )
632 xFilter
= std::make_unique
<SdPPTFilter
>(rMedium
, *this);
633 static_cast<SdPPTFilter
*>(xFilter
.get())->PreSaveBasic();
635 else if ( aTypeName
.indexOf( "CGM_Computer_Graphics_Metafile" ) >= 0 )
637 xFilter
= std::make_unique
<SdCGMFilter
>(rMedium
, *this);
639 else if( aTypeName
.indexOf( "draw8" ) >= 0 ||
640 aTypeName
.indexOf( "impress8" ) >= 0 )
642 xFilter
= std::make_unique
<SdXMLFilter
>(rMedium
, *this);
644 else if( aTypeName
.indexOf( "StarOffice_XML_Impress" ) >= 0 ||
645 aTypeName
.indexOf( "StarOffice_XML_Draw" ) >= 0 )
647 xFilter
= std::make_unique
<SdXMLFilter
>(rMedium
, *this, SdXMLFilterMode::Normal
, SOFFICE_FILEFORMAT_60
);
651 xFilter
= std::make_unique
<SdGRFFilter
>(rMedium
, *this);
658 ::sd::View
* pView
= mpViewShell
->GetView();
659 if ( pView
->IsTextEdit() )
660 pView
->SdrEndTextEdit();
663 bRet
= xFilter
->Export();
671 * Reopen own streams to ensure that nobody else can prevent use from opening
674 bool DrawDocShell::SaveCompleted( const css::uno::Reference
< css::embed::XStorage
>& xStorage
)
678 if( SfxObjectShell::SaveCompleted(xStorage
) )
680 mpDoc
->NbcSetChanged( false );
684 if( dynamic_cast< OutlineViewShell
*>( mpViewShell
) != nullptr )
685 static_cast<OutlineView
*>(mpViewShell
->GetView())
686 ->GetOutliner().ClearModifyFlag();
688 SdrOutliner
* pOutl
= mpViewShell
->GetView()->GetTextEditOutliner();
691 SdrObject
* pObj
= mpViewShell
->GetView()->GetTextEditObject();
693 pObj
->NbcSetOutlinerParaObject( pOutl
->CreateParaObject() );
695 pOutl
->ClearModifyFlag();
701 SfxViewFrame
* pFrame
= ( mpViewShell
&& mpViewShell
->GetViewFrame() ) ?
702 mpViewShell
->GetViewFrame() :
703 SfxViewFrame::Current();
706 pFrame
->GetBindings().Invalidate( SID_NAVIGATOR_STATE
, true );
711 SfxStyleSheetBasePool
* DrawDocShell::GetStyleSheetPool()
713 return mpDoc
->GetStyleSheetPool();
716 void DrawDocShell::GotoBookmark(std::u16string_view rBookmark
)
718 auto pDrawViewShell
= dynamic_cast<DrawViewShell
*>( mpViewShell
);
722 ViewShellBase
& rBase (mpViewShell
->GetViewShellBase());
724 bool bIsMasterPage
= false;
725 sal_uInt16 nPageNumber
= SDRPAGE_NOTFOUND
;
726 SdrObject
* pObj
= nullptr;
728 static constexpr std::u16string_view
sInteraction( u
"action?" );
729 if ( o3tl::starts_with(rBookmark
, sInteraction
) )
731 static constexpr std::u16string_view
sJump( u
"jump=" );
732 if ( o3tl::starts_with(rBookmark
.substr( sInteraction
.size() ), sJump
) )
734 std::u16string_view
aDestination( rBookmark
.substr( sInteraction
.size() + sJump
.size() ) );
735 if ( o3tl::starts_with(aDestination
, u
"firstslide" ) )
739 else if ( o3tl::starts_with(aDestination
, u
"lastslide" ) )
741 nPageNumber
= mpDoc
->GetPageCount() - 2;
743 else if ( o3tl::starts_with(aDestination
, u
"previousslide" ) )
745 SdPage
* pPage
= pDrawViewShell
->GetActualPage();
746 nPageNumber
= pPage
->GetPageNum();
747 nPageNumber
= nPageNumber
> 2 ? nPageNumber
- 2 : SDRPAGE_NOTFOUND
;
749 else if ( o3tl::starts_with(aDestination
, u
"nextslide" ) )
751 SdPage
* pPage
= pDrawViewShell
->GetActualPage();
752 nPageNumber
= pPage
->GetPageNum() + 2;
753 if ( nPageNumber
>= mpDoc
->GetPageCount() )
754 nPageNumber
= SDRPAGE_NOTFOUND
;
760 // Is the bookmark a page?
761 nPageNumber
= mpDoc
->GetPageByName( rBookmark
, bIsMasterPage
);
763 if (nPageNumber
== SDRPAGE_NOTFOUND
)
765 // Is the bookmark an object?
766 pObj
= mpDoc
->GetObj(rBookmark
);
770 nPageNumber
= pObj
->getSdrPageFromSdrObject()->GetPageNum();
774 if (nPageNumber
!= SDRPAGE_NOTFOUND
)
776 // Jump to the bookmarked page. This is done in three steps.
780 pPage
= static_cast<SdPage
*>( mpDoc
->GetMasterPage(nPageNumber
) );
782 pPage
= static_cast<SdPage
*>( mpDoc
->GetPage(nPageNumber
) );
784 // 1.) Change the view shell to the edit view, the notes view,
785 // or the handout view.
786 PageKind eNewPageKind
= pPage
->GetPageKind();
788 if( (eNewPageKind
!= PageKind::Standard
) && (mpDoc
->GetDocumentType() == DocumentType::Draw
) )
791 if (eNewPageKind
!= pDrawViewShell
->GetPageKind())
794 GetFrameView()->SetPageKind(eNewPageKind
);
796 switch (eNewPageKind
)
798 case PageKind::Standard
:
799 sViewURL
= FrameworkHelper::msImpressViewURL
;
801 case PageKind::Notes
:
802 sViewURL
= FrameworkHelper::msNotesViewURL
;
804 case PageKind::Handout
:
805 sViewURL
= FrameworkHelper::msHandoutViewURL
;
810 if (!sViewURL
.isEmpty())
812 std::shared_ptr
<FrameworkHelper
> pHelper (
813 FrameworkHelper::Instance(rBase
));
814 pHelper
->RequestView(
816 FrameworkHelper::msCenterPaneURL
);
817 pHelper
->WaitForUpdate();
819 // Get the new DrawViewShell.
820 mpViewShell
= pHelper
->GetViewShell(FrameworkHelper::msCenterPaneURL
).get();
821 pDrawViewShell
= dynamic_cast<sd::DrawViewShell
*>(mpViewShell
);
825 pDrawViewShell
= nullptr;
829 if (pDrawViewShell
!= nullptr)
831 setEditMode(pDrawViewShell
, bIsMasterPage
);
833 // Make the bookmarked page the current page. This is done
834 // by using the API because this takes care of all the
835 // little things to be done. Especially writing the view
836 // data to the frame view.
837 sal_uInt16 nSdPgNum
= (nPageNumber
- 1) / 2;
838 Reference
<drawing::XDrawView
> xController (rBase
.GetController(), UNO_QUERY
);
839 if (xController
.is())
841 Reference
<drawing::XDrawPage
> xDrawPage (pPage
->getUnoPage(), UNO_QUERY
);
842 xController
->setCurrentPage (xDrawPage
);
846 // As a fall back switch to the page via the core.
847 DBG_ASSERT (xController
.is(),
848 "DrawDocShell::GotoBookmark: can't switch page via API");
849 pDrawViewShell
->SwitchPage(nSdPgNum
);
852 // Do UnmarkAll here to stop the Navigator from reselecting the previously marked
853 // entry when a slide entry is selected.
854 pDrawViewShell
->GetView()->UnmarkAll();
857 // show and select object
858 if (vcl::Window
* pWindow
= pDrawViewShell
->GetActiveWindow())
859 pDrawViewShell
->MakeVisible(pObj
->GetSnapRect(), *pWindow
);
860 pDrawViewShell
->GetView()->MarkObj(
862 pDrawViewShell
->GetView()->GetSdrPageView());
867 if (SfxViewFrame
* pViewFrame
= (pDrawViewShell
&& pDrawViewShell
->GetViewFrame())
868 ? pDrawViewShell
->GetViewFrame()
869 : SfxViewFrame::Current())
871 SfxBindings
& rBindings
= pViewFrame
->GetBindings();
872 rBindings
.Invalidate(SID_NAVIGATOR_STATE
, true);
873 rBindings
.Invalidate(SID_NAVIGATOR_PAGENAME
);
878 * If it should become a document template.
880 bool DrawDocShell::SaveAsOwnFormat( SfxMedium
& rMedium
)
883 std::shared_ptr
<const SfxFilter
> pFilter
= rMedium
.GetFilter();
885 if (pFilter
->IsOwnTemplateFormat())
887 /* now the StarDraw specialty:
888 we assign known layout names to the layout template of the first
889 page, we set the layout names of the affected masterpages and pages.
890 We inform all text objects of the affected standard, note and
891 masterpages about the name change.
894 OUString aLayoutName
;
896 SfxStringItem
const * pLayoutItem
= rMedium
.GetItemSet()->GetItemIfSet(SID_TEMPLATE_NAME
, false);
899 aLayoutName
= pLayoutItem
->GetValue();
903 INetURLObject
aURL( rMedium
.GetName() );
904 aURL
.removeExtension();
905 aLayoutName
= aURL
.getName();
908 if (aLayoutName
.isEmpty())
910 sal_uInt32 nCount
= mpDoc
->GetMasterSdPageCount(PageKind::Standard
);
911 for (sal_uInt32 i
= 0; i
< nCount
; ++i
)
913 OUString aOldPageLayoutName
= mpDoc
->GetMasterSdPage(i
, PageKind::Standard
)->GetLayoutName();
914 OUString aNewLayoutName
= aLayoutName
;
915 // Don't add suffix for the first master page
917 aNewLayoutName
+= OUString::number(i
);
919 mpDoc
->RenameLayoutTemplate(aOldPageLayoutName
, aNewLayoutName
);
924 return SfxObjectShell::SaveAsOwnFormat(rMedium
);
927 void DrawDocShell::FillClass(SvGlobalName
* pClassName
,
928 SotClipboardFormatId
* pFormat
,
929 OUString
* pFullTypeName
,
930 sal_Int32 nFileFormat
,
931 bool bTemplate
/* = false */) const
933 if (nFileFormat
== SOFFICE_FILEFORMAT_60
)
935 if ( meDocType
== DocumentType::Draw
)
937 *pClassName
= SvGlobalName(SO3_SDRAW_CLASSID_60
);
938 *pFormat
= SotClipboardFormatId::STARDRAW_60
;
939 *pFullTypeName
= SdResId(STR_GRAPHIC_DOCUMENT_FULLTYPE_60
);
943 *pClassName
= SvGlobalName(SO3_SIMPRESS_CLASSID_60
);
944 *pFormat
= SotClipboardFormatId::STARIMPRESS_60
;
945 *pFullTypeName
= SdResId(STR_IMPRESS_DOCUMENT_FULLTYPE_60
);
948 else if (nFileFormat
== SOFFICE_FILEFORMAT_8
)
950 if ( meDocType
== DocumentType::Draw
)
952 *pClassName
= SvGlobalName(SO3_SDRAW_CLASSID_60
);
953 *pFormat
= bTemplate
? SotClipboardFormatId::STARDRAW_8_TEMPLATE
: SotClipboardFormatId::STARDRAW_8
;
954 *pFullTypeName
= SdResId(STR_GRAPHIC_DOCUMENT_FULLTYPE_80
); // HACK: method will be removed with new storage API
958 *pClassName
= SvGlobalName(SO3_SIMPRESS_CLASSID_60
);
959 *pFormat
= bTemplate
? SotClipboardFormatId::STARIMPRESS_8_TEMPLATE
: SotClipboardFormatId::STARIMPRESS_8
;
960 *pFullTypeName
= SdResId(STR_IMPRESS_DOCUMENT_FULLTYPE_80
); // HACK: method will be removed with new storage API
965 OutputDevice
* DrawDocShell::GetDocumentRefDev()
967 OutputDevice
* pReferenceDevice
= SfxObjectShell::GetDocumentRefDev ();
968 // Only when our parent does not have a reference device then we return
970 if (pReferenceDevice
== nullptr && mpDoc
!= nullptr)
971 pReferenceDevice
= mpDoc
->GetRefDevice ();
972 return pReferenceDevice
;
975 /** executes the SID_OPENDOC slot to let the framework open a document
976 with the given URL and this document as a referer */
977 void DrawDocShell::OpenBookmark( const OUString
& rBookmarkURL
)
979 SfxStringItem
aStrItem( SID_FILE_NAME
, rBookmarkURL
);
980 SfxStringItem
aReferer( SID_REFERER
, GetMedium()->GetName() );
981 const SfxPoolItem
* ppArgs
[] = { &aStrItem
, &aReferer
, nullptr };
982 if (SfxViewFrame
* pFrame
= mpViewShell
? mpViewShell
->GetViewFrame() : SfxViewFrame::Current())
983 pFrame
->GetBindings().Execute( SID_OPENHYPERLINK
, ppArgs
);
986 std::shared_ptr
<SfxDocumentInfoDialog
> DrawDocShell::CreateDocumentInfoDialog(weld::Window
* pParent
, const SfxItemSet
&rSet
)
988 std::shared_ptr
<SfxDocumentInfoDialog
> xDlg
= std::make_shared
<SfxDocumentInfoDialog
>(pParent
, rSet
);
989 DrawDocShell
* pDocSh
= dynamic_cast<DrawDocShell
*>(SfxObjectShell::Current());
992 xDlg
->AddFontTabPage();
997 void DrawDocShell::setEditMode(DrawViewShell
* pDrawViewShell
, bool isMasterPage
)
999 // Set the edit mode to either the normal edit mode or the
1000 // master page mode.
1001 EditMode eNewEditMode
= EditMode::Page
;
1004 eNewEditMode
= EditMode::MasterPage
;
1007 if (eNewEditMode
!= pDrawViewShell
->GetEditMode())
1010 pDrawViewShell
->ChangeEditMode(eNewEditMode
, false);
1013 } // end of namespace sd
1015 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */