include/vcl/weld.hxx | 4 + sfx2/source/dialog/StyleList.cxx | 107 +++++++++++++++++++++++++-------------- vcl/inc/salvtables.hxx | 9 +-- vcl/source/app/salvtables.cxx | 4 - vcl/unx/gtk3/gtkinst.cxx | 3 - 5 files changed, 80 insertions(+), 47 deletions(-)
New commits: commit 7f42f031ed1b9f374f3fcba9c814dc5862492026 Author: Noel Grandin <noel.gran...@collabora.co.uk> AuthorDate: Thu Oct 10 09:39:14 2024 +0200 Commit: Noel Grandin <noel.gran...@collabora.co.uk> CommitDate: Wed Oct 16 07:38:45 2024 +0200 tdf#100894 speed up style tree creation by using bulk_insert_for_each() more aggressively. Reduces the open time from several minutes to 18s on my machine. I had to pass down a flag, because the gtk and the gen weld backends work differently, and the gen backend absolutely has to know up front if the inserter function is going to call set_text, otherwise it asserts in SvTreeListBox::SetEntryText Change-Id: I84750888c0a80f4041cfe024e6570dd94f6d09db Reviewed-on: https://gerrit.libreoffice.org/c/core/+/174757 Tested-by: Jenkins Reviewed-by: Noel Grandin <noel.gran...@collabora.co.uk> diff --git a/include/vcl/weld.hxx b/include/vcl/weld.hxx index 5988012528b0..c375a7e0c03b 100644 --- a/include/vcl/weld.hxx +++ b/include/vcl/weld.hxx @@ -1235,10 +1235,12 @@ public: // width will not be measured, and the fixed width used instead. Use // sparingly because wider text than the fixed width is clipped and cannot // be scrolled into view horizontally. + // @param bGoingToSetText needs to be true, if you plan to call set_text inside the insert func. virtual void bulk_insert_for_each(int nSourceCount, const std::function<void(TreeIter&, int nSourceIndex)>& func, const weld::TreeIter* pParent = nullptr, - const std::vector<int>* pFixedWidths = nullptr) + const std::vector<int>* pFixedWidths = nullptr, + bool bGoingToSetText = false) = 0; /* expanding on-demand node details diff --git a/sfx2/source/dialog/StyleList.cxx b/sfx2/source/dialog/StyleList.cxx index 84491f524197..775ebc8db551 100644 --- a/sfx2/source/dialog/StyleList.cxx +++ b/sfx2/source/dialog/StyleList.cxx @@ -707,8 +707,8 @@ static bool IsExpanded_Impl(const std::vector<OUString>& rEntries, std::u16strin return false; } -static void lcl_Insert(weld::TreeView& rTreeView, const OUString& rName, SfxStyleFamily eFam, - const weld::TreeIter* pParent, weld::TreeIter* pRet, SfxViewShell* pViewSh) +static void lcl_Update(weld::TreeView& rTreeView, weld::TreeIter& rIter, const OUString& rName, + SfxStyleFamily eFam, SfxViewShell* pViewSh) { Color aColor = ColorHash(rName); @@ -729,7 +729,8 @@ static void lcl_Insert(weld::TreeView& rTreeView, const OUString& rName, SfxStyl // don't show a color or number for default character style 'No Character Style' entry if (rName == sDefaultCharStyleUIName.value() /*"No Character Style"*/) { - rTreeView.insert(pParent, -1, &rName, &rName, nullptr, nullptr, false, pRet); + rTreeView.set_id(rIter, rName); + rTreeView.set_text(rIter, rName); return; } } @@ -746,32 +747,57 @@ static void lcl_Insert(weld::TreeView& rTreeView, const OUString& rName, SfxStyl xDevice->DrawText(aRect, OUString::number(nColor), DrawTextFlags::Center | DrawTextFlags::VCenter); - rTreeView.insert(pParent, -1, &rName, &rName, nullptr, xDevice.get(), false, pRet); + rTreeView.set_id(rIter, rName); + rTreeView.set_text(rIter, rName); + rTreeView.set_image(rIter, *xDevice); } -static void FillBox_Impl(weld::TreeView& rBox, StyleTree_Impl* pEntry, - const std::vector<OUString>& rEntries, SfxStyleFamily eStyleFamily, - const weld::TreeIter* pParent, bool blcl_insert, SfxViewShell* pViewShell, +static void FillBox_Impl(weld::TreeView& rBox, StyleTreeArr_Impl& rTreeArray, + SfxStyleFamily eStyleFamily, const weld::TreeIter* pParent, + bool blcl_insert, SfxViewShell* pViewShell, SfxStyleSheetBasePool* pStyleSheetPool) { - std::unique_ptr<weld::TreeIter> xResult = rBox.make_iterator(); - const OUString& rName = pEntry->getName(); - if (blcl_insert) - { - const SfxStyleSheetBase* pStyle = nullptr; - if (pStyleSheetPool) - pStyle = pStyleSheetPool->Find(rName, eStyleFamily); - if (pStyle && pStyle->IsUsed()) - lcl_Insert(rBox, rName, eStyleFamily, pParent, xResult.get(), pViewShell); - else - rBox.insert(pParent, -1, &rName, &rName, nullptr, nullptr, false, xResult.get()); - } + if (rTreeArray.empty()) + return; + rBox.bulk_insert_for_each(rTreeArray.size(), + [&rTreeArray, blcl_insert, pStyleSheetPool, eStyleFamily, &rBox, + pViewShell](weld::TreeIter& rIter, int i) { + StyleTree_Impl* pChildEntry = rTreeArray[i].get(); + const OUString& rChildName = pChildEntry->getName(); + if (blcl_insert) + { + const SfxStyleSheetBase* pStyle = nullptr; + if (pStyleSheetPool) + pStyle = pStyleSheetPool->Find(rChildName, eStyleFamily); + if (pStyle && pStyle->IsUsed()) + lcl_Update(rBox, rIter, rChildName, eStyleFamily, + pViewShell); + else + { + rBox.set_id(rIter, rChildName); + rBox.set_text(rIter, rChildName); + } + } + else + { + rBox.set_id(rIter, rChildName); + rBox.set_text(rIter, rChildName); + } + }, + pParent, nullptr, /*bGoingToSetText*/ true); + + std::unique_ptr<weld::TreeIter> xChildParentIter = rBox.make_iterator(pParent); + if (!pParent) + rBox.get_iter_first(*xChildParentIter); else - rBox.insert(pParent, -1, &rName, &rName, nullptr, nullptr, false, xResult.get()); - - for (size_t i = 0; i < pEntry->getChildren().size(); ++i) - FillBox_Impl(rBox, pEntry->getChildren()[i].get(), rEntries, eStyleFamily, xResult.get(), + rBox.iter_children(*xChildParentIter); + for (size_t i = 0; i < rTreeArray.size(); ++i) + { + if (i != 0) + rBox.iter_next_sibling(*xChildParentIter); + FillBox_Impl(rBox, rTreeArray[i]->getChildren(), eStyleFamily, xChildParentIter.get(), blcl_insert, pViewShell, pStyleSheetPool); + } } namespace SfxTemplate @@ -1076,12 +1102,9 @@ void StyleList::FillTreeBox(SfxStyleFamily eFam) && ((eFam == SfxStyleFamily::Para && m_bHighlightParaStyles) || (eFam == SfxStyleFamily::Char && m_bHighlightCharStyles)); + FillBox_Impl(*m_xTreeBox, aArr, eFam, nullptr, blcl_insert, pViewShell, m_pStyleSheetPool); for (sal_uInt16 i = 0; i < nCount; ++i) - { - FillBox_Impl(*m_xTreeBox, aArr[i].get(), aEntries, eFam, nullptr, blcl_insert, pViewShell, - m_pStyleSheetPool); aArr[i].reset(); - } m_xTreeBox->columns_autosize(); @@ -1267,25 +1290,33 @@ void StyleList::UpdateStyles(StyleFlags nFlags) } size_t nCount = aStrings.size(); - size_t nPos = 0; if (pViewShell && m_bModuleHasStylesHighlighterFeature && ((eFam == SfxStyleFamily::Para && m_bHighlightParaStyles) || (eFam == SfxStyleFamily::Char && m_bHighlightCharStyles))) { - for (nPos = 0; nPos < nCount; ++nPos) - { - pStyle = m_pStyleSheetPool->Find(aStrings[nPos], eFam); - if (pStyle && pStyle->IsUsed()) - lcl_Insert(*m_xFmtLb, aStrings[nPos], eFam, nullptr, nullptr, pViewShell); - else - m_xFmtLb->append(aStrings[nPos], aStrings[nPos]); - } + m_xFmtLb->bulk_insert_for_each( + nCount, + [this, &aStrings, eFam, pViewShell](weld::TreeIter& rIter, int nIdx) { + auto pChildStyle = m_pStyleSheetPool->Find(aStrings[nIdx], eFam); + if (pChildStyle && pChildStyle->IsUsed()) + lcl_Update(*m_xFmtLb, rIter, aStrings[nIdx], eFam, pViewShell); + else + { + m_xFmtLb->set_id(rIter, aStrings[nIdx]); + m_xFmtLb->set_text(rIter, aStrings[nIdx]); + } + }, + nullptr, nullptr, /*bGoingToSetText*/ true); } else { - for (nPos = 0; nPos < nCount; ++nPos) - m_xFmtLb->append(aStrings[nPos], aStrings[nPos]); + m_xFmtLb->bulk_insert_for_each(nCount, + [this, &aStrings](weld::TreeIter& rIter, int nIdx) { + m_xFmtLb->set_id(rIter, aStrings[nIdx]); + m_xFmtLb->set_text(rIter, aStrings[nIdx]); + }, + nullptr, nullptr, /*bGoingToSetText*/ true); } m_xFmtLb->columns_autosize(); diff --git a/vcl/inc/salvtables.hxx b/vcl/inc/salvtables.hxx index 01da5ed831f6..f7e577ab7808 100644 --- a/vcl/inc/salvtables.hxx +++ b/vcl/inc/salvtables.hxx @@ -1638,11 +1638,10 @@ public: virtual void insert_separator(int pos, const OUString& /*rId*/) override; - virtual void - bulk_insert_for_each(int nSourceCount, - const std::function<void(weld::TreeIter&, int nSourceIndex)>& func, - const weld::TreeIter* pParent = nullptr, - const std::vector<int>* pFixedWidths = nullptr) override; + virtual void bulk_insert_for_each( + int nSourceCount, const std::function<void(weld::TreeIter&, int nSourceIndex)>& func, + const weld::TreeIter* pParent = nullptr, const std::vector<int>* pFixedWidths = nullptr, + bool bGoingToSetText = false) override; virtual void set_font_color(int pos, const Color& rColor) override; diff --git a/vcl/source/app/salvtables.cxx b/vcl/source/app/salvtables.cxx index 2f1e5bb7a996..3c3bc90be2df 100644 --- a/vcl/source/app/salvtables.cxx +++ b/vcl/source/app/salvtables.cxx @@ -4041,7 +4041,7 @@ void SalInstanceTreeView::insert_separator(int pos, const OUString& /*rId*/) void SalInstanceTreeView::bulk_insert_for_each( int nSourceCount, const std::function<void(weld::TreeIter&, int nSourceIndex)>& func, - const weld::TreeIter* pParent, const std::vector<int>* pFixedWidths) + const weld::TreeIter* pParent, const std::vector<int>* pFixedWidths, bool bGoingToSetText) { const SalInstanceTreeIter* pVclIter = static_cast<const SalInstanceTreeIter*>(pParent); SvTreeListEntry* pVclParent = pVclIter ? pVclIter->iter : nullptr; @@ -4068,7 +4068,7 @@ void SalInstanceTreeView::bulk_insert_for_each( for (int i = 0; i < nSourceCount; ++i) { aVclIter.iter = new SvTreeListEntry; - if (bHasAutoCheckButton) + if (bHasAutoCheckButton || bGoingToSetText) AddStringItem(aVclIter.iter, u""_ustr, -1); aVclIter.iter->AddItem(std::make_unique<SvLBoxContextBmp>(aDummy, aDummy, false)); m_xTreeView->Insert(aVclIter.iter, pVclParent, TREELIST_APPEND); diff --git a/vcl/unx/gtk3/gtkinst.cxx b/vcl/unx/gtk3/gtkinst.cxx index 8ebd7625b259..c7a460656f07 100644 --- a/vcl/unx/gtk3/gtkinst.cxx +++ b/vcl/unx/gtk3/gtkinst.cxx @@ -15320,7 +15320,8 @@ public: virtual void bulk_insert_for_each(int nSourceCount, const std::function<void(weld::TreeIter&, int nSourceIndex)>& func, const weld::TreeIter* pParent, - const std::vector<int>* pFixedWidths) override + const std::vector<int>* pFixedWidths, + bool /*bGoingToSetText*/) override { GtkInstanceTreeIter* pGtkIter = const_cast<GtkInstanceTreeIter*>(static_cast<const GtkInstanceTreeIter*>(pParent));