From e77cd8495b88f6da773777909391562ee07055e1 Mon Sep 17 00:00:00 2001 From: Eike Rathke Date: Wed, 18 Jan 2017 22:49:08 +0100 Subject: tdf#104967 preserve isolated notes data in clipboard when closing document Change-Id: I0e263583e27c5103c0bb90e8fe00562e46a52d98 (cherry picked from commit b8b657123cc508c906622d20669507628c93e104) Reviewed-on: https://gerrit.libreoffice.org/33291 Reviewed-by: Markus Mohrhard Reviewed-by: Christian Lohmaier Tested-by: Christian Lohmaier --- sc/inc/column.hxx | 2 +- sc/inc/document.hxx | 2 +- sc/inc/postit.hxx | 10 ++++++++-- sc/inc/table.hxx | 2 +- sc/source/core/data/column4.cxx | 12 ++++++++---- sc/source/core/data/documen2.cxx | 8 +++----- sc/source/core/data/document.cxx | 4 ++-- sc/source/core/data/postit.cxx | 40 +++++++++++++++++++++++++++++++++------- sc/source/core/data/table2.cxx | 4 ++-- sc/source/ui/undo/undoblk.cxx | 2 +- 10 files changed, 60 insertions(+), 26 deletions(-) diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx index 5539f82d5fcc..cfce9d6a4e50 100644 --- a/sc/inc/column.hxx +++ b/sc/inc/column.hxx @@ -598,7 +598,7 @@ public: ScPostIt* ReleaseNote( SCROW nRow ); size_t GetNoteCount() const; void CreateAllNoteCaptions(); - void ForgetNoteCaptions( SCROW nRow1, SCROW nRow2 ); + void ForgetNoteCaptions( SCROW nRow1, SCROW nRow2, bool bPreserveData ); SCROW GetNotePosition( size_t nIndex ) const; void GetAllNoteEntries( std::vector& rNotes ) const; void GetNotesInRange( SCROW nStartRow, SCROW nEndRow, std::vector& rNotes ) const; diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx index 44092fd69006..10ce2e2f750a 100644 --- a/sc/inc/document.hxx +++ b/sc/inc/document.hxx @@ -1108,7 +1108,7 @@ public: * code uses sdr objects to export note data. */ void CreateAllNoteCaptions(); - void ForgetNoteCaptions( const ScRangeList& rRanges ); + void ForgetNoteCaptions( const ScRangeList& rRanges, bool bPreserveData ); ScAddress GetNotePosition( size_t nIndex ) const; ScAddress GetNotePosition( size_t nIndex, SCTAB nTab ) const; diff --git a/sc/inc/postit.hxx b/sc/inc/postit.hxx index 8835deaee972..87553f3f5c3e 100644 --- a/sc/inc/postit.hxx +++ b/sc/inc/postit.hxx @@ -129,8 +129,14 @@ public: /** Returns the caption object of this note. Creates the caption object, if the note contains initial caption data instead of the caption. */ SdrCaptionObj* GetOrCreateCaption( const ScAddress& rPos ) const; - /** Forgets the pointer to the note caption object. */ - void ForgetCaption(); + + /** Forgets the pointer to the note caption object. + + @param bPreserveData + If true then the note text is remembered in maNoteData to be able + to later reconstruct a caption from it. + */ + void ForgetCaption( bool bPreserveData = false ); /** Shows or hides the note caption object. */ void ShowCaption( const ScAddress& rPos, bool bShow ); diff --git a/sc/inc/table.hxx b/sc/inc/table.hxx index da69ea9a0571..34f6e3fd992a 100644 --- a/sc/inc/table.hxx +++ b/sc/inc/table.hxx @@ -400,7 +400,7 @@ public: size_t GetNoteCount( SCCOL nCol ) const; SCROW GetNotePosition( SCCOL nCol, size_t nIndex ) const; void CreateAllNoteCaptions(); - void ForgetNoteCaptions( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 ); + void ForgetNoteCaptions( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, bool bPreserveData ); void GetAllNoteEntries( std::vector& rNotes ) const; void GetNotesInRange( const ScRange& rRange, std::vector& rNotes ) const; diff --git a/sc/source/core/data/column4.cxx b/sc/source/core/data/column4.cxx index e3cfb3d193b6..234a8528b4e7 100644 --- a/sc/source/core/data/column4.cxx +++ b/sc/source/core/data/column4.cxx @@ -598,11 +598,15 @@ public: } }; -struct NoteCaptionCleaner +class NoteCaptionCleaner { + bool mbPreserveData; +public: + explicit NoteCaptionCleaner( bool bPreserveData ) : mbPreserveData(bPreserveData) {} + void operator() ( size_t /*nRow*/, ScPostIt* p ) { - p->ForgetCaption(); + p->ForgetCaption(mbPreserveData); } }; @@ -614,12 +618,12 @@ void ScColumn::CreateAllNoteCaptions() sc::ProcessNote(maCellNotes, aFunc); } -void ScColumn::ForgetNoteCaptions( SCROW nRow1, SCROW nRow2 ) +void ScColumn::ForgetNoteCaptions( SCROW nRow1, SCROW nRow2, bool bPreserveData ) { if (!ValidRow(nRow1) || !ValidRow(nRow2)) return; - NoteCaptionCleaner aFunc; + NoteCaptionCleaner aFunc(bPreserveData); sc::CellNoteStoreType::iterator it = maCellNotes.begin(); sc::ProcessNote(it, maCellNotes, nRow1, nRow2, aFunc); } diff --git a/sc/source/core/data/documen2.cxx b/sc/source/core/data/documen2.cxx index f884bcdd0b0e..7a41f14c01c2 100644 --- a/sc/source/core/data/documen2.cxx +++ b/sc/source/core/data/documen2.cxx @@ -379,13 +379,11 @@ ScDocument::~ScDocument() // copied from this document, forget it as it references this // document's drawing layer pages and what not, which otherwise when // pasting to another document after this document was destructed would - // attempt to access non-existing data. - /* XXX this is only a workaround to prevent a crash, the actual note - * content is lost, only a standard empty note caption will be pasted. - * TODO: come up with a solution. */ + // attempt to access non-existing data. Preserve the text data though. ScDocument* pClipDoc = ScModule::GetClipDoc(); if (pClipDoc) - pClipDoc->ForgetNoteCaptions( ScRangeList( ScRange( 0,0,0, MAXCOL, MAXROW, pClipDoc->GetTableCount()-1))); + pClipDoc->ForgetNoteCaptions( + ScRangeList( ScRange( 0,0,0, MAXCOL, MAXROW, pClipDoc->GetTableCount()-1)), true); } mxFormulaParserPool.reset(); diff --git a/sc/source/core/data/document.cxx b/sc/source/core/data/document.cxx index 604ae0401359..27456da3e612 100644 --- a/sc/source/core/data/document.cxx +++ b/sc/source/core/data/document.cxx @@ -6480,7 +6480,7 @@ void ScDocument::CreateAllNoteCaptions() } } -void ScDocument::ForgetNoteCaptions( const ScRangeList& rRanges ) +void ScDocument::ForgetNoteCaptions( const ScRangeList& rRanges, bool bPreserveData ) { for (size_t i = 0, n = rRanges.size(); i < n; ++i) { @@ -6493,7 +6493,7 @@ void ScDocument::ForgetNoteCaptions( const ScRangeList& rRanges ) if (!pTab) continue; - pTab->ForgetNoteCaptions(s.Col(), s.Row(), e.Col(), e.Row()); + pTab->ForgetNoteCaptions(s.Col(), s.Row(), e.Col(), e.Row(), bPreserveData); } } } diff --git a/sc/source/core/data/postit.cxx b/sc/source/core/data/postit.cxx index 27dfb65113be..83c6111823fa 100644 --- a/sc/source/core/data/postit.cxx +++ b/sc/source/core/data/postit.cxx @@ -584,12 +584,32 @@ SdrCaptionObj* ScPostIt::GetOrCreateCaption( const ScAddress& rPos ) const return maNoteData.mpCaption; } -void ScPostIt::ForgetCaption() +void ScPostIt::ForgetCaption( bool bPreserveData ) { - /* This function is used in undo actions to give up the responsibility for - the caption object which is handled by separate drawing undo actions. */ - maNoteData.mpCaption = nullptr; - maNoteData.mxInitData.reset(); + if (bPreserveData) + { + // Used in clipboard when the originating document is destructed to be + // able to paste into another document. Caption size and relative + // position are not preserved but default created when pasted. Also the + // MergedItemSet can not be carried over or it had to be adapted to + // defaults and pool. At least preserve the text and outline object if + // possible. + ScCaptionInitData* pInitData = new ScCaptionInitData; + const OutlinerParaObject* pOPO = GetOutlinerObject(); + if (pOPO) + pInitData->mxOutlinerObj.reset( new OutlinerParaObject(*pOPO)); + pInitData->maSimpleText = GetText(); + + maNoteData.mxInitData.reset(pInitData); + maNoteData.mpCaption = nullptr; + } + else + { + /* This function is used in undo actions to give up the responsibility for + the caption object which is handled by separate drawing undo actions. */ + maNoteData.mpCaption = nullptr; + maNoteData.mxInitData.reset(); + } } void ScPostIt::ShowCaption( const ScAddress& rPos, bool bShow ) @@ -629,13 +649,19 @@ void ScPostIt::CreateCaptionFromInitData( const ScAddress& rPos ) const to the clipboard/undo document, and when copying cells from the clipboard/undo document. The former should always be called first, so if called in an clipboard/undo document, the caption should have - been created already. */ - OSL_ENSURE( !mrDoc.IsUndo() && !mrDoc.IsClipboard(), "ScPostIt::CreateCaptionFromInitData - note caption should not be created in undo/clip documents" ); + been created already. Hovever, for clipboard in case the + originating document was destructed a new caption has to be + created. */ + OSL_ENSURE( !mrDoc.IsUndo() && (!mrDoc.IsClipboard() || !maNoteData.mpCaption), + "ScPostIt::CreateCaptionFromInitData - note caption should not be created in undo/clip documents" ); /* #i104915# Never try to create notes in Undo document, leads to crash due to missing document members (e.g. row height array). */ if( !maNoteData.mpCaption && !mrDoc.IsUndo() ) { + if (mrDoc.IsClipboard()) + mrDoc.InitDrawLayer(); // ensure there is a drawing layer + // ScNoteCaptionCreator c'tor creates the caption and inserts it into the document and maNoteData ScNoteCaptionCreator aCreator( mrDoc, rPos, maNoteData ); if( maNoteData.mpCaption ) diff --git a/sc/source/core/data/table2.cxx b/sc/source/core/data/table2.cxx index a046bc5cab23..a44ee8939730 100644 --- a/sc/source/core/data/table2.cxx +++ b/sc/source/core/data/table2.cxx @@ -1587,13 +1587,13 @@ void ScTable::CreateAllNoteCaptions() aCol[i].CreateAllNoteCaptions(); } -void ScTable::ForgetNoteCaptions( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 ) +void ScTable::ForgetNoteCaptions( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, bool bPreserveData ) { if (!ValidCol(nCol1) || !ValidCol(nCol2)) return; for (SCCOL i = nCol1; i <= nCol2; ++i) - aCol[i].ForgetNoteCaptions(nRow1, nRow2); + aCol[i].ForgetNoteCaptions(nRow1, nRow2, bPreserveData); } void ScTable::GetAllNoteEntries( std::vector& rNotes ) const diff --git a/sc/source/ui/undo/undoblk.cxx b/sc/source/ui/undo/undoblk.cxx index 46b2ba31db27..2c19695b6b86 100644 --- a/sc/source/ui/undo/undoblk.cxx +++ b/sc/source/ui/undo/undoblk.cxx @@ -939,7 +939,7 @@ void ScUndoPaste::DoChange(bool bUndo) sal_uInt16 nExtFlags = 0; pDocShell->UpdatePaintExt(nExtFlags, maBlockRanges.Combine()); - rDoc.ForgetNoteCaptions(maBlockRanges); + rDoc.ForgetNoteCaptions(maBlockRanges, false); aMarkData.MarkToMulti(); rDoc.DeleteSelection(nUndoFlags, aMarkData, false); // no broadcasting here for (size_t i = 0, n = maBlockRanges.size(); i < n; ++i) -- cgit