sc/inc/columnspanset.hxx | 8 +++++ sc/source/core/data/columnspanset.cxx | 47 ++++++++++++++++++++++++++++++++++ sc/source/ui/inc/undobase.hxx | 13 +++++++++ sc/source/ui/inc/undoblk.hxx | 4 ++ sc/source/ui/undo/undobase.cxx | 45 +++++++++++++++++++++++++++++++- sc/source/ui/undo/undoblk3.cxx | 12 +++++++- sc/source/ui/view/viewfunc.cxx | 32 ++++++++++++++++++++--- 7 files changed, 155 insertions(+), 6 deletions(-)
New commits: commit 23e43dfd8a4b26a9adee87e5274b82a6d1d84a57 Author: Kohei Yoshida <kohei.yosh...@collabora.com> Date: Sat May 3 00:50:46 2014 -0400 fdo#78062: Broadcast only on non-empty cells within deleted range. We don't want to broadcast over the whole selected range, which may be the whole sheet which is well over 1 billion cells ! (cherry picked from commit af7df25bcc8bc95462e2b3bf8c003d035111a479) Conflicts: sc/source/ui/inc/undobase.hxx sc/source/ui/undo/undobase.cxx Change-Id: I7c139ce5efe09312cf824e35f0efe551184032eb Reviewed-on: https://gerrit.libreoffice.org/9240 Tested-by: Markus Mohrhard <markus.mohrh...@googlemail.com> Reviewed-by: Markus Mohrhard <markus.mohrh...@googlemail.com> diff --git a/sc/inc/columnspanset.hxx b/sc/inc/columnspanset.hxx index 62e96a8..c12f13e 100644 --- a/sc/inc/columnspanset.hxx +++ b/sc/inc/columnspanset.hxx @@ -39,8 +39,10 @@ struct RowSpan */ class ColumnSpanSet : boost::noncopyable { +public: typedef mdds::flat_segment_tree<SCROW, bool> ColumnSpansType; +private: struct ColumnType { ColumnSpansType maSpans; @@ -81,6 +83,12 @@ public: void set(SCTAB nTab, SCCOL nCol, SCROW nRow1, SCROW nRow2, bool bVal); void set(const ScRange& rRange, bool bVal); + /** + * Scan specified range in a specified sheet and mark all non-empty cells + * with specified boolean value. + */ + void scan(const ScDocument& rDoc, SCTAB nTab, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, bool bVal); + void executeAction(Action& ac) const; void executeColumnAction(ScDocument& rDoc, ColumnAction& ac) const; }; diff --git a/sc/source/core/data/columnspanset.cxx b/sc/source/core/data/columnspanset.cxx index efa51b5..7bc517b 100644 --- a/sc/source/core/data/columnspanset.cxx +++ b/sc/source/core/data/columnspanset.cxx @@ -20,6 +20,29 @@ namespace sc { +namespace { + +class ColumnScanner +{ + ColumnSpanSet::ColumnSpansType& mrRanges; + bool mbVal; +public: + ColumnScanner(ColumnSpanSet::ColumnSpansType& rRanges, bool bVal) : + mrRanges(rRanges), mbVal(bVal) {} + + void operator() (const sc::CellStoreType::value_type& node, size_t nOffset, size_t nDataSize) + { + if (node.type == sc::element_type_empty) + return; + + size_t nRow = node.position + nOffset; + size_t nEndRow = nRow + nDataSize; // Last row of current block plus 1 + mrRanges.insert_back(nRow, nEndRow, mbVal); + } +}; + +} + RowSpan::RowSpan(SCROW nRow1, SCROW nRow2) : mnRow1(nRow1), mnRow2(nRow2) {} ColumnSpanSet::ColumnType::ColumnType(SCROW nStart, SCROW nEnd, bool bInit) : @@ -94,6 +117,30 @@ void ColumnSpanSet::set(const ScRange& rRange, bool bVal) } } +void ColumnSpanSet::scan( + const ScDocument& rDoc, SCTAB nTab, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, bool bVal) +{ + if (!ValidColRow(nCol1, nRow1) || !ValidColRow(nCol2, nRow2)) + return; + + if (nCol1 > nCol2 || nRow1 > nRow2) + return; + + const ScTable* pTab = rDoc.FetchTable(nTab); + if (!pTab) + return; + + for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol) + { + ColumnType& rCol = getColumn(nTab, nCol); + + const CellStoreType& rSrcCells = pTab->aCol[nCol].maCells; + + ColumnScanner aScanner(rCol.maSpans, bVal); + ParseBlock(rSrcCells.begin(), rSrcCells, aScanner, nRow1, nRow2); + } +} + void ColumnSpanSet::executeAction(Action& ac) const { for (size_t nTab = 0; nTab < maDoc.size(); ++nTab) diff --git a/sc/source/ui/inc/undobase.hxx b/sc/source/ui/inc/undobase.hxx index 5c9df4b..fd84303 100644 --- a/sc/source/ui/inc/undobase.hxx +++ b/sc/source/ui/inc/undobase.hxx @@ -24,6 +24,9 @@ #include "global.hxx" #include "address.hxx" #include "docsh.hxx" +#include <columnspanset.hxx> + +#include <boost/ptr_container/ptr_map.hpp> class ScDocument; class ScDocShell; @@ -39,6 +42,8 @@ class ScSimpleUndo: public SfxUndoAction public: TYPEINFO(); + typedef boost::ptr_map<SCTAB,sc::ColumnSpanSet> DataSpansType; + ScSimpleUndo( ScDocShell* pDocSh ); virtual ~ScSimpleUndo(); @@ -59,6 +64,14 @@ protected: void BroadcastChanges( const ScRange& rRange ); + /** + * Broadcast changes on specified spans. + * + * @param rSpans container that specifies all spans whose changes need to + * be broadcasted. + */ + void BroadcastChanges( const DataSpansType& rSpans ); + static void ShowTable( SCTAB nTab ); static void ShowTable( const ScRange& rRange ); }; diff --git a/sc/source/ui/inc/undoblk.hxx b/sc/source/ui/inc/undoblk.hxx index 758e5bb..007c6e1 100644 --- a/sc/source/ui/inc/undoblk.hxx +++ b/sc/source/ui/inc/undoblk.hxx @@ -274,7 +274,11 @@ public: virtual OUString GetComment() const; + void SetDataSpans( const boost::shared_ptr<DataSpansType>& pSpans ); + private: + boost::shared_ptr<DataSpansType> mpDataSpans; // Spans of non-empty cells. + ScRange aRange; ScMarkData aMarkData; ScDocument* pUndoDoc; // Block mark and deleted data diff --git a/sc/source/ui/undo/undobase.cxx b/sc/source/ui/undo/undobase.cxx index 77f8345..609b6fe 100644 --- a/sc/source/ui/undo/undobase.cxx +++ b/sc/source/ui/undo/undobase.cxx @@ -30,8 +30,7 @@ #include "queryparam.hxx" #include "subtotalparam.hxx" #include "globstr.hrc" - -// STATIC DATA ----------------------------------------------------------- +#include <column.hxx> TYPEINIT1(ScSimpleUndo, SfxUndoAction); TYPEINIT1(ScBlockUndo, ScSimpleUndo); @@ -148,6 +147,48 @@ void ScSimpleUndo::BroadcastChanges( const ScRange& rRange ) pDoc->BroadcastCells(rRange, SC_HINT_DATACHANGED); } +namespace { + +class SpanBroadcaster : public sc::ColumnSpanSet::ColumnAction +{ + ScDocument& mrDoc; + SCTAB mnCurTab; + SCCOL mnCurCol; + +public: + SpanBroadcaster( ScDocument& rDoc ) : mrDoc(rDoc), mnCurTab(-1), mnCurCol(-1) {} + + virtual void startColumn( ScColumn* pCol ) + { + mnCurTab = pCol->GetTab(); + mnCurCol = pCol->GetCol(); + } + + virtual void execute( SCROW nRow1, SCROW nRow2, bool bVal ) + { + if (!bVal) + return; + + ScRange aRange(mnCurTab, mnCurCol, nRow1, mnCurTab, mnCurCol, nRow2); + mrDoc.BroadcastCells(aRange, SC_HINT_DATACHANGED); + }; +}; + +} + +void ScSimpleUndo::BroadcastChanges( const DataSpansType& rSpans ) +{ + ScDocument* pDoc = pDocShell->GetDocument(); + SpanBroadcaster aBroadcaster(*pDoc); + + DataSpansType::const_iterator it = rSpans.begin(), itEnd = rSpans.end(); + for (; it != itEnd; ++it) + { + const sc::ColumnSpanSet& rSet = *it->second; + rSet.executeColumnAction(*pDoc, aBroadcaster); + } +} + void ScSimpleUndo::ShowTable( SCTAB nTab ) { ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); diff --git a/sc/source/ui/undo/undoblk3.cxx b/sc/source/ui/undo/undoblk3.cxx index a06a076..6c258e0 100644 --- a/sc/source/ui/undo/undoblk3.cxx +++ b/sc/source/ui/undo/undoblk3.cxx @@ -105,6 +105,11 @@ OUString ScUndoDeleteContents::GetComment() const return ScGlobal::GetRscString( STR_UNDO_DELETECONTENTS ); // "Delete" } +void ScUndoDeleteContents::SetDataSpans( const boost::shared_ptr<DataSpansType>& pSpans ) +{ + mpDataSpans = pSpans; +} + void ScUndoDeleteContents::SetChangeTrack() { ScChangeTrack* pChangeTrack = pDocShell->GetDocument()->GetChangeTrack(); @@ -183,8 +188,13 @@ void ScUndoDeleteContents::Undo() EndUndo(); if (nFlags & IDF_CONTENTS) + { // Broadcast only when the content changes. fdo#74687 - BroadcastChanges(aRange); + if (mpDataSpans) + BroadcastChanges(*mpDataSpans); + else + BroadcastChanges(aRange); + } HelperNotifyChanges::NotifyIfChangesListeners(*pDocShell, aRange); } diff --git a/sc/source/ui/view/viewfunc.cxx b/sc/source/ui/view/viewfunc.cxx index dd4e562..e308cad 100644 --- a/sc/source/ui/view/viewfunc.cxx +++ b/sc/source/ui/view/viewfunc.cxx @@ -1854,6 +1854,9 @@ void ScViewFunc::DeleteContents( sal_uInt16 nFlags, bool bRecord ) aFuncMark ); } + // To keep track of all non-empty cells within the deleted area. + boost::shared_ptr<ScSimpleUndo::DataSpansType> pDataSpans; + if ( bRecord ) { pUndoDoc = new ScDocument( SCDOCMODE_UNDO ); @@ -1880,6 +1883,26 @@ void ScViewFunc::DeleteContents( sal_uInt16 nFlags, bool bRecord ) // do not copy note captions to undo document nUndoDocFlags |= IDF_NOCAPTIONS; pDoc->CopyToDocument( aCopyRange, nUndoDocFlags, bMulti, pUndoDoc, &aFuncMark ); + + pDataSpans.reset(new ScSimpleUndo::DataSpansType); + + for (itr = aFuncMark.begin(); itr != itrEnd; ++itr) + { + nTab = *itr; + + SCCOL nCol1 = aCopyRange.aStart.Col(), nCol2 = aCopyRange.aEnd.Col(); + SCROW nRow1 = aCopyRange.aStart.Row(), nRow2 = aCopyRange.aEnd.Row(); + + std::pair<ScSimpleUndo::DataSpansType::iterator,bool> r = + pDataSpans->insert(nTab, new sc::ColumnSpanSet(false)); + + if (r.second) + { + ScSimpleUndo::DataSpansType::iterator it = r.first; + sc::ColumnSpanSet* pSet = it->second; + pSet->scan(*pDoc, nTab, nCol1, nRow1, nCol2, nRow2, true); + } + } } HideAllCursors(); // for if summary is cancelled @@ -1894,9 +1917,12 @@ void ScViewFunc::DeleteContents( sal_uInt16 nFlags, bool bRecord ) if ( bRecord ) { - pDocSh->GetUndoManager()->AddUndoAction( - new ScUndoDeleteContents( pDocSh, aFuncMark, aExtendedRange, - pUndoDoc, bMulti, nFlags, bDrawUndo ) ); + ScUndoDeleteContents* pUndo = + new ScUndoDeleteContents( + pDocSh, aFuncMark, aExtendedRange, pUndoDoc, bMulti, nFlags, bDrawUndo); + pUndo->SetDataSpans(pDataSpans); + + pDocSh->GetUndoManager()->AddUndoAction(pUndo); } if (!AdjustRowHeight( aExtendedRange.aStart.Row(), aExtendedRange.aEnd.Row() )) _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits