From b9ecec7c74687ed5a9470cffb7d02e0e6e83107e Mon Sep 17 00:00:00 2001 From: Stephan Bergmann Date: Fri, 1 Jun 2012 17:32:07 +0200 Subject: 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). Change-Id: I89d9c6adf0baab411e737a5f4e6f4e770e7a70be --- 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 | 6 +++--- sfx2/source/doc/objxtor.cxx | 2 +- sfx2/source/view/viewfrm.cxx | 28 ++++++++++++++++------------ 7 files changed, 50 insertions(+), 24 deletions(-) (limited to 'sfx2') diff --git a/sfx2/inc/sfx2/docfile.hxx b/sfx2/inc/sfx2/docfile.hxx index f7f85d5502c5..ca8ad494f3e3 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 3c1837b22187..90acbb7b3c3f 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 4da155678152..e77992ef2dd6 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 037f4bcc2504..4c05bdb7ffed 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 313d95d19054..341821cbc960 100644 --- a/sfx2/source/doc/objstor.cxx +++ b/sfx2/source/doc/objstor.cxx @@ -688,9 +688,6 @@ sal_Bool SfxObjectShell::DoLoad( SfxMedium *pMed ) SFX_ITEMSET_ARG( pMedium->GetItemSet(), pTemplateItem, SfxBoolItem, SID_TEMPLATE, sal_False); if ( !pTemplateItem || !pTemplateItem->GetValue() ) bHasName = sal_True; - - if ( !IsReadOnly() && IsLoadReadonly() ) - SetReadOnlyUI(); } else SetError( ERRCODE_ABORT, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) ); @@ -750,6 +747,9 @@ sal_Bool SfxObjectShell::DoLoad( SfxMedium *pMed ) if ( bOk ) { + if ( IsReadOnlyMedium() || IsLoadReadonly() ) + SetReadOnlyUI(); + try { ::ucbhelper::Content aContent( pMedium->GetName(), com::sun::star::uno::Reference < XCommandEnvironment >() ); diff --git a/sfx2/source/doc/objxtor.cxx b/sfx2/source/doc/objxtor.cxx index 9e20d837b85d..dd1dbc18ec1f 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 0538bce341e0..155c194d05ee 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() ) -- cgit