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
- Work in progress to allow for editing of read-only documents · Stephan Bergmann
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.