android: Update app-specific/MIME type icons
[LibreOffice.git] / sd / source / ui / app / sdmod1.cxx
blob881d5aa1eefd29643f725b55c3cb993064f00072
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>
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>
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_uInt16 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 SfxBoolItem* pItem;
94 if( pSet && (pItem = pSet->GetItemIfSet( SID_AUTOSPELL_CHECK, false ) ) )
96 bool bOnlineSpelling = pItem->GetValue();
97 // save at document:
98 ::sd::DrawDocShell* pDocSh = dynamic_cast< ::sd::DrawDocShell *>( SfxObjectShell::Current() );
99 if( pDocSh )
101 SdDrawDocument* pDoc = pDocSh->GetDoc();
102 pDoc->SetOnlineSpell( bOnlineSpelling );
106 break;
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());
114 switch( eUnit )
116 case FieldUnit::MM: // only the units which are also in the dialog
117 case FieldUnit::CM:
118 case FieldUnit::INCH:
119 case FieldUnit::PICA:
120 case FieldUnit::POINT:
122 ::sd::DrawDocShell* pDocSh = dynamic_cast< ::sd::DrawDocShell *>( SfxObjectShell::Current() );
123 if(pDocSh)
125 DocumentType eDocType = pDocSh->GetDoc()->GetDocumentType();
127 PutItem( *pItem );
128 SdOptions* pOptions = GetSdOptions( eDocType );
129 if(pOptions)
130 pOptions->SetMetric( static_cast<sal_uInt16>(eUnit) );
131 rReq.Done();
134 break;
135 default:
136 break;
141 break;
143 case SID_ATTR_LANGUAGE:
144 case SID_ATTR_CHAR_CJK_LANGUAGE:
145 case SID_ATTR_CHAR_CTL_LANGUAGE:
147 const SfxPoolItem* pItem;
148 if( pSet &&
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() );
158 if ( pDocSh )
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 );
167 else
168 pDoc->SetLanguage( eLanguage, EE_CHAR_LANGUAGE );
170 if( pDoc->GetOnlineSpell() )
172 pDoc->StopOnlineSpelling();
173 pDoc->StartOnlineSpelling();
178 break;
180 case SID_NEWSD:
182 SfxFrame* pFrame = ExecuteNewDocument( rReq );
183 // if a frame was created, set it as return value
184 if(pFrame)
185 rReq.SetReturnValue(SfxFrameItem(0, pFrame));
188 break;
190 case SID_OPENHYPERLINK:
191 case SID_OPENDOC:
193 bool bIntercept = false;
194 ::sd::DrawDocShell* pDocShell = dynamic_cast< ::sd::DrawDocShell *>( SfxObjectShell::Current() );
195 if (pDocShell)
197 ::sd::ViewShell* pViewShell = pDocShell->GetViewShell();
198 if (pViewShell)
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)
207 bIntercept = true;
213 if (!bIntercept)
215 SfxGetpApp()->ExecuteSlot(rReq, SfxGetpApp()->GetInterface());
217 else
219 std::unique_ptr<weld::MessageDialog> xErrorBox(Application::CreateMessageDialog(nullptr,
220 VclMessageType::Warning, VclButtonsType::Ok, SdResId(STR_CANT_PERFORM_IN_LIVEMODE)));
222 xErrorBox->run();
224 const SfxLinkItem* pLinkItem = rReq.GetArg<SfxLinkItem>(SID_DONELINK);
225 if( pLinkItem )
226 pLinkItem->GetValue().Call( nullptr );
229 break;
231 case SID_OUTLINE_TO_IMPRESS:
232 OutlineToImpress (rReq);
233 break;
235 default:
236 break;
240 bool SdModule::OutlineToImpress(SfxRequest const & rRequest)
242 const SfxItemSet* pSet = rRequest.GetArgs();
244 if (pSet)
246 SvLockBytes* pBytes = static_cast<const SfxLockBytesItem&>(pSet->Get(SID_OUTLINE_TO_IMPRESS)).GetValue();
248 if (pBytes)
250 SfxObjectShellLock xDocShell;
251 ::sd::DrawDocShell* pDocSh;
252 xDocShell = pDocSh = new ::sd::DrawDocShell(
253 SfxObjectCreateMode::STANDARD, false, DocumentType::Impress);
255 pDocSh->DoInitNew();
256 SdDrawDocument* pDoc = pDocSh->GetDoc();
257 if(pDoc)
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();
268 if (pViewSh && pDoc)
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() );
306 if(pDocSh)
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());
319 if (pItem)
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());
327 if (pItem)
328 rItemSet.Put(*pItem);
331 if( SfxItemState::DEFAULT == rItemSet.GetItemState( SID_AUTOSPELL_CHECK ) )
333 ::sd::DrawDocShell* pDocSh =
334 dynamic_cast< ::sd::DrawDocShell *>( SfxObjectShell::Current() );
335 if( pDocSh )
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() );
345 if( pDocSh )
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() );
352 if( pDocSh )
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() );
359 if( pDocSh )
360 rItemSet.Put( SvxLanguageItem( pDocSh->GetDoc()->GetLanguage( EE_CHAR_LANGUAGE_CTL ), SID_ATTR_CHAR_CTL_LANGUAGE ) );
363 if ( mbEventListenerAdded )
364 return;
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()) )
383 return;
385 const CommandEvent& rEvent = *static_cast<const CommandEvent*>(static_cast<VclWindowEvent*>(&rSimpleEvent)->GetData());
387 if( rEvent.GetCommand() != CommandEventId::Media )
388 return;
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 );
405 break;
407 default:
408 pMediaData->SetPassThroughToOS(true);
409 break;
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;
428 if( lErr )
430 ErrorHandler::HandleError(lErr);
432 else if( pDocShell )
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;
441 return pFrame;
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);
452 if ( pFrmItem )
453 xTargetFrame = pFrmItem->GetFrame();
455 SdOptions* pOpt = GetSdOptions(DocumentType::Impress);
456 bool bStartWithTemplate = pOpt->IsStartWithTemplate();
458 bool bNewDocDirect = rReq.GetSlot() == SID_NEWSD;
460 if( bNewDocDirect )
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);
472 else
474 //create an empty document
475 pFrame = CreateEmptyDocument( xTargetFrame );
479 if (bStartWithTemplate)
481 //Launch TemplateSelectionDialog
482 SfxTemplateSelectionDlg aTemplDlg(SfxGetpApp()->GetTopWindow());
483 aTemplDlg.run();
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
493 // was open
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 });
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();
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;
530 return pFrame;
533 //===== OutlineToImpressFinalize ==============================================
535 namespace {
537 OutlineToImpressFinalizer::OutlineToImpressFinalizer (
538 ::sd::ViewShellBase& rBase,
539 SdDrawDocument& rDocument,
540 SvLockBytes const & rBytes)
541 : mrBase(rBase),
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)
549 return;
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);
558 bool bLoop (true);
559 while (bLoop)
561 // Read the next part of the original stream.
562 std::size_t nReadByteCount (0);
563 const ErrCode nErrorCode (
564 rBytes.ReadAt(
565 nReadPosition,
566 pBuffer.get(),
567 nBufferSize,
568 &nReadByteCount));
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)
575 bLoop = false;
577 else if (nErrorCode == ERRCODE_IO_PENDING)
579 else
581 bLoop = false;
582 nReadByteCount = 0;
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();
632 if( pDocShell )
633 pDocShell->ClearUndoBuffer();
636 } // end of anonymous namespace
638 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */