diff options
Diffstat (limited to 'sfx2/source/view/viewfrm.cxx')
-rw-r--r-- | sfx2/source/view/viewfrm.cxx | 133 |
1 files changed, 98 insertions, 35 deletions
diff --git a/sfx2/source/view/viewfrm.cxx b/sfx2/source/view/viewfrm.cxx index 840ba418e3e7..8d0fb19f3faf 100644 --- a/sfx2/source/view/viewfrm.cxx +++ b/sfx2/source/view/viewfrm.cxx @@ -137,6 +137,7 @@ using ::com::sun::star::container::XIndexContainer; #include <sfx2/minfitem.hxx> #include "../appl/app.hrc" #include "impviewframe.hxx" +#include <vcl/msgbox.hxx> #define SfxViewFrame #include "sfxslots.hxx" @@ -154,6 +155,7 @@ void SfxViewFrame::InitInterface_Impl() #endif } +namespace { /// Asks the user if editing a read-only document is really wanted. class SfxEditDocumentDialog : public MessageDialog { @@ -186,8 +188,31 @@ void SfxEditDocumentDialog::dispose() MessageDialog::dispose(); } +class SfxQueryOpenAsTemplate : public QueryBox +{ +public: + SfxQueryOpenAsTemplate(vcl::Window* pParent, WinBits nStyle, bool bAllowIgnoreLock); +}; + +SfxQueryOpenAsTemplate::SfxQueryOpenAsTemplate(vcl::Window* pParent, WinBits nStyle, bool bAllowIgnoreLock) + : QueryBox(pParent, nStyle, SfxResId(bAllowIgnoreLock ? STR_QUERY_OPENASTEMPLATE_ALLOW_IGNORE : STR_QUERY_OPENASTEMPLATE)) +{ + AddButton(SfxResId(STR_QUERY_OPENASTEMPLATE_OPENCOPY_BTN), RET_YES, + ButtonDialogFlags::Default | ButtonDialogFlags::OK | ButtonDialogFlags::Focus); + SetButtonHelpText(RET_YES, OUString()); + + if (bAllowIgnoreLock) + { + AddButton(SfxResId(STR_QUERY_OPENASTEMPLATE_OPEN_BTN), RET_IGNORE); + SetButtonHelpText(RET_IGNORE, OUString()); + } + + AddButton(StandardButtonType::Cancel, RET_CANCEL); + SetButtonHelpText(RET_CANCEL, OUString()); +} + /// Is this read-only object shell opened via .uno:SignPDF? -static bool IsSignPDF(SfxObjectShellRef xObjSh) +bool IsSignPDF(SfxObjectShellRef xObjSh) { if (!xObjSh.Is()) return false; @@ -203,7 +228,7 @@ static bool IsSignPDF(SfxObjectShellRef xObjSh) return false; } -static 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 ) +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.getLength() ); @@ -251,6 +276,7 @@ static bool AskPasswordToModify_Impl( const uno::Reference< task::XInteractionHa return bResult; } +} void SfxViewFrame::ExecReload_Impl( SfxRequest& rReq ) { @@ -283,6 +309,23 @@ void SfxViewFrame::ExecReload_Impl( SfxRequest& rReq ) if( !pSh || !pSh->HasName() || !(pSh->Get_Impl()->nLoadedFlags & SfxLoadedFlags::MAINDOCUMENT )) break; + // Only change read-only UI and remove info bar when we succeed + struct ReadOnlyUIGuard + { + SfxViewFrame* m_pFrame; + SfxObjectShell* m_pSh; + bool m_bSetRO; + ~ReadOnlyUIGuard() + { + if (m_bSetRO != m_pSh->IsReadOnlyUI()) + { + m_pSh->SetReadOnlyUI(m_bSetRO); + if (!m_bSetRO) + m_pFrame->RemoveInfoBar("readonly"); + } + } + } aReadOnlyUIGuard{ this, pSh, pSh->IsReadOnlyUI() }; + SfxMedium* pMed = pSh->GetMedium(); const SfxBoolItem* pItem = SfxItemSet::GetItem<SfxBoolItem>(pSh->GetMedium()->GetItemSet(), SID_VIEWONLY, false); @@ -332,7 +375,7 @@ void SfxViewFrame::ExecReload_Impl( SfxRequest& rReq ) } } nOpenMode = SFX_STREAM_READONLY; - pSh->SetReadOnlyUI(); + aReadOnlyUIGuard.m_bSetRO = true; } else { @@ -352,10 +395,8 @@ void SfxViewFrame::ExecReload_Impl( SfxRequest& rReq ) pSh->SetModifyPasswordEntered(); } - // Remove infobar if document was read-only (after password check) - RemoveInfoBar("readonly"); - 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() ) @@ -364,12 +405,8 @@ void SfxViewFrame::ExecReload_Impl( SfxRequest& rReq ) // open mode among other things, so call SetOpenMode before // SetReadOnlyUI: pMed->SetOpenMode( nOpenMode ); - pSh->SetReadOnlyUI( false ); return; } - - - pSh->SetReadOnlyUI( false ); } if ( rReq.IsAPI() ) @@ -416,31 +453,58 @@ void SfxViewFrame::ExecReload_Impl( SfxRequest& rReq ) // <- tdf#82744 { bool bOK = false; - if ( !pVersionItem ) - { - bool bHasStorage = pMed->HasStorage_Impl(); - // switching edit mode could be possible without reload - if ( bHasStorage && pMed->GetStorage() == pSh->GetStorage() ) + bool bRetryIgnoringLock = false; + bool bOpenTemplate = false; + do { + if ( !pVersionItem ) { - // TODO/LATER: faster creation of copy - if ( !pSh->ConnectTmpStorage_Impl( pMed->GetStorage(), pMed ) ) - return; - } + if (bRetryIgnoringLock) + pMed->ResetError(); - pMed->CloseAndRelease(); - pMed->GetItemSet()->Put( SfxBoolItem( SID_DOC_READONLY, !( nOpenMode & StreamMode::WRITE ) ) ); - pMed->SetOpenMode( nOpenMode ); + 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->GetItemSet()->Put( SfxBoolItem( SID_DOC_READONLY, !( nOpenMode & StreamMode::WRITE ) ) ); + pMed->SetOpenMode( nOpenMode ); + + pMed->CompleteReOpen(); + if ( nOpenMode & StreamMode::WRITE ) + { + auto eResult = pMed->LockOrigFileOnDemand( true, true, bRetryIgnoringLock ); + 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 ) ) ); - pMed->CompleteReOpen(); - if ( nOpenMode & StreamMode::WRITE ) - pMed->LockOrigFileOnDemand( false, true ); + if ( !pMed->GetErrorCode() ) + bOK = true; + } - // LockOrigFileOnDemand might set the readonly flag itself, it should be set back - pMed->GetItemSet()->Put( SfxBoolItem( SID_DOC_READONLY, !( nOpenMode & StreamMode::WRITE ) ) ); + if( !bOK ) + { + if (nOpenMode == SFX_STREAM_READWRITE && !rReq.IsAPI()) + { + // css::sdbcx::User offering to open it as a template + ScopedVclPtrInstance<SfxQueryOpenAsTemplate> aBox(&GetWindow(), 0, bRetryIgnoringLock); - if ( !pMed->GetErrorCode() ) - bOK = true; + short nUserAnswer = aBox->Execute(); + bOpenTemplate = RET_YES == nUserAnswer; + // Always reset this here to avoid infinite loop + bRetryIgnoringLock = RET_IGNORE == nUserAnswer; + } + else + bRetryIgnoringLock = false; + } } + while ( !bOK && bRetryIgnoringLock ); if( !bOK ) { @@ -460,10 +524,7 @@ void SfxViewFrame::ExecReload_Impl( SfxRequest& rReq ) if ( nOpenMode == SFX_STREAM_READWRITE && !rReq.IsAPI() ) { - // css::sdbcx::User offering to open it as a template - ScopedVclPtrInstance<MessageDialog> aBox(&GetWindow(), SfxResId(STR_QUERY_OPENASTEMPLATE), - VclMessageType::Question, VCL_BUTTONS_YES_NO); - if ( RET_YES == aBox->Execute() ) + if ( bOpenTemplate ) { SfxApplication* pApp = SfxGetpApp(); SfxAllItemSet aSet( pApp->GetPool() ); @@ -486,10 +547,12 @@ void SfxViewFrame::ExecReload_Impl( SfxRequest& rReq ) GetDispatcher()->Execute( SID_OPENDOC, SfxCallMode::ASYNCHRON, aSet ); return; } - else - nErr = 0; + nErr = 0; } + // Keep the read-only UI + aReadOnlyUIGuard.m_bSetRO = true; + ErrorHandler::HandleError( nErr ); rReq.SetReturnValue( SfxBoolItem( rReq.GetSlot(), false ) ); |