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, 50 insertions(+), 29 deletions(-)

New commits:
commit f1c247acd6b88db0f52c46517373a6fe81408d79
Author:     Noel Grandin <noel.gran...@collabora.co.uk>
AuthorDate: Mon Jul 22 12:00:06 2024 +0200
Commit:     Noel Grandin <noel.gran...@collabora.co.uk>
CommitDate: Mon Jul 22 13:17:07 2024 +0200

    Revert "improve perf of lcl_GetUniqueFlyName"
    
    This reverts commit a61128c95e324b096bf26fec5ad78e67567e0f82.
    
    Reason for revert: Causes trouble with UITests because the names of some 
objects are not predictable
    
    Change-Id: I6320efd694849542ae79f0dc67c15d35eedfb750
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/170742
    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 ba18eedd7ce0..a3fa61143214 100644
--- a/sw/inc/doc.hxx
+++ b/sw/inc/doc.hxx
@@ -306,7 +306,6 @@ 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;
 
@@ -759,7 +758,6 @@ 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 6343d69e63cd..451b90ce1206 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=\"Frame2\"><PARAGRAPH/></TEXT_FRAME>"_ustr,
+    CPPUNIT_ASSERT_EQUAL(u"<PARAGRAPH/><TEXT_FRAME 
name=\"Frame1\"><PARAGRAPH/></TEXT_FRAME>"_ustr,
                          collectText());
 }
 
diff --git a/sw/qa/uitest/ui/frmdlg/frmdlg.py b/sw/qa/uitest/ui/frmdlg/frmdlg.py
index db229f88bec4..a37062c1d392 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.Frame2.Size.Width, 
expected_mm100)
+                self.assertEqual(xComponent.TextFrames.Frame1.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.Frame2.LeftBorder.LineWidth, 0)
+            
self.assertEqual(xComponent.TextFrames.Frame1.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 6f00b9fbb6f1..9353610dcb96 100644
--- a/sw/source/core/doc/doclay.cxx
+++ b/sw/source/core/doc/doclay.cxx
@@ -1276,43 +1276,50 @@ SwFlyFrameFormat* SwDoc::InsertDrawLabel(
     return pNewFormat;
 }
 
-static bool lcl_checkNameUnique(const SdrObject& rObj, const OUString& 
rCmpName)
+static void lcl_collectUsedNums(std::vector<unsigned int>& rSetFlags, 
sal_Int32 nNmLen, std::u16string_view rName, std::u16string_view rCmpName)
 {
-    if (rCmpName == rObj.GetName())
-        return false;
+    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);
     // tdf#122487 take groups into account, iterate and recurse through their
     // contents for name collision check
     if (!rObj.IsGroupObject())
-        return true;
+        return;
 
     const SdrObjList* pSub(rObj.GetSubList());
     assert(pSub && "IsGroupObject is implemented as GetSubList != nullptr");
     for (const rtl::Reference<SdrObject>& pObj : *pSub)
     {
-        if (!lcl_checkNameUnique(*pObj, rCmpName))
-            return false;
+        lcl_collectUsedNums(rSetFlags, nNmLen, *pObj, rCmpName);
     }
-    return true;
 }
 
-static bool lcl_checkNameUnique(const SwDoc& rDoc, sal_uInt16 eType, const 
OUString& rCmpName)
+namespace
 {
-    for(sw::SpzFrameFormat* pFlyFormat: *rDoc.GetSpzFrameFormats())
+    int first_available_number(std::vector<unsigned int>& numbers)
     {
-        if (eType != pFlyFormat->Which())
-            continue;
-        if (eType == RES_DRAWFRMFMT)
+        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)
         {
-            const SdrObject *pObj = pFlyFormat->FindSdrObject();
-            if (pObj)
-                if (!lcl_checkNameUnique(*pObj, rCmpName))
-                    return false;
+            if (numbers[i] != i)
+                return i;
         }
 
-        if (pFlyFormat->GetName() == rCmpName)
-            return false;
+        return numbers.size();
     }
-    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)
@@ -1346,13 +1353,29 @@ static OUString lcl_GetUniqueFlyName(const SwDoc& rDoc, 
TranslateId pDefStrId, s
         return aTmp;
     }
 
-    OUString aBaseName(SwResId(pDefStrId));
-    for (;;)
+    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 aName = aBaseName + 
OUString::number(const_cast<SwDoc&>(rDoc).GetNextDefaultFlyNumber(eType));
-        if (lcl_checkNameUnique(rDoc, eType, aName))
-            return aName;
+        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);
     }
+
+    // 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