[PATCH] Work in progress to allow for editing of read-only documents
Stephan Bergmann
sbergman at redhat.com
Thu May 31 00:25:10 PDT 2012
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
--------------080700050804020305090907--
More information about the LibreOffice
mailing list