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>
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_uLong nSlotId
= rReq
.GetSlot();
86 SfxGetpApp()->ExecuteSlot(rReq
, SfxGetpApp()->GetInterface());
90 case SID_AUTOSPELL_CHECK
:
92 // automatic spell checker
93 const SfxPoolItem
* pItem
;
94 if( pSet
&& SfxItemState::SET
== pSet
->GetItemState(
95 SID_AUTOSPELL_CHECK
, false, &pItem
) )
97 bool bOnlineSpelling
= static_cast<const SfxBoolItem
*>( pItem
)->GetValue();
99 ::sd::DrawDocShell
* pDocSh
= dynamic_cast< ::sd::DrawDocShell
*>( SfxObjectShell::Current() );
102 SdDrawDocument
* pDoc
= pDocSh
->GetDoc();
103 pDoc
->SetOnlineSpell( bOnlineSpelling
);
109 case SID_ATTR_METRIC
:
111 const SfxPoolItem
* pItem
;
112 if ( pSet
&& SfxItemState::SET
== pSet
->GetItemState( SID_ATTR_METRIC
, true, &pItem
) )
114 FieldUnit eUnit
= static_cast<FieldUnit
>(static_cast<const SfxUInt16Item
*>(pItem
)->GetValue());
117 case FieldUnit::MM
: // only the units which are also in the dialog
119 case FieldUnit::INCH
:
120 case FieldUnit::PICA
:
121 case FieldUnit::POINT
:
123 ::sd::DrawDocShell
* pDocSh
= dynamic_cast< ::sd::DrawDocShell
*>( SfxObjectShell::Current() );
126 DocumentType eDocType
= pDocSh
->GetDoc()->GetDocumentType();
129 SdOptions
* pOptions
= GetSdOptions( eDocType
);
131 pOptions
->SetMetric( static_cast<sal_uInt16
>(eUnit
) );
144 case SID_ATTR_LANGUAGE
:
145 case SID_ATTR_CHAR_CJK_LANGUAGE
:
146 case SID_ATTR_CHAR_CTL_LANGUAGE
:
148 const SfxPoolItem
* pItem
;
151 SfxItemState::SET
== pSet
->GetItemState(SID_ATTR_LANGUAGE
, false, &pItem
) ||
152 SfxItemState::SET
== pSet
->GetItemState(SID_ATTR_CHAR_CJK_LANGUAGE
, false, &pItem
) ||
153 SfxItemState::SET
== pSet
->GetItemState(SID_ATTR_CHAR_CTL_LANGUAGE
, false, &pItem
)
157 // save at the document:
158 ::sd::DrawDocShell
* pDocSh
= dynamic_cast< ::sd::DrawDocShell
*>( SfxObjectShell::Current() );
161 LanguageType eLanguage
= static_cast<const SvxLanguageItem
*>(pItem
)->GetValue();
162 SdDrawDocument
* pDoc
= pDocSh
->GetDoc();
164 if( nSlotId
== SID_ATTR_CHAR_CJK_LANGUAGE
)
165 pDoc
->SetLanguage( eLanguage
, EE_CHAR_LANGUAGE_CJK
);
166 else if( nSlotId
== SID_ATTR_CHAR_CTL_LANGUAGE
)
167 pDoc
->SetLanguage( eLanguage
, EE_CHAR_LANGUAGE_CTL
);
169 pDoc
->SetLanguage( eLanguage
, EE_CHAR_LANGUAGE
);
171 if( pDoc
->GetOnlineSpell() )
173 pDoc
->StopOnlineSpelling();
174 pDoc
->StartOnlineSpelling();
183 SfxFrame
* pFrame
= ExecuteNewDocument( rReq
);
184 // if a frame was created, set it as return value
186 rReq
.SetReturnValue(SfxFrameItem(0, pFrame
));
191 case SID_OPENHYPERLINK
:
194 bool bIntercept
= false;
195 ::sd::DrawDocShell
* pDocShell
= dynamic_cast< ::sd::DrawDocShell
*>( SfxObjectShell::Current() );
198 ::sd::ViewShell
* pViewShell
= pDocShell
->GetViewShell();
201 if( sd::SlideShow::IsRunning( pViewShell
->GetViewShellBase() ) )
203 // Prevent documents from opening while the slide
204 // show is running, except when this request comes
205 // from a shape interaction.
206 if (rReq
.GetArgs() == nullptr)
216 SfxGetpApp()->ExecuteSlot(rReq
, SfxGetpApp()->GetInterface());
220 std::unique_ptr
<weld::MessageDialog
> xErrorBox(Application::CreateMessageDialog(nullptr,
221 VclMessageType::Warning
, VclButtonsType::Ok
, SdResId(STR_CANT_PERFORM_IN_LIVEMODE
)));
225 const SfxLinkItem
* pLinkItem
= rReq
.GetArg
<SfxLinkItem
>(SID_DONELINK
);
227 pLinkItem
->GetValue().Call( nullptr );
232 case SID_OUTLINE_TO_IMPRESS
:
233 OutlineToImpress (rReq
);
241 bool SdModule::OutlineToImpress(SfxRequest
const & rRequest
)
243 const SfxItemSet
* pSet
= rRequest
.GetArgs();
247 SvLockBytes
* pBytes
= static_cast<const SfxLockBytesItem
&>(pSet
->Get(SID_OUTLINE_TO_IMPRESS
)).GetValue();
251 SfxObjectShellLock xDocShell
;
252 ::sd::DrawDocShell
* pDocSh
;
253 xDocShell
= pDocSh
= new ::sd::DrawDocShell(
254 SfxObjectCreateMode::STANDARD
, false, DocumentType::Impress
);
257 SdDrawDocument
* pDoc
= pDocSh
->GetDoc();
260 pDoc
->CreateFirstPages();
261 pDoc
->StopWorkStartupDelay();
264 const SfxFrameItem
* pFrmItem
= rRequest
.GetArg
<SfxFrameItem
>(SID_DOCFRAME
);
265 SfxViewFrame::LoadDocumentIntoFrame( *pDocSh
, pFrmItem
, ::sd::OUTLINE_FACTORY_ID
);
267 ::sd::ViewShell
* pViewSh
= pDocSh
->GetViewShell();
271 // AutoLayouts have to be finished
272 pDoc
->StopWorkStartupDelay();
274 SfxViewFrame
* pViewFrame
= pViewSh
->GetViewFrame();
276 // When the view frame has not been just created we have
277 // to switch synchronously to the outline view.
278 // (Otherwise the request will be ignored anyway.)
279 ::sd::ViewShellBase
* pBase
280 = dynamic_cast< ::sd::ViewShellBase
*>(pViewFrame
->GetViewShell());
281 if (pBase
!= nullptr)
283 std::shared_ptr
<FrameworkHelper
> pHelper (
284 FrameworkHelper::Instance(*pBase
));
285 pHelper
->RequestView(
286 FrameworkHelper::msOutlineViewURL
,
287 FrameworkHelper::msCenterPaneURL
);
289 pHelper
->RunOnResourceActivation(
290 FrameworkHelper::CreateResourceId(
291 FrameworkHelper::msOutlineViewURL
,
292 FrameworkHelper::msCenterPaneURL
),
293 OutlineToImpressFinalizer(*pBase
, *pDoc
, *pBytes
));
299 return rRequest
.IsDone();
302 void SdModule::GetState(SfxItemSet
& rItemSet
)
304 if( SfxItemState::DEFAULT
== rItemSet
.GetItemState( SID_ATTR_METRIC
) )
306 ::sd::DrawDocShell
* pDocSh
= dynamic_cast< ::sd::DrawDocShell
*>( SfxObjectShell::Current() );
309 DocumentType eDocType
= pDocSh
->GetDoc()->GetDocumentType();
311 SdOptions
* pOptions
= GetSdOptions(eDocType
);
312 rItemSet
.Put( SfxUInt16Item( SID_ATTR_METRIC
, pOptions
->GetMetric() ) );
316 // state of SID_OPENDOC is determined by the base class
317 if (rItemSet
.GetItemState(SID_OPENDOC
) != SfxItemState::UNKNOWN
)
319 const SfxPoolItem
* pItem
= SfxGetpApp()->GetSlotState(SID_OPENDOC
, SfxGetpApp()->GetInterface());
321 rItemSet
.Put(*pItem
);
324 // state of SID_OPENHYPERLINK is determined by the base class
325 if (rItemSet
.GetItemState(SID_OPENHYPERLINK
) != SfxItemState::UNKNOWN
)
327 const SfxPoolItem
* pItem
= SfxGetpApp()->GetSlotState(SID_OPENHYPERLINK
, SfxGetpApp()->GetInterface());
329 rItemSet
.Put(*pItem
);
332 if( SfxItemState::DEFAULT
== rItemSet
.GetItemState( SID_AUTOSPELL_CHECK
) )
334 ::sd::DrawDocShell
* pDocSh
=
335 dynamic_cast< ::sd::DrawDocShell
*>( SfxObjectShell::Current() );
338 SdDrawDocument
* pDoc
= pDocSh
->GetDoc();
339 rItemSet
.Put( SfxBoolItem( SID_AUTOSPELL_CHECK
, pDoc
->GetOnlineSpell() ) );
343 if( SfxItemState::DEFAULT
== rItemSet
.GetItemState( SID_ATTR_LANGUAGE
) )
345 ::sd::DrawDocShell
* pDocSh
= dynamic_cast< ::sd::DrawDocShell
*>( SfxObjectShell::Current() );
347 rItemSet
.Put( SvxLanguageItem( pDocSh
->GetDoc()->GetLanguage( EE_CHAR_LANGUAGE
), SID_ATTR_LANGUAGE
) );
350 if( SfxItemState::DEFAULT
== rItemSet
.GetItemState( SID_ATTR_CHAR_CJK_LANGUAGE
) )
352 ::sd::DrawDocShell
* pDocSh
= dynamic_cast< ::sd::DrawDocShell
*>( SfxObjectShell::Current() );
354 rItemSet
.Put( SvxLanguageItem( pDocSh
->GetDoc()->GetLanguage( EE_CHAR_LANGUAGE_CJK
), SID_ATTR_CHAR_CJK_LANGUAGE
) );
357 if( SfxItemState::DEFAULT
== rItemSet
.GetItemState( SID_ATTR_CHAR_CTL_LANGUAGE
) )
359 ::sd::DrawDocShell
* pDocSh
= dynamic_cast< ::sd::DrawDocShell
*>( SfxObjectShell::Current() );
361 rItemSet
.Put( SvxLanguageItem( pDocSh
->GetDoc()->GetLanguage( EE_CHAR_LANGUAGE_CTL
), SID_ATTR_CHAR_CTL_LANGUAGE
) );
364 if ( mbEventListenerAdded
)
367 ::sd::DrawDocShell
* pDocShell
= dynamic_cast< ::sd::DrawDocShell
*>( SfxObjectShell::Current() );
368 if( pDocShell
) // Impress or Draw ?
370 ::sd::ViewShell
* pViewShell
= pDocShell
->GetViewShell();
372 if( pViewShell
&& (pDocShell
->GetDocumentType() == DocumentType::Impress
) )
374 // add our event listener as soon as possible
375 Application::AddEventListener( LINK( this, SdModule
, EventListenerHdl
) );
376 mbEventListenerAdded
= true;
381 IMPL_STATIC_LINK( SdModule
, EventListenerHdl
, VclSimpleEvent
&, rSimpleEvent
, void )
383 if( !((rSimpleEvent
.GetId() == VclEventId::WindowCommand
) && static_cast<VclWindowEvent
*>(&rSimpleEvent
)->GetData()) )
386 const CommandEvent
& rEvent
= *static_cast<const CommandEvent
*>(static_cast<VclWindowEvent
*>(&rSimpleEvent
)->GetData());
388 if( rEvent
.GetCommand() != CommandEventId::Media
)
391 CommandMediaData
* pMediaData
= rEvent
.GetMediaData();
392 pMediaData
->SetPassThroughToOS(false);
393 switch (pMediaData
->GetMediaId())
395 case MediaCommand::Play
:
397 ::sd::DrawDocShell
* pDocShell
= dynamic_cast< ::sd::DrawDocShell
*>( SfxObjectShell::Current() );
398 if( pDocShell
) // Impress or Draw ?
400 ::sd::ViewShell
* pViewShell
= pDocShell
->GetViewShell();
402 // #i97925# start the presentation if and only if an Impress document is focused
403 if( pViewShell
&& (pDocShell
->GetDocumentType() == DocumentType::Impress
) )
404 pViewShell
->GetViewFrame()->GetDispatcher()->Execute( SID_PRESENTATION
);
409 pMediaData
->SetPassThroughToOS(true);
415 SfxFrame
* SdModule::CreateFromTemplate(const OUString
& rTemplatePath
, const Reference
<XFrame
>& i_rFrame
,
416 const bool bReplaceable
)
418 SfxFrame
* pFrame
= nullptr;
420 SfxObjectShellLock xDocShell
;
422 std::unique_ptr
<SfxItemSet
> pSet(new SfxAllItemSet( SfxGetpApp()->GetPool() ));
423 pSet
->Put( SfxBoolItem( SID_TEMPLATE
, true ) );
425 ErrCode lErr
= SfxGetpApp()->LoadTemplate( xDocShell
, rTemplatePath
, std::move(pSet
) );
427 SfxObjectShell
* pDocShell
= xDocShell
;
431 ErrorHandler::HandleError(lErr
);
435 if (pDocShell
->GetMedium() && pDocShell
->GetMedium()->GetItemSet())
436 pDocShell
->GetMedium()->GetItemSet()->Put(SfxBoolItem(SID_REPLACEABLE
, bReplaceable
));
437 SfxViewFrame
* pViewFrame
= SfxViewFrame::LoadDocumentIntoFrame( *pDocShell
, i_rFrame
);
438 OSL_ENSURE( pViewFrame
, "SdModule::CreateFromTemplate: no view frame - was the document really loaded?" );
439 pFrame
= pViewFrame
? &pViewFrame
->GetFrame() : nullptr;
446 SfxFrame
* SdModule::ExecuteNewDocument( SfxRequest
const & rReq
)
448 SfxFrame
* pFrame
= nullptr;
449 if ( SvtModuleOptions().IsImpress() )
451 Reference
< XFrame
> xTargetFrame
;
452 const SfxUnoFrameItem
* pFrmItem
= rReq
.GetArg
<SfxUnoFrameItem
>(SID_FILLFRAME
);
454 xTargetFrame
= pFrmItem
->GetFrame();
456 SdOptions
* pOpt
= GetSdOptions(DocumentType::Impress
);
457 bool bStartWithTemplate
= pOpt
->IsStartWithTemplate();
459 bool bNewDocDirect
= rReq
.GetSlot() == SID_NEWSD
;
463 //we start without wizard
465 //check whether we should load a template document
466 OUString
aStandardTemplate( SfxObjectFactory::GetStandardTemplate( "com.sun.star.presentation.PresentationDocument" ) );
468 if( !aStandardTemplate
.isEmpty() )
470 //load a template document
471 pFrame
= CreateFromTemplate(aStandardTemplate
, xTargetFrame
, true);
475 //create an empty document
476 pFrame
= CreateEmptyDocument( xTargetFrame
);
480 if(bStartWithTemplate
)
482 //Launch TemplateSelectionDialog
483 vcl::Window
* pTopLevel
= SfxGetpApp()->GetTopWindow();
484 SfxTemplateSelectionDlg
aTemplDlg(pTopLevel
? pTopLevel
->GetFrameWeld() : nullptr);
487 //check to disable the dialog
488 pOpt
->SetStartWithTemplate( aTemplDlg
.IsStartWithTemplate() );
490 //pFrame is loaded with the desired template
491 if (!aTemplDlg
.getTemplatePath().isEmpty())
492 pFrame
= CreateFromTemplate(aTemplDlg
.getTemplatePath(), xTargetFrame
, false);
499 SfxFrame
* SdModule::CreateEmptyDocument( const Reference
< XFrame
>& i_rFrame
)
501 SfxFrame
* pFrame
= nullptr;
503 SfxObjectShellLock xDocShell
;
504 ::sd::DrawDocShell
* pNewDocSh
;
505 xDocShell
= pNewDocSh
= new ::sd::DrawDocShell(SfxObjectCreateMode::STANDARD
,false,DocumentType::Impress
);
506 pNewDocSh
->DoInitNew();
507 SdDrawDocument
* pDoc
= pNewDocSh
->GetDoc();
510 pDoc
->CreateFirstPages();
511 pDoc
->StopWorkStartupDelay();
513 if (pNewDocSh
->GetMedium() && pNewDocSh
->GetMedium()->GetItemSet())
514 pNewDocSh
->GetMedium()->GetItemSet()->Put(SfxBoolItem(SID_REPLACEABLE
, true));
516 SfxViewFrame
* pViewFrame
= SfxViewFrame::LoadDocumentIntoFrame( *pNewDocSh
, i_rFrame
);
517 OSL_ENSURE( pViewFrame
, "SdModule::CreateEmptyDocument: no view frame - was the document really loaded?" );
518 pFrame
= pViewFrame
? &pViewFrame
->GetFrame() : nullptr;
523 //===== OutlineToImpressFinalize ==============================================
527 OutlineToImpressFinalizer::OutlineToImpressFinalizer (
528 ::sd::ViewShellBase
& rBase
,
529 SdDrawDocument
& rDocument
,
530 SvLockBytes
const & rBytes
)
532 mrDocument(rDocument
),
535 // The given stream has a lifetime shorter than this new
536 // OutlineToImpressFinalizer object. Therefore a local copy of the
537 // stream is created.
538 const SvStream
* pStream (rBytes
.GetStream());
539 if (pStream
== nullptr)
542 // Create a memory stream and prepare to fill it with the content of
543 // the original stream.
544 mpStream
= std::make_shared
<SvMemoryStream
>();
545 static const std::size_t nBufferSize
= 4096;
546 ::std::unique_ptr
<sal_Int8
[]> pBuffer (new sal_Int8
[nBufferSize
]);
548 sal_uInt64
nReadPosition(0);
552 // Read the next part of the original stream.
553 std::size_t nReadByteCount (0);
554 const ErrCode
nErrorCode (
561 // Check the error code and stop copying the stream data when an
562 // error has occurred.
563 if (nErrorCode
== ERRCODE_NONE
)
565 if (nReadByteCount
== 0)
568 else if (nErrorCode
== ERRCODE_IO_PENDING
)
576 // Append the read bytes to the end of the memory stream.
577 if (nReadByteCount
> 0)
579 mpStream
->WriteBytes(pBuffer
.get(), nReadByteCount
);
580 nReadPosition
+= nReadByteCount
;
584 // Rewind the memory stream so that in the operator() method its
585 // content is properly read.
586 mpStream
->Seek(STREAM_SEEK_TO_BEGIN
);
589 void OutlineToImpressFinalizer::operator() (bool)
591 // Fetch the new outline view shell.
592 ::sd::OutlineViewShell
* pOutlineShell
593 = dynamic_cast<sd::OutlineViewShell
*>(FrameworkHelper::Instance(mrBase
)->GetViewShell(FrameworkHelper::msCenterPaneURL
).get());
595 if (pOutlineShell
!= nullptr && mpStream
!= nullptr)
597 sd::OutlineView
* pView
= static_cast<sd::OutlineView
*>(pOutlineShell
->GetView());
598 // mba: the stream can't contain any relative URLs, because we don't
599 // have any information about a BaseURL!
600 pOutlineShell
->ReadRtf(*mpStream
);
602 // Call UpdatePreview once for every slide to resync the
603 // document with the outliner of the OutlineViewShell.
604 sal_uInt16
nPageCount (mrDocument
.GetSdPageCount(PageKind::Standard
));
605 for (sal_uInt16 nIndex
=0; nIndex
<nPageCount
; nIndex
++)
607 SdPage
* pPage
= mrDocument
.GetSdPage(nIndex
, PageKind::Standard
);
608 // Make the page the actual page so that the
609 // following UpdatePreview() call accesses the
610 // correct paragraphs.
611 pView
->SetActualPage(pPage
);
612 pOutlineShell
->UpdatePreview(pPage
);
614 // Select the first slide.
615 SdPage
* pPage
= mrDocument
.GetSdPage(0, PageKind::Standard
);
616 pView
->SetActualPage(pPage
);
617 pOutlineShell
->UpdatePreview(pPage
);
620 // Undo-Stack needs to be cleared, else the user may remove the
621 // only drawpage and this is a state we cannot handle ATM.
622 ::sd::DrawDocShell
* pDocShell
= mrDocument
.GetDocSh();
624 pDocShell
->ClearUndoBuffer();
627 } // end of anonymous namespace
629 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */