Bump version to 21.06.18.1
[LibreOffice.git] / sd / source / ui / app / sdmod1.cxx
blob35bf5ebfb5ea4611567aa7b16093b91f90a6454b
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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>
41 #include <sdmod.hxx>
42 #include <pres.hxx>
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>
52 #include <memory>
53 #include <slideshow.hxx>
55 using ::sd::framework::FrameworkHelper;
56 using ::com::sun::star::uno::Reference;
57 using ::com::sun::star::frame::XFrame;
59 namespace {
61 class OutlineToImpressFinalizer final
63 public:
64 OutlineToImpressFinalizer (
65 ::sd::ViewShellBase& rBase,
66 SdDrawDocument& rDocument,
67 SvLockBytes const & rBytes);
68 void operator() (bool bEventSeen);
69 private:
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();
82 switch ( nSlotId )
84 case SID_NEWDOC:
86 SfxGetpApp()->ExecuteSlot(rReq, SfxGetpApp()->GetInterface());
88 break;
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();
98 // save at document:
99 ::sd::DrawDocShell* pDocSh = dynamic_cast< ::sd::DrawDocShell *>( SfxObjectShell::Current() );
100 if( pDocSh )
102 SdDrawDocument* pDoc = pDocSh->GetDoc();
103 pDoc->SetOnlineSpell( bOnlineSpelling );
107 break;
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());
115 switch( eUnit )
117 case FieldUnit::MM: // only the units which are also in the dialog
118 case FieldUnit::CM:
119 case FieldUnit::INCH:
120 case FieldUnit::PICA:
121 case FieldUnit::POINT:
123 ::sd::DrawDocShell* pDocSh = dynamic_cast< ::sd::DrawDocShell *>( SfxObjectShell::Current() );
124 if(pDocSh)
126 DocumentType eDocType = pDocSh->GetDoc()->GetDocumentType();
128 PutItem( *pItem );
129 SdOptions* pOptions = GetSdOptions( eDocType );
130 if(pOptions)
131 pOptions->SetMetric( static_cast<sal_uInt16>(eUnit) );
132 rReq.Done();
135 break;
136 default:
137 break;
142 break;
144 case SID_ATTR_LANGUAGE:
145 case SID_ATTR_CHAR_CJK_LANGUAGE:
146 case SID_ATTR_CHAR_CTL_LANGUAGE:
148 const SfxPoolItem* pItem;
149 if( pSet &&
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() );
159 if ( pDocSh )
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 );
168 else
169 pDoc->SetLanguage( eLanguage, EE_CHAR_LANGUAGE );
171 if( pDoc->GetOnlineSpell() )
173 pDoc->StopOnlineSpelling();
174 pDoc->StartOnlineSpelling();
179 break;
181 case SID_NEWSD:
183 SfxFrame* pFrame = ExecuteNewDocument( rReq );
184 // if a frame was created, set it as return value
185 if(pFrame)
186 rReq.SetReturnValue(SfxFrameItem(0, pFrame));
189 break;
191 case SID_OPENHYPERLINK:
192 case SID_OPENDOC:
194 bool bIntercept = false;
195 ::sd::DrawDocShell* pDocShell = dynamic_cast< ::sd::DrawDocShell *>( SfxObjectShell::Current() );
196 if (pDocShell)
198 ::sd::ViewShell* pViewShell = pDocShell->GetViewShell();
199 if (pViewShell)
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)
208 bIntercept = true;
214 if (!bIntercept)
216 SfxGetpApp()->ExecuteSlot(rReq, SfxGetpApp()->GetInterface());
218 else
220 std::unique_ptr<weld::MessageDialog> xErrorBox(Application::CreateMessageDialog(nullptr,
221 VclMessageType::Warning, VclButtonsType::Ok, SdResId(STR_CANT_PERFORM_IN_LIVEMODE)));
223 xErrorBox->run();
225 const SfxLinkItem* pLinkItem = rReq.GetArg<SfxLinkItem>(SID_DONELINK);
226 if( pLinkItem )
227 pLinkItem->GetValue().Call( nullptr );
230 break;
232 case SID_OUTLINE_TO_IMPRESS:
233 OutlineToImpress (rReq);
234 break;
236 default:
237 break;
241 bool SdModule::OutlineToImpress(SfxRequest const & rRequest)
243 const SfxItemSet* pSet = rRequest.GetArgs();
245 if (pSet)
247 SvLockBytes* pBytes = static_cast<const SfxLockBytesItem&>(pSet->Get(SID_OUTLINE_TO_IMPRESS)).GetValue();
249 if (pBytes)
251 SfxObjectShellLock xDocShell;
252 ::sd::DrawDocShell* pDocSh;
253 xDocShell = pDocSh = new ::sd::DrawDocShell(
254 SfxObjectCreateMode::STANDARD, false, DocumentType::Impress);
256 pDocSh->DoInitNew();
257 SdDrawDocument* pDoc = pDocSh->GetDoc();
258 if(pDoc)
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();
269 if (pViewSh && pDoc)
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() );
307 if(pDocSh)
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());
320 if (pItem)
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());
328 if (pItem)
329 rItemSet.Put(*pItem);
332 if( SfxItemState::DEFAULT == rItemSet.GetItemState( SID_AUTOSPELL_CHECK ) )
334 ::sd::DrawDocShell* pDocSh =
335 dynamic_cast< ::sd::DrawDocShell *>( SfxObjectShell::Current() );
336 if( pDocSh )
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() );
346 if( pDocSh )
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() );
353 if( pDocSh )
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() );
360 if( pDocSh )
361 rItemSet.Put( SvxLanguageItem( pDocSh->GetDoc()->GetLanguage( EE_CHAR_LANGUAGE_CTL ), SID_ATTR_CHAR_CTL_LANGUAGE ) );
364 if ( mbEventListenerAdded )
365 return;
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()) )
384 return;
386 const CommandEvent& rEvent = *static_cast<const CommandEvent*>(static_cast<VclWindowEvent*>(&rSimpleEvent)->GetData());
388 if( rEvent.GetCommand() != CommandEventId::Media )
389 return;
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 );
406 break;
408 default:
409 pMediaData->SetPassThroughToOS(true);
410 break;
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;
429 if( lErr )
431 ErrorHandler::HandleError(lErr);
433 else if( pDocShell )
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;
442 return pFrame;
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);
453 if ( pFrmItem )
454 xTargetFrame = pFrmItem->GetFrame();
456 SdOptions* pOpt = GetSdOptions(DocumentType::Impress);
457 bool bStartWithTemplate = pOpt->IsStartWithTemplate();
459 bool bNewDocDirect = rReq.GetSlot() == SID_NEWSD;
461 if( bNewDocDirect )
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);
473 else
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);
485 aTemplDlg.run();
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);
496 return pFrame;
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();
508 if (pDoc)
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;
520 return pFrame;
523 //===== OutlineToImpressFinalize ==============================================
525 namespace {
527 OutlineToImpressFinalizer::OutlineToImpressFinalizer (
528 ::sd::ViewShellBase& rBase,
529 SdDrawDocument& rDocument,
530 SvLockBytes const & rBytes)
531 : mrBase(rBase),
532 mrDocument(rDocument),
533 mpStream()
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)
540 return;
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);
549 bool bLoop (true);
550 while (bLoop)
552 // Read the next part of the original stream.
553 std::size_t nReadByteCount (0);
554 const ErrCode nErrorCode (
555 rBytes.ReadAt(
556 nReadPosition,
557 pBuffer.get(),
558 nBufferSize,
559 &nReadByteCount));
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)
566 bLoop = false;
568 else if (nErrorCode == ERRCODE_IO_PENDING)
570 else
572 bLoop = false;
573 nReadByteCount = 0;
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();
623 if( pDocShell )
624 pDocShell->ClearUndoBuffer();
627 } // end of anonymous namespace
629 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */