1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
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 <officecfg/Office/Common.hxx>
36 #include <officecfg/Setup.hxx>
37 #include <toolkit/helper/vclunohelper.hxx>
38 #include <vcl/splitwin.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/slstitm.hxx>
46 #include <svl/whiter.hxx>
47 #include <svl/undo.hxx>
48 #include <vcl/stdtext.hxx>
49 #include <vcl/weld.hxx>
50 #include <svtools/sfxecode.hxx>
51 #include <svtools/miscopt.hxx>
52 #include <svtools/ehdl.hxx>
53 #include <tools/diagnose_ex.h>
54 #include <com/sun/star/container/XIndexAccess.hpp>
55 #include <com/sun/star/frame/XFramesSupplier.hpp>
56 #include <com/sun/star/frame/FrameSearchFlag.hpp>
57 #include <com/sun/star/frame/XFrame.hpp>
58 #include <com/sun/star/awt/XWindow.hpp>
59 #include <com/sun/star/frame/XController.hpp>
60 #include <com/sun/star/util/URLTransformer.hpp>
61 #include <com/sun/star/util/XURLTransformer.hpp>
62 #include <com/sun/star/util/XCloseable.hpp>
63 #include <com/sun/star/frame/XDispatchRecorderSupplier.hpp>
64 #include <com/sun/star/document/UpdateDocMode.hpp>
65 #include <com/sun/star/beans/XPropertySet.hpp>
66 #include <com/sun/star/uri/UriReferenceFactory.hpp>
67 #include <com/sun/star/uri/XVndSunStarScriptUrl.hpp>
68 #include <com/sun/star/embed/XStorage.hpp>
69 #include <com/sun/star/embed/EmbedStates.hpp>
70 #include <com/sun/star/document/XViewDataSupplier.hpp>
71 #include <com/sun/star/container/XIndexContainer.hpp>
72 #include <com/sun/star/task/InteractionHandler.hpp>
73 #include <rtl/ustrbuf.hxx>
74 #include <sal/log.hxx>
75
76 #include <unotools/ucbhelper.hxx>
77 #include <comphelper/lok.hxx>
78 #include <comphelper/processfactory.hxx>
79 #include <comphelper/namedvaluecollection.hxx>
80 #include <comphelper/docpasswordrequest.hxx>
81 #include <comphelper/docpasswordhelper.hxx>
82
83 #include <com/sun/star/uno/Reference.h>
84 #include <com/sun/star/ucb/XContent.hpp>
85
86 #include <basic/basmgr.hxx>
87 #include <basic/sbmod.hxx>
88 #include <basic/sbmeth.hxx>
89 #include <basic/sbx.hxx>
90 #include <svtools/asynclink.hxx>
91 #include <svl/sharecontrolfile.hxx>
92 #include <svtools/strings.hrc>
93 #include <svtools/svtresid.hxx>
94 #include <framework/framelistanalyzer.hxx>
95 #include <shellimpl.hxx>
96
97 #include <boost/optional.hpp>
98
99 #include <unotools/configmgr.hxx>
100
101 using namespace ::com::sun::star;
102 using namespace ::com::sun::star::uno;
103 using namespace ::com::sun::star::ucb;
104 using namespace ::com::sun::star::frame;
105 using namespace ::com::sun::star::lang;
106 using ::com::sun::star::awt::XWindow;
107 using ::com::sun::star::beans::PropertyValue;
108 using ::com::sun::star::document::XViewDataSupplier;
109 using ::com::sun::star::container::XIndexContainer;
110
111 // Due to ViewFrame::Current
112 #include <appdata.hxx>
113 #include <sfx2/app.hxx>
114 #include <sfx2/objface.hxx>
115 #include <openflag.hxx>
116 #include <objshimp.hxx>
117 #include <openuriexternally.hxx>
118 #include <sfx2/viewsh.hxx>
119 #include <sfx2/objsh.hxx>
120 #include <sfx2/bindings.hxx>
121 #include <sfx2/dispatch.hxx>
122 #include <arrdecl.hxx>
123 #include <sfxtypes.hxx>
124 #include <sfx2/request.hxx>
125 #include <sfx2/docfac.hxx>
126 #include <sfx2/ipclient.hxx>
127 #include <sfx2/sfxresid.hxx>
128 #include <sfx2/objitem.hxx>
129 #include <sfx2/viewfac.hxx>
130 #include <sfx2/event.hxx>
131 #include <sfx2/fcontnr.hxx>
132 #include <sfx2/docfile.hxx>
133 #include <sfx2/module.hxx>
134 #include <sfx2/msgpool.hxx>
135 #include "viewimp.hxx"
136 #include <sfx2/sfxbasecontroller.hxx>
137 #include <sfx2/frmdescr.hxx>
138 #include <sfx2/sfxuno.hxx>
139 #include <sfx2/progress.hxx>
140 #include <sfx2/sidebar/Sidebar.hxx>
141 #include <workwin.hxx>
142 #include <helper.hxx>
143 #include <sfx2/minfitem.hxx>
144 #include <sfx2/strings.hrc>
145 #include "impviewframe.hxx"
146 #include <vcl/commandinfoprovider.hxx>
147 #include <vcl/svapp.hxx>
148
149 #define ShellClass_SfxViewFrame
150 #include <sfxslots.hxx>
151
SFX_IMPL_SUPERCLASS_INTERFACE(SfxViewFrame,SfxShell)152 SFX_IMPL_SUPERCLASS_INTERFACE(SfxViewFrame,SfxShell)
153
154 void SfxViewFrame::InitInterface_Impl()
155 {
156 GetStaticInterface()->RegisterChildWindow(SID_BROWSER);
157 GetStaticInterface()->RegisterChildWindow(SID_RECORDING_FLOATWINDOW);
158 #if HAVE_FEATURE_DESKTOP
159 GetStaticInterface()->RegisterObjectBar(SFX_OBJECTBAR_FULLSCREEN, SfxVisibilityFlags::FullScreen, ToolbarId::FullScreenToolbox);
160 GetStaticInterface()->RegisterObjectBar(SFX_OBJECTBAR_APPLICATION, SfxVisibilityFlags::Standard, ToolbarId::EnvToolbox);
161 #endif
162 }
163
164 namespace {
165 /// Asks the user if editing a read-only document is really wanted.
166 class SfxEditDocumentDialog : public weld::MessageDialogController
167 {
168 private:
169 std::unique_ptr<weld::Button> m_xEditDocument;
170 std::unique_ptr<weld::Button> m_xCancel;
171
172 public:
173 SfxEditDocumentDialog(weld::Widget* pParent);
174 };
175
SfxEditDocumentDialog(weld::Widget * pParent)176 SfxEditDocumentDialog::SfxEditDocumentDialog(weld::Widget* pParent)
177 : MessageDialogController(pParent, "sfx/ui/editdocumentdialog.ui",
178 "EditDocumentDialog")
179 , m_xEditDocument(m_xBuilder->weld_button("edit"))
180 , m_xCancel(m_xBuilder->weld_button("cancel"))
181 {
182 }
183
184 class SfxQueryOpenAsTemplate
185 {
186 private:
187 std::unique_ptr<weld::MessageDialog> m_xQueryBox;
188 public:
SfxQueryOpenAsTemplate(weld::Window * pParent,bool bAllowIgnoreLock,LockFileEntry & rLockData)189 SfxQueryOpenAsTemplate(weld::Window* pParent, bool bAllowIgnoreLock, LockFileEntry& rLockData)
190 : m_xQueryBox(Application::CreateMessageDialog(pParent, VclMessageType::Question,
191 VclButtonsType::NONE,
192 QueryString(bAllowIgnoreLock, rLockData)))
193 {
194 m_xQueryBox->add_button(SfxResId(STR_QUERY_OPENASTEMPLATE_OPENCOPY_BTN), RET_YES);
195 if (bAllowIgnoreLock)
196 m_xQueryBox->add_button(SfxResId(STR_QUERY_OPENASTEMPLATE_OPEN_BTN), RET_IGNORE);
197 m_xQueryBox->add_button(GetStandardText( StandardButtonType::Cancel ), RET_CANCEL);
198 m_xQueryBox->set_default_response(RET_YES);
199 }
run()200 short run() { return m_xQueryBox->run(); }
201
202 private:
QueryString(bool bAllowIgnoreLock,LockFileEntry & rLockData)203 static OUString QueryString(bool bAllowIgnoreLock, LockFileEntry& rLockData)
204 {
205 OUString sLockUserData;
206 if (!rLockData[LockFileComponent::OOOUSERNAME].isEmpty())
207 sLockUserData = rLockData[LockFileComponent::OOOUSERNAME];
208 else
209 sLockUserData = rLockData[LockFileComponent::SYSUSERNAME];
210
211 if (!sLockUserData.isEmpty() && !rLockData[LockFileComponent::EDITTIME].isEmpty())
212 sLockUserData += " ( " + rLockData[LockFileComponent::EDITTIME] + " )";
213
214 if (!sLockUserData.isEmpty())
215 sLockUserData = "\n\n" + sLockUserData + "\n";
216
217 const bool bUseLockStr = bAllowIgnoreLock || !sLockUserData.isEmpty();
218
219 OUString sMsg(
220 SfxResId(bUseLockStr ? STR_QUERY_OPENASTEMPLATE_LOCKED : STR_QUERY_OPENASTEMPLATE));
221
222 if (bAllowIgnoreLock)
223 sMsg += "\n\n" + SfxResId(STR_QUERY_OPENASTEMPLATE_ALLOW_IGNORE);
224
225 return sMsg.replaceFirst("%LOCKINFO", sLockUserData);
226 }
227 };
228
229 /// Is this read-only object shell opened via .uno:SignPDF?
IsSignPDF(const SfxObjectShellRef & xObjSh)230 bool IsSignPDF(const SfxObjectShellRef& xObjSh)
231 {
232 if (!xObjSh.is())
233 return false;
234
235 SfxMedium* pMedium = xObjSh->GetMedium();
236 if (pMedium && !pMedium->IsOriginallyReadOnly())
237 {
238 const std::shared_ptr<const SfxFilter>& pFilter = pMedium->GetFilter();
239 if (pFilter && pFilter->GetName() == "draw_pdf_import")
240 return true;
241 }
242
243 return false;
244 }
245
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)246 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 )
247 {
248 // TODO/LATER: In future the info should replace the direct hash completely
249 bool bResult = ( !nPasswordHash && !aInfo.hasElements() );
250
251 SAL_WARN_IF( !(pFilter && ( pFilter->GetFilterFlags() & SfxFilterFlags::PASSWORDTOMODIFY )), "sfx.view",
252 "PasswordToModify feature is active for a filter that does not support it!");
253
254 if ( pFilter && xHandler.is() )
255 {
256 bool bCancel = false;
257 bool bFirstTime = true;
258
259 while ( !bResult && !bCancel )
260 {
261 bool bMSType = !pFilter->IsOwnFormat();
262
263 ::rtl::Reference< ::comphelper::DocPasswordRequest > pPasswordRequest(
264 new ::comphelper::DocPasswordRequest(
265 bMSType ? ::comphelper::DocPasswordRequestType::MS : ::comphelper::DocPasswordRequestType::Standard,
266 bFirstTime ? css::task::PasswordRequestMode_PASSWORD_ENTER : css::task::PasswordRequestMode_PASSWORD_REENTER,
267 aPath,
268 true ) );
269
270 uno::Reference< css::task::XInteractionRequest > rRequest( pPasswordRequest.get() );
271 xHandler->handle( rRequest );
272
273 if ( pPasswordRequest->isPassword() )
274 {
275 if ( aInfo.hasElements() )
276 {
277 bResult = ::comphelper::DocPasswordHelper::IsModifyPasswordCorrect( pPasswordRequest->getPasswordToModify(), aInfo );
278 }
279 else
280 {
281 // the binary format
282 bResult = ( SfxMedium::CreatePasswordToModifyHash( pPasswordRequest->getPasswordToModify(), pFilter->GetServiceName()=="com.sun.star.text.TextDocument" ) == nPasswordHash );
283 }
284 }
285 else
286 bCancel = true;
287
288 bFirstTime = false;
289 }
290 }
291
292 return bResult;
293 }
294 }
295
ExecReload_Impl(SfxRequest & rReq)296 void SfxViewFrame::ExecReload_Impl( SfxRequest& rReq )
297 {
298 SfxObjectShell* pSh = GetObjectShell();
299 switch ( rReq.GetSlot() )
300 {
301 case SID_EDITDOC:
302 case SID_READONLYDOC:
303 {
304 // Due to Double occupancy in toolboxes (with or without Ctrl),
305 // it is also possible that the slot is enabled, but Ctrl-click
306 // despite this is not!
307 if( !pSh || !pSh->HasName() || !(pSh->Get_Impl()->nLoadedFlags & SfxLoadedFlags::MAINDOCUMENT ))
308 break;
309
310 SfxViewShell* pViewSh = GetViewShell();
311 if (pViewSh && pViewSh->isEditDocLocked())
312 break;
313
314 // Only change read-only UI and remove info bar when we succeed
315 struct ReadOnlyUIGuard
316 {
317 SfxViewFrame* m_pFrame;
318 SfxObjectShell* m_pSh;
319 SfxMedium* m_pMed = nullptr;
320 bool m_bSetRO;
321 ReadOnlyUIGuard(SfxViewFrame* pFrame, SfxObjectShell* p_Sh)
322 : m_pFrame(pFrame), m_pSh(p_Sh), m_bSetRO(p_Sh->IsReadOnlyUI())
323 {}
324 ~ReadOnlyUIGuard() COVERITY_NOEXCEPT_FALSE
325 {
326 if (m_bSetRO != m_pSh->IsReadOnlyUI())
327 {
328 m_pSh->SetReadOnlyUI(m_bSetRO);
329 if (!m_bSetRO)
330 m_pFrame->RemoveInfoBar("readonly");
331 if (m_pMed)
332 {
333 // tdf#116066: DoSaveCompleted should be called after SetReadOnlyUI
334 m_pSh->DoSaveCompleted(m_pMed);
335 m_pSh->Broadcast(SfxHint(SfxHintId::ModeChanged));
336 }
337 }
338 }
339 } aReadOnlyUIGuard(this, pSh);
340
341 SfxMedium* pMed = pSh->GetMedium();
342
343 const SfxBoolItem* pItem = SfxItemSet::GetItem<SfxBoolItem>(pSh->GetMedium()->GetItemSet(), SID_VIEWONLY, false);
344 if ( pItem && pItem->GetValue() )
345 {
346 SfxApplication* pApp = SfxGetpApp();
347 SfxAllItemSet aSet( pApp->GetPool() );
348 aSet.Put( SfxStringItem( SID_FILE_NAME, pMed->GetURLObject().GetMainURL(INetURLObject::DecodeMechanism::NONE) ) );
349 aSet.Put( SfxBoolItem( SID_TEMPLATE, true ) );
350 aSet.Put( SfxStringItem( SID_TARGETNAME, "_blank" ) );
351 const SfxStringItem* pReferer = SfxItemSet::GetItem<SfxStringItem>(pMed->GetItemSet(), SID_REFERER, false);
352 if ( pReferer )
353 aSet.Put( *pReferer );
354 const SfxInt16Item* pVersionItem = SfxItemSet::GetItem<SfxInt16Item>(pSh->GetMedium()->GetItemSet(), SID_VERSION, false);
355 if ( pVersionItem )
356 aSet.Put( *pVersionItem );
357
358 if( pMed->GetFilter() )
359 {
360 aSet.Put( SfxStringItem( SID_FILTER_NAME, pMed->GetFilter()->GetFilterName() ) );
361 const SfxStringItem* pOptions = SfxItemSet::GetItem<SfxStringItem>(pMed->GetItemSet(), SID_FILE_FILTEROPTIONS, false);
362 if ( pOptions )
363 aSet.Put( *pOptions );
364 }
365
366 GetDispatcher()->Execute( SID_OPENDOC, SfxCallMode::ASYNCHRON, aSet );
367 return;
368 }
369
370 StreamMode nOpenMode;
371 bool bNeedsReload = false;
372 if ( !pSh->IsReadOnly() )
373 {
374 // Save and reload Readonly
375 if( pSh->IsModified() )
376 {
377 if ( pSh->PrepareClose() )
378 {
379 // the storing could let the medium be changed
380 pMed = pSh->GetMedium();
381 bNeedsReload = true;
382 }
383 else
384 {
385 rReq.SetReturnValue( SfxBoolItem( rReq.GetSlot(), false ) );
386 return;
387 }
388 }
389 nOpenMode = SFX_STREAM_READONLY;
390 aReadOnlyUIGuard.m_bSetRO = true;
391 }
392 else
393 {
394 if ( pSh->IsReadOnlyMedium()
395 && ( pSh->GetModifyPasswordHash() || pSh->GetModifyPasswordInfo().hasElements() )
396 && !pSh->IsModifyPasswordEntered() )
397 {
398 const OUString aDocumentName = INetURLObject( pMed->GetOrigURL() ).GetMainURL( INetURLObject::DecodeMechanism::WithCharset );
399 if( !AskPasswordToModify_Impl( pMed->GetInteractionHandler(), aDocumentName, pMed->GetFilter(), pSh->GetModifyPasswordHash(), pSh->GetModifyPasswordInfo() ) )
400 {
401 // this is a read-only document, if it has "Password to modify"
402 // the user should enter password before he can edit the document
403 rReq.SetReturnValue( SfxBoolItem( rReq.GetSlot(), false ) );
404 return;
405 }
406
407 pSh->SetModifyPasswordEntered();
408 }
409
410 nOpenMode = pSh->IsOriginallyReadOnlyMedium() ? SFX_STREAM_READONLY : SFX_STREAM_READWRITE;
411 aReadOnlyUIGuard.m_bSetRO = false;
412
413 // if only the view was in the readonly mode then there is no need to do the reload
414 if ( !pSh->IsReadOnlyMedium() )
415 {
416 // SetReadOnlyUI causes recomputation of window title, using
417 // open mode among other things, so call SetOpenMode before
418 // SetReadOnlyUI:
419 pMed->SetOpenMode( nOpenMode );
420 return;
421 }
422 }
423
424 if ( rReq.IsAPI() )
425 {
426 // Control through API if r/w or r/o
427 const SfxBoolItem* pEditItem = rReq.GetArg<SfxBoolItem>(SID_EDITDOC);
428 if ( pEditItem )
429 nOpenMode = pEditItem->GetValue() ? SFX_STREAM_READWRITE : SFX_STREAM_READONLY;
430 }
431
432 // doing
433
434 OUString sTemp;
435 osl::FileBase::getFileURLFromSystemPath( pMed->GetPhysicalName(), sTemp );
436 INetURLObject aPhysObj( sTemp );
437 const SfxInt16Item* pVersionItem = SfxItemSet::GetItem<SfxInt16Item>(pSh->GetMedium()->GetItemSet(), SID_VERSION, false);
438
439 INetURLObject aMedObj( pMed->GetName() );
440
441 // -> tdf#82744
442 // the logic below is following:
443 // if the document seems not to need to be reloaded
444 // and the physical name is different to the logical one,
445 // then on file system it can be checked that the copy is still newer than the original and no document reload is required.
446 // Did some semplification to enhance readability of the 'if' expression
447 //
448 // when the 'http/https' protocol is active, the bool bPhysObjIsYounger relies upon the getlastmodified Property of a WebDAV resource.
449 // Said property should be implemented, but sometimes it's not.
450 // implemented. On this case the reload activated here will not work properly.
451 // TODO: change the check age method for WebDAV to etag (entity-tag) property value, need some rethinking, since the
452 // etag tells that the cache representation (e.g. in LO) is different from the one on the server,
453 // but tells nothing about the age
454 // Details at this link: http://tools.ietf.org/html/rfc4918#section-15, section 15.7
455 bool bPhysObjIsYounger = ::utl::UCBContentHelper::IsYounger( aMedObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ),
456 aPhysObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ) );
457 bool bIsWebDAV = aMedObj.isAnyKnownWebDAVScheme();
458
459 if ( ( !bNeedsReload && ( ( aMedObj.GetProtocol() == INetProtocol::File &&
460 aMedObj.getFSysPath( FSysStyle::Detect ) != aPhysObj.getFSysPath( FSysStyle::Detect ) &&
461 !bPhysObjIsYounger )
462 || ( bIsWebDAV && !bPhysObjIsYounger )
463 || ( pMed->IsRemote() && !bIsWebDAV ) ) )
464 || pVersionItem )
465 // <- tdf#82744
466 {
467 bNeedsReload = true;
468
469 bool bOK = false;
470 bool bRetryIgnoringLock = false;
471 bool bOpenTemplate = false;
472 boost::optional<bool> aOrigROVal;
473 if (!pVersionItem)
474 {
475 auto pRO = pMed->GetItemSet()->GetItem<SfxBoolItem>(SID_DOC_READONLY, false);
476 if (pRO)
477 aOrigROVal = pRO->GetValue();
478 }
479 do {
480 LockFileEntry aLockData;
481 if ( !pVersionItem )
482 {
483 if (bRetryIgnoringLock)
484 pMed->ResetError();
485
486 bool bHasStorage = pMed->HasStorage_Impl();
487 // switching edit mode could be possible without reload
488 if ( bHasStorage && pMed->GetStorage() == pSh->GetStorage() )
489 {
490 // TODO/LATER: faster creation of copy
491 if ( !pSh->ConnectTmpStorage_Impl( pMed->GetStorage(), pMed ) )
492 return;
493 }
494
495 pMed->CloseAndRelease();
496 pMed->SetOpenMode( nOpenMode );
497 // We need to clear the SID_DOC_READONLY item from the set, to allow
498 // MediaDescriptor::impl_openStreamWithURL (called indirectly by
499 // SfxMedium::CompleteReOpen) to properly fill input stream of the
500 // descriptor, even when the file can't be open in read-write mode.
501 // Only then can following call to SfxMedium::LockOrigFileOnDemand
502 // return proper information about who has locked the file, to show
503 // in the SfxQueryOpenAsTemplate box below; otherwise it exits right
504 // after call to SfxMedium::GetMedium_Impl. This mimics what happens
505 // when the file is opened initially, when filter detection code also
506 // calls MediaDescriptor::impl_openStreamWithURL without the item set.
507 pMed->GetItemSet()->ClearItem(SID_DOC_READONLY);
508 pMed->CompleteReOpen();
509 pMed->GetItemSet()->Put(
510 SfxBoolItem(SID_DOC_READONLY, !(nOpenMode & StreamMode::WRITE)));
511 if ( nOpenMode & StreamMode::WRITE )
512 {
513 auto eResult = pMed->LockOrigFileOnDemand(
514 true, true, bRetryIgnoringLock, &aLockData);
515 bRetryIgnoringLock
516 = eResult == SfxMedium::LockFileResult::FailedLockFile;
517 }
518
519 // LockOrigFileOnDemand might set the readonly flag itself, it should be set back
520 pMed->GetItemSet()->Put( SfxBoolItem( SID_DOC_READONLY, !( nOpenMode & StreamMode::WRITE ) ) );
521
522 if ( !pMed->GetErrorCode() )
523 bOK = true;
524 }
525
526 if( !bOK )
527 {
528 if (nOpenMode == SFX_STREAM_READWRITE && !rReq.IsAPI())
529 {
530 // css::sdbcx::User offering to open it as a template
531 SfxQueryOpenAsTemplate aBox(GetWindow().GetFrameWeld(),
532 bRetryIgnoringLock, aLockData);
533
534 short nUserAnswer = aBox.run();
535 bOpenTemplate = RET_YES == nUserAnswer;
536 // Always reset this here to avoid infinite loop
537 bRetryIgnoringLock = RET_IGNORE == nUserAnswer;
538 }
539 else
540 bRetryIgnoringLock = false;
541 }
542 }
543 while ( !bOK && bRetryIgnoringLock );
544
545 if( !bOK )
546 {
547 ErrCode nErr = pMed->GetErrorCode();
548 if ( pVersionItem )
549 nErr = ERRCODE_IO_ACCESSDENIED;
550 else
551 {
552 pMed->ResetError();
553 pMed->SetOpenMode( SFX_STREAM_READONLY );
554 if (aOrigROVal)
555 pMed->GetItemSet()->Put(SfxBoolItem(SID_DOC_READONLY, *aOrigROVal));
556 else
557 pMed->GetItemSet()->ClearItem(SID_DOC_READONLY);
558 pMed->ReOpen();
559 pSh->DoSaveCompleted( pMed );
560 }
561
562 // Readonly document can not be switched to edit mode?
563 rReq.Done();
564
565 if ( nOpenMode == SFX_STREAM_READWRITE && !rReq.IsAPI() )
566 {
567 if ( bOpenTemplate )
568 {
569 SfxApplication* pApp = SfxGetpApp();
570 SfxAllItemSet aSet( pApp->GetPool() );
571 aSet.Put( SfxStringItem( SID_FILE_NAME, pMed->GetName() ) );
572 const SfxStringItem* pReferer = SfxItemSet::GetItem<SfxStringItem>(pMed->GetItemSet(), SID_REFERER, false);
573 if ( pReferer )
574 aSet.Put( *pReferer );
575 aSet.Put( SfxBoolItem( SID_TEMPLATE, true ) );
576 if ( pVersionItem )
577 aSet.Put( *pVersionItem );
578
579 if( pMed->GetFilter() )
580 {
581 aSet.Put( SfxStringItem( SID_FILTER_NAME, pMed->GetFilter()->GetFilterName() ) );
582 const SfxStringItem* pOptions = SfxItemSet::GetItem<SfxStringItem>(pMed->GetItemSet(), SID_FILE_FILTEROPTIONS, false);
583 if ( pOptions )
584 aSet.Put( *pOptions );
585 }
586
587 GetDispatcher()->Execute( SID_OPENDOC, SfxCallMode::ASYNCHRON, aSet );
588 return;
589 }
590
591 nErr = ERRCODE_NONE;
592 }
593
594 // Keep the read-only UI
595 aReadOnlyUIGuard.m_bSetRO = true;
596
597 ErrorHandler::HandleError( nErr );
598 rReq.SetReturnValue(
599 SfxBoolItem( rReq.GetSlot(), false ) );
600 return;
601 }
602 else
603 {
604 aReadOnlyUIGuard.m_pMed = pMed;
605 rReq.SetReturnValue( SfxBoolItem( rReq.GetSlot(), true ) );
606 rReq.Done( true );
607 return;
608 }
609 }
610
611 rReq.AppendItem( SfxBoolItem( SID_FORCERELOAD, bNeedsReload) );
612 rReq.AppendItem( SfxBoolItem( SID_SILENT, true ));
613
614 [[fallthrough]]; //TODO ???
615 }
616
617 case SID_RELOAD:
618 {
619 // Due to Double occupancy in toolboxes (with or without Ctrl),
620 // it is also possible that the slot is enabled, but Ctrl-click
621 // despite this is not!
622 if ( !pSh || !pSh->CanReload_Impl() )
623 break;
624 SfxApplication* pApp = SfxGetpApp();
625 const SfxBoolItem* pForceReloadItem = rReq.GetArg<SfxBoolItem>(SID_FORCERELOAD);
626 if( pForceReloadItem && !pForceReloadItem->GetValue() &&
627 !pSh->GetMedium()->IsExpired() )
628 return;
629 if( m_pImpl->bReloading || pSh->IsInModalMode() )
630 return;
631
632 // AutoLoad is prohibited if possible
633 const SfxBoolItem* pAutoLoadItem = rReq.GetArg<SfxBoolItem>(SID_AUTOLOAD);
634 if ( pAutoLoadItem && pAutoLoadItem->GetValue() &&
635 GetFrame().IsAutoLoadLocked_Impl() )
636 return;
637
638 SfxObjectShellLock xOldObj( pSh );
639 m_pImpl->bReloading = true;
640 const SfxStringItem* pURLItem = rReq.GetArg<SfxStringItem>(SID_FILE_NAME);
641 // Open as editable?
642 bool bForEdit = !pSh->IsReadOnly();
643
644 // If possible ask the User
645 bool bDo = GetViewShell()->PrepareClose();
646 const SfxBoolItem* pSilentItem = rReq.GetArg<SfxBoolItem>(SID_SILENT);
647 if ( bDo && GetFrame().DocIsModified_Impl() &&
648 !rReq.IsAPI() && ( !pSilentItem || !pSilentItem->GetValue() ) )
649 {
650 std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(GetWindow().GetFrameWeld(),
651 VclMessageType::Question, VclButtonsType::YesNo,
652 SfxResId(STR_QUERY_LASTVERSION)));
653 bDo = RET_YES == xBox->run();
654 }
655
656 if ( bDo )
657 {
658 SfxMedium *pMedium = xOldObj->GetMedium();
659
660 bool bHandsOff =
661 ( pMedium->GetURLObject().GetProtocol() == INetProtocol::File && !xOldObj->IsDocShared() );
662
663 // Empty existing SfxMDIFrames for this Document
664 // in native format or R/O, open it now for editing?
665 SfxObjectShellLock xNewObj;
666
667 // collect the views of the document
668 // TODO: when UNO ViewFactories are available for SFX-based documents, the below code should
669 // be UNOized, too
670 typedef ::std::pair< Reference< XFrame >, SfxInterfaceId > ViewDescriptor;
671 ::std::vector< ViewDescriptor > aViewFrames;
672 SfxViewFrame *pView = GetFirst( xOldObj );
673 while ( pView )
674 {
675 Reference< XFrame > xFrame( pView->GetFrame().GetFrameInterface() );
676 SAL_WARN_IF( !xFrame.is(), "sfx.view", "SfxViewFrame::ExecReload_Impl: no XFrame?!");
677 aViewFrames.emplace_back( xFrame, pView->GetCurViewId() );
678
679 pView = GetNext( *pView, xOldObj );
680 }
681
682 xOldObj->Get_Impl()->pReloadTimer.reset();
683
684 std::unique_ptr<SfxItemSet> pNewSet;
685 std::shared_ptr<const SfxFilter> pFilter = pMedium->GetFilter();
686 if( pURLItem )
687 {
688 pNewSet.reset(new SfxAllItemSet( pApp->GetPool() ));
689 pNewSet->Put( *pURLItem );
690
691 // Filter Detection
692 OUString referer;
693 const SfxStringItem* refererItem = rReq.GetArg<SfxStringItem>(SID_REFERER);
694 if (refererItem != nullptr) {
695 referer = refererItem->GetValue();
696 }
697 SfxMedium aMedium( pURLItem->GetValue(), referer, SFX_STREAM_READWRITE );
698 SfxFilterMatcher().GuessFilter( aMedium, pFilter );
699 if ( pFilter )
700 pNewSet->Put( SfxStringItem( SID_FILTER_NAME, pFilter->GetName() ) );
701 pNewSet->Put( *aMedium.GetItemSet() );
702 }
703 else
704 {
705 pNewSet.reset(new SfxAllItemSet( *pMedium->GetItemSet() ));
706 pNewSet->ClearItem( SID_VIEW_ID );
707 pNewSet->ClearItem( SID_STREAM );
708 pNewSet->ClearItem( SID_INPUTSTREAM );
709 pNewSet->Put( SfxStringItem( SID_FILTER_NAME, pMedium->GetFilter()->GetName() ) );
710
711 // let the current security settings be checked again
712 pNewSet->Put( SfxUInt16Item( SID_MACROEXECMODE, document::MacroExecMode::USE_CONFIG ) );
713
714 if ( pSh->IsOriginallyReadOnlyMedium()
715 || pSh->IsOriginallyLoadedReadOnlyMedium() )
716 // edit mode is switched or reload of readonly document
717 pNewSet->Put( SfxBoolItem( SID_DOC_READONLY, true ) );
718 else
719 // Reload of file opened for writing
720 pNewSet->ClearItem( SID_DOC_READONLY );
721 }
722
723 // If a salvaged file is present, do not enclose the OrigURL
724 // again, since the Template is invalid after reload.
725 const SfxStringItem* pSalvageItem = SfxItemSet::GetItem<SfxStringItem>(pNewSet.get(), SID_DOC_SALVAGE, false);
726 if( pSalvageItem )
727 {
728 pNewSet->ClearItem( SID_DOC_SALVAGE );
729 }
730
731 #if HAVE_FEATURE_MULTIUSER_ENVIRONMENT
732 // TODO/LATER: Temporary solution, the SfxMedium must know the original URL as aLogicName
733 // SfxMedium::Transfer_Impl() will be forbidden then.
734 if ( xOldObj->IsDocShared() )
735 pNewSet->Put( SfxStringItem( SID_FILE_NAME, xOldObj->GetSharedFileURL() ) );
736 #endif
737 if ( pURLItem )
738 pNewSet->Put( SfxStringItem( SID_REFERER, pMedium->GetName() ) );
739 else
740 pNewSet->Put( SfxStringItem( SID_REFERER, OUString() ) );
741
742 xOldObj->CancelTransfers();
743
744
745 if ( pSilentItem && pSilentItem->GetValue() )
746 pNewSet->Put( SfxBoolItem( SID_SILENT, true ) );
747
748 const SfxUnoAnyItem* pInteractionItem = SfxItemSet::GetItem<SfxUnoAnyItem>(pNewSet.get(), SID_INTERACTIONHANDLER, false);
749 const SfxUInt16Item* pMacroExecItem = SfxItemSet::GetItem<SfxUInt16Item>(pNewSet.get(), SID_MACROEXECMODE, false);
750 const SfxUInt16Item* pDocTemplateItem = SfxItemSet::GetItem<SfxUInt16Item>(pNewSet.get(), SID_UPDATEDOCMODE, false);
751
752 if (!pInteractionItem)
753 {
754 Reference < task::XInteractionHandler2 > xHdl = task::InteractionHandler::createWithParent( ::comphelper::getProcessComponentContext(), nullptr );
755 if (xHdl.is())
756 pNewSet->Put( SfxUnoAnyItem(SID_INTERACTIONHANDLER,css::uno::makeAny(xHdl)) );
757 }
758
759 if (!pMacroExecItem)
760 pNewSet->Put( SfxUInt16Item(SID_MACROEXECMODE,css::document::MacroExecMode::USE_CONFIG) );
761 if (!pDocTemplateItem)
762 pNewSet->Put( SfxUInt16Item(SID_UPDATEDOCMODE,css::document::UpdateDocMode::ACCORDING_TO_CONFIG) );
763
764 xOldObj->SetModified( false );
765 // Do not cache the old Document! Is invalid when loading
766 // another document.
767
768 const SfxStringItem* pSavedOptions = SfxItemSet::GetItem<SfxStringItem>(pMedium->GetItemSet(), SID_FILE_FILTEROPTIONS, false);
769 const SfxStringItem* pSavedReferer = SfxItemSet::GetItem<SfxStringItem>(pMedium->GetItemSet(), SID_REFERER, false);
770
771 bool bHasStorage = pMedium->HasStorage_Impl();
772 if( bHandsOff )
773 {
774 if ( bHasStorage && pMedium->GetStorage() == xOldObj->GetStorage() )
775 {
776 // TODO/LATER: faster creation of copy
777 if ( !xOldObj->ConnectTmpStorage_Impl( pMedium->GetStorage(), pMedium ) )
778 return;
779 }
780
781 pMedium->CloseAndRelease();
782 }
783
784 xNewObj = SfxObjectShell::CreateObject( pFilter->GetServiceName() );
785
786 if ( xOldObj->IsModifyPasswordEntered() )
787 xNewObj->SetModifyPasswordEntered();
788
789 uno::Sequence < beans::PropertyValue > aLoadArgs;
790 TransformItems( SID_OPENDOC, *pNewSet, aLoadArgs );
791 try
792 {
793 uno::Reference < frame::XLoadable > xLoad( xNewObj->GetModel(), uno::UNO_QUERY );
794 xLoad->load( aLoadArgs );
795 }
796 catch ( uno::Exception& )
797 {
798 xNewObj->DoClose();
799 xNewObj = nullptr;
800 }
801
802 pNewSet.reset();
803
804 if( !xNewObj.Is() )
805 {
806 if( bHandsOff )
807 {
808 // back to old medium
809 pMedium->ReOpen();
810 pMedium->LockOrigFileOnDemand( false, true );
811
812 xOldObj->DoSaveCompleted( pMedium );
813 }
814
815 // r/o-Doc couldn't be switched to writing mode
816 if ( bForEdit && ( SID_EDITDOC == rReq.GetSlot() || SID_READONLYDOC == rReq.GetSlot() ) )
817 {
818 // ask user for opening as template
819 std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(GetWindow().GetFrameWeld(),
820 VclMessageType::Question, VclButtonsType::YesNo,
821 SfxResId(STR_QUERY_OPENASTEMPLATE)));
822 if (RET_YES == xBox->run())
823 {
824 SfxAllItemSet aSet( pApp->GetPool() );
825 aSet.Put( SfxStringItem( SID_FILE_NAME, pMedium->GetName() ) );
826 aSet.Put( SfxStringItem( SID_TARGETNAME, "_blank" ) );
827 if ( pSavedOptions )
828 aSet.Put( *pSavedOptions );
829 if ( pSavedReferer )
830 aSet.Put( *pSavedReferer );
831 aSet.Put( SfxBoolItem( SID_TEMPLATE, true ) );
832 if( pFilter )
833 aSet.Put( SfxStringItem( SID_FILTER_NAME, pFilter->GetFilterName() ) );
834 GetDispatcher()->Execute( SID_OPENDOC, SfxCallMode::ASYNCHRON, aSet );
835 }
836 }
837 }
838 else
839 {
840 if ( xNewObj->GetModifyPasswordHash() && xNewObj->GetModifyPasswordHash() != xOldObj->GetModifyPasswordHash() )
841 {
842 xNewObj->SetModifyPasswordEntered( false );
843 xNewObj->SetReadOnly();
844 }
845 else if ( rReq.GetSlot() == SID_EDITDOC || rReq.GetSlot() == SID_READONLYDOC )
846 {
847 xNewObj->SetReadOnlyUI( !bForEdit );
848 }
849
850 #if HAVE_FEATURE_MULTIUSER_ENVIRONMENT
851 if ( xNewObj->IsDocShared() )
852 {
853 // the file is shared but the closing can change the sharing control file
854 xOldObj->DoNotCleanShareControlFile();
855 }
856 #endif
857 // the Reload and Silent items were only temporary, remove them
858 xNewObj->GetMedium()->GetItemSet()->ClearItem( SID_RELOAD );
859 xNewObj->GetMedium()->GetItemSet()->ClearItem( SID_SILENT );
860 TransformItems( SID_OPENDOC, *xNewObj->GetMedium()->GetItemSet(), aLoadArgs );
861
862 UpdateDocument_Impl();
863
864 if (vcl::CommandInfoProvider::GetModuleIdentifier(GetFrame().GetFrameInterface()) == "com.sun.star.text.TextDocument")
865 sfx2::SfxNotebookBar::ReloadNotebookBar("modules/swriter/ui/");
866
867 try
868 {
869 for (auto const& viewFrame : aViewFrames)
870 {
871 LoadViewIntoFrame_Impl( *xNewObj, viewFrame.first, aLoadArgs, viewFrame.second, false );
872 }
873 aViewFrames.clear();
874 }
875 catch( const Exception& )
876 {
877 // close the remaining frames
878 // Don't catch exceptions herein, if this fails, then we're left in an indetermined state, and
879 // crashing is better than trying to proceed
880 for (auto const& viewFrame : aViewFrames)
881 {
882 Reference< util::XCloseable > xClose( viewFrame.first, UNO_QUERY_THROW );
883 xClose->close( true );
884 }
885 aViewFrames.clear();
886 }
887
888 // Propagate document closure.
889 SfxGetpApp()->NotifyEvent( SfxEventHint( SfxEventHintId::CloseDoc, GlobalEventConfig::GetEventName( GlobalEventId::CLOSEDOC ), xOldObj ) );
890 }
891
892 // Record as done
893 rReq.Done( true );
894 rReq.SetReturnValue(SfxBoolItem(rReq.GetSlot(), true));
895 return;
896 }
897 else
898 {
899 // Record as not done
900 rReq.Done();
901 rReq.SetReturnValue(SfxBoolItem(rReq.GetSlot(), false));
902 m_pImpl->bReloading = false;
903 return;
904 }
905 }
906 }
907 }
908
StateReload_Impl(SfxItemSet & rSet)909 void SfxViewFrame::StateReload_Impl( SfxItemSet& rSet )
910 {
911 SfxObjectShell* pSh = GetObjectShell();
912 if ( !pSh )
913 {
914 // I'm just on reload and am yielding myself ...
915 return;
916 }
917
918 SfxWhichIter aIter( rSet );
919 for ( sal_uInt16 nWhich = aIter.FirstWhich(); nWhich; nWhich = aIter.NextWhich() )
920 {
921 switch ( nWhich )
922 {
923 case SID_EDITDOC:
924 case SID_READONLYDOC:
925 {
926 const SfxViewShell *pVSh;
927 const SfxShell *pFSh;
928 if ( !pSh->HasName() ||
929 !( pSh->Get_Impl()->nLoadedFlags & SfxLoadedFlags::MAINDOCUMENT ) ||
930 (GetViewShell() && GetViewShell()->isEditDocLocked()) ||
931 ( pSh->GetCreateMode() == SfxObjectCreateMode::EMBEDDED &&
932 ( !(pVSh = pSh->GetViewShell()) ||
933 !(pFSh = pVSh->GetFormShell()) ||
934 !pFSh->IsDesignMode())))
935 rSet.DisableItem( nWhich );
936 else
937 {
938 const SfxBoolItem* pItem = SfxItemSet::GetItem<SfxBoolItem>(pSh->GetMedium()->GetItemSet(), SID_EDITDOC, false);
939 if ( pItem && !pItem->GetValue() )
940 rSet.DisableItem( nWhich );
941 else
942 {
943 if (nWhich==SID_EDITDOC)
944 rSet.Put( SfxBoolItem( nWhich, !pSh->IsReadOnly() ) );
945 else if (nWhich==SID_READONLYDOC)
946 rSet.Put( SfxBoolItem( nWhich, pSh->IsReadOnly() ) );
947 }
948 }
949 break;
950 }
951
952 case SID_RELOAD:
953 {
954 if ( !pSh->CanReload_Impl() || pSh->GetCreateMode() == SfxObjectCreateMode::EMBEDDED )
955 rSet.DisableItem(nWhich);
956 else
957 {
958 // If any ChildFrame is reloadable, the slot is enabled,
959 // so you can perform CTRL-Reload
960 rSet.Put( SfxBoolItem( nWhich, false));
961 }
962
963 break;
964 }
965 }
966 }
967 }
968
ExecHistory_Impl(SfxRequest & rReq)969 void SfxViewFrame::ExecHistory_Impl( SfxRequest &rReq )
970 {
971 // Is there an Undo-Manager on the top Shell?
972 SfxShell *pSh = GetDispatcher()->GetShell(0);
973 SfxUndoManager* pShUndoMgr = pSh->GetUndoManager();
974 bool bOK = false;
975 if ( pShUndoMgr )
976 {
977 switch ( rReq.GetSlot() )
978 {
979 case SID_CLEARHISTORY:
980 pShUndoMgr->Clear();
981 bOK = true;
982 break;
983
984 case SID_UNDO:
985 pShUndoMgr->Undo();
986 GetBindings().InvalidateAll(false);
987 bOK = true;
988 break;
989
990 case SID_REDO:
991 pShUndoMgr->Redo();
992 GetBindings().InvalidateAll(false);
993 bOK = true;
994 break;
995
996 case SID_REPEAT:
997 if ( pSh->GetRepeatTarget() )
998 pShUndoMgr->Repeat( *pSh->GetRepeatTarget() );
999 bOK = true;
1000 break;
1001 }
1002 }
1003 else if ( GetViewShell() )
1004 {
1005 // The SW has its own undo in the View
1006 const SfxPoolItem *pRet = GetViewShell()->ExecuteSlot( rReq );
1007 if ( pRet )
1008 bOK = static_cast<const SfxBoolItem*>(pRet)->GetValue();
1009 }
1010
1011 rReq.SetReturnValue( SfxBoolItem( rReq.GetSlot(), bOK ) );
1012 rReq.Done();
1013 }
1014
StateHistory_Impl(SfxItemSet & rSet)1015 void SfxViewFrame::StateHistory_Impl( SfxItemSet &rSet )
1016 {
1017 // Search for Undo-Manager
1018 SfxShell *pSh = GetDispatcher()->GetShell(0);
1019 if ( !pSh )
1020 // I'm just on reload and am yielding myself ...
1021 return;
1022
1023 SfxUndoManager *pShUndoMgr = pSh->GetUndoManager();
1024 if ( !pShUndoMgr )
1025 {
1026 // The SW has its own undo in the View
1027 SfxWhichIter aIter( rSet );
1028 SfxViewShell *pViewSh = GetViewShell();
1029 if( !pViewSh ) return;
1030 for ( sal_uInt16 nSID = aIter.FirstWhich(); nSID; nSID = aIter.NextWhich() )
1031 pViewSh->GetSlotState( nSID, nullptr, &rSet );
1032 return;
1033 }
1034
1035 if ( pShUndoMgr->GetUndoActionCount() == 0 &&
1036 pShUndoMgr->GetRedoActionCount() == 0 &&
1037 pShUndoMgr->GetRepeatActionCount() == 0 )
1038 rSet.DisableItem( SID_CLEARHISTORY );
1039
1040 if (pShUndoMgr->GetUndoActionCount())
1041 {
1042 const SfxUndoAction* pAction = pShUndoMgr->GetUndoAction();
1043 SfxViewShell *pViewSh = GetViewShell();
1044 if (pViewSh && pAction->GetViewShellId() != pViewSh->GetViewShellId())
1045 {
1046 rSet.Put(SfxUInt32Item(SID_UNDO, static_cast<sal_uInt32>(SID_REPAIRPACKAGE)));
1047 }
1048 else
1049 {
1050 rSet.Put( SfxStringItem( SID_UNDO, SvtResId(STR_UNDO)+pShUndoMgr->GetUndoActionComment() ) );
1051 }
1052 }
1053 else
1054 rSet.DisableItem( SID_UNDO );
1055
1056 if (pShUndoMgr->GetRedoActionCount())
1057 {
1058 const SfxUndoAction* pAction = pShUndoMgr->GetRedoAction();
1059 SfxViewShell *pViewSh = GetViewShell();
1060 if (pViewSh && pAction->GetViewShellId() != pViewSh->GetViewShellId())
1061 {
1062 rSet.Put(SfxUInt32Item(SID_REDO, static_cast<sal_uInt32>(SID_REPAIRPACKAGE)));
1063 }
1064 else
1065 {
1066 rSet.Put(SfxStringItem(SID_REDO, SvtResId(STR_REDO) + pShUndoMgr->GetRedoActionComment()));
1067 }
1068 }
1069 else
1070 rSet.DisableItem( SID_REDO );
1071
1072 SfxRepeatTarget *pTarget = pSh->GetRepeatTarget();
1073 if (pTarget && pShUndoMgr->GetRepeatActionCount() && pShUndoMgr->CanRepeat(*pTarget))
1074 rSet.Put( SfxStringItem( SID_REPEAT, SvtResId(STR_REPEAT)+pShUndoMgr->GetRepeatActionComment(*pTarget) ) );
1075 else
1076 rSet.DisableItem( SID_REPEAT );
1077 }
1078
PopShellAndSubShells_Impl(SfxViewShell & i_rViewShell)1079 void SfxViewFrame::PopShellAndSubShells_Impl( SfxViewShell& i_rViewShell )
1080 {
1081 i_rViewShell.PopSubShells_Impl();
1082 sal_uInt16 nLevel = m_pDispatcher->GetShellLevel( i_rViewShell );
1083 if ( nLevel != USHRT_MAX )
1084 {
1085 if ( nLevel )
1086 {
1087 // more sub shells on the stack, which were not affected by PopSubShells_Impl
1088 SfxShell *pSubShell = m_pDispatcher->GetShell( nLevel-1 );
1089 m_pDispatcher->Pop( *pSubShell, SfxDispatcherPopFlags::POP_UNTIL | SfxDispatcherPopFlags::POP_DELETE );
1090 }
1091 m_pDispatcher->Pop( i_rViewShell );
1092 m_pDispatcher->Flush();
1093 }
1094
1095 }
1096
1097 /* [Description]
1098
1099 This method empties the SfxViewFrame, i.e. takes the <SfxObjectShell>
1100 from the dispatcher and ends its <SfxListener> Relationship to this
1101 SfxObjectShell (by which they may even destroy themselves).
1102
1103 Thus, by invoking ReleaseObjectShell() and SetObjectShell() the
1104 SfxObjectShell can be replaced.
1105
1106 Between RealeaseObjectShell() and SetObjectShell() can the control not
1107 be handed over to the system.
1108
1109 [Cross-reference]
1110
1111 <SfxViewFrame::SetObjectShell(SfxObjectShell&)>
1112 */
ReleaseObjectShell_Impl()1113 void SfxViewFrame::ReleaseObjectShell_Impl()
1114 {
1115 DBG_ASSERT( m_xObjSh.is(), "no SfxObjectShell to release!" );
1116
1117 GetFrame().ReleasingComponent_Impl();
1118 if ( GetWindow().HasChildPathFocus( true ) )
1119 {
1120 GetWindow().GrabFocus();
1121 }
1122
1123 SfxViewShell *pDyingViewSh = GetViewShell();
1124 if ( pDyingViewSh )
1125 {
1126 PopShellAndSubShells_Impl( *pDyingViewSh );
1127 pDyingViewSh->DisconnectAllClients();
1128 SetViewShell_Impl(nullptr);
1129 delete pDyingViewSh;
1130 }
1131 #ifdef DBG_UTIL
1132 else
1133 OSL_FAIL("No Shell");
1134 #endif
1135
1136 if ( m_xObjSh.is() )
1137 {
1138 m_pDispatcher->Pop( *m_xObjSh );
1139 SfxModule* pModule = m_xObjSh->GetModule();
1140 if( pModule )
1141 m_pDispatcher->RemoveShell_Impl( *pModule );
1142 m_pDispatcher->Flush();
1143 EndListening( *m_xObjSh );
1144
1145 Notify( *m_xObjSh, SfxHint(SfxHintId::TitleChanged) );
1146 Notify( *m_xObjSh, SfxHint(SfxHintId::DocChanged) );
1147
1148 if ( 1 == m_xObjSh->GetOwnerLockCount() && m_pImpl->bObjLocked && m_xObjSh->GetCreateMode() == SfxObjectCreateMode::EMBEDDED )
1149 m_xObjSh->DoClose();
1150 SfxObjectShellRef xDyingObjSh = m_xObjSh;
1151 m_xObjSh.clear();
1152 if( GetHasTitle() && m_pImpl->nDocViewNo )
1153 xDyingObjSh->GetNoSet_Impl().ReleaseIndex(m_pImpl->nDocViewNo-1);
1154 if ( m_pImpl->bObjLocked )
1155 {
1156 xDyingObjSh->OwnerLock( false );
1157 m_pImpl->bObjLocked = false;
1158 }
1159 }
1160
1161 GetDispatcher()->SetDisableFlags( SfxDisableFlags::NONE );
1162 }
1163
Close()1164 void SfxViewFrame::Close()
1165 {
1166
1167 DBG_ASSERT( GetFrame().IsClosing_Impl() || !GetFrame().GetFrameInterface().is(), "ViewFrame closed too early!" );
1168
1169 // If no saving have been made up until now, then embedded Objects should
1170 // not be saved automatically anymore.
1171 if ( GetViewShell() )
1172 GetViewShell()->DisconnectAllClients();
1173 Broadcast( SfxHint( SfxHintId::Dying ) );
1174
1175 if (SfxViewFrame::Current() == this)
1176 SfxViewFrame::SetViewFrame( nullptr );
1177
1178 // Since the Dispatcher is emptied, it can not be used in any reasonable
1179 // manner, thus it is better to let the dispatcher be.
1180 GetDispatcher()->Lock(true);
1181 delete this;
1182 }
1183
DoActivate(bool bUI)1184 void SfxViewFrame::DoActivate( bool bUI )
1185 {
1186 m_pDispatcher->DoActivate_Impl( bUI );
1187 }
1188
DoDeactivate(bool bUI,SfxViewFrame const * pNewFrame)1189 void SfxViewFrame::DoDeactivate(bool bUI, SfxViewFrame const * pNewFrame )
1190 {
1191 m_pDispatcher->DoDeactivate_Impl( bUI, pNewFrame );
1192 }
1193
InvalidateBorderImpl(const SfxViewShell * pSh)1194 void SfxViewFrame::InvalidateBorderImpl( const SfxViewShell* pSh )
1195 {
1196 if( !pSh || m_nAdjustPosPixelLock )
1197 return;
1198
1199 if ( GetViewShell() && GetWindow().IsVisible() )
1200 {
1201 if ( GetFrame().IsInPlace() )
1202 {
1203 return;
1204 }
1205
1206 DoAdjustPosSizePixel( GetViewShell(), Point(),
1207 GetWindow().GetOutputSizePixel(),
1208 false );
1209 }
1210 }
1211
SetBorderPixelImpl(const SfxViewShell * pVSh,const SvBorder & rBorder)1212 void SfxViewFrame::SetBorderPixelImpl
1213 (
1214 const SfxViewShell* pVSh,
1215 const SvBorder& rBorder
1216 )
1217
1218 {
1219 m_pImpl->aBorder = rBorder;
1220
1221 if ( m_pImpl->bResizeInToOut && !GetFrame().IsInPlace() )
1222 {
1223 Size aSize = pVSh->GetWindow()->GetOutputSizePixel();
1224 if ( aSize.Width() && aSize.Height() )
1225 {
1226 aSize.AdjustWidth(rBorder.Left() + rBorder.Right() );
1227 aSize.AdjustHeight(rBorder.Top() + rBorder.Bottom() );
1228
1229 Size aOldSize = GetWindow().GetOutputSizePixel();
1230 GetWindow().SetOutputSizePixel( aSize );
1231 vcl::Window* pParent = &GetWindow();
1232 while ( pParent->GetParent() )
1233 pParent = pParent->GetParent();
1234 Size aOuterSize = pParent->GetOutputSizePixel();
1235 aOuterSize.AdjustWidth( aSize.Width() - aOldSize.Width() );
1236 aOuterSize.AdjustHeight( aSize.Height() - aOldSize.Height() );
1237 pParent->SetOutputSizePixel( aOuterSize );
1238 }
1239 }
1240 else
1241 {
1242 tools::Rectangle aEditArea( Point(), GetWindow().GetOutputSizePixel() );
1243 aEditArea.AdjustLeft(rBorder.Left() );
1244 aEditArea.AdjustRight( -(rBorder.Right()) );
1245 aEditArea.AdjustTop(rBorder.Top() );
1246 aEditArea.AdjustBottom( -(rBorder.Bottom()) );
1247 pVSh->GetWindow()->SetPosSizePixel( aEditArea.TopLeft(), aEditArea.GetSize() );
1248 }
1249 }
1250
GetBorderPixelImpl() const1251 const SvBorder& SfxViewFrame::GetBorderPixelImpl() const
1252 {
1253 return m_pImpl->aBorder;
1254 }
1255
Notify(SfxBroadcaster &,const SfxHint & rHint)1256 void SfxViewFrame::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint )
1257 {
1258 if(m_pImpl->bIsDowning)
1259 return;
1260
1261 // we know only SfxEventHint or simple SfxHint
1262 if (const SfxEventHint* pEventHint = dynamic_cast<const SfxEventHint*>(&rHint))
1263 {
1264 // When the Document is loaded asynchronously, was the Dispatcher
1265 // set as ReadOnly, to what must be returned when the document itself
1266 // is not read only, and the loading is finished.
1267 switch ( pEventHint->GetEventId() )
1268 {
1269 case SfxEventHintId::ModifyChanged:
1270 {
1271 SfxBindings& rBind = GetBindings();
1272 rBind.Invalidate( SID_DOC_MODIFIED );
1273 rBind.Invalidate( SID_RELOAD );
1274 rBind.Invalidate( SID_EDITDOC );
1275 break;
1276 }
1277
1278 case SfxEventHintId::OpenDoc:
1279 case SfxEventHintId::CreateDoc:
1280 {
1281 if ( !m_xObjSh.is() )
1282 break;
1283
1284 SfxBindings& rBind = GetBindings();
1285 rBind.Invalidate( SID_RELOAD );
1286 rBind.Invalidate( SID_EDITDOC );
1287
1288 const auto t0 = std::chrono::system_clock::now().time_since_epoch();
1289
1290 bool bIsUITest = false; //uitest.uicheck fails when the dialog is open
1291 for( sal_uInt16 i = 0; i < Application::GetCommandLineParamCount(); i++ )
1292 {
1293 if( Application::GetCommandLineParam(i) == "--nologo" )
1294 bIsUITest = true;
1295 }
1296
1297 //what's new infobar
1298 if (!officecfg::Setup::Product::ooSetupLastVersion::isReadOnly()) //don't show/update when readonly
1299 {
1300 OUString sSetupVersion = utl::ConfigManager::getProductVersion();
1301 sal_Int32 iCurrent = sSetupVersion.getToken(0,'.').toInt32() * 10 + sSetupVersion.getToken(1,'.').toInt32();
1302 OUString sLastVersion
1303 = officecfg::Setup::Product::ooSetupLastVersion::get().get_value_or("0.0");
1304 sal_Int32 iLast = sLastVersion.getToken(0,'.').toInt32() * 10 + sLastVersion.getToken(1,'.').toInt32();
1305 if ((iCurrent > iLast) && !Application::IsHeadlessModeEnabled() && !bIsUITest)
1306 {
1307 VclPtr<SfxInfoBarWindow> pInfoBar = AppendInfoBar("whatsnew", "", SfxResId(STR_WHATSNEW_TEXT), InfobarType::INFO);
1308 if (pInfoBar)
1309 {
1310 VclPtrInstance<PushButton> xWhatsNewButton(&GetWindow());
1311 xWhatsNewButton->SetText(SfxResId(STR_WHATSNEW_BUTTON));
1312 xWhatsNewButton->SetSizePixel(xWhatsNewButton->GetOptimalSize());
1313 xWhatsNewButton->SetClickHdl(LINK(this, SfxViewFrame, WhatsNewHandler));
1314 pInfoBar->addButton(xWhatsNewButton);
1315
1316 //update lastversion
1317 std::shared_ptr<comphelper::ConfigurationChanges> batch(comphelper::ConfigurationChanges::create());
1318 officecfg::Setup::Product::ooSetupLastVersion::set(
1319 sSetupVersion, batch);
1320 batch->commit();
1321 }
1322 }
1323 }
1324
1325 // show tip-of-the-day dialog
1326 const bool bShowTipOfTheDay = officecfg::Office::Common::Misc::ShowTipOfTheDay::get();
1327 if (bShowTipOfTheDay && !Application::IsHeadlessModeEnabled() && !bIsUITest) {
1328 const sal_Int32 nLastTipOfTheDay = officecfg::Office::Common::Misc::LastTipOfTheDayShown::get();
1329 const sal_Int32 nDay = std::chrono::duration_cast<std::chrono::hours>(t0).count()/24; // days since 1970-01-01
1330 if (nDay-nLastTipOfTheDay > 0) { //only once per day
1331 // tdf#127946 pass in argument for dialog parent
1332 SfxUnoFrameItem aDocFrame(SID_FILLFRAME, GetFrame().GetFrameInterface());
1333 GetDispatcher()->ExecuteList(SID_TIPOFTHEDAY, SfxCallMode::SLOT, {}, { &aDocFrame });
1334 }
1335 } //bShowTipOfTheDay
1336
1337 // inform about the community involvement
1338 const sal_Int64 nLastGetInvolvedShown = officecfg::Setup::Product::LastTimeGetInvolvedShown::get();
1339 const sal_Int64 nNow = std::chrono::duration_cast<std::chrono::seconds>(t0).count();
1340 const sal_Int64 nPeriodSec(60 * 60 * 24 * 180); // 180 days in seconds
1341 bool bUpdateLastTimeGetInvolvedShown = false;
1342
1343 if (nLastGetInvolvedShown == 0)
1344 bUpdateLastTimeGetInvolvedShown = true;
1345 else if (nPeriodSec < nNow && nLastGetInvolvedShown < (nNow + nPeriodSec/2) - nPeriodSec) // 90d alternating with donation
1346 {
1347 bUpdateLastTimeGetInvolvedShown = true;
1348
1349 VclPtr<SfxInfoBarWindow> pInfoBar = AppendInfoBar("getinvolved", "", SfxResId(STR_GET_INVOLVED_TEXT), InfobarType::INFO);
1350
1351 VclPtrInstance<PushButton> xGetInvolvedButton(&GetWindow());
1352 xGetInvolvedButton->SetText(SfxResId(STR_GET_INVOLVED_BUTTON));
1353 xGetInvolvedButton->SetSizePixel(xGetInvolvedButton->GetOptimalSize());
1354 xGetInvolvedButton->SetClickHdl(LINK(this, SfxViewFrame, GetInvolvedHandler));
1355 pInfoBar->addButton(xGetInvolvedButton);
1356 }
1357
1358 if (bUpdateLastTimeGetInvolvedShown
1359 && !officecfg::Setup::Product::LastTimeGetInvolvedShown::isReadOnly())
1360 {
1361 std::shared_ptr<comphelper::ConfigurationChanges> batch(comphelper::ConfigurationChanges::create());
1362 officecfg::Setup::Product::LastTimeGetInvolvedShown::set(nNow, batch);
1363 batch->commit();
1364 }
1365
1366 // inform about donations
1367 const sal_Int64 nLastDonateShown = officecfg::Setup::Product::LastTimeDonateShown::get();
1368 bool bUpdateLastTimeDonateShown = false;
1369
1370 if (nLastDonateShown == 0)
1371 bUpdateLastTimeDonateShown = true;
1372 else if (nPeriodSec < nNow && nLastDonateShown < nNow - nPeriodSec) // 90d alternating with getinvolved
1373 {
1374 bUpdateLastTimeDonateShown = true;
1375
1376 VclPtr<SfxInfoBarWindow> pInfoBar = AppendInfoBar("donate", "", SfxResId(STR_DONATE_TEXT), InfobarType::INFO);
1377
1378 VclPtrInstance<PushButton> xDonateButton(&GetWindow());
1379 xDonateButton->SetText(SfxResId(STR_DONATE_BUTTON));
1380 xDonateButton->SetSizePixel(xDonateButton->GetOptimalSize());
1381 xDonateButton->SetClickHdl(LINK(this, SfxViewFrame, DonationHandler));
1382 pInfoBar->addButton(xDonateButton);
1383 }
1384
1385 if (bUpdateLastTimeDonateShown
1386 && !officecfg::Setup::Product::LastTimeDonateShown::isReadOnly())
1387 {
1388 std::shared_ptr<comphelper::ConfigurationChanges> batch(comphelper::ConfigurationChanges::create());
1389 officecfg::Setup::Product::LastTimeDonateShown::set(nNow, batch);
1390 batch->commit();
1391 }
1392
1393 // read-only infobar if necessary
1394 const SfxViewShell *pVSh;
1395 const SfxShell *pFSh;
1396 if ( m_xObjSh->IsReadOnly() &&
1397 ! m_xObjSh->IsSecurityOptOpenReadOnly() &&
1398 ( m_xObjSh->GetCreateMode() != SfxObjectCreateMode::EMBEDDED ||
1399 (( pVSh = m_xObjSh->GetViewShell()) && (pFSh = pVSh->GetFormShell()) && pFSh->IsDesignMode())))
1400 {
1401 bool bSignPDF = IsSignPDF(m_xObjSh);
1402
1403 auto pInfoBar = AppendInfoBar("readonly", "", SfxResId(bSignPDF ? STR_READONLY_PDF : STR_READONLY_DOCUMENT), InfobarType::INFO);
1404 if (pInfoBar)
1405 {
1406 if (bSignPDF)
1407 {
1408 // SID_SIGNPDF opened a read-write PDF
1409 // read-only for signing purposes.
1410 VclPtrInstance<PushButton> xSignButton(&GetWindow());
1411 xSignButton->SetText(SfxResId(STR_READONLY_SIGN));
1412 xSignButton->SetSizePixel(xSignButton->GetOptimalSize());
1413 xSignButton->SetClickHdl(LINK(this, SfxViewFrame, SignDocumentHandler));
1414 pInfoBar->addButton(xSignButton);
1415 }
1416
1417 bool showEditDocumentButton = true;
1418 if (m_xObjSh->GetViewShell() && m_xObjSh->GetViewShell()->isEditDocLocked())
1419 showEditDocumentButton = false;
1420
1421 if (showEditDocumentButton)
1422 {
1423 VclPtrInstance<PushButton> xBtn(&GetWindow());
1424 xBtn->SetText(SfxResId(STR_READONLY_EDIT));
1425 xBtn->SetSizePixel(xBtn->GetOptimalSize());
1426 xBtn->SetClickHdl(LINK(this, SfxViewFrame, SwitchReadOnlyHandler));
1427 pInfoBar->addButton(xBtn);
1428 }
1429 }
1430 }
1431
1432 if (vcl::CommandInfoProvider::GetModuleIdentifier(GetFrame().GetFrameInterface()) == "com.sun.star.text.TextDocument")
1433 sfx2::SfxNotebookBar::ReloadNotebookBar("modules/swriter/ui/");
1434
1435 if (SfxClassificationHelper::IsClassified(m_xObjSh->getDocProperties()))
1436 {
1437 // Document has BAILS properties, display an infobar accordingly.
1438 SfxClassificationHelper aHelper(m_xObjSh->getDocProperties());
1439 aHelper.UpdateInfobar(*this);
1440 }
1441
1442 // Add pending infobars
1443 std::vector<InfobarData>& aPendingInfobars = m_xObjSh->getPendingInfobars();
1444 while (!aPendingInfobars.empty())
1445 {
1446 InfobarData& aInfobarData = aPendingInfobars.back();
1447 AppendInfoBar(aInfobarData.msId, aInfobarData.msPrimaryMessage,
1448 aInfobarData.msSecondaryMessage, aInfobarData.maInfobarType,
1449 aInfobarData.mbShowCloseButton);
1450 aPendingInfobars.pop_back();
1451 }
1452
1453 break;
1454 }
1455 default: break;
1456 }
1457 }
1458 else
1459 {
1460 switch( rHint.GetId() )
1461 {
1462 case SfxHintId::ModeChanged:
1463 {
1464 UpdateTitle();
1465
1466 if ( !m_xObjSh.is() )
1467 break;
1468
1469 // Switch r/o?
1470 SfxBindings& rBind = GetBindings();
1471 rBind.Invalidate( SID_RELOAD );
1472 SfxDispatcher *pDispat = GetDispatcher();
1473 bool bWasReadOnly = pDispat->GetReadOnly_Impl();
1474 bool bIsReadOnly = m_xObjSh->IsReadOnly();
1475 if ( bWasReadOnly != bIsReadOnly )
1476 {
1477 // Then also TITLE_CHANGED
1478 UpdateTitle();
1479 rBind.Invalidate( SID_FILE_NAME );
1480 rBind.Invalidate( SID_DOCINFO_TITLE );
1481 rBind.Invalidate( SID_EDITDOC );
1482
1483 pDispat->GetBindings()->InvalidateAll(true);
1484 pDispat->SetReadOnly_Impl( bIsReadOnly );
1485
1486 // Only force and Dispatcher-Update, if it is done next
1487 // anyway, otherwise flickering or GPF is possibel since
1488 // the Writer for example prefers in Resize perform some
1489 // actions which has a SetReadOnlyUI in Dispatcher as a
1490 // result!
1491
1492 if ( pDispat->IsUpdated_Impl() )
1493 pDispat->Update_Impl(true);
1494 }
1495
1496 Enable( !m_xObjSh->IsInModalMode() );
1497 break;
1498 }
1499
1500 case SfxHintId::TitleChanged:
1501 {
1502 UpdateTitle();
1503 SfxBindings& rBind = GetBindings();
1504 rBind.Invalidate( SID_FILE_NAME );
1505 rBind.Invalidate( SID_DOCINFO_TITLE );
1506 rBind.Invalidate( SID_EDITDOC );
1507 rBind.Invalidate( SID_RELOAD );
1508 break;
1509 }
1510
1511 case SfxHintId::DocumentRepair:
1512 {
1513 GetBindings().Invalidate( SID_DOC_REPAIR );
1514 break;
1515 }
1516
1517 case SfxHintId::Deinitializing:
1518 {
1519 if (GetWindow().GetLOKNotifier())
1520 GetWindow().ReleaseLOKNotifier();
1521
1522 GetFrame().DoClose();
1523 break;
1524 }
1525 case SfxHintId::Dying:
1526 // when the Object is being deleted, destroy the view too
1527 if ( m_xObjSh.is() )
1528 ReleaseObjectShell_Impl();
1529 else
1530 GetFrame().DoClose();
1531 break;
1532 default: break;
1533 }
1534 }
1535 }
1536
IMPL_LINK_NOARG(SfxViewFrame,WhatsNewHandler,Button *,void)1537 IMPL_LINK_NOARG(SfxViewFrame, WhatsNewHandler, Button*, void)
1538 {
1539 GetDispatcher()->Execute(SID_WHATSNEW);
1540 }
1541
IMPL_LINK_NOARG(SfxViewFrame,GetInvolvedHandler,Button *,void)1542 IMPL_LINK_NOARG(SfxViewFrame, GetInvolvedHandler, Button*, void)
1543 {
1544 GetDispatcher()->Execute(SID_GETINVOLVED);
1545 }
1546
IMPL_LINK_NOARG(SfxViewFrame,DonationHandler,Button *,void)1547 IMPL_LINK_NOARG(SfxViewFrame, DonationHandler, Button*, void)
1548 {
1549 GetDispatcher()->Execute(SID_DONATION);
1550 }
1551
IMPL_LINK(SfxViewFrame,SwitchReadOnlyHandler,Button *,pButton,void)1552 IMPL_LINK(SfxViewFrame, SwitchReadOnlyHandler, Button*, pButton, void)
1553 {
1554 if (m_xObjSh.is() && IsSignPDF(m_xObjSh))
1555 {
1556 SfxEditDocumentDialog aDialog(pButton->GetFrameWeld());
1557 if (aDialog.run() != RET_OK)
1558 return;
1559 }
1560 GetDispatcher()->Execute(SID_EDITDOC);
1561 }
1562
IMPL_LINK_NOARG(SfxViewFrame,SignDocumentHandler,Button *,void)1563 IMPL_LINK_NOARG(SfxViewFrame, SignDocumentHandler, Button*, void)
1564 {
1565 GetDispatcher()->Execute(SID_SIGNATURE);
1566 }
1567
Construct_Impl(SfxObjectShell * pObjSh)1568 void SfxViewFrame::Construct_Impl( SfxObjectShell *pObjSh )
1569 {
1570 m_pImpl->bResizeInToOut = true;
1571 m_pImpl->bObjLocked = false;
1572 m_pImpl->nCurViewId = SFX_INTERFACE_NONE;
1573 m_pImpl->bReloading = false;
1574 m_pImpl->bIsDowning = false;
1575 m_pImpl->bModal = false;
1576 m_pImpl->bEnabled = true;
1577 m_pImpl->nDocViewNo = 0;
1578 m_pImpl->aMargin = Size( -1, -1 );
1579 m_pImpl->pWindow = nullptr;
1580
1581 SetPool( &SfxGetpApp()->GetPool() );
1582 m_pDispatcher.reset( new SfxDispatcher(this) );
1583 if ( !GetBindings().GetDispatcher() )
1584 GetBindings().SetDispatcher( m_pDispatcher.get() );
1585
1586 m_xObjSh = pObjSh;
1587 if ( m_xObjSh.is() && m_xObjSh->IsPreview() )
1588 GetDispatcher()->SetQuietMode_Impl( true );
1589
1590 if ( pObjSh )
1591 {
1592 m_pDispatcher->Push( *SfxGetpApp() );
1593 SfxModule* pModule = m_xObjSh->GetModule();
1594 if( pModule )
1595 m_pDispatcher->Push( *pModule );
1596 m_pDispatcher->Push( *this );
1597 m_pDispatcher->Push( *pObjSh );
1598 m_pDispatcher->Flush();
1599 StartListening( *pObjSh );
1600 Notify( *pObjSh, SfxHint(SfxHintId::TitleChanged) );
1601 Notify( *pObjSh, SfxHint(SfxHintId::DocChanged) );
1602 m_pDispatcher->SetReadOnly_Impl( pObjSh->IsReadOnly() );
1603 }
1604 else
1605 {
1606 m_pDispatcher->Push( *SfxGetpApp() );
1607 m_pDispatcher->Push( *this );
1608 m_pDispatcher->Flush();
1609 }
1610
1611 SfxViewFrameArr_Impl &rViewArr = SfxGetpApp()->GetViewFrames_Impl();
1612 rViewArr.push_back( this );
1613 }
1614
1615 /* [Description]
1616
1617 Constructor of SfxViewFrame for a <SfxObjectShell> from the Resource.
1618 The 'nViewId' to the created <SfxViewShell> can be returned.
1619 (default is the SfxViewShell-Subclass that was registered first).
1620 */
SfxViewFrame(SfxFrame & rFrame,SfxObjectShell * pObjShell)1621 SfxViewFrame::SfxViewFrame
1622 (
1623 SfxFrame& rFrame,
1624 SfxObjectShell* pObjShell
1625 )
1626 : m_pImpl( new SfxViewFrame_Impl( rFrame ) )
1627 , m_pBindings( new SfxBindings )
1628 , m_nAdjustPosPixelLock( 0 )
1629 {
1630
1631 rFrame.SetCurrentViewFrame_Impl( this );
1632 rFrame.SetHasTitle( true );
1633 Construct_Impl( pObjShell );
1634
1635 m_pImpl->pWindow = VclPtr<SfxFrameViewWindow_Impl>::Create( this, rFrame.GetWindow() );
1636 m_pImpl->pWindow->SetSizePixel( rFrame.GetWindow().GetOutputSizePixel() );
1637 rFrame.SetOwnsBindings_Impl( true );
1638 rFrame.CreateWorkWindow_Impl();
1639 }
1640
~SfxViewFrame()1641 SfxViewFrame::~SfxViewFrame()
1642 {
1643 m_pImpl->bIsDowning = true;
1644
1645 if ( SfxViewFrame::Current() == this )
1646 SfxViewFrame::SetViewFrame( nullptr );
1647
1648 ReleaseObjectShell_Impl();
1649
1650 if ( GetFrame().OwnsBindings_Impl() )
1651 // The Bindings delete the Frame!
1652 KillDispatcher_Impl();
1653
1654 m_pImpl->pWindow.disposeAndClear();
1655
1656 if ( GetFrame().GetCurrentViewFrame() == this )
1657 GetFrame().SetCurrentViewFrame_Impl( nullptr );
1658
1659 // Unregister from the Frame List.
1660 SfxApplication *pSfxApp = SfxApplication::Get();
1661 if (pSfxApp)
1662 {
1663 SfxViewFrameArr_Impl &rFrames = pSfxApp->GetViewFrames_Impl();
1664 SfxViewFrameArr_Impl::iterator it = std::find( rFrames.begin(), rFrames.end(), this );
1665 rFrames.erase( it );
1666 }
1667
1668 // Delete Member
1669 KillDispatcher_Impl();
1670 }
1671
1672 // Remove and delete the Dispatcher.
KillDispatcher_Impl()1673 void SfxViewFrame::KillDispatcher_Impl()
1674 {
1675
1676 SfxModule* pModule = m_xObjSh.is() ? m_xObjSh->GetModule() : nullptr;
1677 if ( m_xObjSh.is() )
1678 ReleaseObjectShell_Impl();
1679 if ( m_pDispatcher )
1680 {
1681 if( pModule )
1682 m_pDispatcher->Pop( *pModule, SfxDispatcherPopFlags::POP_UNTIL );
1683 else
1684 m_pDispatcher->Pop( *this );
1685 m_pDispatcher.reset();
1686 }
1687 }
1688
Current()1689 SfxViewFrame* SfxViewFrame::Current()
1690 {
1691 SfxApplication* pApp = SfxApplication::Get();
1692 return pApp ? pApp->Get_Impl()->pViewFrame : nullptr;
1693 }
1694
1695 // returns the first window of spec. type viewing the specified doc.
GetFirst(const SfxObjectShell * pDoc,bool bOnlyIfVisible)1696 SfxViewFrame* SfxViewFrame::GetFirst
1697 (
1698 const SfxObjectShell* pDoc,
1699 bool bOnlyIfVisible
1700 )
1701 {
1702 SfxApplication *pSfxApp = SfxApplication::Get();
1703 if (!pSfxApp)
1704 return nullptr;
1705
1706 SfxViewFrameArr_Impl &rFrames = pSfxApp->GetViewFrames_Impl();
1707
1708 // search for a SfxDocument of the specified type
1709 for (SfxViewFrame* pFrame : rFrames)
1710 {
1711 if ( ( !pDoc || pDoc == pFrame->GetObjectShell() )
1712 && ( !bOnlyIfVisible || pFrame->IsVisible() )
1713 )
1714 return pFrame;
1715 }
1716
1717 return nullptr;
1718 }
1719
1720 // returns the next window of spec. type viewing the specified doc.
GetNext(const SfxViewFrame & rPrev,const SfxObjectShell * pDoc,bool bOnlyIfVisible)1721 SfxViewFrame* SfxViewFrame::GetNext
1722 (
1723 const SfxViewFrame& rPrev,
1724 const SfxObjectShell* pDoc,
1725 bool bOnlyIfVisible
1726 )
1727 {
1728 SfxApplication *pSfxApp = SfxApplication::Get();
1729 if (!pSfxApp)
1730 return nullptr;
1731
1732 SfxViewFrameArr_Impl &rFrames = pSfxApp->GetViewFrames_Impl();
1733
1734 // refind the specified predecessor
1735 size_t nPos;
1736 for ( nPos = 0; nPos < rFrames.size(); ++nPos )
1737 if ( rFrames[nPos] == &rPrev )
1738 break;
1739
1740 // search for a Frame of the specified type
1741 for ( ++nPos; nPos < rFrames.size(); ++nPos )
1742 {
1743 SfxViewFrame *pFrame = rFrames[nPos];
1744 if ( ( !pDoc || pDoc == pFrame->GetObjectShell() )
1745 && ( !bOnlyIfVisible || pFrame->IsVisible() )
1746 )
1747 return pFrame;
1748 }
1749 return nullptr;
1750 }
1751
GetProgress() const1752 SfxProgress* SfxViewFrame::GetProgress() const
1753 {
1754 SfxObjectShell *pObjSh = m_xObjSh.get();
1755 return pObjSh ? pObjSh->GetProgress() : nullptr;
1756 }
1757
DoAdjustPosSizePixel(SfxViewShell * pSh,const Point & rPos,const Size & rSize,bool inplaceEditModeChange)1758 void SfxViewFrame::DoAdjustPosSizePixel //! divide on Inner.../Outer...
1759 (
1760 SfxViewShell* pSh,
1761 const Point& rPos,
1762 const Size& rSize,
1763 bool inplaceEditModeChange
1764 )
1765 {
1766
1767 // Components do not use this Method!
1768 if( pSh && pSh->GetWindow() && !m_nAdjustPosPixelLock )
1769 {
1770 m_nAdjustPosPixelLock++;
1771 if ( m_pImpl->bResizeInToOut )
1772 pSh->InnerResizePixel( rPos, rSize, inplaceEditModeChange );
1773 else
1774 pSh->OuterResizePixel( rPos, rSize );
1775 m_nAdjustPosPixelLock--;
1776 }
1777 }
1778
operator ==(const SfxPoolItem & rItem) const1779 bool SfxViewFrameItem::operator==( const SfxPoolItem &rItem ) const
1780 {
1781 return SfxPoolItem::operator==(rItem) &&
1782 static_cast<const SfxViewFrameItem&>(rItem).pFrame == pFrame;
1783 }
1784
Clone(SfxItemPool *) const1785 SfxPoolItem* SfxViewFrameItem::Clone( SfxItemPool *) const
1786 {
1787 return new SfxViewFrameItem( *this );
1788 }
1789
SetViewShell_Impl(SfxViewShell * pVSh)1790 void SfxViewFrame::SetViewShell_Impl( SfxViewShell *pVSh )
1791 /* [Description]
1792
1793 Internal Method to set the current <SfxViewShell> Instance,
1794 that is active int this SfxViewFrame at the moment.
1795 */
1796 {
1797 SfxShell::SetViewShell_Impl( pVSh );
1798
1799 // Hack: InPlaceMode
1800 if ( pVSh )
1801 m_pImpl->bResizeInToOut = false;
1802 }
1803
ForceOuterResize_Impl()1804 void SfxViewFrame::ForceOuterResize_Impl()
1805 {
1806 m_pImpl->bResizeInToOut = true;
1807 }
1808
GetDocNumber_Impl()1809 void SfxViewFrame::GetDocNumber_Impl()
1810 {
1811 DBG_ASSERT( GetObjectShell(), "No Document!" );
1812 GetObjectShell()->SetNamedVisibility_Impl();
1813 m_pImpl->nDocViewNo = GetObjectShell()->GetNoSet_Impl().GetFreeIndex()+1;
1814 }
1815
Enable(bool bEnable)1816 void SfxViewFrame::Enable( bool bEnable )
1817 {
1818 if ( bEnable == m_pImpl->bEnabled )
1819 return;
1820
1821 m_pImpl->bEnabled = bEnable;
1822
1823 vcl::Window *pWindow = &GetFrame().GetWindow();
1824 if ( !bEnable )
1825 m_pImpl->bWindowWasEnabled = pWindow->IsInputEnabled();
1826 if ( !bEnable || m_pImpl->bWindowWasEnabled )
1827 pWindow->EnableInput( bEnable );
1828
1829 // cursor and focus
1830 SfxViewShell* pViewSh = GetViewShell();
1831 if ( bEnable )
1832 {
1833 // show cursor
1834 if ( pViewSh )
1835 pViewSh->ShowCursor();
1836 }
1837 else
1838 {
1839 // hide cursor
1840 if ( pViewSh )
1841 pViewSh->ShowCursor(false);
1842 }
1843 }
1844
1845 /* [Description]
1846
1847 This method makes the Frame-Window visible and before transmits the
1848 window name. In addition, the document is held. In general one can never
1849 show the window directly!
1850 */
Show()1851 void SfxViewFrame::Show()
1852 {
1853 // First lock the objectShell so that UpdateTitle() is valid:
1854 // IsVisible() == true (:#)
1855 if ( m_xObjSh.is() )
1856 {
1857 m_xObjSh->GetMedium()->GetItemSet()->ClearItem( SID_HIDDEN );
1858 if ( !m_pImpl->bObjLocked )
1859 LockObjectShell_Impl();
1860
1861 // Adjust Doc-Shell title number, get unique view-no
1862 if ( 0 == m_pImpl->nDocViewNo )
1863 {
1864 GetDocNumber_Impl();
1865 UpdateTitle();
1866 }
1867 }
1868 else
1869 UpdateTitle();
1870
1871 // Display Frame-window, but only if the ViewFrame has no window of its
1872 // own or if it does not contain a Component
1873 GetWindow().Show();
1874 GetFrame().GetWindow().Show();
1875 }
1876
1877
IsVisible() const1878 bool SfxViewFrame::IsVisible() const
1879 {
1880 return m_pImpl->bObjLocked;
1881 }
1882
1883
LockObjectShell_Impl()1884 void SfxViewFrame::LockObjectShell_Impl()
1885 {
1886 DBG_ASSERT( !m_pImpl->bObjLocked, "Wrong Locked status!" );
1887
1888 DBG_ASSERT( GetObjectShell(), "No Document!" );
1889 GetObjectShell()->OwnerLock(true);
1890 m_pImpl->bObjLocked = true;
1891 }
1892
1893
MakeActive_Impl(bool bGrabFocus)1894 void SfxViewFrame::MakeActive_Impl( bool bGrabFocus )
1895 {
1896 if ( !GetViewShell() || GetFrame().IsClosing_Impl() )
1897 return;
1898
1899 if ( !IsVisible() )
1900 return;
1901
1902 bool bPreview = false;
1903 if (GetObjectShell()->IsPreview())
1904 {
1905 bPreview = true;
1906 }
1907
1908 css::uno::Reference<css::frame::XFrame> xFrame = GetFrame().GetFrameInterface();
1909 if (!bPreview)
1910 {
1911 SetViewFrame(this);
1912 GetBindings().SetActiveFrame(css::uno::Reference<css::frame::XFrame>());
1913 uno::Reference<frame::XFramesSupplier> xSupp(xFrame, uno::UNO_QUERY);
1914 if (xSupp.is())
1915 xSupp->setActiveFrame(uno::Reference<frame::XFrame>());
1916
1917 css::uno::Reference< css::awt::XWindow > xContainerWindow = xFrame->getContainerWindow();
1918 VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow(xContainerWindow);
1919 if (pWindow && pWindow->HasChildPathFocus() && bGrabFocus)
1920 {
1921 SfxInPlaceClient *pCli = GetViewShell()->GetUIActiveClient();
1922 if (!pCli || !pCli->IsObjectUIActive())
1923 GetFrame().GrabFocusOnComponent_Impl();
1924 }
1925 }
1926 else
1927 {
1928 GetBindings().SetDispatcher(GetDispatcher());
1929 GetBindings().SetActiveFrame(css::uno::Reference<css::frame::XFrame>());
1930 GetDispatcher()->Update_Impl();
1931 }
1932 }
1933
GetObjectShell()1934 SfxObjectShell* SfxViewFrame::GetObjectShell()
1935 {
1936 return m_xObjSh.get();
1937 }
1938
GetMargin_Impl() const1939 const Size& SfxViewFrame::GetMargin_Impl() const
1940 {
1941 return m_pImpl->aMargin;
1942 }
1943
LoadViewIntoFrame_Impl_NoThrow(const SfxObjectShell & i_rDoc,const Reference<XFrame> & i_rFrame,const SfxInterfaceId i_nViewId,const bool i_bHidden)1944 SfxViewFrame* SfxViewFrame::LoadViewIntoFrame_Impl_NoThrow( const SfxObjectShell& i_rDoc, const Reference< XFrame >& i_rFrame,
1945 const SfxInterfaceId i_nViewId, const bool i_bHidden )
1946 {
1947 Reference< XFrame > xFrame( i_rFrame );
1948 bool bOwnFrame = false;
1949 SfxViewShell* pSuccessView = nullptr;
1950 try
1951 {
1952 if ( !xFrame.is() )
1953 {
1954 Reference < XDesktop2 > xDesktop = Desktop::create( ::comphelper::getProcessComponentContext() );
1955
1956 if ( !i_bHidden )
1957 {
1958 try
1959 {
1960 // if there is a backing component, use it
1961 ::framework::FrameListAnalyzer aAnalyzer( xDesktop, Reference< XFrame >(), FrameAnalyzerFlags::BackingComponent );
1962
1963 if ( aAnalyzer.m_xBackingComponent.is() )
1964 xFrame = aAnalyzer.m_xBackingComponent;
1965 }
1966 catch( uno::Exception& )
1967 {}
1968 }
1969
1970 if ( !xFrame.is() )
1971 xFrame.set( xDesktop->findFrame( "_blank", 0 ), UNO_SET_THROW );
1972
1973 bOwnFrame = true;
1974 }
1975
1976 pSuccessView = LoadViewIntoFrame_Impl(
1977 i_rDoc,
1978 xFrame,
1979 Sequence< PropertyValue >(), // means "reuse existing model's args"
1980 i_nViewId,
1981 i_bHidden
1982 );
1983
1984 if ( bOwnFrame && !i_bHidden )
1985 {
1986 // ensure the frame/window is visible
1987 Reference< XWindow > xContainerWindow( xFrame->getContainerWindow(), UNO_SET_THROW );
1988 xContainerWindow->setVisible( true );
1989 }
1990 }
1991 catch( const Exception& )
1992 {
1993 DBG_UNHANDLED_EXCEPTION("sfx.view");
1994 }
1995
1996 if ( pSuccessView )
1997 return pSuccessView->GetViewFrame();
1998
1999 if ( bOwnFrame )
2000 {
2001 try
2002 {
2003 xFrame->dispose();
2004 }
2005 catch( const Exception& )
2006 {
2007 DBG_UNHANDLED_EXCEPTION("sfx.view");
2008 }
2009 }
2010
2011 return nullptr;
2012 }
2013
LoadViewIntoFrame_Impl(const SfxObjectShell & i_rDoc,const Reference<XFrame> & i_rFrame,const Sequence<PropertyValue> & i_rLoadArgs,const SfxInterfaceId i_nViewId,const bool i_bHidden)2014 SfxViewShell* SfxViewFrame::LoadViewIntoFrame_Impl( const SfxObjectShell& i_rDoc, const Reference< XFrame >& i_rFrame,
2015 const Sequence< PropertyValue >& i_rLoadArgs, const SfxInterfaceId i_nViewId,
2016 const bool i_bHidden )
2017 {
2018 Reference< XModel > xDocument( i_rDoc.GetModel(), UNO_SET_THROW );
2019
2020 ::comphelper::NamedValueCollection aTransformLoadArgs( i_rLoadArgs.hasElements() ? i_rLoadArgs : xDocument->getArgs() );
2021 aTransformLoadArgs.put( "Model", xDocument );
2022 if ( i_nViewId )
2023 aTransformLoadArgs.put( "ViewId", sal_uInt16( i_nViewId ) );
2024 if ( i_bHidden )
2025 aTransformLoadArgs.put( "Hidden", i_bHidden );
2026 else
2027 aTransformLoadArgs.remove( "Hidden" );
2028
2029 Reference< XComponentLoader > xLoader( i_rFrame, UNO_QUERY_THROW );
2030 xLoader->loadComponentFromURL( "private:object", "_self", 0,
2031 aTransformLoadArgs.getPropertyValues() );
2032
2033 SfxViewShell* pViewShell = SfxViewShell::Get( i_rFrame->getController() );
2034 ENSURE_OR_THROW( pViewShell,
2035 "SfxViewFrame::LoadViewIntoFrame_Impl: loading an SFX doc into a frame resulted in a non-SFX view - quite impossible" );
2036 return pViewShell;
2037 }
2038
LoadHiddenDocument(SfxObjectShell const & i_rDoc,SfxInterfaceId i_nViewId)2039 SfxViewFrame* SfxViewFrame::LoadHiddenDocument( SfxObjectShell const & i_rDoc, SfxInterfaceId i_nViewId )
2040 {
2041 return LoadViewIntoFrame_Impl_NoThrow( i_rDoc, Reference< XFrame >(), i_nViewId, true );
2042 }
2043
LoadDocument(SfxObjectShell const & i_rDoc,SfxInterfaceId i_nViewId)2044 SfxViewFrame* SfxViewFrame::LoadDocument( SfxObjectShell const & i_rDoc, SfxInterfaceId i_nViewId )
2045 {
2046 return LoadViewIntoFrame_Impl_NoThrow( i_rDoc, Reference< XFrame >(), i_nViewId, false );
2047 }
2048
LoadDocumentIntoFrame(SfxObjectShell const & i_rDoc,const Reference<XFrame> & i_rTargetFrame)2049 SfxViewFrame* SfxViewFrame::LoadDocumentIntoFrame( SfxObjectShell const & i_rDoc, const Reference< XFrame >& i_rTargetFrame )
2050 {
2051 return LoadViewIntoFrame_Impl_NoThrow( i_rDoc, i_rTargetFrame, SFX_INTERFACE_NONE, false );
2052 }
2053
LoadDocumentIntoFrame(SfxObjectShell const & i_rDoc,const SfxFrameItem * i_pFrameItem,SfxInterfaceId i_nViewId)2054 SfxViewFrame* SfxViewFrame::LoadDocumentIntoFrame( SfxObjectShell const & i_rDoc, const SfxFrameItem* i_pFrameItem, SfxInterfaceId i_nViewId )
2055 {
2056 return LoadViewIntoFrame_Impl_NoThrow( i_rDoc, i_pFrameItem && i_pFrameItem->GetFrame() ? i_pFrameItem->GetFrame()->GetFrameInterface() : nullptr, i_nViewId, false );
2057 }
2058
DisplayNewDocument(SfxObjectShell const & i_rDoc,const SfxRequest & i_rCreateDocRequest)2059 SfxViewFrame* SfxViewFrame::DisplayNewDocument( SfxObjectShell const & i_rDoc, const SfxRequest& i_rCreateDocRequest )
2060 {
2061 const SfxUnoFrameItem* pFrameItem = i_rCreateDocRequest.GetArg<SfxUnoFrameItem>(SID_FILLFRAME);
2062 const SfxBoolItem* pHiddenItem = i_rCreateDocRequest.GetArg<SfxBoolItem>(SID_HIDDEN);
2063
2064 return LoadViewIntoFrame_Impl_NoThrow(
2065 i_rDoc,
2066 pFrameItem ? pFrameItem->GetFrame() : nullptr,
2067 SFX_INTERFACE_NONE,
2068 pHiddenItem && pHiddenItem->GetValue()
2069 );
2070 }
2071
Get(const Reference<XController> & i_rController,const SfxObjectShell * i_pDoc)2072 SfxViewFrame* SfxViewFrame::Get( const Reference< XController>& i_rController, const SfxObjectShell* i_pDoc )
2073 {
2074 if ( !i_rController.is() )
2075 return nullptr;
2076
2077 const SfxObjectShell* pDoc = i_pDoc;
2078 if ( !pDoc )
2079 {
2080 Reference< XModel > xDocument( i_rController->getModel() );
2081 for ( pDoc = SfxObjectShell::GetFirst( nullptr, false );
2082 pDoc;
2083 pDoc = SfxObjectShell::GetNext( *pDoc, nullptr, false )
2084 )
2085 {
2086 if ( pDoc->GetModel() == xDocument )
2087 break;
2088 }
2089 }
2090
2091 SfxViewFrame* pViewFrame = nullptr;
2092 for ( pViewFrame = SfxViewFrame::GetFirst( pDoc, false );
2093 pViewFrame;
2094 pViewFrame = SfxViewFrame::GetNext( *pViewFrame, pDoc, false )
2095 )
2096 {
2097 if ( pViewFrame->GetViewShell()->GetController() == i_rController )
2098 break;
2099 }
2100
2101 return pViewFrame;
2102 }
2103
SaveCurrentViewData_Impl(const SfxInterfaceId i_nNewViewId)2104 void SfxViewFrame::SaveCurrentViewData_Impl( const SfxInterfaceId i_nNewViewId )
2105 {
2106 SfxViewShell* pCurrentShell = GetViewShell();
2107 ENSURE_OR_RETURN_VOID( pCurrentShell != nullptr, "SfxViewFrame::SaveCurrentViewData_Impl: no current view shell -> no current view data!" );
2108
2109 // determine the logical (API) view name
2110 const SfxObjectFactory& rDocFactory( pCurrentShell->GetObjectShell()->GetFactory() );
2111 const sal_uInt16 nCurViewNo = rDocFactory.GetViewNo_Impl( GetCurViewId(), 0 );
2112 const OUString sCurrentViewName = rDocFactory.GetViewFactory( nCurViewNo ).GetAPIViewName();
2113 const sal_uInt16 nNewViewNo = rDocFactory.GetViewNo_Impl( i_nNewViewId, 0 );
2114 const OUString sNewViewName = rDocFactory.GetViewFactory( nNewViewNo ).GetAPIViewName();
2115 if ( sCurrentViewName.isEmpty() || sNewViewName.isEmpty() )
2116 {
2117 // can't say anything about the view, the respective application did not yet migrate its code to
2118 // named view factories => bail out
2119 OSL_FAIL( "SfxViewFrame::SaveCurrentViewData_Impl: views without API names? Shouldn't happen anymore?" );
2120 return;
2121 }
2122 SAL_WARN_IF(sNewViewName == sCurrentViewName, "sfx.view", "SfxViewFrame::SaveCurrentViewData_Impl: suspicious: new and old view name are identical!");
2123
2124 // save the view data only when we're moving from a non-print-preview to the print-preview view
2125 if ( sNewViewName != "PrintPreview" )
2126 return;
2127
2128 // retrieve the view data from the view
2129 Sequence< PropertyValue > aViewData;
2130 pCurrentShell->WriteUserDataSequence( aViewData );
2131
2132 try
2133 {
2134 // retrieve view data (for *all* views) from the model
2135 const Reference< XController > xController( pCurrentShell->GetController(), UNO_SET_THROW );
2136 const Reference< XViewDataSupplier > xViewDataSupplier( xController->getModel(), UNO_QUERY_THROW );
2137 const Reference< XIndexContainer > xViewData( xViewDataSupplier->getViewData(), UNO_QUERY_THROW );
2138
2139 // look up the one view data item which corresponds to our current view, and remove it
2140 const sal_Int32 nCount = xViewData->getCount();
2141 for ( sal_Int32 i=0; i<nCount; ++i )
2142 {
2143 const ::comphelper::NamedValueCollection aCurViewData( xViewData->getByIndex(i) );
2144 const OUString sViewId( aCurViewData.getOrDefault( "ViewId", OUString() ) );
2145 if ( sViewId.isEmpty() )
2146 continue;
2147
2148 const SfxViewFactory* pViewFactory = rDocFactory.GetViewFactoryByViewName( sViewId );
2149 if ( pViewFactory == nullptr )
2150 continue;
2151
2152 if ( pViewFactory->GetOrdinal() == GetCurViewId() )
2153 {
2154 xViewData->removeByIndex(i);
2155 break;
2156 }
2157 }
2158
2159 // then replace it with the most recent view data we just obtained
2160 xViewData->insertByIndex( 0, makeAny( aViewData ) );
2161 }
2162 catch( const Exception& )
2163 {
2164 DBG_UNHANDLED_EXCEPTION("sfx.view");
2165 }
2166 }
2167
2168 /* [Description]
2169
2170 Internal Method for switching to another <SfxViewShell> subclass,
2171 which should be created in this SfxMDIFrame. If no SfxViewShell exist
2172 in this SfxMDIFrame, then one will first be created.
2173
2174
2175 [Return Value]
2176
2177 bool true
2178 requested SfxViewShell was created and a
2179 possibly existing one deleted
2180
2181 false
2182 SfxViewShell requested could not be created,
2183 the existing SfxViewShell thus continue to exist
2184 */
SwitchToViewShell_Impl(sal_uInt16 nViewIdOrNo,bool bIsIndex)2185 bool SfxViewFrame::SwitchToViewShell_Impl
2186 (
2187 sal_uInt16 nViewIdOrNo, /* > 0
2188 Registration-Id of the View, to which the
2189 method should switch, for example the one
2190 that will be created.
2191
2192 == 0
2193 First use the Default view. */
2194
2195 bool bIsIndex /* true
2196 'nViewIdOrNo' is no Registration-Id instead
2197 an Index of <SfxViewFrame> in <SfxObjectShell>.
2198 */
2199 )
2200 {
2201 try
2202 {
2203 ENSURE_OR_THROW( GetObjectShell() != nullptr, "not possible without a document" );
2204
2205 // if we already have a view shell, remove it
2206 SfxViewShell* pOldSh = GetViewShell();
2207 OSL_PRECOND( pOldSh, "SfxViewFrame::SwitchToViewShell_Impl: that's called *switch* (not for *initial-load*) for a reason" );
2208 if ( pOldSh )
2209 {
2210 // ask whether it can be closed
2211 if ( !pOldSh->PrepareClose() )
2212 return false;
2213
2214 // remove sub shells from Dispatcher before switching to new ViewShell
2215 PopShellAndSubShells_Impl( *pOldSh );
2216 }
2217
2218 GetBindings().ENTERREGISTRATIONS();
2219 LockAdjustPosSizePixel();
2220
2221 // ID of the new view
2222 SfxObjectFactory& rDocFact = GetObjectShell()->GetFactory();
2223 const SfxInterfaceId nViewId = ( bIsIndex || !nViewIdOrNo ) ? rDocFact.GetViewFactory( nViewIdOrNo ).GetOrdinal() : SfxInterfaceId(nViewIdOrNo);
2224
2225 // save the view data of the old view, so it can be restored later on (when needed)
2226 SaveCurrentViewData_Impl( nViewId );
2227
2228 // create and load new ViewShell
2229 SfxViewShell* pNewSh = LoadViewIntoFrame_Impl(
2230 *GetObjectShell(),
2231 GetFrame().GetFrameInterface(),
2232 Sequence< PropertyValue >(), // means "reuse existing model's args"
2233 nViewId,
2234 false
2235 );
2236
2237 // allow resize events to be processed
2238 UnlockAdjustPosSizePixel();
2239
2240 if ( GetWindow().IsReallyVisible() )
2241 DoAdjustPosSizePixel( pNewSh, Point(), GetWindow().GetOutputSizePixel(), false );
2242
2243 GetBindings().LEAVEREGISTRATIONS();
2244 delete pOldSh;
2245 }
2246 catch ( const css::uno::Exception& )
2247 {
2248 // the SfxCode is not able to cope with exceptions thrown while creating views
2249 // the code will crash in the stack unwinding procedure, so we shouldn't let exceptions go through here
2250 DBG_UNHANDLED_EXCEPTION("sfx.view");
2251 return false;
2252 }
2253
2254 DBG_ASSERT( SfxGetpApp()->GetViewFrames_Impl().size() == SfxGetpApp()->GetViewShells_Impl().size(), "Inconsistent view arrays!" );
2255 return true;
2256 }
2257
SetCurViewId_Impl(const SfxInterfaceId i_nID)2258 void SfxViewFrame::SetCurViewId_Impl( const SfxInterfaceId i_nID )
2259 {
2260 m_pImpl->nCurViewId = i_nID;
2261 }
2262
GetCurViewId() const2263 SfxInterfaceId SfxViewFrame::GetCurViewId() const
2264 {
2265 return m_pImpl->nCurViewId;
2266 }
2267
2268 /* [Description]
2269
2270 Internal method to run the slot for the <SfxShell> Subclass in the
2271 SfxViewFrame <SVIDL> described slots.
2272 */
ExecView_Impl(SfxRequest & rReq)2273 void SfxViewFrame::ExecView_Impl
2274 (
2275 SfxRequest& rReq // The executable <SfxRequest>
2276 )
2277 {
2278
2279 // If the Shells are just being replaced...
2280 if ( !GetObjectShell() || !GetViewShell() )
2281 return;
2282
2283 switch ( rReq.GetSlot() )
2284 {
2285 case SID_TERMINATE_INPLACEACTIVATION :
2286 {
2287 SfxInPlaceClient* pClient = GetViewShell()->GetUIActiveClient();
2288 if ( pClient )
2289 pClient->DeactivateObject();
2290 break;
2291 }
2292
2293 case SID_VIEWSHELL:
2294 {
2295 const SfxPoolItem *pItem = nullptr;
2296 if ( rReq.GetArgs()
2297 && SfxItemState::SET == rReq.GetArgs()->GetItemState( SID_VIEWSHELL, false, &pItem )
2298 )
2299 {
2300 const sal_uInt16 nViewId = static_cast< const SfxUInt16Item* >( pItem )->GetValue();
2301 bool bSuccess = SwitchToViewShell_Impl( nViewId );
2302 rReq.SetReturnValue( SfxBoolItem( 0, bSuccess ) );
2303 }
2304 break;
2305 }
2306
2307 case SID_VIEWSHELL0:
2308 case SID_VIEWSHELL1:
2309 case SID_VIEWSHELL2:
2310 case SID_VIEWSHELL3:
2311 case SID_VIEWSHELL4:
2312 {
2313 const sal_uInt16 nViewNo = rReq.GetSlot() - SID_VIEWSHELL0;
2314 bool bSuccess = SwitchToViewShell_Impl( nViewNo, true );
2315 rReq.SetReturnValue( SfxBoolItem( 0, bSuccess ) );
2316 break;
2317 }
2318
2319 case SID_NEWWINDOW:
2320 {
2321 // Hack. at the moment a virtual Function
2322 if ( !GetViewShell()->NewWindowAllowed() )
2323 {
2324 OSL_FAIL( "You should have disabled the 'Window/New Window' slot!" );
2325 return;
2326 }
2327
2328 // Get ViewData of FrameSets recursively.
2329 GetFrame().GetViewData_Impl();
2330 SfxMedium* pMed = GetObjectShell()->GetMedium();
2331
2332 // do not open the new window hidden
2333 pMed->GetItemSet()->ClearItem( SID_HIDDEN );
2334
2335 // the view ID (optional arg. TODO: this is currently not supported in the slot definition ...)
2336 const SfxUInt16Item* pViewIdItem = rReq.GetArg<SfxUInt16Item>(SID_VIEW_ID);
2337 const SfxInterfaceId nViewId = pViewIdItem ? SfxInterfaceId(pViewIdItem->GetValue()) : GetCurViewId();
2338
2339 Reference < XFrame > xFrame;
2340 // the frame (optional arg. TODO: this is currently not supported in the slot definition ...)
2341 const SfxUnoFrameItem* pFrameItem = rReq.GetArg<SfxUnoFrameItem>(SID_FILLFRAME);
2342 if ( pFrameItem )
2343 xFrame = pFrameItem->GetFrame();
2344
2345 LoadViewIntoFrame_Impl_NoThrow( *GetObjectShell(), xFrame, nViewId, false );
2346
2347 rReq.Done();
2348 break;
2349 }
2350
2351 case SID_OBJECT:
2352 {
2353 const SfxInt16Item* pItem = rReq.GetArg<SfxInt16Item>(SID_OBJECT);
2354
2355 if (pItem)
2356 {
2357 GetViewShell()->DoVerb( pItem->GetValue() );
2358 rReq.Done();
2359 break;
2360 }
2361 }
2362 }
2363 }
2364
2365 /* TODO as96863:
2366 This method try to collect information about the count of currently open documents.
2367 But the algorithm is implemented very simple ...
2368 E.g. hidden documents should be ignored here ... but they are counted.
2369 TODO: export special helper "framework::FrameListAnalyzer" within the framework module
2370 and use it here.
2371 */
impl_maxOpenDocCountReached()2372 static bool impl_maxOpenDocCountReached()
2373 {
2374 css::uno::Reference< css::uno::XComponentContext > xContext = ::comphelper::getProcessComponentContext();
2375 boost::optional<sal_Int32> x(officecfg::Office::Common::Misc::MaxOpenDocuments::get(xContext));
2376 // NIL means: count of allowed documents = infinite !
2377 if (!x)
2378 return false;
2379 sal_Int32 nMaxDocs(x.get());
2380 sal_Int32 nOpenDocs = 0;
2381
2382 css::uno::Reference< css::frame::XDesktop2 > xDesktop = css::frame::Desktop::create(xContext);
2383 css::uno::Reference< css::container::XIndexAccess > xCont(xDesktop->getFrames(), css::uno::UNO_QUERY_THROW);
2384
2385 sal_Int32 c = xCont->getCount();
2386 sal_Int32 i = 0;
2387
2388 for (i=0; i<c; ++i)
2389 {
2390 try
2391 {
2392 css::uno::Reference< css::frame::XFrame > xFrame;
2393 xCont->getByIndex(i) >>= xFrame;
2394 if ( ! xFrame.is())
2395 continue;
2396
2397 // a) do not count the help window
2398 if ( xFrame->getName() == "OFFICE_HELP_TASK" )
2399 continue;
2400
2401 // b) count all other frames
2402 ++nOpenDocs;
2403 }
2404 catch(const css::uno::Exception&)
2405 // An IndexOutOfBoundsException can happen in multithreaded
2406 // environments, where any other thread can change this
2407 // container !
2408 { continue; }
2409 }
2410
2411 return (nOpenDocs >= nMaxDocs);
2412 }
2413
2414 /* [Description]
2415
2416 This internal method returns in 'rSet' the Status for the <SfxShell>
2417 Subclass SfxViewFrame in the <SVIDL> described <Slots>.
2418
2419 Thus exactly those Slots-IDs that are recognized as being invalid by Sfx
2420 are included as Which-ranges in 'rSet'. If there exists a mapping for
2421 single slot-IDs of the <SfxItemPool> set in the shell, then the respective
2422 Which-IDs are used so that items can be replaced directly with a working
2423 Core::sun::com::star::script::Engine of the Which-IDs if possible. .
2424 */
StateView_Impl(SfxItemSet & rSet)2425 void SfxViewFrame::StateView_Impl
2426 (
2427 SfxItemSet& rSet /* empty <SfxItemSet> with <Which-Ranges>,
2428 which describes the Slot Ids */
2429 )
2430 {
2431
2432 SfxObjectShell *pDocSh = GetObjectShell();
2433
2434 if ( !pDocSh )
2435 // I'm just on reload and am yielding myself ...
2436 return;
2437
2438 const sal_uInt16 *pRanges = rSet.GetRanges();
2439 assert(pRanges && "Set with no Range");
2440 while ( *pRanges )
2441 {
2442 sal_uInt16 nStartWhich = *pRanges++;
2443 sal_uInt16 nEndWhich = *pRanges++;
2444 for ( sal_uInt16 nWhich = nStartWhich; nWhich <= nEndWhich; ++nWhich )
2445 {
2446 switch(nWhich)
2447 {
2448 case SID_VIEWSHELL:
2449 {
2450 rSet.Put( SfxUInt16Item( nWhich, sal_uInt16(m_pImpl->nCurViewId )) );
2451 break;
2452 }
2453
2454 case SID_VIEWSHELL0:
2455 case SID_VIEWSHELL1:
2456 case SID_VIEWSHELL2:
2457 case SID_VIEWSHELL3:
2458 case SID_VIEWSHELL4:
2459 {
2460 sal_uInt16 nViewNo = nWhich - SID_VIEWSHELL0;
2461 if ( GetObjectShell()->GetFactory().GetViewFactoryCount() >
2462 nViewNo && !GetObjectShell()->IsInPlaceActive() )
2463 {
2464 SfxViewFactory &rViewFactory =
2465 GetObjectShell()->GetFactory().GetViewFactory(nViewNo);
2466 rSet.Put( SfxBoolItem(
2467 nWhich, m_pImpl->nCurViewId == rViewFactory.GetOrdinal() ) );
2468 }
2469 else
2470 rSet.DisableItem( nWhich );
2471 break;
2472 }
2473
2474 case SID_NEWWINDOW:
2475 {
2476 if ( !GetViewShell()->NewWindowAllowed()
2477 || impl_maxOpenDocCountReached()
2478 )
2479 rSet.DisableItem( nWhich );
2480 break;
2481 }
2482 }
2483 }
2484 }
2485 }
2486
2487
ToTop()2488 void SfxViewFrame::ToTop()
2489 {
2490 GetFrame().Appear();
2491 }
2492
2493
2494 /* [Description]
2495
2496 GetFrame returns the Frame, in which the ViewFrame is located.
2497 */
GetFrame() const2498 SfxFrame& SfxViewFrame::GetFrame() const
2499 {
2500 return m_pImpl->rFrame;
2501 }
2502
GetTopViewFrame() const2503 SfxViewFrame* SfxViewFrame::GetTopViewFrame() const
2504 {
2505 return GetFrame().GetCurrentViewFrame();
2506 }
2507
GetWindow() const2508 vcl::Window& SfxViewFrame::GetWindow() const
2509 {
2510 return m_pImpl->pWindow ? *m_pImpl->pWindow : GetFrame().GetWindow();
2511 }
2512
DoClose()2513 bool SfxViewFrame::DoClose()
2514 {
2515 return GetFrame().DoClose();
2516 }
2517
GetActualPresentationURL_Impl() const2518 OUString SfxViewFrame::GetActualPresentationURL_Impl() const
2519 {
2520 if ( m_xObjSh.is() )
2521 return m_xObjSh->GetMedium()->GetName();
2522 return OUString();
2523 }
2524
SetModalMode(bool bModal)2525 void SfxViewFrame::SetModalMode( bool bModal )
2526 {
2527 // no real modality for LOK
2528 if (comphelper::LibreOfficeKit::isActive())
2529 return;
2530
2531 m_pImpl->bModal = bModal;
2532 if ( m_xObjSh.is() )
2533 {
2534 for ( SfxViewFrame* pFrame = SfxViewFrame::GetFirst( m_xObjSh.get() );
2535 !bModal && pFrame; pFrame = SfxViewFrame::GetNext( *pFrame, m_xObjSh.get() ) )
2536 bModal = pFrame->m_pImpl->bModal;
2537 m_xObjSh->SetModalMode_Impl( bModal );
2538 }
2539 }
2540
IsInModalMode() const2541 bool SfxViewFrame::IsInModalMode() const
2542 {
2543 return m_pImpl->bModal || GetFrame().GetWindow().IsInModalMode();
2544 }
2545
Resize(bool bForce)2546 void SfxViewFrame::Resize( bool bForce )
2547 {
2548 Size aSize = GetWindow().GetOutputSizePixel();
2549 if ( !bForce && aSize == m_pImpl->aSize )
2550 return;
2551
2552 m_pImpl->aSize = aSize;
2553 SfxViewShell *pShell = GetViewShell();
2554 if ( pShell )
2555 {
2556 if ( GetFrame().IsInPlace() )
2557 {
2558 Point aPoint = GetWindow().GetPosPixel();
2559 DoAdjustPosSizePixel( pShell, aPoint, aSize, true );
2560 }
2561 else
2562 {
2563 DoAdjustPosSizePixel( pShell, Point(), aSize, false );
2564 }
2565 }
2566 }
2567
2568 #if HAVE_FEATURE_SCRIPTING
2569
2570 #define LINE_SEP 0x0A
2571
CutLines(OUString & rStr,sal_Int32 nStartLine,sal_Int32 nLines)2572 static void CutLines( OUString& rStr, sal_Int32 nStartLine, sal_Int32 nLines )
2573 {
2574 sal_Int32 nStartPos = 0;
2575 sal_Int32 nLine = 0;
2576 while ( nLine < nStartLine )
2577 {
2578 nStartPos = rStr.indexOf( LINE_SEP, nStartPos );
2579 if( nStartPos == -1 )
2580 break;
2581 nStartPos++; // not the \n.
2582 nLine++;
2583 }
2584
2585 SAL_WARN_IF(nStartPos == -1, "sfx.view", "CutLines: Start row not found!");
2586
2587 if ( nStartPos != -1 )
2588 {
2589 sal_Int32 nEndPos = nStartPos;
2590 for ( sal_Int32 i = 0; i < nLines; i++ )
2591 nEndPos = rStr.indexOf( LINE_SEP, nEndPos+1 );
2592
2593 if ( nEndPos == -1 ) // Can happen at the last row.
2594 nEndPos = rStr.getLength();
2595 else
2596 nEndPos++;
2597
2598 rStr = rStr.copy( 0, nStartPos ) + rStr.copy( nEndPos );
2599 }
2600 // erase trailing lines
2601 if ( nStartPos != -1 )
2602 {
2603 sal_Int32 n = nStartPos;
2604 sal_Int32 nLen = rStr.getLength();
2605 while ( ( n < nLen ) && ( rStr[ n ] == LINE_SEP ) )
2606 n++;
2607
2608 if ( n > nStartPos )
2609 rStr = rStr.copy( 0, nStartPos ) + rStr.copy( n );
2610 }
2611 }
2612
2613 #endif
2614
2615 /*
2616 add new recorded dispatch macro script into the application global basic
2617 lib container. It generates a new unique id for it and insert the macro
2618 by using this number as name for the module
2619 */
AddDispatchMacroToBasic_Impl(const OUString & sMacro)2620 void SfxViewFrame::AddDispatchMacroToBasic_Impl( const OUString& sMacro )
2621 {
2622 #if !HAVE_FEATURE_SCRIPTING
2623 (void) sMacro;
2624 #else
2625 if ( sMacro.isEmpty() )
2626 return;
2627
2628 SfxApplication* pSfxApp = SfxGetpApp();
2629 SfxItemPool& rPool = pSfxApp->GetPool();
2630 SfxRequest aReq(SID_BASICCHOOSER, SfxCallMode::SYNCHRON, rPool);
2631
2632 //seen in tdf#122598, no parent for subsequent dialog
2633 SfxAllItemSet aSet(rPool);
2634 css::uno::Reference< css::frame::XFrame > xFrame =
2635 GetFrame().GetFrameInterface();
2636 aSet.Put(SfxUnoFrameItem(SID_FILLFRAME, xFrame));
2637 aReq.SetInternalArgs_Impl(aSet);
2638
2639 aReq.AppendItem( SfxBoolItem(SID_RECORDMACRO,true) );
2640 const SfxPoolItem* pRet = SfxGetpApp()->ExecuteSlot( aReq );
2641 OUString aScriptURL;
2642 if ( pRet )
2643 aScriptURL = static_cast<const SfxStringItem*>(pRet)->GetValue();
2644 if ( !aScriptURL.isEmpty() )
2645 {
2646 // parse scriptURL
2647 OUString aLibName;
2648 OUString aModuleName;
2649 OUString aMacroName;
2650 OUString aLocation;
2651 Reference< XComponentContext > xContext = ::comphelper::getProcessComponentContext();
2652 Reference< css::uri::XUriReferenceFactory > xFactory =
2653 css::uri::UriReferenceFactory::create( xContext );
2654 Reference< css::uri::XVndSunStarScriptUrl > xUrl( xFactory->parse( aScriptURL ), UNO_QUERY );
2655 if ( xUrl.is() )
2656 {
2657 // get name
2658 const OUString aName = xUrl->getName();
2659 const sal_Unicode cTok = '.';
2660 sal_Int32 nIndex = 0;
2661 aLibName = aName.getToken( 0, cTok, nIndex );
2662 if ( nIndex != -1 )
2663 aModuleName = aName.getToken( 0, cTok, nIndex );
2664 if ( nIndex != -1 )
2665 aMacroName = aName.getToken( 0, cTok, nIndex );
2666
2667 // get location
2668 aLocation = xUrl->getParameter( "location" );
2669 }
2670
2671 BasicManager* pBasMgr = nullptr;
2672 if ( aLocation == "application" )
2673 {
2674 // application basic
2675 pBasMgr = SfxApplication::GetBasicManager();
2676 }
2677 else if ( aLocation == "document" )
2678 {
2679 pBasMgr = GetObjectShell()->GetBasicManager();
2680 }
2681
2682 OUString aOUSource;
2683 if ( pBasMgr)
2684 {
2685 StarBASIC* pBasic = pBasMgr->GetLib( aLibName );
2686 if ( pBasic )
2687 {
2688 SbModule* pModule = pBasic->FindModule( aModuleName );
2689 SbMethod* pMethod = pModule ? pModule->FindMethod(aMacroName, SbxClassType::Method) : nullptr;
2690 if (pMethod)
2691 {
2692 aOUSource = pModule->GetSource32();
2693 sal_uInt16 nStart, nEnd;
2694 pMethod->GetLineRange( nStart, nEnd );
2695 sal_uIntPtr nlStart = nStart;
2696 sal_uIntPtr nlEnd = nEnd;
2697 CutLines( aOUSource, nlStart-1, nlEnd-nlStart+1 );
2698 }
2699 }
2700 }
2701
2702 // open lib container and break operation if it couldn't be opened
2703 css::uno::Reference< css::script::XLibraryContainer > xLibCont;
2704 if ( aLocation == "application" )
2705 {
2706 xLibCont = SfxGetpApp()->GetBasicContainer();
2707 }
2708 else if ( aLocation == "document" )
2709 {
2710 xLibCont = GetObjectShell()->GetBasicContainer();
2711 }
2712
2713 if(!xLibCont.is())
2714 {
2715 SAL_WARN("sfx.view", "couldn't get access to the basic lib container. Adding of macro isn't possible.");
2716 return;
2717 }
2718
2719 // get LibraryContainer
2720 css::uno::Any aTemp;
2721
2722 css::uno::Reference< css::container::XNameAccess > xLib;
2723 if(xLibCont->hasByName(aLibName))
2724 {
2725 // library must be loaded
2726 aTemp = xLibCont->getByName(aLibName);
2727 xLibCont->loadLibrary(aLibName);
2728 aTemp >>= xLib;
2729 }
2730 else
2731 {
2732 xLib = xLibCont->createLibrary(aLibName);
2733 }
2734
2735 // pack the macro as direct usable "sub" routine
2736 OUStringBuffer sRoutine(10000);
2737 bool bReplace = false;
2738
2739 // get module
2740 if(xLib->hasByName(aModuleName))
2741 {
2742 if ( !aOUSource.isEmpty() )
2743 {
2744 sRoutine.append( aOUSource );
2745 }
2746 else
2747 {
2748 OUString sCode;
2749 aTemp = xLib->getByName(aModuleName);
2750 aTemp >>= sCode;
2751 sRoutine.append( sCode );
2752 }
2753
2754 bReplace = true;
2755 }
2756
2757 // append new method
2758 sRoutine.append( "\nsub " );
2759 sRoutine.append(aMacroName);
2760 sRoutine.append( "\n" );
2761 sRoutine.append(sMacro);
2762 sRoutine.append( "\nend sub\n" );
2763
2764 // create the module inside the library and insert the macro routine
2765 aTemp <<= sRoutine.makeStringAndClear();
2766 if ( bReplace )
2767 {
2768 css::uno::Reference< css::container::XNameContainer > xModulCont(
2769 xLib,
2770 css::uno::UNO_QUERY);
2771 xModulCont->replaceByName(aModuleName,aTemp);
2772 }
2773 else
2774 {
2775 css::uno::Reference< css::container::XNameContainer > xModulCont(
2776 xLib,
2777 css::uno::UNO_QUERY);
2778 xModulCont->insertByName(aModuleName,aTemp);
2779 }
2780
2781 // #i17355# update the Basic IDE
2782 for ( SfxViewShell* pViewShell = SfxViewShell::GetFirst(); pViewShell; pViewShell = SfxViewShell::GetNext( *pViewShell ) )
2783 {
2784 if ( pViewShell->GetName() == "BasicIDE" )
2785 {
2786 SfxViewFrame* pViewFrame = pViewShell->GetViewFrame();
2787 SfxDispatcher* pDispat = pViewFrame ? pViewFrame->GetDispatcher() : nullptr;
2788 if ( pDispat )
2789 {
2790 SfxMacroInfoItem aInfoItem( SID_BASICIDE_ARG_MACROINFO, pBasMgr, aLibName, aModuleName, OUString(), OUString() );
2791 pDispat->ExecuteList(SID_BASICIDE_UPDATEMODULESOURCE,
2792 SfxCallMode::SYNCHRON, { &aInfoItem });
2793 }
2794 }
2795 }
2796 }
2797 else
2798 {
2799 // add code for "session only" macro
2800 }
2801 #endif
2802 }
2803
MiscExec_Impl(SfxRequest & rReq)2804 void SfxViewFrame::MiscExec_Impl( SfxRequest& rReq )
2805 {
2806 switch ( rReq.GetSlot() )
2807 {
2808 case SID_STOP_RECORDING :
2809 case SID_RECORDMACRO :
2810 {
2811 // try to find any active recorder on this frame
2812 const OUString sProperty("DispatchRecorderSupplier");
2813 css::uno::Reference< css::frame::XFrame > xFrame =
2814 GetFrame().GetFrameInterface();
2815
2816 css::uno::Reference< css::beans::XPropertySet > xSet(xFrame,css::uno::UNO_QUERY);
2817 css::uno::Any aProp = xSet->getPropertyValue(sProperty);
2818 css::uno::Reference< css::frame::XDispatchRecorderSupplier > xSupplier;
2819 aProp >>= xSupplier;
2820 css::uno::Reference< css::frame::XDispatchRecorder > xRecorder;
2821 if (xSupplier.is())
2822 xRecorder = xSupplier->getDispatchRecorder();
2823
2824 bool bIsRecording = xRecorder.is();
2825 const SfxBoolItem* pItem = rReq.GetArg<SfxBoolItem>(SID_RECORDMACRO);
2826 if ( pItem && pItem->GetValue() == bIsRecording )
2827 return;
2828
2829 if ( xRecorder.is() )
2830 {
2831 // disable active recording
2832 aProp <<= css::uno::Reference< css::frame::XDispatchRecorderSupplier >();
2833 xSet->setPropertyValue(sProperty,aProp);
2834
2835 const SfxBoolItem* pRecordItem = rReq.GetArg<SfxBoolItem>(FN_PARAM_1);
2836 if ( !pRecordItem || !pRecordItem->GetValue() )
2837 // insert script into basic library container of application
2838 AddDispatchMacroToBasic_Impl(xRecorder->getRecordedMacro());
2839
2840 xRecorder->endRecording();
2841 xRecorder = nullptr;
2842 GetBindings().SetRecorder_Impl( xRecorder );
2843
2844 SetChildWindow( SID_RECORDING_FLOATWINDOW, false );
2845 if ( rReq.GetSlot() != SID_RECORDMACRO )
2846 GetBindings().Invalidate( SID_RECORDMACRO );
2847 }
2848 else if ( rReq.GetSlot() == SID_RECORDMACRO )
2849 {
2850 // enable recording
2851 css::uno::Reference< css::uno::XComponentContext > xContext(
2852 ::comphelper::getProcessComponentContext());
2853
2854 xRecorder = css::frame::DispatchRecorder::create( xContext );
2855
2856 xSupplier = css::frame::DispatchRecorderSupplier::create( xContext );
2857
2858 xSupplier->setDispatchRecorder(xRecorder);
2859 xRecorder->startRecording(xFrame);
2860 aProp <<= xSupplier;
2861 xSet->setPropertyValue(sProperty,aProp);
2862 GetBindings().SetRecorder_Impl( xRecorder );
2863 SetChildWindow( SID_RECORDING_FLOATWINDOW, true );
2864 }
2865
2866 rReq.Done();
2867 break;
2868 }
2869
2870 case SID_TOGGLESTATUSBAR:
2871 {
2872 css::uno::Reference< css::frame::XFrame > xFrame =
2873 GetFrame().GetFrameInterface();
2874
2875 Reference< css::beans::XPropertySet > xPropSet( xFrame, UNO_QUERY );
2876 Reference< css::frame::XLayoutManager > xLayoutManager;
2877 if ( xPropSet.is() )
2878 {
2879 try
2880 {
2881 Any aValue = xPropSet->getPropertyValue("LayoutManager");
2882 aValue >>= xLayoutManager;
2883 }
2884 catch ( Exception& )
2885 {
2886 }
2887 }
2888
2889 if ( xLayoutManager.is() )
2890 {
2891 const OUString aStatusbarResString( "private:resource/statusbar/statusbar" );
2892 // Evaluate parameter.
2893 const SfxBoolItem* pShowItem = rReq.GetArg<SfxBoolItem>(rReq.GetSlot());
2894 bool bShow( true );
2895 if ( !pShowItem )
2896 bShow = xLayoutManager->isElementVisible( aStatusbarResString );
2897 else
2898 bShow = pShowItem->GetValue();
2899
2900 if ( bShow )
2901 {
2902 xLayoutManager->createElement( aStatusbarResString );
2903 xLayoutManager->showElement( aStatusbarResString );
2904 }
2905 else
2906 xLayoutManager->hideElement( aStatusbarResString );
2907
2908 if ( !pShowItem )
2909 rReq.AppendItem( SfxBoolItem( SID_TOGGLESTATUSBAR, bShow ) );
2910 }
2911 rReq.Done();
2912 break;
2913 }
2914
2915 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2916 case SID_WIN_FULLSCREEN:
2917 {
2918 const SfxBoolItem* pItem = rReq.GetArg<SfxBoolItem>(rReq.GetSlot());
2919 SfxViewFrame *pTop = GetTopViewFrame();
2920 if ( pTop )
2921 {
2922 WorkWindow* pWork = static_cast<WorkWindow*>( pTop->GetFrame().GetTopWindow_Impl() );
2923 if ( pWork )
2924 {
2925 css::uno::Reference< css::frame::XFrame > xFrame =
2926 GetFrame().GetFrameInterface();
2927
2928 Reference< css::beans::XPropertySet > xPropSet( xFrame, UNO_QUERY );
2929 Reference< css::frame::XLayoutManager > xLayoutManager;
2930 if ( xPropSet.is() )
2931 {
2932 try
2933 {
2934 Any aValue = xPropSet->getPropertyValue("LayoutManager");
2935 aValue >>= xLayoutManager;
2936 }
2937 catch ( Exception& )
2938 {
2939 }
2940 }
2941
2942 bool bNewFullScreenMode = pItem ? pItem->GetValue() : !pWork->IsFullScreenMode();
2943 if ( bNewFullScreenMode != pWork->IsFullScreenMode() )
2944 {
2945 if ( bNewFullScreenMode )
2946 sfx2::SfxNotebookBar::LockNotebookBar();
2947 else
2948 sfx2::SfxNotebookBar::UnlockNotebookBar();
2949
2950 Reference< css::beans::XPropertySet > xLMPropSet( xLayoutManager, UNO_QUERY );
2951 if ( xLMPropSet.is() )
2952 {
2953 try
2954 {
2955 xLMPropSet->setPropertyValue(
2956 "HideCurrentUI",
2957 makeAny( bNewFullScreenMode ));
2958 }
2959 catch ( css::beans::UnknownPropertyException& )
2960 {
2961 }
2962 }
2963 pWork->ShowFullScreenMode( bNewFullScreenMode );
2964 pWork->SetMenuBarMode( bNewFullScreenMode ? MenuBarMode::Hide : MenuBarMode::Normal );
2965 GetFrame().GetWorkWindow_Impl()->SetFullScreen_Impl( bNewFullScreenMode );
2966 if ( !pItem )
2967 rReq.AppendItem( SfxBoolItem( SID_WIN_FULLSCREEN, bNewFullScreenMode ) );
2968 rReq.Done();
2969 }
2970 else
2971 rReq.Ignore();
2972 }
2973 }
2974 else
2975 rReq.Ignore();
2976
2977 GetDispatcher()->Update_Impl( true );
2978 break;
2979 }
2980 }
2981 }
2982
MiscState_Impl(SfxItemSet & rSet)2983 void SfxViewFrame::MiscState_Impl(SfxItemSet &rSet)
2984 {
2985 const sal_uInt16 *pRanges = rSet.GetRanges();
2986 DBG_ASSERT(pRanges && *pRanges, "Set without range");
2987 while ( *pRanges )
2988 {
2989 for(sal_uInt16 nWhich = *pRanges++; nWhich <= *pRanges; ++nWhich)
2990 {
2991 switch(nWhich)
2992 {
2993 case SID_CURRENT_URL:
2994 {
2995 rSet.Put( SfxStringItem( nWhich, GetActualPresentationURL_Impl() ) );
2996 break;
2997 }
2998
2999 case SID_RECORDMACRO :
3000 {
3001 SvtMiscOptions aMiscOptions;
3002 const OUString& sName{GetObjectShell()->GetFactory().GetFactoryName()};
3003 bool bMacrosDisabled = officecfg::Office::Common::Security::Scripting::DisableMacrosExecution::get();
3004 if (bMacrosDisabled || !aMiscOptions.IsMacroRecorderMode() ||
3005 ( sName!="swriter" && sName!="scalc" ) )
3006 {
3007 rSet.DisableItem( nWhich );
3008 rSet.Put(SfxVisibilityItem(nWhich, false));
3009 break;
3010 }
3011
3012 css::uno::Reference< css::beans::XPropertySet > xSet(
3013 GetFrame().GetFrameInterface(),
3014 css::uno::UNO_QUERY);
3015
3016 css::uno::Any aProp = xSet->getPropertyValue("DispatchRecorderSupplier");
3017 css::uno::Reference< css::frame::XDispatchRecorderSupplier > xSupplier;
3018 if ( aProp >>= xSupplier )
3019 rSet.Put( SfxBoolItem( nWhich, xSupplier.is() ) );
3020 else
3021 rSet.DisableItem( nWhich );
3022 break;
3023 }
3024
3025 case SID_STOP_RECORDING :
3026 {
3027 SvtMiscOptions aMiscOptions;
3028 const OUString& sName{GetObjectShell()->GetFactory().GetFactoryName()};
3029 if ( !aMiscOptions.IsMacroRecorderMode() ||
3030 ( sName!="swriter" && sName!="scalc" ) )
3031 {
3032 rSet.DisableItem( nWhich );
3033 break;
3034 }
3035
3036 css::uno::Reference< css::beans::XPropertySet > xSet(
3037 GetFrame().GetFrameInterface(),
3038 css::uno::UNO_QUERY);
3039
3040 css::uno::Any aProp = xSet->getPropertyValue("DispatchRecorderSupplier");
3041 css::uno::Reference< css::frame::XDispatchRecorderSupplier > xSupplier;
3042 if ( !(aProp >>= xSupplier) || !xSupplier.is() )
3043 rSet.DisableItem( nWhich );
3044 break;
3045 }
3046
3047 case SID_TOGGLESTATUSBAR:
3048 {
3049 css::uno::Reference< css::frame::XLayoutManager > xLayoutManager;
3050 css::uno::Reference< css::beans::XPropertySet > xSet(
3051 GetFrame().GetFrameInterface(),
3052 css::uno::UNO_QUERY);
3053 css::uno::Any aProp = xSet->getPropertyValue( "LayoutManager" );
3054
3055 if ( !( aProp >>= xLayoutManager ))
3056 rSet.Put( SfxBoolItem( nWhich, false ));
3057 else
3058 {
3059 bool bShow = xLayoutManager->isElementVisible( "private:resource/statusbar/statusbar" );
3060 rSet.Put( SfxBoolItem( nWhich, bShow ));
3061 }
3062 break;
3063 }
3064
3065 case SID_WIN_FULLSCREEN:
3066 {
3067 SfxViewFrame* pTop = GetTopViewFrame();
3068 if ( pTop )
3069 {
3070 WorkWindow* pWork = static_cast<WorkWindow*>( pTop->GetFrame().GetTopWindow_Impl() );
3071 if ( pWork )
3072 {
3073 rSet.Put( SfxBoolItem( nWhich, pWork->IsFullScreenMode() ) );
3074 break;
3075 }
3076 }
3077
3078 rSet.DisableItem( nWhich );
3079 break;
3080 }
3081
3082 default:
3083 break;
3084 }
3085 }
3086
3087 ++pRanges;
3088 }
3089 }
3090
3091 /* [Description]
3092
3093 This method can be included in the Execute method for the on- and off-
3094 switching of ChildWindows, to implement this and API-bindings.
3095
3096 Simply include as 'ExecuteMethod' in the IDL.
3097 */
ChildWindowExecute(SfxRequest & rReq)3098 void SfxViewFrame::ChildWindowExecute( SfxRequest &rReq )
3099 {
3100 // Evaluate Parameter
3101 sal_uInt16 nSID = rReq.GetSlot();
3102
3103 const SfxBoolItem* pShowItem = rReq.GetArg<SfxBoolItem>(nSID);
3104 if ( nSID == SID_VIEW_DATA_SOURCE_BROWSER )
3105 {
3106 if (!SvtModuleOptions().IsModuleInstalled(SvtModuleOptions::EModule::DATABASE))
3107 return;
3108 Reference < XFrame > xFrame = GetFrame().GetFrameInterface();
3109 Reference < XFrame > xBeamer( xFrame->findFrame( "_beamer", FrameSearchFlag::CHILDREN ) );
3110 bool bHasChild = xBeamer.is();
3111 bool bShow = pShowItem ? pShowItem->GetValue() : !bHasChild;
3112 if ( pShowItem )
3113 {
3114 if( bShow == bHasChild )
3115 return;
3116 }
3117 else
3118 rReq.AppendItem( SfxBoolItem( nSID, bShow ) );
3119
3120 if ( !bShow )
3121 {
3122 SetChildWindow( SID_BROWSER, false );
3123 }
3124 else
3125 {
3126 css::util::URL aTargetURL;
3127 aTargetURL.Complete = ".component:DB/DataSourceBrowser";
3128 Reference < css::util::XURLTransformer > xTrans(
3129 css::util::URLTransformer::create(
3130 ::comphelper::getProcessComponentContext() ) );
3131 xTrans->parseStrict( aTargetURL );
3132
3133 Reference < XDispatchProvider > xProv( xFrame, UNO_QUERY );
3134 Reference < css::frame::XDispatch > xDisp;
3135 if ( xProv.is() )
3136 xDisp = xProv->queryDispatch( aTargetURL, "_beamer", 31 );
3137 if ( xDisp.is() )
3138 {
3139 Sequence < css::beans::PropertyValue > aArgs(1);
3140 css::beans::PropertyValue* pArg = aArgs.getArray();
3141 pArg[0].Name = "Referer";
3142 pArg[0].Value <<= OUString("private:user");
3143 xDisp->dispatch( aTargetURL, aArgs );
3144 }
3145 }
3146
3147 rReq.Done();
3148 return;
3149 }
3150 if (nSID == SID_STYLE_DESIGNER)
3151 {
3152 // First make sure that the sidebar is visible
3153 ShowChildWindow(SID_SIDEBAR);
3154
3155 ::sfx2::sidebar::Sidebar::ShowPanel("StyleListPanel",
3156 GetFrame().GetFrameInterface(), true);
3157 rReq.Done();
3158 return;
3159 }
3160
3161 bool bHasChild = HasChildWindow(nSID);
3162 bool bShow = pShowItem ? pShowItem->GetValue() : !bHasChild;
3163 GetDispatcher()->Update_Impl( true );
3164
3165 // Perform action.
3166 if ( !pShowItem || bShow != bHasChild )
3167 ToggleChildWindow( nSID );
3168
3169 GetBindings().Invalidate( nSID );
3170
3171 // Record if possible.
3172 if ( nSID == SID_HYPERLINK_DIALOG || nSID == SID_SEARCH_DLG )
3173 {
3174 rReq.Ignore();
3175 }
3176 else
3177 {
3178 rReq.AppendItem( SfxBoolItem( nSID, bShow ) );
3179 rReq.Done();
3180 }
3181 }
3182
3183 /* [Description]
3184
3185 This method can be used in the state method for the on and off-state
3186 of child-windows, in order to implement this.
3187
3188 Just register the IDL as 'StateMethod'.
3189 */
ChildWindowState(SfxItemSet & rState)3190 void SfxViewFrame::ChildWindowState( SfxItemSet& rState )
3191 {
3192 SfxWhichIter aIter( rState );
3193 for ( sal_uInt16 nSID = aIter.FirstWhich(); nSID; nSID = aIter.NextWhich() )
3194 {
3195 if ( nSID == SID_VIEW_DATA_SOURCE_BROWSER )
3196 {
3197 rState.Put( SfxBoolItem( nSID, HasChildWindow( SID_BROWSER ) ) );
3198 }
3199 else if ( nSID == SID_HYPERLINK_DIALOG )
3200 {
3201 const SfxPoolItem* pDummy = nullptr;
3202 SfxItemState eState = GetDispatcher()->QueryState( SID_HYPERLINK_SETLINK, pDummy );
3203 if ( SfxItemState::DISABLED == eState )
3204 rState.DisableItem(nSID);
3205 else
3206 {
3207 if ( KnowsChildWindow(nSID) )
3208 rState.Put( SfxBoolItem( nSID, HasChildWindow(nSID)) );
3209 else
3210 rState.DisableItem(nSID);
3211 }
3212 }
3213 else if ( nSID == SID_BROWSER )
3214 {
3215 Reference < XFrame > xFrame = GetFrame().GetFrameInterface()->
3216 findFrame( "_beamer", FrameSearchFlag::CHILDREN );
3217 if ( !xFrame.is() )
3218 rState.DisableItem( nSID );
3219 else if ( KnowsChildWindow(nSID) )
3220 rState.Put( SfxBoolItem( nSID, HasChildWindow(nSID) ) );
3221 }
3222 else if ( nSID == SID_SIDEBAR )
3223 {
3224 if ( !KnowsChildWindow( nSID ) )
3225 {
3226 SAL_WARN("sfx.view", "SID_SIDEBAR state requested, but no task pane child window exists for this ID!");
3227 rState.DisableItem( nSID );
3228 }
3229 else
3230 {
3231 rState.Put( SfxBoolItem( nSID, HasChildWindow( nSID ) ) );
3232 }
3233 }
3234 else if ( KnowsChildWindow(nSID) )
3235 rState.Put( SfxBoolItem( nSID, HasChildWindow(nSID) ) );
3236 else
3237 rState.DisableItem(nSID);
3238 }
3239 }
3240
GetWorkWindow_Impl()3241 SfxWorkWindow* SfxViewFrame::GetWorkWindow_Impl()
3242 {
3243 SfxWorkWindow* pWork = GetFrame().GetWorkWindow_Impl();
3244 return pWork;
3245 }
3246
SetChildWindow(sal_uInt16 nId,bool bOn,bool bSetFocus)3247 void SfxViewFrame::SetChildWindow(sal_uInt16 nId, bool bOn, bool bSetFocus )
3248 {
3249 SfxWorkWindow* pWork = GetWorkWindow_Impl();
3250 if ( pWork )
3251 pWork->SetChildWindow_Impl( nId, bOn, bSetFocus );
3252 }
3253
ToggleChildWindow(sal_uInt16 nId)3254 void SfxViewFrame::ToggleChildWindow(sal_uInt16 nId)
3255 {
3256 SfxWorkWindow* pWork = GetWorkWindow_Impl();
3257 if ( pWork )
3258 pWork->ToggleChildWindow_Impl( nId, true );
3259 }
3260
HasChildWindow(sal_uInt16 nId)3261 bool SfxViewFrame::HasChildWindow( sal_uInt16 nId )
3262 {
3263 SfxWorkWindow* pWork = GetWorkWindow_Impl();
3264 return pWork && pWork->HasChildWindow_Impl(nId);
3265 }
3266
KnowsChildWindow(sal_uInt16 nId)3267 bool SfxViewFrame::KnowsChildWindow( sal_uInt16 nId )
3268 {
3269 SfxWorkWindow* pWork = GetWorkWindow_Impl();
3270 return pWork && pWork->KnowsChildWindow_Impl(nId);
3271 }
3272
ShowChildWindow(sal_uInt16 nId,bool bVisible)3273 void SfxViewFrame::ShowChildWindow( sal_uInt16 nId, bool bVisible )
3274 {
3275 SfxWorkWindow* pWork = GetWorkWindow_Impl();
3276 if ( pWork )
3277 {
3278 GetDispatcher()->Update_Impl(true);
3279 pWork->ShowChildWindow_Impl(nId, bVisible, true );
3280 }
3281 }
3282
GetChildWindow(sal_uInt16 nId)3283 SfxChildWindow* SfxViewFrame::GetChildWindow(sal_uInt16 nId)
3284 {
3285 SfxWorkWindow* pWork = GetWorkWindow_Impl();
3286 return pWork ? pWork->GetChildWindow_Impl(nId) : nullptr;
3287 }
3288
UpdateDocument_Impl()3289 void SfxViewFrame::UpdateDocument_Impl()
3290 {
3291 SfxObjectShell* pDoc = GetObjectShell();
3292 if ( pDoc->IsLoadingFinished() )
3293 pDoc->CheckSecurityOnLoading_Impl();
3294
3295 // check if document depends on a template
3296 pDoc->UpdateFromTemplate_Impl();
3297 }
3298
SetViewFrame(SfxViewFrame * pFrame)3299 void SfxViewFrame::SetViewFrame( SfxViewFrame* pFrame )
3300 {
3301 SfxGetpApp()->SetViewFrame_Impl( pFrame );
3302 }
3303
AppendInfoBar(const OUString & sId,const OUString & sPrimaryMessage,const OUString & sSecondaryMessage,InfobarType aInfobarType,bool bShowCloseButton)3304 VclPtr<SfxInfoBarWindow> SfxViewFrame::AppendInfoBar(const OUString& sId,
3305 const OUString& sPrimaryMessage,
3306 const OUString& sSecondaryMessage,
3307 InfobarType aInfobarType, bool bShowCloseButton)
3308 {
3309 SfxChildWindow* pChild = GetChildWindow(SfxInfoBarContainerChild::GetChildWindowId());
3310 if (!pChild)
3311 return nullptr;
3312
3313 if (HasInfoBarWithID(sId))
3314 return nullptr;
3315
3316 SfxInfoBarContainerWindow* pInfoBarContainer = static_cast<SfxInfoBarContainerWindow*>(pChild->GetWindow());
3317 auto pInfoBar = pInfoBarContainer->appendInfoBar(sId, sPrimaryMessage, sSecondaryMessage,
3318 aInfobarType, WB_LEFT | WB_VCENTER, bShowCloseButton);
3319 ShowChildWindow(SfxInfoBarContainerChild::GetChildWindowId());
3320 return pInfoBar;
3321 }
3322
UpdateInfoBar(const OUString & sId,const OUString & sPrimaryMessage,const OUString & sSecondaryMessage,InfobarType eType)3323 void SfxViewFrame::UpdateInfoBar(const OUString& sId, const OUString& sPrimaryMessage,
3324 const OUString& sSecondaryMessage, InfobarType eType)
3325 {
3326 const sal_uInt16 nId = SfxInfoBarContainerChild::GetChildWindowId();
3327
3328 // Make sure the InfoBar container is visible
3329 if (!HasChildWindow(nId))
3330 ToggleChildWindow(nId);
3331
3332 SfxChildWindow* pChild = GetChildWindow(nId);
3333 if (pChild)
3334 {
3335 SfxInfoBarContainerWindow* pInfoBarContainer = static_cast<SfxInfoBarContainerWindow*>(pChild->GetWindow());
3336 auto pInfoBar = pInfoBarContainer->getInfoBar(sId);
3337
3338 if (pInfoBar)
3339 pInfoBar->Update(sPrimaryMessage, sSecondaryMessage, eType);
3340 }
3341 }
3342
RemoveInfoBar(const OUString & sId)3343 void SfxViewFrame::RemoveInfoBar( const OUString& sId )
3344 {
3345 const sal_uInt16 nId = SfxInfoBarContainerChild::GetChildWindowId();
3346
3347 // Make sure the InfoBar container is visible
3348 if (!HasChildWindow(nId))
3349 ToggleChildWindow(nId);
3350
3351 SfxChildWindow* pChild = GetChildWindow(nId);
3352 if (pChild)
3353 {
3354 SfxInfoBarContainerWindow* pInfoBarContainer = static_cast<SfxInfoBarContainerWindow*>(pChild->GetWindow());
3355 auto pInfoBar = pInfoBarContainer->getInfoBar(sId);
3356 pInfoBarContainer->removeInfoBar(pInfoBar);
3357 ShowChildWindow(nId);
3358 }
3359 }
3360
HasInfoBarWithID(const OUString & sId)3361 bool SfxViewFrame::HasInfoBarWithID( const OUString& sId )
3362 {
3363 const sal_uInt16 nId = SfxInfoBarContainerChild::GetChildWindowId();
3364
3365 SfxChildWindow* pChild = GetChildWindow(nId);
3366 if (pChild)
3367 {
3368 SfxInfoBarContainerWindow* pInfoBarContainer = static_cast<SfxInfoBarContainerWindow*>(pChild->GetWindow());
3369 return pInfoBarContainer->hasInfoBarWithID(sId);
3370 }
3371
3372 return false;
3373 }
3374
3375 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
3376