include/sfx2/docfile.hxx      |   19 ++++--
 sfx2/source/doc/docfile.cxx   |   71 +++++++++++++++-------
 sfx2/source/view/view.hrc     |    7 +-
 sfx2/source/view/view.src     |   12 +++
 sfx2/source/view/viewfrm.cxx  |  133 ++++++++++++++++++++++++++++++------------
 uui/source/iahndl-locking.cxx |   13 +++-
 uui/source/iahndl.cxx         |    9 +-
 uui/source/ids.hrc            |   69 +++++++++++----------
 uui/source/openlocked.cxx     |   22 +++---
 uui/source/openlocked.hxx     |    2 
 uui/source/openlocked.src     |    6 +
 11 files changed, 246 insertions(+), 117 deletions(-)

New commits:
commit e189dd061bb0817e1f9e872c9b8dc82b72bfffc5
Author: Mike Kaganski <mike.kagan...@collabora.com>
Date:   Thu Feb 8 18:06:06 2018 +0300

    tdf#108210: Allow to ignore a lock file if there's no filesystem lock
    
    Two cases are handled: when a file is being opened, and when it was
    opened read-only already, and one tries to reopen it in edit mode.
    The option to ignore locking and open the file anyway is only offered
    when there is no filesystem lock present on the file.
    
    Change-Id: I377d3cae4c949ae64d449634acea8fb3f68a5700
    Reviewed-on: https://gerrit.libreoffice.org/49448
    Tested-by: Jenkins <c...@libreoffice.org>
    Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com>
    Reviewed-on: https://gerrit.libreoffice.org/49470
    Reviewed-by: Aron Budea <aron.bu...@collabora.com>
    Tested-by: Aron Budea <aron.bu...@collabora.com>

diff --git a/include/sfx2/docfile.hxx b/include/sfx2/docfile.hxx
index 3a9c8978774f..6df519c2c625 100644
--- a/include/sfx2/docfile.hxx
+++ b/include/sfx2/docfile.hxx
@@ -163,11 +163,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/sfx2/source/doc/docfile.cxx b/sfx2/source/doc/docfile.cxx
index 98c861358090..a057133e6fc9 100644
--- a/sfx2/source/doc/docfile.cxx
+++ b/sfx2/source/doc/docfile.cxx
@@ -866,6 +866,8 @@ SfxMedium::ShowLockResult 
SfxMedium::ShowLockedDocumentDialog( const LockFileEnt
         OUString aInfo;
         ::rtl::Reference< ::ucbhelper::InteractionRequest > 
xInteractionRequestImpl;
 
+        sal_Int32 nContinuations = 3;
+
         if ( bOwnLock )
         {
             aInfo = aData[LockFileComponent::EDITTIME];
@@ -889,12 +891,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() );
@@ -910,14 +923,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
@@ -1012,12 +1030,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 !
@@ -1088,7 +1110,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& )
@@ -1127,23 +1149,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();
         }
@@ -1211,7 +1238,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;
                         }
                     }
 
@@ -1237,15 +1264,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)
@@ -1305,14 +1323,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;
                                 }
                             }
                         }
@@ -1346,11 +1370,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/view.hrc b/sfx2/source/view/view.hrc
index 548c43592561..af4c02fe59f1 100644
--- a/sfx2/source/view/view.hrc
+++ b/sfx2/source/view/view.hrc
@@ -35,8 +35,11 @@
 
 #define STR_ERROR_SAVE_TEMPLATE             (RID_SFX_VIEW_START+33)
 
-#define STR_QUERY_OPENASTEMPLATE            (RID_SFX_VIEW_START+41)
-#define STR_CANT_CLOSE                      (RID_SFX_VIEW_START+42)
+#define STR_QUERY_OPENASTEMPLATE              (RID_SFX_VIEW_START+41)
+#define STR_QUERY_OPENASTEMPLATE_ALLOW_IGNORE (RID_SFX_VIEW_START+42)
+#define STR_QUERY_OPENASTEMPLATE_OPENCOPY_BTN (RID_SFX_VIEW_START+43)
+#define STR_QUERY_OPENASTEMPLATE_OPEN_BTN     (RID_SFX_VIEW_START+44)
+#define STR_CANT_CLOSE                        (RID_SFX_VIEW_START+45)
 
 #endif
 
diff --git a/sfx2/source/view/view.src b/sfx2/source/view/view.src
index 0826609e5339..47caed97e475 100644
--- a/sfx2/source/view/view.src
+++ b/sfx2/source/view/view.src
@@ -77,6 +77,18 @@ String STR_QUERY_OPENASTEMPLATE
 {
     Text [ en-US ] = "This document cannot be edited, possibly due to missing 
access rights. Do you want to edit a copy of the document?" ;
 };
+String STR_QUERY_OPENASTEMPLATE_ALLOW_IGNORE
+{
+    Text [ en-US ] = "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." ;
+};
+String STR_QUERY_OPENASTEMPLATE_OPENCOPY_BTN
+{
+    Text [ en-US ] = "Open ~Copy" ;
+};
+String STR_QUERY_OPENASTEMPLATE_OPEN_BTN
+{
+    Text [ en-US ] = "~Open" ;
+};
 String STR_REPAIREDDOCUMENT
 {
     Text [ en-US ] = " (repaired document)" ;
diff --git a/sfx2/source/view/viewfrm.cxx b/sfx2/source/view/viewfrm.cxx
index f789a2f74931..f5a610a9a2f0 100644
--- a/sfx2/source/view/viewfrm.cxx
+++ b/sfx2/source/view/viewfrm.cxx
@@ -138,6 +138,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"
@@ -155,6 +156,7 @@ void SfxViewFrame::InitInterface_Impl()
 #endif
 }
 
+namespace {
 /// Asks the user if editing a read-only document is really wanted.
 class SfxEditDocumentDialog : public MessageDialog
 {
@@ -187,8 +189,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;
@@ -204,7 +229,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() );
@@ -252,6 +277,7 @@ static bool AskPasswordToModify_Impl( const uno::Reference< 
task::XInteractionHa
 
     return bResult;
 }
+}
 
 void SfxViewFrame::ExecReload_Impl( SfxRequest& rReq )
 {
@@ -284,6 +310,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);
@@ -333,7 +376,7 @@ void SfxViewFrame::ExecReload_Impl( SfxRequest& rReq )
                     }
                 }
                 nOpenMode = SFX_STREAM_READONLY;
-                pSh->SetReadOnlyUI();
+                aReadOnlyUIGuard.m_bSetRO = true;
             }
             else
             {
@@ -353,10 +396,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() )
@@ -365,12 +406,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() )
@@ -417,31 +454,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 )
                 {
@@ -461,10 +525,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() );
@@ -487,10 +548,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 ) );
diff --git a/uui/source/iahndl-locking.cxx b/uui/source/iahndl-locking.cxx
index 48312637bb21..d1c00706d769 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 <osl/mutex.hxx>
 #include <vcl/svapp.hxx>
@@ -68,7 +69,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;
@@ -91,11 +94,15 @@ handleLockedDocumentRequest_(
                                   ? aInfo
                                   : ResId( STR_UNKNOWNUSER,
                                                *xManager.get() ).toString() );
+            aArguments.push_back( xRetry.is()
+                                  ? ResId( STR_OPENLOCKED_ALLOWIGNORE_MSG,
+                                               *xManager.get() ).toString()
+                                  : "" );
             aMessage = ResId(STR_OPENLOCKED_MSG, *xManager.get()).toString();
             aMessage = UUIInteractionHelper::replaceMessageWithArguments(
                 aMessage, aArguments );
 
-            ScopedVclPtrInstance< OpenLockedQueryBox > xDialog(pParent, 
xManager.get(), aMessage);
+            ScopedVclPtrInstance< OpenLockedQueryBox > xDialog(pParent, 
xManager.get(), aMessage, xRetry.is());
             nResult = xDialog->Execute();
         }
         else if ( nMode == UUI_DOC_SAVE_LOCK )
@@ -133,6 +140,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 57ed634b24c1..f98757d89fd2 100644
--- a/uui/source/iahndl.cxx
+++ b/uui/source/iahndl.cxx
@@ -244,10 +244,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/ids.hrc b/uui/source/ids.hrc
index d06457dbcbe2..d3f2a80f2d59 100644
--- a/uui/source/ids.hrc
+++ b/uui/source/ids.hrc
@@ -36,41 +36,42 @@
 #define STR_UNKNOWNUSER                                 (RID_UUI_START + 31)
 #define STR_OPENLOCKED_TITLE                            (RID_UUI_START + 32)
 #define STR_OPENLOCKED_MSG                              (RID_UUI_START + 33)
-#define STR_OPENLOCKED_OPENREADONLY_BTN                 (RID_UUI_START + 34)
-#define STR_OPENLOCKED_OPENCOPY_BTN                     (RID_UUI_START + 35)
-#define STR_FILECHANGED_TITLE                           (RID_UUI_START + 36)
-#define STR_FILECHANGED_MSG                             (RID_UUI_START + 37)
-#define STR_FILECHANGED_SAVEANYWAY_BTN                  (RID_UUI_START + 38)
-#define STR_ALREADYOPEN_TITLE                           (RID_UUI_START + 39)
-#define STR_ALREADYOPEN_MSG                             (RID_UUI_START + 40)
-#define STR_ALREADYOPEN_READONLY_BTN                    (RID_UUI_START + 41)
-#define STR_ALREADYOPEN_OPEN_BTN                        (RID_UUI_START + 42)
-#define STR_LOCKFAILED_TITLE                            (RID_UUI_START + 43)
-#define STR_LOCKFAILED_MSG                              (RID_UUI_START + 44)
-#define STR_LOCKFAILED_OPENREADONLY_BTN                 (RID_UUI_START + 45)
-#define STR_LOCKCORRUPT_TITLE                           (RID_UUI_START + 46)
-#define STR_LOCKCORRUPT_MSG                             (RID_UUI_START + 47)
-#define STR_LOCKCORRUPT_OPENREADONLY_BTN                (RID_UUI_START + 48)
-#define STR_TRYLATER_TITLE                              (RID_UUI_START + 49)
-#define STR_TRYLATER_MSG                                (RID_UUI_START + 50)
-#define STR_TRYLATER_RETRYSAVING_BTN                    (RID_UUI_START + 51)
-#define STR_TRYLATER_SAVEAS_BTN                         (RID_UUI_START + 52)
-#define STR_ALREADYOPEN_SAVE_MSG                        (RID_UUI_START + 53)
-#define STR_ALREADYOPEN_RETRY_SAVE_BTN                  (RID_UUI_START + 54)
-#define STR_ALREADYOPEN_SAVE_BTN                        (RID_UUI_START + 55)
+#define STR_OPENLOCKED_ALLOWIGNORE_MSG                  (RID_UUI_START + 34)
+#define STR_OPENLOCKED_OPENREADONLY_BTN                 (RID_UUI_START + 35)
+#define STR_OPENLOCKED_OPENCOPY_BTN                     (RID_UUI_START + 36)
+#define STR_FILECHANGED_TITLE                           (RID_UUI_START + 37)
+#define STR_FILECHANGED_MSG                             (RID_UUI_START + 38)
+#define STR_FILECHANGED_SAVEANYWAY_BTN                  (RID_UUI_START + 39)
+#define STR_ALREADYOPEN_TITLE                           (RID_UUI_START + 40)
+#define STR_ALREADYOPEN_MSG                             (RID_UUI_START + 41)
+#define STR_ALREADYOPEN_READONLY_BTN                    (RID_UUI_START + 42)
+#define STR_ALREADYOPEN_OPEN_BTN                        (RID_UUI_START + 43)
+#define STR_LOCKFAILED_TITLE                            (RID_UUI_START + 44)
+#define STR_LOCKFAILED_MSG                              (RID_UUI_START + 45)
+#define STR_LOCKFAILED_OPENREADONLY_BTN                 (RID_UUI_START + 46)
+#define STR_LOCKCORRUPT_TITLE                           (RID_UUI_START + 47)
+#define STR_LOCKCORRUPT_MSG                             (RID_UUI_START + 48)
+#define STR_LOCKCORRUPT_OPENREADONLY_BTN                (RID_UUI_START + 49)
+#define STR_TRYLATER_TITLE                              (RID_UUI_START + 50)
+#define STR_TRYLATER_MSG                                (RID_UUI_START + 51)
+#define STR_TRYLATER_RETRYSAVING_BTN                    (RID_UUI_START + 52)
+#define STR_TRYLATER_SAVEAS_BTN                         (RID_UUI_START + 53)
+#define STR_ALREADYOPEN_SAVE_MSG                        (RID_UUI_START + 54)
+#define STR_ALREADYOPEN_RETRY_SAVE_BTN                  (RID_UUI_START + 55)
+#define STR_ALREADYOPEN_SAVE_BTN                        (RID_UUI_START + 56)
 
-#define STR_WARNING_INCOMPLETE_ENCRYPTION_TITLE         (RID_UUI_START + 56)
-#define STR_WARNING_BROKENSIGNATURE_TITLE               (RID_UUI_START + 57)
-#define STR_ENTER_PASSWORD_TO_OPEN                      (RID_UUI_START + 58)
-#define STR_ENTER_PASSWORD_TO_MODIFY                    (RID_UUI_START + 59)
-#define STR_RENAME_OR_REPLACE                           (RID_UUI_START + 60)
-#define STR_NAME_CLASH_RENAME_ONLY                      (RID_UUI_START + 61)
-#define STR_SAME_NAME_USED                              (RID_UUI_START + 62)
-#define STR_ENTER_SIMPLE_PASSWORD                       (RID_UUI_START + 63)
-#define STR_CONFIRM_SIMPLE_PASSWORD                     (RID_UUI_START + 64)
-#define STR_TITLE_CREATE_PASSWORD                       (RID_UUI_START + 65)
-#define STR_TITLE_ENTER_PASSWORD                        (RID_UUI_START + 66)
-#define STR_PASSWORD_MISMATCH                           (RID_UUI_START + 67)
+#define STR_WARNING_INCOMPLETE_ENCRYPTION_TITLE         (RID_UUI_START + 57)
+#define STR_WARNING_BROKENSIGNATURE_TITLE               (RID_UUI_START + 58)
+#define STR_ENTER_PASSWORD_TO_OPEN                      (RID_UUI_START + 59)
+#define STR_ENTER_PASSWORD_TO_MODIFY                    (RID_UUI_START + 60)
+#define STR_RENAME_OR_REPLACE                           (RID_UUI_START + 61)
+#define STR_NAME_CLASH_RENAME_ONLY                      (RID_UUI_START + 62)
+#define STR_SAME_NAME_USED                              (RID_UUI_START + 63)
+#define STR_ENTER_SIMPLE_PASSWORD                       (RID_UUI_START + 64)
+#define STR_CONFIRM_SIMPLE_PASSWORD                     (RID_UUI_START + 65)
+#define STR_TITLE_CREATE_PASSWORD                       (RID_UUI_START + 66)
+#define STR_TITLE_ENTER_PASSWORD                        (RID_UUI_START + 67)
+#define STR_PASSWORD_MISMATCH                           (RID_UUI_START + 68)
 
 #define ERRCODE_UUI_IO_ABORT                                    
(ERRCODE_AREA_UUI + 0)
 #define ERRCODE_UUI_IO_ACCESSDENIED                             
(ERRCODE_AREA_UUI + 1)
diff --git a/uui/source/openlocked.cxx b/uui/source/openlocked.cxx
index 4de71b54c2ca..90d7ad8bff68 100644
--- a/uui/source/openlocked.cxx
+++ b/uui/source/openlocked.cxx
@@ -20,7 +20,7 @@
 #include "ids.hrc"
 #include "openlocked.hxx"
 
-OpenLockedQueryBox::OpenLockedQueryBox( vcl::Window* pParent, ResMgr* pResMgr, 
const OUString& aMessage ) :
+OpenLockedQueryBox::OpenLockedQueryBox( vcl::Window* pParent, ResMgr* pResMgr, 
const OUString& aMessage, bool bEnableOverride ) :
     MessBox(pParent, 0,
             ResId(STR_OPENLOCKED_TITLE, *pResMgr).toString(),
             aMessage )
@@ -29,21 +29,19 @@ OpenLockedQueryBox::OpenLockedQueryBox( vcl::Window* 
pParent, ResMgr* pResMgr, c
 
     AddButton(ResId(STR_OPENLOCKED_OPENREADONLY_BTN, *pResMgr).toString(), 
RET_YES,
             ButtonDialogFlags::Default | ButtonDialogFlags::OK | 
ButtonDialogFlags::Focus);
+    SetButtonHelpText(RET_YES, OUString());
 
     AddButton(ResId(STR_OPENLOCKED_OPENCOPY_BTN, *pResMgr).toString(), RET_NO);
+    SetButtonHelpText(RET_NO, OUString());
+
+    if (bEnableOverride)
+    {
+        // Present option to ignore the (stale?) lock file and open the 
document
+        AddButton(ResId(STR_ALREADYOPEN_OPEN_BTN, *pResMgr).toString(), 
RET_IGNORE);
+        SetButtonHelpText(RET_IGNORE, OUString());
+    }
 
     AddButton( StandardButtonType::Cancel, RET_CANCEL, 
ButtonDialogFlags::Cancel );
-    SetButtonHelpText( RET_YES, OUString() );
-    SetButtonHelpText( RET_NO, OUString() );
-
-#ifdef _WIN32
-    // bnc#656566
-    // Yes, it is silly to do this only for this dialog but not the
-    // other similar ones. But hey, it was about this dialog that the
-    // customer complained. You who read this and feel the itch, feel
-    // free to fix the problem in a better way.
-    EnableAlwaysOnTop();
-#endif
 }
 
 OpenLockedQueryBox::~OpenLockedQueryBox()
diff --git a/uui/source/openlocked.hxx b/uui/source/openlocked.hxx
index 40c50e403e00..73c435fa6c11 100644
--- a/uui/source/openlocked.hxx
+++ b/uui/source/openlocked.hxx
@@ -24,7 +24,7 @@
 class OpenLockedQueryBox : public MessBox
 {
 public:
-    OpenLockedQueryBox( vcl::Window* pParent, ResMgr* pResMgr, const OUString& 
aMessage );
+    OpenLockedQueryBox( vcl::Window* pParent, ResMgr* pResMgr, const OUString& 
aMessage, bool bEnableOverride );
     virtual ~OpenLockedQueryBox() override;
 };
 
diff --git a/uui/source/openlocked.src b/uui/source/openlocked.src
index 8aee0a643bf9..d0069ce97ee6 100644
--- a/uui/source/openlocked.src
+++ b/uui/source/openlocked.src
@@ -27,7 +27,11 @@ String STR_OPENLOCKED_TITLE
 };
 String STR_OPENLOCKED_MSG
 {
-    Text [ en-US ] = "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";
+    Text [ en-US ] = "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)";
+};
+String STR_OPENLOCKED_ALLOWIGNORE_MSG
+{
+    Text [ en-US ] = "You may also ignore the file locking and open the 
document for editing.\n\n";
 };
 String STR_OPENLOCKED_OPENREADONLY_BTN
 {
_______________________________________________
Libreoffice-commits mailing list
libreoffice-comm...@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits

Reply via email to