Version 6.1.0.2, tag libreoffice-6.1.0.2
[LibreOffice.git] / sd / source / ui / app / sdmod1.cxx
blob56f9eb41cd8fd7bb2bf87fdbfc23aae46ba69554
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 <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>
42 #include <app.hrc>
43 #include <strings.hrc>
45 #include <sdmod.hxx>
46 #include <pres.hxx>
47 #include <optsitem.hxx>
48 #include <ViewShell.hxx>
49 #include <sdattr.hxx>
50 #include <sdpage.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>
61 #include <memory>
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;
72 namespace {
74 class OutlineToImpressFinalizer final
76 public:
77 OutlineToImpressFinalizer (
78 ::sd::ViewShellBase& rBase,
79 SdDrawDocument& rDocument,
80 SvLockBytes const & rBytes);
81 void operator() (bool bEventSeen);
82 private:
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();
95 switch ( nSlotId )
97 case SID_NEWDOC:
99 SfxGetpApp()->ExecuteSlot(rReq, SfxGetpApp()->GetInterface());
101 break;
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();
111 // save at document:
112 ::sd::DrawDocShell* pDocSh = dynamic_cast< ::sd::DrawDocShell *>( SfxObjectShell::Current() );
113 if( pDocSh )
115 SdDrawDocument* pDoc = pDocSh->GetDoc();
116 pDoc->SetOnlineSpell( bOnlineSpelling );
120 break;
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());
128 switch( eUnit )
130 case FUNIT_MM: // only the units which are also in the dialog
131 case FUNIT_CM:
132 case FUNIT_INCH:
133 case FUNIT_PICA:
134 case FUNIT_POINT:
136 ::sd::DrawDocShell* pDocSh = dynamic_cast< ::sd::DrawDocShell *>( SfxObjectShell::Current() );
137 if(pDocSh)
139 DocumentType eDocType = pDocSh->GetDoc()->GetDocumentType();
141 PutItem( *pItem );
142 SdOptions* pOptions = GetSdOptions( eDocType );
143 if(pOptions)
144 pOptions->SetMetric( static_cast<sal_uInt16>(eUnit) );
145 rReq.Done();
148 break;
149 default:
150 break;
155 break;
157 case SID_ATTR_LANGUAGE:
158 case SID_ATTR_CHAR_CJK_LANGUAGE:
159 case SID_ATTR_CHAR_CTL_LANGUAGE:
161 const SfxPoolItem* pItem;
162 if( pSet &&
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() );
172 if ( pDocSh )
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 );
181 else
182 pDoc->SetLanguage( eLanguage, EE_CHAR_LANGUAGE );
184 if( pDoc->GetOnlineSpell() )
186 pDoc->StopOnlineSpelling();
187 pDoc->StartOnlineSpelling();
192 break;
194 case SID_NEWSD:
196 SfxFrame* pFrame = ExecuteNewDocument( rReq );
197 // if a frame was created, set it as return value
198 if(pFrame)
199 rReq.SetReturnValue(SfxFrameItem(0, pFrame));
202 break;
204 case SID_OPENHYPERLINK:
205 case SID_OPENDOC:
207 bool bIntercept = false;
208 ::sd::DrawDocShell* pDocShell = dynamic_cast< ::sd::DrawDocShell *>( SfxObjectShell::Current() );
209 if (pDocShell)
211 ::sd::ViewShell* pViewShell = pDocShell->GetViewShell();
212 if (pViewShell)
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)
221 bIntercept = true;
227 if (!bIntercept)
229 SfxGetpApp()->ExecuteSlot(rReq, SfxGetpApp()->GetInterface());
231 else
233 std::unique_ptr<weld::MessageDialog> xErrorBox(Application::CreateMessageDialog(nullptr,
234 VclMessageType::Warning, VclButtonsType::Ok, SdResId(STR_CANT_PERFORM_IN_LIVEMODE)));
236 xErrorBox->run();
238 const SfxLinkItem* pLinkItem = rReq.GetArg<SfxLinkItem>(SID_DONELINK);
239 if( pLinkItem )
240 pLinkItem->GetValue().Call( nullptr );
243 break;
245 case SID_OUTLINE_TO_IMPRESS:
246 OutlineToImpress (rReq);
247 break;
249 default:
250 break;
254 bool SdModule::OutlineToImpress(SfxRequest const & rRequest)
256 const SfxItemSet* pSet = rRequest.GetArgs();
258 if (pSet)
260 SvLockBytes* pBytes = static_cast<const SfxLockBytesItem&>(pSet->Get(SID_OUTLINE_TO_IMPRESS)).GetValue();
262 if (pBytes)
264 SfxObjectShellLock xDocShell;
265 ::sd::DrawDocShell* pDocSh;
266 xDocShell = pDocSh = new ::sd::DrawDocShell(
267 SfxObjectCreateMode::STANDARD, false, DocumentType::Impress);
269 pDocSh->DoInitNew();
270 SdDrawDocument* pDoc = pDocSh->GetDoc();
271 if(pDoc)
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();
282 if (pViewSh && pDoc)
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() );
320 if(pDocSh)
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());
333 if (pItem)
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());
341 if (pItem)
342 rItemSet.Put(*pItem);
345 if( SfxItemState::DEFAULT == rItemSet.GetItemState( SID_AUTOSPELL_CHECK ) )
347 ::sd::DrawDocShell* pDocSh =
348 dynamic_cast< ::sd::DrawDocShell *>( SfxObjectShell::Current() );
349 if( pDocSh )
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() );
359 if( pDocSh )
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() );
366 if( pDocSh )
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() );
373 if( pDocSh )
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 );
417 break;
419 default:
420 pMediaData->SetPassThroughToOS(true);
421 break;
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;
441 if( lErr )
443 ErrorHandler::HandleError(lErr);
445 else if( pDocShell )
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;
452 return pFrame;
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);
463 if ( pFrmItem )
464 xTargetFrame = pFrmItem->GetFrame();
466 SdOptions* pOpt = GetSdOptions(DocumentType::Impress);
467 bool bStartWithTemplate = pOpt->IsStartWithTemplate();
469 bool bNewDocDirect = rReq.GetSlot() == SID_NEWSD;
471 if( bNewDocDirect )
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 );
484 else
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);
506 return pFrame;
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();
518 if (pDoc)
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;
528 return pFrame;
531 //===== OutlineToImpressFinalize ==============================================
533 namespace {
535 OutlineToImpressFinalizer::OutlineToImpressFinalizer (
536 ::sd::ViewShellBase& rBase,
537 SdDrawDocument& rDocument,
538 SvLockBytes const & rBytes)
539 : mrBase(rBase),
540 mrDocument(rDocument),
541 mpStream()
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);
556 bool bLoop (true);
557 while (bLoop)
559 // Read the next part of the original stream.
560 std::size_t nReadByteCount (0);
561 const ErrCode nErrorCode (
562 rBytes.ReadAt(
563 nReadPosition,
564 pBuffer.get(),
565 nBufferSize,
566 &nReadByteCount));
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)
573 bLoop = false;
575 else if (nErrorCode == ERRCODE_IO_PENDING)
577 else
579 bLoop = false;
580 nReadByteCount = 0;
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();
631 if( pDocShell )
632 pDocShell->ClearUndoBuffer();
635 } // end of anonymous namespace
637 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */