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