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