tdf#130161 detect if a node already had an expansion attempt

and so isn't in child-on-demand mode anymore, in which case in basctl new
module/dialog children should be appended to it similarly to how they are added
if had been expanded in the earlier attempt

Change-Id: I75255fb743852c70e194bbf4828cd90b9112db79
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/88544
Tested-by: Jenkins
Reviewed-by: Caolán McNamara <caolanm@redhat.com>
diff --git a/basctl/source/basicide/bastype2.cxx b/basctl/source/basicide/bastype2.cxx
index a0bff56..7754bd57 100644
--- a/basctl/source/basicide/bastype2.cxx
+++ b/basctl/source/basicide/bastype2.cxx
@@ -253,7 +253,9 @@ void SbTreeListBox::ImpCreateLibEntries(const weld::TreeIter& rIter, const Scrip
            if (bLibRootEntry)
            {
                SetEntryBitmaps(*xLibRootEntry, sId);
                if (m_xControl->get_row_expanded(*xLibRootEntry))
                bool bRowExpanded = m_xControl->get_row_expanded(*xLibRootEntry);
                bool bRowExpandAttempted = !m_xControl->get_children_on_demand(*xLibRootEntry);
                if (bRowExpanded || bRowExpandAttempted)
                    ImpCreateLibSubEntries(*xLibRootEntry, rDocument, aLibName);
            }
            else
diff --git a/include/vcl/weld.hxx b/include/vcl/weld.hxx
index 0c9e4af..9d62ffe 100644
--- a/include/vcl/weld.hxx
+++ b/include/vcl/weld.hxx
@@ -913,6 +913,7 @@ public:
    virtual void select(const TreeIter& rIter) = 0;
    virtual void unselect(const TreeIter& rIter) = 0;
    virtual bool get_row_expanded(const TreeIter& rIter) const = 0;
    virtual bool get_children_on_demand(const TreeIter& rIter) const = 0;
    virtual void expand_row(const TreeIter& rIter) = 0;
    virtual void collapse_row(const TreeIter& rIter) = 0;
    virtual void set_text(const TreeIter& rIter, const OUString& rStr, int col = -1) = 0;
diff --git a/vcl/source/app/salvtables.cxx b/vcl/source/app/salvtables.cxx
index f77d986..5b1c40c 100644
--- a/vcl/source/app/salvtables.cxx
+++ b/vcl/source/app/salvtables.cxx
@@ -3648,6 +3648,18 @@ private:
        return m_xTreeView->GetEntryText(pEntry).trim() == "<dummy>";
    }

    SvTreeListEntry* GetPlaceHolderChild(SvTreeListEntry* pEntry) const
    {
        if (pEntry->HasChildren())
        {
            auto pChild = m_xTreeView->FirstChild(pEntry);
            assert(pChild);
            if (IsDummyEntry(pChild))
                return pChild;
        }
        return nullptr;
    }

public:
    SalInstanceTreeView(SvTabListBox* pTreeView, SalInstanceBuilder* pBuilder, bool bTakeOwnership)
        : SalInstanceContainer(pTreeView, pBuilder, bTakeOwnership)
@@ -4516,6 +4528,12 @@ public:
        return m_xTreeView->IsExpanded(rVclIter.iter);
    }

    virtual bool get_children_on_demand(const weld::TreeIter& rIter) const override
    {
        const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter);
        return GetPlaceHolderChild(rVclIter.iter) != nullptr;
    }

    virtual void expand_row(const weld::TreeIter& rIter) override
    {
        assert(m_xTreeView->IsUpdateMode() && "don't expand when frozen");
@@ -4983,23 +5001,15 @@ IMPL_LINK_NOARG(SalInstanceTreeView, ExpandingHdl, SvTreeListBox*, bool)

    // if there's a preexisting placeholder child, required to make this
    // potentially expandable in the first place, now we remove it
    bool bPlaceHolder = false;
    if (pEntry->HasChildren())
    {
        auto pChild = m_xTreeView->FirstChild(pEntry);
        assert(pChild);
        if (IsDummyEntry(pChild))
        {
            m_xTreeView->RemoveEntry(pChild);
            bPlaceHolder = true;
        }
    }
    SvTreeListEntry* pPlaceHolder = GetPlaceHolderChild(pEntry);
    if (pPlaceHolder)
        m_xTreeView->RemoveEntry(pPlaceHolder);

    SalInstanceTreeIter aIter(pEntry);
    bool bRet = signal_expanding(aIter);

    //expand disallowed, restore placeholder
    if (!bRet && bPlaceHolder)
    if (!bRet && pPlaceHolder)
    {
        m_xTreeView->InsertEntry("<dummy>", pEntry, false, 0, nullptr);
    }
diff --git a/vcl/unx/gtk3/gtk3gtkinst.cxx b/vcl/unx/gtk3/gtk3gtkinst.cxx
index 177dfc7..cb0adf9 100644
--- a/vcl/unx/gtk3/gtk3gtkinst.cxx
+++ b/vcl/unx/gtk3/gtk3gtkinst.cxx
@@ -8697,25 +8697,32 @@ private:
        return !pThis->signal_test_expand_row(*iter);
    }

    bool signal_test_expand_row(GtkTreeIter& iter)
    bool child_is_placeholder(GtkInstanceTreeIter& rGtkIter) const
    {
        disable_notify_events();
        GtkInstanceTreeIter aIter(nullptr);

        // if there's a preexisting placeholder child, required to make this
        // potentially expandable in the first place, now we remove it
        bool bPlaceHolder = false;
        GtkTreeModel *pModel = GTK_TREE_MODEL(m_pTreeStore);
        GtkTreeIter tmp;
        if (gtk_tree_model_iter_children(pModel, &tmp, &iter))
        if (gtk_tree_model_iter_children(pModel, &tmp, &rGtkIter.iter))
        {
            aIter.iter = tmp;
            if (get_text(aIter, -1) == "<dummy>")
            rGtkIter.iter = tmp;
            if (get_text(rGtkIter, -1) == "<dummy>")
            {
                gtk_tree_store_remove(m_pTreeStore, &tmp);
                bPlaceHolder = true;
            }
        }
        return bPlaceHolder;
    }

    bool signal_test_expand_row(GtkTreeIter& iter)
    {
        disable_notify_events();

        // if there's a preexisting placeholder child, required to make this
        // potentially expandable in the first place, now we remove it
        GtkInstanceTreeIter aIter(iter);
        bool bPlaceHolder = child_is_placeholder(aIter);
        if (bPlaceHolder)
            gtk_tree_store_remove(m_pTreeStore, &aIter.iter);

        aIter.iter = iter;
        bool bRet = signal_expanding(aIter);
@@ -10008,6 +10015,13 @@ public:
        return ret;
    }

    virtual bool get_children_on_demand(const weld::TreeIter& rIter) const override
    {
        const GtkInstanceTreeIter& rGtkIter = static_cast<const GtkInstanceTreeIter&>(rIter);
        GtkInstanceTreeIter aIter(&rGtkIter);
        return child_is_placeholder(aIter);
    }

    virtual void expand_row(const weld::TreeIter& rIter) override
    {
        assert(gtk_tree_view_get_model(m_pTreeView) && "don't expand when frozen");