[Libreoffice-commits] core.git: sc/inc sc/source

Eike Rathke erack at redhat.com
Tue Jul 26 14:34:59 UTC 2016


 sc/inc/document.hxx                 |    4 +++
 sc/inc/rangenam.hxx                 |   20 +++++++++++----
 sc/source/core/data/document10.cxx  |   48 ++++++++++++++++++++++++++++++++++++
 sc/source/core/tool/rangenam.cxx    |   23 +++++++++++------
 sc/source/ui/docshell/docfunc.cxx   |    2 -
 sc/source/ui/namedlg/namedefdlg.cxx |    2 -
 sc/source/ui/namedlg/namedlg.cxx    |    7 ++++-
 sc/source/ui/undo/undorangename.cxx |    2 -
 8 files changed, 91 insertions(+), 17 deletions(-)

New commits:
commit 9710fd565f17278dc5e5ee645b3924544a8c4235
Author: Eike Rathke <erack at redhat.com>
Date:   Tue Jul 26 16:32:15 2016 +0200

    Resolves: tdf#87474 handle renaming of named expressions/ranges in formulas
    
    Change-Id: If82b62505624c3c259371fa37de1994a94bbceb5

diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx
index 5d03418..eccc49c 100644
--- a/sc/inc/document.hxx
+++ b/sc/inc/document.hxx
@@ -648,8 +648,12 @@ public:
     /**
      * Call this immediately before updating all named ranges.
      */
+    SC_DLLPUBLIC void PreprocessAllRangeNamesUpdate( const std::map<OUString, std::unique_ptr<ScRangeName>>& rRangeMap );
     SC_DLLPUBLIC void PreprocessRangeNameUpdate();
     SC_DLLPUBLIC void PreprocessDBDataUpdate();
+    /**
+     * Call this immediately after updating named ranges.
+     */
     SC_DLLPUBLIC void CompileHybridFormula();
 
     /**
diff --git a/sc/inc/rangenam.hxx b/sc/inc/rangenam.hxx
index a7a5aa8..e21c5b3 100644
--- a/sc/inc/rangenam.hxx
+++ b/sc/inc/rangenam.hxx
@@ -60,8 +60,9 @@ public:
     };
 
 private:
-    OUString   aName;
-    OUString   aUpperName;     // #i62977# for faster searching (aName is never modified after ctor)
+    OUString        aName;
+    OUString        aUpperName; // #i62977# for faster searching (aName is never modified after ctor)
+    OUString        maNewName;  ///< used for formulas after changing names in the dialog
     ScTokenArray*   pCode;
     ScAddress       aPos;
     Type            eType;
@@ -106,13 +107,15 @@ public:
 
     bool            operator== (const ScRangeData& rData) const;
 
-    void            GetName( OUString& rName ) const  { rName = aName; }
-    const OUString&   GetName() const           { return aName; }
+    void            GetName( OUString& rName ) const  { rName = maNewName.isEmpty() ? aName : maNewName; }
+    const OUString&   GetName() const           { return maNewName.isEmpty() ? aName : maNewName; }
     const OUString&   GetUpperName() const      { return aUpperName; }
     const ScAddress&  GetPos() const                  { return aPos; }
     // The index has to be unique. If index=0 a new index value is assigned.
     void            SetIndex( sal_uInt16 nInd )         { nIndex = nInd; }
     sal_uInt16      GetIndex() const                { return nIndex; }
+    /// Does not change the name, but sets maNewName for formula update after dialog.
+    void            SetNewName( const OUString& rNewName )  { maNewName = rNewName; }
     ScTokenArray*   GetCode()                       { return pCode; }
     SC_DLLPUBLIC void   SetCode( ScTokenArray& );
     const ScTokenArray* GetCode() const             { return pCode; }
@@ -244,8 +247,15 @@ public:
         @ATTENTION: The underlying ::std::map<std::unique_ptr>::insert(p) takes
         ownership of p and if it can't insert it deletes the object! So, if
         this insert here returns false the object where p pointed to is gone!
+
+        @param  bReuseFreeIndex
+                If the ScRangeData p points to has an index value of 0:
+                If `TRUE` then reuse a free index slot if available.
+                If `FALSE` then assign a new index slot. The Manage Names
+                dialog uses this so that deleting and adding ranges in the same
+                run is guaranteed to not reuse previously assigned indexes.
      */
-    SC_DLLPUBLIC bool insert(ScRangeData* p);
+    SC_DLLPUBLIC bool insert( ScRangeData* p, bool bReuseFreeIndex = true );
 
     void erase(const ScRangeData& r);
     void erase(const OUString& rName);
diff --git a/sc/source/core/data/document10.cxx b/sc/source/core/data/document10.cxx
index 0530566..be9c855 100644
--- a/sc/source/core/data/document10.cxx
+++ b/sc/source/core/data/document10.cxx
@@ -227,6 +227,54 @@ void ScDocument::SwapNonEmpty( sc::TableValues& rValues )
     aEndCxt.purgeEmptyBroadcasters();
 }
 
+void ScDocument::PreprocessAllRangeNamesUpdate( const std::map<OUString, std::unique_ptr<ScRangeName>>& rRangeMap )
+{
+    // Update all existing names with new names.
+    // The prerequisites are that the name dialog preserves ScRangeData index
+    // for changes and does not reuse free index slots for new names.
+    // ScDocument::SetAllRangeNames() hereafter then will replace the
+    // ScRangeName containers of ScRangeData instances with empty
+    // ScRangeData::maNewName.
+    std::map<OUString, ScRangeName*> aRangeNameMap;
+    GetRangeNameMap( aRangeNameMap);
+    for (const auto& itTab : aRangeNameMap)
+    {
+        ScRangeName* pOldRangeNames = itTab.second;
+        if (!pOldRangeNames)
+            continue;
+
+        const auto& itNewTab( rRangeMap.find( itTab.first));
+        if (itNewTab == rRangeMap.end())
+            continue;
+
+        const ScRangeName* pNewRangeNames = itNewTab->second.get();
+        if (!pNewRangeNames)
+            continue;
+
+        for (ScRangeName::iterator it( pOldRangeNames->begin()), itEnd( pOldRangeNames->end());
+                it != itEnd; ++it)
+        {
+            ScRangeData* pOldData = it->second.get();
+            if (!pOldData)
+                continue;
+
+            const ScRangeData* pNewData = pNewRangeNames->findByIndex( pOldData->GetIndex());
+            if (pNewData)
+                pOldData->SetNewName( pNewData->GetName());
+        }
+    }
+
+    sc::EndListeningContext aEndListenCxt(*this);
+    sc::CompileFormulaContext aCompileCxt(this);
+
+    TableContainer::iterator it = maTabs.begin(), itEnd = maTabs.end();
+    for (; it != itEnd; ++it)
+    {
+        ScTable* p = *it;
+        p->PreprocessRangeNameUpdate(aEndListenCxt, aCompileCxt);
+    }
+}
+
 void ScDocument::PreprocessRangeNameUpdate()
 {
     sc::EndListeningContext aEndListenCxt(*this);
diff --git a/sc/source/core/tool/rangenam.cxx b/sc/source/core/tool/rangenam.cxx
index 7626e16..19d403d 100644
--- a/sc/source/core/tool/rangenam.cxx
+++ b/sc/source/core/tool/rangenam.cxx
@@ -831,7 +831,7 @@ bool ScRangeName::empty() const
     return m_Data.empty();
 }
 
-bool ScRangeName::insert(ScRangeData* p)
+bool ScRangeName::insert( ScRangeData* p, bool bReuseFreeIndex )
 {
     if (!p)
         return false;
@@ -839,17 +839,24 @@ bool ScRangeName::insert(ScRangeData* p)
     if (!p->GetIndex())
     {
         // Assign a new index.  An index must be unique and is never 0.
-        IndexDataType::iterator itr = std::find(
-            maIndexToData.begin(), maIndexToData.end(), static_cast<ScRangeData*>(nullptr));
-        if (itr != maIndexToData.end())
+        if (bReuseFreeIndex)
         {
-            // Empty slot exists.  Re-use it.
-            size_t nPos = std::distance(maIndexToData.begin(), itr);
-            p->SetIndex(nPos + 1);
+            IndexDataType::iterator itr = std::find(
+                    maIndexToData.begin(), maIndexToData.end(), static_cast<ScRangeData*>(nullptr));
+            if (itr != maIndexToData.end())
+            {
+                // Empty slot exists.  Re-use it.
+                size_t nPos = std::distance(maIndexToData.begin(), itr);
+                p->SetIndex(nPos + 1);
+            }
+            else
+                // No empty slot.  Append it to the end.
+                p->SetIndex(maIndexToData.size() + 1);
         }
         else
-            // No empty slot.  Append it to the end.
+        {
             p->SetIndex(maIndexToData.size() + 1);
+        }
     }
 
     OUString aName(p->GetUpperName());
diff --git a/sc/source/ui/docshell/docfunc.cxx b/sc/source/ui/docshell/docfunc.cxx
index d2b1cc8..1f4ed8d 100644
--- a/sc/source/ui/docshell/docfunc.cxx
+++ b/sc/source/ui/docshell/docfunc.cxx
@@ -4908,7 +4908,7 @@ void ScDocFunc::ModifyAllRangeNames(const std::map<OUString, std::unique_ptr<ScR
                 new ScUndoAllRangeNames(&rDocShell, aOldRangeMap, rRangeMap));
     }
 
-    rDoc.PreprocessRangeNameUpdate();
+    rDoc.PreprocessAllRangeNamesUpdate(rRangeMap);
     rDoc.SetAllRangeNames(rRangeMap);
     rDoc.CompileHybridFormula();
 
diff --git a/sc/source/ui/namedlg/namedefdlg.cxx b/sc/source/ui/namedlg/namedefdlg.cxx
index bb65077..73a293b 100644
--- a/sc/source/ui/namedlg/namedefdlg.cxx
+++ b/sc/source/ui/namedlg/namedefdlg.cxx
@@ -235,7 +235,7 @@ void ScNameDefDlg::AddPushed()
             // aExpression valid?
             if ( 0 == pNewEntry->GetErrCode() )
             {
-                if ( !pRangeName->insert( pNewEntry ) )
+                if ( !pRangeName->insert( pNewEntry, false /*bReuseFreeIndex*/ ) )
                     pNewEntry = nullptr;
 
                 if (mbUndo)
diff --git a/sc/source/ui/namedlg/namedlg.cxx b/sc/source/ui/namedlg/namedlg.cxx
index 4f0164e..ba3d9cd 100644
--- a/sc/source/ui/namedlg/namedlg.cxx
+++ b/sc/source/ui/namedlg/namedlg.cxx
@@ -405,6 +405,10 @@ void ScNameDlg::NameModified()
     // be safe and check for range data
     if (pData)
     {
+        // Assign new index (0) only if the scope is changed, else keep the
+        // existing index.
+        sal_uInt16 nIndex = (aNewScope != aOldScope ? 0 : pData->GetIndex());
+
         pOldRangeName->erase(*pData);
         mbNeedUpdate = false;
         m_pRangeManagerTable->DeleteSelectedEntries();
@@ -416,7 +420,8 @@ void ScNameDlg::NameModified()
 
         ScRangeData* pNewEntry = new ScRangeData( mpDoc, aNewName, aExpr,
                 maCursorPos, nType);
-        pNewRangeName->insert(pNewEntry);
+        pNewEntry->SetIndex( nIndex);
+        pNewRangeName->insert(pNewEntry, false /*bReuseFreeIndex*/);
         aLine.aName = aNewName;
         aLine.aExpression = aExpr;
         aLine.aScope = aNewScope;
diff --git a/sc/source/ui/undo/undorangename.cxx b/sc/source/ui/undo/undorangename.cxx
index eb42eb4..f775269 100644
--- a/sc/source/ui/undo/undorangename.cxx
+++ b/sc/source/ui/undo/undorangename.cxx
@@ -70,7 +70,7 @@ void ScUndoAllRangeNames::DoChange(const std::map<OUString, std::unique_ptr<ScRa
 {
     ScDocument& rDoc = pDocShell->GetDocument();
 
-    rDoc.PreprocessRangeNameUpdate();
+    rDoc.PreprocessAllRangeNamesUpdate(rNames);
     rDoc.SetAllRangeNames(rNames);
     rDoc.CompileHybridFormula();
 


More information about the Libreoffice-commits mailing list