diff options
-rw-r--r-- | include/sfx2/docfile.hxx | 19 | ||||
-rw-r--r-- | include/sfx2/strings.hrc | 3 | ||||
-rw-r--r-- | sfx2/source/doc/docfile.cxx | 71 | ||||
-rw-r--r-- | sfx2/source/view/viewfrm.cxx | 134 | ||||
-rw-r--r-- | uui/inc/strings.hrc | 3 | ||||
-rw-r--r-- | uui/source/iahndl-locking.cxx | 12 | ||||
-rw-r--r-- | uui/source/iahndl.cxx | 9 | ||||
-rw-r--r-- | uui/source/openlocked.cxx | 14 | ||||
-rw-r--r-- | uui/source/openlocked.hxx | 2 |
9 files changed, 194 insertions, 73 deletions
diff --git a/include/sfx2/docfile.hxx b/include/sfx2/docfile.hxx index 822c69b1da4f..06a7f9623764 100644 --- a/include/sfx2/docfile.hxx +++ b/include/sfx2/docfile.hxx @@ -162,11 +162,13 @@ public: bool Commit(); bool IsStorage(); - enum class ShowLockResult { NoLock, Succeeded,Try }; - ShowLockResult ShowLockedDocumentDialog( const LockFileEntry& aData, bool bIsLoading, bool bOwnLock, bool bHandleSysLocked); - void LockOrigFileOnDemand( bool bLoading, bool bNoUI ); - enum class MessageDlg { LockFileIgnore, LockFileCorrupt }; - bool ShowLockFileProblemDialog(MessageDlg nWhichDlg); + enum class LockFileResult + { + Failed, + FailedLockFile, // there was only lock file that prevented success - no syslock or IO error + Succeeded, + }; + LockFileResult LockOrigFileOnDemand( bool bLoading, bool bNoUI, bool bTryIgnoreLockFile = false ); void DisableUnlockWebDAV( bool bDisableUnlockWebDAV = true ); void UnlockFile( bool bReleaseLockStream ); /// Lets Transfer_Impl() not fsync the output file. @@ -275,6 +277,13 @@ public: static bool SetWritableForUserOnly( const OUString& aURL ); static sal_uInt32 CreatePasswordToModifyHash( const OUString& aPasswd, bool bWriter ); + +private: + enum class ShowLockResult { NoLock, Succeeded, Try }; + ShowLockResult ShowLockedDocumentDialog(const LockFileEntry& aData, bool bIsLoading, bool bOwnLock, bool bHandleSysLocked); + enum class MessageDlg { LockFileIgnore, LockFileCorrupt }; + bool ShowLockFileProblemDialog(MessageDlg nWhichDlg); + }; #endif diff --git a/include/sfx2/strings.hrc b/include/sfx2/strings.hrc index 889ccf8ab22b..c36a37b4893a 100644 --- a/include/sfx2/strings.hrc +++ b/include/sfx2/strings.hrc @@ -235,6 +235,9 @@ #define STR_CANT_CLOSE NC_("STR_CANT_CLOSE", "The document cannot be closed because a\n print job is being carried out.") #define STR_ERROR_SEND_MAIL NC_("STR_ERROR_SEND_MAIL", "An error occurred in sending the message. Possible errors could be a missing user account or a defective setup.\nPlease check the %PRODUCTNAME settings or your e-mail program settings.") #define STR_QUERY_OPENASTEMPLATE NC_("STR_QUERY_OPENASTEMPLATE", "This document cannot be edited, possibly due to missing access rights. Do you want to edit a copy of the document?") +#define STR_QUERY_OPENASTEMPLATE_ALLOW_IGNORE NC_("STR_QUERY_OPENASTEMPLATE_ALLOW_IGNORE", "This document cannot be edited, because it is locked in another session. Do you want to edit a copy of the document?\n\nYou can also try to ignore the lock and open the file for editing.") +#define STR_QUERY_OPENASTEMPLATE_OPENCOPY_BTN NC_("STR_QUERY_OPENASTEMPLATE_OPENCOPY_BTN", "Open ~Copy") +#define STR_QUERY_OPENASTEMPLATE_OPEN_BTN NC_("STR_QUERY_OPENASTEMPLATE_OPEN_BTN", "~Open") #define STR_REPAIREDDOCUMENT NC_("STR_REPAIREDDOCUMENT", " (repaired document)") #define STR_NONCHECKEDOUT_DOCUMENT NC_("STR_NONCHECKEDOUT_DOCUMENT", "This document is not checked out on the server.") #define STR_READONLY_DOCUMENT NC_("STR_READONLY_DOCUMENT", "This document is open in read-only mode.") diff --git a/sfx2/source/doc/docfile.cxx b/sfx2/source/doc/docfile.cxx index 055cfa41859d..175ab138c5af 100644 --- a/sfx2/source/doc/docfile.cxx +++ b/sfx2/source/doc/docfile.cxx @@ -846,6 +846,8 @@ SfxMedium::ShowLockResult SfxMedium::ShowLockedDocumentDialog( const LockFileEnt OUString aInfo; ::rtl::Reference< ::ucbhelper::InteractionRequest > xInteractionRequestImpl; + sal_Int32 nContinuations = 3; + if ( bOwnLock ) { aInfo = aData[LockFileComponent::EDITTIME]; @@ -869,12 +871,23 @@ SfxMedium::ShowLockResult SfxMedium::ShowLockedDocumentDialog( const LockFileEnt xInteractionRequestImpl = new ::ucbhelper::InteractionRequest( uno::makeAny( document::LockedDocumentRequest( OUString(), uno::Reference< uno::XInterface >(), aDocumentURL, aInfo ) ) ); + + // Use a fourth continuation in case there's no filesystem lock: + // "Ignore lock file and open the document" + if (!bHandleSysLocked) + nContinuations = 4; } - uno::Sequence< uno::Reference< task::XInteractionContinuation > > aContinuations( 3 ); + uno::Sequence< uno::Reference< task::XInteractionContinuation > > aContinuations(nContinuations); aContinuations[0] = new ::ucbhelper::InteractionAbort( xInteractionRequestImpl.get() ); aContinuations[1] = new ::ucbhelper::InteractionApprove( xInteractionRequestImpl.get() ); aContinuations[2] = new ::ucbhelper::InteractionDisapprove( xInteractionRequestImpl.get() ); + if (nContinuations > 3) + { + // We use InteractionRetry to reflect that user wants to + // ignore the (stale?) alien lock file and open the document + aContinuations[3] = new ::ucbhelper::InteractionRetry(xInteractionRequestImpl.get()); + } xInteractionRequestImpl->setContinuations( aContinuations ); xHandler->handle( xInteractionRequestImpl.get() ); @@ -890,14 +903,19 @@ SfxMedium::ShowLockResult SfxMedium::ShowLockedDocumentDialog( const LockFileEnt // own lock on saving, user has selected to ignore the lock // alien lock on loading, user has selected to edit a copy of document // TODO/LATER: alien lock on saving, user has selected to do SaveAs to different location - if ( bIsLoading && !bOwnLock ) + if ( !bOwnLock ) // bIsLoading implied from outermost condition { // means that a copy of the document should be opened GetItemSet()->Put( SfxBoolItem( SID_TEMPLATE, true ) ); } - else if ( bOwnLock ) + else nResult = ShowLockResult::Succeeded; } + else if (uno::Reference< task::XInteractionRetry >(xSelected.get(), uno::UNO_QUERY).is()) + { + // User decided to ignore the alien (stale?) lock file without filesystem lock + nResult = ShowLockResult::Succeeded; + } else // if ( XSelected == aContinuations[1] ) { // own lock on loading, user has selected to open readonly @@ -992,12 +1010,16 @@ namespace // sets SID_DOC_READONLY if the document cannot be opened for editing // if user cancel the loading the ERROR_ABORT is set -void SfxMedium::LockOrigFileOnDemand( bool bLoading, bool bNoUI ) +SfxMedium::LockFileResult SfxMedium::LockOrigFileOnDemand( bool bLoading, bool bNoUI, bool bTryIgnoreLockFile ) { #if !HAVE_FEATURE_MULTIUSER_ENVIRONMENT (void) bLoading; (void) bNoUI; + (void) bTryIgnoreLockFile; + return LockFileResult::Succeeded; #else + LockFileResult eResult = LockFileResult::Failed; + // check if path scheme is http:// or https:// // may be this is better if used always, in Android and iOS as well? // if this code should be always there, remember to move the relevant code in UnlockFile method as well ! @@ -1069,7 +1091,7 @@ void SfxMedium::LockOrigFileOnDemand( bool bLoading, bool bNoUI ) if ( !bResult && !bNoUI ) { - bUIStatus = ShowLockedDocumentDialog( aLockData, bLoading, false , false ); + bUIStatus = ShowLockedDocumentDialog( aLockData, bLoading, false , true ); } } catch( ucb::InteractiveNetworkWriteException& ) @@ -1108,23 +1130,28 @@ void SfxMedium::LockOrigFileOnDemand( bool bLoading, bool bNoUI ) // when the file is locked, get the current file date if ( bResult && DocNeedsFileDateCheck() ) GetInitFileDate( true ); + + if ( bResult ) + eResult = LockFileResult::Succeeded; } catch ( const uno::Exception& ) { SAL_WARN( "sfx.doc", "Locking exception: WebDAV while trying to lock the file" ); } - return; + return eResult; } - if (!IsLockingUsed() || GetURLObject().HasError()) - return; + if (!IsLockingUsed()) + return LockFileResult::Succeeded; + if (GetURLObject().HasError()) + return eResult; try { if ( pImpl->m_bLocked && bLoading && GetURLObject().GetProtocol() == INetProtocol::File ) { - // if the document is already locked the system locking might be temporarely off after storing + // if the document is already locked the system locking might be temporarily off after storing // check whether the system file locking should be taken again GetLockingStream_Impl(); } @@ -1176,7 +1203,7 @@ void SfxMedium::LockOrigFileOnDemand( bool bLoading, bool bNoUI ) // let the stream be opened to check the system file locking GetMedium_Impl(); if (GetError() != ERRCODE_NONE) { - return; + return eResult; } } @@ -1202,15 +1229,6 @@ void SfxMedium::LockOrigFileOnDemand( bool bLoading, bool bNoUI ) { bResult = aLockFile.CreateOwnLockFile(); } - catch (const ucb::InteractiveIOException&) - { - if (bLoading && !bNoUI) - { - bIoErr = true; - ShowLockFileProblemDialog(MessageDlg::LockFileIgnore); - bResult = true; // always delete the defect lock-file - } - } catch (const uno::Exception&) { if (bLoading && !bNoUI) @@ -1270,14 +1288,20 @@ void SfxMedium::LockOrigFileOnDemand( bool bLoading, bool bNoUI ) } } - if ( !bResult && !bNoUI && !bIoErr) + if ( !bResult && !bIoErr) { - bUIStatus = ShowLockedDocumentDialog( aData, bLoading, bOwnLock, bHandleSysLocked ); + if (!bNoUI) + bUIStatus = ShowLockedDocumentDialog(aData, bLoading, bOwnLock, bHandleSysLocked); + else if (bLoading && bTryIgnoreLockFile && !bHandleSysLocked) + bUIStatus = ShowLockResult::Succeeded; + if ( bUIStatus == ShowLockResult::Succeeded ) { // take the ownership over the lock file bResult = aLockFile.OverwriteOwnLockFile(); } + else if (bLoading && !bHandleSysLocked) + eResult = LockFileResult::FailedLockFile; } } } @@ -1311,11 +1335,16 @@ void SfxMedium::LockOrigFileOnDemand( bool bLoading, bool bNoUI ) // when the file is locked, get the current file date if ( bResult && DocNeedsFileDateCheck() ) GetInitFileDate( true ); + + if ( bResult ) + eResult = LockFileResult::Succeeded; } catch( const uno::Exception& ) { SAL_WARN( "sfx.doc", "Locking exception: high probability, that the content has not been created" ); } + + return eResult; #endif } diff --git a/sfx2/source/view/viewfrm.cxx b/sfx2/source/view/viewfrm.cxx index 7a5a536bb46e..7fee9f85800f 100644 --- a/sfx2/source/view/viewfrm.cxx +++ b/sfx2/source/view/viewfrm.cxx @@ -134,6 +134,7 @@ using ::com::sun::star::container::XIndexContainer; #include <sfx2/minfitem.hxx> #include <sfx2/strings.hrc> #include "impviewframe.hxx" +#include <vcl/msgbox.hxx> #define SfxViewFrame #include <sfxslots.hxx> @@ -151,6 +152,7 @@ void SfxViewFrame::InitInterface_Impl() #endif } +namespace { /// Asks the user if editing a read-only document is really wanted. class SfxEditDocumentDialog : public MessageDialog { @@ -183,8 +185,31 @@ void SfxEditDocumentDialog::dispose() MessageDialog::dispose(); } +class SfxQueryOpenAsTemplate : public QueryBox +{ +public: + SfxQueryOpenAsTemplate(vcl::Window* pParent, MessBoxStyle nStyle, bool bAllowIgnoreLock); +}; + +SfxQueryOpenAsTemplate::SfxQueryOpenAsTemplate(vcl::Window* pParent, MessBoxStyle 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(const SfxObjectShellRef& xObjSh) +bool IsSignPDF(const SfxObjectShellRef& xObjSh) { if (!xObjSh.is()) return false; @@ -200,7 +225,7 @@ static bool IsSignPDF(const 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() ); @@ -248,6 +273,7 @@ static bool AskPasswordToModify_Impl( const uno::Reference< task::XInteractionHa return bResult; } +} void SfxViewFrame::ExecReload_Impl( SfxRequest& rReq ) { @@ -263,6 +289,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); @@ -312,7 +355,7 @@ void SfxViewFrame::ExecReload_Impl( SfxRequest& rReq ) } } nOpenMode = SFX_STREAM_READONLY; - pSh->SetReadOnlyUI(); + aReadOnlyUIGuard.m_bSetRO = true; } else { @@ -332,10 +375,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() ) @@ -344,12 +385,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() ) @@ -396,31 +433,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 ) - pMed->LockOrigFileOnDemand( false, true ); + 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 ) ) ); + + 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(), MessBoxStyle::NONE, 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 ) { @@ -440,10 +504,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, VclButtonsType::YesNo); - if ( RET_YES == aBox->Execute() ) + if ( bOpenTemplate ) { SfxApplication* pApp = SfxGetpApp(); SfxAllItemSet aSet( pApp->GetPool() ); @@ -466,10 +527,13 @@ void SfxViewFrame::ExecReload_Impl( SfxRequest& rReq ) GetDispatcher()->Execute( SID_OPENDOC, SfxCallMode::ASYNCHRON, aSet ); return; } - else - nErr = ERRCODE_NONE; + + nErr = ERRCODE_NONE; } + // Keep the read-only UI + aReadOnlyUIGuard.m_bSetRO = true; + ErrorHandler::HandleError( nErr ); rReq.SetReturnValue( SfxBoolItem( rReq.GetSlot(), false ) ); diff --git a/uui/inc/strings.hrc b/uui/inc/strings.hrc index 760402c1d57b..590a582eba06 100644 --- a/uui/inc/strings.hrc +++ b/uui/inc/strings.hrc @@ -47,7 +47,8 @@ #define STR_LOCKFAILED_OPENREADONLY_BTN NC_("STR_LOCKFAILED_OPENREADONLY_BTN", "Open ~Read-Only") #define STR_OPENLOCKED_TITLE NC_("STR_OPENLOCKED_TITLE", "Document in Use") -#define STR_OPENLOCKED_MSG NC_("STR_OPENLOCKED_MSG", "Document file '$(ARG1)' is locked for editing by:\n\n$(ARG2)\n\nOpen document read-only or open a copy of the document for editing.\n\n") +#define STR_OPENLOCKED_MSG NC_("STR_OPENLOCKED_MSG", "Document file '$(ARG1)' is locked for editing by:\n\n$(ARG2)\n\nOpen document read-only or open a copy of the document for editing.\n\n$(ARG3)") +#define STR_OPENLOCKED_ALLOWIGNORE_MSG NC_("STR_OPENLOCKED_ALLOWIGNORE_MSG", "You may also ignore the file locking and open the document for editing.\n\n") #define STR_OPENLOCKED_OPENREADONLY_BTN NC_("STR_OPENLOCKED_OPENREADONLY_BTN", "Open ~Read-Only") #define STR_OPENLOCKED_OPENCOPY_BTN NC_("STR_OPENLOCKED_OPENCOPY_BTN", "Open ~Copy") #define STR_UNKNOWNUSER NC_("STR_UNKNOWNUSER", "Unknown User") diff --git a/uui/source/iahndl-locking.cxx b/uui/source/iahndl-locking.cxx index 53b0e6a2fc77..08b5b5c7fd99 100644 --- a/uui/source/iahndl-locking.cxx +++ b/uui/source/iahndl-locking.cxx @@ -29,6 +29,7 @@ #include <com/sun/star/task/XInteractionDisapprove.hpp> #include <com/sun/star/task/XInteractionAbort.hpp> #include <com/sun/star/task/XInteractionRequest.hpp> +#include <com/sun/star/task/XInteractionRetry.hpp> #include <unotools/resmgr.hxx> #include <vcl/svapp.hxx> @@ -66,7 +67,9 @@ handleLockedDocumentRequest_( uno::Reference< task::XInteractionApprove > xApprove; uno::Reference< task::XInteractionDisapprove > xDisapprove; uno::Reference< task::XInteractionAbort > xAbort; - getContinuations(rContinuations, &xApprove, &xDisapprove, &xAbort); + // In case an option to ignore lock and open the file is available + uno::Reference< task::XInteractionRetry > xRetry; + getContinuations(rContinuations, &xApprove, &xDisapprove, &xAbort, &xRetry); if ( !xApprove.is() || !xDisapprove.is() || !xAbort.is() ) return; @@ -86,11 +89,14 @@ handleLockedDocumentRequest_( aArguments.push_back( !aInfo.isEmpty() ? aInfo : Translate::get( STR_UNKNOWNUSER, aResLocale) ); + aArguments.push_back( xRetry.is() + ? Translate::get( STR_OPENLOCKED_ALLOWIGNORE_MSG, aResLocale ) + : "" ); aMessage = Translate::get(STR_OPENLOCKED_MSG, aResLocale); aMessage = UUIInteractionHelper::replaceMessageWithArguments( aMessage, aArguments ); - ScopedVclPtrInstance< OpenLockedQueryBox > xDialog(pParent, aResLocale, aMessage); + ScopedVclPtrInstance< OpenLockedQueryBox > xDialog(pParent, aResLocale, aMessage, xRetry.is()); nResult = xDialog->Execute(); } else if ( nMode == UUI_DOC_SAVE_LOCK ) @@ -128,6 +134,8 @@ handleLockedDocumentRequest_( xApprove->select(); else if ( nResult == RET_NO ) xDisapprove->select(); + else if ( nResult == RET_IGNORE && xRetry.is() ) + xRetry->select(); else xAbort->select(); } diff --git a/uui/source/iahndl.cxx b/uui/source/iahndl.cxx index 3d9d331476e6..f03372de3f54 100644 --- a/uui/source/iahndl.cxx +++ b/uui/source/iahndl.cxx @@ -238,10 +238,11 @@ UUIInteractionHelper::replaceMessageWithArguments( OUString aMessage = _aMessage; SAL_WARN_IF(rArguments.size() == 0, "uui", "replaceMessageWithArguments: No arguments passed!"); - if (rArguments.size() > 0) - aMessage = aMessage.replaceAll("$(ARG1)", rArguments[0]); - if (rArguments.size() > 1) - aMessage = aMessage.replaceAll("$(ARG2)", rArguments[1]); + for (size_t i = 0; i < rArguments.size(); ++i) + { + const OUString sReplaceTemplate = "$(ARG" + OUString::number(i+1) + ")"; + aMessage = aMessage.replaceAll(sReplaceTemplate, rArguments[i]); + } return aMessage; } diff --git a/uui/source/openlocked.cxx b/uui/source/openlocked.cxx index 074242b964b8..3267610b78d1 100644 --- a/uui/source/openlocked.cxx +++ b/uui/source/openlocked.cxx @@ -21,7 +21,7 @@ #include "openlocked.hxx" #include <unotools/resmgr.hxx> -OpenLockedQueryBox::OpenLockedQueryBox( vcl::Window* pParent, const std::locale& rResLocale, const OUString& aMessage ) : +OpenLockedQueryBox::OpenLockedQueryBox( vcl::Window* pParent, const std::locale& rResLocale, const OUString& aMessage, bool bEnableOverride ) : MessBox(pParent, MessBoxStyle::NONE, 0, Translate::get(STR_OPENLOCKED_TITLE, rResLocale), aMessage ) @@ -30,13 +30,19 @@ OpenLockedQueryBox::OpenLockedQueryBox( vcl::Window* pParent, const std::locale& AddButton(Translate::get(STR_OPENLOCKED_OPENREADONLY_BTN, rResLocale), RET_YES, ButtonDialogFlags::Default | ButtonDialogFlags::OK | ButtonDialogFlags::Focus); + SetButtonHelpText(RET_YES, OUString()); AddButton(Translate::get(STR_OPENLOCKED_OPENCOPY_BTN, rResLocale), RET_NO); + SetButtonHelpText(RET_NO, OUString()); - AddButton( StandardButtonType::Cancel, RET_CANCEL, ButtonDialogFlags::Cancel ); - SetButtonHelpText( RET_YES, OUString() ); - SetButtonHelpText( RET_NO, OUString() ); + if (bEnableOverride) + { + // Present option to ignore the (stale?) lock file and open the document + AddButton(Translate::get(STR_ALREADYOPEN_OPEN_BTN, rResLocale), RET_IGNORE); + SetButtonHelpText(RET_IGNORE, OUString()); + } + AddButton( StandardButtonType::Cancel, RET_CANCEL, ButtonDialogFlags::Cancel ); } OpenLockedQueryBox::~OpenLockedQueryBox() diff --git a/uui/source/openlocked.hxx b/uui/source/openlocked.hxx index 8584c45c2c7e..bb80a3c64146 100644 --- a/uui/source/openlocked.hxx +++ b/uui/source/openlocked.hxx @@ -24,7 +24,7 @@ class OpenLockedQueryBox : public MessBox { public: - OpenLockedQueryBox(vcl::Window* pParent, const std::locale& rResLocale, const OUString& rMessage); + OpenLockedQueryBox(vcl::Window* pParent, const std::locale& rResLocale, const OUString& rMessage, bool bEnableOverride); virtual ~OpenLockedQueryBox() override; }; |