Date: prev next · Thread: first prev next last
2012 Archives by date, by thread · List index


Hi all,

Just a heads up on the attached 0001-Work-in-progress-to-allow-for-editing-of-read-only-d.patch. Its commit message gives a rationale for what I aim at with the patch, but also explains why its not yet ready for prime time.

Nevertheless, I would appreciate it if people versed with the details of the various applications could give it a try, to see whether it breaks any obscure behaviour. (For example, there is reportedly already some support in Writer for editing form content of r/o documents. Does this patch affect that?) The patch looks rather short, but I struggled with it on-and-off over the course of several weeks, as every little change triggered unexpected changes in other, seemingly unrelated areas.

I'll try to get the Calc (and other applications?) problems fixed as soon as possible (I only noticed that problem now that I thought I was mainly done, but had only ever tested my changes with Writer), but am reluctant to press this into master towards LO 3.6 so short before feature freeze. Experience won over the last weeks indicates that too many surprises lurk in this area. So I would really like to hear other people's thoughts.

Thanks,
Stephan
From e215c5b5796194d5ba3b3f4b926d296b21e495cb Mon Sep 17 00:00:00 2001
From: Stephan Bergmann <sbergman@redhat.com>
Date: Thu, 31 May 2012 09:25:10 +0200
Subject: [PATCH] Work in progress to allow for editing of read-only documents

When e.g. viewing mail attachments (that have been stored r/o to some download
directory by the mail application), it would be nice if the user could easily
temporarily modify them (say, play around with a spreadsheet, changing some
numbers and triggering recalculation of formulas) by clicking the "Edit File"
button and not being asked to create a copy for editing.

This patch tries to make editability of a view independent of the r/o status of
the medium:

* SID_EDITDOC (the "Edit File" button) now only toggles the r/o status of the
  view.  It no longer asks to create a copy for editing if the underlying medium
  is r/o.

* When a modified document is toggled to r/o via SID_EDITDOC, LO still asks the
  user to save or discard the changes.  However, if the underlying medium is
  physically r/o (see next), saving the document opens the "Save As" dialog,
  instead of just doing a "Save" operation (which would fail on the r/o file).

* A new state of "IsOriginallyReadOnly" needed to be added to the medium, to
  keep track whether the medium was originally opened r/o (and is thus assumed
  to be physically r/o), as toggling SID_EDITDOC in the view also changes the
  open mode of the underlying medium.  Instead of trying to fully understand and
  disentangle that horrible mess, I just added yet another state to the mess...

* The title of the document window now contains "(read-only)" if and only if
  either the view is r/o or the medium is originally r/o (or both).

However, while this patch appears to work fine at least for simple cases of
Writer documents, it does not work well yet e.g. for Calc documents.  Opening a
r/o .ods file shows it in r/o view mode, but nonetheless allows for modification
of cell content etc.

Change-Id: Ic81f625eb0494dbd90db2e27403e89d48b2c3f87
---
 sfx2/inc/sfx2/docfile.hxx    |    5 +++++
 sfx2/inc/sfx2/objsh.hxx      |    1 +
 sfx2/source/doc/docfile.cxx  |   20 ++++++++++++++++----
 sfx2/source/doc/objmisc.cxx  |   12 ++++++++----
 sfx2/source/doc/objstor.cxx  |    2 +-
 sfx2/source/doc/objxtor.cxx  |    2 +-
 sfx2/source/view/viewfrm.cxx |   28 ++++++++++++++++------------
 7 files changed, 48 insertions(+), 22 deletions(-)

diff --git a/sfx2/inc/sfx2/docfile.hxx b/sfx2/inc/sfx2/docfile.hxx
index f7f85d5..ca8ad49 100644
--- a/sfx2/inc/sfx2/docfile.hxx
+++ b/sfx2/inc/sfx2/docfile.hxx
@@ -213,6 +213,11 @@ public:
                         GetVersionList( bool _bNoReload = false );
     sal_Bool            IsReadOnly();
 
+    // Whether the medium had originally been opened r/o, independent of later
+    // changes via SetOpenMode; used to keep track of the "true" state of the
+    // medium across toggles via SID_EDITDOC (which do change SetOpenMode):
+    bool                IsOriginallyReadOnly() const;
+
     ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >  GetInputStream();
 
     void                CreateTempFile( sal_Bool bReplace = sal_True );
diff --git a/sfx2/inc/sfx2/objsh.hxx b/sfx2/inc/sfx2/objsh.hxx
index 3c1837b..90acbb7 100644
--- a/sfx2/inc/sfx2/objsh.hxx
+++ b/sfx2/inc/sfx2/objsh.hxx
@@ -273,6 +273,7 @@ public:
     void                        SetReadOnly();
     sal_Bool                    IsReadOnly() const;
     sal_Bool                    IsReadOnlyMedium() const;
+    bool                        IsOriginallyReadOnlyMedium() const;
     void                        SetReadOnlyUI( sal_Bool bReadOnly = sal_True );
     sal_Bool                    IsReadOnlyUI() const;
     void                        SetNoName();
diff --git a/sfx2/source/doc/docfile.cxx b/sfx2/source/doc/docfile.cxx
index 4da1556..e77992e 100644
--- a/sfx2/source/doc/docfile.cxx
+++ b/sfx2/source/doc/docfile.cxx
@@ -312,6 +312,8 @@ public:
 
     uno::Reference< logging::XSimpleLogRing > m_xLogRing;
 
+    bool m_originallyReadOnly;
+
     SfxMedium_Impl( SfxMedium* pAntiImplP );
     ~SfxMedium_Impl();
 };
@@ -339,7 +341,8 @@ SfxMedium_Impl::SfxMedium_Impl( SfxMedium* pAntiImplP )
     pTempFile( NULL ),
     nLastStorageError( 0 ),
     m_bRemoveBackup( sal_False ),
-    m_nSignatureState( SIGNATURESTATE_NOSIGNATURES )
+    m_nSignatureState( SIGNATURESTATE_NOSIGNATURES ),
+    m_originallyReadOnly(false)
 {
     aDoneLink.CreateMutex();
 }
@@ -1057,6 +1060,11 @@ sal_Bool SfxMedium::LockOrigFileOnDemand( sal_Bool bLoading, sal_Bool bNoUI )
                         bContentReadonly = IsReadonlyAccordingACL( aPhysPath.GetBuffer() );
                 }
 #endif
+
+                if ( bContentReadonly )
+                {
+                    pImp->m_originallyReadOnly = true;
+                }
             }
 
             // do further checks only if the file not readonly in fs
@@ -2874,15 +2882,14 @@ SfxMedium::SfxMedium( const ::com::sun::star::uno::Sequence< 
::com::sun::star::b
         }
     }
 
-    sal_Bool bReadOnly = sal_False;
     SFX_ITEMSET_ARG( pSet, pReadOnlyItem, SfxBoolItem, SID_DOC_READONLY, sal_False );
     if ( pReadOnlyItem && pReadOnlyItem->GetValue() )
-        bReadOnly = sal_True;
+        pImp->m_originallyReadOnly = true;
 
     SFX_ITEMSET_ARG( pSet, pFileNameItem, SfxStringItem, SID_FILE_NAME, sal_False );
     if (!pFileNameItem) throw uno::RuntimeException();
     aLogicName = pFileNameItem->GetValue();
-    nStorOpenMode = bReadOnly ? SFX_STREAM_READONLY : SFX_STREAM_READWRITE;
+    nStorOpenMode = pImp->m_originallyReadOnly ? SFX_STREAM_READONLY : SFX_STREAM_READWRITE;
     Init_Impl();
 }
 
@@ -3207,6 +3214,11 @@ sal_Bool SfxMedium::IsReadOnly()
     return bReadOnly;
 }
 
+bool SfxMedium::IsOriginallyReadOnly() const
+{
+    return pImp->m_originallyReadOnly;
+}
+
 //----------------------------------------------------------------
 sal_Bool SfxMedium::SetWritableForUserOnly( const ::rtl::OUString& aURL )
 {
diff --git a/sfx2/source/doc/objmisc.cxx b/sfx2/source/doc/objmisc.cxx
index 037f4bc..4c05bdb 100644
--- a/sfx2/source/doc/objmisc.cxx
+++ b/sfx2/source/doc/objmisc.cxx
@@ -404,6 +404,11 @@ sal_Bool SfxObjectShell::IsReadOnlyMedium() const
     return pMedium->IsReadOnly();
 }
 
+bool SfxObjectShell::IsOriginallyReadOnlyMedium() const
+{
+    return pMedium == 0 || pMedium->IsOriginallyReadOnly();
+}
+
 //-------------------------------------------------------------------------
 
 void SfxObjectShell::SetReadOnlyUI( sal_Bool bReadOnly )
@@ -415,10 +420,9 @@ void SfxObjectShell::SetReadOnlyUI( sal_Bool bReadOnly )
 */
 
 {
-    sal_Bool bWasRO = IsReadOnly();
-    pImp->bReadOnlyUI = bReadOnly;
-    if ( bWasRO != IsReadOnly() )
+    if ( bReadOnly != pImp->bReadOnlyUI )
     {
+        pImp->bReadOnlyUI = bReadOnly;
         Broadcast( SfxSimpleHint(SFX_HINT_MODECHANGED) );
     }
 }
@@ -453,7 +457,7 @@ void SfxObjectShell::SetReadOnly()
 
 sal_Bool SfxObjectShell::IsReadOnly() const
 {
-    return pImp->bReadOnlyUI || IsReadOnlyMedium();
+    return pImp->bReadOnlyUI || pMedium == 0;
 }
 
 //-------------------------------------------------------------------------
diff --git a/sfx2/source/doc/objstor.cxx b/sfx2/source/doc/objstor.cxx
index 313d95d..a8e3c61 100644
--- a/sfx2/source/doc/objstor.cxx
+++ b/sfx2/source/doc/objstor.cxx
@@ -689,7 +689,7 @@ sal_Bool SfxObjectShell::DoLoad( SfxMedium *pMed )
                     if ( !pTemplateItem || !pTemplateItem->GetValue() )
                         bHasName = sal_True;
 
-                    if ( !IsReadOnly() && IsLoadReadonly() )
+                    if ( IsReadOnlyMedium() || IsLoadReadonly() )
                         SetReadOnlyUI();
                 }
                 else
diff --git a/sfx2/source/doc/objxtor.cxx b/sfx2/source/doc/objxtor.cxx
index 9e20d83..dd1dbc1 100644
--- a/sfx2/source/doc/objxtor.cxx
+++ b/sfx2/source/doc/objxtor.cxx
@@ -661,7 +661,7 @@ sal_uInt16 SfxObjectShell::PrepareClose
             {
                 SfxBoolItem aWarnItem( SID_FAIL_ON_WARNING, bUI );
                 const SfxPoolItem* ppArgs[] = { &aWarnItem, 0 };
-                pPoolItem = pFrame->GetBindings().ExecuteSynchron( SID_SAVEDOC, ppArgs );
+                pPoolItem = pFrame->GetBindings().ExecuteSynchron( IsReadOnlyMedium() ? 
SID_SAVEASDOC : SID_SAVEDOC, ppArgs );
             }
 
             if ( !pPoolItem || pPoolItem->ISA(SfxVoidItem) || ( pPoolItem->ISA(SfxBoolItem) && !( 
(const SfxBoolItem*) pPoolItem )->GetValue() ) )
diff --git a/sfx2/source/view/viewfrm.cxx b/sfx2/source/view/viewfrm.cxx
index 0538bce..155c194 100644
--- a/sfx2/source/view/viewfrm.cxx
+++ b/sfx2/source/view/viewfrm.cxx
@@ -405,6 +405,7 @@ void SfxViewFrame::ExecReload_Impl( SfxRequest& rReq )
                     }
                 }
                 nOpenMode = SFX_STREAM_READONLY;
+                pSh->SetReadOnlyUI(true);
             }
             else
             {
@@ -424,12 +425,20 @@ void SfxViewFrame::ExecReload_Impl( SfxRequest& rReq )
                     pSh->SetModifyPasswordEntered();
                 }
 
-                nOpenMode = SFX_STREAM_READWRITE;
-                pSh->SetReadOnlyUI( sal_False );
+                nOpenMode = pSh->IsOriginallyReadOnlyMedium() ? SFX_STREAM_READONLY : 
SFX_STREAM_READWRITE;
 
                 // if only the view was in the readonly mode then there is no need to do the reload
-                if ( !pSh->IsReadOnly() )
+                if ( !pSh->IsReadOnlyMedium() )
+                {
+                    // SetReadOnlyUI causes recomputation of window title, using
+                    // open mode among other things, so call SetOpenMode before
+                    // SetReadOnlyUI:
+                    pMed->SetOpenMode( nOpenMode );
+                    pSh->SetReadOnlyUI( sal_False );
                     return;
+                }
+
+                pSh->SetReadOnlyUI( sal_False );
             }
 
             if ( rReq.IsAPI() )
@@ -580,8 +589,6 @@ void SfxViewFrame::ExecReload_Impl( SfxRequest& rReq )
                             SID_FILE_NAME, sal_False);
             // Open as editable?
             sal_Bool bForEdit = !pSh->IsReadOnly();
-            if ( rReq.GetSlot() == SID_EDITDOC )
-                bForEdit = !bForEdit;
 
             // If possible ask the User
             sal_Bool bDo = ( GetViewShell()->PrepareClose() != sal_False );
@@ -650,9 +657,9 @@ void SfxViewFrame::ExecReload_Impl( SfxRequest& rReq )
                     // let the current security settings be checked again
                     pNewSet->Put( SfxUInt16Item( SID_MACROEXECMODE, 
document::MacroExecMode::USE_CONFIG ) );
 
-                    if ( rReq.GetSlot() == SID_EDITDOC || !bForEdit )
+                    if ( pSh->IsOriginallyReadOnlyMedium() )
                         // edit mode is switched or reload of readonly document
-                        pNewSet->Put( SfxBoolItem( SID_DOC_READONLY, !bForEdit ) );
+                        pNewSet->Put( SfxBoolItem( SID_DOC_READONLY, true ) );
                     else
                         // Reload of file opened for writing
                         pNewSet->ClearItem( SID_DOC_READONLY );
@@ -778,12 +785,9 @@ void SfxViewFrame::ExecReload_Impl( SfxRequest& rReq )
                         xNewObj->SetModifyPasswordEntered( sal_False );
                         xNewObj->SetReadOnly();
                     }
-                    else if ( rReq.GetSlot() == SID_EDITDOC && bForEdit && 
!xNewObj->IsReadOnlyMedium() )
+                    else if ( rReq.GetSlot() == SID_EDITDOC )
                     {
-                        // the filter might request setting of the document to readonly state
-                        // but in case of SID_EDITDOC it should not happen if the document
-                        // can be opened for editing
-                        xNewObj->SetReadOnlyUI( sal_False );
+                        xNewObj->SetReadOnlyUI( !bForEdit );
                     }
 
                     if ( xNewObj->IsDocShared() )
-- 
1.7.10.2


Context


Privacy Policy | Impressum (Legal Info) | Copyright information: Unless otherwise specified, all text and images on this website are licensed under the Creative Commons Attribution-Share Alike 3.0 License. This does not include the source code of LibreOffice, which is licensed under the Mozilla Public License (MPLv2). "LibreOffice" and "The Document Foundation" are registered trademarks of their corresponding registered owners or are in actual use as trademarks in one or more countries. Their respective logos and icons are also subject to international copyright laws. Use thereof is explained in our trademark policy.