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 <svl/lckbitem.hxx>
21 #include <svl/intitem.hxx>
22 #include <sfx2/frame.hxx>
23 #include <sfx2/viewfrm.hxx>
24 #include <unotools/moduleoptions.hxx>
25 #include <framework/FrameworkHelper.hxx>
26 #include <osl/diagnose.h>
27 #include <vcl/commandevent.hxx>
28 #include <vcl/svapp.hxx>
29 #include <vcl/errinf.hxx>
30 #include <editeng/langitem.hxx>
31 #include <vcl/weld.hxx>
32 #include <sfx2/dispatch.hxx>
33 #include <sfx2/docfile.hxx>
34 #include <sfx2/request.hxx>
35 #include <sfx2/templatedlg.hxx>
36 #include <editeng/eeitem.hxx>
38 #include <svx/svxids.hrc>
39 #include <strings.hrc>
43 #include <optsitem.hxx>
44 #include <ViewShell.hxx>
45 #include <DrawDocShell.hxx>
46 #include <drawdoc.hxx>
47 #include <sdresid.hxx>
48 #include <OutlineView.hxx>
49 #include <OutlineViewShell.hxx>
50 #include <ViewShellBase.hxx>
51 #include <FactoryIds.hxx>
53 #include <slideshow.hxx>
55 using ::sd::framework::FrameworkHelper
;
56 using ::com::sun::star::uno::Reference
;
57 using ::com::sun::star::frame::XFrame
;
61 class OutlineToImpressFinalizer final
64 OutlineToImpressFinalizer (
65 ::sd::ViewShellBase
& rBase
,
66 SdDrawDocument
& rDocument
,
67 SvLockBytes
const & rBytes
);
68 void operator() (bool bEventSeen
);
70 ::sd::ViewShellBase
& mrBase
;
71 SdDrawDocument
& mrDocument
;
72 std::shared_ptr
<SvMemoryStream
> mpStream
;
75 } //end of anonymous namespace
77 void SdModule::Execute(SfxRequest
& rReq
)
79 const SfxItemSet
* pSet
= rReq
.GetArgs();
80 sal_uInt16 nSlotId
= rReq
.GetSlot();
86 SfxGetpApp()->ExecuteSlot(rReq
, SfxGetpApp()->GetInterface());
90 case SID_AUTOSPELL_CHECK
:
92 // automatic spell checker
93 const SfxBoolItem
* pItem
;
94 if( pSet
&& (pItem
= pSet
->GetItemIfSet( SID_AUTOSPELL_CHECK
, false ) ) )
96 bool bOnlineSpelling
= pItem
->GetValue();
98 ::sd::DrawDocShell
* pDocSh
= dynamic_cast< ::sd::DrawDocShell
*>( SfxObjectShell::Current() );
101 SdDrawDocument
* pDoc
= pDocSh
->GetDoc();
102 pDoc
->SetOnlineSpell( bOnlineSpelling
);
108 case SID_ATTR_METRIC
:
110 const SfxUInt16Item
* pItem
;
111 if ( pSet
&& (pItem
= pSet
->GetItemIfSet( SID_ATTR_METRIC
) ) )
113 FieldUnit eUnit
= static_cast<FieldUnit
>(pItem
->GetValue());
116 case FieldUnit::MM
: // only the units which are also in the dialog
118 case FieldUnit::INCH
:
119 case FieldUnit::PICA
:
120 case FieldUnit::POINT
:
122 ::sd::DrawDocShell
* pDocSh
= dynamic_cast< ::sd::DrawDocShell
*>( SfxObjectShell::Current() );
125 DocumentType eDocType
= pDocSh
->GetDoc()->GetDocumentType();
128 SdOptions
* pOptions
= GetSdOptions( eDocType
);
130 pOptions
->SetMetric( static_cast<sal_uInt16
>(eUnit
) );
143 case SID_ATTR_LANGUAGE
:
144 case SID_ATTR_CHAR_CJK_LANGUAGE
:
145 case SID_ATTR_CHAR_CTL_LANGUAGE
:
147 const SfxPoolItem
* pItem
;
150 SfxItemState::SET
== pSet
->GetItemState(SID_ATTR_LANGUAGE
, false, &pItem
) ||
151 SfxItemState::SET
== pSet
->GetItemState(SID_ATTR_CHAR_CJK_LANGUAGE
, false, &pItem
) ||
152 SfxItemState::SET
== pSet
->GetItemState(SID_ATTR_CHAR_CTL_LANGUAGE
, false, &pItem
)
156 // save at the document:
157 ::sd::DrawDocShell
* pDocSh
= dynamic_cast< ::sd::DrawDocShell
*>( SfxObjectShell::Current() );
160 LanguageType eLanguage
= static_cast<const SvxLanguageItem
*>(pItem
)->GetValue();
161 SdDrawDocument
* pDoc
= pDocSh
->GetDoc();
163 if( nSlotId
== SID_ATTR_CHAR_CJK_LANGUAGE
)
164 pDoc
->SetLanguage( eLanguage
, EE_CHAR_LANGUAGE_CJK
);
165 else if( nSlotId
== SID_ATTR_CHAR_CTL_LANGUAGE
)
166 pDoc
->SetLanguage( eLanguage
, EE_CHAR_LANGUAGE_CTL
);
168 pDoc
->SetLanguage( eLanguage
, EE_CHAR_LANGUAGE
);
170 if( pDoc
->GetOnlineSpell() )
172 pDoc
->StopOnlineSpelling();
173 pDoc
->StartOnlineSpelling();
182 SfxFrame
* pFrame
= ExecuteNewDocument( rReq
);
183 // if a frame was created, set it as return value
185 rReq
.SetReturnValue(SfxFrameItem(0, pFrame
));
190 case SID_OPENHYPERLINK
:
193 bool bIntercept
= false;
194 ::sd::DrawDocShell
* pDocShell
= dynamic_cast< ::sd::DrawDocShell
*>( SfxObjectShell::Current() );
197 ::sd::ViewShell
* pViewShell
= pDocShell
->GetViewShell();
200 if( sd::SlideShow::IsRunning( pViewShell
->GetViewShellBase() ) )
202 // Prevent documents from opening while the slide
203 // show is running, except when this request comes
204 // from a shape interaction.
205 if (rReq
.GetArgs() == nullptr)
215 SfxGetpApp()->ExecuteSlot(rReq
, SfxGetpApp()->GetInterface());
219 std::unique_ptr
<weld::MessageDialog
> xErrorBox(Application::CreateMessageDialog(nullptr,
220 VclMessageType::Warning
, VclButtonsType::Ok
, SdResId(STR_CANT_PERFORM_IN_LIVEMODE
)));
224 const SfxLinkItem
* pLinkItem
= rReq
.GetArg
<SfxLinkItem
>(SID_DONELINK
);
226 pLinkItem
->GetValue().Call( nullptr );
231 case SID_OUTLINE_TO_IMPRESS
:
232 OutlineToImpress (rReq
);
240 bool SdModule::OutlineToImpress(SfxRequest
const & rRequest
)
242 const SfxItemSet
* pSet
= rRequest
.GetArgs();
246 SvLockBytes
* pBytes
= static_cast<const SfxLockBytesItem
&>(pSet
->Get(SID_OUTLINE_TO_IMPRESS
)).GetValue();
250 SfxObjectShellLock xDocShell
;
251 ::sd::DrawDocShell
* pDocSh
;
252 xDocShell
= pDocSh
= new ::sd::DrawDocShell(
253 SfxObjectCreateMode::STANDARD
, false, DocumentType::Impress
);
256 SdDrawDocument
* pDoc
= pDocSh
->GetDoc();
259 pDoc
->CreateFirstPages();
260 pDoc
->StopWorkStartupDelay();
263 const SfxFrameItem
* pFrmItem
= rRequest
.GetArg
<SfxFrameItem
>(SID_DOCFRAME
);
264 SfxViewFrame::LoadDocumentIntoFrame( *pDocSh
, pFrmItem
, ::sd::OUTLINE_FACTORY_ID
);
266 ::sd::ViewShell
* pViewSh
= pDocSh
->GetViewShell();
270 // AutoLayouts have to be finished
271 pDoc
->StopWorkStartupDelay();
273 SfxViewFrame
* pViewFrame
= pViewSh
->GetViewFrame();
275 // When the view frame has not been just created we have
276 // to switch synchronously to the outline view.
277 // (Otherwise the request will be ignored anyway.)
278 ::sd::ViewShellBase
* pBase
279 = dynamic_cast< ::sd::ViewShellBase
*>(pViewFrame
->GetViewShell());
280 if (pBase
!= nullptr)
282 std::shared_ptr
<FrameworkHelper
> pHelper (
283 FrameworkHelper::Instance(*pBase
));
284 pHelper
->RequestView(
285 FrameworkHelper::msOutlineViewURL
,
286 FrameworkHelper::msCenterPaneURL
);
288 pHelper
->RunOnResourceActivation(
289 FrameworkHelper::CreateResourceId(
290 FrameworkHelper::msOutlineViewURL
,
291 FrameworkHelper::msCenterPaneURL
),
292 OutlineToImpressFinalizer(*pBase
, *pDoc
, *pBytes
));
298 return rRequest
.IsDone();
301 void SdModule::GetState(SfxItemSet
& rItemSet
)
303 if( SfxItemState::DEFAULT
== rItemSet
.GetItemState( SID_ATTR_METRIC
) )
305 ::sd::DrawDocShell
* pDocSh
= dynamic_cast< ::sd::DrawDocShell
*>( SfxObjectShell::Current() );
308 DocumentType eDocType
= pDocSh
->GetDoc()->GetDocumentType();
310 SdOptions
* pOptions
= GetSdOptions(eDocType
);
311 rItemSet
.Put( SfxUInt16Item( SID_ATTR_METRIC
, pOptions
->GetMetric() ) );
315 // state of SID_OPENDOC is determined by the base class
316 if (rItemSet
.GetItemState(SID_OPENDOC
) != SfxItemState::UNKNOWN
)
318 const SfxPoolItem
* pItem
= SfxGetpApp()->GetSlotState(SID_OPENDOC
, SfxGetpApp()->GetInterface());
320 rItemSet
.Put(*pItem
);
323 // state of SID_OPENHYPERLINK is determined by the base class
324 if (rItemSet
.GetItemState(SID_OPENHYPERLINK
) != SfxItemState::UNKNOWN
)
326 const SfxPoolItem
* pItem
= SfxGetpApp()->GetSlotState(SID_OPENHYPERLINK
, SfxGetpApp()->GetInterface());
328 rItemSet
.Put(*pItem
);
331 if( SfxItemState::DEFAULT
== rItemSet
.GetItemState( SID_AUTOSPELL_CHECK
) )
333 ::sd::DrawDocShell
* pDocSh
=
334 dynamic_cast< ::sd::DrawDocShell
*>( SfxObjectShell::Current() );
337 SdDrawDocument
* pDoc
= pDocSh
->GetDoc();
338 rItemSet
.Put( SfxBoolItem( SID_AUTOSPELL_CHECK
, pDoc
->GetOnlineSpell() ) );
342 if( SfxItemState::DEFAULT
== rItemSet
.GetItemState( SID_ATTR_LANGUAGE
) )
344 ::sd::DrawDocShell
* pDocSh
= dynamic_cast< ::sd::DrawDocShell
*>( SfxObjectShell::Current() );
346 rItemSet
.Put( SvxLanguageItem( pDocSh
->GetDoc()->GetLanguage( EE_CHAR_LANGUAGE
), SID_ATTR_LANGUAGE
) );
349 if( SfxItemState::DEFAULT
== rItemSet
.GetItemState( SID_ATTR_CHAR_CJK_LANGUAGE
) )
351 ::sd::DrawDocShell
* pDocSh
= dynamic_cast< ::sd::DrawDocShell
*>( SfxObjectShell::Current() );
353 rItemSet
.Put( SvxLanguageItem( pDocSh
->GetDoc()->GetLanguage( EE_CHAR_LANGUAGE_CJK
), SID_ATTR_CHAR_CJK_LANGUAGE
) );
356 if( SfxItemState::DEFAULT
== rItemSet
.GetItemState( SID_ATTR_CHAR_CTL_LANGUAGE
) )
358 ::sd::DrawDocShell
* pDocSh
= dynamic_cast< ::sd::DrawDocShell
*>( SfxObjectShell::Current() );
360 rItemSet
.Put( SvxLanguageItem( pDocSh
->GetDoc()->GetLanguage( EE_CHAR_LANGUAGE_CTL
), SID_ATTR_CHAR_CTL_LANGUAGE
) );
363 if ( mbEventListenerAdded
)
366 ::sd::DrawDocShell
* pDocShell
= dynamic_cast< ::sd::DrawDocShell
*>( SfxObjectShell::Current() );
367 if( pDocShell
) // Impress or Draw ?
369 ::sd::ViewShell
* pViewShell
= pDocShell
->GetViewShell();
371 if( pViewShell
&& (pDocShell
->GetDocumentType() == DocumentType::Impress
) )
373 // add our event listener as soon as possible
374 Application::AddEventListener( LINK( this, SdModule
, EventListenerHdl
) );
375 mbEventListenerAdded
= true;
380 IMPL_STATIC_LINK( SdModule
, EventListenerHdl
, VclSimpleEvent
&, rSimpleEvent
, void )
382 if( !((rSimpleEvent
.GetId() == VclEventId::WindowCommand
) && static_cast<VclWindowEvent
*>(&rSimpleEvent
)->GetData()) )
385 const CommandEvent
& rEvent
= *static_cast<const CommandEvent
*>(static_cast<VclWindowEvent
*>(&rSimpleEvent
)->GetData());
387 if( rEvent
.GetCommand() != CommandEventId::Media
)
390 CommandMediaData
* pMediaData
= rEvent
.GetMediaData();
391 pMediaData
->SetPassThroughToOS(false);
392 switch (pMediaData
->GetMediaId())
394 case MediaCommand::Play
:
396 ::sd::DrawDocShell
* pDocShell
= dynamic_cast< ::sd::DrawDocShell
*>( SfxObjectShell::Current() );
397 if( pDocShell
) // Impress or Draw ?
399 ::sd::ViewShell
* pViewShell
= pDocShell
->GetViewShell();
401 // #i97925# start the presentation if and only if an Impress document is focused
402 if( pViewShell
&& (pDocShell
->GetDocumentType() == DocumentType::Impress
) )
403 pViewShell
->GetViewFrame()->GetDispatcher()->Execute( SID_PRESENTATION
);
408 pMediaData
->SetPassThroughToOS(true);
414 SfxFrame
* SdModule::CreateFromTemplate(const OUString
& rTemplatePath
, const Reference
<XFrame
>& i_rFrame
,
415 const bool bReplaceable
)
417 SfxFrame
* pFrame
= nullptr;
419 SfxObjectShellLock xDocShell
;
421 std::unique_ptr
<SfxItemSet
> pSet(new SfxAllItemSet( SfxGetpApp()->GetPool() ));
422 pSet
->Put( SfxBoolItem( SID_TEMPLATE
, true ) );
424 ErrCode lErr
= SfxGetpApp()->LoadTemplate( xDocShell
, rTemplatePath
, std::move(pSet
) );
426 SfxObjectShell
* pDocShell
= xDocShell
;
430 ErrorHandler::HandleError(lErr
);
434 if (pDocShell
->GetMedium() && pDocShell
->GetMedium()->GetItemSet())
435 pDocShell
->GetMedium()->GetItemSet()->Put(SfxBoolItem(SID_REPLACEABLE
, bReplaceable
));
436 SfxViewFrame
* pViewFrame
= SfxViewFrame::LoadDocumentIntoFrame( *pDocShell
, i_rFrame
);
437 OSL_ENSURE( pViewFrame
, "SdModule::CreateFromTemplate: no view frame - was the document really loaded?" );
438 pFrame
= pViewFrame
? &pViewFrame
->GetFrame() : nullptr;
445 SfxFrame
* SdModule::ExecuteNewDocument( SfxRequest
const & rReq
)
447 SfxFrame
* pFrame
= nullptr;
448 if ( SvtModuleOptions().IsImpress() )
450 Reference
< XFrame
> xTargetFrame
;
451 const SfxUnoFrameItem
* pFrmItem
= rReq
.GetArg
<SfxUnoFrameItem
>(SID_FILLFRAME
);
453 xTargetFrame
= pFrmItem
->GetFrame();
455 SdOptions
* pOpt
= GetSdOptions(DocumentType::Impress
);
456 bool bStartWithTemplate
= pOpt
->IsStartWithTemplate();
458 bool bNewDocDirect
= rReq
.GetSlot() == SID_NEWSD
;
462 //we start without wizard
464 //check whether we should load a template document
465 OUString
aStandardTemplate( SfxObjectFactory::GetStandardTemplate( u
"com.sun.star.presentation.PresentationDocument" ) );
467 if( !aStandardTemplate
.isEmpty() )
469 //load a template document
470 pFrame
= CreateFromTemplate(aStandardTemplate
, xTargetFrame
, true);
474 //create an empty document
475 pFrame
= CreateEmptyDocument( xTargetFrame
);
479 if (bStartWithTemplate
)
481 //Launch TemplateSelectionDialog
482 SfxTemplateSelectionDlg
aTemplDlg(SfxGetpApp()->GetTopWindow());
485 //check to disable the dialog
486 pOpt
->SetStartWithTemplate( aTemplDlg
.IsStartWithTemplate() );
488 //pFrame is loaded with the desired template
489 if (!aTemplDlg
.getTemplatePath().isEmpty())
490 pFrame
= CreateFromTemplate(aTemplDlg
.getTemplatePath(), xTargetFrame
, false);
492 // show tip-of-the-day dialog if it was deferred because SfxTemplateSelectionDlg
494 if (pFrame
&& SfxApplication::IsTipOfTheDayDue() && !SfxApplication::IsHeadlessOrUITest())
496 if (SfxDispatcher
* pDispatcher
= GetDispatcher())
498 // tdf#127946 pass in argument for dialog parent
499 SfxUnoFrameItem
aDocFrame(SID_FILLFRAME
, pFrame
->GetFrameInterface());
500 pDispatcher
->ExecuteList(SID_TIPOFTHEDAY
, SfxCallMode::SLOT
, {}, { &aDocFrame
});
509 SfxFrame
* SdModule::CreateEmptyDocument( const Reference
< XFrame
>& i_rFrame
)
511 SfxFrame
* pFrame
= nullptr;
513 SfxObjectShellLock xDocShell
;
514 ::sd::DrawDocShell
* pNewDocSh
;
515 xDocShell
= pNewDocSh
= new ::sd::DrawDocShell(SfxObjectCreateMode::STANDARD
,false,DocumentType::Impress
);
516 pNewDocSh
->DoInitNew();
517 SdDrawDocument
* pDoc
= pNewDocSh
->GetDoc();
520 pDoc
->CreateFirstPages();
521 pDoc
->StopWorkStartupDelay();
523 if (pNewDocSh
->GetMedium() && pNewDocSh
->GetMedium()->GetItemSet())
524 pNewDocSh
->GetMedium()->GetItemSet()->Put(SfxBoolItem(SID_REPLACEABLE
, true));
526 SfxViewFrame
* pViewFrame
= SfxViewFrame::LoadDocumentIntoFrame( *pNewDocSh
, i_rFrame
);
527 OSL_ENSURE( pViewFrame
, "SdModule::CreateEmptyDocument: no view frame - was the document really loaded?" );
528 pFrame
= pViewFrame
? &pViewFrame
->GetFrame() : nullptr;
533 //===== OutlineToImpressFinalize ==============================================
537 OutlineToImpressFinalizer::OutlineToImpressFinalizer (
538 ::sd::ViewShellBase
& rBase
,
539 SdDrawDocument
& rDocument
,
540 SvLockBytes
const & rBytes
)
542 mrDocument(rDocument
)
544 // The given stream has a lifetime shorter than this new
545 // OutlineToImpressFinalizer object. Therefore a local copy of the
546 // stream is created.
547 const SvStream
* pStream (rBytes
.GetStream());
548 if (pStream
== nullptr)
551 // Create a memory stream and prepare to fill it with the content of
552 // the original stream.
553 mpStream
= std::make_shared
<SvMemoryStream
>();
554 static const std::size_t nBufferSize
= 4096;
555 ::std::unique_ptr
<sal_Int8
[]> pBuffer (new sal_Int8
[nBufferSize
]);
557 sal_uInt64
nReadPosition(0);
561 // Read the next part of the original stream.
562 std::size_t nReadByteCount (0);
563 const ErrCode
nErrorCode (
570 // Check the error code and stop copying the stream data when an
571 // error has occurred.
572 if (nErrorCode
== ERRCODE_NONE
)
574 if (nReadByteCount
== 0)
577 else if (nErrorCode
== ERRCODE_IO_PENDING
)
585 // Append the read bytes to the end of the memory stream.
586 if (nReadByteCount
> 0)
588 mpStream
->WriteBytes(pBuffer
.get(), nReadByteCount
);
589 nReadPosition
+= nReadByteCount
;
593 // Rewind the memory stream so that in the operator() method its
594 // content is properly read.
595 mpStream
->Seek(STREAM_SEEK_TO_BEGIN
);
598 void OutlineToImpressFinalizer::operator() (bool)
600 // Fetch the new outline view shell.
601 ::sd::OutlineViewShell
* pOutlineShell
602 = dynamic_cast<sd::OutlineViewShell
*>(FrameworkHelper::Instance(mrBase
)->GetViewShell(FrameworkHelper::msCenterPaneURL
).get());
604 if (pOutlineShell
!= nullptr && mpStream
!= nullptr)
606 sd::OutlineView
* pView
= static_cast<sd::OutlineView
*>(pOutlineShell
->GetView());
607 // mba: the stream can't contain any relative URLs, because we don't
608 // have any information about a BaseURL!
609 pOutlineShell
->ReadRtf(*mpStream
);
611 // Call UpdatePreview once for every slide to resync the
612 // document with the outliner of the OutlineViewShell.
613 sal_uInt16
nPageCount (mrDocument
.GetSdPageCount(PageKind::Standard
));
614 for (sal_uInt16 nIndex
=0; nIndex
<nPageCount
; nIndex
++)
616 SdPage
* pPage
= mrDocument
.GetSdPage(nIndex
, PageKind::Standard
);
617 // Make the page the actual page so that the
618 // following UpdatePreview() call accesses the
619 // correct paragraphs.
620 pView
->SetActualPage(pPage
);
621 pOutlineShell
->UpdatePreview(pPage
);
623 // Select the first slide.
624 SdPage
* pPage
= mrDocument
.GetSdPage(0, PageKind::Standard
);
625 pView
->SetActualPage(pPage
);
626 pOutlineShell
->UpdatePreview(pPage
);
629 // Undo-Stack needs to be cleared, else the user may remove the
630 // only drawpage and this is a state we cannot handle ATM.
631 ::sd::DrawDocShell
* pDocShell
= mrDocument
.GetDocSh();
633 pDocShell
->ClearUndoBuffer();
636 } // end of anonymous namespace
638 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */