LanguageTool: don't crash if REST protocol isn't set
[LibreOffice.git] / sfx2 / source / view / viewfrm.cxx
blobcca28ca016baba4cf14f313521c1da78af80f4b0
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 <config_feature_desktop.h>
21 #include <osl/file.hxx>
22 #include <sfx2/docfilt.hxx>
23 #include <sfx2/infobar.hxx>
24 #include <sfx2/sfxsids.hrc>
25 #include <sfx2/viewfrm.hxx>
26 #include <sfx2/classificationhelper.hxx>
27 #include <sfx2/notebookbar/SfxNotebookBar.hxx>
28 #include <svx/svdview.hxx>
29 #include <com/sun/star/document/MacroExecMode.hpp>
30 #include <com/sun/star/frame/Desktop.hpp>
31 #include <com/sun/star/frame/DispatchRecorder.hpp>
32 #include <com/sun/star/frame/DispatchRecorderSupplier.hpp>
33 #include <com/sun/star/frame/XLoadable.hpp>
34 #include <com/sun/star/frame/XLayoutManager.hpp>
35 #include <com/sun/star/frame/XComponentLoader.hpp>
36 #include <com/sun/star/task/PasswordContainer.hpp>
37 #include <officecfg/Office/Common.hxx>
38 #include <officecfg/Setup.hxx>
39 #include <toolkit/helper/vclunohelper.hxx>
40 #include <vcl/wrkwin.hxx>
41 #include <unotools/moduleoptions.hxx>
42 #include <svl/intitem.hxx>
43 #include <svl/visitem.hxx>
44 #include <svl/stritem.hxx>
45 #include <svl/eitem.hxx>
46 #include <svl/whiter.hxx>
47 #include <svl/undo.hxx>
48 #include <vcl/stdtext.hxx>
49 #include <vcl/weld.hxx>
50 #include <vcl/weldutils.hxx>
51 #include <unotools/VersionConfig.hxx>
52 #include <svtools/miscopt.hxx>
53 #include <tools/diagnose_ex.h>
54 #include <com/sun/star/container/XIndexAccess.hpp>
55 #include <com/sun/star/frame/XFramesSupplier.hpp>
56 #include <com/sun/star/frame/FrameSearchFlag.hpp>
57 #include <com/sun/star/frame/XFrame.hpp>
58 #include <com/sun/star/awt/XWindow.hpp>
59 #include <com/sun/star/frame/XController.hpp>
60 #include <com/sun/star/util/URLTransformer.hpp>
61 #include <com/sun/star/util/XURLTransformer.hpp>
62 #include <com/sun/star/util/XCloseable.hpp>
63 #include <com/sun/star/frame/XDispatchRecorderSupplier.hpp>
64 #include <com/sun/star/document/UpdateDocMode.hpp>
65 #include <com/sun/star/beans/XPropertySet.hpp>
66 #include <com/sun/star/uri/UriReferenceFactory.hpp>
67 #include <com/sun/star/uri/XVndSunStarScriptUrl.hpp>
68 #include <com/sun/star/document/XViewDataSupplier.hpp>
69 #include <com/sun/star/container/XIndexContainer.hpp>
70 #include <com/sun/star/task/InteractionHandler.hpp>
71 #include <com/sun/star/drawing/XDrawView.hpp>
72 #include <com/sun/star/drawing/XDrawPagesSupplier.hpp>
73 #include <com/sun/star/frame/ModuleManager.hpp>
74 #include <com/sun/star/frame/UnknownModuleException.hpp>
75 #include <rtl/ustrbuf.hxx>
76 #include <sal/log.hxx>
78 #include <unotools/ucbhelper.hxx>
79 #include <comphelper/lok.hxx>
80 #include <comphelper/processfactory.hxx>
81 #include <comphelper/namedvaluecollection.hxx>
82 #include <comphelper/docpasswordrequest.hxx>
83 #include <comphelper/docpasswordhelper.hxx>
85 #include <com/sun/star/uno/Reference.h>
87 #include <basic/basmgr.hxx>
88 #include <basic/sbmod.hxx>
89 #include <basic/sbmeth.hxx>
90 #include <svtools/strings.hrc>
91 #include <svtools/svtresid.hxx>
92 #include <framework/framelistanalyzer.hxx>
94 #include <optional>
96 #include <unotools/configmgr.hxx>
97 #include <comphelper/sequenceashashmap.hxx>
99 #include <commandpopup/CommandPopup.hxx>
102 using namespace ::com::sun::star;
103 using namespace ::com::sun::star::uno;
104 using namespace ::com::sun::star::ucb;
105 using namespace ::com::sun::star::frame;
106 using namespace ::com::sun::star::lang;
107 using ::com::sun::star::awt::XWindow;
108 using ::com::sun::star::beans::PropertyValue;
109 using ::com::sun::star::document::XViewDataSupplier;
110 using ::com::sun::star::container::XIndexContainer;
112 // Due to ViewFrame::Current
113 #include <appdata.hxx>
114 #include <sfx2/app.hxx>
115 #include <sfx2/objface.hxx>
116 #include <openflag.hxx>
117 #include <objshimp.hxx>
118 #include <sfx2/viewsh.hxx>
119 #include <sfx2/objsh.hxx>
120 #include <sfx2/bindings.hxx>
121 #include <sfx2/dispatch.hxx>
122 #include <sfx2/request.hxx>
123 #include <sfx2/docfac.hxx>
124 #include <sfx2/ipclient.hxx>
125 #include <sfx2/sfxresid.hxx>
126 #include <sfx2/viewfac.hxx>
127 #include <sfx2/event.hxx>
128 #include <sfx2/fcontnr.hxx>
129 #include <sfx2/docfile.hxx>
130 #include <sfx2/module.hxx>
131 #include <sfx2/sfxuno.hxx>
132 #include <sfx2/progress.hxx>
133 #include <sfx2/sidebar/Sidebar.hxx>
134 #include <workwin.hxx>
135 #include <sfx2/minfitem.hxx>
136 #include <sfx2/strings.hrc>
137 #include "impviewframe.hxx"
138 #include <vcl/commandinfoprovider.hxx>
139 #include <vcl/svapp.hxx>
141 #define ShellClass_SfxViewFrame
142 #include <sfxslots.hxx>
144 #include <sfx2/sidebar/SidebarController.hxx>
145 constexpr OUStringLiteral CHANGES_STR = u"private:resource/toolbar/changes";
147 SFX_IMPL_SUPERCLASS_INTERFACE(SfxViewFrame,SfxShell)
149 void SfxViewFrame::InitInterface_Impl()
151 GetStaticInterface()->RegisterChildWindow(SID_BROWSER);
152 GetStaticInterface()->RegisterChildWindow(SID_RECORDING_FLOATWINDOW);
153 #if HAVE_FEATURE_DESKTOP
154 GetStaticInterface()->RegisterObjectBar(SFX_OBJECTBAR_FULLSCREEN, SfxVisibilityFlags::FullScreen, ToolbarId::FullScreenToolbox);
155 GetStaticInterface()->RegisterObjectBar(SFX_OBJECTBAR_APPLICATION, SfxVisibilityFlags::Standard, ToolbarId::EnvToolbox);
156 #endif
159 namespace {
160 /// Asks the user if editing a read-only document is really wanted.
161 class SfxEditDocumentDialog : public weld::MessageDialogController
163 private:
164 std::unique_ptr<weld::Button> m_xEditDocument;
165 std::unique_ptr<weld::Button> m_xCancel;
167 public:
168 SfxEditDocumentDialog(weld::Widget* pParent);
171 SfxEditDocumentDialog::SfxEditDocumentDialog(weld::Widget* pParent)
172 : MessageDialogController(pParent, "sfx/ui/editdocumentdialog.ui",
173 "EditDocumentDialog")
174 , m_xEditDocument(m_xBuilder->weld_button("edit"))
175 , m_xCancel(m_xBuilder->weld_button("cancel"))
179 class SfxQueryOpenAsTemplate
181 private:
182 std::unique_ptr<weld::MessageDialog> m_xQueryBox;
183 public:
184 SfxQueryOpenAsTemplate(weld::Window* pParent, bool bAllowIgnoreLock, LockFileEntry& rLockData)
185 : m_xQueryBox(Application::CreateMessageDialog(pParent, VclMessageType::Question,
186 VclButtonsType::NONE, ""))
188 m_xQueryBox->add_button(SfxResId(STR_QUERY_OPENASTEMPLATE_OPENCOPY_BTN), RET_YES);
189 bAllowIgnoreLock
190 = bAllowIgnoreLock && officecfg::Office::Common::Misc::AllowOverrideLocking::get();
191 if (bAllowIgnoreLock)
192 m_xQueryBox->add_button(SfxResId(STR_QUERY_OPENASTEMPLATE_OPEN_BTN), RET_IGNORE);
193 m_xQueryBox->add_button(GetStandardText( StandardButtonType::Cancel ), RET_CANCEL);
194 m_xQueryBox->set_primary_text(QueryString(bAllowIgnoreLock, rLockData));
195 m_xQueryBox->set_default_response(RET_YES);
197 short run() { return m_xQueryBox->run(); }
199 private:
200 static OUString QueryString(bool bAllowIgnoreLock, LockFileEntry& rLockData)
202 OUString sLockUserData;
203 if (!rLockData[LockFileComponent::OOOUSERNAME].isEmpty())
204 sLockUserData = rLockData[LockFileComponent::OOOUSERNAME];
205 else
206 sLockUserData = rLockData[LockFileComponent::SYSUSERNAME];
208 if (!sLockUserData.isEmpty() && !rLockData[LockFileComponent::EDITTIME].isEmpty())
209 sLockUserData += " ( " + rLockData[LockFileComponent::EDITTIME] + " )";
211 if (!sLockUserData.isEmpty())
212 sLockUserData = "\n\n" + sLockUserData + "\n";
214 const bool bUseLockStr = bAllowIgnoreLock || !sLockUserData.isEmpty();
216 OUString sMsg(
217 SfxResId(bUseLockStr ? STR_QUERY_OPENASTEMPLATE_LOCKED : STR_QUERY_OPENASTEMPLATE));
219 if (bAllowIgnoreLock)
220 sMsg += "\n\n" + SfxResId(STR_QUERY_OPENASTEMPLATE_ALLOW_IGNORE);
222 return sMsg.replaceFirst("%LOCKINFO", sLockUserData);
226 bool AskPasswordToModify_Impl( const uno::Reference< task::XInteractionHandler >& xHandler, const OUString& aPath, const std::shared_ptr<const SfxFilter>& pFilter, sal_uInt32 nPasswordHash, const uno::Sequence< beans::PropertyValue >& aInfo )
228 // TODO/LATER: In future the info should replace the direct hash completely
229 bool bResult = ( !nPasswordHash && !aInfo.hasElements() );
231 SAL_WARN_IF( !(pFilter && ( pFilter->GetFilterFlags() & SfxFilterFlags::PASSWORDTOMODIFY )), "sfx.view",
232 "PasswordToModify feature is active for a filter that does not support it!");
234 if ( pFilter && xHandler.is() )
236 bool bCancel = false;
237 bool bFirstTime = true;
239 while ( !bResult && !bCancel )
241 bool bMSType = !pFilter->IsOwnFormat();
243 ::rtl::Reference< ::comphelper::DocPasswordRequest > pPasswordRequest(
244 new ::comphelper::DocPasswordRequest(
245 bMSType ? ::comphelper::DocPasswordRequestType::MS : ::comphelper::DocPasswordRequestType::Standard,
246 bFirstTime ? css::task::PasswordRequestMode_PASSWORD_ENTER : css::task::PasswordRequestMode_PASSWORD_REENTER,
247 aPath,
248 true ) );
250 xHandler->handle( pPasswordRequest );
252 if ( pPasswordRequest->isPassword() )
254 if ( aInfo.hasElements() )
256 bResult = ::comphelper::DocPasswordHelper::IsModifyPasswordCorrect( pPasswordRequest->getPasswordToModify(), aInfo );
258 else
260 // the binary format
261 bResult = ( SfxMedium::CreatePasswordToModifyHash( pPasswordRequest->getPasswordToModify(), pFilter->GetServiceName()=="com.sun.star.text.TextDocument" ) == nPasswordHash );
264 else
265 bCancel = true;
267 bFirstTime = false;
271 return bResult;
274 bool physObjIsOlder(INetURLObject const & aMedObj, INetURLObject const & aPhysObj) {
275 return ::utl::UCBContentHelper::IsYounger(aMedObj.GetMainURL( INetURLObject::DecodeMechanism::NONE),
276 aPhysObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ) );
280 void SfxViewFrame::ExecReload_Impl( SfxRequest& rReq )
282 SfxObjectShell* pSh = GetObjectShell();
283 switch ( rReq.GetSlot() )
285 case SID_EDITDOC:
286 case SID_READONLYDOC:
288 // Due to Double occupancy in toolboxes (with or without Ctrl),
289 // it is also possible that the slot is enabled, but Ctrl-click
290 // despite this is not!
291 if( !pSh || !pSh->HasName() || !(pSh->Get_Impl()->nLoadedFlags & SfxLoadedFlags::MAINDOCUMENT ))
292 break;
294 if (pSh->isEditDocLocked())
295 break;
297 // Only change read-only UI and remove info bar when we succeed
298 struct ReadOnlyUIGuard
300 SfxViewFrame* m_pFrame;
301 SfxObjectShell* m_pSh;
302 SfxMedium* m_pMed = nullptr;
303 bool m_bSetRO;
304 ReadOnlyUIGuard(SfxViewFrame* pFrame, SfxObjectShell* p_Sh)
305 : m_pFrame(pFrame), m_pSh(p_Sh), m_bSetRO(p_Sh->IsReadOnlyUI())
307 ~ReadOnlyUIGuard() COVERITY_NOEXCEPT_FALSE
309 if (m_bSetRO != m_pSh->IsReadOnlyUI())
311 m_pSh->SetReadOnlyUI(m_bSetRO);
312 if (!m_bSetRO)
313 m_pFrame->RemoveInfoBar(u"readonly");
314 if (m_pMed)
316 // tdf#116066: DoSaveCompleted should be called after SetReadOnlyUI
317 m_pSh->DoSaveCompleted(m_pMed);
318 m_pSh->Broadcast(SfxHint(SfxHintId::ModeChanged));
322 } aReadOnlyUIGuard(this, pSh);
324 SfxMedium* pMed = pSh->GetMedium();
326 std::shared_ptr<std::recursive_mutex> pChkEditMutex = pMed->GetCheckEditableMutex();
327 std::unique_lock<std::recursive_mutex> chkEditLock;
328 if (pChkEditMutex != nullptr)
329 chkEditLock = std::unique_lock<std::recursive_mutex>(*pChkEditMutex);
330 pMed->CancelCheckEditableEntry();
332 const SfxBoolItem* pItem = SfxItemSet::GetItem<SfxBoolItem>(pSh->GetMedium()->GetItemSet(), SID_VIEWONLY, false);
333 if ( pItem && pItem->GetValue() )
335 SfxApplication* pApp = SfxGetpApp();
336 SfxAllItemSet aSet( pApp->GetPool() );
337 aSet.Put( SfxStringItem( SID_FILE_NAME, pMed->GetURLObject().GetMainURL(INetURLObject::DecodeMechanism::NONE) ) );
338 aSet.Put( SfxBoolItem( SID_TEMPLATE, true ) );
339 aSet.Put( SfxStringItem( SID_TARGETNAME, "_blank" ) );
340 const SfxStringItem* pReferer = SfxItemSet::GetItem<SfxStringItem>(pMed->GetItemSet(), SID_REFERER, false);
341 if ( pReferer )
342 aSet.Put( *pReferer );
343 const SfxInt16Item* pVersionItem = SfxItemSet::GetItem<SfxInt16Item>(pSh->GetMedium()->GetItemSet(), SID_VERSION, false);
344 if ( pVersionItem )
345 aSet.Put( *pVersionItem );
347 if( pMed->GetFilter() )
349 aSet.Put( SfxStringItem( SID_FILTER_NAME, pMed->GetFilter()->GetFilterName() ) );
350 const SfxStringItem* pOptions = SfxItemSet::GetItem<SfxStringItem>(pMed->GetItemSet(), SID_FILE_FILTEROPTIONS, false);
351 if ( pOptions )
352 aSet.Put( *pOptions );
355 GetDispatcher()->Execute( SID_OPENDOC, SfxCallMode::ASYNCHRON, aSet );
356 return;
359 StreamMode nOpenMode;
360 bool bNeedsReload = false;
361 bool bPasswordEntered = false;
362 if ( !pSh->IsReadOnly() )
364 // Save and reload Readonly
365 if( pSh->IsModified() )
367 if ( pSh->PrepareClose() )
369 // the storing could let the medium be changed
370 pMed = pSh->GetMedium();
371 bNeedsReload = true;
373 else
375 rReq.SetReturnValue( SfxBoolItem( rReq.GetSlot(), false ) );
376 return;
379 nOpenMode = SFX_STREAM_READONLY;
380 aReadOnlyUIGuard.m_bSetRO = true;
382 else
384 if ( pSh->IsReadOnlyMedium()
385 && ( pSh->GetModifyPasswordHash() || pSh->GetModifyPasswordInfo().hasElements() )
386 && !pSh->IsModifyPasswordEntered() )
388 const OUString aDocumentName = INetURLObject( pMed->GetOrigURL() ).GetMainURL( INetURLObject::DecodeMechanism::WithCharset );
389 if( !AskPasswordToModify_Impl( pMed->GetInteractionHandler(), aDocumentName, pMed->GetFilter(), pSh->GetModifyPasswordHash(), pSh->GetModifyPasswordInfo() ) )
391 // this is a read-only document, if it has "Password to modify"
392 // the user should enter password before he can edit the document
393 rReq.SetReturnValue( SfxBoolItem( rReq.GetSlot(), false ) );
394 return;
397 pSh->SetModifyPasswordEntered();
398 bPasswordEntered = true;
401 nOpenMode = pSh->IsOriginallyReadOnlyMedium() ? SFX_STREAM_READONLY : SFX_STREAM_READWRITE;
402 aReadOnlyUIGuard.m_bSetRO = false;
404 // if only the view was in the readonly mode then there is no need to do the reload
405 if ( !pSh->IsReadOnlyMedium() )
407 // SetReadOnlyUI causes recomputation of window title, using
408 // open mode among other things, so call SetOpenMode before
409 // SetReadOnlyUI:
410 pMed->SetOpenMode( nOpenMode );
411 return;
415 if ( rReq.IsAPI() )
417 // Control through API if r/w or r/o
418 const SfxBoolItem* pEditItem = rReq.GetArg<SfxBoolItem>(SID_EDITDOC);
419 if ( pEditItem )
420 nOpenMode = pEditItem->GetValue() ? SFX_STREAM_READWRITE : SFX_STREAM_READONLY;
423 // doing
425 OUString sTemp;
426 osl::FileBase::getFileURLFromSystemPath( pMed->GetPhysicalName(), sTemp );
427 INetURLObject aPhysObj( sTemp );
428 const SfxInt16Item* pVersionItem = SfxItemSet::GetItem<SfxInt16Item>(pSh->GetMedium()->GetItemSet(), SID_VERSION, false);
430 INetURLObject aMedObj( pMed->GetName() );
432 // -> tdf#82744
433 // the logic below is following:
434 // if the document seems not to need to be reloaded
435 // and the physical name is different to the logical one,
436 // then on file system it can be checked that the copy is still newer than the original and no document reload is required.
437 // Did some semplification to enhance readability of the 'if' expression
439 // when the 'http/https' protocol is active, the bool bPhysObjIsYounger relies upon the getlastmodified Property of a WebDAV resource.
440 // Said property should be implemented, but sometimes it's not.
441 // implemented. On this case the reload activated here will not work properly.
442 // TODO: change the check age method for WebDAV to etag (entity-tag) property value, need some rethinking, since the
443 // etag tells that the cache representation (e.g. in LO) is different from the one on the server,
444 // but tells nothing about the age
445 // Details at this link: http://tools.ietf.org/html/rfc4918#section-15, section 15.7
446 bool bIsWebDAV = aMedObj.isAnyKnownWebDAVScheme();
448 // tdf#118938 Reload the document when the user enters the editing password,
449 // even if the physical name isn't different to the logical name.
450 if ( ( !bNeedsReload && ( ( aMedObj.GetProtocol() == INetProtocol::File &&
451 ( aMedObj.getFSysPath( FSysStyle::Detect ) != aPhysObj.getFSysPath( FSysStyle::Detect )
452 || bPasswordEntered ) &&
453 !physObjIsOlder(aMedObj, aPhysObj) )
454 || ( bIsWebDAV && !physObjIsOlder(aMedObj, aPhysObj) )
455 || ( pMed->IsRemote() && !bIsWebDAV ) ) )
456 || pVersionItem )
457 // <- tdf#82744
459 bNeedsReload = true;
461 bool bOK = false;
462 bool bRetryIgnoringLock = false;
463 bool bOpenTemplate = false;
464 std::optional<bool> aOrigROVal;
465 if (!pVersionItem)
467 auto pRO = pMed->GetItemSet()->GetItem<SfxBoolItem>(SID_DOC_READONLY, false);
468 if (pRO)
469 aOrigROVal = pRO->GetValue();
471 do {
472 LockFileEntry aLockData;
473 if ( !pVersionItem )
475 if (bRetryIgnoringLock)
476 pMed->ResetError();
478 bool bHasStorage = pMed->HasStorage_Impl();
479 // switching edit mode could be possible without reload
480 if ( bHasStorage && pMed->GetStorage() == pSh->GetStorage() )
482 // TODO/LATER: faster creation of copy
483 if ( !pSh->ConnectTmpStorage_Impl( pMed->GetStorage(), pMed ) )
484 return;
487 pMed->CloseAndRelease();
488 pMed->SetOpenMode( nOpenMode );
489 // We need to clear the SID_DOC_READONLY item from the set, to allow
490 // MediaDescriptor::impl_openStreamWithURL (called indirectly by
491 // SfxMedium::CompleteReOpen) to properly fill input stream of the
492 // descriptor, even when the file can't be open in read-write mode.
493 // Only then can following call to SfxMedium::LockOrigFileOnDemand
494 // return proper information about who has locked the file, to show
495 // in the SfxQueryOpenAsTemplate box below; otherwise it exits right
496 // after call to SfxMedium::GetMedium_Impl. This mimics what happens
497 // when the file is opened initially, when filter detection code also
498 // calls MediaDescriptor::impl_openStreamWithURL without the item set.
499 pMed->GetItemSet()->ClearItem(SID_DOC_READONLY);
500 pMed->CompleteReOpen();
501 pMed->GetItemSet()->Put(
502 SfxBoolItem(SID_DOC_READONLY, !(nOpenMode & StreamMode::WRITE)));
503 if ( nOpenMode & StreamMode::WRITE )
505 auto eResult = pMed->LockOrigFileOnDemand(
506 true, true, bRetryIgnoringLock, &aLockData);
507 bRetryIgnoringLock
508 = eResult == SfxMedium::LockFileResult::FailedLockFile;
511 // LockOrigFileOnDemand might set the readonly flag itself, it should be set back
512 pMed->GetItemSet()->Put( SfxBoolItem( SID_DOC_READONLY, !( nOpenMode & StreamMode::WRITE ) ) );
514 if ( !pMed->GetErrorCode() )
515 bOK = true;
518 if( !bOK )
520 if (nOpenMode == SFX_STREAM_READWRITE && !rReq.IsAPI())
522 // css::sdbcx::User offering to open it as a template
523 SfxQueryOpenAsTemplate aBox(GetWindow().GetFrameWeld(),
524 bRetryIgnoringLock, aLockData);
526 short nUserAnswer = aBox.run();
527 bOpenTemplate = RET_YES == nUserAnswer;
528 // Always reset this here to avoid infinite loop
529 bRetryIgnoringLock = RET_IGNORE == nUserAnswer;
530 if (RET_CANCEL == nUserAnswer)
531 pMed->AddToCheckEditableWorkerList();
533 else
534 bRetryIgnoringLock = false;
537 while ( !bOK && bRetryIgnoringLock );
539 if( !bOK )
541 ErrCode nErr = pMed->GetErrorCode();
542 if ( pVersionItem )
543 nErr = ERRCODE_IO_ACCESSDENIED;
544 else
546 pMed->ResetError();
547 pMed->SetOpenMode( SFX_STREAM_READONLY );
548 if (aOrigROVal)
549 pMed->GetItemSet()->Put(SfxBoolItem(SID_DOC_READONLY, *aOrigROVal));
550 else
551 pMed->GetItemSet()->ClearItem(SID_DOC_READONLY);
552 pMed->ReOpen();
553 pSh->DoSaveCompleted( pMed );
556 // Readonly document can not be switched to edit mode?
557 rReq.Done();
559 if ( nOpenMode == SFX_STREAM_READWRITE && !rReq.IsAPI() )
561 if ( bOpenTemplate )
563 SfxApplication* pApp = SfxGetpApp();
564 SfxAllItemSet aSet( pApp->GetPool() );
565 aSet.Put( SfxStringItem( SID_FILE_NAME, pMed->GetName() ) );
566 const SfxStringItem* pReferer = SfxItemSet::GetItem<SfxStringItem>(pMed->GetItemSet(), SID_REFERER, false);
567 if ( pReferer )
568 aSet.Put( *pReferer );
569 aSet.Put( SfxBoolItem( SID_TEMPLATE, true ) );
570 if ( pVersionItem )
571 aSet.Put( *pVersionItem );
573 if( pMed->GetFilter() )
575 aSet.Put( SfxStringItem( SID_FILTER_NAME, pMed->GetFilter()->GetFilterName() ) );
576 const SfxStringItem* pOptions = SfxItemSet::GetItem<SfxStringItem>(pMed->GetItemSet(), SID_FILE_FILTEROPTIONS, false);
577 if ( pOptions )
578 aSet.Put( *pOptions );
581 GetDispatcher()->Execute( SID_OPENDOC, SfxCallMode::ASYNCHRON, aSet );
582 return;
585 nErr = ERRCODE_NONE;
588 // Keep the read-only UI
589 aReadOnlyUIGuard.m_bSetRO = true;
591 ErrorHandler::HandleError( nErr );
592 rReq.SetReturnValue(
593 SfxBoolItem( rReq.GetSlot(), false ) );
594 return;
596 else
598 aReadOnlyUIGuard.m_pMed = pMed;
599 rReq.SetReturnValue( SfxBoolItem( rReq.GetSlot(), true ) );
600 rReq.Done( true );
601 return;
605 rReq.AppendItem( SfxBoolItem(SID_FORCERELOAD,
606 rReq.GetSlot() == SID_EDITDOC || bNeedsReload) );
607 rReq.AppendItem( SfxBoolItem( SID_SILENT, true ));
609 [[fallthrough]]; //TODO ???
612 case SID_RELOAD:
614 // Due to Double occupancy in toolboxes (with or without Ctrl),
615 // it is also possible that the slot is enabled, but Ctrl-click
616 // despite this is not!
617 if ( !pSh || !pSh->CanReload_Impl() )
618 break;
619 SfxApplication* pApp = SfxGetpApp();
620 const SfxBoolItem* pForceReloadItem = rReq.GetArg<SfxBoolItem>(SID_FORCERELOAD);
621 if( pForceReloadItem && !pForceReloadItem->GetValue() &&
622 !pSh->GetMedium()->IsExpired() )
623 return;
624 if( m_pImpl->bReloading || pSh->IsInModalMode() )
625 return;
627 // AutoLoad is prohibited if possible
628 const SfxBoolItem* pAutoLoadItem = rReq.GetArg<SfxBoolItem>(SID_AUTOLOAD);
629 if ( pAutoLoadItem && pAutoLoadItem->GetValue() &&
630 GetFrame().IsAutoLoadLocked_Impl() )
631 return;
633 SfxObjectShellLock xOldObj( pSh );
634 m_pImpl->bReloading = true;
635 const SfxStringItem* pURLItem = rReq.GetArg<SfxStringItem>(SID_FILE_NAME);
636 // Open as editable?
637 bool bForEdit = !pSh->IsReadOnly();
639 // If possible ask the User
640 bool bDo = GetViewShell()->PrepareClose();
641 const SfxBoolItem* pSilentItem = rReq.GetArg<SfxBoolItem>(SID_SILENT);
642 if ( bDo && GetFrame().DocIsModified_Impl() &&
643 !rReq.IsAPI() && ( !pSilentItem || !pSilentItem->GetValue() ) )
645 std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(GetWindow().GetFrameWeld(),
646 VclMessageType::Question, VclButtonsType::YesNo,
647 SfxResId(STR_QUERY_LASTVERSION)));
648 bDo = RET_YES == xBox->run();
651 if ( bDo )
653 SfxMedium *pMedium = xOldObj->GetMedium();
654 std::shared_ptr<std::recursive_mutex> pChkEditMutex
655 = pMedium->GetCheckEditableMutex();
656 std::unique_lock<std::recursive_mutex> chkEditLock;
657 if (pChkEditMutex != nullptr)
658 chkEditLock = std::unique_lock<std::recursive_mutex>(*pChkEditMutex);
659 pMedium->CancelCheckEditableEntry();
661 bool bHandsOff =
662 ( pMedium->GetURLObject().GetProtocol() == INetProtocol::File && !xOldObj->IsDocShared() );
664 // Empty existing SfxMDIFrames for this Document
665 // in native format or R/O, open it now for editing?
666 SfxObjectShellLock xNewObj;
668 // collect the views of the document
669 // TODO: when UNO ViewFactories are available for SFX-based documents, the below code should
670 // be UNOized, too
671 typedef ::std::pair< Reference< XFrame >, SfxInterfaceId > ViewDescriptor;
672 ::std::vector< ViewDescriptor > aViewFrames;
673 SfxViewFrame *pView = GetFirst( xOldObj );
674 while ( pView )
676 Reference< XFrame > xFrame( pView->GetFrame().GetFrameInterface() );
677 SAL_WARN_IF( !xFrame.is(), "sfx.view", "SfxViewFrame::ExecReload_Impl: no XFrame?!");
678 aViewFrames.emplace_back( xFrame, pView->GetCurViewId() );
680 pView = GetNext( *pView, xOldObj );
683 xOldObj->Get_Impl()->pReloadTimer.reset();
685 std::optional<SfxAllItemSet> pNewSet;
686 std::shared_ptr<const SfxFilter> pFilter = pMedium->GetFilter();
687 if( pURLItem )
689 pNewSet.emplace( pApp->GetPool() );
690 pNewSet->Put( *pURLItem );
692 // Filter Detection
693 OUString referer;
694 const SfxStringItem* refererItem = rReq.GetArg<SfxStringItem>(SID_REFERER);
695 if (refererItem != nullptr) {
696 referer = refererItem->GetValue();
698 SfxMedium aMedium( pURLItem->GetValue(), referer, SFX_STREAM_READWRITE );
699 SfxFilterMatcher().GuessFilter( aMedium, pFilter );
700 if ( pFilter )
701 pNewSet->Put( SfxStringItem( SID_FILTER_NAME, pFilter->GetName() ) );
702 pNewSet->Put( *aMedium.GetItemSet() );
704 else
706 pNewSet.emplace( *pMedium->GetItemSet() );
707 pNewSet->ClearItem( SID_VIEW_ID );
708 pNewSet->ClearItem( SID_STREAM );
709 pNewSet->ClearItem( SID_INPUTSTREAM );
710 pNewSet->Put( SfxStringItem( SID_FILTER_NAME, pMedium->GetFilter()->GetName() ) );
712 // let the current security settings be checked again
713 pNewSet->Put( SfxUInt16Item( SID_MACROEXECMODE, document::MacroExecMode::USE_CONFIG ) );
715 if ( pSh->IsOriginallyReadOnlyMedium()
716 || pSh->IsOriginallyLoadedReadOnlyMedium() )
717 // edit mode is switched or reload of readonly document
718 pNewSet->Put( SfxBoolItem( SID_DOC_READONLY, true ) );
719 else
720 // Reload of file opened for writing
721 pNewSet->ClearItem( SID_DOC_READONLY );
724 // If a salvaged file is present, do not enclose the OrigURL
725 // again, since the Template is invalid after reload.
726 const SfxStringItem* pSalvageItem = SfxItemSet::GetItem<SfxStringItem>(&*pNewSet, SID_DOC_SALVAGE, false);
727 if( pSalvageItem )
729 pNewSet->ClearItem( SID_DOC_SALVAGE );
732 #if HAVE_FEATURE_MULTIUSER_ENVIRONMENT
733 // TODO/LATER: Temporary solution, the SfxMedium must know the original URL as aLogicName
734 // SfxMedium::Transfer_Impl() will be forbidden then.
735 if ( xOldObj->IsDocShared() )
736 pNewSet->Put( SfxStringItem( SID_FILE_NAME, xOldObj->GetSharedFileURL() ) );
737 #endif
738 if ( pURLItem )
739 pNewSet->Put( SfxStringItem( SID_REFERER, pMedium->GetName() ) );
740 else
741 pNewSet->Put( SfxStringItem( SID_REFERER, OUString() ) );
743 xOldObj->CancelTransfers();
746 if ( pSilentItem && pSilentItem->GetValue() )
747 pNewSet->Put( SfxBoolItem( SID_SILENT, true ) );
749 const SfxUnoAnyItem* pInteractionItem = SfxItemSet::GetItem<SfxUnoAnyItem>(&*pNewSet, SID_INTERACTIONHANDLER, false);
750 const SfxUInt16Item* pMacroExecItem = SfxItemSet::GetItem<SfxUInt16Item>(&*pNewSet, SID_MACROEXECMODE, false);
751 const SfxUInt16Item* pDocTemplateItem = SfxItemSet::GetItem<SfxUInt16Item>(&*pNewSet, SID_UPDATEDOCMODE, false);
753 if (!pInteractionItem)
755 Reference < task::XInteractionHandler2 > xHdl = task::InteractionHandler::createWithParent( ::comphelper::getProcessComponentContext(), nullptr );
756 if (xHdl.is())
757 pNewSet->Put( SfxUnoAnyItem(SID_INTERACTIONHANDLER,css::uno::makeAny(xHdl)) );
760 if (!pMacroExecItem)
761 pNewSet->Put( SfxUInt16Item(SID_MACROEXECMODE,css::document::MacroExecMode::USE_CONFIG) );
762 if (!pDocTemplateItem)
763 pNewSet->Put( SfxUInt16Item(SID_UPDATEDOCMODE,css::document::UpdateDocMode::ACCORDING_TO_CONFIG) );
765 xOldObj->SetModified( false );
766 // Do not cache the old Document! Is invalid when loading
767 // another document.
769 const SfxStringItem* pSavedOptions = SfxItemSet::GetItem<SfxStringItem>(pMedium->GetItemSet(), SID_FILE_FILTEROPTIONS, false);
770 const SfxStringItem* pSavedReferer = SfxItemSet::GetItem<SfxStringItem>(pMedium->GetItemSet(), SID_REFERER, false);
772 bool bHasStorage = pMedium->HasStorage_Impl();
773 if( bHandsOff )
775 if ( bHasStorage && pMedium->GetStorage() == xOldObj->GetStorage() )
777 // TODO/LATER: faster creation of copy
778 if ( !xOldObj->ConnectTmpStorage_Impl( pMedium->GetStorage(), pMedium ) )
779 return;
782 pMedium->CloseAndRelease();
785 xNewObj = SfxObjectShell::CreateObject( pFilter->GetServiceName() );
787 if ( xOldObj->IsModifyPasswordEntered() )
788 xNewObj->SetModifyPasswordEntered();
790 uno::Sequence < beans::PropertyValue > aLoadArgs;
791 TransformItems( SID_OPENDOC, *pNewSet, aLoadArgs );
794 uno::Reference < frame::XLoadable > xLoad( xNewObj->GetModel(), uno::UNO_QUERY );
795 xLoad->load( aLoadArgs );
797 catch ( uno::Exception& )
799 xNewObj->DoClose();
800 xNewObj = nullptr;
801 pMedium->AddToCheckEditableWorkerList();
804 pNewSet.reset();
806 if( !xNewObj.Is() )
808 if( bHandsOff )
810 // back to old medium
811 pMedium->ReOpen();
812 pMedium->LockOrigFileOnDemand( false, true );
814 xOldObj->DoSaveCompleted( pMedium );
817 // r/o-Doc couldn't be switched to writing mode
818 if ( bForEdit && ( SID_EDITDOC == rReq.GetSlot() || SID_READONLYDOC == rReq.GetSlot() ) )
820 // ask user for opening as template
821 std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(GetWindow().GetFrameWeld(),
822 VclMessageType::Question, VclButtonsType::YesNo,
823 SfxResId(STR_QUERY_OPENASTEMPLATE)));
824 if (RET_YES == xBox->run())
826 SfxAllItemSet aSet( pApp->GetPool() );
827 aSet.Put( SfxStringItem( SID_FILE_NAME, pMedium->GetName() ) );
828 aSet.Put( SfxStringItem( SID_TARGETNAME, "_blank" ) );
829 if ( pSavedOptions )
830 aSet.Put( *pSavedOptions );
831 if ( pSavedReferer )
832 aSet.Put( *pSavedReferer );
833 aSet.Put( SfxBoolItem( SID_TEMPLATE, true ) );
834 if( pFilter )
835 aSet.Put( SfxStringItem( SID_FILTER_NAME, pFilter->GetFilterName() ) );
836 GetDispatcher()->Execute( SID_OPENDOC, SfxCallMode::ASYNCHRON, aSet );
840 else
842 if ( xNewObj->GetModifyPasswordHash() && xNewObj->GetModifyPasswordHash() != xOldObj->GetModifyPasswordHash() )
844 xNewObj->SetModifyPasswordEntered( false );
845 xNewObj->SetReadOnly();
847 else if ( rReq.GetSlot() == SID_EDITDOC || rReq.GetSlot() == SID_READONLYDOC )
849 xNewObj->SetReadOnlyUI( !bForEdit );
852 #if HAVE_FEATURE_MULTIUSER_ENVIRONMENT
853 if ( xNewObj->IsDocShared() )
855 // the file is shared but the closing can change the sharing control file
856 xOldObj->DoNotCleanShareControlFile();
858 #endif
859 // the Reload and Silent items were only temporary, remove them
860 xNewObj->GetMedium()->GetItemSet()->ClearItem( SID_RELOAD );
861 xNewObj->GetMedium()->GetItemSet()->ClearItem( SID_SILENT );
862 TransformItems( SID_OPENDOC, *xNewObj->GetMedium()->GetItemSet(), aLoadArgs );
864 UpdateDocument_Impl();
866 if (vcl::CommandInfoProvider::GetModuleIdentifier(GetFrame().GetFrameInterface()) == "com.sun.star.text.TextDocument")
867 sfx2::SfxNotebookBar::ReloadNotebookBar(u"modules/swriter/ui/");
871 for (auto const& viewFrame : aViewFrames)
873 LoadViewIntoFrame_Impl( *xNewObj, viewFrame.first, aLoadArgs, viewFrame.second, false );
875 aViewFrames.clear();
877 catch( const Exception& )
879 // close the remaining frames
880 // Don't catch exceptions herein, if this fails, then we're left in an indetermined state, and
881 // crashing is better than trying to proceed
882 for (auto const& viewFrame : aViewFrames)
884 Reference< util::XCloseable > xClose( viewFrame.first, UNO_QUERY_THROW );
885 xClose->close( true );
887 aViewFrames.clear();
890 const SfxInt32Item* pPageNumber = rReq.GetArg<SfxInt32Item>(SID_PAGE_NUMBER);
891 if (pPageNumber && pPageNumber->GetValue() >= 0)
893 // Restore current page after reload.
894 uno::Reference<drawing::XDrawView> xController(
895 xNewObj->GetModel()->getCurrentController(), uno::UNO_QUERY);
896 uno::Reference<drawing::XDrawPagesSupplier> xSupplier(xNewObj->GetModel(),
897 uno::UNO_QUERY);
898 uno::Reference<drawing::XDrawPages> xDrawPages = xSupplier->getDrawPages();
899 uno::Reference<drawing::XDrawPage> xDrawPage(
900 xDrawPages->getByIndex(pPageNumber->GetValue()), uno::UNO_QUERY);
901 xController->setCurrentPage(xDrawPage);
904 // Propagate document closure.
905 SfxGetpApp()->NotifyEvent( SfxEventHint( SfxEventHintId::CloseDoc, GlobalEventConfig::GetEventName( GlobalEventId::CLOSEDOC ), xOldObj ) );
908 // Record as done
909 rReq.Done( true );
910 rReq.SetReturnValue(SfxBoolItem(rReq.GetSlot(), true));
911 return;
913 else
915 // Record as not done
916 rReq.Done();
917 rReq.SetReturnValue(SfxBoolItem(rReq.GetSlot(), false));
918 m_pImpl->bReloading = false;
919 return;
925 void SfxViewFrame::StateReload_Impl( SfxItemSet& rSet )
927 SfxObjectShell* pSh = GetObjectShell();
928 if ( !pSh )
930 // I'm just on reload and am yielding myself ...
931 return;
934 SfxWhichIter aIter( rSet );
935 for ( sal_uInt16 nWhich = aIter.FirstWhich(); nWhich; nWhich = aIter.NextWhich() )
937 switch ( nWhich )
939 case SID_EDITDOC:
940 case SID_READONLYDOC:
942 const SfxViewShell *pVSh;
943 const SfxShell *pFSh;
944 if ( !pSh->HasName() ||
945 !( pSh->Get_Impl()->nLoadedFlags & SfxLoadedFlags::MAINDOCUMENT ) ||
946 (pSh->isEditDocLocked()) ||
947 ( pSh->GetCreateMode() == SfxObjectCreateMode::EMBEDDED &&
948 ( !(pVSh = pSh->GetViewShell()) ||
949 !(pFSh = pVSh->GetFormShell()) ||
950 !pFSh->IsDesignMode())))
951 rSet.DisableItem( nWhich );
952 else
954 const SfxBoolItem* pItem = SfxItemSet::GetItem<SfxBoolItem>(pSh->GetMedium()->GetItemSet(), SID_EDITDOC, false);
955 if ( pItem && !pItem->GetValue() )
956 rSet.DisableItem( nWhich );
957 else
959 if (nWhich==SID_EDITDOC)
960 rSet.Put( SfxBoolItem( nWhich, !pSh->IsReadOnly() ) );
961 else if (nWhich==SID_READONLYDOC)
962 rSet.Put( SfxBoolItem( nWhich, pSh->IsReadOnly() ) );
965 break;
968 case SID_RELOAD:
970 if ( !pSh->CanReload_Impl() || pSh->GetCreateMode() == SfxObjectCreateMode::EMBEDDED )
971 rSet.DisableItem(nWhich);
972 else
974 // If any ChildFrame is reloadable, the slot is enabled,
975 // so you can perform CTRL-Reload
976 rSet.Put( SfxBoolItem( nWhich, false));
979 break;
985 void SfxViewFrame::ExecHistory_Impl( SfxRequest &rReq )
987 // Is there an Undo-Manager on the top Shell?
988 SfxShell *pSh = GetDispatcher()->GetShell(0);
989 SfxUndoManager* pShUndoMgr = pSh->GetUndoManager();
990 bool bOK = false;
991 if ( pShUndoMgr )
993 switch ( rReq.GetSlot() )
995 case SID_CLEARHISTORY:
996 pShUndoMgr->Clear();
997 bOK = true;
998 break;
1000 case SID_UNDO:
1001 pShUndoMgr->Undo();
1002 GetBindings().InvalidateAll(false);
1003 bOK = true;
1004 break;
1006 case SID_REDO:
1007 pShUndoMgr->Redo();
1008 GetBindings().InvalidateAll(false);
1009 bOK = true;
1010 break;
1012 case SID_REPEAT:
1013 if ( pSh->GetRepeatTarget() )
1014 pShUndoMgr->Repeat( *pSh->GetRepeatTarget() );
1015 bOK = true;
1016 break;
1019 else if ( GetViewShell() )
1021 // The SW has its own undo in the View
1022 const SfxPoolItem *pRet = GetViewShell()->ExecuteSlot( rReq );
1023 if ( pRet )
1024 bOK = static_cast<const SfxBoolItem*>(pRet)->GetValue();
1027 rReq.SetReturnValue( SfxBoolItem( rReq.GetSlot(), bOK ) );
1028 rReq.Done();
1031 void SfxViewFrame::StateHistory_Impl( SfxItemSet &rSet )
1033 // Search for Undo-Manager
1034 SfxShell *pSh = GetDispatcher()->GetShell(0);
1035 if ( !pSh )
1036 // I'm just on reload and am yielding myself ...
1037 return;
1039 SfxUndoManager *pShUndoMgr = pSh->GetUndoManager();
1040 if ( !pShUndoMgr )
1042 // The SW has its own undo in the View
1043 SfxWhichIter aIter( rSet );
1044 SfxViewShell *pViewSh = GetViewShell();
1045 if( !pViewSh ) return;
1046 for ( sal_uInt16 nSID = aIter.FirstWhich(); nSID; nSID = aIter.NextWhich() )
1047 pViewSh->GetSlotState( nSID, nullptr, &rSet );
1048 return;
1051 if ( pShUndoMgr->GetUndoActionCount() == 0 &&
1052 pShUndoMgr->GetRedoActionCount() == 0 &&
1053 pShUndoMgr->GetRepeatActionCount() == 0 )
1054 rSet.DisableItem( SID_CLEARHISTORY );
1056 if (pShUndoMgr->GetUndoActionCount())
1058 const SfxUndoAction* pAction = pShUndoMgr->GetUndoAction();
1059 SfxViewShell *pViewSh = GetViewShell();
1060 if (pViewSh && pAction->GetViewShellId() != pViewSh->GetViewShellId())
1062 rSet.Put(SfxUInt32Item(SID_UNDO, static_cast<sal_uInt32>(SID_REPAIRPACKAGE)));
1064 else
1066 rSet.Put( SfxStringItem( SID_UNDO, SvtResId(STR_UNDO)+pShUndoMgr->GetUndoActionComment() ) );
1069 else
1070 rSet.DisableItem( SID_UNDO );
1072 if (pShUndoMgr->GetRedoActionCount())
1074 const SfxUndoAction* pAction = pShUndoMgr->GetRedoAction();
1075 SfxViewShell *pViewSh = GetViewShell();
1076 if (pViewSh && pAction->GetViewShellId() != pViewSh->GetViewShellId())
1078 rSet.Put(SfxUInt32Item(SID_REDO, static_cast<sal_uInt32>(SID_REPAIRPACKAGE)));
1080 else
1082 rSet.Put(SfxStringItem(SID_REDO, SvtResId(STR_REDO) + pShUndoMgr->GetRedoActionComment()));
1085 else
1086 rSet.DisableItem( SID_REDO );
1088 SfxRepeatTarget *pTarget = pSh->GetRepeatTarget();
1089 if (pTarget && pShUndoMgr->GetRepeatActionCount() && pShUndoMgr->CanRepeat(*pTarget))
1090 rSet.Put( SfxStringItem( SID_REPEAT, SvtResId(STR_REPEAT)+pShUndoMgr->GetRepeatActionComment(*pTarget) ) );
1091 else
1092 rSet.DisableItem( SID_REPEAT );
1095 void SfxViewFrame::PopShellAndSubShells_Impl( SfxViewShell& i_rViewShell )
1097 i_rViewShell.PopSubShells_Impl();
1098 sal_uInt16 nLevel = m_pDispatcher->GetShellLevel( i_rViewShell );
1099 if ( nLevel != USHRT_MAX )
1101 if ( nLevel )
1103 // more sub shells on the stack, which were not affected by PopSubShells_Impl
1104 SfxShell *pSubShell = m_pDispatcher->GetShell( nLevel-1 );
1105 m_pDispatcher->Pop( *pSubShell, SfxDispatcherPopFlags::POP_UNTIL | SfxDispatcherPopFlags::POP_DELETE );
1107 m_pDispatcher->Pop( i_rViewShell );
1108 m_pDispatcher->Flush();
1113 /* [Description]
1115 This method empties the SfxViewFrame, i.e. takes the <SfxObjectShell>
1116 from the dispatcher and ends its <SfxListener> Relationship to this
1117 SfxObjectShell (by which they may even destroy themselves).
1119 Thus, by invoking ReleaseObjectShell() and SetObjectShell() the
1120 SfxObjectShell can be replaced.
1122 Between ReleaseObjectShell() and SetObjectShell() the control cannot
1123 be handed over to the system.
1125 [Cross-reference]
1127 <SfxViewFrame::SetObjectShell(SfxObjectShell&)>
1129 void SfxViewFrame::ReleaseObjectShell_Impl()
1131 DBG_ASSERT( m_xObjSh.is(), "no SfxObjectShell to release!" );
1133 GetFrame().ReleasingComponent_Impl();
1134 if ( GetWindow().HasChildPathFocus( true ) )
1136 GetWindow().GrabFocus();
1139 SfxViewShell *pDyingViewSh = GetViewShell();
1140 if ( pDyingViewSh )
1142 PopShellAndSubShells_Impl( *pDyingViewSh );
1143 pDyingViewSh->DisconnectAllClients();
1144 SetViewShell_Impl(nullptr);
1145 delete pDyingViewSh;
1147 #ifdef DBG_UTIL
1148 else
1149 OSL_FAIL("No Shell");
1150 #endif
1152 if ( m_xObjSh.is() )
1154 m_pDispatcher->Pop( *m_xObjSh );
1155 SfxModule* pModule = m_xObjSh->GetModule();
1156 if( pModule )
1157 m_pDispatcher->RemoveShell_Impl( *pModule );
1158 m_pDispatcher->Flush();
1159 EndListening( *m_xObjSh );
1161 Notify( *m_xObjSh, SfxHint(SfxHintId::TitleChanged) );
1162 Notify( *m_xObjSh, SfxHint(SfxHintId::DocChanged) );
1164 if ( 1 == m_xObjSh->GetOwnerLockCount() && m_pImpl->bObjLocked && m_xObjSh->GetCreateMode() == SfxObjectCreateMode::EMBEDDED )
1165 m_xObjSh->DoClose();
1166 SfxObjectShellRef xDyingObjSh = m_xObjSh;
1167 m_xObjSh.clear();
1168 if( GetFrame().GetHasTitle() && m_pImpl->nDocViewNo )
1169 xDyingObjSh->GetNoSet_Impl().ReleaseIndex(m_pImpl->nDocViewNo-1);
1170 if ( m_pImpl->bObjLocked )
1172 xDyingObjSh->OwnerLock( false );
1173 m_pImpl->bObjLocked = false;
1177 GetDispatcher()->SetDisableFlags( SfxDisableFlags::NONE );
1180 void SfxViewFrame::Close()
1183 DBG_ASSERT( GetFrame().IsClosing_Impl() || !GetFrame().GetFrameInterface().is(), "ViewFrame closed too early!" );
1185 // If no saving have been made up until now, then embedded Objects should
1186 // not be saved automatically anymore.
1187 if ( GetViewShell() )
1188 GetViewShell()->DisconnectAllClients();
1189 Broadcast( SfxHint( SfxHintId::Dying ) );
1191 if (SfxViewFrame::Current() == this)
1192 SfxViewFrame::SetViewFrame( nullptr );
1194 // Since the Dispatcher is emptied, it can not be used in any reasonable
1195 // manner, thus it is better to let the dispatcher be.
1196 GetDispatcher()->Lock(true);
1197 delete this;
1200 void SfxViewFrame::DoActivate( bool bUI )
1202 m_pDispatcher->DoActivate_Impl( bUI );
1205 void SfxViewFrame::DoDeactivate(bool bUI, SfxViewFrame const * pNewFrame )
1207 m_pDispatcher->DoDeactivate_Impl( bUI, pNewFrame );
1210 void SfxViewFrame::InvalidateBorderImpl( const SfxViewShell* pSh )
1212 if( !pSh || m_nAdjustPosPixelLock )
1213 return;
1215 if ( GetViewShell() && GetWindow().IsVisible() )
1217 if ( GetFrame().IsInPlace() )
1219 return;
1222 DoAdjustPosSizePixel( GetViewShell(), Point(),
1223 GetWindow().GetOutputSizePixel(),
1224 false );
1228 void SfxViewFrame::SetBorderPixelImpl
1230 const SfxViewShell* pVSh,
1231 const SvBorder& rBorder
1235 m_pImpl->aBorder = rBorder;
1237 if ( m_pImpl->bResizeInToOut && !GetFrame().IsInPlace() )
1239 Size aSize = pVSh->GetWindow()->GetOutputSizePixel();
1240 if ( aSize.Width() && aSize.Height() )
1242 aSize.AdjustWidth(rBorder.Left() + rBorder.Right() );
1243 aSize.AdjustHeight(rBorder.Top() + rBorder.Bottom() );
1245 Size aOldSize = GetWindow().GetOutputSizePixel();
1246 GetWindow().SetOutputSizePixel( aSize );
1247 vcl::Window* pParent = &GetWindow();
1248 while ( pParent->GetParent() )
1249 pParent = pParent->GetParent();
1250 Size aOuterSize = pParent->GetOutputSizePixel();
1251 aOuterSize.AdjustWidth( aSize.Width() - aOldSize.Width() );
1252 aOuterSize.AdjustHeight( aSize.Height() - aOldSize.Height() );
1253 pParent->SetOutputSizePixel( aOuterSize );
1256 else
1258 tools::Rectangle aEditArea( Point(), GetWindow().GetOutputSizePixel() );
1259 aEditArea.AdjustLeft(rBorder.Left() );
1260 aEditArea.AdjustRight( -(rBorder.Right()) );
1261 aEditArea.AdjustTop(rBorder.Top() );
1262 aEditArea.AdjustBottom( -(rBorder.Bottom()) );
1263 pVSh->GetWindow()->SetPosSizePixel( aEditArea.TopLeft(), aEditArea.GetSize() );
1267 const SvBorder& SfxViewFrame::GetBorderPixelImpl() const
1269 return m_pImpl->aBorder;
1272 void SfxViewFrame::AppendReadOnlyInfobar()
1274 bool bSignPDF = m_xObjSh->IsSignPDF();
1275 bool bSignWithCert = false;
1276 if (bSignPDF)
1278 SfxObjectShell* pObjectShell = GetObjectShell();
1279 uno::Reference<security::XCertificate> xCertificate = pObjectShell->GetSignPDFCertificate();
1280 bSignWithCert = xCertificate.is();
1283 auto pInfoBar = AppendInfoBar("readonly", "",
1284 SfxResId(bSignPDF ? STR_READONLY_PDF : STR_READONLY_DOCUMENT),
1285 InfobarType::INFO);
1286 if (!pInfoBar)
1287 return;
1289 if (bSignPDF)
1291 // SID_SIGNPDF opened a read-write PDF
1292 // read-only for signing purposes.
1293 weld::Button& rSignButton = pInfoBar->addButton();
1294 if (bSignWithCert)
1296 rSignButton.set_label(SfxResId(STR_READONLY_FINISH_SIGN));
1298 else
1300 rSignButton.set_label(SfxResId(STR_READONLY_SIGN));
1303 rSignButton.connect_clicked(LINK(this, SfxViewFrame, SignDocumentHandler));
1306 bool showEditDocumentButton = true;
1307 if (m_xObjSh->isEditDocLocked())
1308 showEditDocumentButton = false;
1310 if (showEditDocumentButton)
1312 weld::Button& rBtn = pInfoBar->addButton();
1313 rBtn.set_label(SfxResId(STR_READONLY_EDIT));
1314 rBtn.connect_clicked(LINK(this, SfxViewFrame, SwitchReadOnlyHandler));
1318 namespace
1320 css::uno::Reference<css::frame::XLayoutManager> getLayoutManager(const SfxFrame& rFrame)
1322 css::uno::Reference<css::frame::XLayoutManager> xLayoutManager;
1323 css::uno::Reference<css::beans::XPropertySet> xPropSet(rFrame.GetFrameInterface(),
1324 uno::UNO_QUERY);
1325 if (xPropSet.is())
1329 xLayoutManager.set(xPropSet->getPropertyValue("LayoutManager"), uno::UNO_QUERY);
1331 catch (const Exception& e)
1333 SAL_WARN("sfx.view", "Failure getting layout manager: " + e.Message);
1336 return xLayoutManager;
1340 bool SfxApplication::IsHeadlessOrUITest()
1342 if (Application::IsHeadlessModeEnabled())
1343 return true;
1345 bool bIsUITest = false; //uitest.uicheck fails when the dialog is open
1346 for (sal_uInt16 i = 0, nCount = Application::GetCommandLineParamCount(); i < nCount; ++i)
1348 if (Application::GetCommandLineParam(i) == "--nologo")
1350 bIsUITest = true;
1351 break;
1354 return bIsUITest;
1357 bool SfxApplication::IsTipOfTheDayDue()
1359 const bool bShowTipOfTheDay = officecfg::Office::Common::Misc::ShowTipOfTheDay::get();
1360 if (!bShowTipOfTheDay)
1361 return false;
1363 const auto t0 = std::chrono::system_clock::now().time_since_epoch();
1365 // show tip-of-the-day dialog ?
1366 const sal_Int32 nLastTipOfTheDay = officecfg::Office::Common::Misc::LastTipOfTheDayShown::get();
1367 const sal_Int32 nDay = std::chrono::duration_cast<std::chrono::hours>(t0).count()/24; // days since 1970-01-01
1368 return nDay - nLastTipOfTheDay > 0; //only once per day
1371 void SfxViewFrame::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint )
1373 if(m_pImpl->bIsDowning)
1374 return;
1376 // we know only SfxEventHint or simple SfxHint
1377 if (const SfxEventHint* pEventHint = dynamic_cast<const SfxEventHint*>(&rHint))
1379 // When the Document is loaded asynchronously, was the Dispatcher
1380 // set as ReadOnly, to what must be returned when the document itself
1381 // is not read only, and the loading is finished.
1382 switch ( pEventHint->GetEventId() )
1384 case SfxEventHintId::ModifyChanged:
1386 SfxBindings& rBind = GetBindings();
1387 rBind.Invalidate( SID_DOC_MODIFIED );
1388 rBind.Invalidate( SID_RELOAD );
1389 rBind.Invalidate( SID_EDITDOC );
1390 break;
1393 case SfxEventHintId::OpenDoc:
1394 case SfxEventHintId::CreateDoc:
1396 if ( !m_xObjSh.is() )
1397 break;
1399 SfxBindings& rBind = GetBindings();
1400 rBind.Invalidate( SID_RELOAD );
1401 rBind.Invalidate( SID_EDITDOC );
1403 bool bIsHeadlessOrUITest = SfxApplication::IsHeadlessOrUITest(); //uitest.uicheck fails when the dialog is open
1405 //what's new infobar
1406 if (utl::isProductVersionUpgraded(true) && !bIsHeadlessOrUITest)
1408 VclPtr<SfxInfoBarWindow> pInfoBar = AppendInfoBar("whatsnew", "", SfxResId(STR_WHATSNEW_TEXT), InfobarType::INFO);
1409 if (pInfoBar)
1411 weld::Button& rWhatsNewButton = pInfoBar->addButton();
1412 rWhatsNewButton.set_label(SfxResId(STR_WHATSNEW_BUTTON));
1413 rWhatsNewButton.connect_clicked(LINK(this, SfxViewFrame, WhatsNewHandler));
1417 // show tip-of-the-day dialog if it due, but not if there is the impress modal template dialog
1418 // open where SdModule::ExecuteNewDocument will launch it instead when that dialog is dismissed
1419 if (SfxApplication::IsTipOfTheDayDue() && !bIsHeadlessOrUITest && !IsInModalMode())
1421 // tdf#127946 pass in argument for dialog parent
1422 SfxUnoFrameItem aDocFrame(SID_FILLFRAME, GetFrame().GetFrameInterface());
1423 GetDispatcher()->ExecuteList(SID_TIPOFTHEDAY, SfxCallMode::SLOT, {}, { &aDocFrame });
1426 if (officecfg::Office::Common::Passwords::HasMaster::get() &&
1427 officecfg::Office::Common::Passwords::StorageVersion::get() == 0)
1429 // master password stored in deprecated format
1430 VclPtr<SfxInfoBarWindow> pOldMasterPasswordInfoBar =
1431 AppendInfoBar("oldmasterpassword", "",
1432 SfxResId(STR_REFRESH_MASTER_PASSWORD), InfobarType::DANGER, false);
1433 if (pOldMasterPasswordInfoBar)
1435 weld::Button& rButton = pOldMasterPasswordInfoBar->addButton();
1436 rButton.set_label(SfxResId(STR_REFRESH_PASSWORD));
1437 rButton.connect_clicked(LINK(this,
1438 SfxViewFrame, RefreshMasterPasswordHdl));
1442 // read-only infobar if necessary
1443 const SfxViewShell *pVSh;
1444 const SfxShell *pFSh;
1445 if ( m_xObjSh->IsReadOnly() &&
1446 ! m_xObjSh->IsSecurityOptOpenReadOnly() &&
1447 ( m_xObjSh->GetCreateMode() != SfxObjectCreateMode::EMBEDDED ||
1448 (( pVSh = m_xObjSh->GetViewShell()) && (pFSh = pVSh->GetFormShell()) && pFSh->IsDesignMode())))
1450 AppendReadOnlyInfobar();
1453 if (vcl::CommandInfoProvider::GetModuleIdentifier(GetFrame().GetFrameInterface()) == "com.sun.star.text.TextDocument")
1454 sfx2::SfxNotebookBar::ReloadNotebookBar(u"modules/swriter/ui/");
1456 if (SfxClassificationHelper::IsClassified(m_xObjSh->getDocProperties()))
1458 // Document has BAILS properties, display an infobar accordingly.
1459 SfxClassificationHelper aHelper(m_xObjSh->getDocProperties());
1460 aHelper.UpdateInfobar(*this);
1463 // Add pending infobars
1464 std::vector<InfobarData>& aPendingInfobars = m_xObjSh->getPendingInfobars();
1465 while (!aPendingInfobars.empty())
1467 InfobarData& aInfobarData = aPendingInfobars.back();
1469 // don't show Track Changes infobar, if Track Changes toolbar is visible
1470 if (aInfobarData.msId == "hiddentrackchanges")
1472 if (auto xLayoutManager = getLayoutManager(GetFrame()))
1474 if ( xLayoutManager->getElement(CHANGES_STR).is() )
1476 aPendingInfobars.pop_back();
1477 continue;
1482 // Track Changes infobar: add a button to show/hide Track Changes functions
1483 // Hyphenation infobar: add a button to get more information
1484 // tdf#148913 limit VclPtr usage for these
1485 bool bTrackChanges = aInfobarData.msId == "hiddentrackchanges";
1486 if ( bTrackChanges || aInfobarData.msId == "hyphenationmissing" )
1488 VclPtr<SfxInfoBarWindow> pInfoBar =
1489 AppendInfoBar(aInfobarData.msId, aInfobarData.msPrimaryMessage,
1490 aInfobarData.msSecondaryMessage, aInfobarData.maInfobarType,
1491 aInfobarData.mbShowCloseButton);
1493 // tdf#148913 don't extend this condition to keep it thread-safe
1494 if (pInfoBar)
1496 weld::Button& rButton = pInfoBar->addButton();
1497 rButton.set_label(SfxResId(bTrackChanges
1498 ? STR_TRACK_CHANGES_BUTTON
1499 : STR_HYPHENATION_BUTTON));
1500 if (bTrackChanges)
1502 rButton.connect_clicked(LINK(this,
1503 SfxViewFrame, HiddenTrackChangesHandler));
1505 else
1507 rButton.connect_clicked(LINK(this,
1508 SfxViewFrame, HyphenationMissingHandler));
1512 else
1514 AppendInfoBar(aInfobarData.msId, aInfobarData.msPrimaryMessage,
1515 aInfobarData.msSecondaryMessage, aInfobarData.maInfobarType,
1516 aInfobarData.mbShowCloseButton);
1519 aPendingInfobars.pop_back();
1522 break;
1524 default: break;
1527 else
1529 switch( rHint.GetId() )
1531 case SfxHintId::ModeChanged:
1533 UpdateTitle();
1535 if ( !m_xObjSh.is() )
1536 break;
1538 // Switch r/o?
1539 SfxBindings& rBind = GetBindings();
1540 rBind.Invalidate( SID_RELOAD );
1541 SfxDispatcher *pDispat = GetDispatcher();
1542 bool bWasReadOnly = pDispat->GetReadOnly_Impl();
1543 bool bIsReadOnly = m_xObjSh->IsReadOnly();
1544 if ( bWasReadOnly != bIsReadOnly )
1546 // Then also TITLE_CHANGED
1547 UpdateTitle();
1548 rBind.Invalidate( SID_FILE_NAME );
1549 rBind.Invalidate( SID_DOCINFO_TITLE );
1550 rBind.Invalidate( SID_EDITDOC );
1552 pDispat->GetBindings()->InvalidateAll(true);
1553 pDispat->SetReadOnly_Impl( bIsReadOnly );
1555 // Only force and Dispatcher-Update, if it is done next
1556 // anyway, otherwise flickering or GPF is possible since
1557 // the Writer for example prefers in Resize perform some
1558 // actions which has a SetReadOnlyUI in Dispatcher as a
1559 // result!
1561 if ( pDispat->IsUpdated_Impl() )
1562 pDispat->Update_Impl(true);
1565 Enable( !m_xObjSh->IsInModalMode() );
1566 break;
1569 case SfxHintId::TitleChanged:
1571 UpdateTitle();
1572 SfxBindings& rBind = GetBindings();
1573 rBind.Invalidate( SID_FILE_NAME );
1574 rBind.Invalidate( SID_DOCINFO_TITLE );
1575 rBind.Invalidate( SID_EDITDOC );
1576 rBind.Invalidate( SID_RELOAD );
1577 break;
1580 case SfxHintId::DocumentRepair:
1582 GetBindings().Invalidate( SID_DOC_REPAIR );
1583 break;
1586 case SfxHintId::Deinitializing:
1588 vcl::Window* pFrameWin = GetWindow().GetFrameWindow();
1589 if (pFrameWin && pFrameWin->GetLOKNotifier())
1590 pFrameWin->ReleaseLOKNotifier();
1592 GetFrame().DoClose();
1593 break;
1595 case SfxHintId::Dying:
1596 // when the Object is being deleted, destroy the view too
1597 if ( m_xObjSh.is() )
1598 ReleaseObjectShell_Impl();
1599 else
1600 GetFrame().DoClose();
1601 break;
1602 default: break;
1607 IMPL_LINK_NOARG(SfxViewFrame, WhatsNewHandler, weld::Button&, void)
1609 GetDispatcher()->Execute(SID_WHATSNEW);
1612 IMPL_LINK_NOARG(SfxViewFrame, GetInvolvedHandler, weld::Button&, void)
1614 GetDispatcher()->Execute(SID_GETINVOLVED);
1617 IMPL_LINK_NOARG(SfxViewFrame, DonationHandler, weld::Button&, void)
1619 GetDispatcher()->Execute(SID_DONATION);
1622 IMPL_LINK(SfxViewFrame, SwitchReadOnlyHandler, weld::Button&, rButton, void)
1624 if (m_xObjSh.is() && m_xObjSh->IsSignPDF())
1626 SfxEditDocumentDialog aDialog(&rButton);
1627 if (aDialog.run() != RET_OK)
1628 return;
1630 GetDispatcher()->Execute(SID_EDITDOC);
1633 IMPL_LINK_NOARG(SfxViewFrame, SignDocumentHandler, weld::Button&, void)
1635 GetDispatcher()->Execute(SID_SIGNATURE);
1638 IMPL_LINK(SfxViewFrame, HiddenTrackChangesHandler, weld::Button&, rButton, void)
1640 // enable Track Changes toolbar, if it is disabled.
1641 // Otherwise disable the toolbar, and close the infobar
1642 auto xLayoutManager = getLayoutManager(GetFrame());
1643 if (!xLayoutManager)
1644 return;
1646 if (!xLayoutManager->getElement(CHANGES_STR).is())
1648 xLayoutManager->createElement(CHANGES_STR);
1649 xLayoutManager->showElement(CHANGES_STR);
1650 rButton.set_label(SfxResId(STR_TRACK_CHANGES_BUTTON_HIDE));
1652 else
1654 xLayoutManager->hideElement(CHANGES_STR);
1655 xLayoutManager->destroyElement(CHANGES_STR);
1656 RemoveInfoBar(u"hiddentrackchanges");
1660 IMPL_LINK_NOARG(SfxViewFrame, HyphenationMissingHandler, weld::Button&, void)
1662 GetDispatcher()->Execute(SID_HYPHENATIONMISSING);
1663 RemoveInfoBar(u"hyphenationmissing");
1666 IMPL_LINK_NOARG(SfxViewFrame, RefreshMasterPasswordHdl, weld::Button&, void)
1668 bool bChanged = false;
1671 Reference< task::XPasswordContainer2 > xMasterPasswd(
1672 task::PasswordContainer::create(comphelper::getProcessComponentContext()));
1674 css::uno::Reference<css::frame::XFrame> xFrame = GetFrame().GetFrameInterface();
1675 css::uno::Reference<css::awt::XWindow> xContainerWindow = xFrame->getContainerWindow();
1677 uno::Reference<task::XInteractionHandler> xTmpHandler(task::InteractionHandler::createWithParent(comphelper::getProcessComponentContext(),
1678 xContainerWindow));
1679 bChanged = xMasterPasswd->changeMasterPassword(xTmpHandler);
1681 catch (const Exception&)
1683 if (bChanged)
1684 RemoveInfoBar(u"oldmasterpassword");
1687 void SfxViewFrame::Construct_Impl( SfxObjectShell *pObjSh )
1689 m_pImpl->bResizeInToOut = true;
1690 m_pImpl->bObjLocked = false;
1691 m_pImpl->nCurViewId = SFX_INTERFACE_NONE;
1692 m_pImpl->bReloading = false;
1693 m_pImpl->bIsDowning = false;
1694 m_pImpl->bModal = false;
1695 m_pImpl->bEnabled = true;
1696 m_pImpl->nDocViewNo = 0;
1697 m_pImpl->aMargin = Size( -1, -1 );
1698 m_pImpl->pWindow = nullptr;
1700 SetPool( &SfxGetpApp()->GetPool() );
1701 m_pDispatcher.reset( new SfxDispatcher(this) );
1702 if ( !GetBindings().GetDispatcher() )
1703 GetBindings().SetDispatcher( m_pDispatcher.get() );
1705 m_xObjSh = pObjSh;
1706 if ( m_xObjSh.is() && m_xObjSh->IsPreview() )
1707 GetDispatcher()->SetQuietMode_Impl( true );
1709 if ( pObjSh )
1711 m_pDispatcher->Push( *SfxGetpApp() );
1712 SfxModule* pModule = m_xObjSh->GetModule();
1713 if( pModule )
1714 m_pDispatcher->Push( *pModule );
1715 m_pDispatcher->Push( *this );
1716 m_pDispatcher->Push( *pObjSh );
1717 m_pDispatcher->Flush();
1718 StartListening( *pObjSh );
1719 Notify( *pObjSh, SfxHint(SfxHintId::TitleChanged) );
1720 Notify( *pObjSh, SfxHint(SfxHintId::DocChanged) );
1721 m_pDispatcher->SetReadOnly_Impl( pObjSh->IsReadOnly() );
1723 else
1725 m_pDispatcher->Push( *SfxGetpApp() );
1726 m_pDispatcher->Push( *this );
1727 m_pDispatcher->Flush();
1730 SfxGetpApp()->GetViewFrames_Impl().push_back(this);
1733 /* [Description]
1735 Constructor of SfxViewFrame for a <SfxObjectShell> from the Resource.
1736 The 'nViewId' to the created <SfxViewShell> can be returned.
1737 (default is the SfxViewShell-Subclass that was registered first).
1739 SfxViewFrame::SfxViewFrame
1741 SfxFrame& rFrame,
1742 SfxObjectShell* pObjShell
1744 : m_pImpl( new SfxViewFrame_Impl( rFrame ) )
1745 , m_pBindings( new SfxBindings )
1746 , m_pHelpData(CreateSVHelpData())
1747 , m_pWinData(CreateSVWinData())
1748 , m_nAdjustPosPixelLock( 0 )
1749 , m_pCommandPopupHandler(new CommandPopupHandler)
1752 rFrame.SetCurrentViewFrame_Impl( this );
1753 rFrame.SetHasTitle( true );
1754 Construct_Impl( pObjShell );
1756 m_pImpl->pWindow = VclPtr<SfxFrameViewWindow_Impl>::Create( this, rFrame.GetWindow() );
1757 m_pImpl->pWindow->SetSizePixel( rFrame.GetWindow().GetOutputSizePixel() );
1758 rFrame.SetOwnsBindings_Impl( true );
1759 rFrame.CreateWorkWindow_Impl();
1762 SfxViewFrame::~SfxViewFrame()
1764 m_pImpl->bIsDowning = true;
1766 if ( SfxViewFrame::Current() == this )
1767 SfxViewFrame::SetViewFrame( nullptr );
1769 ReleaseObjectShell_Impl();
1771 if ( GetFrame().OwnsBindings_Impl() )
1772 // The Bindings delete the Frame!
1773 KillDispatcher_Impl();
1775 m_pImpl->pWindow.disposeAndClear();
1777 if ( GetFrame().GetCurrentViewFrame() == this )
1778 GetFrame().SetCurrentViewFrame_Impl( nullptr );
1780 // Unregister from the Frame List.
1781 SfxApplication *pSfxApp = SfxApplication::Get();
1782 if (pSfxApp)
1784 auto &rFrames = pSfxApp->GetViewFrames_Impl();
1785 auto it = std::find( rFrames.begin(), rFrames.end(), this );
1786 rFrames.erase( it );
1789 // Delete Member
1790 KillDispatcher_Impl();
1792 DestroySVHelpData(m_pHelpData);
1793 m_pHelpData = nullptr;
1795 DestroySVWinData(m_pWinData);
1796 m_pWinData = nullptr;
1799 // Remove and delete the Dispatcher.
1800 void SfxViewFrame::KillDispatcher_Impl()
1803 SfxModule* pModule = m_xObjSh.is() ? m_xObjSh->GetModule() : nullptr;
1804 if ( m_xObjSh.is() )
1805 ReleaseObjectShell_Impl();
1806 if ( m_pDispatcher )
1808 if( pModule )
1809 m_pDispatcher->Pop( *pModule, SfxDispatcherPopFlags::POP_UNTIL );
1810 else
1811 m_pDispatcher->Pop( *this );
1812 m_pDispatcher.reset();
1816 SfxViewFrame* SfxViewFrame::Current()
1818 SfxApplication* pApp = SfxApplication::Get();
1819 return pApp ? pApp->Get_Impl()->pViewFrame : nullptr;
1822 // returns the first window of spec. type viewing the specified doc.
1823 SfxViewFrame* SfxViewFrame::GetFirst
1825 const SfxObjectShell* pDoc,
1826 bool bOnlyIfVisible
1829 SfxApplication *pSfxApp = SfxApplication::Get();
1830 if (!pSfxApp)
1831 return nullptr;
1833 // search for a SfxDocument of the specified type
1834 for (SfxViewFrame* pFrame : pSfxApp->GetViewFrames_Impl())
1836 if ( ( !pDoc || pDoc == pFrame->GetObjectShell() )
1837 && ( !bOnlyIfVisible || pFrame->IsVisible() )
1839 return pFrame;
1842 return nullptr;
1845 // returns the next window of spec. type viewing the specified doc.
1846 SfxViewFrame* SfxViewFrame::GetNext
1848 const SfxViewFrame& rPrev,
1849 const SfxObjectShell* pDoc,
1850 bool bOnlyIfVisible
1853 SfxApplication *pSfxApp = SfxApplication::Get();
1854 if (!pSfxApp)
1855 return nullptr;
1857 auto &rFrames = pSfxApp->GetViewFrames_Impl();
1859 // refind the specified predecessor
1860 size_t nPos;
1861 for ( nPos = 0; nPos < rFrames.size(); ++nPos )
1862 if ( rFrames[nPos] == &rPrev )
1863 break;
1865 // search for a Frame of the specified type
1866 for ( ++nPos; nPos < rFrames.size(); ++nPos )
1868 SfxViewFrame *pFrame = rFrames[nPos];
1869 if ( ( !pDoc || pDoc == pFrame->GetObjectShell() )
1870 && ( !bOnlyIfVisible || pFrame->IsVisible() )
1872 return pFrame;
1874 return nullptr;
1877 SfxProgress* SfxViewFrame::GetProgress() const
1879 SfxObjectShell *pObjSh = m_xObjSh.get();
1880 return pObjSh ? pObjSh->GetProgress() : nullptr;
1883 void SfxViewFrame::DoAdjustPosSizePixel //! divide on Inner.../Outer...
1885 SfxViewShell* pSh,
1886 const Point& rPos,
1887 const Size& rSize,
1888 bool inplaceEditModeChange
1892 // Components do not use this Method!
1893 if( pSh && pSh->GetWindow() && !m_nAdjustPosPixelLock )
1895 m_nAdjustPosPixelLock++;
1896 if ( m_pImpl->bResizeInToOut )
1897 pSh->InnerResizePixel( rPos, rSize, inplaceEditModeChange );
1898 else
1899 pSh->OuterResizePixel( rPos, rSize );
1900 m_nAdjustPosPixelLock--;
1904 bool SfxViewFrameItem::operator==( const SfxPoolItem &rItem ) const
1906 return SfxPoolItem::operator==(rItem) &&
1907 static_cast<const SfxViewFrameItem&>(rItem).pFrame == pFrame;
1910 SfxViewFrameItem* SfxViewFrameItem::Clone( SfxItemPool *) const
1912 return new SfxViewFrameItem( *this );
1915 void SfxViewFrame::SetViewShell_Impl( SfxViewShell *pVSh )
1916 /* [Description]
1918 Internal Method to set the current <SfxViewShell> Instance,
1919 that is active int this SfxViewFrame at the moment.
1922 SfxShell::SetViewShell_Impl( pVSh );
1924 // Hack: InPlaceMode
1925 if ( pVSh )
1926 m_pImpl->bResizeInToOut = false;
1929 void SfxViewFrame::ForceOuterResize_Impl()
1931 m_pImpl->bResizeInToOut = true;
1934 void SfxViewFrame::GetDocNumber_Impl()
1936 DBG_ASSERT( GetObjectShell(), "No Document!" );
1937 GetObjectShell()->SetNamedVisibility_Impl();
1938 m_pImpl->nDocViewNo = GetObjectShell()->GetNoSet_Impl().GetFreeIndex()+1;
1941 void SfxViewFrame::Enable( bool bEnable )
1943 if ( bEnable == m_pImpl->bEnabled )
1944 return;
1946 m_pImpl->bEnabled = bEnable;
1948 vcl::Window *pWindow = &GetFrame().GetWindow();
1949 if ( !bEnable )
1950 m_pImpl->bWindowWasEnabled = pWindow->IsInputEnabled();
1951 if ( !bEnable || m_pImpl->bWindowWasEnabled )
1952 pWindow->EnableInput( bEnable );
1954 // cursor and focus
1955 SfxViewShell* pViewSh = GetViewShell();
1956 if ( bEnable )
1958 // show cursor
1959 if ( pViewSh )
1960 pViewSh->ShowCursor();
1962 else
1964 // hide cursor
1965 if ( pViewSh )
1966 pViewSh->ShowCursor(false);
1970 /* [Description]
1972 This method makes the Frame-Window visible and before transmits the
1973 window name. In addition, the document is held. In general one can never
1974 show the window directly!
1976 void SfxViewFrame::Show()
1978 // First lock the objectShell so that UpdateTitle() is valid:
1979 // IsVisible() == true (:#)
1980 if ( m_xObjSh.is() )
1982 m_xObjSh->GetMedium()->GetItemSet()->ClearItem( SID_HIDDEN );
1983 if ( !m_pImpl->bObjLocked )
1984 LockObjectShell_Impl();
1986 // Adjust Doc-Shell title number, get unique view-no
1987 if ( 0 == m_pImpl->nDocViewNo )
1989 GetDocNumber_Impl();
1990 UpdateTitle();
1993 else
1994 UpdateTitle();
1996 // Display Frame-window, but only if the ViewFrame has no window of its
1997 // own or if it does not contain a Component
1998 GetWindow().Show();
1999 GetFrame().GetWindow().Show();
2003 bool SfxViewFrame::IsVisible() const
2005 return m_pImpl->bObjLocked;
2009 void SfxViewFrame::LockObjectShell_Impl()
2011 DBG_ASSERT( !m_pImpl->bObjLocked, "Wrong Locked status!" );
2013 DBG_ASSERT( GetObjectShell(), "No Document!" );
2014 GetObjectShell()->OwnerLock(true);
2015 m_pImpl->bObjLocked = true;
2019 void SfxViewFrame::MakeActive_Impl( bool bGrabFocus )
2021 if ( !GetViewShell() || GetFrame().IsClosing_Impl() )
2022 return;
2024 if ( !IsVisible() )
2025 return;
2027 bool bPreview = false;
2028 if (GetObjectShell()->IsPreview())
2030 bPreview = true;
2033 css::uno::Reference<css::frame::XFrame> xFrame = GetFrame().GetFrameInterface();
2034 if (!bPreview)
2036 SetViewFrame(this);
2037 GetBindings().SetActiveFrame(css::uno::Reference<css::frame::XFrame>());
2038 uno::Reference<frame::XFramesSupplier> xSupp(xFrame, uno::UNO_QUERY);
2039 if (xSupp.is())
2040 xSupp->setActiveFrame(uno::Reference<frame::XFrame>());
2042 css::uno::Reference< css::awt::XWindow > xContainerWindow = xFrame->getContainerWindow();
2043 VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow(xContainerWindow);
2044 if (pWindow && pWindow->HasChildPathFocus() && bGrabFocus)
2046 SfxInPlaceClient *pCli = GetViewShell()->GetUIActiveClient();
2047 if (!pCli || !pCli->IsObjectUIActive())
2048 GetFrame().GrabFocusOnComponent_Impl();
2051 else
2053 GetBindings().SetDispatcher(GetDispatcher());
2054 GetBindings().SetActiveFrame(css::uno::Reference<css::frame::XFrame>());
2055 GetDispatcher()->Update_Impl();
2059 SfxObjectShell* SfxViewFrame::GetObjectShell()
2061 return m_xObjSh.get();
2064 const Size& SfxViewFrame::GetMargin_Impl() const
2066 return m_pImpl->aMargin;
2069 SfxViewFrame* SfxViewFrame::LoadViewIntoFrame_Impl_NoThrow( const SfxObjectShell& i_rDoc, const Reference< XFrame >& i_rFrame,
2070 const SfxInterfaceId i_nViewId, const bool i_bHidden )
2072 Reference< XFrame > xFrame( i_rFrame );
2073 bool bOwnFrame = false;
2074 SfxViewShell* pSuccessView = nullptr;
2077 if ( !xFrame.is() )
2079 Reference < XDesktop2 > xDesktop = Desktop::create( ::comphelper::getProcessComponentContext() );
2081 if ( !i_bHidden )
2085 // if there is a backing component, use it
2086 ::framework::FrameListAnalyzer aAnalyzer( xDesktop, Reference< XFrame >(), FrameAnalyzerFlags::BackingComponent );
2088 if ( aAnalyzer.m_xBackingComponent.is() )
2089 xFrame = aAnalyzer.m_xBackingComponent;
2091 catch( uno::Exception& )
2095 if ( !xFrame.is() )
2096 xFrame.set( xDesktop->findFrame( "_blank", 0 ), UNO_SET_THROW );
2098 bOwnFrame = true;
2101 pSuccessView = LoadViewIntoFrame_Impl(
2102 i_rDoc,
2103 xFrame,
2104 Sequence< PropertyValue >(), // means "reuse existing model's args"
2105 i_nViewId,
2106 i_bHidden
2109 if ( bOwnFrame && !i_bHidden )
2111 // ensure the frame/window is visible
2112 Reference< XWindow > xContainerWindow( xFrame->getContainerWindow(), UNO_SET_THROW );
2113 xContainerWindow->setVisible( true );
2116 catch( const Exception& )
2118 DBG_UNHANDLED_EXCEPTION("sfx.view");
2121 if ( pSuccessView )
2122 return pSuccessView->GetViewFrame();
2124 if ( bOwnFrame )
2128 xFrame->dispose();
2130 catch( const Exception& )
2132 DBG_UNHANDLED_EXCEPTION("sfx.view");
2136 return nullptr;
2139 SfxViewShell* SfxViewFrame::LoadViewIntoFrame_Impl( const SfxObjectShell& i_rDoc, const Reference< XFrame >& i_rFrame,
2140 const Sequence< PropertyValue >& i_rLoadArgs, const SfxInterfaceId i_nViewId,
2141 const bool i_bHidden )
2143 Reference< XModel > xDocument( i_rDoc.GetModel(), UNO_SET_THROW );
2145 ::comphelper::NamedValueCollection aTransformLoadArgs( i_rLoadArgs.hasElements() ? i_rLoadArgs : xDocument->getArgs() );
2146 aTransformLoadArgs.put( "Model", xDocument );
2147 if ( i_nViewId )
2148 aTransformLoadArgs.put( "ViewId", sal_uInt16( i_nViewId ) );
2149 if ( i_bHidden )
2150 aTransformLoadArgs.put( "Hidden", i_bHidden );
2151 else
2152 aTransformLoadArgs.remove( "Hidden" );
2154 Reference< XComponentLoader > xLoader( i_rFrame, UNO_QUERY_THROW );
2155 xLoader->loadComponentFromURL( "private:object", "_self", 0,
2156 aTransformLoadArgs.getPropertyValues() );
2158 SfxViewShell* pViewShell = SfxViewShell::Get( i_rFrame->getController() );
2159 ENSURE_OR_THROW( pViewShell,
2160 "SfxViewFrame::LoadViewIntoFrame_Impl: loading an SFX doc into a frame resulted in a non-SFX view - quite impossible" );
2161 return pViewShell;
2164 SfxViewFrame* SfxViewFrame::LoadHiddenDocument( SfxObjectShell const & i_rDoc, SfxInterfaceId i_nViewId )
2166 return LoadViewIntoFrame_Impl_NoThrow( i_rDoc, Reference< XFrame >(), i_nViewId, true );
2169 SfxViewFrame* SfxViewFrame::LoadDocument( SfxObjectShell const & i_rDoc, SfxInterfaceId i_nViewId )
2171 return LoadViewIntoFrame_Impl_NoThrow( i_rDoc, Reference< XFrame >(), i_nViewId, false );
2174 SfxViewFrame* SfxViewFrame::LoadDocumentIntoFrame( SfxObjectShell const & i_rDoc, const Reference< XFrame >& i_rTargetFrame )
2176 return LoadViewIntoFrame_Impl_NoThrow( i_rDoc, i_rTargetFrame, SFX_INTERFACE_NONE, false );
2179 SfxViewFrame* SfxViewFrame::LoadDocumentIntoFrame( SfxObjectShell const & i_rDoc, const SfxFrameItem* i_pFrameItem, SfxInterfaceId i_nViewId )
2181 return LoadViewIntoFrame_Impl_NoThrow( i_rDoc, i_pFrameItem && i_pFrameItem->GetFrame() ? i_pFrameItem->GetFrame()->GetFrameInterface() : nullptr, i_nViewId, false );
2184 SfxViewFrame* SfxViewFrame::DisplayNewDocument( SfxObjectShell const & i_rDoc, const SfxRequest& i_rCreateDocRequest )
2186 const SfxUnoFrameItem* pFrameItem = i_rCreateDocRequest.GetArg<SfxUnoFrameItem>(SID_FILLFRAME);
2187 const SfxBoolItem* pHiddenItem = i_rCreateDocRequest.GetArg<SfxBoolItem>(SID_HIDDEN);
2189 return LoadViewIntoFrame_Impl_NoThrow(
2190 i_rDoc,
2191 pFrameItem ? pFrameItem->GetFrame() : nullptr,
2192 SFX_INTERFACE_NONE,
2193 pHiddenItem && pHiddenItem->GetValue()
2197 SfxViewFrame* SfxViewFrame::Get( const Reference< XController>& i_rController, const SfxObjectShell* i_pDoc )
2199 if ( !i_rController.is() )
2200 return nullptr;
2202 const SfxObjectShell* pDoc = i_pDoc;
2203 if ( !pDoc )
2205 Reference< XModel > xDocument( i_rController->getModel() );
2206 for ( pDoc = SfxObjectShell::GetFirst( nullptr, false );
2207 pDoc;
2208 pDoc = SfxObjectShell::GetNext( *pDoc, nullptr, false )
2211 if ( pDoc->GetModel() == xDocument )
2212 break;
2216 SfxViewFrame* pViewFrame = nullptr;
2217 for ( pViewFrame = SfxViewFrame::GetFirst( pDoc, false );
2218 pViewFrame;
2219 pViewFrame = SfxViewFrame::GetNext( *pViewFrame, pDoc, false )
2222 if ( pViewFrame->GetViewShell()->GetController() == i_rController )
2223 break;
2226 return pViewFrame;
2229 void SfxViewFrame::SaveCurrentViewData_Impl( const SfxInterfaceId i_nNewViewId )
2231 SfxViewShell* pCurrentShell = GetViewShell();
2232 ENSURE_OR_RETURN_VOID( pCurrentShell != nullptr, "SfxViewFrame::SaveCurrentViewData_Impl: no current view shell -> no current view data!" );
2234 // determine the logical (API) view name
2235 const SfxObjectFactory& rDocFactory( pCurrentShell->GetObjectShell()->GetFactory() );
2236 const sal_uInt16 nCurViewNo = rDocFactory.GetViewNo_Impl( GetCurViewId(), 0 );
2237 const OUString sCurrentViewName = rDocFactory.GetViewFactory( nCurViewNo ).GetAPIViewName();
2238 const sal_uInt16 nNewViewNo = rDocFactory.GetViewNo_Impl( i_nNewViewId, 0 );
2239 const OUString sNewViewName = rDocFactory.GetViewFactory( nNewViewNo ).GetAPIViewName();
2240 if ( sCurrentViewName.isEmpty() || sNewViewName.isEmpty() )
2242 // can't say anything about the view, the respective application did not yet migrate its code to
2243 // named view factories => bail out
2244 OSL_FAIL( "SfxViewFrame::SaveCurrentViewData_Impl: views without API names? Shouldn't happen anymore?" );
2245 return;
2247 SAL_WARN_IF(sNewViewName == sCurrentViewName, "sfx.view", "SfxViewFrame::SaveCurrentViewData_Impl: suspicious: new and old view name are identical!");
2249 // save the view data only when we're moving from a non-print-preview to the print-preview view
2250 if ( sNewViewName != "PrintPreview" )
2251 return;
2253 // retrieve the view data from the view
2254 Sequence< PropertyValue > aViewData;
2255 pCurrentShell->WriteUserDataSequence( aViewData );
2259 // retrieve view data (for *all* views) from the model
2260 const Reference< XController > xController( pCurrentShell->GetController(), UNO_SET_THROW );
2261 const Reference< XViewDataSupplier > xViewDataSupplier( xController->getModel(), UNO_QUERY_THROW );
2262 const Reference< XIndexContainer > xViewData( xViewDataSupplier->getViewData(), UNO_QUERY_THROW );
2264 // look up the one view data item which corresponds to our current view, and remove it
2265 const sal_Int32 nCount = xViewData->getCount();
2266 for ( sal_Int32 i=0; i<nCount; ++i )
2268 const ::comphelper::NamedValueCollection aCurViewData( xViewData->getByIndex(i) );
2269 const OUString sViewId( aCurViewData.getOrDefault( "ViewId", OUString() ) );
2270 if ( sViewId.isEmpty() )
2271 continue;
2273 const SfxViewFactory* pViewFactory = rDocFactory.GetViewFactoryByViewName( sViewId );
2274 if ( pViewFactory == nullptr )
2275 continue;
2277 if ( pViewFactory->GetOrdinal() == GetCurViewId() )
2279 xViewData->removeByIndex(i);
2280 break;
2284 // then replace it with the most recent view data we just obtained
2285 xViewData->insertByIndex( 0, makeAny( aViewData ) );
2287 catch( const Exception& )
2289 DBG_UNHANDLED_EXCEPTION("sfx.view");
2293 /* [Description]
2295 Internal Method for switching to another <SfxViewShell> subclass,
2296 which should be created in this SfxMDIFrame. If no SfxViewShell exist
2297 in this SfxMDIFrame, then one will first be created.
2300 [Return Value]
2302 bool true
2303 requested SfxViewShell was created and a
2304 possibly existing one deleted
2306 false
2307 SfxViewShell requested could not be created,
2308 the existing SfxViewShell thus continue to exist
2310 bool SfxViewFrame::SwitchToViewShell_Impl
2312 sal_uInt16 nViewIdOrNo, /* > 0
2313 Registration-Id of the View, to which the
2314 method should switch, for example the one
2315 that will be created.
2317 == 0
2318 First use the Default view. */
2320 bool bIsIndex /* true
2321 'nViewIdOrNo' is no Registration-Id instead
2322 an Index of <SfxViewFrame> in <SfxObjectShell>.
2328 ENSURE_OR_THROW( GetObjectShell() != nullptr, "not possible without a document" );
2330 // if we already have a view shell, remove it
2331 SfxViewShell* pOldSh = GetViewShell();
2332 OSL_PRECOND( pOldSh, "SfxViewFrame::SwitchToViewShell_Impl: that's called *switch* (not for *initial-load*) for a reason" );
2333 if ( pOldSh )
2335 // ask whether it can be closed
2336 if ( !pOldSh->PrepareClose() )
2337 return false;
2339 // remove sub shells from Dispatcher before switching to new ViewShell
2340 PopShellAndSubShells_Impl( *pOldSh );
2343 GetBindings().ENTERREGISTRATIONS();
2344 LockAdjustPosSizePixel();
2346 // ID of the new view
2347 SfxObjectFactory& rDocFact = GetObjectShell()->GetFactory();
2348 const SfxInterfaceId nViewId = ( bIsIndex || !nViewIdOrNo ) ? rDocFact.GetViewFactory( nViewIdOrNo ).GetOrdinal() : SfxInterfaceId(nViewIdOrNo);
2350 // save the view data of the old view, so it can be restored later on (when needed)
2351 SaveCurrentViewData_Impl( nViewId );
2353 // create and load new ViewShell
2354 SfxViewShell* pNewSh = LoadViewIntoFrame_Impl(
2355 *GetObjectShell(),
2356 GetFrame().GetFrameInterface(),
2357 Sequence< PropertyValue >(), // means "reuse existing model's args"
2358 nViewId,
2359 false
2362 // allow resize events to be processed
2363 UnlockAdjustPosSizePixel();
2365 if ( GetWindow().IsReallyVisible() )
2366 DoAdjustPosSizePixel( pNewSh, Point(), GetWindow().GetOutputSizePixel(), false );
2368 GetBindings().LEAVEREGISTRATIONS();
2369 delete pOldSh;
2371 catch ( const css::uno::Exception& )
2373 // the SfxCode is not able to cope with exceptions thrown while creating views
2374 // the code will crash in the stack unwinding procedure, so we shouldn't let exceptions go through here
2375 DBG_UNHANDLED_EXCEPTION("sfx.view");
2376 return false;
2379 DBG_ASSERT( SfxGetpApp()->GetViewFrames_Impl().size() == SfxGetpApp()->GetViewShells_Impl().size(), "Inconsistent view arrays!" );
2380 return true;
2383 void SfxViewFrame::SetCurViewId_Impl( const SfxInterfaceId i_nID )
2385 m_pImpl->nCurViewId = i_nID;
2388 SfxInterfaceId SfxViewFrame::GetCurViewId() const
2390 return m_pImpl->nCurViewId;
2393 /* [Description]
2395 Internal method to run the slot for the <SfxShell> Subclass in the
2396 SfxViewFrame <SVIDL> described slots.
2398 void SfxViewFrame::ExecView_Impl
2400 SfxRequest& rReq // The executable <SfxRequest>
2404 // If the Shells are just being replaced...
2405 if ( !GetObjectShell() || !GetViewShell() )
2406 return;
2408 switch ( rReq.GetSlot() )
2410 case SID_TERMINATE_INPLACEACTIVATION :
2412 SfxInPlaceClient* pClient = GetViewShell()->GetUIActiveClient();
2413 if ( pClient )
2414 pClient->DeactivateObject();
2415 break;
2418 case SID_VIEWSHELL:
2420 const SfxPoolItem *pItem = nullptr;
2421 if ( rReq.GetArgs()
2422 && SfxItemState::SET == rReq.GetArgs()->GetItemState( SID_VIEWSHELL, false, &pItem )
2425 const sal_uInt16 nViewId = static_cast< const SfxUInt16Item* >( pItem )->GetValue();
2426 bool bSuccess = SwitchToViewShell_Impl( nViewId );
2427 rReq.SetReturnValue( SfxBoolItem( 0, bSuccess ) );
2429 break;
2432 case SID_VIEWSHELL0:
2433 case SID_VIEWSHELL1:
2434 case SID_VIEWSHELL2:
2435 case SID_VIEWSHELL3:
2436 case SID_VIEWSHELL4:
2438 const sal_uInt16 nViewNo = rReq.GetSlot() - SID_VIEWSHELL0;
2439 bool bSuccess = SwitchToViewShell_Impl( nViewNo, true );
2440 rReq.SetReturnValue( SfxBoolItem( 0, bSuccess ) );
2441 break;
2444 case SID_NEWWINDOW:
2446 // Hack. at the moment a virtual Function
2447 if ( !GetViewShell()->NewWindowAllowed() )
2449 OSL_FAIL( "You should have disabled the 'Window/New Window' slot!" );
2450 return;
2453 // Get ViewData of FrameSets recursively.
2454 GetFrame().GetViewData_Impl();
2455 SfxMedium* pMed = GetObjectShell()->GetMedium();
2457 // do not open the new window hidden
2458 pMed->GetItemSet()->ClearItem( SID_HIDDEN );
2460 // the view ID (optional arg. TODO: this is currently not supported in the slot definition ...)
2461 const SfxUInt16Item* pViewIdItem = rReq.GetArg<SfxUInt16Item>(SID_VIEW_ID);
2462 const SfxInterfaceId nViewId = pViewIdItem ? SfxInterfaceId(pViewIdItem->GetValue()) : GetCurViewId();
2464 Reference < XFrame > xFrame;
2465 // the frame (optional arg. TODO: this is currently not supported in the slot definition ...)
2466 const SfxUnoFrameItem* pFrameItem = rReq.GetArg<SfxUnoFrameItem>(SID_FILLFRAME);
2467 if ( pFrameItem )
2468 xFrame = pFrameItem->GetFrame();
2470 LoadViewIntoFrame_Impl_NoThrow( *GetObjectShell(), xFrame, nViewId, false );
2472 rReq.Done();
2473 break;
2476 case SID_OBJECT:
2478 const SfxInt16Item* pItem = rReq.GetArg<SfxInt16Item>(SID_OBJECT);
2480 if (pItem)
2482 GetViewShell()->DoVerb( pItem->GetValue() );
2483 rReq.Done();
2484 break;
2490 /* TODO as96863:
2491 This method try to collect information about the count of currently open documents.
2492 But the algorithm is implemented very simple ...
2493 E.g. hidden documents should be ignored here ... but they are counted.
2494 TODO: export special helper "framework::FrameListAnalyzer" within the framework module
2495 and use it here.
2497 static bool impl_maxOpenDocCountReached()
2499 css::uno::Reference< css::uno::XComponentContext > xContext = ::comphelper::getProcessComponentContext();
2500 std::optional<sal_Int32> x(officecfg::Office::Common::Misc::MaxOpenDocuments::get(xContext));
2501 // NIL means: count of allowed documents = infinite !
2502 if (!x)
2503 return false;
2504 sal_Int32 nMaxDocs(*x);
2505 sal_Int32 nOpenDocs = 0;
2507 css::uno::Reference< css::frame::XDesktop2 > xDesktop = css::frame::Desktop::create(xContext);
2508 css::uno::Reference< css::container::XIndexAccess > xCont(xDesktop->getFrames(), css::uno::UNO_QUERY_THROW);
2510 sal_Int32 c = xCont->getCount();
2511 sal_Int32 i = 0;
2513 for (i=0; i<c; ++i)
2517 css::uno::Reference< css::frame::XFrame > xFrame;
2518 xCont->getByIndex(i) >>= xFrame;
2519 if ( ! xFrame.is())
2520 continue;
2522 // a) do not count the help window
2523 if ( xFrame->getName() == "OFFICE_HELP_TASK" )
2524 continue;
2526 // b) count all other frames
2527 ++nOpenDocs;
2529 catch(const css::uno::Exception&)
2530 // An IndexOutOfBoundsException can happen in multithreaded
2531 // environments, where any other thread can change this
2532 // container !
2533 { continue; }
2536 return (nOpenDocs >= nMaxDocs);
2539 /* [Description]
2541 This internal method returns in 'rSet' the Status for the <SfxShell>
2542 Subclass SfxViewFrame in the <SVIDL> described <Slots>.
2544 Thus exactly those Slots-IDs that are recognized as being invalid by Sfx
2545 are included as Which-ranges in 'rSet'. If there exists a mapping for
2546 single slot-IDs of the <SfxItemPool> set in the shell, then the respective
2547 Which-IDs are used so that items can be replaced directly with a working
2548 Core::sun::com::star::script::Engine of the Which-IDs if possible. .
2550 void SfxViewFrame::StateView_Impl
2552 SfxItemSet& rSet /* empty <SfxItemSet> with <Which-Ranges>,
2553 which describes the Slot Ids */
2557 SfxObjectShell *pDocSh = GetObjectShell();
2559 if ( !pDocSh )
2560 // I'm just on reload and am yielding myself ...
2561 return;
2563 const WhichRangesContainer & pRanges = rSet.GetRanges();
2564 assert(!pRanges.empty() && "Set with no Range");
2565 for ( auto const & pRange : pRanges )
2567 sal_uInt16 nStartWhich = pRange.first;
2568 sal_uInt16 nEndWhich = pRange.second;
2569 for ( sal_uInt16 nWhich = nStartWhich; nWhich <= nEndWhich; ++nWhich )
2571 switch(nWhich)
2573 case SID_VIEWSHELL:
2575 rSet.Put( SfxUInt16Item( nWhich, sal_uInt16(m_pImpl->nCurViewId )) );
2576 break;
2579 case SID_VIEWSHELL0:
2580 case SID_VIEWSHELL1:
2581 case SID_VIEWSHELL2:
2582 case SID_VIEWSHELL3:
2583 case SID_VIEWSHELL4:
2585 sal_uInt16 nViewNo = nWhich - SID_VIEWSHELL0;
2586 if ( GetObjectShell()->GetFactory().GetViewFactoryCount() >
2587 nViewNo && !GetObjectShell()->IsInPlaceActive() )
2589 SfxViewFactory &rViewFactory =
2590 GetObjectShell()->GetFactory().GetViewFactory(nViewNo);
2591 rSet.Put( SfxBoolItem(
2592 nWhich, m_pImpl->nCurViewId == rViewFactory.GetOrdinal() ) );
2594 else
2595 rSet.DisableItem( nWhich );
2596 break;
2599 case SID_NEWWINDOW:
2601 if ( !GetViewShell()->NewWindowAllowed()
2602 || impl_maxOpenDocCountReached()
2604 rSet.DisableItem( nWhich );
2605 break;
2613 void SfxViewFrame::ToTop()
2615 GetFrame().Appear();
2619 /* [Description]
2621 GetFrame returns the Frame, in which the ViewFrame is located.
2623 SfxFrame& SfxViewFrame::GetFrame() const
2625 return m_pImpl->rFrame;
2628 SfxViewFrame* SfxViewFrame::GetTopViewFrame() const
2630 return GetFrame().GetCurrentViewFrame();
2633 vcl::Window& SfxViewFrame::GetWindow() const
2635 return m_pImpl->pWindow ? *m_pImpl->pWindow : GetFrame().GetWindow();
2638 weld::Window* SfxViewFrame::GetFrameWeld() const
2640 return GetWindow().GetFrameWeld();
2643 bool SfxViewFrame::DoClose()
2645 return GetFrame().DoClose();
2648 OUString SfxViewFrame::GetActualPresentationURL_Impl() const
2650 if ( m_xObjSh.is() )
2651 return m_xObjSh->GetMedium()->GetName();
2652 return OUString();
2655 void SfxViewFrame::SetModalMode( bool bModal )
2657 // no real modality for LOK
2658 if (comphelper::LibreOfficeKit::isActive())
2659 return;
2661 m_pImpl->bModal = bModal;
2662 if ( m_xObjSh.is() )
2664 for ( SfxViewFrame* pFrame = SfxViewFrame::GetFirst( m_xObjSh.get() );
2665 !bModal && pFrame; pFrame = SfxViewFrame::GetNext( *pFrame, m_xObjSh.get() ) )
2666 bModal = pFrame->m_pImpl->bModal;
2667 m_xObjSh->SetModalMode_Impl( bModal );
2671 bool SfxViewFrame::IsInModalMode() const
2673 return m_pImpl->bModal || GetFrame().GetWindow().IsInModalMode();
2676 void SfxViewFrame::Resize( bool bForce )
2678 Size aSize = GetWindow().GetOutputSizePixel();
2679 if ( !bForce && aSize == m_pImpl->aSize )
2680 return;
2682 m_pImpl->aSize = aSize;
2683 SfxViewShell *pShell = GetViewShell();
2684 if ( pShell )
2686 if ( GetFrame().IsInPlace() )
2688 Point aPoint = GetWindow().GetPosPixel();
2689 DoAdjustPosSizePixel( pShell, aPoint, aSize, true );
2691 else
2693 DoAdjustPosSizePixel( pShell, Point(), aSize, false );
2698 #if HAVE_FEATURE_SCRIPTING
2700 #define LINE_SEP 0x0A
2702 static void CutLines( OUString& rStr, sal_Int32 nStartLine, sal_Int32 nLines )
2704 sal_Int32 nStartPos = 0;
2705 sal_Int32 nLine = 0;
2706 while ( nLine < nStartLine )
2708 nStartPos = rStr.indexOf( LINE_SEP, nStartPos );
2709 if( nStartPos == -1 )
2710 break;
2711 nStartPos++; // not the \n.
2712 nLine++;
2715 SAL_WARN_IF(nStartPos == -1, "sfx.view", "CutLines: Start row not found!");
2717 if ( nStartPos != -1 )
2719 sal_Int32 nEndPos = nStartPos;
2720 for ( sal_Int32 i = 0; i < nLines; i++ )
2721 nEndPos = rStr.indexOf( LINE_SEP, nEndPos+1 );
2723 if ( nEndPos == -1 ) // Can happen at the last row.
2724 nEndPos = rStr.getLength();
2725 else
2726 nEndPos++;
2728 rStr = OUString::Concat(rStr.subView( 0, nStartPos )) + rStr.subView( nEndPos );
2730 // erase trailing lines
2731 if ( nStartPos != -1 )
2733 sal_Int32 n = nStartPos;
2734 sal_Int32 nLen = rStr.getLength();
2735 while ( ( n < nLen ) && ( rStr[ n ] == LINE_SEP ) )
2736 n++;
2738 if ( n > nStartPos )
2739 rStr = OUString::Concat(rStr.subView( 0, nStartPos )) + rStr.subView( n );
2743 #endif
2746 add new recorded dispatch macro script into the application global basic
2747 lib container. It generates a new unique id for it and insert the macro
2748 by using this number as name for the module
2750 void SfxViewFrame::AddDispatchMacroToBasic_Impl( const OUString& sMacro )
2752 #if !HAVE_FEATURE_SCRIPTING
2753 (void) sMacro;
2754 #else
2755 if ( sMacro.isEmpty() )
2756 return;
2758 SfxApplication* pSfxApp = SfxGetpApp();
2759 SfxItemPool& rPool = pSfxApp->GetPool();
2760 SfxRequest aReq(SID_BASICCHOOSER, SfxCallMode::SYNCHRON, rPool);
2762 //seen in tdf#122598, no parent for subsequent dialog
2763 SfxAllItemSet aSet(rPool);
2764 css::uno::Reference< css::frame::XFrame > xFrame =
2765 GetFrame().GetFrameInterface();
2766 aSet.Put(SfxUnoFrameItem(SID_FILLFRAME, xFrame));
2767 aReq.SetInternalArgs_Impl(aSet);
2769 aReq.AppendItem( SfxBoolItem(SID_RECORDMACRO,true) );
2770 const SfxPoolItem* pRet = SfxGetpApp()->ExecuteSlot( aReq );
2771 OUString aScriptURL;
2772 if ( pRet )
2773 aScriptURL = static_cast<const SfxStringItem*>(pRet)->GetValue();
2774 if ( !aScriptURL.isEmpty() )
2776 // parse scriptURL
2777 OUString aLibName;
2778 OUString aModuleName;
2779 OUString aMacroName;
2780 OUString aLocation;
2781 Reference< XComponentContext > xContext = ::comphelper::getProcessComponentContext();
2782 Reference< css::uri::XUriReferenceFactory > xFactory =
2783 css::uri::UriReferenceFactory::create( xContext );
2784 Reference< css::uri::XVndSunStarScriptUrl > xUrl( xFactory->parse( aScriptURL ), UNO_QUERY );
2785 if ( xUrl.is() )
2787 // get name
2788 const OUString aName = xUrl->getName();
2789 const sal_Unicode cTok = '.';
2790 sal_Int32 nIndex = 0;
2791 aLibName = aName.getToken( 0, cTok, nIndex );
2792 if ( nIndex != -1 )
2793 aModuleName = aName.getToken( 0, cTok, nIndex );
2794 if ( nIndex != -1 )
2795 aMacroName = aName.getToken( 0, cTok, nIndex );
2797 // get location
2798 aLocation = xUrl->getParameter( "location" );
2801 BasicManager* pBasMgr = nullptr;
2802 if ( aLocation == "application" )
2804 // application basic
2805 pBasMgr = SfxApplication::GetBasicManager();
2807 else if ( aLocation == "document" )
2809 pBasMgr = GetObjectShell()->GetBasicManager();
2812 OUString aOUSource;
2813 if ( pBasMgr)
2815 StarBASIC* pBasic = pBasMgr->GetLib( aLibName );
2816 if ( pBasic )
2818 SbModule* pModule = pBasic->FindModule( aModuleName );
2819 SbMethod* pMethod = pModule ? pModule->FindMethod(aMacroName, SbxClassType::Method) : nullptr;
2820 if (pMethod)
2822 aOUSource = pModule->GetSource32();
2823 sal_uInt16 nStart, nEnd;
2824 pMethod->GetLineRange( nStart, nEnd );
2825 sal_uInt16 nlStart = nStart;
2826 sal_uInt16 nlEnd = nEnd;
2827 CutLines( aOUSource, nlStart-1, nlEnd-nlStart+1 );
2832 // open lib container and break operation if it couldn't be opened
2833 css::uno::Reference< css::script::XLibraryContainer > xLibCont;
2834 if ( aLocation == "application" )
2836 xLibCont = SfxGetpApp()->GetBasicContainer();
2838 else if ( aLocation == "document" )
2840 xLibCont = GetObjectShell()->GetBasicContainer();
2843 if(!xLibCont.is())
2845 SAL_WARN("sfx.view", "couldn't get access to the basic lib container. Adding of macro isn't possible.");
2846 return;
2849 // get LibraryContainer
2850 css::uno::Any aTemp;
2852 css::uno::Reference< css::container::XNameAccess > xLib;
2853 if(xLibCont->hasByName(aLibName))
2855 // library must be loaded
2856 aTemp = xLibCont->getByName(aLibName);
2857 xLibCont->loadLibrary(aLibName);
2858 aTemp >>= xLib;
2860 else
2862 xLib = xLibCont->createLibrary(aLibName);
2865 // pack the macro as direct usable "sub" routine
2866 OUStringBuffer sRoutine(10000);
2867 bool bReplace = false;
2869 // get module
2870 if(xLib->hasByName(aModuleName))
2872 if ( !aOUSource.isEmpty() )
2874 sRoutine.append( aOUSource );
2876 else
2878 OUString sCode;
2879 aTemp = xLib->getByName(aModuleName);
2880 aTemp >>= sCode;
2881 sRoutine.append( sCode );
2884 bReplace = true;
2887 // append new method
2888 sRoutine.append( "\nsub " );
2889 sRoutine.append(aMacroName);
2890 sRoutine.append( "\n" );
2891 sRoutine.append(sMacro);
2892 sRoutine.append( "\nend sub\n" );
2894 // create the module inside the library and insert the macro routine
2895 aTemp <<= sRoutine.makeStringAndClear();
2896 if ( bReplace )
2898 css::uno::Reference< css::container::XNameContainer > xModulCont(
2899 xLib,
2900 css::uno::UNO_QUERY);
2901 xModulCont->replaceByName(aModuleName,aTemp);
2903 else
2905 css::uno::Reference< css::container::XNameContainer > xModulCont(
2906 xLib,
2907 css::uno::UNO_QUERY);
2908 xModulCont->insertByName(aModuleName,aTemp);
2911 // #i17355# update the Basic IDE
2912 for ( SfxViewShell* pViewShell = SfxViewShell::GetFirst(); pViewShell; pViewShell = SfxViewShell::GetNext( *pViewShell ) )
2914 if ( pViewShell->GetName() == "BasicIDE" )
2916 SfxViewFrame* pViewFrame = pViewShell->GetViewFrame();
2917 SfxDispatcher* pDispat = pViewFrame ? pViewFrame->GetDispatcher() : nullptr;
2918 if ( pDispat )
2920 SfxMacroInfoItem aInfoItem( SID_BASICIDE_ARG_MACROINFO, pBasMgr, aLibName, aModuleName, OUString(), OUString() );
2921 pDispat->ExecuteList(SID_BASICIDE_UPDATEMODULESOURCE,
2922 SfxCallMode::SYNCHRON, { &aInfoItem });
2927 else
2929 // add code for "session only" macro
2931 #endif
2934 void SfxViewFrame::MiscExec_Impl( SfxRequest& rReq )
2936 switch ( rReq.GetSlot() )
2938 case SID_STOP_RECORDING :
2939 case SID_RECORDMACRO :
2941 // try to find any active recorder on this frame
2942 static const OUStringLiteral sProperty(u"DispatchRecorderSupplier");
2943 css::uno::Reference< css::frame::XFrame > xFrame =
2944 GetFrame().GetFrameInterface();
2946 css::uno::Reference< css::beans::XPropertySet > xSet(xFrame,css::uno::UNO_QUERY);
2947 css::uno::Any aProp = xSet->getPropertyValue(sProperty);
2948 css::uno::Reference< css::frame::XDispatchRecorderSupplier > xSupplier;
2949 aProp >>= xSupplier;
2950 css::uno::Reference< css::frame::XDispatchRecorder > xRecorder;
2951 if (xSupplier.is())
2952 xRecorder = xSupplier->getDispatchRecorder();
2954 bool bIsRecording = xRecorder.is();
2955 const SfxBoolItem* pItem = rReq.GetArg<SfxBoolItem>(SID_RECORDMACRO);
2956 if ( pItem && pItem->GetValue() == bIsRecording )
2957 return;
2959 if ( xRecorder.is() )
2961 // disable active recording
2962 aProp <<= css::uno::Reference< css::frame::XDispatchRecorderSupplier >();
2963 xSet->setPropertyValue(sProperty,aProp);
2965 const SfxBoolItem* pRecordItem = rReq.GetArg<SfxBoolItem>(FN_PARAM_1);
2966 if ( !pRecordItem || !pRecordItem->GetValue() )
2967 // insert script into basic library container of application
2968 AddDispatchMacroToBasic_Impl(xRecorder->getRecordedMacro());
2970 xRecorder->endRecording();
2971 xRecorder = nullptr;
2972 GetBindings().SetRecorder_Impl( xRecorder );
2974 SetChildWindow( SID_RECORDING_FLOATWINDOW, false );
2975 if ( rReq.GetSlot() != SID_RECORDMACRO )
2976 GetBindings().Invalidate( SID_RECORDMACRO );
2978 else if ( rReq.GetSlot() == SID_RECORDMACRO )
2980 // enable recording
2981 css::uno::Reference< css::uno::XComponentContext > xContext(
2982 ::comphelper::getProcessComponentContext());
2984 xRecorder = css::frame::DispatchRecorder::create( xContext );
2986 xSupplier = css::frame::DispatchRecorderSupplier::create( xContext );
2988 xSupplier->setDispatchRecorder(xRecorder);
2989 xRecorder->startRecording(xFrame);
2990 aProp <<= xSupplier;
2991 xSet->setPropertyValue(sProperty,aProp);
2992 GetBindings().SetRecorder_Impl( xRecorder );
2993 SetChildWindow( SID_RECORDING_FLOATWINDOW, true );
2996 rReq.Done();
2997 break;
3000 case SID_TOGGLESTATUSBAR:
3002 if ( auto xLayoutManager = getLayoutManager(GetFrame()) )
3004 static const OUStringLiteral aStatusbarResString( u"private:resource/statusbar/statusbar" );
3005 // Evaluate parameter.
3006 const SfxBoolItem* pShowItem = rReq.GetArg<SfxBoolItem>(rReq.GetSlot());
3007 bool bShow( true );
3008 if ( !pShowItem )
3009 bShow = xLayoutManager->isElementVisible( aStatusbarResString );
3010 else
3011 bShow = pShowItem->GetValue();
3013 if ( bShow )
3015 xLayoutManager->createElement( aStatusbarResString );
3016 xLayoutManager->showElement( aStatusbarResString );
3018 else
3019 xLayoutManager->hideElement( aStatusbarResString );
3021 if ( !pShowItem )
3022 rReq.AppendItem( SfxBoolItem( SID_TOGGLESTATUSBAR, bShow ) );
3024 rReq.Done();
3025 break;
3027 case SID_COMMAND_POPUP:
3029 tools::Rectangle aRectangle(Point(0,0), GetWindow().GetSizePixel());
3030 weld::Window* pParent = weld::GetPopupParent(GetWindow(), aRectangle);
3031 m_pCommandPopupHandler->showPopup(pParent, GetFrame().GetFrameInterface());
3033 rReq.Done();
3034 break;
3036 case SID_WIN_FULLSCREEN:
3038 const SfxBoolItem* pItem = rReq.GetArg<SfxBoolItem>(rReq.GetSlot());
3039 SfxViewFrame *pTop = GetTopViewFrame();
3040 if ( pTop )
3042 WorkWindow* pWork = static_cast<WorkWindow*>( pTop->GetFrame().GetTopWindow_Impl() );
3043 if ( pWork )
3045 Reference< css::frame::XLayoutManager > xLayoutManager = getLayoutManager(GetFrame());
3046 bool bNewFullScreenMode = pItem ? pItem->GetValue() : !pWork->IsFullScreenMode();
3047 if ( bNewFullScreenMode != pWork->IsFullScreenMode() )
3049 if ( bNewFullScreenMode )
3050 sfx2::SfxNotebookBar::LockNotebookBar();
3051 else
3052 sfx2::SfxNotebookBar::UnlockNotebookBar();
3054 Reference< css::beans::XPropertySet > xLMPropSet( xLayoutManager, UNO_QUERY );
3055 if ( xLMPropSet.is() )
3059 xLMPropSet->setPropertyValue(
3060 "HideCurrentUI",
3061 makeAny( bNewFullScreenMode ));
3063 catch ( css::beans::UnknownPropertyException& )
3067 pWork->ShowFullScreenMode( bNewFullScreenMode );
3068 pWork->SetMenuBarMode( bNewFullScreenMode ? MenuBarMode::Hide : MenuBarMode::Normal );
3069 GetFrame().GetWorkWindow_Impl()->SetFullScreen_Impl( bNewFullScreenMode );
3070 if ( !pItem )
3071 rReq.AppendItem( SfxBoolItem( SID_WIN_FULLSCREEN, bNewFullScreenMode ) );
3072 rReq.Done();
3074 else
3075 rReq.Ignore();
3078 else
3079 rReq.Ignore();
3081 GetDispatcher()->Update_Impl( true );
3082 break;
3087 void SfxViewFrame::MiscState_Impl(SfxItemSet &rSet)
3089 const WhichRangesContainer & pRanges = rSet.GetRanges();
3090 DBG_ASSERT(!pRanges.empty(), "Set without range");
3091 for ( auto const & pRange : pRanges )
3093 for(sal_uInt16 nWhich = pRange.first; nWhich <= pRange.second; ++nWhich)
3095 switch(nWhich)
3097 case SID_CURRENT_URL:
3099 rSet.Put( SfxStringItem( nWhich, GetActualPresentationURL_Impl() ) );
3100 break;
3103 case SID_RECORDMACRO :
3105 SvtMiscOptions aMiscOptions;
3106 const OUString& sName{GetObjectShell()->GetFactory().GetFactoryName()};
3107 bool bMacrosDisabled = officecfg::Office::Common::Security::Scripting::DisableMacrosExecution::get();
3108 if (bMacrosDisabled ||
3109 !officecfg::Office::Common::Misc::MacroRecorderMode::get() ||
3110 ( sName!="swriter" && sName!="scalc" ) )
3112 rSet.DisableItem( nWhich );
3113 rSet.Put(SfxVisibilityItem(nWhich, false));
3114 break;
3117 css::uno::Reference< css::beans::XPropertySet > xSet(
3118 GetFrame().GetFrameInterface(),
3119 css::uno::UNO_QUERY);
3121 css::uno::Any aProp = xSet->getPropertyValue("DispatchRecorderSupplier");
3122 css::uno::Reference< css::frame::XDispatchRecorderSupplier > xSupplier;
3123 if ( aProp >>= xSupplier )
3124 rSet.Put( SfxBoolItem( nWhich, xSupplier.is() ) );
3125 else
3126 rSet.DisableItem( nWhich );
3127 break;
3130 case SID_STOP_RECORDING :
3132 SvtMiscOptions aMiscOptions;
3133 const OUString& sName{GetObjectShell()->GetFactory().GetFactoryName()};
3134 if ( !officecfg::Office::Common::Misc::MacroRecorderMode::get() ||
3135 ( sName!="swriter" && sName!="scalc" ) )
3137 rSet.DisableItem( nWhich );
3138 break;
3141 css::uno::Reference< css::beans::XPropertySet > xSet(
3142 GetFrame().GetFrameInterface(),
3143 css::uno::UNO_QUERY);
3145 css::uno::Any aProp = xSet->getPropertyValue("DispatchRecorderSupplier");
3146 css::uno::Reference< css::frame::XDispatchRecorderSupplier > xSupplier;
3147 if ( !(aProp >>= xSupplier) || !xSupplier.is() )
3148 rSet.DisableItem( nWhich );
3149 break;
3152 case SID_TOGGLESTATUSBAR:
3154 css::uno::Reference< css::frame::XLayoutManager > xLayoutManager;
3155 css::uno::Reference< css::beans::XPropertySet > xSet(
3156 GetFrame().GetFrameInterface(),
3157 css::uno::UNO_QUERY);
3158 css::uno::Any aProp = xSet->getPropertyValue( "LayoutManager" );
3160 if ( !( aProp >>= xLayoutManager ))
3161 rSet.Put( SfxBoolItem( nWhich, false ));
3162 else
3164 bool bShow = xLayoutManager->isElementVisible( "private:resource/statusbar/statusbar" );
3165 rSet.Put( SfxBoolItem( nWhich, bShow ));
3167 break;
3170 case SID_WIN_FULLSCREEN:
3172 SfxViewFrame* pTop = GetTopViewFrame();
3173 if ( pTop )
3175 WorkWindow* pWork = static_cast<WorkWindow*>( pTop->GetFrame().GetTopWindow_Impl() );
3176 if ( pWork )
3178 rSet.Put( SfxBoolItem( nWhich, pWork->IsFullScreenMode() ) );
3179 break;
3183 rSet.DisableItem( nWhich );
3184 break;
3187 default:
3188 break;
3194 /* [Description]
3196 This method can be included in the Execute method for the on- and off-
3197 switching of ChildWindows, to implement this and API-bindings.
3199 Simply include as 'ExecuteMethod' in the IDL.
3201 void SfxViewFrame::ChildWindowExecute( SfxRequest &rReq )
3203 // Evaluate Parameter
3204 sal_uInt16 nSID = rReq.GetSlot();
3206 if (nSID == SID_SIDEBAR_DECK)
3208 const SfxStringItem* pDeckIdItem = rReq.GetArg<SfxStringItem>(SID_SIDEBAR_DECK);
3209 if (pDeckIdItem)
3211 const OUString aDeckId(pDeckIdItem->GetValue());
3212 ::sfx2::sidebar::Sidebar::ToggleDeck(aDeckId, this);
3214 rReq.Done();
3215 return;
3218 const SfxBoolItem* pShowItem = rReq.GetArg<SfxBoolItem>(nSID);
3219 if ( nSID == SID_VIEW_DATA_SOURCE_BROWSER )
3221 if (!SvtModuleOptions().IsModuleInstalled(SvtModuleOptions::EModule::DATABASE))
3222 return;
3223 Reference < XFrame > xFrame = GetFrame().GetFrameInterface();
3224 Reference < XFrame > xBeamer( xFrame->findFrame( "_beamer", FrameSearchFlag::CHILDREN ) );
3225 bool bHasChild = xBeamer.is();
3226 bool bShow = pShowItem ? pShowItem->GetValue() : !bHasChild;
3227 if ( pShowItem )
3229 if( bShow == bHasChild )
3230 return;
3232 else
3233 rReq.AppendItem( SfxBoolItem( nSID, bShow ) );
3235 if ( !bShow )
3237 SetChildWindow( SID_BROWSER, false );
3239 else
3241 css::util::URL aTargetURL;
3242 aTargetURL.Complete = ".component:DB/DataSourceBrowser";
3243 Reference < css::util::XURLTransformer > xTrans(
3244 css::util::URLTransformer::create(
3245 ::comphelper::getProcessComponentContext() ) );
3246 xTrans->parseStrict( aTargetURL );
3248 Reference < XDispatchProvider > xProv( xFrame, UNO_QUERY );
3249 Reference < css::frame::XDispatch > xDisp;
3250 if ( xProv.is() )
3251 xDisp = xProv->queryDispatch( aTargetURL, "_beamer", 31 );
3252 if ( xDisp.is() )
3254 Sequence < css::beans::PropertyValue > aArgs(1);
3255 css::beans::PropertyValue* pArg = aArgs.getArray();
3256 pArg[0].Name = "Referer";
3257 pArg[0].Value <<= OUString("private:user");
3258 xDisp->dispatch( aTargetURL, aArgs );
3262 rReq.Done();
3263 return;
3265 if (nSID == SID_STYLE_DESIGNER)
3267 // First make sure that the sidebar is visible
3268 ShowChildWindow(SID_SIDEBAR);
3270 ::sfx2::sidebar::Sidebar::ShowPanel(u"StyleListPanel",
3271 GetFrame().GetFrameInterface(), true);
3272 rReq.Done();
3273 return;
3276 bool bHasChild = HasChildWindow(nSID);
3277 bool bShow = pShowItem ? pShowItem->GetValue() : !bHasChild;
3278 GetDispatcher()->Update_Impl( true );
3280 // Perform action.
3281 if ( !pShowItem || bShow != bHasChild )
3282 ToggleChildWindow( nSID );
3284 GetBindings().Invalidate( nSID );
3286 // Record if possible.
3287 if ( nSID == SID_HYPERLINK_DIALOG || nSID == SID_SEARCH_DLG )
3289 rReq.Ignore();
3291 else
3293 rReq.AppendItem( SfxBoolItem( nSID, bShow ) );
3294 rReq.Done();
3298 /* [Description]
3300 This method can be used in the state method for the on and off-state
3301 of child-windows, in order to implement this.
3303 Just register the IDL as 'StateMethod'.
3305 void SfxViewFrame::ChildWindowState( SfxItemSet& rState )
3307 SfxWhichIter aIter( rState );
3308 for ( sal_uInt16 nSID = aIter.FirstWhich(); nSID; nSID = aIter.NextWhich() )
3310 if ( nSID == SID_VIEW_DATA_SOURCE_BROWSER )
3312 rState.Put( SfxBoolItem( nSID, HasChildWindow( SID_BROWSER ) ) );
3314 else if ( nSID == SID_HYPERLINK_DIALOG )
3316 const SfxPoolItem* pDummy = nullptr;
3317 SfxItemState eState = GetDispatcher()->QueryState( SID_HYPERLINK_SETLINK, pDummy );
3318 if ( SfxItemState::DISABLED == eState )
3319 rState.DisableItem(nSID);
3320 else
3322 if ( KnowsChildWindow(nSID) )
3323 rState.Put( SfxBoolItem( nSID, HasChildWindow(nSID)) );
3324 else
3325 rState.DisableItem(nSID);
3328 else if ( nSID == SID_BROWSER )
3330 Reference < XFrame > xFrame = GetFrame().GetFrameInterface()->
3331 findFrame( "_beamer", FrameSearchFlag::CHILDREN );
3332 if ( !xFrame.is() )
3333 rState.DisableItem( nSID );
3334 else if ( KnowsChildWindow(nSID) )
3335 rState.Put( SfxBoolItem( nSID, HasChildWindow(nSID) ) );
3337 else if ( nSID == SID_SIDEBAR )
3339 if ( !KnowsChildWindow( nSID ) )
3341 SAL_INFO("sfx.view", "SID_SIDEBAR state requested, but no task pane child window exists for this ID!");
3342 rState.DisableItem( nSID );
3344 else
3346 rState.Put( SfxBoolItem( nSID, HasChildWindow( nSID ) ) );
3349 else if ( KnowsChildWindow(nSID) )
3350 rState.Put( SfxBoolItem( nSID, HasChildWindow(nSID) ) );
3351 else
3352 rState.DisableItem(nSID);
3356 SfxWorkWindow* SfxViewFrame::GetWorkWindow_Impl()
3358 SfxWorkWindow* pWork = GetFrame().GetWorkWindow_Impl();
3359 return pWork;
3362 void SfxViewFrame::SetChildWindow(sal_uInt16 nId, bool bOn, bool bSetFocus )
3364 SfxWorkWindow* pWork = GetWorkWindow_Impl();
3365 if ( pWork )
3366 pWork->SetChildWindow_Impl( nId, bOn, bSetFocus );
3369 void SfxViewFrame::ToggleChildWindow(sal_uInt16 nId)
3371 SfxWorkWindow* pWork = GetWorkWindow_Impl();
3372 if ( pWork )
3373 pWork->ToggleChildWindow_Impl( nId, true );
3376 bool SfxViewFrame::HasChildWindow( sal_uInt16 nId )
3378 SfxWorkWindow* pWork = GetWorkWindow_Impl();
3379 return pWork && pWork->HasChildWindow_Impl(nId);
3382 bool SfxViewFrame::KnowsChildWindow( sal_uInt16 nId )
3384 SfxWorkWindow* pWork = GetWorkWindow_Impl();
3385 return pWork && pWork->KnowsChildWindow_Impl(nId);
3388 void SfxViewFrame::ShowChildWindow( sal_uInt16 nId, bool bVisible )
3390 SfxWorkWindow* pWork = GetWorkWindow_Impl();
3391 if ( pWork )
3393 GetDispatcher()->Update_Impl(true);
3394 pWork->ShowChildWindow_Impl(nId, bVisible, true );
3398 SfxChildWindow* SfxViewFrame::GetChildWindow(sal_uInt16 nId)
3400 SfxWorkWindow* pWork = GetWorkWindow_Impl();
3401 return pWork ? pWork->GetChildWindow_Impl(nId) : nullptr;
3404 void SfxViewFrame::UpdateDocument_Impl()
3406 SfxObjectShell* pDoc = GetObjectShell();
3407 if ( pDoc->IsLoadingFinished() )
3408 pDoc->CheckSecurityOnLoading_Impl();
3410 // check if document depends on a template
3411 pDoc->UpdateFromTemplate_Impl();
3414 void SfxViewFrame::SetViewFrame( SfxViewFrame* pFrame )
3416 if(pFrame)
3417 SetSVHelpData(pFrame->m_pHelpData);
3419 SetSVWinData(pFrame ? pFrame->m_pWinData : nullptr);
3421 SfxGetpApp()->SetViewFrame_Impl( pFrame );
3424 VclPtr<SfxInfoBarWindow> SfxViewFrame::AppendInfoBar(const OUString& sId,
3425 const OUString& sPrimaryMessage,
3426 const OUString& sSecondaryMessage,
3427 InfobarType aInfobarType, bool bShowCloseButton)
3429 SfxChildWindow* pChild = GetChildWindow(SfxInfoBarContainerChild::GetChildWindowId());
3430 if (!pChild)
3431 return nullptr;
3433 if (HasInfoBarWithID(sId))
3434 return nullptr;
3436 SfxInfoBarContainerWindow* pInfoBarContainer = static_cast<SfxInfoBarContainerWindow*>(pChild->GetWindow());
3437 auto pInfoBar = pInfoBarContainer->appendInfoBar(sId, sPrimaryMessage, sSecondaryMessage,
3438 aInfobarType, bShowCloseButton);
3439 ShowChildWindow(SfxInfoBarContainerChild::GetChildWindowId());
3440 return pInfoBar;
3443 void SfxViewFrame::UpdateInfoBar(std::u16string_view sId, const OUString& sPrimaryMessage,
3444 const OUString& sSecondaryMessage, InfobarType eType)
3446 const sal_uInt16 nId = SfxInfoBarContainerChild::GetChildWindowId();
3448 // Make sure the InfoBar container is visible
3449 if (!HasChildWindow(nId))
3450 ToggleChildWindow(nId);
3452 SfxChildWindow* pChild = GetChildWindow(nId);
3453 if (pChild)
3455 SfxInfoBarContainerWindow* pInfoBarContainer = static_cast<SfxInfoBarContainerWindow*>(pChild->GetWindow());
3456 auto pInfoBar = pInfoBarContainer->getInfoBar(sId);
3458 if (pInfoBar)
3459 pInfoBar->Update(sPrimaryMessage, sSecondaryMessage, eType);
3463 void SfxViewFrame::RemoveInfoBar( std::u16string_view sId )
3465 const sal_uInt16 nId = SfxInfoBarContainerChild::GetChildWindowId();
3467 // Make sure the InfoBar container is visible
3468 if (!HasChildWindow(nId))
3469 ToggleChildWindow(nId);
3471 SfxChildWindow* pChild = GetChildWindow(nId);
3472 if (pChild)
3474 SfxInfoBarContainerWindow* pInfoBarContainer = static_cast<SfxInfoBarContainerWindow*>(pChild->GetWindow());
3475 auto pInfoBar = pInfoBarContainer->getInfoBar(sId);
3476 pInfoBarContainer->removeInfoBar(pInfoBar);
3477 ShowChildWindow(nId);
3481 bool SfxViewFrame::HasInfoBarWithID( std::u16string_view sId )
3483 const sal_uInt16 nId = SfxInfoBarContainerChild::GetChildWindowId();
3485 SfxChildWindow* pChild = GetChildWindow(nId);
3486 if (pChild)
3488 SfxInfoBarContainerWindow* pInfoBarContainer = static_cast<SfxInfoBarContainerWindow*>(pChild->GetWindow());
3489 return pInfoBarContainer->hasInfoBarWithID(sId);
3492 return false;
3495 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */