Version 7.1.7.1, tag libreoffice-7.1.7.1
[LibreOffice.git] / sfx2 / source / view / viewsh.cxx
blobd35253d1342a2ac3e53c8c497b511b2366a5794f
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
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 <config_features.h>
22 #include <sal/log.hxx>
23 #include <svl/stritem.hxx>
24 #include <svl/eitem.hxx>
25 #include <svl/whiter.hxx>
26 #include <vcl/toolbox.hxx>
27 #include <vcl/svapp.hxx>
28 #include <vcl/weld.hxx>
29 #include <svl/intitem.hxx>
30 #include <svtools/langhelp.hxx>
31 #include <com/sun/star/frame/XLayoutManager.hpp>
32 #include <com/sun/star/frame/ModuleManager.hpp>
33 #include <com/sun/star/io/IOException.hpp>
34 #include <com/sun/star/beans/XPropertySet.hpp>
35 #include <com/sun/star/embed/EmbedStates.hpp>
36 #include <com/sun/star/embed/EmbedMisc.hpp>
37 #include <com/sun/star/embed/XEmbeddedObject.hpp>
38 #include <com/sun/star/container/XContainerQuery.hpp>
39 #include <com/sun/star/frame/XStorable.hpp>
40 #include <com/sun/star/frame/XModel.hpp>
41 #include <com/sun/star/datatransfer/clipboard/XClipboard.hpp>
42 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
43 #include <com/sun/star/datatransfer/clipboard/XClipboardListener.hpp>
44 #include <com/sun/star/datatransfer/clipboard/XClipboardNotifier.hpp>
45 #include <com/sun/star/view/XRenderable.hpp>
46 #include <com/sun/star/uno/Reference.hxx>
47 #include <cppuhelper/implbase.hxx>
49 #include <tools/diagnose_ex.h>
50 #include <tools/urlobj.hxx>
51 #include <unotools/tempfile.hxx>
52 #include <svtools/soerr.hxx>
53 #include <tools/svborder.hxx>
55 #include <framework/actiontriggerhelper.hxx>
56 #include <comphelper/lok.hxx>
57 #include <comphelper/namedvaluecollection.hxx>
58 #include <comphelper/processfactory.hxx>
59 #include <comphelper/sequenceashashmap.hxx>
60 #include <toolkit/helper/vclunohelper.hxx>
61 #include <vcl/settings.hxx>
62 #include <vcl/commandinfoprovider.hxx>
63 #include <LibreOfficeKit/LibreOfficeKitEnums.h>
65 #include <officecfg/Office/Common.hxx>
66 #include <officecfg/Setup.hxx>
67 #include <sfx2/app.hxx>
68 #include <sfx2/flatpak.hxx>
69 #include <sfx2/viewsh.hxx>
70 #include "viewimp.hxx"
71 #include <sfx2/sfxresid.hxx>
72 #include <sfx2/request.hxx>
73 #include <sfx2/printer.hxx>
74 #include <sfx2/docfile.hxx>
75 #include <sfx2/dispatch.hxx>
76 #include <sfx2/strings.hrc>
77 #include <sfx2/sfxbasecontroller.hxx>
78 #include <sfx2/mailmodelapi.hxx>
79 #include <bluthsndapi.hxx>
80 #include <sfx2/viewfrm.hxx>
81 #include <sfx2/event.hxx>
82 #include <sfx2/ipclient.hxx>
83 #include <sfx2/sfxsids.hrc>
84 #include <sfx2/objface.hxx>
85 #include <sfx2/lokhelper.hxx>
86 #include <openuriexternally.hxx>
87 #include <shellimpl.hxx>
89 #include <vector>
90 #include <libxml/xmlwriter.h>
92 using namespace ::com::sun::star;
93 using namespace ::com::sun::star::uno;
94 using namespace ::com::sun::star::frame;
95 using namespace ::com::sun::star::beans;
96 using namespace ::com::sun::star::util;
97 using namespace ::cppu;
99 #define ShellClass_SfxViewShell
100 #include <sfxslots.hxx>
103 class SfxClipboardChangeListener : public ::cppu::WeakImplHelper<
104 datatransfer::clipboard::XClipboardListener >
106 public:
107 SfxClipboardChangeListener( SfxViewShell* pView, const uno::Reference< datatransfer::clipboard::XClipboardNotifier >& xClpbrdNtfr );
109 // XEventListener
110 virtual void SAL_CALL disposing( const lang::EventObject& rEventObject ) override;
112 // XClipboardListener
113 virtual void SAL_CALL changedContents( const datatransfer::clipboard::ClipboardEvent& rEventObject ) override;
115 void DisconnectViewShell() { m_pViewShell = nullptr; }
116 void ChangedContents();
118 enum AsyncExecuteCmd
120 ASYNCEXECUTE_CMD_DISPOSING,
121 ASYNCEXECUTE_CMD_CHANGEDCONTENTS
124 struct AsyncExecuteInfo
126 AsyncExecuteInfo( AsyncExecuteCmd eCmd, SfxClipboardChangeListener* pListener ) :
127 m_eCmd( eCmd ), m_xListener( pListener ) {}
129 AsyncExecuteCmd m_eCmd;
130 rtl::Reference<SfxClipboardChangeListener> m_xListener;
133 private:
134 SfxViewShell* m_pViewShell;
135 uno::Reference< datatransfer::clipboard::XClipboardNotifier > m_xClpbrdNtfr;
136 uno::Reference< lang::XComponent > m_xCtrl;
138 DECL_STATIC_LINK( SfxClipboardChangeListener, AsyncExecuteHdl_Impl, void*, void );
141 SfxClipboardChangeListener::SfxClipboardChangeListener( SfxViewShell* pView, const uno::Reference< datatransfer::clipboard::XClipboardNotifier >& xClpbrdNtfr )
142 : m_pViewShell( nullptr ), m_xClpbrdNtfr( xClpbrdNtfr ), m_xCtrl(pView->GetController())
144 if ( m_xCtrl.is() )
146 m_xCtrl->addEventListener( uno::Reference < lang::XEventListener > ( static_cast < lang::XEventListener* >( this ) ) );
147 m_pViewShell = pView;
149 if ( m_xClpbrdNtfr.is() )
151 m_xClpbrdNtfr->addClipboardListener( uno::Reference< datatransfer::clipboard::XClipboardListener >(
152 static_cast< datatransfer::clipboard::XClipboardListener* >( this )));
156 void SfxClipboardChangeListener::ChangedContents()
158 const SolarMutexGuard aGuard;
159 if (!m_pViewShell)
160 return;
162 SfxBindings& rBind = m_pViewShell->GetViewFrame()->GetBindings();
163 rBind.Invalidate(SID_PASTE);
164 rBind.Invalidate(SID_PASTE_SPECIAL);
165 rBind.Invalidate(SID_CLIPBOARD_FORMAT_ITEMS);
167 if (comphelper::LibreOfficeKit::isActive())
169 // In the future we might send the payload as well.
170 SfxLokHelper::notifyAllViews(LOK_CALLBACK_CLIPBOARD_CHANGED, "");
174 IMPL_STATIC_LINK( SfxClipboardChangeListener, AsyncExecuteHdl_Impl, void*, p, void )
176 AsyncExecuteInfo* pAsyncExecuteInfo = static_cast<AsyncExecuteInfo*>(p);
177 if ( pAsyncExecuteInfo )
179 if ( pAsyncExecuteInfo->m_xListener.is() )
181 if ( pAsyncExecuteInfo->m_eCmd == ASYNCEXECUTE_CMD_DISPOSING )
182 pAsyncExecuteInfo->m_xListener->DisconnectViewShell();
183 else if ( pAsyncExecuteInfo->m_eCmd == ASYNCEXECUTE_CMD_CHANGEDCONTENTS )
184 pAsyncExecuteInfo->m_xListener->ChangedContents();
187 delete pAsyncExecuteInfo;
190 void SAL_CALL SfxClipboardChangeListener::disposing( const lang::EventObject& /*rEventObject*/ )
192 // Either clipboard or ViewShell is going to be destroyed -> no interest in listening anymore
193 uno::Reference< lang::XComponent > xCtrl( m_xCtrl );
194 uno::Reference< datatransfer::clipboard::XClipboardNotifier > xNotify( m_xClpbrdNtfr );
196 uno::Reference< datatransfer::clipboard::XClipboardListener > xThis( static_cast< datatransfer::clipboard::XClipboardListener* >( this ));
197 if ( xCtrl.is() )
198 xCtrl->removeEventListener( uno::Reference < lang::XEventListener > ( static_cast < lang::XEventListener* >( this )));
199 if ( xNotify.is() )
200 xNotify->removeClipboardListener( xThis );
202 // Make asynchronous call to avoid locking SolarMutex which is the
203 // root for many deadlocks, especially in conjunction with the "Windows"
204 // based single thread apartment clipboard code!
205 AsyncExecuteInfo* pInfo = new AsyncExecuteInfo( ASYNCEXECUTE_CMD_DISPOSING, this );
206 Application::PostUserEvent( LINK( nullptr, SfxClipboardChangeListener, AsyncExecuteHdl_Impl ), pInfo );
209 void SAL_CALL SfxClipboardChangeListener::changedContents( const datatransfer::clipboard::ClipboardEvent& )
211 // Make asynchronous call to avoid locking SolarMutex which is the
212 // root for many deadlocks, especially in conjunction with the "Windows"
213 // based single thread apartment clipboard code!
214 AsyncExecuteInfo* pInfo = new AsyncExecuteInfo( ASYNCEXECUTE_CMD_CHANGEDCONTENTS, this );
215 Application::PostUserEvent( LINK( nullptr, SfxClipboardChangeListener, AsyncExecuteHdl_Impl ), pInfo );
218 sal_uInt32 SfxViewShell_Impl::m_nLastViewShellId = 0;
220 SfxViewShell_Impl::SfxViewShell_Impl(SfxViewShellFlags const nFlags, ViewShellDocId nDocId)
221 : aInterceptorContainer( aMutex )
222 , m_bHasPrintOptions(nFlags & SfxViewShellFlags::HAS_PRINTOPTIONS)
223 , m_nFamily(0xFFFF) // undefined, default set by TemplateDialog
224 , m_pLibreOfficeKitViewCallback(nullptr)
225 , m_pLibreOfficeKitViewData(nullptr)
226 , m_bTiledSearching(false)
227 , m_nViewShellId(SfxViewShell_Impl::m_nLastViewShellId++)
228 , m_nDocId(nDocId)
232 SfxViewShell_Impl::~SfxViewShell_Impl()
236 std::vector< SfxInPlaceClient* > *SfxViewShell_Impl::GetIPClients_Impl( bool bCreate ) const
238 if (!mpIPClients && bCreate)
239 mpIPClients.reset(new std::vector< SfxInPlaceClient* >);
240 return mpIPClients.get();
243 SFX_IMPL_SUPERCLASS_INTERFACE(SfxViewShell,SfxShell)
245 void SfxViewShell::InitInterface_Impl()
250 /** search for a filter name dependent on type and module
252 static OUString impl_retrieveFilterNameFromTypeAndModule(
253 const css::uno::Reference< css::container::XContainerQuery >& rContainerQuery,
254 const OUString& rType,
255 const OUString& rModuleIdentifier,
256 const sal_Int32 nFlags )
258 // Retrieve filter from type
259 css::uno::Sequence< css::beans::NamedValue > aQuery {
260 { "Type", css::uno::makeAny( rType ) },
261 { "DocumentService", css::uno::makeAny( rModuleIdentifier ) }
264 css::uno::Reference< css::container::XEnumeration > xEnumeration =
265 rContainerQuery->createSubSetEnumerationByProperties( aQuery );
267 OUString aFoundFilterName;
268 while ( xEnumeration->hasMoreElements() )
270 ::comphelper::SequenceAsHashMap aFilterPropsHM( xEnumeration->nextElement() );
271 OUString aFilterName = aFilterPropsHM.getUnpackedValueOrDefault(
272 "Name",
273 OUString() );
275 sal_Int32 nFilterFlags = aFilterPropsHM.getUnpackedValueOrDefault(
276 "Flags",
277 sal_Int32( 0 ) );
279 if ( nFilterFlags & nFlags )
281 aFoundFilterName = aFilterName;
282 break;
286 return aFoundFilterName;
289 namespace {
291 /** search for an internal typename, which map to the current app module
292 and map also to a "family" of file formats as e.g. PDF/MS Doc/OOo Doc.
294 enum ETypeFamily
296 E_MS_DOC,
297 E_OOO_DOC
302 static OUString impl_searchFormatTypeForApp(const css::uno::Reference< css::frame::XFrame >& xFrame ,
303 ETypeFamily eTypeFamily)
307 css::uno::Reference< css::uno::XComponentContext > xContext (::comphelper::getProcessComponentContext());
308 css::uno::Reference< css::frame::XModuleManager2 > xModuleManager(css::frame::ModuleManager::create(xContext));
310 OUString sModule = xModuleManager->identify(xFrame);
311 OUString sType ;
313 switch(eTypeFamily)
315 case E_MS_DOC:
317 if ( sModule == "com.sun.star.text.TextDocument" )
318 sType = "writer_MS_Word_2007";
319 else
320 if ( sModule == "com.sun.star.sheet.SpreadsheetDocument" )
321 sType = "MS Excel 2007 XML";
322 else
323 if ( sModule == "com.sun.star.presentation.PresentationDocument" )
324 sType = "MS PowerPoint 2007 XML";
326 break;
328 case E_OOO_DOC:
330 if ( sModule == "com.sun.star.text.TextDocument" )
331 sType = "writer8";
332 else
333 if ( sModule == "com.sun.star.sheet.SpreadsheetDocument" )
334 sType = "calc8";
335 else
336 if ( sModule == "com.sun.star.drawing.DrawingDocument" )
337 sType = "draw8";
338 else
339 if ( sModule == "com.sun.star.presentation.PresentationDocument" )
340 sType = "impress8";
342 break;
345 return sType;
347 catch (const css::uno::RuntimeException&)
349 throw;
351 catch (const css::uno::Exception&)
355 return OUString();
358 void SfxViewShell::NewIPClient_Impl( SfxInPlaceClient *pIPClient )
360 pImpl->GetIPClients_Impl()->push_back(pIPClient);
363 void SfxViewShell::IPClientGone_Impl( SfxInPlaceClient const *pIPClient )
365 std::vector< SfxInPlaceClient* > *pClients = pImpl->GetIPClients_Impl();
367 auto it = std::find(pClients->begin(), pClients->end(), pIPClient);
368 if (it != pClients->end())
369 pClients->erase( it );
373 void SfxViewShell::ExecMisc_Impl( SfxRequest &rReq )
375 const sal_uInt16 nId = rReq.GetSlot();
376 switch( nId )
378 case SID_STYLE_FAMILY :
380 const SfxUInt16Item* pItem = rReq.GetArg<SfxUInt16Item>(nId);
381 if (pItem)
383 pImpl->m_nFamily = pItem->GetValue();
385 break;
387 case SID_ACTIVATE_STYLE_APPLY:
389 uno::Reference< frame::XFrame > xFrame =
390 GetViewFrame()->GetFrame().GetFrameInterface();
392 Reference< beans::XPropertySet > xPropSet( xFrame, UNO_QUERY );
393 Reference< frame::XLayoutManager > xLayoutManager;
394 if ( xPropSet.is() )
398 Any aValue = xPropSet->getPropertyValue("LayoutManager");
399 aValue >>= xLayoutManager;
400 if ( xLayoutManager.is() )
402 uno::Reference< ui::XUIElement > xElement = xLayoutManager->getElement( "private:resource/toolbar/textobjectbar" );
403 if(!xElement.is())
405 xElement = xLayoutManager->getElement( "private:resource/toolbar/frameobjectbar" );
407 if(!xElement.is())
409 xElement = xLayoutManager->getElement( "private:resource/toolbar/oleobjectbar" );
411 if(xElement.is())
413 uno::Reference< awt::XWindow > xWin( xElement->getRealInterface(), uno::UNO_QUERY_THROW );
414 VclPtr<vcl::Window> pWin = VCLUnoHelper::GetWindow( xWin );
415 ToolBox* pTextToolbox = dynamic_cast< ToolBox* >( pWin.get() );
416 if( pTextToolbox )
418 ToolBox::ImplToolItems::size_type nItemCount = pTextToolbox->GetItemCount();
419 for( ToolBox::ImplToolItems::size_type nItem = 0; nItem < nItemCount; ++nItem )
421 sal_uInt16 nItemId = pTextToolbox->GetItemId( nItem );
422 const OUString& rCommand = pTextToolbox->GetItemCommand( nItemId );
423 if (rCommand == ".uno:StyleApply")
425 vcl::Window* pItemWin = pTextToolbox->GetItemWindow( nItemId );
426 if( pItemWin )
427 pItemWin->GrabFocus();
428 break;
435 catch (const Exception&)
439 rReq.Done();
441 break;
443 case SID_MAIL_SENDDOCASMS:
444 case SID_MAIL_SENDDOCASOOO:
445 case SID_MAIL_SENDDOCASPDF:
446 case SID_MAIL_SENDDOC:
447 case SID_MAIL_SENDDOCASFORMAT:
449 SfxObjectShell* pDoc = GetObjectShell();
450 if ( pDoc && pDoc->QueryHiddenInformation(
451 HiddenWarningFact::WhenSaving, GetViewFrame()->GetWindow().GetFrameWeld() ) != RET_YES )
452 break;
455 SfxMailModel aModel;
456 OUString aDocType;
458 const SfxStringItem* pMailRecipient = rReq.GetArg<SfxStringItem>(SID_MAIL_RECIPIENT);
459 if ( pMailRecipient )
461 OUString aRecipient( pMailRecipient->GetValue() );
462 OUString aMailToStr("mailto:");
464 if ( aRecipient.startsWith( aMailToStr ) )
465 aRecipient = aRecipient.copy( aMailToStr.getLength() );
466 aModel.AddToAddress( aRecipient );
468 const SfxStringItem* pMailDocType = rReq.GetArg<SfxStringItem>(SID_TYPE_NAME);
469 if ( pMailDocType )
470 aDocType = pMailDocType->GetValue();
472 uno::Reference < frame::XFrame > xFrame( pFrame->GetFrame().GetFrameInterface() );
473 SfxMailModel::SendMailResult eResult = SfxMailModel::SEND_MAIL_ERROR;
475 if ( nId == SID_MAIL_SENDDOC )
476 eResult = aModel.SaveAndSend( xFrame, OUString() );
477 else if ( nId == SID_MAIL_SENDDOCASPDF )
478 eResult = aModel.SaveAndSend( xFrame, "pdf_Portable_Document_Format");
479 else if ( nId == SID_MAIL_SENDDOCASMS )
481 aDocType = impl_searchFormatTypeForApp(xFrame, E_MS_DOC);
482 if (!aDocType.isEmpty())
483 eResult = aModel.SaveAndSend( xFrame, aDocType );
485 else if ( nId == SID_MAIL_SENDDOCASOOO )
487 aDocType = impl_searchFormatTypeForApp(xFrame, E_OOO_DOC);
488 if (!aDocType.isEmpty())
489 eResult = aModel.SaveAndSend( xFrame, aDocType );
492 if ( eResult == SfxMailModel::SEND_MAIL_ERROR )
494 vcl::Window* pWin = SfxGetpApp()->GetTopWindow();
495 std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(pWin ? pWin->GetFrameWeld() : nullptr,
496 VclMessageType::Info, VclButtonsType::Ok,
497 SfxResId(STR_ERROR_SEND_MAIL)));
498 xBox->run();
499 rReq.Ignore();
501 else
502 rReq.Done();
504 break;
506 case SID_BLUETOOTH_SENDDOC:
508 SfxBluetoothModel aModel;
509 SfxObjectShell* pDoc = GetObjectShell();
510 if ( pDoc && pDoc->QueryHiddenInformation(
511 HiddenWarningFact::WhenSaving, GetViewFrame()->GetWindow().GetFrameWeld() ) != RET_YES )
512 break;
513 uno::Reference < frame::XFrame > xFrame( pFrame->GetFrame().GetFrameInterface() );
514 SfxMailModel::SendMailResult eResult = aModel.SaveAndSend( xFrame );
515 if( eResult == SfxMailModel::SEND_MAIL_ERROR )
517 vcl::Window* pWin = SfxGetpApp()->GetTopWindow();
518 std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(pWin ? pWin->GetFrameWeld() : nullptr,
519 VclMessageType::Info, VclButtonsType::Ok,
520 SfxResId(STR_ERROR_SEND_MAIL)));
521 xBox->run();
522 rReq.Ignore();
524 else
525 rReq.Done();
527 break;
529 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
530 case SID_WEBHTML:
532 css::uno::Reference< lang::XMultiServiceFactory > xSMGR(::comphelper::getProcessServiceFactory(), css::uno::UNO_SET_THROW);
533 css::uno::Reference< uno::XComponentContext > xContext(::comphelper::getProcessComponentContext(), css::uno::UNO_SET_THROW);
534 css::uno::Reference< css::frame::XFrame > xFrame( pFrame->GetFrame().GetFrameInterface() );
535 css::uno::Reference< css::frame::XModel > xModel;
537 css::uno::Reference< css::frame::XModuleManager2 > xModuleManager( css::frame::ModuleManager::create(xContext) );
539 OUString aModule;
542 aModule = xModuleManager->identify( xFrame );
544 catch (const css::uno::RuntimeException&)
546 throw;
548 catch (const css::uno::Exception&)
552 if ( xFrame.is() )
554 css::uno::Reference< css::frame::XController > xController = xFrame->getController();
555 if ( xController.is() )
556 xModel = xController->getModel();
559 // We need at least a valid module name and model reference
560 css::uno::Reference< css::frame::XStorable > xStorable( xModel, css::uno::UNO_QUERY );
561 if ( xModel.is() && xStorable.is() )
563 OUString aFilterName;
564 OUString aTypeName( "generic_HTML" );
565 OUString aFileName;
567 OUString aLocation = xStorable->getLocation();
568 INetURLObject aFileObj( aLocation );
570 bool bPrivateProtocol = ( aFileObj.GetProtocol() == INetProtocol::PrivSoffice );
571 bool bHasLocation = !aLocation.isEmpty() && !bPrivateProtocol;
573 css::uno::Reference< css::container::XContainerQuery > xContainerQuery(
574 xSMGR->createInstance( "com.sun.star.document.FilterFactory" ),
575 css::uno::UNO_QUERY_THROW );
577 // Retrieve filter from type
579 sal_Int32 nFilterFlags = 0x00000002; // export
580 aFilterName = impl_retrieveFilterNameFromTypeAndModule( xContainerQuery, aTypeName, aModule, nFilterFlags );
581 if ( aFilterName.isEmpty() )
583 // Draw/Impress uses a different type. 2nd chance try to use alternative type name
584 aFilterName = impl_retrieveFilterNameFromTypeAndModule(
585 xContainerQuery, "graphic_HTML", aModule, nFilterFlags );
588 // No filter found => error
589 // No type and no location => error
590 if ( aFilterName.isEmpty() || aTypeName.isEmpty())
592 rReq.Done();
593 return;
596 // Use provided save file name. If empty determine file name
597 if ( !bHasLocation )
599 // Create a default file name with the correct extension
600 aFileName = "webpreview";
602 else
604 // Determine file name from model
605 INetURLObject aFObj( xStorable->getLocation() );
606 aFileName = aFObj.getName( INetURLObject::LAST_SEGMENT, true, INetURLObject::DecodeMechanism::NONE );
609 OSL_ASSERT( !aFilterName.isEmpty() );
610 OSL_ASSERT( !aFileName.isEmpty() );
612 // Creates a temporary directory to store our predefined file into it (for the
613 // flatpak case, create it in XDG_CACHE_HOME instead of /tmp for technical reasons,
614 // so that it can be accessed by the browser running outside the sandbox):
615 OUString * parent = nullptr;
616 if (flatpak::isFlatpak() && !flatpak::createTemporaryHtmlDirectory(&parent))
618 SAL_WARN("sfx.view", "cannot create Flatpak html temp dir");
620 ::utl::TempFile aTempDir( parent, true );
622 INetURLObject aFilePathObj( aTempDir.GetURL() );
623 aFilePathObj.insertName( aFileName );
624 aFilePathObj.setExtension( "htm" );
626 OUString aFileURL = aFilePathObj.GetMainURL( INetURLObject::DecodeMechanism::NONE );
628 css::uno::Sequence< css::beans::PropertyValue > aArgs( 1 );
629 aArgs[0].Name = "FilterName";
630 aArgs[0].Value <<= aFilterName;
632 // Store document in the html format
635 xStorable->storeToURL( aFileURL, aArgs );
637 catch (const io::IOException&)
639 rReq.Done();
640 return;
643 sfx2::openUriExternally(aFileURL, true);
644 rReq.Done(true);
645 break;
647 else
649 rReq.Done();
650 return;
657 void SfxViewShell::GetState_Impl( SfxItemSet &rSet )
660 SfxWhichIter aIter( rSet );
661 SfxObjectShell *pSh = GetViewFrame()->GetObjectShell();
662 for ( sal_uInt16 nSID = aIter.FirstWhich(); nSID; nSID = aIter.NextWhich() )
664 switch ( nSID )
667 case SID_BLUETOOTH_SENDDOC:
668 case SID_MAIL_SENDDOC:
669 case SID_MAIL_SENDDOCASFORMAT:
670 case SID_MAIL_SENDDOCASMS:
671 case SID_MAIL_SENDDOCASOOO:
672 case SID_MAIL_SENDDOCASPDF:
674 #if HAVE_FEATURE_MACOSX_SANDBOX
675 rSet.DisableItem(nSID);
676 #endif
677 if (pSh && pSh->isExportLocked() && nSID != SID_MAIL_SENDDOC)
678 rSet.DisableItem(nSID);
679 break;
681 case SID_WEBHTML:
683 if (pSh && pSh->isExportLocked())
684 rSet.DisableItem(nSID);
685 break;
687 // Printer functions
688 case SID_PRINTDOC:
689 case SID_PRINTDOCDIRECT:
690 case SID_SETUPPRINTER:
691 case SID_PRINTER_NAME:
693 if (Application::GetSettings().GetMiscSettings().GetDisablePrinting()
694 || (pSh && pSh->isPrintLocked()))
696 rSet.DisableItem(nSID);
697 break;
700 SfxPrinter *pPrinter = GetPrinter();
702 if ( SID_PRINTDOCDIRECT == nSID )
704 OUString aPrinterName;
705 if ( pPrinter != nullptr )
706 aPrinterName = pPrinter->GetName();
707 else
708 aPrinterName = Printer::GetDefaultPrinterName();
709 if ( !aPrinterName.isEmpty() )
711 uno::Reference < frame::XFrame > xFrame( pFrame->GetFrame().GetFrameInterface() );
713 OUStringBuffer aBuffer( 60 );
714 auto aProperties = vcl::CommandInfoProvider::GetCommandProperties(".uno:PrintDefault",
715 vcl::CommandInfoProvider::GetModuleIdentifier(xFrame));
716 aBuffer.append(vcl::CommandInfoProvider::GetLabelForCommand(aProperties));
717 aBuffer.append( " (" );
718 aBuffer.append( aPrinterName );
719 aBuffer.append(')');
721 rSet.Put( SfxStringItem( SID_PRINTDOCDIRECT, aBuffer.makeStringAndClear() ) );
724 break;
726 case SID_STYLE_FAMILY :
728 rSet.Put( SfxUInt16Item( SID_STYLE_FAMILY, pImpl->m_nFamily ) );
729 break;
736 void SfxViewShell::SetZoomFactor( const Fraction &rZoomX,
737 const Fraction &rZoomY )
739 DBG_ASSERT( GetWindow(), "no window" );
740 MapMode aMap( GetWindow()->GetMapMode() );
741 aMap.SetScaleX( rZoomX );
742 aMap.SetScaleY( rZoomY );
743 GetWindow()->SetMapMode( aMap );
747 ErrCode SfxViewShell::DoVerb(tools::Long /*nVerb*/)
749 /* [Description]
751 Virtual Method used to perform a Verb on a selected Object.
752 Since this Object is only known by the derived classes, they must override
753 DoVerb.
757 return ERRCODE_SO_NOVERBS;
761 void SfxViewShell::OutplaceActivated( bool bActive )
763 if ( !bActive )
764 GetFrame()->GetFrame().Appear();
768 void SfxViewShell::UIActivating( SfxInPlaceClient* /*pClient*/ )
770 uno::Reference < frame::XFrame > xOwnFrame( pFrame->GetFrame().GetFrameInterface() );
771 uno::Reference < frame::XFramesSupplier > xParentFrame = xOwnFrame->getCreator();
772 if ( xParentFrame.is() )
773 xParentFrame->setActiveFrame( xOwnFrame );
775 pFrame->GetBindings().HidePopups();
776 pFrame->GetDispatcher()->Update_Impl( true );
780 void SfxViewShell::UIDeactivated( SfxInPlaceClient* /*pClient*/ )
782 if ( !pFrame->GetFrame().IsClosing_Impl() || SfxViewFrame::Current() != pFrame )
783 pFrame->GetDispatcher()->Update_Impl( true );
784 pFrame->GetBindings().HidePopups(false);
786 pFrame->GetBindings().InvalidateAll(true);
790 SfxInPlaceClient* SfxViewShell::FindIPClient
792 const uno::Reference < embed::XEmbeddedObject >& xObj,
793 vcl::Window* pObjParentWin
794 ) const
796 std::vector< SfxInPlaceClient* > *pClients = pImpl->GetIPClients_Impl(false);
797 if ( !pClients )
798 return nullptr;
800 if( !pObjParentWin )
801 pObjParentWin = GetWindow();
802 for (SfxInPlaceClient* pIPClient : *pClients)
804 if ( pIPClient->GetObject() == xObj && pIPClient->GetEditWin() == pObjParentWin )
805 return pIPClient;
808 return nullptr;
812 SfxInPlaceClient* SfxViewShell::GetIPClient() const
814 return GetUIActiveClient();
818 SfxInPlaceClient* SfxViewShell::GetUIActiveIPClient_Impl() const
820 // this method is needed as long as SFX still manages the border space for ChildWindows (see SfxFrame::Resize)
821 std::vector< SfxInPlaceClient* > *pClients = pImpl->GetIPClients_Impl(false);
822 if ( !pClients )
823 return nullptr;
825 for (SfxInPlaceClient* pIPClient : *pClients)
827 if ( pIPClient->IsUIActive() )
828 return pIPClient;
831 return nullptr;
834 SfxInPlaceClient* SfxViewShell::GetUIActiveClient() const
836 std::vector< SfxInPlaceClient* > *pClients = pImpl->GetIPClients_Impl(false);
837 if ( !pClients )
838 return nullptr;
840 const bool bIsTiledRendering = comphelper::LibreOfficeKit::isActive();
842 for (SfxInPlaceClient* pIPClient : *pClients)
844 if ( pIPClient->IsObjectUIActive() || ( bIsTiledRendering && pIPClient->IsObjectInPlaceActive() ) )
845 return pIPClient;
848 return nullptr;
852 void SfxViewShell::Activate( bool bMDI )
854 if ( bMDI )
856 SfxObjectShell *pSh = GetViewFrame()->GetObjectShell();
857 if ( pSh->GetModel().is() )
858 pSh->GetModel()->setCurrentController( GetViewFrame()->GetFrame().GetController() );
860 SetCurrentDocument();
865 void SfxViewShell::Deactivate(bool /*bMDI*/)
870 void SfxViewShell::Move()
872 /* [Description]
874 This virtual Method is called when the window displayed in the
875 SfxViewShell gets a StarView-Move() notification.
877 This base implementation does not have to be called. .
879 [Note]
881 This Method can be used to cancel a selection, in order to catch the
882 mouse movement which is due to moving a window.
884 For now the notification does not work In-Place.
891 void SfxViewShell::OuterResizePixel
893 const Point& /*rToolOffset*/,// Upper left corner Tools in Frame-Window
894 const Size& /*rSize*/ // All available sizes.
897 /* [Description]
899 Override this Method to be able to react to the size-change of
900 the View. Thus the View is defined as the Edit window and also the
901 attached Tools are defined (for example the ruler).
903 The Edit window must not be changed either in size or position.
905 The Vis-Area of SfxObjectShell, its scale and position can be changed
906 here. The main use is to change the size of the Vis-Area.
908 If the Border is changed due to the new calculation then this has to be set
909 by <SfxViewShell::SetBorderPixel(const SvBorder&)>. The Positioning of Tools
910 is only allowed after the calling of 'SetBorderPixel'.
912 [Example]
914 void AppViewSh::OuterViewResizePixel( const Point &rOfs, const Size &rSz )
916 // Calculate Tool position and size externally, do not set!
917 // (due to the following Border calculation)
918 Point aHLinPos...; Size aHLinSz...;
921 // Calculate and Set a Border of Tools which matches rSize.
922 SvBorder aBorder...
923 SetBorderPixel( aBorder ); // Allow Positioning from here on.
925 // Arrange Tools
926 pHLin->SetPosSizePixel( aHLinPos, aHLinSz );
930 [Cross-reference]
932 <SfxViewShell::InnerResizePixel(const Point&,const Size& rSize)>
936 SetBorderPixel( SvBorder() );
940 void SfxViewShell::InnerResizePixel
942 const Point& /*rToolOffset*/,// Upper left corner Tools in Frame-Window
943 const Size& /*rSize*/, // All available sizes.
944 bool
947 /* [Description]
949 Override this Method to be able to react to the size-change of
950 the Edit window.
952 The Edit window must not be changed either in size or position.
953 Neither the Vis-Area of SfxObjectShell nor its scale or position are
954 allowed to be changed
956 If the Border is changed due to the new calculation then is has to be set
957 by <SfxViewShell::SetBorderPixel(const SvBorder&)>.
958 The Positioning of Tools is only allowed after the calling of
959 'SetBorderPixel'.
962 [Note]
964 void AppViewSh::InnerViewResizePixel( const Point &rOfs, const Size &rSz )
966 // Calculate Tool position and size internally, do not set!
967 // (due to the following Border calculation)
968 Point aHLinPos...; Size aHLinSz...;
971 // Calculate and Set a Border of Tools which matches rSize.
972 SvBorder aBorder...
973 SetBorderPixel( aBorder ); // Allow Positioning from here on.
975 // Arrange Tools
976 pHLin->SetPosSizePixel( aHLinPos, aHLinSz );
980 [Cross-reference]
982 <SfxViewShell::OuterResizePixel(const Point&,const Size& rSize)>
986 SetBorderPixel( SvBorder() );
990 void SfxViewShell::InvalidateBorder()
992 DBG_ASSERT( GetViewFrame(), "SfxViewShell without SfxViewFrame" );
994 GetViewFrame()->InvalidateBorderImpl( this );
995 if (pImpl->m_pController.is())
997 pImpl->m_pController->BorderWidthsChanged_Impl();
1002 void SfxViewShell::SetBorderPixel( const SvBorder &rBorder )
1004 DBG_ASSERT( GetViewFrame(), "SfxViewShell without SfxViewFrame" );
1006 GetViewFrame()->SetBorderPixelImpl( this, rBorder );
1008 // notify related controller that border size is changed
1009 if (pImpl->m_pController.is())
1011 pImpl->m_pController->BorderWidthsChanged_Impl();
1016 const SvBorder& SfxViewShell::GetBorderPixel() const
1018 DBG_ASSERT( GetViewFrame(), "SfxViewShell without SfxViewFrame" );
1020 return GetViewFrame()->GetBorderPixelImpl();
1024 void SfxViewShell::SetWindow
1026 vcl::Window* pViewPort // For example Null pointer in the Destructor.
1029 /* [Description]
1031 With this method the SfxViewShell is set in the data window. This is
1032 needed for the in-place container and for restoring the proper focus.
1034 Even in-place-active the conversion of the ViewPort Windows is forbidden.
1038 if( pWindow == pViewPort )
1039 return;
1041 // Disconnect existing IP-Clients if possible
1042 DisconnectAllClients();
1044 // Switch View-Port
1045 bool bHadFocus = pWindow && pWindow->HasChildPathFocus( true );
1046 pWindow = pViewPort;
1048 if( pWindow )
1050 // Disable automatic GUI mirroring (right-to-left) for document windows
1051 pWindow->EnableRTL( false );
1054 if ( bHadFocus && pWindow )
1055 pWindow->GrabFocus();
1056 //TODO/CLEANUP
1057 //Do we still need this Method?!
1058 //SfxGetpApp()->GrabFocus( pWindow );
1061 ViewShellDocId SfxViewShell::mnCurrentDocId(0);
1063 SfxViewShell::SfxViewShell
1065 SfxViewFrame* pViewFrame, /* <SfxViewFrame>, which will be
1066 displayed in this View */
1067 SfxViewShellFlags nFlags /* See <SfxViewShell-Flags> */
1070 : SfxShell(this)
1071 , pImpl( new SfxViewShell_Impl(nFlags, SfxViewShell::mnCurrentDocId) )
1072 , pFrame(pViewFrame)
1073 , pWindow(nullptr)
1074 , bNoNewWindow( nFlags & SfxViewShellFlags::NO_NEWWINDOW )
1075 , mbPrinterSettingsModified(false)
1076 , maLOKLanguageTag(LANGUAGE_NONE)
1077 , maLOKLocale(LANGUAGE_NONE)
1078 , maLOKDeviceFormFactor(LOKDeviceFormFactor::UNKNOWN)
1080 SetMargin( pViewFrame->GetMargin_Impl() );
1082 SetPool( &pViewFrame->GetObjectShell()->GetPool() );
1083 StartListening(*pViewFrame->GetObjectShell());
1085 // Insert into list
1086 SfxViewShellArr_Impl &rViewArr = SfxGetpApp()->GetViewShells_Impl();
1087 rViewArr.push_back(this);
1089 if (comphelper::LibreOfficeKit::isActive())
1091 maLOKLanguageTag = SfxLokHelper::getDefaultLanguage();
1092 maLOKLocale = SfxLokHelper::getDefaultLanguage();
1094 maLOKDeviceFormFactor = SfxLokHelper::getDeviceFormFactor();
1096 vcl::Window* pFrameWin = pViewFrame->GetWindow().GetFrameWindow();
1097 if (pFrameWin && !pFrameWin->GetLOKNotifier())
1098 pFrameWin->SetLOKNotifier(this, true);
1103 SfxViewShell::~SfxViewShell()
1105 // Remove from list
1106 const SfxViewShell *pThis = this;
1107 SfxViewShellArr_Impl &rViewArr = SfxGetpApp()->GetViewShells_Impl();
1108 SfxViewShellArr_Impl::iterator it = std::find( rViewArr.begin(), rViewArr.end(), pThis );
1109 rViewArr.erase( it );
1111 if ( pImpl->xClipboardListener.is() )
1113 pImpl->xClipboardListener->DisconnectViewShell();
1114 pImpl->xClipboardListener = nullptr;
1117 if (pImpl->m_pController.is())
1119 pImpl->m_pController->ReleaseShell_Impl();
1120 pImpl->m_pController.clear();
1123 vcl::Window* pFrameWin = GetViewFrame()->GetWindow().GetFrameWindow();
1124 if (pFrameWin && pFrameWin->GetLOKNotifier() == this)
1125 pFrameWin->ReleaseLOKNotifier();
1128 bool SfxViewShell::PrepareClose
1130 bool bUI // TRUE: Allow Dialog and so on, FALSE: silent-mode
1133 if (GetViewFrame()->GetWindow().GetLOKNotifier() == this)
1134 GetViewFrame()->GetWindow().ReleaseLOKNotifier();
1136 SfxPrinter *pPrinter = GetPrinter();
1137 if ( pPrinter && pPrinter->IsPrinting() )
1139 if ( bUI )
1141 std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(GetViewFrame()->GetWindow().GetFrameWeld(),
1142 VclMessageType::Info, VclButtonsType::Ok,
1143 SfxResId(STR_CANT_CLOSE)));
1144 xBox->run();
1147 return false;
1150 if( GetViewFrame()->IsInModalMode() )
1151 return false;
1153 if( bUI && GetViewFrame()->GetDispatcher()->IsLocked() )
1154 return false;
1156 return true;
1160 SfxViewShell* SfxViewShell::Current()
1162 SfxViewFrame *pCurrent = SfxViewFrame::Current();
1163 return pCurrent ? pCurrent->GetViewShell() : nullptr;
1167 SfxViewShell* SfxViewShell::Get( const Reference< XController>& i_rController )
1169 if ( !i_rController.is() )
1170 return nullptr;
1172 for ( SfxViewShell* pViewShell = SfxViewShell::GetFirst( false );
1173 pViewShell;
1174 pViewShell = SfxViewShell::GetNext( *pViewShell, false )
1177 if ( pViewShell->GetController() == i_rController )
1178 return pViewShell;
1180 return nullptr;
1184 SdrView* SfxViewShell::GetDrawView() const
1186 /* [Description]
1188 This virtual Method has to be overloaded by the sub classes, to be able
1189 make the Property-Editor available.
1191 The default implementation does always return zero.
1195 return nullptr;
1199 OUString SfxViewShell::GetSelectionText
1201 bool /*bCompleteWords*/ /* FALSE (default)
1202 Only the actual selected text is returned.
1204 TRUE
1205 The selected text is expanded so that only
1206 whole words are returned. As word separators
1207 these are used: white spaces and punctuation
1208 ".,;" and single and double quotes.
1212 /* [Description]
1214 Override this Method to return a text that
1215 is included in the current selection. This is for example used when
1216 sending emails.
1218 When called with "CompleteWords == TRUE", it is for example sufficient
1219 with having the Cursor positioned somewhere within a URL in-order
1220 to have the entire URL returned.
1224 return OUString();
1228 bool SfxViewShell::HasSelection( bool ) const
1230 /* [Description]
1232 With this virtual Method can a for example a Dialog be queried, to
1233 check if something is selected in the current view. If the Parameter
1234 is <BOOL> TRUE then it is checked whether some text is selected.
1238 return false;
1241 void SfxViewShell::AddSubShell( SfxShell& rShell )
1243 pImpl->aArr.push_back(&rShell);
1244 SfxDispatcher *pDisp = pFrame->GetDispatcher();
1245 if ( pDisp->IsActive(*this) )
1247 pDisp->Push(rShell);
1248 pDisp->Flush();
1252 void SfxViewShell::RemoveSubShell( SfxShell* pShell )
1254 SfxDispatcher *pDisp = pFrame->GetDispatcher();
1255 if ( !pShell )
1257 size_t nCount = pImpl->aArr.size();
1258 if ( pDisp->IsActive(*this) )
1260 for(size_t n = nCount; n > 0; --n)
1261 pDisp->Pop(*pImpl->aArr[n - 1]);
1262 pDisp->Flush();
1264 pImpl->aArr.clear();
1266 else
1268 SfxShellArr_Impl::iterator i = std::find(pImpl->aArr.begin(), pImpl->aArr.end(), pShell);
1269 if(i != pImpl->aArr.end())
1271 pImpl->aArr.erase(i);
1272 if(pDisp->IsActive(*this))
1274 pDisp->RemoveShell_Impl(*pShell);
1275 pDisp->Flush();
1281 SfxShell* SfxViewShell::GetSubShell( sal_uInt16 nNo )
1283 sal_uInt16 nCount = pImpl->aArr.size();
1284 if(nNo < nCount)
1285 return pImpl->aArr[nCount - nNo - 1];
1286 return nullptr;
1289 void SfxViewShell::PushSubShells_Impl( bool bPush )
1291 SfxDispatcher *pDisp = pFrame->GetDispatcher();
1292 if ( bPush )
1294 for (auto const& elem : pImpl->aArr)
1295 pDisp->Push(*elem);
1297 else if(!pImpl->aArr.empty())
1299 SfxShell& rPopUntil = *pImpl->aArr[0];
1300 if ( pDisp->GetShellLevel( rPopUntil ) != USHRT_MAX )
1301 pDisp->Pop( rPopUntil, SfxDispatcherPopFlags::POP_UNTIL );
1304 pDisp->Flush();
1308 void SfxViewShell::WriteUserData( OUString&, bool )
1313 void SfxViewShell::ReadUserData(const OUString&, bool )
1317 void SfxViewShell::ReadUserDataSequence ( const uno::Sequence < beans::PropertyValue >& )
1321 void SfxViewShell::WriteUserDataSequence ( uno::Sequence < beans::PropertyValue >& )
1326 // returns the first shell of spec. type viewing the specified doc.
1327 SfxViewShell* SfxViewShell::GetFirst
1329 bool bOnlyVisible,
1330 const std::function< bool ( const SfxViewShell* ) >& isViewShell
1333 // search for a SfxViewShell of the specified type
1334 SfxViewShellArr_Impl &rShells = SfxGetpApp()->GetViewShells_Impl();
1335 SfxViewFrameArr_Impl &rFrames = SfxGetpApp()->GetViewFrames_Impl();
1336 for (SfxViewShell* pShell : rShells)
1338 if ( pShell )
1340 // sometimes dangling SfxViewShells exist that point to a dead SfxViewFrame
1341 // these ViewShells shouldn't be accessible anymore
1342 // a destroyed ViewFrame is not in the ViewFrame array anymore, so checking this array helps
1343 for (SfxViewFrame* pFrame : rFrames)
1345 if ( pFrame == pShell->GetViewFrame() )
1347 // only ViewShells with a valid ViewFrame will be returned
1348 if ( ( !bOnlyVisible || pFrame->IsVisible() ) && (!isViewShell || isViewShell(pShell)))
1349 return pShell;
1350 break;
1356 return nullptr;
1360 // returns the next shell of spec. type viewing the specified doc.
1362 SfxViewShell* SfxViewShell::GetNext
1364 const SfxViewShell& rPrev,
1365 bool bOnlyVisible,
1366 const std::function<bool ( const SfxViewShell* )>& isViewShell
1369 SfxViewShellArr_Impl &rShells = SfxGetpApp()->GetViewShells_Impl();
1370 SfxViewFrameArr_Impl &rFrames = SfxGetpApp()->GetViewFrames_Impl();
1371 size_t nPos;
1372 for ( nPos = 0; nPos < rShells.size(); ++nPos )
1373 if ( rShells[nPos] == &rPrev )
1374 break;
1376 for ( ++nPos; nPos < rShells.size(); ++nPos )
1378 SfxViewShell *pShell = rShells[nPos];
1379 if ( pShell )
1381 // sometimes dangling SfxViewShells exist that point to a dead SfxViewFrame
1382 // these ViewShells shouldn't be accessible anymore
1383 // a destroyed ViewFrame is not in the ViewFrame array anymore, so checking this array helps
1384 for (SfxViewFrame* pFrame : rFrames)
1386 if ( pFrame == pShell->GetViewFrame() )
1388 // only ViewShells with a valid ViewFrame will be returned
1389 if ( ( !bOnlyVisible || pFrame->IsVisible() ) && (!isViewShell || isViewShell(pShell)) )
1390 return pShell;
1391 break;
1397 return nullptr;
1401 void SfxViewShell::Notify( SfxBroadcaster& rBC,
1402 const SfxHint& rHint )
1404 const SfxEventHint* pEventHint = dynamic_cast<const SfxEventHint*>(&rHint);
1405 if ( !(pEventHint && pEventHint->GetEventId() == SfxEventHintId::LoadFinished) )
1406 return;
1408 if ( !GetController().is() )
1409 return;
1411 // avoid access to dangling ViewShells
1412 SfxViewFrameArr_Impl &rFrames = SfxGetpApp()->GetViewFrames_Impl();
1413 for (SfxViewFrame* frame : rFrames)
1415 if ( frame == GetViewFrame() && &rBC == GetObjectShell() )
1417 SfxItemSet* pSet = GetObjectShell()->GetMedium()->GetItemSet();
1418 const SfxUnoAnyItem* pItem = SfxItemSet::GetItem<SfxUnoAnyItem>(pSet, SID_VIEW_DATA, false);
1419 if ( pItem )
1421 pImpl->m_pController->restoreViewData( pItem->GetValue() );
1422 pSet->ClearItem( SID_VIEW_DATA );
1424 break;
1429 bool SfxViewShell::ExecKey_Impl(const KeyEvent& aKey)
1431 if (!pImpl->m_xAccExec)
1433 pImpl->m_xAccExec = ::svt::AcceleratorExecute::createAcceleratorHelper();
1434 pImpl->m_xAccExec->init(::comphelper::getProcessComponentContext(),
1435 pFrame->GetFrame().GetFrameInterface());
1438 return pImpl->m_xAccExec->execute(aKey.GetKeyCode());
1441 void SfxViewShell::registerLibreOfficeKitViewCallback(LibreOfficeKitCallback pCallback, void* pData)
1443 pImpl->m_pLibreOfficeKitViewCallback = pCallback;
1444 pImpl->m_pLibreOfficeKitViewData = pData;
1446 afterCallbackRegistered();
1448 if (!pCallback)
1449 return;
1451 // Ask other views to tell us about their cursors.
1452 SfxViewShell* pViewShell = SfxViewShell::GetFirst();
1453 while (pViewShell)
1455 if (pViewShell->GetDocId() == GetDocId())
1456 pViewShell->NotifyCursor(this);
1457 pViewShell = SfxViewShell::GetNext(*pViewShell);
1461 void SfxViewShell::libreOfficeKitViewCallback(int nType, const char* pPayload) const
1463 if (!comphelper::LibreOfficeKit::isActive())
1464 return;
1466 if (comphelper::LibreOfficeKit::isTiledPainting() && nType != LOK_CALLBACK_FORM_FIELD_BUTTON)
1467 return;
1469 if (pImpl->m_bTiledSearching)
1471 switch (nType)
1473 case LOK_CALLBACK_TEXT_SELECTION:
1474 case LOK_CALLBACK_TEXT_VIEW_SELECTION:
1475 case LOK_CALLBACK_TEXT_SELECTION_START:
1476 case LOK_CALLBACK_TEXT_SELECTION_END:
1477 case LOK_CALLBACK_GRAPHIC_SELECTION:
1478 case LOK_CALLBACK_GRAPHIC_VIEW_SELECTION:
1479 return;
1483 if (pImpl->m_pLibreOfficeKitViewCallback)
1484 pImpl->m_pLibreOfficeKitViewCallback(nType, pPayload, pImpl->m_pLibreOfficeKitViewData);
1485 else
1486 SAL_INFO(
1487 "sfx.view",
1488 "SfxViewShell::libreOfficeKitViewCallback no callback set! Dropped payload of type "
1489 << lokCallbackTypeToString(nType) << ": [" << pPayload << ']');
1492 void SfxViewShell::afterCallbackRegistered()
1496 vcl::Window* SfxViewShell::GetEditWindowForActiveOLEObj() const
1498 vcl::Window* pEditWin = nullptr;
1499 SfxInPlaceClient* pIPClient = GetIPClient();
1500 if (pIPClient)
1502 pEditWin = pIPClient->GetEditWin();
1504 return pEditWin;
1507 void SfxViewShell::SetLOKLanguageTag(const OUString& rBcp47LanguageTag)
1509 LanguageTag aTag(rBcp47LanguageTag, true);
1511 css::uno::Sequence<OUString> inst(officecfg::Setup::Office::InstalledLocales::get()->getElementNames());
1512 LanguageTag aFallbackTag = LanguageTag(getInstalledLocaleForSystemUILanguage(inst, /* bRequestInstallIfMissing */ false, rBcp47LanguageTag), true).makeFallback();
1514 // If we want de-CH, and the de localisation is available, we don't want to use de-DE as then
1515 // the magic in Translate::get() won't turn ess-zet into double s. Possibly other similar cases?
1516 if (comphelper::LibreOfficeKit::isActive() && aTag.getLanguage() == aFallbackTag.getLanguage())
1517 maLOKLanguageTag = aTag;
1518 else
1519 maLOKLanguageTag = aFallbackTag;
1522 void SfxViewShell::SetLOKLocale(const OUString& rBcp47LanguageTag)
1524 maLOKLocale = LanguageTag(rBcp47LanguageTag, true).makeFallback();
1527 void SfxViewShell::NotifyCursor(SfxViewShell* /*pViewShell*/) const
1531 void SfxViewShell::setTiledSearching(bool bTiledSearching)
1533 pImpl->m_bTiledSearching = bTiledSearching;
1536 int SfxViewShell::getPart() const
1538 return 0;
1541 ViewShellId SfxViewShell::GetViewShellId() const
1543 return pImpl->m_nViewShellId;
1546 void SfxViewShell::SetCurrentDocId(ViewShellDocId nId)
1548 mnCurrentDocId = nId;
1551 ViewShellDocId SfxViewShell::GetDocId() const
1553 assert(pImpl->m_nDocId >= ViewShellDocId(0) && "m_nDocId should have been initialized, but it is invalid.");
1554 return pImpl->m_nDocId;
1557 void SfxViewShell::NotifyOtherViews(int nType, const OString& rKey, const OString& rPayload)
1559 SfxLokHelper::notifyOtherViews(this, nType, rKey, rPayload);
1562 void SfxViewShell::NotifyOtherView(OutlinerViewShell* pOther, int nType, const OString& rKey, const OString& rPayload)
1564 auto pOtherShell = dynamic_cast<SfxViewShell*>(pOther);
1565 if (!pOtherShell)
1566 return;
1568 SfxLokHelper::notifyOtherView(this, pOtherShell, nType, rKey, rPayload);
1571 void SfxViewShell::dumpAsXml(xmlTextWriterPtr pWriter) const
1573 xmlTextWriterStartElement(pWriter, BAD_CAST("SfxViewShell"));
1574 xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("ptr"), "%p", this);
1575 xmlTextWriterWriteAttribute(pWriter, BAD_CAST("id"), BAD_CAST(OString::number(static_cast<sal_Int32>(GetViewShellId())).getStr()));
1576 xmlTextWriterEndElement(pWriter);
1579 bool SfxViewShell::KeyInput( const KeyEvent &rKeyEvent )
1581 /* [Description]
1583 This Method executes the KeyEvent 'rKeyEvent' of the Keys (Accelerator)
1584 configured either direct or indirect (for example by the Application)
1585 in the SfxViewShell.
1587 [Return value]
1589 bool TRUE
1590 The Key (Accelerator) is configured and the
1591 associated Handler was called
1593 FALSE
1594 The Key (Accelerator) is not configured and
1595 subsequently no Handler was called
1597 [Cross-reference]
1599 <SfxApplication::KeyInput(const KeyEvent&)>
1602 return ExecKey_Impl(rKeyEvent);
1605 bool SfxViewShell::GlobalKeyInput_Impl( const KeyEvent &rKeyEvent )
1607 return ExecKey_Impl(rKeyEvent);
1611 void SfxViewShell::ShowCursor( bool /*bOn*/ )
1613 /* [Description]
1615 Subclasses must override this Method so that SFx can switch the
1616 Cursor on and off, for example while a <SfxProgress> is running.
1623 void SfxViewShell::ResetAllClients_Impl( SfxInPlaceClient const *pIP )
1626 std::vector< SfxInPlaceClient* > *pClients = pImpl->GetIPClients_Impl(false);
1627 if ( !pClients )
1628 return;
1630 for (SfxInPlaceClient* pIPClient : *pClients)
1632 if( pIPClient != pIP )
1633 pIPClient->ResetObject();
1638 void SfxViewShell::DisconnectAllClients()
1640 std::vector< SfxInPlaceClient* > *pClients = pImpl->GetIPClients_Impl(false);
1641 if ( !pClients )
1642 return;
1644 for ( size_t n = 0; n < pClients->size(); )
1645 // clients will remove themselves from the list
1646 delete pClients->at( n );
1650 void SfxViewShell::QueryObjAreaPixel( tools::Rectangle& ) const
1655 void SfxViewShell::VisAreaChanged()
1657 std::vector< SfxInPlaceClient* > *pClients = pImpl->GetIPClients_Impl(false);
1658 if ( !pClients )
1659 return;
1661 for (SfxInPlaceClient* pIPClient : *pClients)
1663 if ( pIPClient->IsObjectInPlaceActive() )
1664 // client is active, notify client that the VisArea might have changed
1665 pIPClient->VisAreaChanged();
1670 void SfxViewShell::CheckIPClient_Impl(
1671 SfxInPlaceClient const *const pIPClient, const tools::Rectangle& rVisArea)
1673 if ( GetObjectShell()->IsInClose() )
1674 return;
1676 bool bAlwaysActive =
1677 ( ( pIPClient->GetObjectMiscStatus() & embed::EmbedMisc::EMBED_ACTIVATEIMMEDIATELY ) != 0 );
1678 bool bActiveWhenVisible =
1679 ( pIPClient->GetObjectMiscStatus() & embed::EmbedMisc::MS_EMBED_ACTIVATEWHENVISIBLE ) != 0;
1681 // this method is called when a client is created
1682 if (pIPClient->IsObjectInPlaceActive())
1683 return;
1685 // object in client is currently not active
1686 // check if the object wants to be activated always or when it becomes at least partially visible
1687 // TODO/LATER: maybe we should use the scaled area instead of the ObjArea?!
1688 if (bAlwaysActive || (bActiveWhenVisible && rVisArea.IsOver(pIPClient->GetObjArea())))
1692 pIPClient->GetObject()->changeState( embed::EmbedStates::INPLACE_ACTIVE );
1694 catch (const uno::Exception&)
1696 TOOLS_WARN_EXCEPTION("sfx.view", "SfxViewShell::CheckIPClient_Impl");
1702 SfxObjectShell* SfxViewShell::GetObjectShell()
1704 return pFrame ? pFrame->GetObjectShell() : nullptr;
1708 Reference< XModel > SfxViewShell::GetCurrentDocument() const
1710 Reference< XModel > xDocument;
1712 const SfxObjectShell* pDocShell( const_cast< SfxViewShell* >( this )->GetObjectShell() );
1713 OSL_ENSURE( pDocShell, "SfxViewFrame::GetCurrentDocument: no DocShell!?" );
1714 if ( pDocShell )
1715 xDocument = pDocShell->GetModel();
1716 return xDocument;
1720 void SfxViewShell::SetCurrentDocument() const
1722 uno::Reference< frame::XModel > xDocument( GetCurrentDocument() );
1723 if ( xDocument.is() )
1724 SfxObjectShell::SetCurrentComponent( xDocument );
1728 const Size& SfxViewShell::GetMargin() const
1730 return pImpl->aMargin;
1734 void SfxViewShell::SetMargin( const Size& rSize )
1736 // the default margin was verified using www.apple.com !!
1737 Size aMargin = rSize;
1738 if ( aMargin.Width() == -1 )
1739 aMargin.setWidth( DEFAULT_MARGIN_WIDTH );
1740 if ( aMargin.Height() == -1 )
1741 aMargin.setHeight( DEFAULT_MARGIN_HEIGHT );
1743 if ( aMargin != pImpl->aMargin )
1745 pImpl->aMargin = aMargin;
1746 MarginChanged();
1750 void SfxViewShell::MarginChanged()
1754 void SfxViewShell::JumpToMark( const OUString& rMark )
1756 SfxStringItem aMarkItem( SID_JUMPTOMARK, rMark );
1757 GetViewFrame()->GetDispatcher()->ExecuteList(
1758 SID_JUMPTOMARK,
1759 SfxCallMode::SYNCHRON|SfxCallMode::RECORD,
1760 { &aMarkItem });
1763 void SfxViewShell::SetController( SfxBaseController* pController )
1765 pImpl->m_pController = pController;
1767 // there should be no old listener, but if there is one, it should be disconnected
1768 if ( pImpl->xClipboardListener.is() )
1769 pImpl->xClipboardListener->DisconnectViewShell();
1771 pImpl->xClipboardListener = new SfxClipboardChangeListener( this, GetClipboardNotifier() );
1774 Reference < XController > SfxViewShell::GetController() const
1776 return pImpl->m_pController.get();
1779 SfxBaseController* SfxViewShell::GetBaseController_Impl() const
1781 return pImpl->m_pController.get();
1784 void SfxViewShell::AddContextMenuInterceptor_Impl( const uno::Reference< ui::XContextMenuInterceptor >& xInterceptor )
1786 pImpl->aInterceptorContainer.addInterface( xInterceptor );
1789 void SfxViewShell::RemoveContextMenuInterceptor_Impl( const uno::Reference< ui::XContextMenuInterceptor >& xInterceptor )
1791 pImpl->aInterceptorContainer.removeInterface( xInterceptor );
1794 static void Change( Menu* pMenu, SfxViewShell* pView )
1796 SfxDispatcher *pDisp = pView->GetViewFrame()->GetDispatcher();
1797 sal_uInt16 nCount = pMenu->GetItemCount();
1798 for ( sal_uInt16 nPos=0; nPos<nCount; ++nPos )
1800 sal_uInt16 nId = pMenu->GetItemId(nPos);
1801 OUString aCmd = pMenu->GetItemCommand(nId);
1802 PopupMenu* pPopup = pMenu->GetPopupMenu(nId);
1803 if ( pPopup )
1805 Change( pPopup, pView );
1807 else if ( nId < 5000 )
1809 if ( aCmd.startsWith(".uno:") )
1811 for (sal_uInt16 nIdx=0;;)
1813 SfxShell *pShell=pDisp->GetShell(nIdx++);
1814 if (pShell == nullptr)
1815 break;
1816 const SfxInterface *pIFace = pShell->GetInterface();
1817 const SfxSlot* pSlot = pIFace->GetSlot( aCmd );
1818 if ( pSlot )
1820 pMenu->InsertItem( pSlot->GetSlotId(), pMenu->GetItemText( nId ),
1821 pMenu->GetItemBits( nId ), OString(), nPos );
1822 pMenu->SetItemCommand( pSlot->GetSlotId(), aCmd );
1823 pMenu->RemoveItem( nPos+1 );
1824 break;
1833 bool SfxViewShell::TryContextMenuInterception( Menu& rIn, const OUString& rMenuIdentifier, VclPtr<Menu>& rpOut, ui::ContextMenuExecuteEvent aEvent )
1835 rpOut = nullptr;
1836 bool bModified = false;
1838 // create container from menu
1839 aEvent.ActionTriggerContainer = ::framework::ActionTriggerHelper::CreateActionTriggerContainerFromMenu(
1840 &rIn, &rMenuIdentifier );
1842 // get selection from controller
1843 aEvent.Selection.set( GetController(), uno::UNO_QUERY );
1845 // call interceptors
1846 ::comphelper::OInterfaceIteratorHelper2 aIt( pImpl->aInterceptorContainer );
1847 while( aIt.hasMoreElements() )
1851 ui::ContextMenuInterceptorAction eAction;
1853 SolarMutexReleaser rel;
1854 eAction = static_cast<ui::XContextMenuInterceptor*>(aIt.next())->notifyContextMenuExecute( aEvent );
1856 switch ( eAction )
1858 case ui::ContextMenuInterceptorAction_CANCELLED :
1859 // interceptor does not want execution
1860 return false;
1861 case ui::ContextMenuInterceptorAction_EXECUTE_MODIFIED :
1862 // interceptor wants his modified menu to be executed
1863 bModified = true;
1864 break;
1865 case ui::ContextMenuInterceptorAction_CONTINUE_MODIFIED :
1866 // interceptor has modified menu, but allows for calling other interceptors
1867 bModified = true;
1868 continue;
1869 case ui::ContextMenuInterceptorAction_IGNORED :
1870 // interceptor is indifferent
1871 continue;
1872 default:
1873 OSL_FAIL("Wrong return value of ContextMenuInterceptor!");
1874 continue;
1877 catch (...)
1879 aIt.remove();
1882 break;
1885 if ( bModified )
1887 // container was modified, create a new window out of it
1888 rpOut = VclPtr<PopupMenu>::Create();
1889 ::framework::ActionTriggerHelper::CreateMenuFromActionTriggerContainer( rpOut, aEvent.ActionTriggerContainer );
1891 Change( rpOut, this );
1894 return true;
1897 bool SfxViewShell::TryContextMenuInterception( Menu& rMenu, const OUString& rMenuIdentifier, css::ui::ContextMenuExecuteEvent aEvent )
1899 bool bModified = false;
1901 // create container from menu
1902 aEvent.ActionTriggerContainer = ::framework::ActionTriggerHelper::CreateActionTriggerContainerFromMenu( &rMenu, &rMenuIdentifier );
1904 // get selection from controller
1905 aEvent.Selection = css::uno::Reference< css::view::XSelectionSupplier >( GetController(), css::uno::UNO_QUERY );
1907 // call interceptors
1908 ::comphelper::OInterfaceIteratorHelper2 aIt( pImpl->aInterceptorContainer );
1909 while( aIt.hasMoreElements() )
1913 css::ui::ContextMenuInterceptorAction eAction;
1915 SolarMutexReleaser rel;
1916 eAction = static_cast< css::ui::XContextMenuInterceptor* >( aIt.next() )->notifyContextMenuExecute( aEvent );
1918 switch ( eAction )
1920 case css::ui::ContextMenuInterceptorAction_CANCELLED:
1921 // interceptor does not want execution
1922 return false;
1923 case css::ui::ContextMenuInterceptorAction_EXECUTE_MODIFIED:
1924 // interceptor wants his modified menu to be executed
1925 bModified = true;
1926 break;
1927 case css::ui::ContextMenuInterceptorAction_CONTINUE_MODIFIED:
1928 // interceptor has modified menu, but allows for calling other interceptors
1929 bModified = true;
1930 continue;
1931 case css::ui::ContextMenuInterceptorAction_IGNORED:
1932 // interceptor is indifferent
1933 continue;
1934 default:
1935 SAL_WARN( "sfx.view", "Wrong return value of ContextMenuInterceptor!" );
1936 continue;
1939 catch (...)
1941 aIt.remove();
1944 break;
1947 if ( bModified )
1949 rMenu.Clear();
1950 ::framework::ActionTriggerHelper::CreateMenuFromActionTriggerContainer( &rMenu, aEvent.ActionTriggerContainer );
1953 return true;
1956 bool SfxViewShell::HandleNotifyEvent_Impl( NotifyEvent const & rEvent )
1958 if (pImpl->m_pController.is())
1959 return pImpl->m_pController->HandleEvent_Impl( rEvent );
1960 return false;
1963 bool SfxViewShell::HasKeyListeners_Impl() const
1965 return (pImpl->m_pController.is())
1966 && pImpl->m_pController->HasKeyListeners_Impl();
1969 bool SfxViewShell::HasMouseClickListeners_Impl() const
1971 return (pImpl->m_pController.is())
1972 && pImpl->m_pController->HasMouseClickListeners_Impl();
1975 bool SfxViewShell::Escape()
1977 return GetViewFrame()->GetBindings().Execute( SID_TERMINATE_INPLACEACTIVATION );
1980 Reference< view::XRenderable > SfxViewShell::GetRenderable()
1982 Reference< view::XRenderable >xRender;
1983 SfxObjectShell* pObj = GetObjectShell();
1984 if( pObj )
1986 Reference< frame::XModel > xModel( pObj->GetModel() );
1987 if( xModel.is() )
1988 xRender.set( xModel, UNO_QUERY );
1990 return xRender;
1993 void SfxViewShell::notifyWindow(vcl::LOKWindowId nDialogId, const OUString& rAction, const std::vector<vcl::LOKPayloadItem>& rPayload) const
1995 SfxLokHelper::notifyWindow(this, nDialogId, rAction, rPayload);
1998 uno::Reference< datatransfer::clipboard::XClipboardNotifier > SfxViewShell::GetClipboardNotifier() const
2000 uno::Reference< datatransfer::clipboard::XClipboardNotifier > xClipboardNotifier;
2001 if ( GetViewFrame() )
2002 xClipboardNotifier.set( GetViewFrame()->GetWindow().GetClipboard(), uno::UNO_QUERY );
2004 return xClipboardNotifier;
2007 void SfxViewShell::AddRemoveClipboardListener( const uno::Reference < datatransfer::clipboard::XClipboardListener >& rClp, bool bAdd )
2011 if ( GetViewFrame() )
2013 uno::Reference< datatransfer::clipboard::XClipboard > xClipboard( GetViewFrame()->GetWindow().GetClipboard() );
2014 if( xClipboard.is() )
2016 uno::Reference< datatransfer::clipboard::XClipboardNotifier > xClpbrdNtfr( xClipboard, uno::UNO_QUERY );
2017 if( xClpbrdNtfr.is() )
2019 if( bAdd )
2020 xClpbrdNtfr->addClipboardListener( rClp );
2021 else
2022 xClpbrdNtfr->removeClipboardListener( rClp );
2027 catch (const uno::Exception&)
2032 weld::Window* SfxViewShell::GetFrameWeld() const
2034 return pWindow ? pWindow->GetFrameWeld() : nullptr;
2037 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */