Coverage Report

Created: 2026-10-14 09:33

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