sw/source/uibase/utlui/content.cxx |  287 +++++++++++++++++--------------------
 1 file changed, 136 insertions(+), 151 deletions(-)

New commits:
commit 7270ed7b81c12c8ba2e57b1a0d2ae084f8489d61
Author:     Jim Raykowski <rayk...@gmail.com>
AuthorDate: Sun Dec 5 21:31:59 2021 -0900
Commit:     Jim Raykowski <rayk...@gmail.com>
CommitDate: Sat Jan 22 09:30:36 2022 +0100

    SwNavigator: revamp SwContentType::HasContentChanged function
    
    Effort here is to improve function performace and understanding by
    restructuring code and providing code intended purpose comments. Non
    in-depth testing shows modest improvement in function speed for
    documents with large amounts of content fill in the Navigator.
    
    Change-Id: Iedf53ef8e759c848c417d9a390fb6422d4896794
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/126467
    Tested-by: Jenkins
    Reviewed-by: Jim Raykowski <rayk...@gmail.com>

diff --git a/sw/source/uibase/utlui/content.cxx 
b/sw/source/uibase/utlui/content.cxx
index 650c9cdb2686..517b0a658814 100644
--- a/sw/source/uibase/utlui/content.cxx
+++ b/sw/source/uibase/utlui/content.cxx
@@ -703,9 +703,8 @@ void SwContentType::FillMemberList(bool* 
pbLevelOrVisibilityChanged)
                 m_pMember->insert(std::move(pCnt));
             }
 
-            if (nullptr != pbLevelOrVisibilityChanged)
+            if (pOldMember && nullptr != pbLevelOrVisibilityChanged)
             {
-                assert(pOldMember);
                 // need to check visibility (and equal entry number) after
                 // creation due to a sorted list being used here (before,
                 // entries with same index were compared already at creation
@@ -756,9 +755,8 @@ void SwContentType::FillMemberList(bool* 
pbLevelOrVisibilityChanged)
                 m_pMember->insert(std::unique_ptr<SwContent>(pCnt));
             }
 
-            if(nullptr != pbLevelOrVisibilityChanged)
+            if (pOldMember && nullptr != pbLevelOrVisibilityChanged)
             {
-                assert(pOldMember);
                 // need to check visibility (and equal entry number) after
                 // creation due to a sorted list being used here (before,
                 // entries with same index were compared already at creation
@@ -932,9 +930,8 @@ void SwContentType::FillMemberList(bool* 
pbLevelOrVisibilityChanged)
                     m_pMember->insert(std::move(pCnt));
                 }
 
-                if(nullptr != pbLevelOrVisibilityChanged)
+                if (pOldMember && nullptr != pbLevelOrVisibilityChanged)
                 {
-                    assert(pOldMember);
                     // need to check visibility (and equal entry number) after
                     // creation due to a sorted list being used here (before,
                     // entries with same index were compared already at 
creation
@@ -1045,9 +1042,8 @@ void SwContentType::FillMemberList(bool* 
pbLevelOrVisibilityChanged)
                     }
                 }
 
-                if (nullptr != pbLevelOrVisibilityChanged)
+                if (pOldMember && nullptr != pbLevelOrVisibilityChanged)
                 {
-                    assert(pOldMember);
                     // need to check visibility (and equal entry number) after
                     // creation due to a sorted list being used here (before,
                     // entries with same index were compared already at 
creation
@@ -2806,11 +2802,6 @@ bool SwContentTree::HasContentChanged()
 //  at the same time. Once a difference occurs it will be only replenished
 //  no longer checked. Finally, the box is filled again.
 
-    // bVisibilityChanged gets set to true if some element, like a section,
-    // changed visibility and should have its name rerendered with a new
-    // grayed-out state
-    bool bVisibilityChanged = false;
-
     if (State::HIDDEN == m_eState)
     {
         for(ContentTypeId i : o3tl::enumrange<ContentTypeId>())
@@ -2818,190 +2809,184 @@ bool SwContentTree::HasContentChanged()
             if(m_aActiveContentArr[i])
                 m_aActiveContentArr[i]->Invalidate();
         }
+        return false;
     }
+
     // root content navigation view
-    else if(m_bIsRoot)
+    if(m_bIsRoot)
     {
         std::unique_ptr<weld::TreeIter> 
xRootEntry(m_xTreeView->make_iterator());
         if (!m_xTreeView->get_iter_first(*xRootEntry))
-            bContentChanged = true;
-        else
+            return true;
+
+        
assert(dynamic_cast<SwContentType*>(reinterpret_cast<SwTypeNumber*>(m_xTreeView->get_id(*xRootEntry).toInt64())));
+        const ContentTypeId nType = 
reinterpret_cast<SwContentType*>(m_xTreeView->get_id(*xRootEntry).toInt64())->GetType();
+        SwContentType* pArrType = m_aActiveContentArr[nType].get();
+        assert(OUString::number(reinterpret_cast<sal_Int64>(pArrType)) == 
m_xTreeView->get_id(*xRootEntry));
+        if (!pArrType)
+            return true;
+
+        pArrType->FillMemberList(&bContentChanged);
+        if (bContentChanged)
+            return true;
+
+        // FillMemberList tests if member count in old member array equals 
member count in new
+        // member array. Test here for member count difference between array 
and tree.
+        const size_t nChildCount = GetChildCount(*xRootEntry);
+        if (nChildCount != pArrType->GetMemberCount())
+            return true;
+
+        std::unique_ptr<weld::TreeIter> 
xEntry(m_xTreeView->make_iterator(xRootEntry.get()));
+        for (size_t j = 0; j < nChildCount; ++j)
         {
-            
assert(dynamic_cast<SwContentType*>(reinterpret_cast<SwTypeNumber*>(m_xTreeView->get_id(*xRootEntry).toInt64())));
-            const ContentTypeId nType = 
reinterpret_cast<SwContentType*>(m_xTreeView->get_id(*xRootEntry).toInt64())->GetType();
-            SwContentType* pArrType = m_aActiveContentArr[nType].get();
-            if (!pArrType)
-                bContentChanged = true;
-            else
+            if (!m_xTreeView->iter_next(*xEntry))
             {
-                // start check if first selected outline level has changed
-                bool bCheckChanged = m_nRootType == ContentTypeId::OUTLINE && 
!m_xTreeView->has_focus();
-                if (bCheckChanged)
-                {
-                    std::unique_ptr<weld::TreeIter> 
xFirstSel(m_xTreeView->make_iterator());
-                    bool bFirstSel = 
m_xTreeView->get_selected(xFirstSel.get());
-                    if (bFirstSel && lcl_IsContent(*xFirstSel, *m_xTreeView))
-                    {
-                        
assert(dynamic_cast<SwOutlineContent*>(reinterpret_cast<SwTypeNumber*>(m_xTreeView->get_id(*xFirstSel).toInt64())));
-                        const auto nSelLevel = 
reinterpret_cast<SwOutlineContent*>(m_xTreeView->get_id(*xFirstSel).toInt64())->GetOutlineLevel();
-                        SwWrtShell* pSh = GetWrtShell();
-                        const SwOutlineNodes::size_type nOutlinePos = 
pSh->GetOutlinePos(MAXLEVEL);
-                        if (nOutlinePos != SwOutlineNodes::npos && 
pSh->getIDocumentOutlineNodesAccess()->getOutlineLevel(nOutlinePos) != 
nSelLevel)
-                            bContentChanged = true;
-                    }
-                }
-                // end check if first selected outline level has changed
+                SAL_WARN("sw.ui", "unexpected missing entry");
+                return true;
+            }
 
-                pArrType->Init(&bVisibilityChanged);
-                pArrType->FillMemberList();
-                OUString 
sId(OUString::number(reinterpret_cast<sal_Int64>(pArrType)));
-                m_xTreeView->set_id(*xRootEntry, sId);
-                if (!bContentChanged)
-                {
-                    const size_t nChildCount = GetChildCount(*xRootEntry);
-                    if (nChildCount != pArrType->GetMemberCount())
-                        bContentChanged = true;
-                    else
-                    {
-                        std::unique_ptr<weld::TreeIter> 
xEntry(m_xTreeView->make_iterator(xRootEntry.get()));
-                        for (size_t j = 0; j < nChildCount; ++j)
-                        {
-                            if (!m_xTreeView->iter_next(*xEntry))
-                            {
-                                SAL_WARN("sw.ui", "unexpected missing entry");
-                                break;
-                            }
-                            const SwContent* pCnt = pArrType->GetMember(j);
-                            OUString 
sSubId(OUString::number(reinterpret_cast<sal_Int64>(pCnt)));
-                            m_xTreeView->set_id(*xEntry, sSubId);
-                            OUString sEntryText = 
m_xTreeView->get_text(*xEntry);
-                            if( sEntryText != pCnt->GetName() &&
-                                !(sEntryText == m_sSpace && 
pCnt->GetName().isEmpty()))
-                                bContentChanged = true;
-                        }
-                    }
-                }
+            // FillMemberList clears the content type member list and refills 
with new data.
+            // Treeview entry user data is set here to the string 
representation of the pointer to
+            // the member data in the array. The Display function will clear 
and recreate the
+            // treeview from the content type member arrays if content change 
is detected.
+            const SwContent* pCnt = pArrType->GetMember(j);
+            OUString 
sSubId(OUString::number(reinterpret_cast<sal_Int64>(pCnt)));
+            m_xTreeView->set_id(*xEntry, sSubId);
+
+            OUString sEntryText = m_xTreeView->get_text(*xEntry);
+            if (sEntryText != pCnt->GetName() &&
+                    !(sEntryText == m_sSpace && pCnt->GetName().isEmpty()))
+            {
+                return true;
             }
         }
     }
     // all content navigation view
     else
     {
+        // Fill member list for each content type and check for content 
change. If content change
+        // is detected only fill member lists for remaining content types. The 
Display function
+        // will clear and recreate the treeview from the content type member 
arrays if content has
+        // changed.
         std::unique_ptr<weld::TreeIter> xEntry(m_xTreeView->make_iterator());
-        bool bEntry = m_xTreeView->get_iter_first(*xEntry);
-        while (bEntry)
+
+        // lambda function to find the next content type entry
+        auto lcl_nextContentTypeEntry = [this, &xEntry](){
+            while (m_xTreeView->get_iter_depth(*xEntry))
+                m_xTreeView->iter_parent(*xEntry);
+            return m_xTreeView->iter_next_sibling(*xEntry);
+            };
+
+        for (bool bEntry = m_xTreeView->get_iter_first(*xEntry); bEntry;
+             bEntry = lcl_nextContentTypeEntry())
         {
-            bool bNext = true; // at least a next must be
             
assert(dynamic_cast<SwContentType*>(reinterpret_cast<SwTypeNumber*>(m_xTreeView->get_id(*xEntry).toInt64())));
             SwContentType* pCntType = 
reinterpret_cast<SwContentType*>(m_xTreeView->get_id(*xEntry).toInt64());
             const size_t nCntCount = pCntType->GetMemberCount();
             const ContentTypeId nType = pCntType->GetType();
             SwContentType* pArrType = m_aActiveContentArr[nType].get();
+            assert(OUString::number(reinterpret_cast<sal_Int64>(pArrType)) == 
m_xTreeView->get_id(*xEntry));
+
             if (!pArrType)
+            {
                 bContentChanged = true;
-            else
+                continue;
+            }
+
+            // all content type member lists must be filled!
+            if (bContentChanged)
             {
-                pArrType->Init(&bVisibilityChanged);
-                OUString 
sId(OUString::number(reinterpret_cast<sal_Int64>(pArrType)));
-                m_xTreeView->set_id(*xEntry, sId);
-                if (m_xTreeView->get_row_expanded(*xEntry))
+                // If content change has already been detected there is no 
need to detect
+                // other content change so no argument is supplied here to 
FillMemberList.
+                pArrType->FillMemberList();
+                continue;
+            }
+
+            pArrType->FillMemberList(&bContentChanged);
+            if (bContentChanged)
+                continue;
+
+            // does entry have childern?
+            if (m_xTreeView->get_row_expanded(*xEntry))
+            {
+                const size_t nChildCount = GetChildCount(*xEntry);
+                if(nChildCount != pArrType->GetMemberCount())
                 {
-                    bool bLevelOrVisibilityChanged = false;
-                    // bLevelOrVisibilityChanged is set if outlines have 
changed their level
-                    // or if the visibility of objects (frames, sections, 
tables) has changed
-                    // i.e. in header/footer
-                    pArrType->FillMemberList(&bLevelOrVisibilityChanged);
-                    const size_t nChildCount = GetChildCount(*xEntry);
-                    if (bLevelOrVisibilityChanged)
+                    bContentChanged = true;
+                    continue;
+                }
+
+                for(size_t j = 0; j < nChildCount; ++j)
+                {
+                    if (!m_xTreeView->iter_next(*xEntry))
                     {
-                        if (nType == ContentTypeId::OUTLINE)
-                            bContentChanged = true;
-                        else
-                            bVisibilityChanged = true;
+                        SAL_WARN("sw.ui", "unexpected missing entry");
+                        bContentChanged = true;
+                        continue;
                     }
 
-                    if(nChildCount != pArrType->GetMemberCount())
-                        bContentChanged = true;
-                    else
+                    const SwContent* pCnt = pArrType->GetMember(j);
+                    OUString 
sSubId(OUString::number(reinterpret_cast<sal_Int64>(pCnt)));
+                    m_xTreeView->set_id(*xEntry, sSubId);
+
+                    OUString sEntryText = m_xTreeView->get_text(*xEntry);
+                    if( sEntryText != pCnt->GetName() &&
+                            !(sEntryText == m_sSpace && 
pCnt->GetName().isEmpty()))
                     {
-                        for(size_t j = 0; j < nChildCount; ++j)
-                        {
-                            bEntry = m_xTreeView->iter_next(*xEntry);
-                            bNext = false;
-                            const SwContent* pCnt = pArrType->GetMember(j);
-                            OUString 
sSubId(OUString::number(reinterpret_cast<sal_Int64>(pCnt)));
-                            m_xTreeView->set_id(*xEntry, sSubId);
-                            OUString sEntryText = 
m_xTreeView->get_text(*xEntry);
-                            if( sEntryText != pCnt->GetName() &&
-                                !(sEntryText == m_sSpace && 
pCnt->GetName().isEmpty()))
-                                bContentChanged = true;
-                        }
+                        bContentChanged = true;
+                        continue;
                     }
                 }
-                // not expanded and has children
-                else if (m_xTreeView->iter_has_child(*xEntry))
+            }
+            // not expanded and has children
+            else if (m_xTreeView->iter_has_child(*xEntry))
+            {
+                bool bRemoveChildren = false;
+                const size_t nOldChildCount = GetChildCount(*xEntry);
+                const size_t nNewChildCount = pArrType->GetMemberCount();
+                if (nOldChildCount != nNewChildCount)
                 {
-                    // was the entry once opened, then must also the
-                    // invisible records be examined.
-                    // At least the user data must be updated.
-                    bool bLevelOrVisibilityChanged = false;
-                    // bLevelOrVisibilityChanged is set if outlines have 
changed their level
-                    // or if the visibility of objects (frames, sections, 
tables) has changed
-                    // i.e. in header/footer
-                    pArrType->FillMemberList(&bLevelOrVisibilityChanged);
-                    bool bRemoveChildren = false;
-                    const size_t nOldChildCount = GetChildCount(*xEntry);
-                    const size_t nNewChildCount = pArrType->GetMemberCount();
-                    if (nOldChildCount != nNewChildCount)
-                    {
-                        bRemoveChildren = true;
-                    }
-                    else
+                    bRemoveChildren = true;
+                }
+                else
+                {
+                    std::unique_ptr<weld::TreeIter> 
xChild(m_xTreeView->make_iterator(xEntry.get()));
+                    (void)m_xTreeView->iter_children(*xChild);
+                    for (size_t j = 0; j < nOldChildCount; ++j)
                     {
-                        std::unique_ptr<weld::TreeIter> 
xChild(m_xTreeView->make_iterator(xEntry.get()));
-                        (void)m_xTreeView->iter_children(*xChild);
-                        for (size_t j = 0; j < nOldChildCount; ++j)
-                        {
-                            const SwContent* pCnt = pArrType->GetMember(j);
-                            OUString 
sSubId(OUString::number(reinterpret_cast<sal_Int64>(pCnt)));
-                            m_xTreeView->set_id(*xChild, sSubId);
-                            OUString sEntryText = 
m_xTreeView->get_text(*xChild);
-                            if( sEntryText != pCnt->GetName() &&
+                        const SwContent* pCnt = pArrType->GetMember(j);
+                        OUString 
sSubId(OUString::number(reinterpret_cast<sal_Int64>(pCnt)));
+                        m_xTreeView->set_id(*xChild, sSubId);
+                        OUString sEntryText = m_xTreeView->get_text(*xChild);
+                        if( sEntryText != pCnt->GetName() &&
                                 !(sEntryText == m_sSpace && 
pCnt->GetName().isEmpty()))
-                                bRemoveChildren = true;
-                            (void)m_xTreeView->iter_next(*xChild);
-                        }
-                    }
-                    if (bRemoveChildren)
-                    {
-                        std::unique_ptr<weld::TreeIter> 
xRemove(m_xTreeView->make_iterator(xEntry.get()));
-                        while (m_xTreeView->iter_children(*xRemove))
                         {
-                            remove(*xRemove);
-                            m_xTreeView->copy_iterator(*xEntry, *xRemove);
+                            bRemoveChildren = true;
                         }
-                        m_xTreeView->set_children_on_demand(*xEntry, 
nNewChildCount != 0);
+                        (void)m_xTreeView->iter_next(*xChild);
                     }
                 }
-                else if((nCntCount != 0)
-                            != (pArrType->GetMemberCount()!=0))
+                if (bRemoveChildren)
                 {
-                    bContentChanged = true;
+                    std::unique_ptr<weld::TreeIter> 
xRemove(m_xTreeView->make_iterator(xEntry.get()));
+                    while (m_xTreeView->iter_children(*xRemove))
+                    {
+                        remove(*xRemove);
+                        m_xTreeView->copy_iterator(*xEntry, *xRemove);
+                    }
+                    m_xTreeView->set_children_on_demand(*xEntry, 
nNewChildCount != 0);
                 }
             }
-            // The Root-Entry has to be found now
-            while (bEntry && (bNext || m_xTreeView->get_iter_depth(*xEntry)))
+            else if((nCntCount != 0)
+                    != (pArrType->GetMemberCount()!=0))
             {
-                bEntry = m_xTreeView->iter_next(*xEntry);
-                bNext = false;
+                bContentChanged = true;
+                continue;
             }
         }
     }
 
-    if (!bContentChanged && bVisibilityChanged)
-        m_aUpdTimer.Start();
-
-    return bContentChanged || bVisibilityChanged;
+    return bContentChanged;
 }
 
 void SwContentTree::UpdateLastSelType()

Reply via email to