Version 7.1.7.1, tag libreoffice-7.1.7.1
[LibreOffice.git] / sfx2 / source / view / viewfrm.cxx
blob46a7c4d9dc42466c59611ecacd1c162fb1ad7779
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 <com/sun/star/document/MacroExecMode.hpp>
29 #include <com/sun/star/frame/Desktop.hpp>
30 #include <com/sun/star/frame/DispatchRecorder.hpp>
31 #include <com/sun/star/frame/DispatchRecorderSupplier.hpp>
32 #include <com/sun/star/frame/XLoadable.hpp>
33 #include <com/sun/star/frame/XLayoutManager.hpp>
34 #include <com/sun/star/frame/XComponentLoader.hpp>
35 #include <com/sun/star/drawing/XShapes.hpp>
36 #include <officecfg/Office/Common.hxx>
37 #include <officecfg/Setup.hxx>
38 #include <toolkit/helper/vclunohelper.hxx>
39 #include <vcl/wrkwin.hxx>
40 #include <unotools/moduleoptions.hxx>
41 #include <svl/intitem.hxx>
42 #include <svl/visitem.hxx>
43 #include <svl/stritem.hxx>
44 #include <svl/eitem.hxx>
45 #include <svl/whiter.hxx>
46 #include <svl/undo.hxx>
47 #include <vcl/stdtext.hxx>
48 #include <vcl/weld.hxx>
49 #include <svtools/miscopt.hxx>
50 #include <tools/diagnose_ex.h>
51 #include <com/sun/star/container/XIndexAccess.hpp>
52 #include <com/sun/star/frame/XFramesSupplier.hpp>
53 #include <com/sun/star/frame/FrameSearchFlag.hpp>
54 #include <com/sun/star/frame/XFrame.hpp>
55 #include <com/sun/star/awt/XWindow.hpp>
56 #include <com/sun/star/frame/XController.hpp>
57 #include <com/sun/star/util/URLTransformer.hpp>
58 #include <com/sun/star/util/XURLTransformer.hpp>
59 #include <com/sun/star/util/XCloseable.hpp>
60 #include <com/sun/star/frame/XDispatchRecorderSupplier.hpp>
61 #include <com/sun/star/document/UpdateDocMode.hpp>
62 #include <com/sun/star/beans/XPropertySet.hpp>
63 #include <com/sun/star/uri/UriReferenceFactory.hpp>
64 #include <com/sun/star/uri/XVndSunStarScriptUrl.hpp>
65 #include <com/sun/star/document/XViewDataSupplier.hpp>
66 #include <com/sun/star/container/XIndexContainer.hpp>
67 #include <com/sun/star/task/InteractionHandler.hpp>
68 #include <com/sun/star/drawing/XDrawView.hpp>
69 #include <com/sun/star/drawing/XDrawPagesSupplier.hpp>
70 #include <rtl/ustrbuf.hxx>
71 #include <sal/log.hxx>
73 #include <unotools/ucbhelper.hxx>
74 #include <comphelper/lok.hxx>
75 #include <comphelper/processfactory.hxx>
76 #include <comphelper/namedvaluecollection.hxx>
77 #include <comphelper/docpasswordrequest.hxx>
78 #include <comphelper/docpasswordhelper.hxx>
80 #include <com/sun/star/uno/Reference.h>
82 #include <basic/basmgr.hxx>
83 #include <basic/sbmod.hxx>
84 #include <basic/sbmeth.hxx>
85 #include <svtools/strings.hrc>
86 #include <svtools/svtresid.hxx>
87 #include <framework/framelistanalyzer.hxx>
88 #include <shellimpl.hxx>
90 #include <optional>
92 #include <unotools/configmgr.hxx>
93 #include <comphelper/sequenceashashmap.hxx>
95 using namespace ::com::sun::star;
96 using namespace ::com::sun::star::uno;
97 using namespace ::com::sun::star::ucb;
98 using namespace ::com::sun::star::frame;
99 using namespace ::com::sun::star::lang;
100 using ::com::sun::star::awt::XWindow;
101 using ::com::sun::star::beans::PropertyValue;
102 using ::com::sun::star::document::XViewDataSupplier;
103 using ::com::sun::star::container::XIndexContainer;
105 // Due to ViewFrame::Current
106 #include <appdata.hxx>
107 #include <sfx2/app.hxx>
108 #include <sfx2/objface.hxx>
109 #include <openflag.hxx>
110 #include <objshimp.hxx>
111 #include <sfx2/viewsh.hxx>
112 #include <sfx2/objsh.hxx>
113 #include <sfx2/bindings.hxx>
114 #include <sfx2/dispatch.hxx>
115 #include <sfx2/request.hxx>
116 #include <sfx2/docfac.hxx>
117 #include <sfx2/ipclient.hxx>
118 #include <sfx2/sfxresid.hxx>
119 #include <sfx2/viewfac.hxx>
120 #include <sfx2/event.hxx>
121 #include <sfx2/fcontnr.hxx>
122 #include <sfx2/docfile.hxx>
123 #include <sfx2/module.hxx>
124 #include <sfx2/sfxuno.hxx>
125 #include <sfx2/progress.hxx>
126 #include <sfx2/sidebar/Sidebar.hxx>
127 #include <workwin.hxx>
128 #include <sfx2/minfitem.hxx>
129 #include <sfx2/strings.hrc>
130 #include "impviewframe.hxx"
131 #include <vcl/commandinfoprovider.hxx>
132 #include <vcl/svapp.hxx>
134 #define ShellClass_SfxViewFrame
135 #include <sfxslots.hxx>
137 SFX_IMPL_SUPERCLASS_INTERFACE(SfxViewFrame,SfxShell)
139 void SfxViewFrame::InitInterface_Impl()
141 GetStaticInterface()->RegisterChildWindow(SID_BROWSER);
142 GetStaticInterface()->RegisterChildWindow(SID_RECORDING_FLOATWINDOW);
143 #if HAVE_FEATURE_DESKTOP
144 GetStaticInterface()->RegisterObjectBar(SFX_OBJECTBAR_FULLSCREEN, SfxVisibilityFlags::FullScreen, ToolbarId::FullScreenToolbox);
145 GetStaticInterface()->RegisterObjectBar(SFX_OBJECTBAR_APPLICATION, SfxVisibilityFlags::Standard, ToolbarId::EnvToolbox);
146 #endif
149 namespace {
150 /// Asks the user if editing a read-only document is really wanted.
151 class SfxEditDocumentDialog : public weld::MessageDialogController
153 private:
154 std::unique_ptr<weld::Button> m_xEditDocument;
155 std::unique_ptr<weld::Button> m_xCancel;
157 public:
158 SfxEditDocumentDialog(weld::Widget* pParent);
161 SfxEditDocumentDialog::SfxEditDocumentDialog(weld::Widget* pParent)
162 : MessageDialogController(pParent, "sfx/ui/editdocumentdialog.ui",
163 "EditDocumentDialog")
164 , m_xEditDocument(m_xBuilder->weld_button("edit"))
165 , m_xCancel(m_xBuilder->weld_button("cancel"))
169 class SfxQueryOpenAsTemplate
171 private:
172 std::unique_ptr<weld::MessageDialog> m_xQueryBox;
173 public:
174 SfxQueryOpenAsTemplate(weld::Window* pParent, bool bAllowIgnoreLock, LockFileEntry& rLockData)
175 : m_xQueryBox(Application::CreateMessageDialog(pParent, VclMessageType::Question,
176 VclButtonsType::NONE, ""))
178 m_xQueryBox->add_button(SfxResId(STR_QUERY_OPENASTEMPLATE_OPENCOPY_BTN), RET_YES);
179 bAllowIgnoreLock
180 = bAllowIgnoreLock && officecfg::Office::Common::Misc::AllowOverrideLocking::get();
181 if (bAllowIgnoreLock)
182 m_xQueryBox->add_button(SfxResId(STR_QUERY_OPENASTEMPLATE_OPEN_BTN), RET_IGNORE);
183 m_xQueryBox->add_button(GetStandardText( StandardButtonType::Cancel ), RET_CANCEL);
184 m_xQueryBox->set_primary_text(QueryString(bAllowIgnoreLock, rLockData));
185 m_xQueryBox->set_default_response(RET_YES);
187 short run() { return m_xQueryBox->run(); }
189 private:
190 static OUString QueryString(bool bAllowIgnoreLock, LockFileEntry& rLockData)
192 OUString sLockUserData;
193 if (!rLockData[LockFileComponent::OOOUSERNAME].isEmpty())
194 sLockUserData = rLockData[LockFileComponent::OOOUSERNAME];
195 else
196 sLockUserData = rLockData[LockFileComponent::SYSUSERNAME];
198 if (!sLockUserData.isEmpty() && !rLockData[LockFileComponent::EDITTIME].isEmpty())
199 sLockUserData += " ( " + rLockData[LockFileComponent::EDITTIME] + " )";
201 if (!sLockUserData.isEmpty())
202 sLockUserData = "\n\n" + sLockUserData + "\n";
204 const bool bUseLockStr = bAllowIgnoreLock || !sLockUserData.isEmpty();
206 OUString sMsg(
207 SfxResId(bUseLockStr ? STR_QUERY_OPENASTEMPLATE_LOCKED : STR_QUERY_OPENASTEMPLATE));
209 if (bAllowIgnoreLock)
210 sMsg += "\n\n" + SfxResId(STR_QUERY_OPENASTEMPLATE_ALLOW_IGNORE);
212 return sMsg.replaceFirst("%LOCKINFO", sLockUserData);
216 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 )
218 // TODO/LATER: In future the info should replace the direct hash completely
219 bool bResult = ( !nPasswordHash && !aInfo.hasElements() );
221 SAL_WARN_IF( !(pFilter && ( pFilter->GetFilterFlags() & SfxFilterFlags::PASSWORDTOMODIFY )), "sfx.view",
222 "PasswordToModify feature is active for a filter that does not support it!");
224 if ( pFilter && xHandler.is() )
226 bool bCancel = false;
227 bool bFirstTime = true;
229 while ( !bResult && !bCancel )
231 bool bMSType = !pFilter->IsOwnFormat();
233 ::rtl::Reference< ::comphelper::DocPasswordRequest > pPasswordRequest(
234 new ::comphelper::DocPasswordRequest(
235 bMSType ? ::comphelper::DocPasswordRequestType::MS : ::comphelper::DocPasswordRequestType::Standard,
236 bFirstTime ? css::task::PasswordRequestMode_PASSWORD_ENTER : css::task::PasswordRequestMode_PASSWORD_REENTER,
237 aPath,
238 true ) );
240 uno::Reference< css::task::XInteractionRequest > rRequest( pPasswordRequest.get() );
241 xHandler->handle( rRequest );
243 if ( pPasswordRequest->isPassword() )
245 if ( aInfo.hasElements() )
247 bResult = ::comphelper::DocPasswordHelper::IsModifyPasswordCorrect( pPasswordRequest->getPasswordToModify(), aInfo );
249 else
251 // the binary format
252 bResult = ( SfxMedium::CreatePasswordToModifyHash( pPasswordRequest->getPasswordToModify(), pFilter->GetServiceName()=="com.sun.star.text.TextDocument" ) == nPasswordHash );
255 else
256 bCancel = true;
258 bFirstTime = false;
262 return bResult;
266 void SfxViewFrame::ExecReload_Impl( SfxRequest& rReq )
268 SfxObjectShell* pSh = GetObjectShell();
269 switch ( rReq.GetSlot() )
271 case SID_EDITDOC:
272 case SID_READONLYDOC:
274 // Due to Double occupancy in toolboxes (with or without Ctrl),
275 // it is also possible that the slot is enabled, but Ctrl-click
276 // despite this is not!
277 if( !pSh || !pSh->HasName() || !(pSh->Get_Impl()->nLoadedFlags & SfxLoadedFlags::MAINDOCUMENT ))
278 break;
280 if (pSh->isEditDocLocked())
281 break;
283 // Only change read-only UI and remove info bar when we succeed
284 struct ReadOnlyUIGuard
286 SfxViewFrame* m_pFrame;
287 SfxObjectShell* m_pSh;
288 SfxMedium* m_pMed = nullptr;
289 bool m_bSetRO;
290 ReadOnlyUIGuard(SfxViewFrame* pFrame, SfxObjectShell* p_Sh)
291 : m_pFrame(pFrame), m_pSh(p_Sh), m_bSetRO(p_Sh->IsReadOnlyUI())
293 ~ReadOnlyUIGuard() COVERITY_NOEXCEPT_FALSE
295 if (m_bSetRO != m_pSh->IsReadOnlyUI())
297 m_pSh->SetReadOnlyUI(m_bSetRO);
298 if (!m_bSetRO)
299 m_pFrame->RemoveInfoBar("readonly");
300 if (m_pMed)
302 // tdf#116066: DoSaveCompleted should be called after SetReadOnlyUI
303 m_pSh->DoSaveCompleted(m_pMed);
304 m_pSh->Broadcast(SfxHint(SfxHintId::ModeChanged));
308 } aReadOnlyUIGuard(this, pSh);
310 SfxMedium* pMed = pSh->GetMedium();
312 const SfxBoolItem* pItem = SfxItemSet::GetItem<SfxBoolItem>(pSh->GetMedium()->GetItemSet(), SID_VIEWONLY, false);
313 if ( pItem && pItem->GetValue() )
315 SfxApplication* pApp = SfxGetpApp();
316 SfxAllItemSet aSet( pApp->GetPool() );
317 aSet.Put( SfxStringItem( SID_FILE_NAME, pMed->GetURLObject().GetMainURL(INetURLObject::DecodeMechanism::NONE) ) );
318 aSet.Put( SfxBoolItem( SID_TEMPLATE, true ) );
319 aSet.Put( SfxStringItem( SID_TARGETNAME, "_blank" ) );
320 const SfxStringItem* pReferer = SfxItemSet::GetItem<SfxStringItem>(pMed->GetItemSet(), SID_REFERER, false);
321 if ( pReferer )
322 aSet.Put( *pReferer );
323 const SfxInt16Item* pVersionItem = SfxItemSet::GetItem<SfxInt16Item>(pSh->GetMedium()->GetItemSet(), SID_VERSION, false);
324 if ( pVersionItem )
325 aSet.Put( *pVersionItem );
327 if( pMed->GetFilter() )
329 aSet.Put( SfxStringItem( SID_FILTER_NAME, pMed->GetFilter()->GetFilterName() ) );
330 const SfxStringItem* pOptions = SfxItemSet::GetItem<SfxStringItem>(pMed->GetItemSet(), SID_FILE_FILTEROPTIONS, false);
331 if ( pOptions )
332 aSet.Put( *pOptions );
335 GetDispatcher()->Execute( SID_OPENDOC, SfxCallMode::ASYNCHRON, aSet );
336 return;
339 StreamMode nOpenMode;
340 bool bNeedsReload = false;
341 if ( !pSh->IsReadOnly() )
343 // Save and reload Readonly
344 if( pSh->IsModified() )
346 if ( pSh->PrepareClose() )
348 // the storing could let the medium be changed
349 pMed = pSh->GetMedium();
350 bNeedsReload = true;
352 else
354 rReq.SetReturnValue( SfxBoolItem( rReq.GetSlot(), false ) );
355 return;
358 nOpenMode = SFX_STREAM_READONLY;
359 aReadOnlyUIGuard.m_bSetRO = true;
361 else
363 if ( pSh->IsReadOnlyMedium()
364 && ( pSh->GetModifyPasswordHash() || pSh->GetModifyPasswordInfo().hasElements() )
365 && !pSh->IsModifyPasswordEntered() )
367 const OUString aDocumentName = INetURLObject( pMed->GetOrigURL() ).GetMainURL( INetURLObject::DecodeMechanism::WithCharset );
368 if( !AskPasswordToModify_Impl( pMed->GetInteractionHandler(), aDocumentName, pMed->GetFilter(), pSh->GetModifyPasswordHash(), pSh->GetModifyPasswordInfo() ) )
370 // this is a read-only document, if it has "Password to modify"
371 // the user should enter password before he can edit the document
372 rReq.SetReturnValue( SfxBoolItem( rReq.GetSlot(), false ) );
373 return;
376 pSh->SetModifyPasswordEntered();
379 nOpenMode = pSh->IsOriginallyReadOnlyMedium() ? SFX_STREAM_READONLY : SFX_STREAM_READWRITE;
380 aReadOnlyUIGuard.m_bSetRO = false;
382 // if only the view was in the readonly mode then there is no need to do the reload
383 if ( !pSh->IsReadOnlyMedium() )
385 // SetReadOnlyUI causes recomputation of window title, using
386 // open mode among other things, so call SetOpenMode before
387 // SetReadOnlyUI:
388 pMed->SetOpenMode( nOpenMode );
389 return;
393 if ( rReq.IsAPI() )
395 // Control through API if r/w or r/o
396 const SfxBoolItem* pEditItem = rReq.GetArg<SfxBoolItem>(SID_EDITDOC);
397 if ( pEditItem )
398 nOpenMode = pEditItem->GetValue() ? SFX_STREAM_READWRITE : SFX_STREAM_READONLY;
401 // doing
403 OUString sTemp;
404 osl::FileBase::getFileURLFromSystemPath( pMed->GetPhysicalName(), sTemp );
405 INetURLObject aPhysObj( sTemp );
406 const SfxInt16Item* pVersionItem = SfxItemSet::GetItem<SfxInt16Item>(pSh->GetMedium()->GetItemSet(), SID_VERSION, false);
408 INetURLObject aMedObj( pMed->GetName() );
410 // -> tdf#82744
411 // the logic below is following:
412 // if the document seems not to need to be reloaded
413 // and the physical name is different to the logical one,
414 // then on file system it can be checked that the copy is still newer than the original and no document reload is required.
415 // Did some semplification to enhance readability of the 'if' expression
417 // when the 'http/https' protocol is active, the bool bPhysObjIsYounger relies upon the getlastmodified Property of a WebDAV resource.
418 // Said property should be implemented, but sometimes it's not.
419 // implemented. On this case the reload activated here will not work properly.
420 // TODO: change the check age method for WebDAV to etag (entity-tag) property value, need some rethinking, since the
421 // etag tells that the cache representation (e.g. in LO) is different from the one on the server,
422 // but tells nothing about the age
423 // Details at this link: http://tools.ietf.org/html/rfc4918#section-15, section 15.7
424 bool bPhysObjIsYounger = ::utl::UCBContentHelper::IsYounger( aMedObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ),
425 aPhysObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ) );
426 bool bIsWebDAV = aMedObj.isAnyKnownWebDAVScheme();
428 if ( ( !bNeedsReload && ( ( aMedObj.GetProtocol() == INetProtocol::File &&
429 aMedObj.getFSysPath( FSysStyle::Detect ) != aPhysObj.getFSysPath( FSysStyle::Detect ) &&
430 !bPhysObjIsYounger )
431 || ( bIsWebDAV && !bPhysObjIsYounger )
432 || ( pMed->IsRemote() && !bIsWebDAV ) ) )
433 || pVersionItem )
434 // <- tdf#82744
436 bNeedsReload = true;
438 bool bOK = false;
439 bool bRetryIgnoringLock = false;
440 bool bOpenTemplate = false;
441 std::optional<bool> aOrigROVal;
442 if (!pVersionItem)
444 auto pRO = pMed->GetItemSet()->GetItem<SfxBoolItem>(SID_DOC_READONLY, false);
445 if (pRO)
446 aOrigROVal = pRO->GetValue();
448 do {
449 LockFileEntry aLockData;
450 if ( !pVersionItem )
452 if (bRetryIgnoringLock)
453 pMed->ResetError();
455 bool bHasStorage = pMed->HasStorage_Impl();
456 // switching edit mode could be possible without reload
457 if ( bHasStorage && pMed->GetStorage() == pSh->GetStorage() )
459 // TODO/LATER: faster creation of copy
460 if ( !pSh->ConnectTmpStorage_Impl( pMed->GetStorage(), pMed ) )
461 return;
464 pMed->CloseAndRelease();
465 pMed->SetOpenMode( nOpenMode );
466 // We need to clear the SID_DOC_READONLY item from the set, to allow
467 // MediaDescriptor::impl_openStreamWithURL (called indirectly by
468 // SfxMedium::CompleteReOpen) to properly fill input stream of the
469 // descriptor, even when the file can't be open in read-write mode.
470 // Only then can following call to SfxMedium::LockOrigFileOnDemand
471 // return proper information about who has locked the file, to show
472 // in the SfxQueryOpenAsTemplate box below; otherwise it exits right
473 // after call to SfxMedium::GetMedium_Impl. This mimics what happens
474 // when the file is opened initially, when filter detection code also
475 // calls MediaDescriptor::impl_openStreamWithURL without the item set.
476 pMed->GetItemSet()->ClearItem(SID_DOC_READONLY);
477 pMed->CompleteReOpen();
478 pMed->GetItemSet()->Put(
479 SfxBoolItem(SID_DOC_READONLY, !(nOpenMode & StreamMode::WRITE)));
480 if ( nOpenMode & StreamMode::WRITE )
482 auto eResult = pMed->LockOrigFileOnDemand(
483 true, true, bRetryIgnoringLock, &aLockData);
484 bRetryIgnoringLock
485 = eResult == SfxMedium::LockFileResult::FailedLockFile;
488 // LockOrigFileOnDemand might set the readonly flag itself, it should be set back
489 pMed->GetItemSet()->Put( SfxBoolItem( SID_DOC_READONLY, !( nOpenMode & StreamMode::WRITE ) ) );
491 if ( !pMed->GetErrorCode() )
492 bOK = true;
495 if( !bOK )
497 if (nOpenMode == SFX_STREAM_READWRITE && !rReq.IsAPI())
499 // css::sdbcx::User offering to open it as a template
500 SfxQueryOpenAsTemplate aBox(GetWindow().GetFrameWeld(),
501 bRetryIgnoringLock, aLockData);
503 short nUserAnswer = aBox.run();
504 bOpenTemplate = RET_YES == nUserAnswer;
505 // Always reset this here to avoid infinite loop
506 bRetryIgnoringLock = RET_IGNORE == nUserAnswer;
508 else
509 bRetryIgnoringLock = false;
512 while ( !bOK && bRetryIgnoringLock );
514 if( !bOK )
516 ErrCode nErr = pMed->GetErrorCode();
517 if ( pVersionItem )
518 nErr = ERRCODE_IO_ACCESSDENIED;
519 else
521 pMed->ResetError();
522 pMed->SetOpenMode( SFX_STREAM_READONLY );
523 if (aOrigROVal)
524 pMed->GetItemSet()->Put(SfxBoolItem(SID_DOC_READONLY, *aOrigROVal));
525 else
526 pMed->GetItemSet()->ClearItem(SID_DOC_READONLY);
527 pMed->ReOpen();
528 pSh->DoSaveCompleted( pMed );
531 // Readonly document can not be switched to edit mode?
532 rReq.Done();
534 if ( nOpenMode == SFX_STREAM_READWRITE && !rReq.IsAPI() )
536 if ( bOpenTemplate )
538 SfxApplication* pApp = SfxGetpApp();
539 SfxAllItemSet aSet( pApp->GetPool() );
540 aSet.Put( SfxStringItem( SID_FILE_NAME, pMed->GetName() ) );
541 const SfxStringItem* pReferer = SfxItemSet::GetItem<SfxStringItem>(pMed->GetItemSet(), SID_REFERER, false);
542 if ( pReferer )
543 aSet.Put( *pReferer );
544 aSet.Put( SfxBoolItem( SID_TEMPLATE, true ) );
545 if ( pVersionItem )
546 aSet.Put( *pVersionItem );
548 if( pMed->GetFilter() )
550 aSet.Put( SfxStringItem( SID_FILTER_NAME, pMed->GetFilter()->GetFilterName() ) );
551 const SfxStringItem* pOptions = SfxItemSet::GetItem<SfxStringItem>(pMed->GetItemSet(), SID_FILE_FILTEROPTIONS, false);
552 if ( pOptions )
553 aSet.Put( *pOptions );
556 GetDispatcher()->Execute( SID_OPENDOC, SfxCallMode::ASYNCHRON, aSet );
557 return;
560 nErr = ERRCODE_NONE;
563 // Keep the read-only UI
564 aReadOnlyUIGuard.m_bSetRO = true;
566 ErrorHandler::HandleError( nErr );
567 rReq.SetReturnValue(
568 SfxBoolItem( rReq.GetSlot(), false ) );
569 return;
571 else
573 aReadOnlyUIGuard.m_pMed = pMed;
574 rReq.SetReturnValue( SfxBoolItem( rReq.GetSlot(), true ) );
575 rReq.Done( true );
576 return;
580 rReq.AppendItem( SfxBoolItem( SID_FORCERELOAD, bNeedsReload) );
581 rReq.AppendItem( SfxBoolItem( SID_SILENT, true ));
583 [[fallthrough]]; //TODO ???
586 case SID_RELOAD:
588 // Due to Double occupancy in toolboxes (with or without Ctrl),
589 // it is also possible that the slot is enabled, but Ctrl-click
590 // despite this is not!
591 if ( !pSh || !pSh->CanReload_Impl() )
592 break;
593 SfxApplication* pApp = SfxGetpApp();
594 const SfxBoolItem* pForceReloadItem = rReq.GetArg<SfxBoolItem>(SID_FORCERELOAD);
595 if( pForceReloadItem && !pForceReloadItem->GetValue() &&
596 !pSh->GetMedium()->IsExpired() )
597 return;
598 if( m_pImpl->bReloading || pSh->IsInModalMode() )
599 return;
601 // AutoLoad is prohibited if possible
602 const SfxBoolItem* pAutoLoadItem = rReq.GetArg<SfxBoolItem>(SID_AUTOLOAD);
603 if ( pAutoLoadItem && pAutoLoadItem->GetValue() &&
604 GetFrame().IsAutoLoadLocked_Impl() )
605 return;
607 SfxObjectShellLock xOldObj( pSh );
608 m_pImpl->bReloading = true;
609 const SfxStringItem* pURLItem = rReq.GetArg<SfxStringItem>(SID_FILE_NAME);
610 // Open as editable?
611 bool bForEdit = !pSh->IsReadOnly();
613 // If possible ask the User
614 bool bDo = GetViewShell()->PrepareClose();
615 const SfxBoolItem* pSilentItem = rReq.GetArg<SfxBoolItem>(SID_SILENT);
616 if ( bDo && GetFrame().DocIsModified_Impl() &&
617 !rReq.IsAPI() && ( !pSilentItem || !pSilentItem->GetValue() ) )
619 std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(GetWindow().GetFrameWeld(),
620 VclMessageType::Question, VclButtonsType::YesNo,
621 SfxResId(STR_QUERY_LASTVERSION)));
622 bDo = RET_YES == xBox->run();
625 if ( bDo )
627 SfxMedium *pMedium = xOldObj->GetMedium();
629 bool bHandsOff =
630 ( pMedium->GetURLObject().GetProtocol() == INetProtocol::File && !xOldObj->IsDocShared() );
632 // Empty existing SfxMDIFrames for this Document
633 // in native format or R/O, open it now for editing?
634 SfxObjectShellLock xNewObj;
636 // collect the views of the document
637 // TODO: when UNO ViewFactories are available for SFX-based documents, the below code should
638 // be UNOized, too
639 typedef ::std::pair< Reference< XFrame >, SfxInterfaceId > ViewDescriptor;
640 ::std::vector< ViewDescriptor > aViewFrames;
641 SfxViewFrame *pView = GetFirst( xOldObj );
642 while ( pView )
644 Reference< XFrame > xFrame( pView->GetFrame().GetFrameInterface() );
645 SAL_WARN_IF( !xFrame.is(), "sfx.view", "SfxViewFrame::ExecReload_Impl: no XFrame?!");
646 aViewFrames.emplace_back( xFrame, pView->GetCurViewId() );
648 pView = GetNext( *pView, xOldObj );
651 xOldObj->Get_Impl()->pReloadTimer.reset();
653 std::unique_ptr<SfxItemSet> pNewSet;
654 std::shared_ptr<const SfxFilter> pFilter = pMedium->GetFilter();
655 if( pURLItem )
657 pNewSet.reset(new SfxAllItemSet( pApp->GetPool() ));
658 pNewSet->Put( *pURLItem );
660 // Filter Detection
661 OUString referer;
662 const SfxStringItem* refererItem = rReq.GetArg<SfxStringItem>(SID_REFERER);
663 if (refererItem != nullptr) {
664 referer = refererItem->GetValue();
666 SfxMedium aMedium( pURLItem->GetValue(), referer, SFX_STREAM_READWRITE );
667 SfxFilterMatcher().GuessFilter( aMedium, pFilter );
668 if ( pFilter )
669 pNewSet->Put( SfxStringItem( SID_FILTER_NAME, pFilter->GetName() ) );
670 pNewSet->Put( *aMedium.GetItemSet() );
672 else
674 pNewSet.reset(new SfxAllItemSet( *pMedium->GetItemSet() ));
675 pNewSet->ClearItem( SID_VIEW_ID );
676 pNewSet->ClearItem( SID_STREAM );
677 pNewSet->ClearItem( SID_INPUTSTREAM );
678 pNewSet->Put( SfxStringItem( SID_FILTER_NAME, pMedium->GetFilter()->GetName() ) );
680 // let the current security settings be checked again
681 pNewSet->Put( SfxUInt16Item( SID_MACROEXECMODE, document::MacroExecMode::USE_CONFIG ) );
683 if ( pSh->IsOriginallyReadOnlyMedium()
684 || pSh->IsOriginallyLoadedReadOnlyMedium() )
685 // edit mode is switched or reload of readonly document
686 pNewSet->Put( SfxBoolItem( SID_DOC_READONLY, true ) );
687 else
688 // Reload of file opened for writing
689 pNewSet->ClearItem( SID_DOC_READONLY );
692 // If a salvaged file is present, do not enclose the OrigURL
693 // again, since the Template is invalid after reload.
694 const SfxStringItem* pSalvageItem = SfxItemSet::GetItem<SfxStringItem>(pNewSet.get(), SID_DOC_SALVAGE, false);
695 if( pSalvageItem )
697 pNewSet->ClearItem( SID_DOC_SALVAGE );
700 #if HAVE_FEATURE_MULTIUSER_ENVIRONMENT
701 // TODO/LATER: Temporary solution, the SfxMedium must know the original URL as aLogicName
702 // SfxMedium::Transfer_Impl() will be forbidden then.
703 if ( xOldObj->IsDocShared() )
704 pNewSet->Put( SfxStringItem( SID_FILE_NAME, xOldObj->GetSharedFileURL() ) );
705 #endif
706 if ( pURLItem )
707 pNewSet->Put( SfxStringItem( SID_REFERER, pMedium->GetName() ) );
708 else
709 pNewSet->Put( SfxStringItem( SID_REFERER, OUString() ) );
711 xOldObj->CancelTransfers();
714 if ( pSilentItem && pSilentItem->GetValue() )
715 pNewSet->Put( SfxBoolItem( SID_SILENT, true ) );
717 const SfxUnoAnyItem* pInteractionItem = SfxItemSet::GetItem<SfxUnoAnyItem>(pNewSet.get(), SID_INTERACTIONHANDLER, false);
718 const SfxUInt16Item* pMacroExecItem = SfxItemSet::GetItem<SfxUInt16Item>(pNewSet.get(), SID_MACROEXECMODE, false);
719 const SfxUInt16Item* pDocTemplateItem = SfxItemSet::GetItem<SfxUInt16Item>(pNewSet.get(), SID_UPDATEDOCMODE, false);
721 if (!pInteractionItem)
723 Reference < task::XInteractionHandler2 > xHdl = task::InteractionHandler::createWithParent( ::comphelper::getProcessComponentContext(), nullptr );
724 if (xHdl.is())
725 pNewSet->Put( SfxUnoAnyItem(SID_INTERACTIONHANDLER,css::uno::makeAny(xHdl)) );
728 if (!pMacroExecItem)
729 pNewSet->Put( SfxUInt16Item(SID_MACROEXECMODE,css::document::MacroExecMode::USE_CONFIG) );
730 if (!pDocTemplateItem)
731 pNewSet->Put( SfxUInt16Item(SID_UPDATEDOCMODE,css::document::UpdateDocMode::ACCORDING_TO_CONFIG) );
733 xOldObj->SetModified( false );
734 // Do not cache the old Document! Is invalid when loading
735 // another document.
737 const SfxStringItem* pSavedOptions = SfxItemSet::GetItem<SfxStringItem>(pMedium->GetItemSet(), SID_FILE_FILTEROPTIONS, false);
738 const SfxStringItem* pSavedReferer = SfxItemSet::GetItem<SfxStringItem>(pMedium->GetItemSet(), SID_REFERER, false);
740 bool bHasStorage = pMedium->HasStorage_Impl();
741 if( bHandsOff )
743 if ( bHasStorage && pMedium->GetStorage() == xOldObj->GetStorage() )
745 // TODO/LATER: faster creation of copy
746 if ( !xOldObj->ConnectTmpStorage_Impl( pMedium->GetStorage(), pMedium ) )
747 return;
750 pMedium->CloseAndRelease();
753 xNewObj = SfxObjectShell::CreateObject( pFilter->GetServiceName() );
755 if ( xOldObj->IsModifyPasswordEntered() )
756 xNewObj->SetModifyPasswordEntered();
758 uno::Sequence < beans::PropertyValue > aLoadArgs;
759 TransformItems( SID_OPENDOC, *pNewSet, aLoadArgs );
762 uno::Reference < frame::XLoadable > xLoad( xNewObj->GetModel(), uno::UNO_QUERY );
763 xLoad->load( aLoadArgs );
765 catch ( uno::Exception& )
767 xNewObj->DoClose();
768 xNewObj = nullptr;
771 pNewSet.reset();
773 if( !xNewObj.Is() )
775 if( bHandsOff )
777 // back to old medium
778 pMedium->ReOpen();
779 pMedium->LockOrigFileOnDemand( false, true );
781 xOldObj->DoSaveCompleted( pMedium );
784 // r/o-Doc couldn't be switched to writing mode
785 if ( bForEdit && ( SID_EDITDOC == rReq.GetSlot() || SID_READONLYDOC == rReq.GetSlot() ) )
787 // ask user for opening as template
788 std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(GetWindow().GetFrameWeld(),
789 VclMessageType::Question, VclButtonsType::YesNo,
790 SfxResId(STR_QUERY_OPENASTEMPLATE)));
791 if (RET_YES == xBox->run())
793 SfxAllItemSet aSet( pApp->GetPool() );
794 aSet.Put( SfxStringItem( SID_FILE_NAME, pMedium->GetName() ) );
795 aSet.Put( SfxStringItem( SID_TARGETNAME, "_blank" ) );
796 if ( pSavedOptions )
797 aSet.Put( *pSavedOptions );
798 if ( pSavedReferer )
799 aSet.Put( *pSavedReferer );
800 aSet.Put( SfxBoolItem( SID_TEMPLATE, true ) );
801 if( pFilter )
802 aSet.Put( SfxStringItem( SID_FILTER_NAME, pFilter->GetFilterName() ) );
803 GetDispatcher()->Execute( SID_OPENDOC, SfxCallMode::ASYNCHRON, aSet );
807 else
809 if ( xNewObj->GetModifyPasswordHash() && xNewObj->GetModifyPasswordHash() != xOldObj->GetModifyPasswordHash() )
811 xNewObj->SetModifyPasswordEntered( false );
812 xNewObj->SetReadOnly();
814 else if ( rReq.GetSlot() == SID_EDITDOC || rReq.GetSlot() == SID_READONLYDOC )
816 xNewObj->SetReadOnlyUI( !bForEdit );
819 #if HAVE_FEATURE_MULTIUSER_ENVIRONMENT
820 if ( xNewObj->IsDocShared() )
822 // the file is shared but the closing can change the sharing control file
823 xOldObj->DoNotCleanShareControlFile();
825 #endif
826 // the Reload and Silent items were only temporary, remove them
827 xNewObj->GetMedium()->GetItemSet()->ClearItem( SID_RELOAD );
828 xNewObj->GetMedium()->GetItemSet()->ClearItem( SID_SILENT );
829 TransformItems( SID_OPENDOC, *xNewObj->GetMedium()->GetItemSet(), aLoadArgs );
831 UpdateDocument_Impl();
833 if (vcl::CommandInfoProvider::GetModuleIdentifier(GetFrame().GetFrameInterface()) == "com.sun.star.text.TextDocument")
834 sfx2::SfxNotebookBar::ReloadNotebookBar("modules/swriter/ui/");
838 for (auto const& viewFrame : aViewFrames)
840 LoadViewIntoFrame_Impl( *xNewObj, viewFrame.first, aLoadArgs, viewFrame.second, false );
842 aViewFrames.clear();
844 catch( const Exception& )
846 // close the remaining frames
847 // Don't catch exceptions herein, if this fails, then we're left in an indetermined state, and
848 // crashing is better than trying to proceed
849 for (auto const& viewFrame : aViewFrames)
851 Reference< util::XCloseable > xClose( viewFrame.first, UNO_QUERY_THROW );
852 xClose->close( true );
854 aViewFrames.clear();
857 const SfxInt32Item* pPageNumber = rReq.GetArg<SfxInt32Item>(SID_PAGE_NUMBER);
858 if (pPageNumber && pPageNumber->GetValue() >= 0)
860 // Restore current page after reload.
861 uno::Reference<drawing::XDrawView> xController(
862 xNewObj->GetModel()->getCurrentController(), uno::UNO_QUERY);
863 uno::Reference<drawing::XDrawPagesSupplier> xSupplier(xNewObj->GetModel(),
864 uno::UNO_QUERY);
865 uno::Reference<drawing::XDrawPages> xDrawPages = xSupplier->getDrawPages();
866 uno::Reference<drawing::XDrawPage> xDrawPage(
867 xDrawPages->getByIndex(pPageNumber->GetValue()), uno::UNO_QUERY);
868 xController->setCurrentPage(xDrawPage);
871 // Propagate document closure.
872 SfxGetpApp()->NotifyEvent( SfxEventHint( SfxEventHintId::CloseDoc, GlobalEventConfig::GetEventName( GlobalEventId::CLOSEDOC ), xOldObj ) );
875 // Record as done
876 rReq.Done( true );
877 rReq.SetReturnValue(SfxBoolItem(rReq.GetSlot(), true));
878 return;
880 else
882 // Record as not done
883 rReq.Done();
884 rReq.SetReturnValue(SfxBoolItem(rReq.GetSlot(), false));
885 m_pImpl->bReloading = false;
886 return;
892 void SfxViewFrame::StateReload_Impl( SfxItemSet& rSet )
894 SfxObjectShell* pSh = GetObjectShell();
895 if ( !pSh )
897 // I'm just on reload and am yielding myself ...
898 return;
901 SfxWhichIter aIter( rSet );
902 for ( sal_uInt16 nWhich = aIter.FirstWhich(); nWhich; nWhich = aIter.NextWhich() )
904 switch ( nWhich )
906 case SID_EDITDOC:
907 case SID_READONLYDOC:
909 const SfxViewShell *pVSh;
910 const SfxShell *pFSh;
911 if ( !pSh->HasName() ||
912 !( pSh->Get_Impl()->nLoadedFlags & SfxLoadedFlags::MAINDOCUMENT ) ||
913 (pSh->isEditDocLocked()) ||
914 ( pSh->GetCreateMode() == SfxObjectCreateMode::EMBEDDED &&
915 ( !(pVSh = pSh->GetViewShell()) ||
916 !(pFSh = pVSh->GetFormShell()) ||
917 !pFSh->IsDesignMode())))
918 rSet.DisableItem( nWhich );
919 else
921 const SfxBoolItem* pItem = SfxItemSet::GetItem<SfxBoolItem>(pSh->GetMedium()->GetItemSet(), SID_EDITDOC, false);
922 if ( pItem && !pItem->GetValue() )
923 rSet.DisableItem( nWhich );
924 else
926 if (nWhich==SID_EDITDOC)
927 rSet.Put( SfxBoolItem( nWhich, !pSh->IsReadOnly() ) );
928 else if (nWhich==SID_READONLYDOC)
929 rSet.Put( SfxBoolItem( nWhich, pSh->IsReadOnly() ) );
932 break;
935 case SID_RELOAD:
937 if ( !pSh->CanReload_Impl() || pSh->GetCreateMode() == SfxObjectCreateMode::EMBEDDED )
938 rSet.DisableItem(nWhich);
939 else
941 // If any ChildFrame is reloadable, the slot is enabled,
942 // so you can perform CTRL-Reload
943 rSet.Put( SfxBoolItem( nWhich, false));
946 break;
952 void SfxViewFrame::ExecHistory_Impl( SfxRequest &rReq )
954 // Is there an Undo-Manager on the top Shell?
955 SfxShell *pSh = GetDispatcher()->GetShell(0);
956 SfxUndoManager* pShUndoMgr = pSh->GetUndoManager();
957 bool bOK = false;
958 if ( pShUndoMgr )
960 switch ( rReq.GetSlot() )
962 case SID_CLEARHISTORY:
963 pShUndoMgr->Clear();
964 bOK = true;
965 break;
967 case SID_UNDO:
968 pShUndoMgr->Undo();
969 GetBindings().InvalidateAll(false);
970 bOK = true;
971 break;
973 case SID_REDO:
974 pShUndoMgr->Redo();
975 GetBindings().InvalidateAll(false);
976 bOK = true;
977 break;
979 case SID_REPEAT:
980 if ( pSh->GetRepeatTarget() )
981 pShUndoMgr->Repeat( *pSh->GetRepeatTarget() );
982 bOK = true;
983 break;
986 else if ( GetViewShell() )
988 // The SW has its own undo in the View
989 const SfxPoolItem *pRet = GetViewShell()->ExecuteSlot( rReq );
990 if ( pRet )
991 bOK = static_cast<const SfxBoolItem*>(pRet)->GetValue();
994 rReq.SetReturnValue( SfxBoolItem( rReq.GetSlot(), bOK ) );
995 rReq.Done();
998 void SfxViewFrame::StateHistory_Impl( SfxItemSet &rSet )
1000 // Search for Undo-Manager
1001 SfxShell *pSh = GetDispatcher()->GetShell(0);
1002 if ( !pSh )
1003 // I'm just on reload and am yielding myself ...
1004 return;
1006 SfxUndoManager *pShUndoMgr = pSh->GetUndoManager();
1007 if ( !pShUndoMgr )
1009 // The SW has its own undo in the View
1010 SfxWhichIter aIter( rSet );
1011 SfxViewShell *pViewSh = GetViewShell();
1012 if( !pViewSh ) return;
1013 for ( sal_uInt16 nSID = aIter.FirstWhich(); nSID; nSID = aIter.NextWhich() )
1014 pViewSh->GetSlotState( nSID, nullptr, &rSet );
1015 return;
1018 if ( pShUndoMgr->GetUndoActionCount() == 0 &&
1019 pShUndoMgr->GetRedoActionCount() == 0 &&
1020 pShUndoMgr->GetRepeatActionCount() == 0 )
1021 rSet.DisableItem( SID_CLEARHISTORY );
1023 if (pShUndoMgr->GetUndoActionCount())
1025 const SfxUndoAction* pAction = pShUndoMgr->GetUndoAction();
1026 SfxViewShell *pViewSh = GetViewShell();
1027 if (pViewSh && pAction->GetViewShellId() != pViewSh->GetViewShellId())
1029 rSet.Put(SfxUInt32Item(SID_UNDO, static_cast<sal_uInt32>(SID_REPAIRPACKAGE)));
1031 else
1033 rSet.Put( SfxStringItem( SID_UNDO, SvtResId(STR_UNDO)+pShUndoMgr->GetUndoActionComment() ) );
1036 else
1037 rSet.DisableItem( SID_UNDO );
1039 if (pShUndoMgr->GetRedoActionCount())
1041 const SfxUndoAction* pAction = pShUndoMgr->GetRedoAction();
1042 SfxViewShell *pViewSh = GetViewShell();
1043 if (pViewSh && pAction->GetViewShellId() != pViewSh->GetViewShellId())
1045 rSet.Put(SfxUInt32Item(SID_REDO, static_cast<sal_uInt32>(SID_REPAIRPACKAGE)));
1047 else
1049 rSet.Put(SfxStringItem(SID_REDO, SvtResId(STR_REDO) + pShUndoMgr->GetRedoActionComment()));
1052 else
1053 rSet.DisableItem( SID_REDO );
1055 SfxRepeatTarget *pTarget = pSh->GetRepeatTarget();
1056 if (pTarget && pShUndoMgr->GetRepeatActionCount() && pShUndoMgr->CanRepeat(*pTarget))
1057 rSet.Put( SfxStringItem( SID_REPEAT, SvtResId(STR_REPEAT)+pShUndoMgr->GetRepeatActionComment(*pTarget) ) );
1058 else
1059 rSet.DisableItem( SID_REPEAT );
1062 void SfxViewFrame::PopShellAndSubShells_Impl( SfxViewShell& i_rViewShell )
1064 i_rViewShell.PopSubShells_Impl();
1065 sal_uInt16 nLevel = m_pDispatcher->GetShellLevel( i_rViewShell );
1066 if ( nLevel != USHRT_MAX )
1068 if ( nLevel )
1070 // more sub shells on the stack, which were not affected by PopSubShells_Impl
1071 SfxShell *pSubShell = m_pDispatcher->GetShell( nLevel-1 );
1072 m_pDispatcher->Pop( *pSubShell, SfxDispatcherPopFlags::POP_UNTIL | SfxDispatcherPopFlags::POP_DELETE );
1074 m_pDispatcher->Pop( i_rViewShell );
1075 m_pDispatcher->Flush();
1080 /* [Description]
1082 This method empties the SfxViewFrame, i.e. takes the <SfxObjectShell>
1083 from the dispatcher and ends its <SfxListener> Relationship to this
1084 SfxObjectShell (by which they may even destroy themselves).
1086 Thus, by invoking ReleaseObjectShell() and SetObjectShell() the
1087 SfxObjectShell can be replaced.
1089 Between ReleaseObjectShell() and SetObjectShell() the control cannot
1090 be handed over to the system.
1092 [Cross-reference]
1094 <SfxViewFrame::SetObjectShell(SfxObjectShell&)>
1096 void SfxViewFrame::ReleaseObjectShell_Impl()
1098 DBG_ASSERT( m_xObjSh.is(), "no SfxObjectShell to release!" );
1100 GetFrame().ReleasingComponent_Impl();
1101 if ( GetWindow().HasChildPathFocus( true ) )
1103 GetWindow().GrabFocus();
1106 SfxViewShell *pDyingViewSh = GetViewShell();
1107 if ( pDyingViewSh )
1109 PopShellAndSubShells_Impl( *pDyingViewSh );
1110 pDyingViewSh->DisconnectAllClients();
1111 SetViewShell_Impl(nullptr);
1112 delete pDyingViewSh;
1114 #ifdef DBG_UTIL
1115 else
1116 OSL_FAIL("No Shell");
1117 #endif
1119 if ( m_xObjSh.is() )
1121 m_pDispatcher->Pop( *m_xObjSh );
1122 SfxModule* pModule = m_xObjSh->GetModule();
1123 if( pModule )
1124 m_pDispatcher->RemoveShell_Impl( *pModule );
1125 m_pDispatcher->Flush();
1126 EndListening( *m_xObjSh );
1128 Notify( *m_xObjSh, SfxHint(SfxHintId::TitleChanged) );
1129 Notify( *m_xObjSh, SfxHint(SfxHintId::DocChanged) );
1131 if ( 1 == m_xObjSh->GetOwnerLockCount() && m_pImpl->bObjLocked && m_xObjSh->GetCreateMode() == SfxObjectCreateMode::EMBEDDED )
1132 m_xObjSh->DoClose();
1133 SfxObjectShellRef xDyingObjSh = m_xObjSh;
1134 m_xObjSh.clear();
1135 if( GetFrame().GetHasTitle() && m_pImpl->nDocViewNo )
1136 xDyingObjSh->GetNoSet_Impl().ReleaseIndex(m_pImpl->nDocViewNo-1);
1137 if ( m_pImpl->bObjLocked )
1139 xDyingObjSh->OwnerLock( false );
1140 m_pImpl->bObjLocked = false;
1144 GetDispatcher()->SetDisableFlags( SfxDisableFlags::NONE );
1147 void SfxViewFrame::Close()
1150 DBG_ASSERT( GetFrame().IsClosing_Impl() || !GetFrame().GetFrameInterface().is(), "ViewFrame closed too early!" );
1152 // If no saving have been made up until now, then embedded Objects should
1153 // not be saved automatically anymore.
1154 if ( GetViewShell() )
1155 GetViewShell()->DisconnectAllClients();
1156 Broadcast( SfxHint( SfxHintId::Dying ) );
1158 if (SfxViewFrame::Current() == this)
1159 SfxViewFrame::SetViewFrame( nullptr );
1161 // Since the Dispatcher is emptied, it can not be used in any reasonable
1162 // manner, thus it is better to let the dispatcher be.
1163 GetDispatcher()->Lock(true);
1164 delete this;
1167 void SfxViewFrame::DoActivate( bool bUI )
1169 m_pDispatcher->DoActivate_Impl( bUI );
1172 void SfxViewFrame::DoDeactivate(bool bUI, SfxViewFrame const * pNewFrame )
1174 m_pDispatcher->DoDeactivate_Impl( bUI, pNewFrame );
1177 void SfxViewFrame::InvalidateBorderImpl( const SfxViewShell* pSh )
1179 if( !pSh || m_nAdjustPosPixelLock )
1180 return;
1182 if ( GetViewShell() && GetWindow().IsVisible() )
1184 if ( GetFrame().IsInPlace() )
1186 return;
1189 DoAdjustPosSizePixel( GetViewShell(), Point(),
1190 GetWindow().GetOutputSizePixel(),
1191 false );
1195 void SfxViewFrame::SetBorderPixelImpl
1197 const SfxViewShell* pVSh,
1198 const SvBorder& rBorder
1202 m_pImpl->aBorder = rBorder;
1204 if ( m_pImpl->bResizeInToOut && !GetFrame().IsInPlace() )
1206 Size aSize = pVSh->GetWindow()->GetOutputSizePixel();
1207 if ( aSize.Width() && aSize.Height() )
1209 aSize.AdjustWidth(rBorder.Left() + rBorder.Right() );
1210 aSize.AdjustHeight(rBorder.Top() + rBorder.Bottom() );
1212 Size aOldSize = GetWindow().GetOutputSizePixel();
1213 GetWindow().SetOutputSizePixel( aSize );
1214 vcl::Window* pParent = &GetWindow();
1215 while ( pParent->GetParent() )
1216 pParent = pParent->GetParent();
1217 Size aOuterSize = pParent->GetOutputSizePixel();
1218 aOuterSize.AdjustWidth( aSize.Width() - aOldSize.Width() );
1219 aOuterSize.AdjustHeight( aSize.Height() - aOldSize.Height() );
1220 pParent->SetOutputSizePixel( aOuterSize );
1223 else
1225 tools::Rectangle aEditArea( Point(), GetWindow().GetOutputSizePixel() );
1226 aEditArea.AdjustLeft(rBorder.Left() );
1227 aEditArea.AdjustRight( -(rBorder.Right()) );
1228 aEditArea.AdjustTop(rBorder.Top() );
1229 aEditArea.AdjustBottom( -(rBorder.Bottom()) );
1230 pVSh->GetWindow()->SetPosSizePixel( aEditArea.TopLeft(), aEditArea.GetSize() );
1234 const SvBorder& SfxViewFrame::GetBorderPixelImpl() const
1236 return m_pImpl->aBorder;
1239 void SfxViewFrame::AppendReadOnlyInfobar()
1241 bool bSignPDF = m_xObjSh->IsSignPDF();
1242 bool bSignWithCert = false;
1243 if (bSignPDF)
1245 SfxObjectShell* pObjectShell = GetObjectShell();
1246 uno::Reference<security::XCertificate> xCertificate = pObjectShell->GetSignPDFCertificate();
1247 bSignWithCert = xCertificate.is();
1250 auto pInfoBar = AppendInfoBar("readonly", "",
1251 SfxResId(bSignPDF ? STR_READONLY_PDF : STR_READONLY_DOCUMENT),
1252 InfobarType::INFO);
1253 if (!pInfoBar)
1254 return;
1256 if (bSignPDF)
1258 // SID_SIGNPDF opened a read-write PDF
1259 // read-only for signing purposes.
1260 weld::Button& rSignButton = pInfoBar->addButton();
1261 if (bSignWithCert)
1263 rSignButton.set_label(SfxResId(STR_READONLY_FINISH_SIGN));
1265 else
1267 rSignButton.set_label(SfxResId(STR_READONLY_SIGN));
1270 rSignButton.connect_clicked(LINK(this, SfxViewFrame, SignDocumentHandler));
1273 bool showEditDocumentButton = true;
1274 if (m_xObjSh->isEditDocLocked())
1275 showEditDocumentButton = false;
1277 if (showEditDocumentButton)
1279 weld::Button& rBtn = pInfoBar->addButton();
1280 rBtn.set_label(SfxResId(STR_READONLY_EDIT));
1281 rBtn.connect_clicked(LINK(this, SfxViewFrame, SwitchReadOnlyHandler));
1285 void SfxViewFrame::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint )
1287 if(m_pImpl->bIsDowning)
1288 return;
1290 // we know only SfxEventHint or simple SfxHint
1291 if (const SfxEventHint* pEventHint = dynamic_cast<const SfxEventHint*>(&rHint))
1293 // When the Document is loaded asynchronously, was the Dispatcher
1294 // set as ReadOnly, to what must be returned when the document itself
1295 // is not read only, and the loading is finished.
1296 switch ( pEventHint->GetEventId() )
1298 case SfxEventHintId::ModifyChanged:
1300 SfxBindings& rBind = GetBindings();
1301 rBind.Invalidate( SID_DOC_MODIFIED );
1302 rBind.Invalidate( SID_RELOAD );
1303 rBind.Invalidate( SID_EDITDOC );
1304 break;
1307 case SfxEventHintId::OpenDoc:
1308 case SfxEventHintId::CreateDoc:
1310 if ( !m_xObjSh.is() )
1311 break;
1313 SfxBindings& rBind = GetBindings();
1314 rBind.Invalidate( SID_RELOAD );
1315 rBind.Invalidate( SID_EDITDOC );
1317 const auto t0 = std::chrono::system_clock::now().time_since_epoch();
1319 bool bIsUITest = false; //uitest.uicheck fails when the dialog is open
1320 for( sal_uInt16 i = 0; i < Application::GetCommandLineParamCount(); i++ )
1322 if( Application::GetCommandLineParam(i) == "--nologo" )
1323 bIsUITest = true;
1326 //what's new infobar
1327 OUString sSetupVersion = utl::ConfigManager::getProductVersion();
1328 sal_Int32 iCurrent = sSetupVersion.getToken(0,'.').toInt32() * 10 + sSetupVersion.getToken(1,'.').toInt32();
1329 OUString sLastVersion
1330 = officecfg::Setup::Product::ooSetupLastVersion::get().value_or("0.0");
1331 sal_Int32 iLast = sLastVersion.getToken(0,'.').toInt32() * 10 + sLastVersion.getToken(1,'.').toInt32();
1332 if ((iCurrent > iLast) && !Application::IsHeadlessModeEnabled() && !bIsUITest)
1334 VclPtr<SfxInfoBarWindow> pInfoBar = AppendInfoBar("whatsnew", "", SfxResId(STR_WHATSNEW_TEXT), InfobarType::INFO);
1335 if (pInfoBar)
1337 weld::Button& rWhatsNewButton = pInfoBar->addButton();
1338 rWhatsNewButton.set_label(SfxResId(STR_WHATSNEW_BUTTON));
1339 rWhatsNewButton.connect_clicked(LINK(this, SfxViewFrame, WhatsNewHandler));
1341 //update lastversion
1342 std::shared_ptr<comphelper::ConfigurationChanges> batch(comphelper::ConfigurationChanges::create());
1343 officecfg::Setup::Product::ooSetupLastVersion::set(sSetupVersion, batch);
1344 batch->commit();
1347 // show tip-of-the-day dialog
1348 const bool bShowTipOfTheDay = officecfg::Office::Common::Misc::ShowTipOfTheDay::get();
1349 if (bShowTipOfTheDay && !Application::IsHeadlessModeEnabled() && !bIsUITest) {
1350 const sal_Int32 nLastTipOfTheDay = officecfg::Office::Common::Misc::LastTipOfTheDayShown::get();
1351 const sal_Int32 nDay = std::chrono::duration_cast<std::chrono::hours>(t0).count()/24; // days since 1970-01-01
1352 if (nDay-nLastTipOfTheDay > 0) { //only once per day
1353 // tdf#127946 pass in argument for dialog parent
1354 SfxUnoFrameItem aDocFrame(SID_FILLFRAME, GetFrame().GetFrameInterface());
1355 GetDispatcher()->ExecuteList(SID_TIPOFTHEDAY, SfxCallMode::SLOT, {}, { &aDocFrame });
1357 } //bShowTipOfTheDay
1359 // inform about the community involvement
1360 const sal_Int64 nLastGetInvolvedShown = officecfg::Setup::Product::LastTimeGetInvolvedShown::get();
1361 const sal_Int64 nNow = std::chrono::duration_cast<std::chrono::seconds>(t0).count();
1362 const sal_Int64 nPeriodSec(60 * 60 * 24 * 180); // 180 days in seconds
1363 bool bUpdateLastTimeGetInvolvedShown = false;
1365 if (nLastGetInvolvedShown == 0)
1366 bUpdateLastTimeGetInvolvedShown = true;
1367 else if (nPeriodSec < nNow && nLastGetInvolvedShown < (nNow + nPeriodSec/2) - nPeriodSec) // 90d alternating with donation
1369 bUpdateLastTimeGetInvolvedShown = true;
1371 VclPtr<SfxInfoBarWindow> pInfoBar = AppendInfoBar("getinvolved", "", SfxResId(STR_GET_INVOLVED_TEXT), InfobarType::INFO);
1373 if (pInfoBar)
1375 weld::Button& rGetInvolvedButton = pInfoBar->addButton();
1376 rGetInvolvedButton.set_label(SfxResId(STR_GET_INVOLVED_BUTTON));
1377 rGetInvolvedButton.connect_clicked(LINK(this, SfxViewFrame, GetInvolvedHandler));
1381 if (bUpdateLastTimeGetInvolvedShown
1382 && !officecfg::Setup::Product::LastTimeGetInvolvedShown::isReadOnly())
1384 std::shared_ptr<comphelper::ConfigurationChanges> batch(comphelper::ConfigurationChanges::create());
1385 officecfg::Setup::Product::LastTimeGetInvolvedShown::set(nNow, batch);
1386 batch->commit();
1389 // inform about donations
1390 const sal_Int64 nLastDonateShown = officecfg::Setup::Product::LastTimeDonateShown::get();
1391 bool bUpdateLastTimeDonateShown = false;
1393 if (nLastDonateShown == 0)
1394 bUpdateLastTimeDonateShown = true;
1395 else if (nPeriodSec < nNow && nLastDonateShown < nNow - nPeriodSec) // 90d alternating with getinvolved
1397 bUpdateLastTimeDonateShown = true;
1399 VclPtr<SfxInfoBarWindow> pInfoBar = AppendInfoBar("donate", "", SfxResId(STR_DONATE_TEXT), InfobarType::INFO);
1400 if (pInfoBar)
1402 weld::Button& rDonateButton = pInfoBar->addButton();
1403 rDonateButton.set_label(SfxResId(STR_DONATE_BUTTON));
1404 rDonateButton.connect_clicked(LINK(this, SfxViewFrame, DonationHandler));
1408 if (bUpdateLastTimeDonateShown
1409 && !officecfg::Setup::Product::LastTimeDonateShown::isReadOnly())
1411 std::shared_ptr<comphelper::ConfigurationChanges> batch(comphelper::ConfigurationChanges::create());
1412 officecfg::Setup::Product::LastTimeDonateShown::set(nNow, batch);
1413 batch->commit();
1416 // read-only infobar if necessary
1417 const SfxViewShell *pVSh;
1418 const SfxShell *pFSh;
1419 if ( m_xObjSh->IsReadOnly() &&
1420 ! m_xObjSh->IsSecurityOptOpenReadOnly() &&
1421 ( m_xObjSh->GetCreateMode() != SfxObjectCreateMode::EMBEDDED ||
1422 (( pVSh = m_xObjSh->GetViewShell()) && (pFSh = pVSh->GetFormShell()) && pFSh->IsDesignMode())))
1424 AppendReadOnlyInfobar();
1427 if (vcl::CommandInfoProvider::GetModuleIdentifier(GetFrame().GetFrameInterface()) == "com.sun.star.text.TextDocument")
1428 sfx2::SfxNotebookBar::ReloadNotebookBar("modules/swriter/ui/");
1430 if (SfxClassificationHelper::IsClassified(m_xObjSh->getDocProperties()))
1432 // Document has BAILS properties, display an infobar accordingly.
1433 SfxClassificationHelper aHelper(m_xObjSh->getDocProperties());
1434 aHelper.UpdateInfobar(*this);
1437 // Add pending infobars
1438 std::vector<InfobarData>& aPendingInfobars = m_xObjSh->getPendingInfobars();
1439 while (!aPendingInfobars.empty())
1441 InfobarData& aInfobarData = aPendingInfobars.back();
1442 AppendInfoBar(aInfobarData.msId, aInfobarData.msPrimaryMessage,
1443 aInfobarData.msSecondaryMessage, aInfobarData.maInfobarType,
1444 aInfobarData.mbShowCloseButton);
1445 aPendingInfobars.pop_back();
1448 break;
1450 default: break;
1453 else
1455 switch( rHint.GetId() )
1457 case SfxHintId::ModeChanged:
1459 UpdateTitle();
1461 if ( !m_xObjSh.is() )
1462 break;
1464 // Switch r/o?
1465 SfxBindings& rBind = GetBindings();
1466 rBind.Invalidate( SID_RELOAD );
1467 SfxDispatcher *pDispat = GetDispatcher();
1468 bool bWasReadOnly = pDispat->GetReadOnly_Impl();
1469 bool bIsReadOnly = m_xObjSh->IsReadOnly();
1470 if ( bWasReadOnly != bIsReadOnly )
1472 // Then also TITLE_CHANGED
1473 UpdateTitle();
1474 rBind.Invalidate( SID_FILE_NAME );
1475 rBind.Invalidate( SID_DOCINFO_TITLE );
1476 rBind.Invalidate( SID_EDITDOC );
1478 pDispat->GetBindings()->InvalidateAll(true);
1479 pDispat->SetReadOnly_Impl( bIsReadOnly );
1481 // Only force and Dispatcher-Update, if it is done next
1482 // anyway, otherwise flickering or GPF is possible since
1483 // the Writer for example prefers in Resize perform some
1484 // actions which has a SetReadOnlyUI in Dispatcher as a
1485 // result!
1487 if ( pDispat->IsUpdated_Impl() )
1488 pDispat->Update_Impl(true);
1491 Enable( !m_xObjSh->IsInModalMode() );
1492 break;
1495 case SfxHintId::TitleChanged:
1497 UpdateTitle();
1498 SfxBindings& rBind = GetBindings();
1499 rBind.Invalidate( SID_FILE_NAME );
1500 rBind.Invalidate( SID_DOCINFO_TITLE );
1501 rBind.Invalidate( SID_EDITDOC );
1502 rBind.Invalidate( SID_RELOAD );
1503 break;
1506 case SfxHintId::DocumentRepair:
1508 GetBindings().Invalidate( SID_DOC_REPAIR );
1509 break;
1512 case SfxHintId::Deinitializing:
1514 vcl::Window* pFrameWin = GetWindow().GetFrameWindow();
1515 if (pFrameWin && pFrameWin->GetLOKNotifier())
1516 pFrameWin->ReleaseLOKNotifier();
1518 GetFrame().DoClose();
1519 break;
1521 case SfxHintId::Dying:
1522 // when the Object is being deleted, destroy the view too
1523 if ( m_xObjSh.is() )
1524 ReleaseObjectShell_Impl();
1525 else
1526 GetFrame().DoClose();
1527 break;
1528 default: break;
1533 IMPL_LINK_NOARG(SfxViewFrame, WhatsNewHandler, weld::Button&, void)
1535 GetDispatcher()->Execute(SID_WHATSNEW);
1538 IMPL_LINK_NOARG(SfxViewFrame, GetInvolvedHandler, weld::Button&, void)
1540 GetDispatcher()->Execute(SID_GETINVOLVED);
1543 IMPL_LINK_NOARG(SfxViewFrame, DonationHandler, weld::Button&, void)
1545 GetDispatcher()->Execute(SID_DONATION);
1548 IMPL_LINK(SfxViewFrame, SwitchReadOnlyHandler, weld::Button&, rButton, void)
1550 if (m_xObjSh.is() && m_xObjSh->IsSignPDF())
1552 SfxEditDocumentDialog aDialog(&rButton);
1553 if (aDialog.run() != RET_OK)
1554 return;
1556 GetDispatcher()->Execute(SID_EDITDOC);
1559 IMPL_LINK_NOARG(SfxViewFrame, SignDocumentHandler, weld::Button&, void)
1561 GetDispatcher()->Execute(SID_SIGNATURE);
1564 void SfxViewFrame::Construct_Impl( SfxObjectShell *pObjSh )
1566 m_pImpl->bResizeInToOut = true;
1567 m_pImpl->bObjLocked = false;
1568 m_pImpl->nCurViewId = SFX_INTERFACE_NONE;
1569 m_pImpl->bReloading = false;
1570 m_pImpl->bIsDowning = false;
1571 m_pImpl->bModal = false;
1572 m_pImpl->bEnabled = true;
1573 m_pImpl->nDocViewNo = 0;
1574 m_pImpl->aMargin = Size( -1, -1 );
1575 m_pImpl->pWindow = nullptr;
1577 SetPool( &SfxGetpApp()->GetPool() );
1578 m_pDispatcher.reset( new SfxDispatcher(this) );
1579 if ( !GetBindings().GetDispatcher() )
1580 GetBindings().SetDispatcher( m_pDispatcher.get() );
1582 m_xObjSh = pObjSh;
1583 if ( m_xObjSh.is() && m_xObjSh->IsPreview() )
1584 GetDispatcher()->SetQuietMode_Impl( true );
1586 if ( pObjSh )
1588 m_pDispatcher->Push( *SfxGetpApp() );
1589 SfxModule* pModule = m_xObjSh->GetModule();
1590 if( pModule )
1591 m_pDispatcher->Push( *pModule );
1592 m_pDispatcher->Push( *this );
1593 m_pDispatcher->Push( *pObjSh );
1594 m_pDispatcher->Flush();
1595 StartListening( *pObjSh );
1596 Notify( *pObjSh, SfxHint(SfxHintId::TitleChanged) );
1597 Notify( *pObjSh, SfxHint(SfxHintId::DocChanged) );
1598 m_pDispatcher->SetReadOnly_Impl( pObjSh->IsReadOnly() );
1600 else
1602 m_pDispatcher->Push( *SfxGetpApp() );
1603 m_pDispatcher->Push( *this );
1604 m_pDispatcher->Flush();
1607 SfxViewFrameArr_Impl &rViewArr = SfxGetpApp()->GetViewFrames_Impl();
1608 rViewArr.push_back( this );
1611 /* [Description]
1613 Constructor of SfxViewFrame for a <SfxObjectShell> from the Resource.
1614 The 'nViewId' to the created <SfxViewShell> can be returned.
1615 (default is the SfxViewShell-Subclass that was registered first).
1617 SfxViewFrame::SfxViewFrame
1619 SfxFrame& rFrame,
1620 SfxObjectShell* pObjShell
1622 : m_pImpl( new SfxViewFrame_Impl( rFrame ) )
1623 , m_pBindings( new SfxBindings )
1624 , m_pHelpData(CreateSVHelpData())
1625 , m_pWinData(CreateSVWinData())
1626 , m_nAdjustPosPixelLock( 0 )
1629 rFrame.SetCurrentViewFrame_Impl( this );
1630 rFrame.SetHasTitle( true );
1631 Construct_Impl( pObjShell );
1633 m_pImpl->pWindow = VclPtr<SfxFrameViewWindow_Impl>::Create( this, rFrame.GetWindow() );
1634 m_pImpl->pWindow->SetSizePixel( rFrame.GetWindow().GetOutputSizePixel() );
1635 rFrame.SetOwnsBindings_Impl( true );
1636 rFrame.CreateWorkWindow_Impl();
1639 SfxViewFrame::~SfxViewFrame()
1641 m_pImpl->bIsDowning = true;
1643 if ( SfxViewFrame::Current() == this )
1644 SfxViewFrame::SetViewFrame( nullptr );
1646 ReleaseObjectShell_Impl();
1648 if ( GetFrame().OwnsBindings_Impl() )
1649 // The Bindings delete the Frame!
1650 KillDispatcher_Impl();
1652 m_pImpl->pWindow.disposeAndClear();
1654 if ( GetFrame().GetCurrentViewFrame() == this )
1655 GetFrame().SetCurrentViewFrame_Impl( nullptr );
1657 // Unregister from the Frame List.
1658 SfxApplication *pSfxApp = SfxApplication::Get();
1659 if (pSfxApp)
1661 SfxViewFrameArr_Impl &rFrames = pSfxApp->GetViewFrames_Impl();
1662 SfxViewFrameArr_Impl::iterator it = std::find( rFrames.begin(), rFrames.end(), this );
1663 rFrames.erase( it );
1666 // Delete Member
1667 KillDispatcher_Impl();
1669 DestroySVHelpData(m_pHelpData);
1670 m_pHelpData = nullptr;
1672 DestroySVWinData(m_pWinData);
1673 m_pWinData = nullptr;
1676 // Remove and delete the Dispatcher.
1677 void SfxViewFrame::KillDispatcher_Impl()
1680 SfxModule* pModule = m_xObjSh.is() ? m_xObjSh->GetModule() : nullptr;
1681 if ( m_xObjSh.is() )
1682 ReleaseObjectShell_Impl();
1683 if ( m_pDispatcher )
1685 if( pModule )
1686 m_pDispatcher->Pop( *pModule, SfxDispatcherPopFlags::POP_UNTIL );
1687 else
1688 m_pDispatcher->Pop( *this );
1689 m_pDispatcher.reset();
1693 SfxViewFrame* SfxViewFrame::Current()
1695 SfxApplication* pApp = SfxApplication::Get();
1696 return pApp ? pApp->Get_Impl()->pViewFrame : nullptr;
1699 // returns the first window of spec. type viewing the specified doc.
1700 SfxViewFrame* SfxViewFrame::GetFirst
1702 const SfxObjectShell* pDoc,
1703 bool bOnlyIfVisible
1706 SfxApplication *pSfxApp = SfxApplication::Get();
1707 if (!pSfxApp)
1708 return nullptr;
1710 SfxViewFrameArr_Impl &rFrames = pSfxApp->GetViewFrames_Impl();
1712 // search for a SfxDocument of the specified type
1713 for (SfxViewFrame* pFrame : rFrames)
1715 if ( ( !pDoc || pDoc == pFrame->GetObjectShell() )
1716 && ( !bOnlyIfVisible || pFrame->IsVisible() )
1718 return pFrame;
1721 return nullptr;
1724 // returns the next window of spec. type viewing the specified doc.
1725 SfxViewFrame* SfxViewFrame::GetNext
1727 const SfxViewFrame& rPrev,
1728 const SfxObjectShell* pDoc,
1729 bool bOnlyIfVisible
1732 SfxApplication *pSfxApp = SfxApplication::Get();
1733 if (!pSfxApp)
1734 return nullptr;
1736 SfxViewFrameArr_Impl &rFrames = pSfxApp->GetViewFrames_Impl();
1738 // refind the specified predecessor
1739 size_t nPos;
1740 for ( nPos = 0; nPos < rFrames.size(); ++nPos )
1741 if ( rFrames[nPos] == &rPrev )
1742 break;
1744 // search for a Frame of the specified type
1745 for ( ++nPos; nPos < rFrames.size(); ++nPos )
1747 SfxViewFrame *pFrame = rFrames[nPos];
1748 if ( ( !pDoc || pDoc == pFrame->GetObjectShell() )
1749 && ( !bOnlyIfVisible || pFrame->IsVisible() )
1751 return pFrame;
1753 return nullptr;
1756 SfxProgress* SfxViewFrame::GetProgress() const
1758 SfxObjectShell *pObjSh = m_xObjSh.get();
1759 return pObjSh ? pObjSh->GetProgress() : nullptr;
1762 void SfxViewFrame::DoAdjustPosSizePixel //! divide on Inner.../Outer...
1764 SfxViewShell* pSh,
1765 const Point& rPos,
1766 const Size& rSize,
1767 bool inplaceEditModeChange
1771 // Components do not use this Method!
1772 if( pSh && pSh->GetWindow() && !m_nAdjustPosPixelLock )
1774 m_nAdjustPosPixelLock++;
1775 if ( m_pImpl->bResizeInToOut )
1776 pSh->InnerResizePixel( rPos, rSize, inplaceEditModeChange );
1777 else
1778 pSh->OuterResizePixel( rPos, rSize );
1779 m_nAdjustPosPixelLock--;
1783 bool SfxViewFrameItem::operator==( const SfxPoolItem &rItem ) const
1785 return SfxPoolItem::operator==(rItem) &&
1786 static_cast<const SfxViewFrameItem&>(rItem).pFrame == pFrame;
1789 SfxViewFrameItem* SfxViewFrameItem::Clone( SfxItemPool *) const
1791 return new SfxViewFrameItem( *this );
1794 void SfxViewFrame::SetViewShell_Impl( SfxViewShell *pVSh )
1795 /* [Description]
1797 Internal Method to set the current <SfxViewShell> Instance,
1798 that is active int this SfxViewFrame at the moment.
1801 SfxShell::SetViewShell_Impl( pVSh );
1803 // Hack: InPlaceMode
1804 if ( pVSh )
1805 m_pImpl->bResizeInToOut = false;
1808 void SfxViewFrame::ForceOuterResize_Impl()
1810 m_pImpl->bResizeInToOut = true;
1813 void SfxViewFrame::GetDocNumber_Impl()
1815 DBG_ASSERT( GetObjectShell(), "No Document!" );
1816 GetObjectShell()->SetNamedVisibility_Impl();
1817 m_pImpl->nDocViewNo = GetObjectShell()->GetNoSet_Impl().GetFreeIndex()+1;
1820 void SfxViewFrame::Enable( bool bEnable )
1822 if ( bEnable == m_pImpl->bEnabled )
1823 return;
1825 m_pImpl->bEnabled = bEnable;
1827 vcl::Window *pWindow = &GetFrame().GetWindow();
1828 if ( !bEnable )
1829 m_pImpl->bWindowWasEnabled = pWindow->IsInputEnabled();
1830 if ( !bEnable || m_pImpl->bWindowWasEnabled )
1831 pWindow->EnableInput( bEnable );
1833 // cursor and focus
1834 SfxViewShell* pViewSh = GetViewShell();
1835 if ( bEnable )
1837 // show cursor
1838 if ( pViewSh )
1839 pViewSh->ShowCursor();
1841 else
1843 // hide cursor
1844 if ( pViewSh )
1845 pViewSh->ShowCursor(false);
1849 /* [Description]
1851 This method makes the Frame-Window visible and before transmits the
1852 window name. In addition, the document is held. In general one can never
1853 show the window directly!
1855 void SfxViewFrame::Show()
1857 // First lock the objectShell so that UpdateTitle() is valid:
1858 // IsVisible() == true (:#)
1859 if ( m_xObjSh.is() )
1861 m_xObjSh->GetMedium()->GetItemSet()->ClearItem( SID_HIDDEN );
1862 if ( !m_pImpl->bObjLocked )
1863 LockObjectShell_Impl();
1865 // Adjust Doc-Shell title number, get unique view-no
1866 if ( 0 == m_pImpl->nDocViewNo )
1868 GetDocNumber_Impl();
1869 UpdateTitle();
1872 else
1873 UpdateTitle();
1875 // Display Frame-window, but only if the ViewFrame has no window of its
1876 // own or if it does not contain a Component
1877 GetWindow().Show();
1878 GetFrame().GetWindow().Show();
1882 bool SfxViewFrame::IsVisible() const
1884 return m_pImpl->bObjLocked;
1888 void SfxViewFrame::LockObjectShell_Impl()
1890 DBG_ASSERT( !m_pImpl->bObjLocked, "Wrong Locked status!" );
1892 DBG_ASSERT( GetObjectShell(), "No Document!" );
1893 GetObjectShell()->OwnerLock(true);
1894 m_pImpl->bObjLocked = true;
1898 void SfxViewFrame::MakeActive_Impl( bool bGrabFocus )
1900 if ( !GetViewShell() || GetFrame().IsClosing_Impl() )
1901 return;
1903 if ( !IsVisible() )
1904 return;
1906 bool bPreview = false;
1907 if (GetObjectShell()->IsPreview())
1909 bPreview = true;
1912 css::uno::Reference<css::frame::XFrame> xFrame = GetFrame().GetFrameInterface();
1913 if (!bPreview)
1915 SetViewFrame(this);
1916 GetBindings().SetActiveFrame(css::uno::Reference<css::frame::XFrame>());
1917 uno::Reference<frame::XFramesSupplier> xSupp(xFrame, uno::UNO_QUERY);
1918 if (xSupp.is())
1919 xSupp->setActiveFrame(uno::Reference<frame::XFrame>());
1921 css::uno::Reference< css::awt::XWindow > xContainerWindow = xFrame->getContainerWindow();
1922 VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow(xContainerWindow);
1923 if (pWindow && pWindow->HasChildPathFocus() && bGrabFocus)
1925 SfxInPlaceClient *pCli = GetViewShell()->GetUIActiveClient();
1926 if (!pCli || !pCli->IsObjectUIActive())
1927 GetFrame().GrabFocusOnComponent_Impl();
1930 else
1932 GetBindings().SetDispatcher(GetDispatcher());
1933 GetBindings().SetActiveFrame(css::uno::Reference<css::frame::XFrame>());
1934 GetDispatcher()->Update_Impl();
1938 SfxObjectShell* SfxViewFrame::GetObjectShell()
1940 return m_xObjSh.get();
1943 const Size& SfxViewFrame::GetMargin_Impl() const
1945 return m_pImpl->aMargin;
1948 SfxViewFrame* SfxViewFrame::LoadViewIntoFrame_Impl_NoThrow( const SfxObjectShell& i_rDoc, const Reference< XFrame >& i_rFrame,
1949 const SfxInterfaceId i_nViewId, const bool i_bHidden )
1951 Reference< XFrame > xFrame( i_rFrame );
1952 bool bOwnFrame = false;
1953 SfxViewShell* pSuccessView = nullptr;
1956 if ( !xFrame.is() )
1958 Reference < XDesktop2 > xDesktop = Desktop::create( ::comphelper::getProcessComponentContext() );
1960 if ( !i_bHidden )
1964 // if there is a backing component, use it
1965 ::framework::FrameListAnalyzer aAnalyzer( xDesktop, Reference< XFrame >(), FrameAnalyzerFlags::BackingComponent );
1967 if ( aAnalyzer.m_xBackingComponent.is() )
1968 xFrame = aAnalyzer.m_xBackingComponent;
1970 catch( uno::Exception& )
1974 if ( !xFrame.is() )
1975 xFrame.set( xDesktop->findFrame( "_blank", 0 ), UNO_SET_THROW );
1977 bOwnFrame = true;
1980 pSuccessView = LoadViewIntoFrame_Impl(
1981 i_rDoc,
1982 xFrame,
1983 Sequence< PropertyValue >(), // means "reuse existing model's args"
1984 i_nViewId,
1985 i_bHidden
1988 if ( bOwnFrame && !i_bHidden )
1990 // ensure the frame/window is visible
1991 Reference< XWindow > xContainerWindow( xFrame->getContainerWindow(), UNO_SET_THROW );
1992 xContainerWindow->setVisible( true );
1995 catch( const Exception& )
1997 DBG_UNHANDLED_EXCEPTION("sfx.view");
2000 if ( pSuccessView )
2001 return pSuccessView->GetViewFrame();
2003 if ( bOwnFrame )
2007 xFrame->dispose();
2009 catch( const Exception& )
2011 DBG_UNHANDLED_EXCEPTION("sfx.view");
2015 return nullptr;
2018 SfxViewShell* SfxViewFrame::LoadViewIntoFrame_Impl( const SfxObjectShell& i_rDoc, const Reference< XFrame >& i_rFrame,
2019 const Sequence< PropertyValue >& i_rLoadArgs, const SfxInterfaceId i_nViewId,
2020 const bool i_bHidden )
2022 Reference< XModel > xDocument( i_rDoc.GetModel(), UNO_SET_THROW );
2024 ::comphelper::NamedValueCollection aTransformLoadArgs( i_rLoadArgs.hasElements() ? i_rLoadArgs : xDocument->getArgs() );
2025 aTransformLoadArgs.put( "Model", xDocument );
2026 if ( i_nViewId )
2027 aTransformLoadArgs.put( "ViewId", sal_uInt16( i_nViewId ) );
2028 if ( i_bHidden )
2029 aTransformLoadArgs.put( "Hidden", i_bHidden );
2030 else
2031 aTransformLoadArgs.remove( "Hidden" );
2033 Reference< XComponentLoader > xLoader( i_rFrame, UNO_QUERY_THROW );
2034 xLoader->loadComponentFromURL( "private:object", "_self", 0,
2035 aTransformLoadArgs.getPropertyValues() );
2037 SfxViewShell* pViewShell = SfxViewShell::Get( i_rFrame->getController() );
2038 ENSURE_OR_THROW( pViewShell,
2039 "SfxViewFrame::LoadViewIntoFrame_Impl: loading an SFX doc into a frame resulted in a non-SFX view - quite impossible" );
2040 return pViewShell;
2043 SfxViewFrame* SfxViewFrame::LoadHiddenDocument( SfxObjectShell const & i_rDoc, SfxInterfaceId i_nViewId )
2045 return LoadViewIntoFrame_Impl_NoThrow( i_rDoc, Reference< XFrame >(), i_nViewId, true );
2048 SfxViewFrame* SfxViewFrame::LoadDocument( SfxObjectShell const & i_rDoc, SfxInterfaceId i_nViewId )
2050 return LoadViewIntoFrame_Impl_NoThrow( i_rDoc, Reference< XFrame >(), i_nViewId, false );
2053 SfxViewFrame* SfxViewFrame::LoadDocumentIntoFrame( SfxObjectShell const & i_rDoc, const Reference< XFrame >& i_rTargetFrame )
2055 return LoadViewIntoFrame_Impl_NoThrow( i_rDoc, i_rTargetFrame, SFX_INTERFACE_NONE, false );
2058 SfxViewFrame* SfxViewFrame::LoadDocumentIntoFrame( SfxObjectShell const & i_rDoc, const SfxFrameItem* i_pFrameItem, SfxInterfaceId i_nViewId )
2060 return LoadViewIntoFrame_Impl_NoThrow( i_rDoc, i_pFrameItem && i_pFrameItem->GetFrame() ? i_pFrameItem->GetFrame()->GetFrameInterface() : nullptr, i_nViewId, false );
2063 SfxViewFrame* SfxViewFrame::DisplayNewDocument( SfxObjectShell const & i_rDoc, const SfxRequest& i_rCreateDocRequest )
2065 const SfxUnoFrameItem* pFrameItem = i_rCreateDocRequest.GetArg<SfxUnoFrameItem>(SID_FILLFRAME);
2066 const SfxBoolItem* pHiddenItem = i_rCreateDocRequest.GetArg<SfxBoolItem>(SID_HIDDEN);
2068 return LoadViewIntoFrame_Impl_NoThrow(
2069 i_rDoc,
2070 pFrameItem ? pFrameItem->GetFrame() : nullptr,
2071 SFX_INTERFACE_NONE,
2072 pHiddenItem && pHiddenItem->GetValue()
2076 SfxViewFrame* SfxViewFrame::Get( const Reference< XController>& i_rController, const SfxObjectShell* i_pDoc )
2078 if ( !i_rController.is() )
2079 return nullptr;
2081 const SfxObjectShell* pDoc = i_pDoc;
2082 if ( !pDoc )
2084 Reference< XModel > xDocument( i_rController->getModel() );
2085 for ( pDoc = SfxObjectShell::GetFirst( nullptr, false );
2086 pDoc;
2087 pDoc = SfxObjectShell::GetNext( *pDoc, nullptr, false )
2090 if ( pDoc->GetModel() == xDocument )
2091 break;
2095 SfxViewFrame* pViewFrame = nullptr;
2096 for ( pViewFrame = SfxViewFrame::GetFirst( pDoc, false );
2097 pViewFrame;
2098 pViewFrame = SfxViewFrame::GetNext( *pViewFrame, pDoc, false )
2101 if ( pViewFrame->GetViewShell()->GetController() == i_rController )
2102 break;
2105 return pViewFrame;
2108 void SfxViewFrame::SaveCurrentViewData_Impl( const SfxInterfaceId i_nNewViewId )
2110 SfxViewShell* pCurrentShell = GetViewShell();
2111 ENSURE_OR_RETURN_VOID( pCurrentShell != nullptr, "SfxViewFrame::SaveCurrentViewData_Impl: no current view shell -> no current view data!" );
2113 // determine the logical (API) view name
2114 const SfxObjectFactory& rDocFactory( pCurrentShell->GetObjectShell()->GetFactory() );
2115 const sal_uInt16 nCurViewNo = rDocFactory.GetViewNo_Impl( GetCurViewId(), 0 );
2116 const OUString sCurrentViewName = rDocFactory.GetViewFactory( nCurViewNo ).GetAPIViewName();
2117 const sal_uInt16 nNewViewNo = rDocFactory.GetViewNo_Impl( i_nNewViewId, 0 );
2118 const OUString sNewViewName = rDocFactory.GetViewFactory( nNewViewNo ).GetAPIViewName();
2119 if ( sCurrentViewName.isEmpty() || sNewViewName.isEmpty() )
2121 // can't say anything about the view, the respective application did not yet migrate its code to
2122 // named view factories => bail out
2123 OSL_FAIL( "SfxViewFrame::SaveCurrentViewData_Impl: views without API names? Shouldn't happen anymore?" );
2124 return;
2126 SAL_WARN_IF(sNewViewName == sCurrentViewName, "sfx.view", "SfxViewFrame::SaveCurrentViewData_Impl: suspicious: new and old view name are identical!");
2128 // save the view data only when we're moving from a non-print-preview to the print-preview view
2129 if ( sNewViewName != "PrintPreview" )
2130 return;
2132 // retrieve the view data from the view
2133 Sequence< PropertyValue > aViewData;
2134 pCurrentShell->WriteUserDataSequence( aViewData );
2138 // retrieve view data (for *all* views) from the model
2139 const Reference< XController > xController( pCurrentShell->GetController(), UNO_SET_THROW );
2140 const Reference< XViewDataSupplier > xViewDataSupplier( xController->getModel(), UNO_QUERY_THROW );
2141 const Reference< XIndexContainer > xViewData( xViewDataSupplier->getViewData(), UNO_QUERY_THROW );
2143 // look up the one view data item which corresponds to our current view, and remove it
2144 const sal_Int32 nCount = xViewData->getCount();
2145 for ( sal_Int32 i=0; i<nCount; ++i )
2147 const ::comphelper::NamedValueCollection aCurViewData( xViewData->getByIndex(i) );
2148 const OUString sViewId( aCurViewData.getOrDefault( "ViewId", OUString() ) );
2149 if ( sViewId.isEmpty() )
2150 continue;
2152 const SfxViewFactory* pViewFactory = rDocFactory.GetViewFactoryByViewName( sViewId );
2153 if ( pViewFactory == nullptr )
2154 continue;
2156 if ( pViewFactory->GetOrdinal() == GetCurViewId() )
2158 xViewData->removeByIndex(i);
2159 break;
2163 // then replace it with the most recent view data we just obtained
2164 xViewData->insertByIndex( 0, makeAny( aViewData ) );
2166 catch( const Exception& )
2168 DBG_UNHANDLED_EXCEPTION("sfx.view");
2172 /* [Description]
2174 Internal Method for switching to another <SfxViewShell> subclass,
2175 which should be created in this SfxMDIFrame. If no SfxViewShell exist
2176 in this SfxMDIFrame, then one will first be created.
2179 [Return Value]
2181 bool true
2182 requested SfxViewShell was created and a
2183 possibly existing one deleted
2185 false
2186 SfxViewShell requested could not be created,
2187 the existing SfxViewShell thus continue to exist
2189 bool SfxViewFrame::SwitchToViewShell_Impl
2191 sal_uInt16 nViewIdOrNo, /* > 0
2192 Registration-Id of the View, to which the
2193 method should switch, for example the one
2194 that will be created.
2196 == 0
2197 First use the Default view. */
2199 bool bIsIndex /* true
2200 'nViewIdOrNo' is no Registration-Id instead
2201 an Index of <SfxViewFrame> in <SfxObjectShell>.
2207 ENSURE_OR_THROW( GetObjectShell() != nullptr, "not possible without a document" );
2209 // if we already have a view shell, remove it
2210 SfxViewShell* pOldSh = GetViewShell();
2211 OSL_PRECOND( pOldSh, "SfxViewFrame::SwitchToViewShell_Impl: that's called *switch* (not for *initial-load*) for a reason" );
2212 if ( pOldSh )
2214 // ask whether it can be closed
2215 if ( !pOldSh->PrepareClose() )
2216 return false;
2218 // remove sub shells from Dispatcher before switching to new ViewShell
2219 PopShellAndSubShells_Impl( *pOldSh );
2222 GetBindings().ENTERREGISTRATIONS();
2223 LockAdjustPosSizePixel();
2225 // ID of the new view
2226 SfxObjectFactory& rDocFact = GetObjectShell()->GetFactory();
2227 const SfxInterfaceId nViewId = ( bIsIndex || !nViewIdOrNo ) ? rDocFact.GetViewFactory( nViewIdOrNo ).GetOrdinal() : SfxInterfaceId(nViewIdOrNo);
2229 // save the view data of the old view, so it can be restored later on (when needed)
2230 SaveCurrentViewData_Impl( nViewId );
2232 // create and load new ViewShell
2233 SfxViewShell* pNewSh = LoadViewIntoFrame_Impl(
2234 *GetObjectShell(),
2235 GetFrame().GetFrameInterface(),
2236 Sequence< PropertyValue >(), // means "reuse existing model's args"
2237 nViewId,
2238 false
2241 // allow resize events to be processed
2242 UnlockAdjustPosSizePixel();
2244 if ( GetWindow().IsReallyVisible() )
2245 DoAdjustPosSizePixel( pNewSh, Point(), GetWindow().GetOutputSizePixel(), false );
2247 GetBindings().LEAVEREGISTRATIONS();
2248 delete pOldSh;
2250 catch ( const css::uno::Exception& )
2252 // the SfxCode is not able to cope with exceptions thrown while creating views
2253 // the code will crash in the stack unwinding procedure, so we shouldn't let exceptions go through here
2254 DBG_UNHANDLED_EXCEPTION("sfx.view");
2255 return false;
2258 DBG_ASSERT( SfxGetpApp()->GetViewFrames_Impl().size() == SfxGetpApp()->GetViewShells_Impl().size(), "Inconsistent view arrays!" );
2259 return true;
2262 void SfxViewFrame::SetCurViewId_Impl( const SfxInterfaceId i_nID )
2264 m_pImpl->nCurViewId = i_nID;
2267 SfxInterfaceId SfxViewFrame::GetCurViewId() const
2269 return m_pImpl->nCurViewId;
2272 /* [Description]
2274 Internal method to run the slot for the <SfxShell> Subclass in the
2275 SfxViewFrame <SVIDL> described slots.
2277 void SfxViewFrame::ExecView_Impl
2279 SfxRequest& rReq // The executable <SfxRequest>
2283 // If the Shells are just being replaced...
2284 if ( !GetObjectShell() || !GetViewShell() )
2285 return;
2287 switch ( rReq.GetSlot() )
2289 case SID_TERMINATE_INPLACEACTIVATION :
2291 SfxInPlaceClient* pClient = GetViewShell()->GetUIActiveClient();
2292 if ( pClient )
2293 pClient->DeactivateObject();
2294 break;
2297 case SID_VIEWSHELL:
2299 const SfxPoolItem *pItem = nullptr;
2300 if ( rReq.GetArgs()
2301 && SfxItemState::SET == rReq.GetArgs()->GetItemState( SID_VIEWSHELL, false, &pItem )
2304 const sal_uInt16 nViewId = static_cast< const SfxUInt16Item* >( pItem )->GetValue();
2305 bool bSuccess = SwitchToViewShell_Impl( nViewId );
2306 rReq.SetReturnValue( SfxBoolItem( 0, bSuccess ) );
2308 break;
2311 case SID_VIEWSHELL0:
2312 case SID_VIEWSHELL1:
2313 case SID_VIEWSHELL2:
2314 case SID_VIEWSHELL3:
2315 case SID_VIEWSHELL4:
2317 const sal_uInt16 nViewNo = rReq.GetSlot() - SID_VIEWSHELL0;
2318 bool bSuccess = SwitchToViewShell_Impl( nViewNo, true );
2319 rReq.SetReturnValue( SfxBoolItem( 0, bSuccess ) );
2320 break;
2323 case SID_NEWWINDOW:
2325 // Hack. at the moment a virtual Function
2326 if ( !GetViewShell()->NewWindowAllowed() )
2328 OSL_FAIL( "You should have disabled the 'Window/New Window' slot!" );
2329 return;
2332 // Get ViewData of FrameSets recursively.
2333 GetFrame().GetViewData_Impl();
2334 SfxMedium* pMed = GetObjectShell()->GetMedium();
2336 // do not open the new window hidden
2337 pMed->GetItemSet()->ClearItem( SID_HIDDEN );
2339 // the view ID (optional arg. TODO: this is currently not supported in the slot definition ...)
2340 const SfxUInt16Item* pViewIdItem = rReq.GetArg<SfxUInt16Item>(SID_VIEW_ID);
2341 const SfxInterfaceId nViewId = pViewIdItem ? SfxInterfaceId(pViewIdItem->GetValue()) : GetCurViewId();
2343 Reference < XFrame > xFrame;
2344 // the frame (optional arg. TODO: this is currently not supported in the slot definition ...)
2345 const SfxUnoFrameItem* pFrameItem = rReq.GetArg<SfxUnoFrameItem>(SID_FILLFRAME);
2346 if ( pFrameItem )
2347 xFrame = pFrameItem->GetFrame();
2349 LoadViewIntoFrame_Impl_NoThrow( *GetObjectShell(), xFrame, nViewId, false );
2351 rReq.Done();
2352 break;
2355 case SID_OBJECT:
2357 const SfxInt16Item* pItem = rReq.GetArg<SfxInt16Item>(SID_OBJECT);
2359 if (pItem)
2361 GetViewShell()->DoVerb( pItem->GetValue() );
2362 rReq.Done();
2363 break;
2369 /* TODO as96863:
2370 This method try to collect information about the count of currently open documents.
2371 But the algorithm is implemented very simple ...
2372 E.g. hidden documents should be ignored here ... but they are counted.
2373 TODO: export special helper "framework::FrameListAnalyzer" within the framework module
2374 and use it here.
2376 static bool impl_maxOpenDocCountReached()
2378 css::uno::Reference< css::uno::XComponentContext > xContext = ::comphelper::getProcessComponentContext();
2379 std::optional<sal_Int32> x(officecfg::Office::Common::Misc::MaxOpenDocuments::get(xContext));
2380 // NIL means: count of allowed documents = infinite !
2381 if (!x)
2382 return false;
2383 sal_Int32 nMaxDocs(*x);
2384 sal_Int32 nOpenDocs = 0;
2386 css::uno::Reference< css::frame::XDesktop2 > xDesktop = css::frame::Desktop::create(xContext);
2387 css::uno::Reference< css::container::XIndexAccess > xCont(xDesktop->getFrames(), css::uno::UNO_QUERY_THROW);
2389 sal_Int32 c = xCont->getCount();
2390 sal_Int32 i = 0;
2392 for (i=0; i<c; ++i)
2396 css::uno::Reference< css::frame::XFrame > xFrame;
2397 xCont->getByIndex(i) >>= xFrame;
2398 if ( ! xFrame.is())
2399 continue;
2401 // a) do not count the help window
2402 if ( xFrame->getName() == "OFFICE_HELP_TASK" )
2403 continue;
2405 // b) count all other frames
2406 ++nOpenDocs;
2408 catch(const css::uno::Exception&)
2409 // An IndexOutOfBoundsException can happen in multithreaded
2410 // environments, where any other thread can change this
2411 // container !
2412 { continue; }
2415 return (nOpenDocs >= nMaxDocs);
2418 /* [Description]
2420 This internal method returns in 'rSet' the Status for the <SfxShell>
2421 Subclass SfxViewFrame in the <SVIDL> described <Slots>.
2423 Thus exactly those Slots-IDs that are recognized as being invalid by Sfx
2424 are included as Which-ranges in 'rSet'. If there exists a mapping for
2425 single slot-IDs of the <SfxItemPool> set in the shell, then the respective
2426 Which-IDs are used so that items can be replaced directly with a working
2427 Core::sun::com::star::script::Engine of the Which-IDs if possible. .
2429 void SfxViewFrame::StateView_Impl
2431 SfxItemSet& rSet /* empty <SfxItemSet> with <Which-Ranges>,
2432 which describes the Slot Ids */
2436 SfxObjectShell *pDocSh = GetObjectShell();
2438 if ( !pDocSh )
2439 // I'm just on reload and am yielding myself ...
2440 return;
2442 const sal_uInt16 *pRanges = rSet.GetRanges();
2443 assert(pRanges && "Set with no Range");
2444 while ( *pRanges )
2446 sal_uInt16 nStartWhich = *pRanges++;
2447 sal_uInt16 nEndWhich = *pRanges++;
2448 for ( sal_uInt16 nWhich = nStartWhich; nWhich <= nEndWhich; ++nWhich )
2450 switch(nWhich)
2452 case SID_VIEWSHELL:
2454 rSet.Put( SfxUInt16Item( nWhich, sal_uInt16(m_pImpl->nCurViewId )) );
2455 break;
2458 case SID_VIEWSHELL0:
2459 case SID_VIEWSHELL1:
2460 case SID_VIEWSHELL2:
2461 case SID_VIEWSHELL3:
2462 case SID_VIEWSHELL4:
2464 sal_uInt16 nViewNo = nWhich - SID_VIEWSHELL0;
2465 if ( GetObjectShell()->GetFactory().GetViewFactoryCount() >
2466 nViewNo && !GetObjectShell()->IsInPlaceActive() )
2468 SfxViewFactory &rViewFactory =
2469 GetObjectShell()->GetFactory().GetViewFactory(nViewNo);
2470 rSet.Put( SfxBoolItem(
2471 nWhich, m_pImpl->nCurViewId == rViewFactory.GetOrdinal() ) );
2473 else
2474 rSet.DisableItem( nWhich );
2475 break;
2478 case SID_NEWWINDOW:
2480 if ( !GetViewShell()->NewWindowAllowed()
2481 || impl_maxOpenDocCountReached()
2483 rSet.DisableItem( nWhich );
2484 break;
2492 void SfxViewFrame::ToTop()
2494 GetFrame().Appear();
2498 /* [Description]
2500 GetFrame returns the Frame, in which the ViewFrame is located.
2502 SfxFrame& SfxViewFrame::GetFrame() const
2504 return m_pImpl->rFrame;
2507 SfxViewFrame* SfxViewFrame::GetTopViewFrame() const
2509 return GetFrame().GetCurrentViewFrame();
2512 vcl::Window& SfxViewFrame::GetWindow() const
2514 return m_pImpl->pWindow ? *m_pImpl->pWindow : GetFrame().GetWindow();
2517 bool SfxViewFrame::DoClose()
2519 return GetFrame().DoClose();
2522 OUString SfxViewFrame::GetActualPresentationURL_Impl() const
2524 if ( m_xObjSh.is() )
2525 return m_xObjSh->GetMedium()->GetName();
2526 return OUString();
2529 void SfxViewFrame::SetModalMode( bool bModal )
2531 // no real modality for LOK
2532 if (comphelper::LibreOfficeKit::isActive())
2533 return;
2535 m_pImpl->bModal = bModal;
2536 if ( m_xObjSh.is() )
2538 for ( SfxViewFrame* pFrame = SfxViewFrame::GetFirst( m_xObjSh.get() );
2539 !bModal && pFrame; pFrame = SfxViewFrame::GetNext( *pFrame, m_xObjSh.get() ) )
2540 bModal = pFrame->m_pImpl->bModal;
2541 m_xObjSh->SetModalMode_Impl( bModal );
2545 bool SfxViewFrame::IsInModalMode() const
2547 return m_pImpl->bModal || GetFrame().GetWindow().IsInModalMode();
2550 void SfxViewFrame::Resize( bool bForce )
2552 Size aSize = GetWindow().GetOutputSizePixel();
2553 if ( !bForce && aSize == m_pImpl->aSize )
2554 return;
2556 m_pImpl->aSize = aSize;
2557 SfxViewShell *pShell = GetViewShell();
2558 if ( pShell )
2560 if ( GetFrame().IsInPlace() )
2562 Point aPoint = GetWindow().GetPosPixel();
2563 DoAdjustPosSizePixel( pShell, aPoint, aSize, true );
2565 else
2567 DoAdjustPosSizePixel( pShell, Point(), aSize, false );
2572 #if HAVE_FEATURE_SCRIPTING
2574 #define LINE_SEP 0x0A
2576 static void CutLines( OUString& rStr, sal_Int32 nStartLine, sal_Int32 nLines )
2578 sal_Int32 nStartPos = 0;
2579 sal_Int32 nLine = 0;
2580 while ( nLine < nStartLine )
2582 nStartPos = rStr.indexOf( LINE_SEP, nStartPos );
2583 if( nStartPos == -1 )
2584 break;
2585 nStartPos++; // not the \n.
2586 nLine++;
2589 SAL_WARN_IF(nStartPos == -1, "sfx.view", "CutLines: Start row not found!");
2591 if ( nStartPos != -1 )
2593 sal_Int32 nEndPos = nStartPos;
2594 for ( sal_Int32 i = 0; i < nLines; i++ )
2595 nEndPos = rStr.indexOf( LINE_SEP, nEndPos+1 );
2597 if ( nEndPos == -1 ) // Can happen at the last row.
2598 nEndPos = rStr.getLength();
2599 else
2600 nEndPos++;
2602 rStr = OUString::Concat(rStr.subView( 0, nStartPos )) + rStr.subView( nEndPos );
2604 // erase trailing lines
2605 if ( nStartPos != -1 )
2607 sal_Int32 n = nStartPos;
2608 sal_Int32 nLen = rStr.getLength();
2609 while ( ( n < nLen ) && ( rStr[ n ] == LINE_SEP ) )
2610 n++;
2612 if ( n > nStartPos )
2613 rStr = OUString::Concat(rStr.subView( 0, nStartPos )) + rStr.subView( n );
2617 #endif
2620 add new recorded dispatch macro script into the application global basic
2621 lib container. It generates a new unique id for it and insert the macro
2622 by using this number as name for the module
2624 void SfxViewFrame::AddDispatchMacroToBasic_Impl( const OUString& sMacro )
2626 #if !HAVE_FEATURE_SCRIPTING
2627 (void) sMacro;
2628 #else
2629 if ( sMacro.isEmpty() )
2630 return;
2632 SfxApplication* pSfxApp = SfxGetpApp();
2633 SfxItemPool& rPool = pSfxApp->GetPool();
2634 SfxRequest aReq(SID_BASICCHOOSER, SfxCallMode::SYNCHRON, rPool);
2636 //seen in tdf#122598, no parent for subsequent dialog
2637 SfxAllItemSet aSet(rPool);
2638 css::uno::Reference< css::frame::XFrame > xFrame =
2639 GetFrame().GetFrameInterface();
2640 aSet.Put(SfxUnoFrameItem(SID_FILLFRAME, xFrame));
2641 aReq.SetInternalArgs_Impl(aSet);
2643 aReq.AppendItem( SfxBoolItem(SID_RECORDMACRO,true) );
2644 const SfxPoolItem* pRet = SfxGetpApp()->ExecuteSlot( aReq );
2645 OUString aScriptURL;
2646 if ( pRet )
2647 aScriptURL = static_cast<const SfxStringItem*>(pRet)->GetValue();
2648 if ( !aScriptURL.isEmpty() )
2650 // parse scriptURL
2651 OUString aLibName;
2652 OUString aModuleName;
2653 OUString aMacroName;
2654 OUString aLocation;
2655 Reference< XComponentContext > xContext = ::comphelper::getProcessComponentContext();
2656 Reference< css::uri::XUriReferenceFactory > xFactory =
2657 css::uri::UriReferenceFactory::create( xContext );
2658 Reference< css::uri::XVndSunStarScriptUrl > xUrl( xFactory->parse( aScriptURL ), UNO_QUERY );
2659 if ( xUrl.is() )
2661 // get name
2662 const OUString aName = xUrl->getName();
2663 const sal_Unicode cTok = '.';
2664 sal_Int32 nIndex = 0;
2665 aLibName = aName.getToken( 0, cTok, nIndex );
2666 if ( nIndex != -1 )
2667 aModuleName = aName.getToken( 0, cTok, nIndex );
2668 if ( nIndex != -1 )
2669 aMacroName = aName.getToken( 0, cTok, nIndex );
2671 // get location
2672 aLocation = xUrl->getParameter( "location" );
2675 BasicManager* pBasMgr = nullptr;
2676 if ( aLocation == "application" )
2678 // application basic
2679 pBasMgr = SfxApplication::GetBasicManager();
2681 else if ( aLocation == "document" )
2683 pBasMgr = GetObjectShell()->GetBasicManager();
2686 OUString aOUSource;
2687 if ( pBasMgr)
2689 StarBASIC* pBasic = pBasMgr->GetLib( aLibName );
2690 if ( pBasic )
2692 SbModule* pModule = pBasic->FindModule( aModuleName );
2693 SbMethod* pMethod = pModule ? pModule->FindMethod(aMacroName, SbxClassType::Method) : nullptr;
2694 if (pMethod)
2696 aOUSource = pModule->GetSource32();
2697 sal_uInt16 nStart, nEnd;
2698 pMethod->GetLineRange( nStart, nEnd );
2699 sal_uInt16 nlStart = nStart;
2700 sal_uInt16 nlEnd = nEnd;
2701 CutLines( aOUSource, nlStart-1, nlEnd-nlStart+1 );
2706 // open lib container and break operation if it couldn't be opened
2707 css::uno::Reference< css::script::XLibraryContainer > xLibCont;
2708 if ( aLocation == "application" )
2710 xLibCont = SfxGetpApp()->GetBasicContainer();
2712 else if ( aLocation == "document" )
2714 xLibCont = GetObjectShell()->GetBasicContainer();
2717 if(!xLibCont.is())
2719 SAL_WARN("sfx.view", "couldn't get access to the basic lib container. Adding of macro isn't possible.");
2720 return;
2723 // get LibraryContainer
2724 css::uno::Any aTemp;
2726 css::uno::Reference< css::container::XNameAccess > xLib;
2727 if(xLibCont->hasByName(aLibName))
2729 // library must be loaded
2730 aTemp = xLibCont->getByName(aLibName);
2731 xLibCont->loadLibrary(aLibName);
2732 aTemp >>= xLib;
2734 else
2736 xLib = xLibCont->createLibrary(aLibName);
2739 // pack the macro as direct usable "sub" routine
2740 OUStringBuffer sRoutine(10000);
2741 bool bReplace = false;
2743 // get module
2744 if(xLib->hasByName(aModuleName))
2746 if ( !aOUSource.isEmpty() )
2748 sRoutine.append( aOUSource );
2750 else
2752 OUString sCode;
2753 aTemp = xLib->getByName(aModuleName);
2754 aTemp >>= sCode;
2755 sRoutine.append( sCode );
2758 bReplace = true;
2761 // append new method
2762 sRoutine.append( "\nsub " );
2763 sRoutine.append(aMacroName);
2764 sRoutine.append( "\n" );
2765 sRoutine.append(sMacro);
2766 sRoutine.append( "\nend sub\n" );
2768 // create the module inside the library and insert the macro routine
2769 aTemp <<= sRoutine.makeStringAndClear();
2770 if ( bReplace )
2772 css::uno::Reference< css::container::XNameContainer > xModulCont(
2773 xLib,
2774 css::uno::UNO_QUERY);
2775 xModulCont->replaceByName(aModuleName,aTemp);
2777 else
2779 css::uno::Reference< css::container::XNameContainer > xModulCont(
2780 xLib,
2781 css::uno::UNO_QUERY);
2782 xModulCont->insertByName(aModuleName,aTemp);
2785 // #i17355# update the Basic IDE
2786 for ( SfxViewShell* pViewShell = SfxViewShell::GetFirst(); pViewShell; pViewShell = SfxViewShell::GetNext( *pViewShell ) )
2788 if ( pViewShell->GetName() == "BasicIDE" )
2790 SfxViewFrame* pViewFrame = pViewShell->GetViewFrame();
2791 SfxDispatcher* pDispat = pViewFrame ? pViewFrame->GetDispatcher() : nullptr;
2792 if ( pDispat )
2794 SfxMacroInfoItem aInfoItem( SID_BASICIDE_ARG_MACROINFO, pBasMgr, aLibName, aModuleName, OUString(), OUString() );
2795 pDispat->ExecuteList(SID_BASICIDE_UPDATEMODULESOURCE,
2796 SfxCallMode::SYNCHRON, { &aInfoItem });
2801 else
2803 // add code for "session only" macro
2805 #endif
2808 void SfxViewFrame::MiscExec_Impl( SfxRequest& rReq )
2810 switch ( rReq.GetSlot() )
2812 case SID_STOP_RECORDING :
2813 case SID_RECORDMACRO :
2815 // try to find any active recorder on this frame
2816 const OUString sProperty("DispatchRecorderSupplier");
2817 css::uno::Reference< css::frame::XFrame > xFrame =
2818 GetFrame().GetFrameInterface();
2820 css::uno::Reference< css::beans::XPropertySet > xSet(xFrame,css::uno::UNO_QUERY);
2821 css::uno::Any aProp = xSet->getPropertyValue(sProperty);
2822 css::uno::Reference< css::frame::XDispatchRecorderSupplier > xSupplier;
2823 aProp >>= xSupplier;
2824 css::uno::Reference< css::frame::XDispatchRecorder > xRecorder;
2825 if (xSupplier.is())
2826 xRecorder = xSupplier->getDispatchRecorder();
2828 bool bIsRecording = xRecorder.is();
2829 const SfxBoolItem* pItem = rReq.GetArg<SfxBoolItem>(SID_RECORDMACRO);
2830 if ( pItem && pItem->GetValue() == bIsRecording )
2831 return;
2833 if ( xRecorder.is() )
2835 // disable active recording
2836 aProp <<= css::uno::Reference< css::frame::XDispatchRecorderSupplier >();
2837 xSet->setPropertyValue(sProperty,aProp);
2839 const SfxBoolItem* pRecordItem = rReq.GetArg<SfxBoolItem>(FN_PARAM_1);
2840 if ( !pRecordItem || !pRecordItem->GetValue() )
2841 // insert script into basic library container of application
2842 AddDispatchMacroToBasic_Impl(xRecorder->getRecordedMacro());
2844 xRecorder->endRecording();
2845 xRecorder = nullptr;
2846 GetBindings().SetRecorder_Impl( xRecorder );
2848 SetChildWindow( SID_RECORDING_FLOATWINDOW, false );
2849 if ( rReq.GetSlot() != SID_RECORDMACRO )
2850 GetBindings().Invalidate( SID_RECORDMACRO );
2852 else if ( rReq.GetSlot() == SID_RECORDMACRO )
2854 // enable recording
2855 css::uno::Reference< css::uno::XComponentContext > xContext(
2856 ::comphelper::getProcessComponentContext());
2858 xRecorder = css::frame::DispatchRecorder::create( xContext );
2860 xSupplier = css::frame::DispatchRecorderSupplier::create( xContext );
2862 xSupplier->setDispatchRecorder(xRecorder);
2863 xRecorder->startRecording(xFrame);
2864 aProp <<= xSupplier;
2865 xSet->setPropertyValue(sProperty,aProp);
2866 GetBindings().SetRecorder_Impl( xRecorder );
2867 SetChildWindow( SID_RECORDING_FLOATWINDOW, true );
2870 rReq.Done();
2871 break;
2874 case SID_TOGGLESTATUSBAR:
2876 css::uno::Reference< css::frame::XFrame > xFrame =
2877 GetFrame().GetFrameInterface();
2879 Reference< css::beans::XPropertySet > xPropSet( xFrame, UNO_QUERY );
2880 Reference< css::frame::XLayoutManager > xLayoutManager;
2881 if ( xPropSet.is() )
2885 Any aValue = xPropSet->getPropertyValue("LayoutManager");
2886 aValue >>= xLayoutManager;
2888 catch ( Exception& )
2893 if ( xLayoutManager.is() )
2895 const OUString aStatusbarResString( "private:resource/statusbar/statusbar" );
2896 // Evaluate parameter.
2897 const SfxBoolItem* pShowItem = rReq.GetArg<SfxBoolItem>(rReq.GetSlot());
2898 bool bShow( true );
2899 if ( !pShowItem )
2900 bShow = xLayoutManager->isElementVisible( aStatusbarResString );
2901 else
2902 bShow = pShowItem->GetValue();
2904 if ( bShow )
2906 xLayoutManager->createElement( aStatusbarResString );
2907 xLayoutManager->showElement( aStatusbarResString );
2909 else
2910 xLayoutManager->hideElement( aStatusbarResString );
2912 if ( !pShowItem )
2913 rReq.AppendItem( SfxBoolItem( SID_TOGGLESTATUSBAR, bShow ) );
2915 rReq.Done();
2916 break;
2919 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2920 case SID_WIN_FULLSCREEN:
2922 const SfxBoolItem* pItem = rReq.GetArg<SfxBoolItem>(rReq.GetSlot());
2923 SfxViewFrame *pTop = GetTopViewFrame();
2924 if ( pTop )
2926 WorkWindow* pWork = static_cast<WorkWindow*>( pTop->GetFrame().GetTopWindow_Impl() );
2927 if ( pWork )
2929 css::uno::Reference< css::frame::XFrame > xFrame =
2930 GetFrame().GetFrameInterface();
2932 Reference< css::beans::XPropertySet > xPropSet( xFrame, UNO_QUERY );
2933 Reference< css::frame::XLayoutManager > xLayoutManager;
2934 if ( xPropSet.is() )
2938 Any aValue = xPropSet->getPropertyValue("LayoutManager");
2939 aValue >>= xLayoutManager;
2941 catch ( Exception& )
2946 bool bNewFullScreenMode = pItem ? pItem->GetValue() : !pWork->IsFullScreenMode();
2947 if ( bNewFullScreenMode != pWork->IsFullScreenMode() )
2949 if ( bNewFullScreenMode )
2950 sfx2::SfxNotebookBar::LockNotebookBar();
2951 else
2952 sfx2::SfxNotebookBar::UnlockNotebookBar();
2954 Reference< css::beans::XPropertySet > xLMPropSet( xLayoutManager, UNO_QUERY );
2955 if ( xLMPropSet.is() )
2959 xLMPropSet->setPropertyValue(
2960 "HideCurrentUI",
2961 makeAny( bNewFullScreenMode ));
2963 catch ( css::beans::UnknownPropertyException& )
2967 pWork->ShowFullScreenMode( bNewFullScreenMode );
2968 pWork->SetMenuBarMode( bNewFullScreenMode ? MenuBarMode::Hide : MenuBarMode::Normal );
2969 GetFrame().GetWorkWindow_Impl()->SetFullScreen_Impl( bNewFullScreenMode );
2970 if ( !pItem )
2971 rReq.AppendItem( SfxBoolItem( SID_WIN_FULLSCREEN, bNewFullScreenMode ) );
2972 rReq.Done();
2974 else
2975 rReq.Ignore();
2978 else
2979 rReq.Ignore();
2981 GetDispatcher()->Update_Impl( true );
2982 break;
2987 void SfxViewFrame::MiscState_Impl(SfxItemSet &rSet)
2989 const sal_uInt16 *pRanges = rSet.GetRanges();
2990 DBG_ASSERT(pRanges && *pRanges, "Set without range");
2991 while ( *pRanges )
2993 for(sal_uInt16 nWhich = *pRanges++; nWhich <= *pRanges; ++nWhich)
2995 switch(nWhich)
2997 case SID_CURRENT_URL:
2999 rSet.Put( SfxStringItem( nWhich, GetActualPresentationURL_Impl() ) );
3000 break;
3003 case SID_RECORDMACRO :
3005 SvtMiscOptions aMiscOptions;
3006 const OUString& sName{GetObjectShell()->GetFactory().GetFactoryName()};
3007 bool bMacrosDisabled = officecfg::Office::Common::Security::Scripting::DisableMacrosExecution::get();
3008 if (bMacrosDisabled ||
3009 !officecfg::Office::Common::Misc::MacroRecorderMode::get() ||
3010 ( sName!="swriter" && sName!="scalc" ) )
3012 rSet.DisableItem( nWhich );
3013 rSet.Put(SfxVisibilityItem(nWhich, false));
3014 break;
3017 css::uno::Reference< css::beans::XPropertySet > xSet(
3018 GetFrame().GetFrameInterface(),
3019 css::uno::UNO_QUERY);
3021 css::uno::Any aProp = xSet->getPropertyValue("DispatchRecorderSupplier");
3022 css::uno::Reference< css::frame::XDispatchRecorderSupplier > xSupplier;
3023 if ( aProp >>= xSupplier )
3024 rSet.Put( SfxBoolItem( nWhich, xSupplier.is() ) );
3025 else
3026 rSet.DisableItem( nWhich );
3027 break;
3030 case SID_STOP_RECORDING :
3032 SvtMiscOptions aMiscOptions;
3033 const OUString& sName{GetObjectShell()->GetFactory().GetFactoryName()};
3034 if ( !officecfg::Office::Common::Misc::MacroRecorderMode::get() ||
3035 ( sName!="swriter" && sName!="scalc" ) )
3037 rSet.DisableItem( nWhich );
3038 break;
3041 css::uno::Reference< css::beans::XPropertySet > xSet(
3042 GetFrame().GetFrameInterface(),
3043 css::uno::UNO_QUERY);
3045 css::uno::Any aProp = xSet->getPropertyValue("DispatchRecorderSupplier");
3046 css::uno::Reference< css::frame::XDispatchRecorderSupplier > xSupplier;
3047 if ( !(aProp >>= xSupplier) || !xSupplier.is() )
3048 rSet.DisableItem( nWhich );
3049 break;
3052 case SID_TOGGLESTATUSBAR:
3054 css::uno::Reference< css::frame::XLayoutManager > xLayoutManager;
3055 css::uno::Reference< css::beans::XPropertySet > xSet(
3056 GetFrame().GetFrameInterface(),
3057 css::uno::UNO_QUERY);
3058 css::uno::Any aProp = xSet->getPropertyValue( "LayoutManager" );
3060 if ( !( aProp >>= xLayoutManager ))
3061 rSet.Put( SfxBoolItem( nWhich, false ));
3062 else
3064 bool bShow = xLayoutManager->isElementVisible( "private:resource/statusbar/statusbar" );
3065 rSet.Put( SfxBoolItem( nWhich, bShow ));
3067 break;
3070 case SID_WIN_FULLSCREEN:
3072 SfxViewFrame* pTop = GetTopViewFrame();
3073 if ( pTop )
3075 WorkWindow* pWork = static_cast<WorkWindow*>( pTop->GetFrame().GetTopWindow_Impl() );
3076 if ( pWork )
3078 rSet.Put( SfxBoolItem( nWhich, pWork->IsFullScreenMode() ) );
3079 break;
3083 rSet.DisableItem( nWhich );
3084 break;
3087 default:
3088 break;
3092 ++pRanges;
3096 /* [Description]
3098 This method can be included in the Execute method for the on- and off-
3099 switching of ChildWindows, to implement this and API-bindings.
3101 Simply include as 'ExecuteMethod' in the IDL.
3103 void SfxViewFrame::ChildWindowExecute( SfxRequest &rReq )
3105 // Evaluate Parameter
3106 sal_uInt16 nSID = rReq.GetSlot();
3108 const SfxBoolItem* pShowItem = rReq.GetArg<SfxBoolItem>(nSID);
3109 if ( nSID == SID_VIEW_DATA_SOURCE_BROWSER )
3111 if (!SvtModuleOptions().IsModuleInstalled(SvtModuleOptions::EModule::DATABASE))
3112 return;
3113 Reference < XFrame > xFrame = GetFrame().GetFrameInterface();
3114 Reference < XFrame > xBeamer( xFrame->findFrame( "_beamer", FrameSearchFlag::CHILDREN ) );
3115 bool bHasChild = xBeamer.is();
3116 bool bShow = pShowItem ? pShowItem->GetValue() : !bHasChild;
3117 if ( pShowItem )
3119 if( bShow == bHasChild )
3120 return;
3122 else
3123 rReq.AppendItem( SfxBoolItem( nSID, bShow ) );
3125 if ( !bShow )
3127 SetChildWindow( SID_BROWSER, false );
3129 else
3131 css::util::URL aTargetURL;
3132 aTargetURL.Complete = ".component:DB/DataSourceBrowser";
3133 Reference < css::util::XURLTransformer > xTrans(
3134 css::util::URLTransformer::create(
3135 ::comphelper::getProcessComponentContext() ) );
3136 xTrans->parseStrict( aTargetURL );
3138 Reference < XDispatchProvider > xProv( xFrame, UNO_QUERY );
3139 Reference < css::frame::XDispatch > xDisp;
3140 if ( xProv.is() )
3141 xDisp = xProv->queryDispatch( aTargetURL, "_beamer", 31 );
3142 if ( xDisp.is() )
3144 Sequence < css::beans::PropertyValue > aArgs(1);
3145 css::beans::PropertyValue* pArg = aArgs.getArray();
3146 pArg[0].Name = "Referer";
3147 pArg[0].Value <<= OUString("private:user");
3148 xDisp->dispatch( aTargetURL, aArgs );
3152 rReq.Done();
3153 return;
3155 if (nSID == SID_STYLE_DESIGNER)
3157 // First make sure that the sidebar is visible
3158 ShowChildWindow(SID_SIDEBAR);
3160 ::sfx2::sidebar::Sidebar::ShowPanel("StyleListPanel",
3161 GetFrame().GetFrameInterface(), true);
3162 rReq.Done();
3163 return;
3166 bool bHasChild = HasChildWindow(nSID);
3167 bool bShow = pShowItem ? pShowItem->GetValue() : !bHasChild;
3168 GetDispatcher()->Update_Impl( true );
3170 // Perform action.
3171 if ( !pShowItem || bShow != bHasChild )
3172 ToggleChildWindow( nSID );
3174 GetBindings().Invalidate( nSID );
3176 // Record if possible.
3177 if ( nSID == SID_HYPERLINK_DIALOG || nSID == SID_SEARCH_DLG )
3179 rReq.Ignore();
3181 else
3183 rReq.AppendItem( SfxBoolItem( nSID, bShow ) );
3184 rReq.Done();
3188 /* [Description]
3190 This method can be used in the state method for the on and off-state
3191 of child-windows, in order to implement this.
3193 Just register the IDL as 'StateMethod'.
3195 void SfxViewFrame::ChildWindowState( SfxItemSet& rState )
3197 SfxWhichIter aIter( rState );
3198 for ( sal_uInt16 nSID = aIter.FirstWhich(); nSID; nSID = aIter.NextWhich() )
3200 if ( nSID == SID_VIEW_DATA_SOURCE_BROWSER )
3202 rState.Put( SfxBoolItem( nSID, HasChildWindow( SID_BROWSER ) ) );
3204 else if ( nSID == SID_HYPERLINK_DIALOG )
3206 const SfxPoolItem* pDummy = nullptr;
3207 SfxItemState eState = GetDispatcher()->QueryState( SID_HYPERLINK_SETLINK, pDummy );
3208 if ( SfxItemState::DISABLED == eState )
3209 rState.DisableItem(nSID);
3210 else
3212 if ( KnowsChildWindow(nSID) )
3213 rState.Put( SfxBoolItem( nSID, HasChildWindow(nSID)) );
3214 else
3215 rState.DisableItem(nSID);
3218 else if ( nSID == SID_BROWSER )
3220 Reference < XFrame > xFrame = GetFrame().GetFrameInterface()->
3221 findFrame( "_beamer", FrameSearchFlag::CHILDREN );
3222 if ( !xFrame.is() )
3223 rState.DisableItem( nSID );
3224 else if ( KnowsChildWindow(nSID) )
3225 rState.Put( SfxBoolItem( nSID, HasChildWindow(nSID) ) );
3227 else if ( nSID == SID_SIDEBAR )
3229 if ( !KnowsChildWindow( nSID ) )
3231 SAL_INFO("sfx.view", "SID_SIDEBAR state requested, but no task pane child window exists for this ID!");
3232 rState.DisableItem( nSID );
3234 else
3236 rState.Put( SfxBoolItem( nSID, HasChildWindow( nSID ) ) );
3239 else if ( KnowsChildWindow(nSID) )
3240 rState.Put( SfxBoolItem( nSID, HasChildWindow(nSID) ) );
3241 else
3242 rState.DisableItem(nSID);
3246 SfxWorkWindow* SfxViewFrame::GetWorkWindow_Impl()
3248 SfxWorkWindow* pWork = GetFrame().GetWorkWindow_Impl();
3249 return pWork;
3252 void SfxViewFrame::SetChildWindow(sal_uInt16 nId, bool bOn, bool bSetFocus )
3254 SfxWorkWindow* pWork = GetWorkWindow_Impl();
3255 if ( pWork )
3256 pWork->SetChildWindow_Impl( nId, bOn, bSetFocus );
3259 void SfxViewFrame::ToggleChildWindow(sal_uInt16 nId)
3261 SfxWorkWindow* pWork = GetWorkWindow_Impl();
3262 if ( pWork )
3263 pWork->ToggleChildWindow_Impl( nId, true );
3266 bool SfxViewFrame::HasChildWindow( sal_uInt16 nId )
3268 SfxWorkWindow* pWork = GetWorkWindow_Impl();
3269 return pWork && pWork->HasChildWindow_Impl(nId);
3272 bool SfxViewFrame::KnowsChildWindow( sal_uInt16 nId )
3274 SfxWorkWindow* pWork = GetWorkWindow_Impl();
3275 return pWork && pWork->KnowsChildWindow_Impl(nId);
3278 void SfxViewFrame::ShowChildWindow( sal_uInt16 nId, bool bVisible )
3280 SfxWorkWindow* pWork = GetWorkWindow_Impl();
3281 if ( pWork )
3283 GetDispatcher()->Update_Impl(true);
3284 pWork->ShowChildWindow_Impl(nId, bVisible, true );
3288 SfxChildWindow* SfxViewFrame::GetChildWindow(sal_uInt16 nId)
3290 SfxWorkWindow* pWork = GetWorkWindow_Impl();
3291 return pWork ? pWork->GetChildWindow_Impl(nId) : nullptr;
3294 void SfxViewFrame::UpdateDocument_Impl()
3296 SfxObjectShell* pDoc = GetObjectShell();
3297 if ( pDoc->IsLoadingFinished() )
3298 pDoc->CheckSecurityOnLoading_Impl();
3300 // check if document depends on a template
3301 pDoc->UpdateFromTemplate_Impl();
3304 void SfxViewFrame::SetViewFrame( SfxViewFrame* pFrame )
3306 if(pFrame)
3307 SetSVHelpData(pFrame->m_pHelpData);
3309 SetSVWinData(pFrame ? pFrame->m_pWinData : nullptr);
3311 SfxGetpApp()->SetViewFrame_Impl( pFrame );
3314 VclPtr<SfxInfoBarWindow> SfxViewFrame::AppendInfoBar(const OUString& sId,
3315 const OUString& sPrimaryMessage,
3316 const OUString& sSecondaryMessage,
3317 InfobarType aInfobarType, bool bShowCloseButton)
3319 SfxChildWindow* pChild = GetChildWindow(SfxInfoBarContainerChild::GetChildWindowId());
3320 if (!pChild)
3321 return nullptr;
3323 if (HasInfoBarWithID(sId))
3324 return nullptr;
3326 SfxInfoBarContainerWindow* pInfoBarContainer = static_cast<SfxInfoBarContainerWindow*>(pChild->GetWindow());
3327 auto pInfoBar = pInfoBarContainer->appendInfoBar(sId, sPrimaryMessage, sSecondaryMessage,
3328 aInfobarType, bShowCloseButton);
3329 ShowChildWindow(SfxInfoBarContainerChild::GetChildWindowId());
3330 return pInfoBar;
3333 void SfxViewFrame::UpdateInfoBar(const OUString& sId, const OUString& sPrimaryMessage,
3334 const OUString& sSecondaryMessage, InfobarType eType)
3336 const sal_uInt16 nId = SfxInfoBarContainerChild::GetChildWindowId();
3338 // Make sure the InfoBar container is visible
3339 if (!HasChildWindow(nId))
3340 ToggleChildWindow(nId);
3342 SfxChildWindow* pChild = GetChildWindow(nId);
3343 if (pChild)
3345 SfxInfoBarContainerWindow* pInfoBarContainer = static_cast<SfxInfoBarContainerWindow*>(pChild->GetWindow());
3346 auto pInfoBar = pInfoBarContainer->getInfoBar(sId);
3348 if (pInfoBar)
3349 pInfoBar->Update(sPrimaryMessage, sSecondaryMessage, eType);
3353 void SfxViewFrame::RemoveInfoBar( const OUString& sId )
3355 const sal_uInt16 nId = SfxInfoBarContainerChild::GetChildWindowId();
3357 // Make sure the InfoBar container is visible
3358 if (!HasChildWindow(nId))
3359 ToggleChildWindow(nId);
3361 SfxChildWindow* pChild = GetChildWindow(nId);
3362 if (pChild)
3364 SfxInfoBarContainerWindow* pInfoBarContainer = static_cast<SfxInfoBarContainerWindow*>(pChild->GetWindow());
3365 auto pInfoBar = pInfoBarContainer->getInfoBar(sId);
3366 pInfoBarContainer->removeInfoBar(pInfoBar);
3367 ShowChildWindow(nId);
3371 bool SfxViewFrame::HasInfoBarWithID( const OUString& sId )
3373 const sal_uInt16 nId = SfxInfoBarContainerChild::GetChildWindowId();
3375 SfxChildWindow* pChild = GetChildWindow(nId);
3376 if (pChild)
3378 SfxInfoBarContainerWindow* pInfoBarContainer = static_cast<SfxInfoBarContainerWindow*>(pChild->GetWindow());
3379 return pInfoBarContainer->hasInfoBarWithID(sId);
3382 return false;
3385 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */