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));
 

Reply via email to