[Libreoffice-commits] core.git: Branch 'libreoffice-4-2' - sc/inc sc/source

Eike Rathke erack at redhat.com
Fri Aug 22 10:35:36 PDT 2014


 sc/inc/types.hxx                 |    8 ++++
 sc/source/core/data/bcaslot.cxx  |   36 ++++++++++++++++++--
 sc/source/core/data/documen7.cxx |    2 -
 sc/source/core/data/table3.cxx   |   67 +++++++++++++++++++++++++++++++++++++--
 sc/source/core/inc/bcaslot.hxx   |    6 ++-
 sc/source/core/tool/token.cxx    |    2 +
 6 files changed, 111 insertions(+), 10 deletions(-)

New commits:
commit 2d8d35f9f74102b800a3b777a5e3d79dce283ae9
Author: Eike Rathke <erack at redhat.com>
Date:   Thu Aug 14 23:36:47 2014 +0200

    correct references after sort, fdo#79441
    
    5c6ee09126631342939ae8766fe36083d8c011e3 introduced a different
    algorithm for reference handling during sort. Unfortunately that clashed
    with the SC_CLONECELL_ADJUST3DREL introduced a little earlier resulting
    in relative 3D references effectively being "adjusted" twice.
    
    Furthermore, in-sort-range range references to one row (or column) were
    not adapted to the move at all if the formula within the range listened
    only to ranges and not a single cell. Added collecting and adjusting
    area listeners for this.
    
    Last but not least, external (relative) references need to be treated
    the same as internal 3D references, making them point to the same
    location after the sort.
    
    (cherry picked from commit 69adec3ec051ff94f600ab899506ca9d645a8b56)
    
    Conflicts:
    	sc/inc/types.hxx
    	sc/source/core/data/bcaslot.cxx
    
    Plus necessary parts of 27182231acd3a0c9898a8dba78b76dc8a827b4c0 related
    to bcaslot changes.
    
    Change-Id: I492768b525f95f1c43d1c6e7a63a36cce093fa5a
    Reviewed-on: https://gerrit.libreoffice.org/10930
    Reviewed-by: Kohei Yoshida <libreoffice at kohei.us>
    Tested-by: Kohei Yoshida <libreoffice at kohei.us>

diff --git a/sc/inc/types.hxx b/sc/inc/types.hxx
index 732ff19..5226463 100644
--- a/sc/inc/types.hxx
+++ b/sc/inc/types.hxx
@@ -100,6 +100,14 @@ struct RangeMatrix
 
 typedef boost::unordered_map<SCCOLROW,SCCOLROW> ColRowReorderMapType;
 
+enum AreaOverlapType
+{
+    AreaInside,
+    AreaPartialOverlap,
+    OneRowInsideArea,
+    OneColumnInsideArea
+};
+
 }
 
 #endif
diff --git a/sc/source/core/data/bcaslot.cxx b/sc/source/core/data/bcaslot.cxx
index 2dfc9a7..1eff597 100644
--- a/sc/source/core/data/bcaslot.cxx
+++ b/sc/source/core/data/bcaslot.cxx
@@ -446,7 +446,8 @@ void ScBroadcastAreaSlot::EraseArea( ScBroadcastAreas::iterator& rIter )
     }
 }
 
-void ScBroadcastAreaSlot::GetAllListeners( const ScRange& rRange, std::vector<sc::AreaListener>& rListeners )
+void ScBroadcastAreaSlot::GetAllListeners(
+    const ScRange& rRange, std::vector<sc::AreaListener>& rListeners, sc::AreaOverlapType eType )
 {
     for (ScBroadcastAreas::const_iterator aIter( aBroadcastAreaTbl.begin()),
             aIterEnd( aBroadcastAreaTbl.end()); aIter != aIterEnd; ++aIter )
@@ -456,8 +457,32 @@ void ScBroadcastAreaSlot::GetAllListeners( const ScRange& rRange, std::vector<sc
 
         ScBroadcastArea* pArea = (*aIter).mpArea;
         const ScRange& rAreaRange = pArea->GetRange();
-        if (!rRange.In(rAreaRange))
-            continue;
+
+        switch (eType)
+        {
+            case sc::AreaInside:
+                if (!rRange.In(rAreaRange))
+                    // The range needs to be fully inside specified range.
+                    continue;
+                break;
+            case sc::AreaPartialOverlap:
+                if (!rRange.Intersects(rAreaRange) || rRange.In(rAreaRange))
+                    // The range needs to be only partially overlapping.
+                    continue;
+                break;
+            case sc::OneRowInsideArea:
+                if (rAreaRange.aStart.Row() != rAreaRange.aEnd.Row() || !rRange.In(rAreaRange))
+                    // The range needs to be one single row and fully inside
+                    // specified range.
+                    continue;
+                break;
+            case sc::OneColumnInsideArea:
+                if (rAreaRange.aStart.Col() != rAreaRange.aEnd.Col() || !rRange.In(rAreaRange))
+                    // The range needs to be one single column and fully inside
+                    // specified range.
+                    continue;
+                break;
+        }
 
         SvtBroadcaster::ListenersType& rLst = pArea->GetBroadcaster().GetAllListeners();
         SvtBroadcaster::ListenersType::iterator itLst = rLst.begin(), itLstEnd = rLst.end();
@@ -1000,7 +1025,8 @@ void ScBroadcastAreaSlotMachine::FinallyEraseAreas( ScBroadcastAreaSlot* pSlot )
     maAreasToBeErased.swap( aCopy);
 }
 
-std::vector<sc::AreaListener> ScBroadcastAreaSlotMachine::GetAllListeners( const ScRange& rRange )
+std::vector<sc::AreaListener> ScBroadcastAreaSlotMachine::GetAllListeners(
+    const ScRange& rRange, sc::AreaOverlapType eType )
 {
     std::vector<sc::AreaListener> aRet;
 
@@ -1017,7 +1043,7 @@ std::vector<sc::AreaListener> ScBroadcastAreaSlotMachine::GetAllListeners( const
         while ( nOff <= nEnd )
         {
             ScBroadcastAreaSlot* p = *pp;
-            p->GetAllListeners(rRange, aRet);
+            p->GetAllListeners(rRange, aRet, eType);
             ComputeNextSlot( nOff, nBreak, pp, nStart, ppSlots, nRowBreak);
         }
     }
diff --git a/sc/source/core/data/documen7.cxx b/sc/source/core/data/documen7.cxx
index a960c5a..581da65 100644
--- a/sc/source/core/data/documen7.cxx
+++ b/sc/source/core/data/documen7.cxx
@@ -156,7 +156,7 @@ void ScDocument::BroadcastRefMoved( const sc::RefMovedHint& rHint )
     const ScAddress& rDelta = rHint.getDelta();
 
     // Get all area listeners that listens on the old range, and end their listening.
-    std::vector<sc::AreaListener> aAreaListeners = pBASM->GetAllListeners(rSrcRange);
+    std::vector<sc::AreaListener> aAreaListeners = pBASM->GetAllListeners(rSrcRange, sc::AreaInside);
     {
         std::vector<sc::AreaListener>::iterator it = aAreaListeners.begin(), itEnd = aAreaListeners.end();
         for (; it != itEnd; ++it)
diff --git a/sc/source/core/data/table3.cxx b/sc/source/core/data/table3.cxx
index 3b63f7e..a719f85 100644
--- a/sc/source/core/data/table3.cxx
+++ b/sc/source/core/data/table3.cxx
@@ -62,6 +62,7 @@
 #include <sharedformula.hxx>
 #include <refhint.hxx>
 #include <listenerquery.hxx>
+#include <bcaslot.hxx>
 
 #include "svl/sharedstringpool.hxx"
 
@@ -721,6 +722,21 @@ void ScTable::SortReorderByColumn(
 
     // Collect all listeners within sorted range ahead of time.
     std::vector<SvtListener*> aListeners;
+
+    // Get all area listeners that listen on one column within the range and
+    // end their listening.
+    ScRange aMoveRange( nStart, nRow1, nTab, nLast, nRow2, nTab);
+    std::vector<sc::AreaListener> aAreaListeners = pDocument->GetBASM()->GetAllListeners(
+            aMoveRange, sc::OneColumnInsideArea);
+    {
+        std::vector<sc::AreaListener>::iterator it = aAreaListeners.begin(), itEnd = aAreaListeners.end();
+        for (; it != itEnd; ++it)
+        {
+            pDocument->EndListeningArea(it->maArea, it->mpListener);
+            aListeners.push_back( it->mpListener);
+        }
+    }
+
     for (SCCOL nCol = nStart; nCol <= nLast; ++nCol)
         aCol[nCol].CollectListeners(aListeners, nRow1, nRow2);
 
@@ -732,6 +748,22 @@ void ScTable::SortReorderByColumn(
     ColReorderNotifier aFunc(aColMap, nTab, nRow1, nRow2);
     std::for_each(aListeners.begin(), aListeners.end(), aFunc);
 
+    // Re-start area listeners on the reordered columns.
+    {
+        std::vector<sc::AreaListener>::iterator it = aAreaListeners.begin(), itEnd = aAreaListeners.end();
+        for (; it != itEnd; ++it)
+        {
+            ScRange aNewRange = it->maArea;
+            sc::ColRowReorderMapType::const_iterator itCol = aColMap.find( aNewRange.aStart.Col());
+            if (itCol != aColMap.end())
+            {
+                aNewRange.aStart.SetCol( itCol->second);
+                aNewRange.aEnd.SetCol( itCol->second);
+            }
+            pDocument->StartListeningArea(aNewRange, it->mpListener);
+        }
+    }
+
     // Re-join formulas at row boundaries now that all the references have
     // been adjusted for column reordering.
     for (SCCOL nCol = nStart; nCol <= nLast; ++nCol)
@@ -807,8 +839,7 @@ void ScTable::SortReorderByRow(
                     assert(rCell.mpAttr);
                     ScAddress aOldPos = rCell.maCell.mpFormula->aPos;
 
-                    ScFormulaCell* pNew = rCell.maCell.mpFormula->Clone(
-                        aCellPos, SC_CLONECELL_DEFAULT | SC_CLONECELL_ADJUST3DREL);
+                    ScFormulaCell* pNew = rCell.maCell.mpFormula->Clone( aCellPos, SC_CLONECELL_DEFAULT);
                     pNew->CopyAllBroadcasters(*rCell.maCell.mpFormula);
                     pNew->GetCode()->AdjustReferenceOnMovedOrigin(aOldPos, aCellPos);
 
@@ -948,6 +979,22 @@ void ScTable::SortReorderByRow(
 
     // Collect all listeners within sorted range ahead of time.
     std::vector<SvtListener*> aListeners;
+
+    // Get all area listeners that listen on one row within the range and end
+    // their listening.
+    ScRange aMoveRange( nCol1, nRow1, nTab, nCol2, nRow2, nTab);
+    std::vector<sc::AreaListener> aAreaListeners = pDocument->GetBASM()->GetAllListeners(
+            aMoveRange, sc::OneRowInsideArea);
+    {
+        std::vector<sc::AreaListener>::iterator it = aAreaListeners.begin(), itEnd = aAreaListeners.end();
+        for (; it != itEnd; ++it)
+        {
+            pDocument->EndListeningArea(it->maArea, it->mpListener);
+            aListeners.push_back( it->mpListener);
+        }
+    }
+
+    // Collect listeners of cell broadcasters.
     for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
         aCol[nCol].CollectListeners(aListeners, nRow1, nRow2);
 
@@ -980,6 +1027,22 @@ void ScTable::SortReorderByRow(
     RowReorderNotifier aFunc(aRowMap, nTab, nCol1, nCol2);
     std::for_each(aListeners.begin(), aListeners.end(), aFunc);
 
+    // Re-start area listeners on the reordered rows.
+    {
+        std::vector<sc::AreaListener>::iterator it = aAreaListeners.begin(), itEnd = aAreaListeners.end();
+        for (; it != itEnd; ++it)
+        {
+            ScRange aNewRange = it->maArea;
+            sc::ColRowReorderMapType::const_iterator itRow = aRowMap.find( aNewRange.aStart.Row());
+            if (itRow != aRowMap.end())
+            {
+                aNewRange.aStart.SetRow( itRow->second);
+                aNewRange.aEnd.SetRow( itRow->second);
+            }
+            pDocument->StartListeningArea(aNewRange, it->mpListener);
+        }
+    }
+
     // Re-group formulas in affected columns.
     for (itGroupTab = rGroupTabs.begin(); itGroupTab != itGroupTabEnd; ++itGroupTab)
     {
diff --git a/sc/source/core/inc/bcaslot.hxx b/sc/source/core/inc/bcaslot.hxx
index b8587d6..b4b57e9 100644
--- a/sc/source/core/inc/bcaslot.hxx
+++ b/sc/source/core/inc/bcaslot.hxx
@@ -221,7 +221,8 @@ public:
      */
     void                EraseArea( ScBroadcastAreas::iterator& rIter );
 
-    void GetAllListeners( const ScRange& rRange, std::vector<sc::AreaListener>& rListeners );
+    void GetAllListeners(
+        const ScRange& rRange, std::vector<sc::AreaListener>& rListeners, sc::AreaOverlapType eType );
 };
 
 
@@ -317,7 +318,8 @@ public:
     // only for ScBroadcastAreaSlot
     void                FinallyEraseAreas( ScBroadcastAreaSlot* pSlot );
 
-    std::vector<sc::AreaListener> GetAllListeners( const ScRange& rRange );
+    std::vector<sc::AreaListener> GetAllListeners(
+        const ScRange& rRange, sc::AreaOverlapType eType );
 };
 
 
diff --git a/sc/source/core/tool/token.cxx b/sc/source/core/tool/token.cxx
index d392550..24f0343 100644
--- a/sc/source/core/tool/token.cxx
+++ b/sc/source/core/tool/token.cxx
@@ -3469,6 +3469,7 @@ void ScTokenArray::AdjustReferenceOnMovedOrigin( const ScAddress& rOldPos, const
         switch ((*p)->GetType())
         {
             case svSingleRef:
+            case svExternalSingleRef:
             {
                 ScToken* pToken = static_cast<ScToken*>(*p);
                 ScSingleRefData& rRef = pToken->GetSingleRef();
@@ -3477,6 +3478,7 @@ void ScTokenArray::AdjustReferenceOnMovedOrigin( const ScAddress& rOldPos, const
             }
             break;
             case svDoubleRef:
+            case svExternalDoubleRef:
             {
                 ScToken* pToken = static_cast<ScToken*>(*p);
                 ScComplexRefData& rRef = pToken->GetDoubleRef();


More information about the Libreoffice-commits mailing list