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 <sfx2/frame.hxx>
22 #include <sfx2/viewfrm.hxx>
23 #include <unotools/moduleoptions.hxx>
24 #include <framework/FrameworkHelper.hxx>
26 #include <svx/dialogs.hrc>
27 #include <vcl/errinf.hxx>
28 #include <editeng/langitem.hxx>
29 #include <editeng/editdata.hxx>
30 #include <vcl/weld.hxx>
31 #include <editeng/svxenum.hxx>
32 #include <sfx2/dispatch.hxx>
33 #include <sfx2/request.hxx>
34 #include <sfx2/printer.hxx>
35 #include <sfx2/docfile.hxx>
36 #include <sfx2/templatedlg.hxx>
37 #include <editeng/paperinf.hxx>
38 #include <editeng/eeitem.hxx>
39 #include <unotools/useroptions.hxx>
40 #include <com/sun/star/uno/Sequence.h>
43 #include <strings.hrc>
47 #include <optsitem.hxx>
48 #include <ViewShell.hxx>
51 #include <DrawDocShell.hxx>
52 #include <drawdoc.hxx>
53 #include <assclass.hxx>
54 #include <sdenumdef.hxx>
55 #include <sdresid.hxx>
56 #include <OutlineViewShell.hxx>
57 #include <ViewShellBase.hxx>
58 #include <FrameView.hxx>
59 #include <FactoryIds.hxx>
60 #include <sdabstdlg.hxx>
62 #include <slideshow.hxx>
64 #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
65 #include <com/sun/star/document/XDocumentProperties.hpp>
67 using ::sd::framework::FrameworkHelper
;
68 using ::com::sun::star::uno::Reference
;
69 using ::com::sun::star::frame::XFrame
;
70 using ::com::sun::star::uno::Sequence
;
74 class OutlineToImpressFinalizer final
77 OutlineToImpressFinalizer (
78 ::sd::ViewShellBase
& rBase
,
79 SdDrawDocument
& rDocument
,
80 SvLockBytes
const & rBytes
);
81 void operator() (bool bEventSeen
);
83 ::sd::ViewShellBase
& mrBase
;
84 SdDrawDocument
& mrDocument
;
85 std::shared_ptr
<SvMemoryStream
> mpStream
;
88 } //end of anonymous namespace
90 void SdModule::Execute(SfxRequest
& rReq
)
92 const SfxItemSet
* pSet
= rReq
.GetArgs();
93 sal_uLong nSlotId
= rReq
.GetSlot();
99 SfxGetpApp()->ExecuteSlot(rReq
, SfxGetpApp()->GetInterface());
103 case SID_AUTOSPELL_CHECK
:
105 // automatic spell checker
106 const SfxPoolItem
* pItem
;
107 if( pSet
&& SfxItemState::SET
== pSet
->GetItemState(
108 SID_AUTOSPELL_CHECK
, false, &pItem
) )
110 bool bOnlineSpelling
= static_cast<const SfxBoolItem
*>( pItem
)->GetValue();
112 ::sd::DrawDocShell
* pDocSh
= dynamic_cast< ::sd::DrawDocShell
*>( SfxObjectShell::Current() );
115 SdDrawDocument
* pDoc
= pDocSh
->GetDoc();
116 pDoc
->SetOnlineSpell( bOnlineSpelling
);
122 case SID_ATTR_METRIC
:
124 const SfxPoolItem
* pItem
;
125 if ( pSet
&& SfxItemState::SET
== pSet
->GetItemState( SID_ATTR_METRIC
, true, &pItem
) )
127 FieldUnit eUnit
= static_cast<FieldUnit
>(static_cast<const SfxUInt16Item
*>(pItem
)->GetValue());
130 case FUNIT_MM
: // only the units which are also in the dialog
136 ::sd::DrawDocShell
* pDocSh
= dynamic_cast< ::sd::DrawDocShell
*>( SfxObjectShell::Current() );
139 DocumentType eDocType
= pDocSh
->GetDoc()->GetDocumentType();
142 SdOptions
* pOptions
= GetSdOptions( eDocType
);
144 pOptions
->SetMetric( static_cast<sal_uInt16
>(eUnit
) );
157 case SID_ATTR_LANGUAGE
:
158 case SID_ATTR_CHAR_CJK_LANGUAGE
:
159 case SID_ATTR_CHAR_CTL_LANGUAGE
:
161 const SfxPoolItem
* pItem
;
164 SfxItemState::SET
== pSet
->GetItemState(SID_ATTR_LANGUAGE
, false, &pItem
) ||
165 SfxItemState::SET
== pSet
->GetItemState(SID_ATTR_CHAR_CJK_LANGUAGE
, false, &pItem
) ||
166 SfxItemState::SET
== pSet
->GetItemState(SID_ATTR_CHAR_CTL_LANGUAGE
, false, &pItem
)
170 // save at the document:
171 ::sd::DrawDocShell
* pDocSh
= dynamic_cast< ::sd::DrawDocShell
*>( SfxObjectShell::Current() );
174 LanguageType eLanguage
= static_cast<const SvxLanguageItem
*>(pItem
)->GetValue();
175 SdDrawDocument
* pDoc
= pDocSh
->GetDoc();
177 if( nSlotId
== SID_ATTR_CHAR_CJK_LANGUAGE
)
178 pDoc
->SetLanguage( eLanguage
, EE_CHAR_LANGUAGE_CJK
);
179 else if( nSlotId
== SID_ATTR_CHAR_CTL_LANGUAGE
)
180 pDoc
->SetLanguage( eLanguage
, EE_CHAR_LANGUAGE_CTL
);
182 pDoc
->SetLanguage( eLanguage
, EE_CHAR_LANGUAGE
);
184 if( pDoc
->GetOnlineSpell() )
186 pDoc
->StopOnlineSpelling();
187 pDoc
->StartOnlineSpelling();
196 SfxFrame
* pFrame
= ExecuteNewDocument( rReq
);
197 // if a frame was created, set it as return value
199 rReq
.SetReturnValue(SfxFrameItem(0, pFrame
));
204 case SID_OPENHYPERLINK
:
207 bool bIntercept
= false;
208 ::sd::DrawDocShell
* pDocShell
= dynamic_cast< ::sd::DrawDocShell
*>( SfxObjectShell::Current() );
211 ::sd::ViewShell
* pViewShell
= pDocShell
->GetViewShell();
214 if( sd::SlideShow::IsRunning( pViewShell
->GetViewShellBase() ) )
216 // Prevent documents from opening while the slide
217 // show is running, except when this request comes
218 // from a shape interaction.
219 if (rReq
.GetArgs() == nullptr)
229 SfxGetpApp()->ExecuteSlot(rReq
, SfxGetpApp()->GetInterface());
233 std::unique_ptr
<weld::MessageDialog
> xErrorBox(Application::CreateMessageDialog(nullptr,
234 VclMessageType::Warning
, VclButtonsType::Ok
, SdResId(STR_CANT_PERFORM_IN_LIVEMODE
)));
238 const SfxLinkItem
* pLinkItem
= rReq
.GetArg
<SfxLinkItem
>(SID_DONELINK
);
240 pLinkItem
->GetValue().Call( nullptr );
245 case SID_OUTLINE_TO_IMPRESS
:
246 OutlineToImpress (rReq
);
254 bool SdModule::OutlineToImpress(SfxRequest
const & rRequest
)
256 const SfxItemSet
* pSet
= rRequest
.GetArgs();
260 SvLockBytes
* pBytes
= static_cast<const SfxLockBytesItem
&>(pSet
->Get(SID_OUTLINE_TO_IMPRESS
)).GetValue();
264 SfxObjectShellLock xDocShell
;
265 ::sd::DrawDocShell
* pDocSh
;
266 xDocShell
= pDocSh
= new ::sd::DrawDocShell(
267 SfxObjectCreateMode::STANDARD
, false, DocumentType::Impress
);
270 SdDrawDocument
* pDoc
= pDocSh
->GetDoc();
273 pDoc
->CreateFirstPages();
274 pDoc
->StopWorkStartupDelay();
277 const SfxFrameItem
* pFrmItem
= rRequest
.GetArg
<SfxFrameItem
>(SID_DOCFRAME
);
278 SfxViewFrame::LoadDocumentIntoFrame( *pDocSh
, pFrmItem
, ::sd::OUTLINE_FACTORY_ID
);
280 ::sd::ViewShell
* pViewSh
= pDocSh
->GetViewShell();
284 // AutoLayouts have to be finished
285 pDoc
->StopWorkStartupDelay();
287 SfxViewFrame
* pViewFrame
= pViewSh
->GetViewFrame();
289 // When the view frame has not been just created we have
290 // to switch synchronously to the outline view.
291 // (Otherwise the request will be ignored anyway.)
292 ::sd::ViewShellBase
* pBase
293 = dynamic_cast< ::sd::ViewShellBase
*>(pViewFrame
->GetViewShell());
294 if (pBase
!= nullptr)
296 std::shared_ptr
<FrameworkHelper
> pHelper (
297 FrameworkHelper::Instance(*pBase
));
298 pHelper
->RequestView(
299 FrameworkHelper::msOutlineViewURL
,
300 FrameworkHelper::msCenterPaneURL
);
302 pHelper
->RunOnResourceActivation(
303 FrameworkHelper::CreateResourceId(
304 FrameworkHelper::msOutlineViewURL
,
305 FrameworkHelper::msCenterPaneURL
),
306 OutlineToImpressFinalizer(*pBase
, *pDoc
, *pBytes
));
312 return rRequest
.IsDone();
315 void SdModule::GetState(SfxItemSet
& rItemSet
)
317 if( SfxItemState::DEFAULT
== rItemSet
.GetItemState( SID_ATTR_METRIC
) )
319 ::sd::DrawDocShell
* pDocSh
= dynamic_cast< ::sd::DrawDocShell
*>( SfxObjectShell::Current() );
322 DocumentType eDocType
= pDocSh
->GetDoc()->GetDocumentType();
324 SdOptions
* pOptions
= GetSdOptions(eDocType
);
325 rItemSet
.Put( SfxUInt16Item( SID_ATTR_METRIC
, pOptions
->GetMetric() ) );
329 // state of SID_OPENDOC is determined by the base class
330 if (rItemSet
.GetItemState(SID_OPENDOC
) != SfxItemState::UNKNOWN
)
332 const SfxPoolItem
* pItem
= SfxGetpApp()->GetSlotState(SID_OPENDOC
, SfxGetpApp()->GetInterface());
334 rItemSet
.Put(*pItem
);
337 // state of SID_OPENHYPERLINK is determined by the base class
338 if (rItemSet
.GetItemState(SID_OPENHYPERLINK
) != SfxItemState::UNKNOWN
)
340 const SfxPoolItem
* pItem
= SfxGetpApp()->GetSlotState(SID_OPENHYPERLINK
, SfxGetpApp()->GetInterface());
342 rItemSet
.Put(*pItem
);
345 if( SfxItemState::DEFAULT
== rItemSet
.GetItemState( SID_AUTOSPELL_CHECK
) )
347 ::sd::DrawDocShell
* pDocSh
=
348 dynamic_cast< ::sd::DrawDocShell
*>( SfxObjectShell::Current() );
351 SdDrawDocument
* pDoc
= pDocSh
->GetDoc();
352 rItemSet
.Put( SfxBoolItem( SID_AUTOSPELL_CHECK
, pDoc
->GetOnlineSpell() ) );
356 if( SfxItemState::DEFAULT
== rItemSet
.GetItemState( SID_ATTR_LANGUAGE
) )
358 ::sd::DrawDocShell
* pDocSh
= dynamic_cast< ::sd::DrawDocShell
*>( SfxObjectShell::Current() );
360 rItemSet
.Put( SvxLanguageItem( pDocSh
->GetDoc()->GetLanguage( EE_CHAR_LANGUAGE
), SID_ATTR_LANGUAGE
) );
363 if( SfxItemState::DEFAULT
== rItemSet
.GetItemState( SID_ATTR_CHAR_CJK_LANGUAGE
) )
365 ::sd::DrawDocShell
* pDocSh
= dynamic_cast< ::sd::DrawDocShell
*>( SfxObjectShell::Current() );
367 rItemSet
.Put( SvxLanguageItem( pDocSh
->GetDoc()->GetLanguage( EE_CHAR_LANGUAGE_CJK
), SID_ATTR_CHAR_CJK_LANGUAGE
) );
370 if( SfxItemState::DEFAULT
== rItemSet
.GetItemState( SID_ATTR_CHAR_CTL_LANGUAGE
) )
372 ::sd::DrawDocShell
* pDocSh
= dynamic_cast< ::sd::DrawDocShell
*>( SfxObjectShell::Current() );
374 rItemSet
.Put( SvxLanguageItem( pDocSh
->GetDoc()->GetLanguage( EE_CHAR_LANGUAGE_CTL
), SID_ATTR_CHAR_CTL_LANGUAGE
) );
377 if ( !mbEventListenerAdded
)
379 ::sd::DrawDocShell
* pDocShell
= dynamic_cast< ::sd::DrawDocShell
*>( SfxObjectShell::Current() );
380 if( pDocShell
) // Impress or Draw ?
382 ::sd::ViewShell
* pViewShell
= pDocShell
->GetViewShell();
384 if( pViewShell
&& (pDocShell
->GetDocumentType() == DocumentType::Impress
) )
386 // add our event listener as soon as possible
387 Application::AddEventListener( LINK( this, SdModule
, EventListenerHdl
) );
388 mbEventListenerAdded
= true;
394 IMPL_STATIC_LINK( SdModule
, EventListenerHdl
, VclSimpleEvent
&, rSimpleEvent
, void )
396 if( (rSimpleEvent
.GetId() == VclEventId::WindowCommand
) && static_cast<VclWindowEvent
*>(&rSimpleEvent
)->GetData() )
398 const CommandEvent
& rEvent
= *static_cast<const CommandEvent
*>(static_cast<VclWindowEvent
*>(&rSimpleEvent
)->GetData());
400 if( rEvent
.GetCommand() == CommandEventId::Media
)
402 CommandMediaData
* pMediaData
= rEvent
.GetMediaData();
403 pMediaData
->SetPassThroughToOS(false);
404 switch (pMediaData
->GetMediaId())
406 case MediaCommand::Play
:
408 ::sd::DrawDocShell
* pDocShell
= dynamic_cast< ::sd::DrawDocShell
*>( SfxObjectShell::Current() );
409 if( pDocShell
) // Impress or Draw ?
411 ::sd::ViewShell
* pViewShell
= pDocShell
->GetViewShell();
413 // #i97925# start the presentation if and only if an Impress document is focused
414 if( pViewShell
&& (pDocShell
->GetDocumentType() == DocumentType::Impress
) )
415 pViewShell
->GetViewFrame()->GetDispatcher()->Execute( SID_PRESENTATION
);
420 pMediaData
->SetPassThroughToOS(true);
428 SfxFrame
* SdModule::CreateFromTemplate( const OUString
& rTemplatePath
, const Reference
< XFrame
>& i_rFrame
)
430 SfxFrame
* pFrame
= nullptr;
432 SfxObjectShellLock xDocShell
;
434 SfxItemSet
* pSet
= new SfxAllItemSet( SfxGetpApp()->GetPool() );
435 pSet
->Put( SfxBoolItem( SID_TEMPLATE
, true ) );
437 ErrCode lErr
= SfxGetpApp()->LoadTemplate( xDocShell
, rTemplatePath
, pSet
);
439 SfxObjectShell
* pDocShell
= xDocShell
;
443 ErrorHandler::HandleError(lErr
);
447 SfxViewFrame
* pViewFrame
= SfxViewFrame::LoadDocumentIntoFrame( *pDocShell
, i_rFrame
);
448 OSL_ENSURE( pViewFrame
, "SdModule::CreateFromTemplate: no view frame - was the document really loaded?" );
449 pFrame
= pViewFrame
? &pViewFrame
->GetFrame() : nullptr;
456 SfxFrame
* SdModule::ExecuteNewDocument( SfxRequest
const & rReq
)
458 SfxFrame
* pFrame
= nullptr;
459 if ( SvtModuleOptions().IsImpress() )
461 Reference
< XFrame
> xTargetFrame
;
462 const SfxUnoFrameItem
* pFrmItem
= rReq
.GetArg
<SfxUnoFrameItem
>(SID_FILLFRAME
);
464 xTargetFrame
= pFrmItem
->GetFrame();
466 SdOptions
* pOpt
= GetSdOptions(DocumentType::Impress
);
467 bool bStartWithTemplate
= pOpt
->IsStartWithTemplate();
469 bool bNewDocDirect
= rReq
.GetSlot() == SID_NEWSD
;
473 //we start without wizard
475 //check whether we should load a template document
476 const OUString
aServiceName( "com.sun.star.presentation.PresentationDocument" );
477 OUString
aStandardTemplate( SfxObjectFactory::GetStandardTemplate( aServiceName
) );
479 if( !aStandardTemplate
.isEmpty() )
481 //load a template document
482 pFrame
= CreateFromTemplate( aStandardTemplate
, xTargetFrame
);
486 //create an empty document
487 pFrame
= CreateEmptyDocument( xTargetFrame
);
491 if(bStartWithTemplate
)
493 //Launch TemplateSelectionDialog
494 ScopedVclPtrInstance
< SfxTemplateSelectionDlg
> aTemplDlg( SfxGetpApp()->GetTopWindow());
495 aTemplDlg
->Execute();
497 //check to disable the dialog
498 pOpt
->SetStartWithTemplate( aTemplDlg
->IsStartWithTemplate() );
500 //pFrame is loaded with the desired template
501 if(!aTemplDlg
->getTemplatePath().isEmpty())
502 pFrame
= CreateFromTemplate(aTemplDlg
->getTemplatePath(), xTargetFrame
);
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();
524 SfxViewFrame
* pViewFrame
= SfxViewFrame::LoadDocumentIntoFrame( *pNewDocSh
, i_rFrame
);
525 OSL_ENSURE( pViewFrame
, "SdModule::CreateEmptyDocument: no view frame - was the document really loaded?" );
526 pFrame
= pViewFrame
? &pViewFrame
->GetFrame() : nullptr;
531 //===== OutlineToImpressFinalize ==============================================
535 OutlineToImpressFinalizer::OutlineToImpressFinalizer (
536 ::sd::ViewShellBase
& rBase
,
537 SdDrawDocument
& rDocument
,
538 SvLockBytes
const & rBytes
)
540 mrDocument(rDocument
),
543 // The given stream has a lifetime shorter than this new
544 // OutlineToImpressFinalizer object. Therefore a local copy of the
545 // stream is created.
546 const SvStream
* pStream (rBytes
.GetStream());
547 if (pStream
!= nullptr)
549 // Create a memory stream and prepare to fill it with the content of
550 // the original stream.
551 mpStream
.reset(new SvMemoryStream());
552 static const std::size_t nBufferSize
= 4096;
553 ::std::unique_ptr
<sal_Int8
[]> pBuffer (new sal_Int8
[nBufferSize
]);
555 sal_uInt64
nReadPosition(0);
559 // Read the next part of the original stream.
560 std::size_t nReadByteCount (0);
561 const ErrCode
nErrorCode (
568 // Check the error code and stop copying the stream data when an
569 // error has occurred.
570 if (nErrorCode
== ERRCODE_NONE
)
572 if (nReadByteCount
== 0)
575 else if (nErrorCode
== ERRCODE_IO_PENDING
)
583 // Append the read bytes to the end of the memory stream.
584 if (nReadByteCount
> 0)
586 mpStream
->WriteBytes(pBuffer
.get(), nReadByteCount
);
587 nReadPosition
+= nReadByteCount
;
591 // Rewind the memory stream so that in the operator() method its
592 // content is properly read.
593 mpStream
->Seek(STREAM_SEEK_TO_BEGIN
);
597 void OutlineToImpressFinalizer::operator() (bool)
599 // Fetch the new outline view shell.
600 ::sd::OutlineViewShell
* pOutlineShell
601 = dynamic_cast<sd::OutlineViewShell
*>(FrameworkHelper::Instance(mrBase
)->GetViewShell(FrameworkHelper::msCenterPaneURL
).get());
603 if (pOutlineShell
!= nullptr && mpStream
.get() != nullptr)
605 sd::OutlineView
* pView
= static_cast<sd::OutlineView
*>(pOutlineShell
->GetView());
606 // mba: the stream can't contain any relative URLs, because we don't
607 // have any information about a BaseURL!
608 pOutlineShell
->ReadRtf(*mpStream
);
610 // Call UpdatePreview once for every slide to resync the
611 // document with the outliner of the OutlineViewShell.
612 sal_uInt16
nPageCount (mrDocument
.GetSdPageCount(PageKind::Standard
));
613 for (sal_uInt16 nIndex
=0; nIndex
<nPageCount
; nIndex
++)
615 SdPage
* pPage
= mrDocument
.GetSdPage(nIndex
, PageKind::Standard
);
616 // Make the page the actual page so that the
617 // following UpdatePreview() call accesses the
618 // correct paragraphs.
619 pView
->SetActualPage(pPage
);
620 pOutlineShell
->UpdatePreview(pPage
, true);
622 // Select the first slide.
623 SdPage
* pPage
= mrDocument
.GetSdPage(0, PageKind::Standard
);
624 pView
->SetActualPage(pPage
);
625 pOutlineShell
->UpdatePreview(pPage
, true);
628 // Undo-Stack needs to be cleared, else the user may remove the
629 // only drawpage and this is a state we cannot handle ATM.
630 ::sd::DrawDocShell
* pDocShell
= mrDocument
.GetDocSh();
632 pDocShell
->ClearUndoBuffer();
635 } // end of anonymous namespace
637 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */