sw/inc/doc.hxx                         |    2 
 sw/qa/extras/accessibility/dialogs.cxx |    2 
 sw/qa/uitest/ui/frmdlg/frmdlg.py       |    4 -
 sw/source/core/doc/doclay.cxx          |   71 +++++++++++----------------------
 4 files changed, 29 insertions(+), 50 deletions(-)

New commits:
commit a61128c95e324b096bf26fec5ad78e67567e0f82
Author:     Noel Grandin <noel.gran...@collabora.co.uk>
AuthorDate: Sat Jul 20 15:43:49 2024 +0200
Commit:     Noel Grandin <noel.gran...@collabora.co.uk>
CommitDate: Sun Jul 21 12:00:36 2024 +0200

    improve perf of lcl_GetUniqueFlyName
    
    reduces the load time of a complex document from 18s to 16s
    
    Change-Id: I5382e27bf1b6beaf7276ef46f10d43d5bf9822d6
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/170795
    Tested-by: Jenkins
    Reviewed-by: Noel Grandin <noel.gran...@collabora.co.uk>

diff --git a/sw/inc/doc.hxx b/sw/inc/doc.hxx
index a3fa61143214..ba18eedd7ce0 100644
--- a/sw/inc/doc.hxx
+++ b/sw/inc/doc.hxx
@@ -306,6 +306,7 @@ private:
 
     sal_uInt32  mnRsid;              //< current session ID of the document
     sal_uInt32  mnRsidRoot;          //< session ID when the document was 
created
+    std::unordered_map<sal_uInt16, sal_Int32> maDefaultFlyNameCounters; //< 
counters used to generate unique fly names
 
     oslInterlockedCount  mReferenceCount;
 
@@ -758,6 +759,7 @@ public:
     // LayoutFormats (frames, DrawObjects), sometimes const sometimes not
     const sw::FrameFormats<sw::SpzFrameFormat*>* GetSpzFrameFormats() const   
{ return mpSpzFrameFormatTable.get(); }
           sw::FrameFormats<sw::SpzFrameFormat*>* GetSpzFrameFormats()         
{ return mpSpzFrameFormatTable.get(); }
+    sal_Int32 GetNextDefaultFlyNumber(sal_uInt16 nWhich) { return 
++maDefaultFlyNameCounters[nWhich]; }
 
     const SwFrameFormat *GetDfltFrameFormat() const   { return 
mpDfltFrameFormat.get(); }
           SwFrameFormat *GetDfltFrameFormat()         { return 
mpDfltFrameFormat.get(); }
diff --git a/sw/qa/extras/accessibility/dialogs.cxx 
b/sw/qa/extras/accessibility/dialogs.cxx
index 451b90ce1206..6343d69e63cd 100644
--- a/sw/qa/extras/accessibility/dialogs.cxx
+++ b/sw/qa/extras/accessibility/dialogs.cxx
@@ -186,7 +186,7 @@ CPPUNIT_TEST_FIXTURE(test::SwAccessibleTestBase, 
BasicTestFrameDialog)
     CPPUNIT_ASSERT(activateMenuItem(u"Insert", u"Frame", u"Frame..."));
     CPPUNIT_ASSERT(dialogWaiter->waitEndDialog());
 
-    CPPUNIT_ASSERT_EQUAL(u"<PARAGRAPH/><TEXT_FRAME 
name=\"Frame1\"><PARAGRAPH/></TEXT_FRAME>"_ustr,
+    CPPUNIT_ASSERT_EQUAL(u"<PARAGRAPH/><TEXT_FRAME 
name=\"Frame2\"><PARAGRAPH/></TEXT_FRAME>"_ustr,
                          collectText());
 }
 
diff --git a/sw/qa/uitest/ui/frmdlg/frmdlg.py b/sw/qa/uitest/ui/frmdlg/frmdlg.py
index a37062c1d392..db229f88bec4 100644
--- a/sw/qa/uitest/ui/frmdlg/frmdlg.py
+++ b/sw/qa/uitest/ui/frmdlg/frmdlg.py
@@ -78,7 +78,7 @@ class Test(UITestCase):
                 # Without the accompanying fix in place, this test would have 
failed with:
                 # AssertionError: 0 != 2000.0
                 # i.e. the width was empty instead of the size from the UI.
-                self.assertEqual(xComponent.TextFrames.Frame1.Size.Width, 
expected_mm100)
+                self.assertEqual(xComponent.TextFrames.Frame2.Size.Width, 
expected_mm100)
 
     def test_insert_floating_table(self):
         with self.ui_test.create_doc_in_start_center("writer") as xComponent:
@@ -101,7 +101,7 @@ class Test(UITestCase):
             # Without the accompanying fix in place, this test would have 
failed with:
             # AssertionError: 2 != 0
             # i.e. the frame had a border by default when the table already 
had its own border.
-            
self.assertEqual(xComponent.TextFrames.Frame1.LeftBorder.LineWidth, 0)
+            
self.assertEqual(xComponent.TextFrames.Frame2.LeftBorder.LineWidth, 0)
 
     def test_insert_simple_frame(self):
         # Given a Writer document:
diff --git a/sw/source/core/doc/doclay.cxx b/sw/source/core/doc/doclay.cxx
index 9353610dcb96..6f00b9fbb6f1 100644
--- a/sw/source/core/doc/doclay.cxx
+++ b/sw/source/core/doc/doclay.cxx
@@ -1276,50 +1276,43 @@ SwFlyFrameFormat* SwDoc::InsertDrawLabel(
     return pNewFormat;
 }
 
-static void lcl_collectUsedNums(std::vector<unsigned int>& rSetFlags, 
sal_Int32 nNmLen, std::u16string_view rName, std::u16string_view rCmpName)
+static bool lcl_checkNameUnique(const SdrObject& rObj, const OUString& 
rCmpName)
 {
-    if (o3tl::starts_with(rName, rCmpName))
-    {
-        // Only get and set the Flag
-        const sal_Int32 nNum = o3tl::toInt32(rName.substr(nNmLen)) - 1;
-        if (nNum >= 0)
-            rSetFlags.push_back(nNum);
-    }
-}
-
-static void lcl_collectUsedNums(std::vector<unsigned int>& rSetFlags, 
sal_Int32 nNmLen, const SdrObject& rObj, const OUString& rCmpName)
-{
-    OUString sName = rObj.GetName();
-    lcl_collectUsedNums(rSetFlags, nNmLen, sName, rCmpName);
+    if (rCmpName == rObj.GetName())
+        return false;
     // tdf#122487 take groups into account, iterate and recurse through their
     // contents for name collision check
     if (!rObj.IsGroupObject())
-        return;
+        return true;
 
     const SdrObjList* pSub(rObj.GetSubList());
     assert(pSub && "IsGroupObject is implemented as GetSubList != nullptr");
     for (const rtl::Reference<SdrObject>& pObj : *pSub)
     {
-        lcl_collectUsedNums(rSetFlags, nNmLen, *pObj, rCmpName);
+        if (!lcl_checkNameUnique(*pObj, rCmpName))
+            return false;
     }
+    return true;
 }
 
-namespace
+static bool lcl_checkNameUnique(const SwDoc& rDoc, sal_uInt16 eType, const 
OUString& rCmpName)
 {
-    int first_available_number(std::vector<unsigned int>& numbers)
+    for(sw::SpzFrameFormat* pFlyFormat: *rDoc.GetSpzFrameFormats())
     {
-        std::sort(numbers.begin(), numbers.end());
-        auto last = std::unique(numbers.begin(), numbers.end());
-        numbers.erase(last, numbers.end());
-
-        for (size_t i = 0; i < numbers.size(); ++i)
+        if (eType != pFlyFormat->Which())
+            continue;
+        if (eType == RES_DRAWFRMFMT)
         {
-            if (numbers[i] != i)
-                return i;
+            const SdrObject *pObj = pFlyFormat->FindSdrObject();
+            if (pObj)
+                if (!lcl_checkNameUnique(*pObj, rCmpName))
+                    return false;
         }
 
-        return numbers.size();
+        if (pFlyFormat->GetName() == rCmpName)
+            return false;
     }
+    return true;
 }
 
 static OUString lcl_GetUniqueFlyName(const SwDoc& rDoc, TranslateId pDefStrId, 
sal_uInt16 eType, std::u16string_view rPrefix = std::u16string_view(), 
SwNodeType nNdTyp = SwNodeType::NONE)
@@ -1353,29 +1346,13 @@ static OUString lcl_GetUniqueFlyName(const SwDoc& rDoc, 
TranslateId pDefStrId, s
         return aTmp;
     }
 
-    OUString aName(SwResId(pDefStrId));
-    sal_Int32 nNmLen = aName.getLength();
-
-    std::vector<unsigned int> aUsedNums;
-    aUsedNums.reserve(rDoc.GetSpzFrameFormats()->size());
-
-    for(sw::SpzFrameFormat* pFlyFormat: *rDoc.GetSpzFrameFormats())
+    OUString aBaseName(SwResId(pDefStrId));
+    for (;;)
     {
-        if (eType != pFlyFormat->Which())
-            continue;
-        if (eType == RES_DRAWFRMFMT)
-        {
-            const SdrObject *pObj = pFlyFormat->FindSdrObject();
-            if (pObj)
-                lcl_collectUsedNums(aUsedNums, nNmLen, *pObj, aName);
-        }
-
-        lcl_collectUsedNums(aUsedNums, nNmLen, pFlyFormat->GetName(), aName);
+        OUString aName = aBaseName + 
OUString::number(const_cast<SwDoc&>(rDoc).GetNextDefaultFlyNumber(eType));
+        if (lcl_checkNameUnique(rDoc, eType, aName))
+            return aName;
     }
-
-    // All numbers are flagged accordingly, so determine the right one
-    auto nNum = first_available_number(aUsedNums) + 1;
-    return aName + OUString::number(nNum);
 }
 
 OUString SwDoc::GetUniqueGrfName(std::u16string_view rPrefix) const

Reply via email to