Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/LibreOffice/sfx2/source/view/   (Office von Apache Version 25.8.3.2©)  Datei vom 5.10.2025 mit Größe 140 kB image not shown  

Quelle  viewfrm.cxx   Sprache: C

 
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */


#include <config_feature_desktop.h>
#include <config_wasm_strip.h>

#include <o3tl/test_info.hxx>
#include <osl/file.hxx>
#include <sfx2/docfilt.hxx>
#include <sfx2/infobar.hxx>
#include <sfx2/sfxdlg.hxx>
#include <sfx2/sfxsids.hrc>
#include <sfx2/viewfrm.hxx>
#include <sfx2/classificationhelper.hxx>
#include <sfx2/notebookbar/SfxNotebookBar.hxx>
#include <sfx2/pageids.hxx>
#include <com/sun/star/document/MacroExecMode.hpp>
#include <com/sun/star/frame/Desktop.hpp>
#include <com/sun/star/frame/DispatchRecorder.hpp>
#include <com/sun/star/frame/DispatchRecorderSupplier.hpp>
#include <com/sun/star/frame/XLoadable.hpp>
#include <com/sun/star/frame/XLayoutManager.hpp>
#include <com/sun/star/frame/XComponentLoader.hpp>
#include <com/sun/star/task/PasswordContainer.hpp>
#include <com/sun/star/security/DocumentDigitalSignatures.hpp>
#include <officecfg/Office/Common.hxx>
#include <officecfg/Setup.hxx>
#include <toolkit/helper/vclunohelper.hxx>
#include <vcl/wrkwin.hxx>
#include <unotools/moduleoptions.hxx>
#include <svl/intitem.hxx>
#include <svl/visitem.hxx>
#include <svl/stritem.hxx>
#include <svl/eitem.hxx>
#include <svl/whiter.hxx>
#include <svl/undo.hxx>
#include <vcl/help.hxx>
#include <vcl/stdtext.hxx>
#include <vcl/weld.hxx>
#include <vcl/weldutils.hxx>
#if !ENABLE_WASM_STRIP_PINGUSER
#include <unotools/VersionConfig.hxx>
#endif
#include <unotools/securityoptions.hxx>
#include <svtools/miscopt.hxx>
#include <comphelper/diagnose_ex.hxx>
#include <com/sun/star/container/XIndexAccess.hpp>
#include <com/sun/star/frame/XFramesSupplier.hpp>
#include <com/sun/star/frame/FrameSearchFlag.hpp>
#include <com/sun/star/frame/XFrame.hpp>
#include <com/sun/star/awt/XWindow.hpp>
#include <com/sun/star/frame/XController.hpp>
#include <com/sun/star/util/URLTransformer.hpp>
#include <com/sun/star/util/XURLTransformer.hpp>
#include <com/sun/star/util/XCloseable.hpp>
#include <com/sun/star/frame/XDispatchRecorderSupplier.hpp>
#include <com/sun/star/document/UpdateDocMode.hpp>
#include <com/sun/star/beans/XPropertySet.hpp>
#include <com/sun/star/uri/UriReferenceFactory.hpp>
#include <com/sun/star/uri/XVndSunStarScriptUrl.hpp>
#include <com/sun/star/document/XViewDataSupplier.hpp>
#include <com/sun/star/container/XIndexContainer.hpp>
#include <com/sun/star/task/InteractionHandler.hpp>
#include <com/sun/star/drawing/XDrawView.hpp>
#include <com/sun/star/drawing/XDrawPagesSupplier.hpp>
#include <rtl/ustrbuf.hxx>
#include <sal/log.hxx>
#include <com/sun/star/frame/ModuleManager.hpp>

#include <unotools/ucbhelper.hxx>
#include <comphelper/lok.hxx>
#include <comphelper/processfactory.hxx>
#include <comphelper/namedvaluecollection.hxx>
#include <comphelper/docpasswordrequest.hxx>
#include <comphelper/docpasswordhelper.hxx>

#include <com/sun/star/uno/Reference.h>

#include <basic/basmgr.hxx>
#include <basic/sbmod.hxx>
#include <basic/sbmeth.hxx>
#include <svtools/strings.hrc>
#include <svtools/svtresid.hxx>
#include <framework/framelistanalyzer.hxx>

#include <optional>

#include <comphelper/sequenceashashmap.hxx>

#include <commandpopup/CommandPopup.hxx>

// Due to ViewFrame::Current
#include <appdata.hxx>
#include <sfx2/app.hxx>
#include <sfx2/objface.hxx>
#include <openflag.hxx>
#include <objshimp.hxx>
#include <sfx2/viewsh.hxx>
#include <sfx2/objsh.hxx>
#include <sfx2/bindings.hxx>
#include <sfx2/dispatch.hxx>
#include <sfx2/request.hxx>
#include <sfx2/docfac.hxx>
#include <sfx2/ipclient.hxx>
#include <sfx2/sfxresid.hxx>
#include <sfx2/viewfac.hxx>
#include <sfx2/event.hxx>
#include <sfx2/fcontnr.hxx>
#include <sfx2/docfile.hxx>
#include <sfx2/module.hxx>
#include <sfx2/sfxuno.hxx>
#include <sfx2/progress.hxx>
#include <sfx2/sidebar/Sidebar.hxx>
#include <workwin.hxx>
#include <sfx2/minfitem.hxx>
#include <sfx2/strings.hrc>
#include "impviewframe.hxx"
#include <vcl/commandinfoprovider.hxx>
#include <vcl/svapp.hxx>
#include <svl/cryptosign.hxx>

#define ShellClass_SfxViewFrame
#include <sfxslots.hxx>

using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::ucb;
using namespace ::com::sun::star::frame;
using namespace ::com::sun::star::lang;
using ::com::sun::star::awt::XWindow;
using ::com::sun::star::beans::PropertyValue;
using ::com::sun::star::document::XViewDataSupplier;
using ::com::sun::star::container::XIndexContainer;

constexpr OUString CHANGES_STR = u"private:resource/toolbar/changes"_ustr;

SFX_IMPL_SUPERCLASS_INTERFACE(SfxViewFrame,SfxShell)

void SfxViewFrame::InitInterface_Impl()
{
    GetStaticInterface()->RegisterChildWindow(SID_BROWSER);
    GetStaticInterface()->RegisterChildWindow(SID_RECORDING_FLOATWINDOW);
#if HAVE_FEATURE_DESKTOP
    GetStaticInterface()->RegisterObjectBar(SFX_OBJECTBAR_FULLSCREEN, SfxVisibilityFlags::FullScreen, ToolbarId::FullScreenToolbox);
    GetStaticInterface()->RegisterObjectBar(SFX_OBJECTBAR_APPLICATION, SfxVisibilityFlags::Standard, ToolbarId::EnvToolbox);
#endif
}

namespace {
/// Asks the user if editing a read-only document is really wanted.
class SfxEditDocumentDialog : public weld::MessageDialogController
{
public:
    SfxEditDocumentDialog(weld::Widget* pParent);
};

SfxEditDocumentDialog::SfxEditDocumentDialog(weld::Widget* pParent)
    : MessageDialogController(pParent, u"sfx/ui/editdocumentdialog.ui"_ustr,
            u"EditDocumentDialog"_ustr)
{
}

class SfxQueryOpenAsTemplate
{
private:
    std::unique_ptr<weld::MessageDialog> m_xQueryBox;
public:
    SfxQueryOpenAsTemplate(weld::Window* pParent, bool bAllowIgnoreLock, LockFileEntry&&nbsp;rLockData)
        : m_xQueryBox(Application::CreateMessageDialog(pParent, VclMessageType::Question,
                                                       VclButtonsType::NONE, u""_ustr))
    {
        m_xQueryBox->add_button(SfxResId(STR_QUERY_OPENASTEMPLATE_OPENCOPY_BTN), RET_YES);
        bAllowIgnoreLock
            = bAllowIgnoreLock && officecfg::Office::Common::Misc::AllowOverrideLocking::get();
        if (bAllowIgnoreLock)
            m_xQueryBox->add_button(SfxResId(STR_QUERY_OPENASTEMPLATE_OPEN_BTN), RET_IGNORE);
        m_xQueryBox->add_button(GetStandardText( StandardButtonType::Cancel ), RET_CANCEL);
        m_xQueryBox->set_primary_text(QueryString(bAllowIgnoreLock, rLockData));
        m_xQueryBox->set_default_response(RET_YES);
    }
    short run() { return m_xQueryBox->run(); }

private:
    static OUString QueryString(bool bAllowIgnoreLock, LockFileEntry& rLockData)
    {
        OUString sLockUserData;
        if (!rLockData[LockFileComponent::OOOUSERNAME].isEmpty())
            sLockUserData = rLockData[LockFileComponent::OOOUSERNAME];
        else
            sLockUserData = rLockData[LockFileComponent::SYSUSERNAME];

        if (!sLockUserData.isEmpty() && !rLockData[LockFileComponent::EDITTIME].isEmpty())
            sLockUserData += " ( " + rLockData[LockFileComponent::EDITTIME] + " )";

        if (!sLockUserData.isEmpty())
            sLockUserData = "\n\n" + sLockUserData + "\n";

        const bool bUseLockStr = bAllowIgnoreLock || !sLockUserData.isEmpty();

        OUString sMsg(
            SfxResId(bUseLockStr ? STR_QUERY_OPENASTEMPLATE_LOCKED : STR_QUERY_OPENASTEMPLATE));

        if (bAllowIgnoreLock)
            sMsg += "\n\n" + SfxResId(STR_QUERY_OPENASTEMPLATE_ALLOW_IGNORE);

        return sMsg.replaceFirst("%LOCKINFO", sLockUserData);
    }
};

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 )
{
    // TODO/LATER: In future the info should replace the direct hash completely
    bool bResult = ( !nPasswordHash && !aInfo.hasElements() );

    SAL_WARN_IF( !(pFilter && ( pFilter->GetFilterFlags() & SfxFilterFlags::PASSWORDTOMODIFY )), "sfx.view",
                       "PasswordToModify feature is active for a filter that does not support it!");

    if ( pFilter && xHandler.is() )
    {
        bool bCancel = false;
        bool bFirstTime = true;

        while ( !bResult && !bCancel )
        {
            bool bMSType = !pFilter->IsOwnFormat();

            ::rtl::Reference< ::comphelper::DocPasswordRequest > pPasswordRequest(
                 new ::comphelper::DocPasswordRequest(
                 bMSType ? ::comphelper::DocPasswordRequestType::MS : ::comphelper::DocPasswordRequestType::Standard,
                 bFirstTime ? css::task::PasswordRequestMode_PASSWORD_ENTER : css::task::PasswordRequestMode_PASSWORD_REENTER,
                 aPath,
                 true ) );

            xHandler->handle( pPasswordRequest );

            if ( pPasswordRequest->isPassword() )
            {
                if ( aInfo.hasElements() )
                {
                    bResult = ::comphelper::DocPasswordHelper::IsModifyPasswordCorrect( pPasswordRequest->getPasswordToModify(), aInfo );
                }
                else
                {
                    // the binary format
                    bResult = ( SfxMedium::CreatePasswordToModifyHash( pPasswordRequest->getPasswordToModify(), pFilter->GetServiceName()=="com.sun.star.text.TextDocument" ) == nPasswordHash );
                }
            }
            else
                bCancel = true;

            bFirstTime = false;
        }
    }

    return bResult;
}

bool physObjIsOlder(INetURLObject const & aMedObj, INetURLObject const & aPhysObj) {
    return ::utl::UCBContentHelper::IsYounger(aMedObj.GetMainURL( INetURLObject::DecodeMechanism::NONE),
                                           aPhysObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ) );
}
}

void SfxViewFrame::ExecReload_Impl( SfxRequest& rReq )
{
    SfxObjectShell* pSh = GetObjectShell();
    switch ( rReq.GetSlot() )
    {
        case SID_EDITDOC:
        case SID_READONLYDOC:
        {
            // Due to Double occupancy in toolboxes (with or without Ctrl),
            // it is also possible that the slot is enabled, but Ctrl-click
            // despite this is not!
            if( !pSh || !pSh->HasName() || !(pSh->Get_Impl()->nLoadedFlags & SfxLoadedFlags::MAINDOCUMENT ))
                break;

            if (pSh->isEditDocLocked())
                break;

            // Only change read-only UI and remove info bar when we succeed
            struct ReadOnlyUIGuard
            {
                SfxViewFrame* m_pFrame;
                SfxObjectShell* m_pSh;
                SfxMedium* m_pMed = nullptr;
                bool m_bSetRO;
                ReadOnlyUIGuard(SfxViewFrame* pFrame, SfxObjectShell* p_Sh)
                    : m_pFrame(pFrame), m_pSh(p_Sh), m_bSetRO(p_Sh->IsReadOnlyUI())
                {}
                ~ReadOnlyUIGuard() COVERITY_NOEXCEPT_FALSE
                {
                    if (m_bSetRO != m_pSh->IsReadOnlyUI())
                    {
                        m_pSh->SetReadOnlyUI(m_bSetRO);
                        if (!m_bSetRO)
                            m_pFrame->RemoveInfoBar(u"readonly");
                        if (m_pMed)
                        {
                            bool const isEnableSetModified(m_pSh->IsEnableSetModified());
                            m_pSh->EnableSetModified(false);
                            // tdf#116066: DoSaveCompleted should be called after SetReadOnlyUI
                            m_pSh->DoSaveCompleted(m_pMed);
                            m_pSh->Broadcast(SfxHint(SfxHintId::ModeChanged));
                            m_pSh->EnableSetModified(isEnableSetModified);
                        }
                    }
                }
            } aReadOnlyUIGuard(this, pSh);

            SfxMedium* pMed = pSh->GetMedium();

            std::shared_ptr<std::recursive_mutex> pChkEditMutex = pMed->GetCheckEditableMutex();
            std::unique_lock<std::recursive_mutex> chkEditLock;
            if (pChkEditMutex != nullptr)
                chkEditLock = std::unique_lock<std::recursive_mutex>(*pChkEditMutex);
            pMed->CancelCheckEditableEntry();

            const SfxBoolItem* pItem = pMed->GetItemSet().GetItem(SID_VIEWONLY, false);
            if ( pItem && pItem->GetValue() )
            {
                SfxApplication* pApp = SfxGetpApp();
                SfxAllItemSet aSet( pApp->GetPool() );
                aSet.Put( SfxStringItem( SID_FILE_NAME, pMed->GetURLObject().GetMainURL(INetURLObject::DecodeMechanism::NONE) ) );
                aSet.Put( SfxBoolItem( SID_TEMPLATE, true ) );
                aSet.Put( SfxStringItem( SID_TARGETNAME, u"_blank"_ustr ) );
                const SfxStringItem* pReferer = pMed->GetItemSet().GetItem(SID_REFERER, false);
                if ( pReferer )
                    aSet.Put( *pReferer );
                const SfxInt16Item* pVersionItem = pMed->GetItemSet().GetItem(SID_VERSION, false);
                if ( pVersionItem )
                    aSet.Put( *pVersionItem );

                if( pMed->GetFilter() )
                {
                    aSet.Put( SfxStringItem( SID_FILTER_NAME, pMed->GetFilter()->GetFilterName() ) );
                    const SfxStringItem* pOptions = pMed->GetItemSet().GetItem(SID_FILE_FILTEROPTIONS, false);
                    if ( pOptions )
                        aSet.Put( *pOptions );
                }

                GetDispatcher()->Execute( SID_OPENDOC, SfxCallMode::ASYNCHRON, aSet );
                return;
            }

            StreamMode nOpenMode;
            bool bNeedsReload = false;
            bool bPasswordEntered = false;
            if ( !pSh->IsReadOnly() )
            {
                // Save and reload Readonly
                if( pSh->IsModified() )
                {
                    if ( pSh->PrepareClose() )
                    {
                        // the storing could let the medium be changed
                        pMed = pSh->GetMedium();
                        bNeedsReload = true;
                    }
                    else
                    {
                        rReq.SetReturnValue( SfxBoolItem( rReq.GetSlot(), false ) );
                        return;
                    }
                }
                nOpenMode = SFX_STREAM_READONLY;
                aReadOnlyUIGuard.m_bSetRO = true;
            }
            else
            {
                if ( pSh->IsReadOnlyMedium()
                  && ( pSh->GetModifyPasswordHash() || pSh->GetModifyPasswordInfo().hasElements() )
                  && !pSh->IsModifyPasswordEntered() )
                {
                    const OUString aDocumentName = INetURLObject( pMed->GetOrigURL() ).GetMainURL( INetURLObject::DecodeMechanism::WithCharset );
                    if( !AskPasswordToModify_Impl( pMed->GetInteractionHandler(), aDocumentName, pMed->GetFilter(), pSh->GetModifyPasswordHash(), pSh->GetModifyPasswordInfo() ) )
                    {
                        // this is a read-only document, if it has "Password to modify"
                        // the user should enter password before he can edit the document
                        rReq.SetReturnValue( SfxBoolItem( rReq.GetSlot(), false ) );
                        return;
                    }

                    pSh->SetModifyPasswordEntered();
                    bPasswordEntered = true;
                }

                nOpenMode = pSh->IsOriginallyReadOnlyMedium() ? SFX_STREAM_READONLY : SFX_STREAM_READWRITE;
                aReadOnlyUIGuard.m_bSetRO = false;

                // if only the view was in the readonly mode then there is no need to do the reload
                if ( !pSh->IsReadOnlyMedium() )
                {
                    // SetReadOnlyUI causes recomputation of window title, using
                    // open mode among other things, so call SetOpenMode before
                    // SetReadOnlyUI:
                    pMed->SetOpenMode( nOpenMode );
                    return;
                }
            }

            if ( rReq.IsAPI() )
            {
                // Control through API if r/w or r/o
                const SfxBoolItem* pEditItem = rReq.GetArg<SfxBoolItem>(SID_EDITDOC);
                if ( pEditItem )
                    nOpenMode = pEditItem->GetValue() ? SFX_STREAM_READWRITE : SFX_STREAM_READONLY;
            }

            // doing

            OUString sTemp;
            osl::FileBase::getFileURLFromSystemPath( pMed->GetPhysicalName(), sTemp );
            INetURLObject aPhysObj( sTemp );
            const SfxInt16Item* pVersionItem = pMed->GetItemSet().GetItem(SID_VERSION, false);

            INetURLObject aMedObj( pMed->GetName() );

            // -> tdf#82744
            // the logic below is following:
            // if the document seems not to need to be reloaded
            //     and the physical name is different to the logical one,
            // then on file system it can be checked that the copy is still newer than the original and no document reload is required.
            // Did some semplification to enhance readability of the 'if' expression
            //
            // when the 'http/https' protocol is active, the bool bPhysObjIsYounger relies upon the getlastmodified Property of a WebDAV resource.
            // Said property should be implemented, but sometimes it's not.
            // implemented. On this case the reload activated here will not work properly.
            // TODO: change the check age method for WebDAV to etag (entity-tag) property value, need some rethinking, since the
            // etag tells that the cache representation (e.g. in LO) is different from the one on the server,
            // but tells nothing about the age
            // Details at this link: http://tools.ietf.org/html/rfc4918#section-15, section 15.7
            bool bIsWebDAV = aMedObj.isAnyKnownWebDAVScheme();

            // tdf#118938 Reload the document when the user enters the editing password,
            //            even if the physical name isn't different to the logical name.
            if ( ( !bNeedsReload && ( ( aMedObj.GetProtocol() == INetProtocol::File &&
                                        ( aMedObj.getFSysPath( FSysStyle::Detect ) != aPhysObj.getFSysPath( FSysStyle::Detect )
                                          || bPasswordEntered ) &&
                                        !physObjIsOlder(aMedObj, aPhysObj))
                                      || (bIsWebDAV && !physObjIsOlder(aMedObj, aPhysObj))
                                      || ( pMed->IsRemote() && !bIsWebDAV ) ) )
                 || pVersionItem )
            // <- tdf#82744
            {
                bool bOK = false;
                bool bRetryIgnoringLock = false;
                bool bOpenTemplate = false;
                std::optional<bool> aOrigROVal;
                if (!pVersionItem)
                {
                    auto pRO = pMed->GetItemSet().GetItem<SfxBoolItem>(SID_DOC_READONLY, false);
                    if (pRO)
                        aOrigROVal = pRO->GetValue();
                }
                do {
                    LockFileEntry aLockData;
                    if ( !pVersionItem )
                    {
                        if (bRetryIgnoringLock)
                            pMed->ResetError();

                        bool bHasStorage = pMed->HasStorage_Impl();
                        // switching edit mode could be possible without reload
                        if ( bHasStorage && pMed->GetStorage() == pSh->GetStorage() )
                        {
                            // TODO/LATER: faster creation of copy
                            if ( !pSh->ConnectTmpStorage_Impl( pMed->GetStorage(), pMed ) )
                                return;
                        }

                        pMed->CloseAndRelease();
                        pMed->SetOpenMode( nOpenMode );
                        // We need to clear the SID_DOC_READONLY item from the set, to allow
                        // MediaDescriptor::impl_openStreamWithURL (called indirectly by
                        // SfxMedium::CompleteReOpen) to properly fill input stream of the
                        // descriptor, even when the file can't be open in read-write mode.
                        // Only then can following call to SfxMedium::LockOrigFileOnDemand
                        // return proper information about who has locked the file, to show
                        // in the SfxQueryOpenAsTemplate box below; otherwise it exits right
                        // after call to SfxMedium::GetMedium_Impl. This mimics what happens
                        // when the file is opened initially, when filter detection code also
                        // calls MediaDescriptor::impl_openStreamWithURL without the item set.
                        pMed->GetItemSet().ClearItem(SID_DOC_READONLY);
                        pMed->CompleteReOpen();
                        pMed->GetItemSet().Put(
                            SfxBoolItem(SID_DOC_READONLY, !(nOpenMode & StreamMode::WRITE)));
                        if ( nOpenMode & StreamMode::WRITE )
                        {
                            auto eResult = pMed->LockOrigFileOnDemand(
                                truetrue, bRetryIgnoringLock, &aLockData);
                            bRetryIgnoringLock
                                = eResult == SfxMedium::LockFileResult::FailedLockFile;
                        }

                        // LockOrigFileOnDemand might set the readonly flag itself, it should be set back
                        pMed->GetItemSet().Put( SfxBoolItem( SID_DOC_READONLY, !( nOpenMode & StreamMode::WRITE ) ) );

                        if ( !pMed->GetErrorCode() )
                            bOK = true;
                    }

                    if( !bOK )
                    {
                        if (nOpenMode == SFX_STREAM_READWRITE && !rReq.IsAPI())
                        {
                            // css::sdbcx::User offering to open it as a template
                            SfxQueryOpenAsTemplate aBox(GetWindow().GetFrameWeld(),
                                                        bRetryIgnoringLock, aLockData);

                            short nUserAnswer = aBox.run();
                            bOpenTemplate = RET_YES == nUserAnswer;
                            // Always reset this here to avoid infinite loop
                            bRetryIgnoringLock = RET_IGNORE == nUserAnswer;
                            if (RET_CANCEL == nUserAnswer)
                                pMed->AddToCheckEditableWorkerList();
                        }
                        else
                            bRetryIgnoringLock = false;
                    }
                }
                while ( !bOK && bRetryIgnoringLock );

                if( !bOK )
                {
                    ErrCodeMsg nErr = pMed->GetErrorCode();
                    if ( pVersionItem )
                        nErr = ERRCODE_IO_ACCESSDENIED;
                    else
                    {
                        pMed->ResetError();
                        pMed->SetOpenMode( SFX_STREAM_READONLY );
                        if (aOrigROVal)
                            pMed->GetItemSet().Put(SfxBoolItem(SID_DOC_READONLY, *aOrigROVal));
                        else
                            pMed->GetItemSet().ClearItem(SID_DOC_READONLY);
                        pMed->ReOpen();
                        pSh->DoSaveCompleted( pMed );
                    }

                    // Readonly document can not be switched to edit mode?
                    rReq.Done();

                    if ( nOpenMode == SFX_STREAM_READWRITE && !rReq.IsAPI() )
                    {
                        if ( bOpenTemplate )
                        {
                            SfxApplication* pApp = SfxGetpApp();
                            SfxAllItemSet aSet( pApp->GetPool() );
                            aSet.Put( SfxStringItem( SID_FILE_NAME, pMed->GetName() ) );
                            const SfxStringItem* pReferer = pMed->GetItemSet().GetItem(SID_REFERER, false);
                            if ( pReferer )
                                aSet.Put( *pReferer );
                            aSet.Put( SfxBoolItem( SID_TEMPLATE, true ) );
                            if ( pVersionItem )
                                aSet.Put( *pVersionItem );

                            if( pMed->GetFilter() )
                            {
                                aSet.Put( SfxStringItem( SID_FILTER_NAME, pMed->GetFilter()->GetFilterName() ) );
                                const SfxStringItem* pOptions = pMed->GetItemSet().GetItem(SID_FILE_FILTEROPTIONS, false);
                                if ( pOptions )
                                    aSet.Put( *pOptions );
                            }

                            GetDispatcher()->Execute( SID_OPENDOC, SfxCallMode::ASYNCHRON, aSet );
                            return;
                        }

                        nErr = ERRCODE_NONE;
                    }

                    // Keep the read-only UI
                    aReadOnlyUIGuard.m_bSetRO = true;

                    ErrorHandler::HandleError( nErr );
                    rReq.SetReturnValue(
                        SfxBoolItem( rReq.GetSlot(), false ) );
                    return;
                }
                else
                {
                    aReadOnlyUIGuard.m_pMed = pMed;
                    rReq.SetReturnValue( SfxBoolItem( rReq.GetSlot(), true ) );
                    rReq.Done( true );
                    return;
                }
            }

            rReq.AppendItem( SfxBoolItem(SID_FORCERELOAD,
                    (rReq.GetSlot() == SID_EDITDOC
                     // tdf#151715 exclude files loaded from /tmp to avoid Notebookbar bugs
                     && (!pSh->IsOriginallyReadOnlyMedium() || pSh->IsOriginallyLoadedReadOnlyMedium()))
                    || bNeedsReload) );
            rReq.AppendItem( SfxBoolItem( SID_SILENT, true ));

            [[fallthrough]]; //TODO ???
        }

        case SID_RELOAD:
        {
            // Due to Double occupancy in toolboxes (with or without Ctrl),
            // it is also possible that the slot is enabled, but Ctrl-click
            // despite this is not!
            if ( !pSh || !pSh->CanReload_Impl() )
                break;
            SfxApplication* pApp = SfxGetpApp();
            const SfxBoolItem* pForceReloadItem = rReq.GetArg<SfxBoolItem>(SID_FORCERELOAD);
            if(  pForceReloadItem && !pForceReloadItem->GetValue() &&
                !pSh->GetMedium()->IsExpired() )
                return;
            if( m_pImpl->bReloading || pSh->IsInModalMode() )
                return;

            // AutoLoad is prohibited if possible
            const SfxBoolItem* pAutoLoadItem = rReq.GetArg<SfxBoolItem>(SID_AUTOLOAD);
            if ( pAutoLoadItem && pAutoLoadItem->GetValue() &&
                 GetFrame().IsAutoLoadLocked_Impl() )
                return;

            SfxObjectShellLock xOldObj( pSh );
            m_pImpl->bReloading = true;
            const SfxStringItem* pURLItem = rReq.GetArg<SfxStringItem>(SID_FILE_NAME);
            // Open as editable?
            bool bForEdit = !pSh->IsReadOnly();

            // If possible ask the User
            bool bDo = GetViewShell()->PrepareClose();
            const SfxBoolItem* pSilentItem = rReq.GetArg<SfxBoolItem>(SID_SILENT);
            if (getenv("SAL_NO_QUERYSAVE"))
                bDo = true;
            else if (bDo && GetFrame().DocIsModified_Impl() && !rReq.IsAPI()
                     && (!pSilentItem || !pSilentItem->GetValue()))
            {
                std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(
                    GetWindow().GetFrameWeld(), VclMessageType::Question, VclButtonsType::YesNo,
                    SfxResId(STR_QUERY_LASTVERSION)));
                bDo = RET_YES == xBox->run();
            }

            if ( bDo )
            {
                SfxMedium *pMedium = xOldObj->GetMedium();
                std::shared_ptr<std::recursive_mutex> pChkEditMutex
                    = pMedium->GetCheckEditableMutex();
                std::unique_lock<std::recursive_mutex> chkEditLock;
                if (pChkEditMutex != nullptr)
                    chkEditLock = std::unique_lock<std::recursive_mutex>(*pChkEditMutex);
                pMedium->CancelCheckEditableEntry();

                bool bHandsOff =
                    ( pMedium->GetURLObject().GetProtocol() == INetProtocol::File && !xOldObj->IsDocShared() );

                // Empty existing SfxMDIFrames for this Document
                // in native format or R/O, open it now for editing?
                SfxObjectShellLock xNewObj;

                // collect the views of the document
                // TODO: when UNO ViewFactories are available for SFX-based documents, the below code should
                // be UNOized, too
                typedef ::std::pair< Reference< XFrame >, SfxInterfaceId >  ViewDescriptor;
                ::std::vector< ViewDescriptor > aViewFrames;
                SfxViewFrame *pView = GetFirst( xOldObj );
                while ( pView )
                {
                    Reference< XFrame > xFrame( pView->GetFrame().GetFrameInterface() );
                    SAL_WARN_IF( !xFrame.is(), "sfx.view""SfxViewFrame::ExecReload_Impl: no XFrame?!");
                    aViewFrames.emplace_back( xFrame, pView->GetCurViewId() );

                    pView = GetNext( *pView, xOldObj );
                }

                xOldObj->Get_Impl()->pReloadTimer.reset();

                std::optional<SfxAllItemSet> pNewSet;
                std::shared_ptr<const SfxFilter> pFilter = pMedium->GetFilter();
                if( pURLItem )
                {
                    pNewSet.emplace( pApp->GetPool() );
                    pNewSet->Put( *pURLItem );

                    // Filter Detection
                    OUString referer;
                    const SfxStringItem* refererItem = rReq.GetArg<SfxStringItem>(SID_REFERER);
                    if (refererItem != nullptr) {
                        referer = refererItem->GetValue();
                    }
                    SfxMedium aMedium( pURLItem->GetValue(), referer, SFX_STREAM_READWRITE );
                    SfxFilterMatcher().GuessFilter( aMedium, pFilter );
                    if ( pFilter )
                        pNewSet->Put( SfxStringItem( SID_FILTER_NAME, pFilter->GetName() ) );
                    pNewSet->Put( aMedium.GetItemSet() );
                }
                else
                {
                    pNewSet.emplace( pMedium->GetItemSet() );
                    pNewSet->ClearItem( SID_VIEW_ID );
                    pNewSet->ClearItem( SID_STREAM );
                    pNewSet->ClearItem( SID_INPUTSTREAM );
                    pNewSet->Put( SfxStringItem( SID_FILTER_NAME, pMedium->GetFilter()->GetName() ) );

                    // let the current security settings be checked again
                    pNewSet->Put( SfxUInt16Item( SID_MACROEXECMODE, document::MacroExecMode::USE_CONFIG ) );

                    if ( pSh->IsOriginallyReadOnlyMedium()
                         || pSh->IsOriginallyLoadedReadOnlyMedium() )
                        // edit mode is switched or reload of readonly document
                        pNewSet->Put( SfxBoolItem( SID_DOC_READONLY, true ) );
                    else
                        // Reload of file opened for writing
                        pNewSet->ClearItem( SID_DOC_READONLY );
                }

                // If a salvaged file is present, do not enclose the OrigURL
                // again, since the Template is invalid after reload.
                const SfxStringItem* pSalvageItem = SfxItemSet::GetItem<SfxStringItem>(&*pNewSet, SID_DOC_SALVAGE, false);
                if( pSalvageItem )
                {
                    pNewSet->ClearItem( SID_DOC_SALVAGE );
                }

#if HAVE_FEATURE_MULTIUSER_ENVIRONMENT
                // TODO/LATER: Temporary solution, the SfxMedium must know the original URL as aLogicName
                //             SfxMedium::Transfer_Impl() will be forbidden then.
                if ( xOldObj->IsDocShared() )
                    pNewSet->Put( SfxStringItem( SID_FILE_NAME, xOldObj->GetSharedFileURL() ) );
#endif
                if ( pURLItem )
                    pNewSet->Put( SfxStringItem( SID_REFERER, pMedium->GetName() ) );
                else
                    pNewSet->Put( SfxStringItem( SID_REFERER, OUString() ) );

                xOldObj->CancelTransfers();


                if ( pSilentItem && pSilentItem->GetValue() )
                    pNewSet->Put( SfxBoolItem( SID_SILENT, true ) );

                const SfxUnoAnyItem* pInteractionItem = SfxItemSet::GetItem<SfxUnoAnyItem>(&*pNewSet, SID_INTERACTIONHANDLER, false);
                const SfxUInt16Item* pMacroExecItem = SfxItemSet::GetItem<SfxUInt16Item>(&*pNewSet, SID_MACROEXECMODE, false);
                const SfxUInt16Item* pDocTemplateItem = SfxItemSet::GetItem<SfxUInt16Item>(&*pNewSet, SID_UPDATEDOCMODE, false);

                if (!pInteractionItem)
                {
                    Reference < task::XInteractionHandler2 > xHdl = task::InteractionHandler::createWithParent( ::comphelper::getProcessComponentContext(), nullptr );
                    if (xHdl.is())
                        pNewSet->Put( SfxUnoAnyItem(SID_INTERACTIONHANDLER,css::uno::Any(xHdl)) );
                }

                if (!pMacroExecItem)
                    pNewSet->Put( SfxUInt16Item(SID_MACROEXECMODE,css::document::MacroExecMode::USE_CONFIG) );
                if (!pDocTemplateItem)
                    pNewSet->Put( SfxUInt16Item(SID_UPDATEDOCMODE,css::document::UpdateDocMode::ACCORDING_TO_CONFIG) );

                xOldObj->SetModified( false );
                // Do not cache the old Document! Is invalid when loading
                // another document.

                bool bHasStorage = pMedium->HasStorage_Impl();
                if( bHandsOff )
                {
                    if ( bHasStorage && pMedium->GetStorage() == xOldObj->GetStorage() )
                    {
                        // TODO/LATER: faster creation of copy
                        if ( !xOldObj->ConnectTmpStorage_Impl( pMedium->GetStorage(), pMedium ) )
                            return;
                    }

                    pMedium->CloseAndRelease();
                }

                xNewObj = SfxObjectShell::CreateObject( pFilter->GetServiceName() );

                if ( xOldObj->IsModifyPasswordEntered() )
                    xNewObj->SetModifyPasswordEntered();

                uno::Sequence < beans::PropertyValue > aLoadArgs;
                TransformItems( SID_OPENDOC, *pNewSet, aLoadArgs );
                try
                {
                    uno::Reference < frame::XLoadable > xLoad( xNewObj->GetModel(), uno::UNO_QUERY );
                    xLoad->load( aLoadArgs );
                }
                catch ( uno::Exception& )
                {
                    xNewObj->DoClose();
                    xNewObj = nullptr;
                    pMedium->AddToCheckEditableWorkerList();
                }

                pNewSet.reset();

                if( !xNewObj.Is() )
                {
                    if( bHandsOff )
                    {
                        // back to old medium
                        pMedium->ReOpen();
                        pMedium->LockOrigFileOnDemand( falsetrue );

                        xOldObj->DoSaveCompleted( pMedium );
                    }
                }
                else
                {
                    if ( xNewObj->GetModifyPasswordHash() && xNewObj->GetModifyPasswordHash() != xOldObj->GetModifyPasswordHash() )
                    {
                        xNewObj->SetModifyPasswordEntered( false );
                        xNewObj->SetReadOnly();
                    }
                    else if ( rReq.GetSlot() == SID_EDITDOC || rReq.GetSlot() == SID_READONLYDOC )
                    {
                        xNewObj->SetReadOnlyUI( !bForEdit );
                    }

#if HAVE_FEATURE_MULTIUSER_ENVIRONMENT
                    if ( xNewObj->IsDocShared() )
                    {
                        // the file is shared but the closing can change the sharing control file
                        xOldObj->DoNotCleanShareControlFile();
                    }
#endif
                    // the Reload and Silent items were only temporary, remove them
                    xNewObj->GetMedium()->GetItemSet().ClearItem( SID_RELOAD );
                    xNewObj->GetMedium()->GetItemSet().ClearItem( SID_SILENT );
                    TransformItems( SID_OPENDOC, xNewObj->GetMedium()->GetItemSet(), aLoadArgs );

                    UpdateDocument_Impl();

                    auto sModule = vcl::CommandInfoProvider::GetModuleIdentifier(GetFrame().GetFrameInterface());
                    OUString sReloadNotebookBar;
                    if (sModule == "com.sun.star.text.TextDocument")
                        sReloadNotebookBar = u"modules/swriter/ui/"_ustr;
                    else if (sModule == "com.sun.star.sheet.SpreadsheetDocument")
                        sReloadNotebookBar = u"modules/scalc/ui/"_ustr;
                    else if (sfx2::SfxNotebookBar::IsActive()
                             && sModule != "presentation.PresentationDocument"
                             && sModule != "com.sun.star.drawing.DrawingDocument")
                    {
                        assert(false && "SID_RELOAD Notebookbar active, but not refreshed here");
                    }

                    try
                    {
                        for (auto const& viewFrame : aViewFrames)
                        {
                            LoadViewIntoFrame_Impl( *xNewObj, viewFrame.first, aLoadArgs, viewFrame.second, false );
                        }
                        aViewFrames.clear();
                    }
                    catchconst Exception& )
                    {
                        // close the remaining frames
                        // Don't catch exceptions herein, if this fails, then we're left in an indetermined state, and
                        // crashing is better than trying to proceed
                        for (auto const& viewFrame : aViewFrames)
                        {
                            Reference< util::XCloseable > xClose( viewFrame.first, UNO_QUERY_THROW );
                            xClose->close( true );
                        }
                        aViewFrames.clear();
                    }

                    const SfxInt32Item* pPageNumber = rReq.GetArg<SfxInt32Item>(SID_PAGE_NUMBER);
                    if (pPageNumber && pPageNumber->GetValue() >= 0)
                    {
                        // Restore current page after reload.
                        uno::Reference<drawing::XDrawView> xController(
                            xNewObj->GetModel()->getCurrentController(), uno::UNO_QUERY);
                        uno::Reference<drawing::XDrawPagesSupplier> xSupplier(xNewObj->GetModel(),
                                                                              uno::UNO_QUERY);
                        uno::Reference<drawing::XDrawPages> xDrawPages = xSupplier->getDrawPages();
                        uno::Reference<drawing::XDrawPage> xDrawPage(
                            xDrawPages->getByIndex(pPageNumber->GetValue()), uno::UNO_QUERY);
                        xController->setCurrentPage(xDrawPage);
                    }

                    // Propagate document closure.
                    SfxGetpApp()->NotifyEvent( SfxEventHint( SfxEventHintId::CloseDoc, GlobalEventConfig::GetEventName( GlobalEventId::CLOSEDOC ), xOldObj ) );

                    // tdf#126006 Calc needs to reload the notebookbar after closing the document
                    if (!sReloadNotebookBar.isEmpty())
                        sfx2::SfxNotebookBar::ReloadNotebookBar(sReloadNotebookBar);
                }

                // Record as done
                rReq.Done( true );
                rReq.SetReturnValue(SfxBoolItem(rReq.GetSlot(), true));
                return;
            }
            else
            {
                // Record as not done
                rReq.Done();
                rReq.SetReturnValue(SfxBoolItem(rReq.GetSlot(), false));
                m_pImpl->bReloading = false;
                return;
            }
        }
    }
}

void SfxViewFrame::StateReload_Impl( SfxItemSet& rSet )
{
    SfxObjectShell* pSh = GetObjectShell();
    if ( !pSh )
    {
        // I'm just on reload and am yielding myself ...
        return;
    }

    SfxWhichIter aIter( rSet );
    for ( sal_uInt16 nWhich = aIter.FirstWhich(); nWhich; nWhich = aIter.NextWhich() )
    {
        switch ( nWhich )
        {
            case SID_EDITDOC:
            case SID_READONLYDOC:
            {
                const SfxViewShell *pVSh;
                const SfxShell *pFSh;
                if ( !pSh->HasName() ||
                     !( pSh->Get_Impl()->nLoadedFlags &  SfxLoadedFlags::MAINDOCUMENT ) ||
                     (pSh->isEditDocLocked()) ||
                     ( pSh->GetCreateMode() == SfxObjectCreateMode::EMBEDDED &&
                       ( !(pVSh = pSh->GetViewShell())  ||
                         !(pFSh = pVSh->GetFormShell()) ||
                         !pFSh->IsDesignMode())))
                    rSet.DisableItem( nWhich );
                else
                {
                    SfxMedium* pMedium = pSh->GetMedium();
                    const SfxBoolItem* pItem = pMedium ? pMedium->GetItemSet().GetItem(SID_EDITDOC, false) : nullptr;
                    if ( pItem && !pItem->GetValue() )
                        rSet.DisableItem( nWhich );
                    else
                    {
                        if (nWhich==SID_EDITDOC)
                            rSet.Put( SfxBoolItem( nWhich, !pSh->IsReadOnly() ) );
                        else if (nWhich==SID_READONLYDOC)
                            rSet.Put( SfxBoolItem( nWhich, pSh->IsReadOnly() ) );
                    }
                }
                break;
            }

            case SID_RELOAD:
            {
                if ( !pSh->CanReload_Impl() || pSh->GetCreateMode() == SfxObjectCreateMode::EMBEDDED )
                    rSet.DisableItem(nWhich);
                else
                {
                    // If any ChildFrame is reloadable, the slot is enabled,
                    // so you can perform CTRL-Reload
                    rSet.Put( SfxBoolItem( nWhich, false));
                }

                break;
            }
        }
    }
}

void SfxViewFrame::ExecHistory_Impl( SfxRequest &rReq )
{
    // Is there an Undo-Manager on the top Shell?
    SfxShell *pSh = GetDispatcher()->GetShell(0);
    if (!pSh)
        return;

    SfxUndoManager* pShUndoMgr = pSh->GetUndoManager();
    bool bOK = false;
    if ( pShUndoMgr )
    {
        switch ( rReq.GetSlot() )
        {
            case SID_CLEARHISTORY:
                pShUndoMgr->Clear();
                bOK = true;
                break;

            case SID_UNDO:
                pShUndoMgr->Undo();
                GetBindings().InvalidateAll(false);
                bOK = true;
                break;

            case SID_REDO:
                pShUndoMgr->Redo();
                GetBindings().InvalidateAll(false);
                bOK = true;
                break;

            case SID_REPEAT:
                if ( pSh->GetRepeatTarget() )
                    pShUndoMgr->Repeat( *pSh->GetRepeatTarget() );
                bOK = true;
                break;
        }
    }
    else if ( GetViewShell() )
    {
        // The SW has its own undo in the View
        const SfxPoolItemHolder& rResult(GetViewShell()->ExecuteSlot(rReq));
        if (rResult)
            bOK = static_cast<const SfxBoolItem*>(rResult.getItem())->GetValue();
    }

    rReq.SetReturnValue( SfxBoolItem( rReq.GetSlot(), bOK ) );
    rReq.Done();
}

void SfxViewFrame::StateHistory_Impl( SfxItemSet &rSet )
{
    // Search for Undo-Manager
    SfxShell *pSh = GetDispatcher()->GetShell(0);
    if ( !pSh )
        // I'm just on reload and am yielding myself ...
        return;

    SfxUndoManager *pShUndoMgr = pSh->GetUndoManager();
    if ( !pShUndoMgr )
    {
        // The SW has its own undo in the View
        SfxWhichIter aIter( rSet );
        SfxViewShell *pViewSh = GetViewShell();
        if( !pViewSh ) return;
        for ( sal_uInt16 nSID = aIter.FirstWhich(); nSID; nSID = aIter.NextWhich() )
            pViewSh->GetSlotState( nSID, nullptr, &rSet );
        return;
    }

    if ( pShUndoMgr->GetUndoActionCount() == 0 &&
         pShUndoMgr->GetRedoActionCount() == 0 &&
         pShUndoMgr->GetRepeatActionCount() == 0 )
        rSet.DisableItem( SID_CLEARHISTORY );

    if (pShUndoMgr->GetUndoActionCount())
    {
        const SfxUndoAction* pAction = pShUndoMgr->GetUndoAction();
        SfxViewShell *pViewSh = GetViewShell();
        if (pViewSh && pAction->GetViewShellId() != pViewSh->GetViewShellId())
        {
            rSet.Put(SfxUInt32Item(SID_UNDO, static_cast<sal_uInt32>(SID_REPAIRPACKAGE)));
        }
        else
        {
            rSet.Put( SfxStringItem( SID_UNDO, SvtResId(STR_UNDO)+pShUndoMgr->GetUndoActionComment() ) );
        }
    }
    else
        rSet.DisableItem( SID_UNDO );

    if (pShUndoMgr->GetRedoActionCount())
    {
        const SfxUndoAction* pAction = pShUndoMgr->GetRedoAction();
        SfxViewShell *pViewSh = GetViewShell();
        if (pViewSh && pAction->GetViewShellId() != pViewSh->GetViewShellId())
        {
            rSet.Put(SfxUInt32Item(SID_REDO, static_cast<sal_uInt32>(SID_REPAIRPACKAGE)));
        }
        else
        {
            rSet.Put(SfxStringItem(SID_REDO, SvtResId(STR_REDO) + pShUndoMgr->GetRedoActionComment()));
        }
    }
    else
        rSet.DisableItem( SID_REDO );

    SfxRepeatTarget *pTarget = pSh->GetRepeatTarget();
    if (pTarget && pShUndoMgr->GetRepeatActionCount() && pShUndoMgr->CanRepeat(*pTarget))
        rSet.Put( SfxStringItem( SID_REPEAT, SvtResId(STR_REPEAT)+pShUndoMgr->GetRepeatActionComment(*pTarget) ) );
    else
        rSet.DisableItem( SID_REPEAT );
}

void SfxViewFrame::PopShellAndSubShells_Impl( SfxViewShell& i_rViewShell )
{
    i_rViewShell.PopSubShells_Impl();
    sal_uInt16 nLevel = m_pDispatcher->GetShellLevel( i_rViewShell );
    if ( nLevel != USHRT_MAX )
    {
        if ( nLevel )
        {
            // more sub shells on the stack, which were not affected by PopSubShells_Impl
            if (SfxShell *pSubShell = m_pDispatcher->GetShell( nLevel-1 ))
                m_pDispatcher->Pop( *pSubShell, SfxDispatcherPopFlags::POP_UNTIL | SfxDispatcherPopFlags::POP_DELETE );
        }
        m_pDispatcher->Pop( i_rViewShell );
        m_pDispatcher->Flush();
    }

}

/*  [Description]

    This method empties the SfxViewFrame, i.e. takes the <SfxObjectShell>
    from the dispatcher and ends its <SfxListener> Relationship to this
    SfxObjectShell (by which they may even destroy themselves).

    Thus, by invoking ReleaseObjectShell() and  SetObjectShell() the
    SfxObjectShell can be replaced.

    Between ReleaseObjectShell() and SetObjectShell() the control cannot
    be handed over to the system.

    [Cross-reference]

    <SfxViewFrame::SetObjectShell(SfxObjectShell&)>
*/

void SfxViewFrame::ReleaseObjectShell_Impl()
{
    DBG_ASSERT( m_xObjSh.is(), "no SfxObjectShell to release!" );

    GetFrame().ReleasingComponent_Impl();
    if ( GetWindow().HasChildPathFocus( true ) )
    {
        GetWindow().GrabFocus();
    }

    SfxViewShell *pDyingViewSh = GetViewShell();
    if ( pDyingViewSh )
    {
        PopShellAndSubShells_Impl( *pDyingViewSh );
        pDyingViewSh->DisconnectAllClients();
        SetViewShell_Impl(nullptr);
        delete pDyingViewSh;
    }
#ifdef DBG_UTIL
    else
        OSL_FAIL("No Shell");
#endif

    if ( m_xObjSh.is() )
    {
        m_pDispatcher->Pop( *m_xObjSh );
        SfxModule* pModule = m_xObjSh->GetModule();
        if( pModule )
            m_pDispatcher->RemoveShell_Impl( *pModule );
        m_pDispatcher->Flush();
        EndListening( *m_xObjSh );

        Notify( *m_xObjSh, SfxHint(SfxHintId::TitleChanged) );
        Notify( *m_xObjSh, SfxHint(SfxHintId::DocChanged) );

        if ( 1 == m_xObjSh->GetOwnerLockCount() && m_pImpl->bObjLocked && m_xObjSh->GetCreateMode() == SfxObjectCreateMode::EMBEDDED )
            m_xObjSh->DoClose();
        SfxObjectShellRef xDyingObjSh = m_xObjSh;
        m_xObjSh.clear();
        if( GetFrame().GetHasTitle() && m_pImpl->nDocViewNo )
            xDyingObjSh->GetNoSet_Impl().ReleaseIndex(m_pImpl->nDocViewNo-1);
        if ( m_pImpl->bObjLocked )
        {
            xDyingObjSh->OwnerLock( false );
            m_pImpl->bObjLocked = false;
        }
    }

    GetDispatcher()->SetDisableFlags( SfxDisableFlags::NONE );
}

void SfxViewFrame::Close()
{

    DBG_ASSERT( GetFrame().IsClosing_Impl() || !GetFrame().GetFrameInterface().is(), "ViewFrame closed too early!" );

    // If no saving have been made up until now, then embedded Objects should
    // not be saved automatically anymore.
    if ( GetViewShell() )
        GetViewShell()->DisconnectAllClients();
    Broadcast( SfxHint( SfxHintId::Dying ) );

    if (SfxViewFrame::Current() == this)
        SfxViewFrame::SetViewFrame( nullptr );

    // Since the Dispatcher is emptied, it can not be used in any reasonable
    // manner, thus it is better to let the dispatcher be.
    GetDispatcher()->Lock(true);
    delete this;
}

void SfxViewFrame::DoActivate( bool bUI )
{
    m_pDispatcher->DoActivate_Impl( bUI );
}

void SfxViewFrame::DoDeactivate(bool bUI, SfxViewFrame const * pNewFrame )
{
    m_pDispatcher->DoDeactivate_Impl( bUI, pNewFrame );
}

void SfxViewFrame::InvalidateBorderImpl( const SfxViewShell* pSh )
{
    if( !pSh || m_nAdjustPosPixelLock )
        return;

    if ( GetViewShell() && GetWindow().IsVisible() )
    {
        if ( GetFrame().IsInPlace() )
        {
            return;
        }

        DoAdjustPosSizePixel( GetViewShell(), Point(),
                                        GetWindow().GetOutputSizePixel(),
                                        false );
    }
}

void SfxViewFrame::SetBorderPixelImpl
(
    const SfxViewShell* pVSh,
    const SvBorder&     rBorder
)

{
    m_pImpl->aBorder = rBorder;

    if ( m_pImpl->bResizeInToOut && !GetFrame().IsInPlace() )
    {
        Size aSize = pVSh->GetWindow()->GetOutputSizePixel();
        if ( aSize.Width() && aSize.Height() )
        {
            aSize.AdjustWidth(rBorder.Left() + rBorder.Right() );
            aSize.AdjustHeight(rBorder.Top() + rBorder.Bottom() );

            Size aOldSize = GetWindow().GetOutputSizePixel();
            GetWindow().SetOutputSizePixel( aSize );
            vcl::Window* pParent = &GetWindow();
            while ( pParent->GetParent() )
                pParent = pParent->GetParent();
            Size aOuterSize = pParent->GetOutputSizePixel();
            aOuterSize.AdjustWidth( aSize.Width() - aOldSize.Width() );
            aOuterSize.AdjustHeight( aSize.Height() - aOldSize.Height() );
            pParent->SetOutputSizePixel( aOuterSize );
        }
    }
    else
    {
        tools::Rectangle aEditArea( Point(), GetWindow().GetOutputSizePixel() );
        aEditArea.AdjustLeft(rBorder.Left() );
        aEditArea.AdjustRight( -(rBorder.Right()) );
        aEditArea.AdjustTop(rBorder.Top() );
        aEditArea.AdjustBottom( -(rBorder.Bottom()) );
        pVSh->GetWindow()->SetPosSizePixel( aEditArea.TopLeft(), aEditArea.GetSize() );
    }
}

const SvBorder& SfxViewFrame::GetBorderPixelImpl() const
{
    return m_pImpl->aBorder;
}

void SfxViewFrame::AppendReadOnlyInfobar()
{
    if (officecfg::Office::Common::Misc::ViewerAppMode::get())
        return;

    bool bSignPDF = m_xObjSh->IsSignPDF();
    bool bSignWithCert = false;
    if (bSignPDF)
    {
        SfxViewShell* pViewShell = GetViewShell();
        uno::Reference<security::XCertificate> xCertificate = pViewShell->GetSignPDFCertificate().m_xCertificate;
        bSignWithCert = xCertificate.is();
    }

    auto pInfoBar = AppendInfoBar(u"readonly"_ustr, u""_ustr,
                                  SfxResId(bSignPDF ? STR_READONLY_PDF : STR_READONLY_DOCUMENT),
                                  InfobarType::INFO);
    if (!pInfoBar)
        return;

    if (bSignPDF)
    {
        // SID_SIGNPDF opened a read-write PDF
        // read-only for signing purposes.
        weld::Button& rSignButton = pInfoBar->addButton();
        if (bSignWithCert)
        {
            rSignButton.set_label(SfxResId(STR_READONLY_FINISH_SIGN));
        }
        else
        {
            rSignButton.set_label(SfxResId(STR_READONLY_SIGN));
        }

        rSignButton.connect_clicked(LINK(this, SfxViewFrame, SignDocumentHandler));
    }

    bool showEditDocumentButton = true;
    if (m_xObjSh->isEditDocLocked())
        showEditDocumentButton = false;

    if (showEditDocumentButton)
    {
        weld::Button& rBtn = pInfoBar->addButton();
        rBtn.set_label(SfxResId(STR_READONLY_EDIT));
        rBtn.connect_clicked(LINK(this, SfxViewFrame, SwitchReadOnlyHandler));
    }
}

void SfxViewFrame::HandleSecurityInfobar(const OUString& sSecondaryMessage)
{
    if (!HasInfoBarWithID(u"securitywarn"))
    {
        // new info bar
        if (!sSecondaryMessage.isEmpty())
        {
            auto pInfoBar = AppendInfoBar(u"securitywarn"_ustr, SfxResId(STR_HIDDENINFO_CONTAINS).replaceAll("\n\n"" "),
                sSecondaryMessage, InfobarType::WARNING);
            if (!pInfoBar)
                return;

            weld::Button& rGetInvolvedButton = pInfoBar->addButton();
            rGetInvolvedButton.set_label(SfxResId(STR_SECURITY_OPTIONS));
            rGetInvolvedButton.connect_clicked(LINK(this, SfxViewFrame, SecurityButtonHandler));
        }
    }
    else
    {
        // info bar exists already
        if (sSecondaryMessage.isEmpty())
        {
            RemoveInfoBar(u"securitywarn");
        }
        else
        {
            UpdateInfoBar(u"securitywarn", SfxResId(STR_HIDDENINFO_CONTAINS).replaceAll("\n\n"" "),
                sSecondaryMessage, InfobarType::WARNING);
        }
    }
}

void SfxViewFrame::AppendContainsMacrosInfobar()
{
    if (officecfg::Office::Common::Misc::ViewerAppMode::get())
        return;

    SfxObjectShell_Impl* pObjImpl = m_xObjSh->Get_Impl();

    auto aResId = STR_CONTAINS_MACROS;
    if (SvtSecurityOptions::IsMacroDisabled())
        aResId = STR_MACROS_DISABLED;
    else if (pObjImpl->aMacroMode.hasUnsignedContentError())
        aResId = STR_MACROS_DISABLED_CONTENT_UNSIGNED;
    else if(pObjImpl->aMacroMode.hasInvalidSignaturesError())
        aResId = STR_MACROS_DISABLED_SIGNATURE_INVALID;
    // The idea here is to always present an infobar is there was some
    // macro/script related potential hazard disabled in the source document
    auto pInfoBar = AppendInfoBar(u"macro"_ustr, SfxResId(STR_MACROS_DISABLED_TITLE),
                                  SfxResId(aResId), InfobarType::WARNING);
    if (!pInfoBar)
        return;

    // Then show buttons to help navigate to whatever that hazard is.  Whether
    // that is included macros, so the user could delete them.  Or events bound
    // to scripts which could be cleared.  But there are likely other cases not
    // captured here, which could be added, various blocked features where its
    // likely still worth displaying the infobar that they have been disabled,
    // even if we don't currently provide a way to indicate what exactly those
    // are and how to remove them.

    // No access to macro dialog when macros are disabled globally, so return
    // early without adding buttons to help explore what the macros/script/events
    // might be.
    if (SvtSecurityOptions::IsMacroDisabled())
        return;

    // what's the difference between pObjImpl->documentStorageHasMacros() and pObjImpl->aMacroMode.hasMacroLibrary() ?
    bool bHasDocumentMacros = pObjImpl->aMacroMode.hasMacroLibrary();

    Reference<XModel> xModel = m_xObjSh->GetModel();
    uno::Reference<document::XEventsSupplier> xSupplier(xModel, uno::UNO_QUERY);
    bool bHasBoundConfigEvents(false);
    if (xSupplier.is())
    {
        css::uno::Reference<css::container::XNameReplace> xDocumentEvents = xSupplier->getEvents();

        Sequence<OUString> eventNames = xDocumentEvents->getElementNames();
        sal_Int32 nEventCount = eventNames.getLength();
        for (sal_Int32 nEvent = 0; nEvent < nEventCount; ++nEvent)
        {
            OUString url;
            try
            {
                Any aAny(xDocumentEvents->getByName(eventNames[nEvent]));
                Sequence<beans::PropertyValue> props;
                if (aAny >>= props)
                {
                    ::comphelper::NamedValueCollection aProps(props);
                    url = aProps.getOrDefault(u"Script"_ustr, url);
                }
            }
            catch (const Exception&)
            {
            }
            if (!url.isEmpty())
            {
                bHasBoundConfigEvents = true;
                break;
            }
        }
    }

    if (bHasDocumentMacros)
    {
        weld::Button& rMacroButton = pInfoBar->addButton();
        rMacroButton.set_label(SfxResId(STR_MACROS));
        rMacroButton.connect_clicked(LINK(this, SfxViewFrame, MacroButtonHandler));
    }

    if (bHasBoundConfigEvents)
    {
        weld::Button& rEventButton = pInfoBar->addButton();
        rEventButton.set_label(SfxResId(STR_EVENTS));
        rEventButton.connect_clicked(LINK(this, SfxViewFrame, EventButtonHandler));
    }

    if (pObjImpl->aMacroMode.hasInvalidSignaturesError())
    {
        weld::Button& rSignaturesButton = pInfoBar->addButton();
        rSignaturesButton.set_label(SfxResId(STR_SIGNATURE_SHOW));
        rSignaturesButton.connect_clicked(LINK(this, SfxViewFrame, ViewSignaturesButtonHandler));
    }
}

namespace
{
css::uno::Reference<css::frame::XLayoutManager> getLayoutManager(const SfxFrame& rFrame)
{
    css::uno::Reference<css::frame::XLayoutManager> xLayoutManager;
    css::uno::Reference<css::beans::XPropertySet> xPropSet(rFrame.GetFrameInterface(),
                                                 uno::UNO_QUERY);
    if (xPropSet.is())
    {
        try
        {
            xLayoutManager.set(xPropSet->getPropertyValue(u"LayoutManager"_ustr), uno::UNO_QUERY);
        }
        catch (const Exception& e)
        {
            SAL_WARN("sfx.view""Failure getting layout manager: " + e.Message);
        }
    }
    return xLayoutManager;
}
}

bool SfxApplication::IsHeadlessOrUITest()
{
    if (Application::IsHeadlessModeEnabled())
        return true;

    bool bRet = o3tl::IsRunningUITest(); //uitest.uicheck fails when the dialog is open
    for (sal_uInt16 i = 0, nCount = Application::GetCommandLineParamCount(); i < nCount; ++i)
    {
        if (Application::GetCommandLineParam(i) == "--nologo")
        {
            bRet = true;
            break;
        }
    }
    return bRet;
}

bool SfxApplication::IsTipOfTheDayDue()
{
    const bool bShowTipOfTheDay = officecfg::Office::Common::Misc::ShowTipOfTheDay::get();
    if (!bShowTipOfTheDay)
        return false;

    const auto t0 = std::chrono::system_clock::now().time_since_epoch();

    // show tip-of-the-day dialog ?
    const sal_Int32 nLastTipOfTheDay = officecfg::Office::Common::Misc::LastTipOfTheDayShown::get();
    const sal_Int32 nDay = std::chrono::duration_cast<std::chrono::hours>(t0).count()/24; // days since 1970-01-01
    return nDay - nLastTipOfTheDay > 0; //only once per day
}

void SfxViewFrame::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint )
{
    if(m_pImpl->bIsDowning)
        return;

    // we know only SfxEventHint or simple SfxHint
    if (rHint.GetId() == SfxHintId::ThisIsAnSfxEventHint)
    {
        // When the Document is loaded asynchronously, was the Dispatcher
        // set as ReadOnly, to what must be returned when the document itself
        // is not read only, and the loading is finished.
        switch (static_cast<const SfxEventHint&>(rHint).GetEventId())
        {
            case SfxEventHintId::ModifyChanged:
            {
                SfxBindings& rBind = GetBindings();
                rBind.Invalidate( SID_DOC_MODIFIED );
                rBind.Invalidate( SID_RELOAD );
                rBind.Invalidate( SID_EDITDOC );
                break;
            }

            case SfxEventHintId::OpenDoc:
            case SfxEventHintId::CreateDoc:
            {
                if ( !m_xObjSh.is() )
                    break;

                SfxBindings& rBind = GetBindings();
                rBind.Invalidate( SID_RELOAD );
                rBind.Invalidate( SID_EDITDOC );

                bool bIsInfobarShown(false);

                if (officecfg::Office::Common::Passwords::HasMaster::get() &&
                    officecfg::Office::Common::Passwords::StorageVersion::get() == 0)
                {
                    // master password stored in deprecated format
                    VclPtr<SfxInfoBarWindow> pOldMasterPasswordInfoBar =
                        AppendInfoBar(u"oldmasterpassword"_ustr, u""_ustr,
                                      SfxResId(STR_REFRESH_MASTER_PASSWORD), InfobarType::DANGER, false);
                    bIsInfobarShown = true;
                    if (pOldMasterPasswordInfoBar)
                    {
                        weld::Button& rButton = pOldMasterPasswordInfoBar->addButton();
                        rButton.set_label(SfxResId(STR_REFRESH_PASSWORD));
                        rButton.connect_clicked(LINK(this,
                                                   SfxViewFrame, RefreshMasterPasswordHdl));
                        if (Application::GetHelp())
                        {
                            weld::Button& rHelp = pOldMasterPasswordInfoBar->addButton();
                            rHelp.set_label(SfxResId(RID_STR_HELP));
                            rHelp.connect_clicked(LINK(this, SfxViewFrame, HelpMasterPasswordHdl));
                        }
                    }
                }

                const bool bEmbedded = m_xObjSh->GetCreateMode() == SfxObjectCreateMode::EMBEDDED;

                // read-only infobar if necessary
                const SfxViewShell *pVSh;
                const SfxShell *pFSh;
                if ( m_xObjSh->IsReadOnly() &&
                    ! m_xObjSh->IsSecurityOptOpenReadOnly() &&
                    ( !bEmbedded ||
                        (( pVSh = m_xObjSh->GetViewShell()) && (pFSh = pVSh->GetFormShell()) && pFSh->IsDesignMode())))
                {
                    AppendReadOnlyInfobar();
                    bIsInfobarShown = true;
                }

                if (!bEmbedded && m_xObjSh->Get_Impl()->getCurrentMacroExecMode() == css::document::MacroExecMode::NEVER_EXECUTE)
                {
                    AppendContainsMacrosInfobar();
                    bIsInfobarShown = true;
                }

                if (vcl::CommandInfoProvider::GetModuleIdentifier(GetFrame().GetFrameInterface()) == "com.sun.star.text.TextDocument")
                    sfx2::SfxNotebookBar::ReloadNotebookBar(u"modules/swriter/ui/");

                if (SfxClassificationHelper::IsClassified(m_xObjSh->getDocProperties()))
                {
                    // Document has BAILS properties, display an infobar accordingly.
                    SfxClassificationHelper aHelper(m_xObjSh->getDocProperties());
                    aHelper.UpdateInfobar(*this);
                }

                // Add pending infobars
                std::vector<InfobarData>& aPendingInfobars = m_xObjSh->getPendingInfobars();
                while (!aPendingInfobars.empty())
                {
                    InfobarData& aInfobarData = aPendingInfobars.back();

                    // don't show Track Changes infobar, if Track Changes toolbar is visible
                    if (aInfobarData.msId == "hiddentrackchanges")
                    {
                        if (auto xLayoutManager = getLayoutManager(GetFrame()))
                        {
--> --------------------

--> maximum size reached

--> --------------------

Messung V0.5
C=94 H=98 G=95

¤ Dauer der Verarbeitung: 0.20 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.