basctl/source/basicide/idecodecompletiontypes.cxx |   26 +
 basctl/source/basicide/idedataprovider.cxx        |  291 +++++++++++++++++++++-
 basctl/source/basicide/idetimer.cxx               |   11 
 basctl/source/basicide/idetimer.hxx               |    1 
 basctl/source/basicide/objectbrowser.cxx          |   68 +++--
 basctl/source/inc/idedataprovider.hxx             |   44 +++
 basctl/source/inc/objectbrowser.hxx               |   14 -
 include/basctl/idecodecompletiontypes.hxx         |    2 
 8 files changed, 422 insertions(+), 35 deletions(-)

New commits:
commit a2d19c07041bf6fe1208dd7cb94b9c80aff33979
Author:     Devansh Varshney <[email protected]>
AuthorDate: Tue Sep 23 20:15:09 2025 +0530
Commit:     Hossein <[email protected]>
CommitDate: Tue Oct 14 18:35:47 2025 +0200

    tdf#165785: basctl: Implement data provider for Object Browser
    
    This patch introduces the core data-fetching logic for the new Object
    Browser. It implements the logic to scan all available UNO APIs and to
    preload BASIC libraries.
    
    For this foundational patch, the data initialization is performed
    synchronously. A subsequent patch will refactor this into a non-blocking,
    asynchronous operation to keep the UI fully responsive.
    
    (GSoC 2025 - Object Browser: Data Provider Implementation)
    
    Change-Id: I46446fc498820d9776d77ba25c4fa3fd4ca89a8d
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/191405
    Tested-by: Jenkins
    Reviewed-by: Hossein <[email protected]>

diff --git a/basctl/source/basicide/idecodecompletiontypes.cxx 
b/basctl/source/basicide/idecodecompletiontypes.cxx
index 3d9d87756c0a..22779828e520 100644
--- a/basctl/source/basicide/idecodecompletiontypes.cxx
+++ b/basctl/source/basicide/idecodecompletiontypes.cxx
@@ -8,6 +8,7 @@
  */
 
 #include <basctl/idecodecompletiontypes.hxx>
+#include <rtl/ustrbuf.hxx>
 
 namespace basctl
 {
@@ -50,6 +51,31 @@ void IdeSymbolInfo::AddMember(std::shared_ptr<IdeSymbolInfo> 
pMember)
     mapMembers.insert_or_assign(pMember->sName, std::move(pMember));
 }
 
+OUString CreateRootIdentifier(IdeSymbolKind eKind, std::u16string_view 
sOptionalPayload)
+{
+    OUStringBuffer sId(u"root:");
+
+    switch (eKind)
+    {
+        case IdeSymbolKind::ROOT_UNO_APIS:
+            sId.append(u"uno_apis");
+            break;
+        case IdeSymbolKind::ROOT_APPLICATION_LIBS:
+            sId.append(u"app_macros");
+            break;
+        case IdeSymbolKind::ROOT_DOCUMENT_LIBS:
+            sId.append(OUString::Concat(u"doc:") + sOptionalPayload);
+            break;
+        case IdeSymbolKind::ROOT_BASIC_BUILTINS:
+            sId.append(u"builtins");
+            break;
+        default:
+            sId.append(u"unknown");
+            break;
+    }
+    return sId.makeStringAndClear();
+}
+
 } // namespace basctl
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s 
cinkeys+=0=break: */
diff --git a/basctl/source/basicide/idedataprovider.cxx 
b/basctl/source/basicide/idedataprovider.cxx
index 7cd4458ba6e8..8d6d27febcb2 100644
--- a/basctl/source/basicide/idedataprovider.cxx
+++ b/basctl/source/basicide/idedataprovider.cxx
@@ -8,20 +8,299 @@
  */
 
 #include <idedataprovider.hxx>
-#include <vcl/svapp.hxx>
+#include "idetimer.hxx"
+
+#include <basic/basmgr.hxx>
+#include <basctl/scriptdocument.hxx>
+#include <comphelper/processfactory.hxx>
+#include <sal/log.hxx>
+
+#include <com/sun/star/container/XHierarchicalNameAccess.hpp>
+#include <com/sun/star/reflection/XTypeDescriptionEnumeration.hpp>
+#include <com/sun/star/reflection/XTypeDescriptionEnumerationAccess.hpp>
+#include <com/sun/star/reflection/theCoreReflection.hpp>
 
 namespace basctl
 {
-IdeDataProvider::IdeDataProvider() {}
+using namespace basic;
+
+namespace css = ::com::sun::star;
+using namespace css::container;
+using namespace css::uno;
+using namespace css::lang;
+using namespace css::reflection;
+
+IdeDataProvider::IdeDataProvider()
+    : m_pUnoHierarchy(std::make_unique<UnoApiHierarchy>())
+    , m_bInitialized(false)
+{
+}
+
+void IdeDataProvider::Initialize()
+{
+    if (m_bInitialized)
+        return;
+
+    IdeTimer aTotalInitTimer(u"IdeDataProvider::Initialize 
(Synchronous)"_ustr);
+    SAL_INFO("basctl", "Starting synchronous data provider initialization...");
+
+    // Perform a full synchronous UNO scan
+    SAL_INFO("basctl", "Performing full synchronous UNO scan...");
+    performFullUnoScan();
+
+    // Preload all BASIC Libraries
+    IdeTimer aBasicTimer(u"IdeDataProvider::Initialize (Basic Library 
Preload)"_ustr);
+    SAL_INFO("basctl", "Starting BASIC library preload...");
+
+    try
+    {
+        ScriptDocument aAppDoc = 
ScriptDocument::getApplicationScriptDocument();
+        if (aAppDoc.isAlive())
+        {
+            Reference<css::script::XLibraryContainer> xLibContainer
+                = aAppDoc.getLibraryContainer(E_SCRIPTS);
+            if (xLibContainer.is())
+            {
+                for (const OUString& rLibName : 
xLibContainer->getElementNames())
+                {
+                    try
+                    {
+                        if (xLibContainer->hasByName(rLibName)
+                            && !xLibContainer->isLibraryLoaded(rLibName))
+                        {
+                            xLibContainer->loadLibrary(rLibName);
+                        }
+                    }
+                    catch (const Exception& e)
+                    {
+                        SAL_WARN("basctl", "Exception while preloading 
application library '"
+                                               << rLibName << "': " << 
e.Message);
+                    }
+                }
+            }
+        }
+    }
+    catch (const Exception& e)
+    {
+        SAL_WARN("basctl", "Could not retrieve Application library container: 
" << e.Message);
+    }
+
+    // Preload from any open documents
+    try
+    {
+        for (const auto& rDoc :
+             
ScriptDocument::getAllScriptDocuments(ScriptDocument::DocumentsSorted))
+        {
+            if (rDoc.isAlive())
+            {
+                auto xDocLibContainer = rDoc.getLibraryContainer(E_SCRIPTS);
+                if (xDocLibContainer.is())
+                {
+                    for (const OUString& rLibName : 
xDocLibContainer->getElementNames())
+                    {
+                        try
+                        {
+                            if (xDocLibContainer->hasByName(rLibName)
+                                && 
!xDocLibContainer->isLibraryLoaded(rLibName))
+                            {
+                                xDocLibContainer->loadLibrary(rLibName);
+                            }
+                        }
+                        catch (const Exception& e)
+                        {
+                            SAL_WARN("basctl", "Exception while preloading 
document library '"
+                                                   << rLibName << "' in 
document '"
+                                                   << rDoc.getTitle() << "': " 
<< e.Message);
+                        }
+                    }
+                }
+            }
+        }
+    }
+    catch (const Exception& e)
+    {
+        SAL_WARN("basctl", "Could not iterate through document libraries: " << 
e.Message);
+    }
+    SAL_INFO("basctl", "BASIC library preload finished.");
+
+    m_aTopLevelNodes.clear();
+    m_aTopLevelNodes.push_back(
+        std::make_shared<IdeSymbolInfo>(u"UNO APIs", 
IdeSymbolKind::ROOT_UNO_APIS, u"root"));
+    m_aTopLevelNodes.push_back(std::make_shared<IdeSymbolInfo>(
+        u"Application Macros", IdeSymbolKind::ROOT_APPLICATION_LIBS, u"root"));
+
+    m_bInitialized = true;
+    SAL_INFO("basctl", "Synchronous data provider initialization complete.");
+}
+
+void IdeDataProvider::Reset()
+{
+    SAL_INFO("basctl", "IdeDataProvider: Resetting state.");
+    m_bInitialized = false;
+    m_aTopLevelNodes.clear();
 
-IdeDataProvider::~IdeDataProvider() = default;
+    m_pUnoHierarchy = std::make_unique<UnoApiHierarchy>();
+}
 
-void IdeDataProvider::AsyncInitialize(const Link<void*, void>& rFinishCallback)
+void IdeDataProvider::performFullUnoScan()
 {
-    Application::PostUserEvent(rFinishCallback);
+    IdeTimer aScanTimer(u"IdeDataProvider::performFullUnoScan"_ustr);
+    sal_Int32 nProcessedCount = 0;
+
+    try
+    {
+        Reference<XHierarchicalNameAccess> xTypeManager;
+        comphelper::getProcessComponentContext()->getValueByName(
+            
u"/singletons/com.sun.star.reflection.theTypeDescriptionManager"_ustr)
+            >>= xTypeManager;
+
+        if (xTypeManager.is())
+        {
+            Reference<XTypeDescriptionEnumerationAccess> 
xEnumAccess(xTypeManager, UNO_QUERY_THROW);
+            Reference<XEnumeration> xEnum = 
xEnumAccess->createTypeDescriptionEnumeration(
+                u""_ustr, {}, TypeDescriptionSearchDepth_INFINITE);
+
+            while (xEnum.is() && xEnum->hasMoreElements())
+            {
+                try
+                {
+                    Reference<XTypeDescription> xTypeDesc;
+                    if ((xEnum->nextElement() >>= xTypeDesc) && xTypeDesc.is())
+                    {
+                        m_pUnoHierarchy->addNode(xTypeDesc->getName(), 
xTypeDesc->getTypeClass());
+                        nProcessedCount++;
+                    }
+                }
+                catch (const Exception& e)
+                {
+                    SAL_WARN("basctl",
+                             "performFullUnoScan: Exception processing a 
single UNO type: "
+                                 << e.Message);
+                }
+            }
+        }
+    }
+    catch (const Exception& e)
+    {
+        SAL_WARN("basctl", "Full UNO scan failed with exception: " << 
e.Message);
+    }
+
+    sal_Int64 nFullScanTimeMs = aScanTimer.getElapsedTimeMs();
+    SAL_INFO("basctl", "UNO scan completed in " << nFullScanTimeMs << " ms. 
Found "
+                                                << nProcessedCount << " 
types.");
 }
 
-bool IdeDataProvider::IsInitialized() const { return m_bInitialized; }
+SymbolInfoList IdeDataProvider::GetTopLevelNodes()
+{
+    if (!m_bInitialized)
+    {
+        SymbolInfoList aNodes;
+        auto pLoadingNode = 
std::make_shared<IdeSymbolInfo>(u"[Initializing...]",
+                                                            
IdeSymbolKind::PLACEHOLDER, u"");
+        pLoadingNode->bSelectable = false;
+        aNodes.push_back(pLoadingNode);
+        return aNodes;
+    }
+    return m_aTopLevelNodes;
+}
+
+GroupedSymbolInfoList IdeDataProvider::GetMembers(const IdeSymbolInfo& 
/*rNode*/) { return {}; }
+
+SymbolInfoList IdeDataProvider::GetChildNodes(const IdeSymbolInfo& rParent)
+{
+    if (!m_bInitialized)
+    {
+        return {};
+    }
+
+    SymbolInfoList aChildren;
+    if (rParent.eKind == IdeSymbolKind::ROOT_UNO_APIS)
+    {
+        aChildren = m_pUnoHierarchy->m_hierarchyCache[OUString()];
+    }
+    else if (rParent.eKind == IdeSymbolKind::UNO_NAMESPACE)
+    {
+        aChildren = m_pUnoHierarchy->m_hierarchyCache[rParent.sQualifiedName];
+    }
+
+    return aChildren;
+}
+
+void UnoApiHierarchy::addNode(std::u16string_view sQualifiedNameView, 
TypeClass eTypeClass)
+{
+    const OUString sQualifiedName(sQualifiedNameView);
+
+    if (sQualifiedName.isEmpty())
+        return;
+
+    OUString sParentPath;
+    OUString sCurrentPath;
+    sal_Int32 nStartIndex = 0;
+    sal_Int32 nDotIndex;
+
+    do
+    {
+        nDotIndex = sQualifiedName.indexOf('.', nStartIndex);
+        OUString sPart = (nDotIndex == -1)
+                             ? sQualifiedName.copy(nStartIndex)
+                             : sQualifiedName.copy(nStartIndex, nDotIndex - 
nStartIndex);
+
+        if (sPart.isEmpty())
+            continue;
+
+        sParentPath = sCurrentPath;
+        sCurrentPath = sCurrentPath.isEmpty() ? sPart : sCurrentPath + u"." + 
sPart;
+
+        // Find the list of childern for the current parent
+        auto& rChildren = m_hierarchyCache[sParentPath];
+
+        // Avoid adding duplicate nodes
+        bool bExists = std::any_of(rChildren.begin(), rChildren.end(),
+                                   [&sPart](const auto& pNode) { return 
pNode->sName == sPart; });
+
+        if (!bExists)
+        {
+            IdeSymbolKind eKind = (nDotIndex == -1) ? 
typeClassToSymbolKind(eTypeClass)
+                                                    : 
IdeSymbolKind::UNO_NAMESPACE;
+
+            auto pNewNode
+                = std::make_shared<IdeSymbolInfo>(sPart.getStr(), eKind, 
sParentPath.getStr());
+            pNewNode->sQualifiedName = sCurrentPath;
+            pNewNode->sParentName = sParentPath;
+            pNewNode->sIdentifier = sCurrentPath;
+            rChildren.push_back(std::move(pNewNode));
+        }
+
+        nStartIndex = nDotIndex + 1;
+    } while (nDotIndex != -1);
+}
+
+IdeSymbolKind UnoApiHierarchy::typeClassToSymbolKind(TypeClass eTypeClass)
+{
+    switch (eTypeClass)
+    {
+        case TypeClass_INTERFACE:
+            return IdeSymbolKind::UNO_INTERFACE;
+        case TypeClass_STRUCT:
+            return IdeSymbolKind::UNO_STRUCT;
+        case TypeClass_ENUM:
+            return IdeSymbolKind::UNO_ENUM;
+        case TypeClass_TYPEDEF:
+            return IdeSymbolKind::UNO_TYPEDEF;
+        case TypeClass_CONSTANTS:
+            return IdeSymbolKind::UNO_CONSTANTS;
+        case TypeClass_EXCEPTION:
+            return IdeSymbolKind::UNO_EXCEPTION;
+        case TypeClass_SERVICE:
+            return IdeSymbolKind::UNO_SERVICE;
+        case TypeClass_MODULE:
+            return IdeSymbolKind::UNO_NAMESPACE;
+        case TypeClass_SINGLETON:
+            return IdeSymbolKind::UNO_SERVICE; // Treat singletons as services
+        default:
+            return IdeSymbolKind::UNO_TYPE;
+    }
+}
 
 } // namespace basctl
 
diff --git a/basctl/source/basicide/idetimer.cxx 
b/basctl/source/basicide/idetimer.cxx
index 2818890e1999..9e8d135fda12 100644
--- a/basctl/source/basicide/idetimer.cxx
+++ b/basctl/source/basicide/idetimer.cxx
@@ -37,6 +37,17 @@ IdeTimer::~IdeTimer()
                                    << "' took " << fElapsedSeconds << " 
seconds.");
 }
 
+sal_Int64 IdeTimer::getElapsedTimeMs() const
+{
+    TimeValue aEnd;
+    osl_getSystemTime(&aEnd);
+
+    sal_Int64 nSeconds = static_cast<sal_Int64>(aEnd.Seconds) - 
m_aStart.Seconds;
+    sal_Int64 nNanos = static_cast<sal_Int64>(aEnd.Nanosec) - m_aStart.Nanosec;
+
+    return (nSeconds * 1000) + (nNanos / 1000000);
+}
+
 } // namespace basctl
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s 
cinkeys+=0=break: */
diff --git a/basctl/source/basicide/idetimer.hxx 
b/basctl/source/basicide/idetimer.hxx
index 58f4c0bda589..2cf28b5a0264 100644
--- a/basctl/source/basicide/idetimer.hxx
+++ b/basctl/source/basicide/idetimer.hxx
@@ -23,6 +23,7 @@ class IdeTimer
 public:
     explicit IdeTimer(const rtl::OUString& operationName);
     ~IdeTimer();
+    sal_Int64 getElapsedTimeMs() const;
 
 private:
     IdeTimer(const IdeTimer&) = delete;
diff --git a/basctl/source/basicide/objectbrowser.cxx 
b/basctl/source/basicide/objectbrowser.cxx
index 8b7c9f411ed9..5ccac1884b6f 100644
--- a/basctl/source/basicide/objectbrowser.cxx
+++ b/basctl/source/basicide/objectbrowser.cxx
@@ -11,15 +11,16 @@
 #include <objectbrowser.hxx>
 #include <objectbrowsersearch.hxx>
 #include <idedataprovider.hxx>
+#include "idetimer.hxx"
 #include <iderid.hxx>
 #include <strings.hrc>
 
-#include <vcl/svapp.hxx>
 #include <vcl/taskpanelist.hxx>
 #include <sal/log.hxx>
 #include <sfx2/bindings.hxx>
 #include <sfx2/sfxsids.hrc>
 #include <sfx2/viewfrm.hxx>
+#include <vcl/weld.hxx>
 
 namespace basctl
 {
@@ -29,14 +30,13 @@ ObjectBrowser::ObjectBrowser(Shell& rShell, vcl::Window* 
pParent)
     , m_pShell(&rShell)
     , m_pDataProvider(std::make_unique<IdeDataProvider>())
     , m_bDisposed(false)
+    , m_eInitState(ObjectBrowserInitState::NotInitialized)
     , m_bUIInitialized(false)
     , m_pDocNotifier(std::make_unique<DocumentEventNotifier>(*this))
 {
     SetText(IDEResId(RID_STR_OBJECT_BROWSER));
     SetBackground(GetSettings().GetStyleSettings().GetWindowColor());
     EnableInput(true, true);
-
-    Initialize();
 }
 
 ObjectBrowser::~ObjectBrowser() { disposeOnce(); }
@@ -103,6 +103,7 @@ void ObjectBrowser::dispose()
     {
         return;
     }
+    m_bDisposed = true;
 
     m_eInitState = ObjectBrowserInitState::Disposed;
 
@@ -154,48 +155,82 @@ void ObjectBrowser::dispose()
 bool ObjectBrowser::Close()
 {
     Show(false);
-
-    SfxBindings& rBindings = m_pShell->GetViewFrame().GetBindings();
-    rBindings.Invalidate(SID_BASICIDE_OBJECT_BROWSER);
-
+    
m_pShell->GetViewFrame().GetBindings().Invalidate(SID_BASICIDE_OBJECT_BROWSER);
     return false;
 }
 
 void ObjectBrowser::Show(bool bVisible)
 {
     DockingWindow::Show(bVisible);
+    if (!bVisible)
+        return;
 
-    if (bVisible)
+    if (m_eInitState == ObjectBrowserInitState::NotInitialized)
     {
-        if (m_eInitState == ObjectBrowserInitState::NotInitialized)
-        {
-            Initialize();
-        }
+        Initialize();
+    }
 
-        if (!m_pDataProvider->IsInitialized())
+    if (m_pDataProvider && !m_pDataProvider->IsInitialized())
+    {
+        ShowLoadingState();
         {
-            ShowLoadingState();
-            m_pDataProvider->AsyncInitialize(LINK(this, ObjectBrowser, 
OnDataProviderInitialized));
+            weld::WaitObject aWait(GetFrameWeld());
+            m_pDataProvider->Initialize();
         }
+        RefreshUI();
     }
 }
 
 void ObjectBrowser::RefreshUI(bool /*bForceKeepUno*/)
 {
-    if (!m_pDataProvider->IsInitialized())
+    if (m_pDataProvider && m_pDataProvider->IsInitialized())
+    {
+        PopulateLeftTree();
+        if (m_xStatusLabel)
+            m_xStatusLabel->set_label(u"Ready"_ustr);
+    }
+    else
     {
         ShowLoadingState();
     }
 }
 
+void ObjectBrowser::PopulateLeftTree()
+{
+    if (!m_xLeftTreeView)
+        return;
+
+    m_xLeftTreeView->freeze();
+    ClearTreeView(*m_xLeftTreeView, m_aLeftTreeSymbolStore);
+
+    SymbolInfoList aTopLevelNodes = m_pDataProvider->GetTopLevelNodes();
+    for (const auto& pNode : aTopLevelNodes)
+    {
+        m_aLeftTreeSymbolStore.push_back(pNode);
+        m_xLeftTreeView->insert(nullptr, -1, &pNode->sName, nullptr, nullptr, 
nullptr, true,
+                                nullptr);
+    }
+
+    m_xLeftTreeView->thaw();
+}
+
 void ObjectBrowser::ShowLoadingState()
 {
     if (m_xLeftTreeView)
     {
         m_xLeftTreeView->freeze();
         ClearTreeView(*m_xLeftTreeView, m_aLeftTreeSymbolStore);
+
+        auto pLoadingNode = 
std::make_shared<IdeSymbolInfo>(u"[Initializing...]",
+                                                            
IdeSymbolKind::PLACEHOLDER, u"");
+
+        m_aLeftTreeSymbolStore.push_back(pLoadingNode);
+        m_xLeftTreeView->insert(nullptr, -1, &pLoadingNode->sName, nullptr, 
nullptr, nullptr, false,
+                                nullptr);
         m_xLeftTreeView->thaw();
     }
+    if (m_xStatusLabel)
+        m_xStatusLabel->set_label(u"Initializing Object Browser..."_ustr);
 }
 
 void ObjectBrowser::ClearTreeView(weld::TreeView& rTree,
@@ -215,7 +250,6 @@ void ObjectBrowser::onDocumentClosed(const ScriptDocument&) 
{ /* STUB */}
 void ObjectBrowser::onDocumentTitleChanged(const ScriptDocument&) { /* STUB */}
 void ObjectBrowser::onDocumentModeChanged(const ScriptDocument&) { /* STUB */}
 
-IMPL_STATIC_LINK(ObjectBrowser, OnDataProviderInitialized, void*, /*p*/, void) 
{ /* STUB */}
 IMPL_STATIC_LINK(ObjectBrowser, OnLeftTreeSelect, weld::TreeView&, /*rTree*/, 
void) { /* STUB */}
 IMPL_STATIC_LINK(ObjectBrowser, OnRightTreeSelect, weld::TreeView&, /*rTree*/, 
void) { /* STUB */}
 IMPL_STATIC_LINK(ObjectBrowser, OnNodeExpand, const weld::TreeIter&, 
/*rParentIter*/, bool)
diff --git a/basctl/source/inc/idedataprovider.hxx 
b/basctl/source/inc/idedataprovider.hxx
index 73d46badf140..4d943b1f7556 100644
--- a/basctl/source/inc/idedataprovider.hxx
+++ b/basctl/source/inc/idedataprovider.hxx
@@ -12,27 +12,63 @@
 #include <basctl/idecodecompletiontypes.hxx>
 
 #include <memory>
+#include <vector>
+
+#include <rtl/ustring.hxx>
 #include <tools/link.hxx>
 
+#include <com/sun/star/uno/TypeClass.hpp>
+
 namespace basctl
 {
+using IdeSymbolInfo = basctl::IdeSymbolInfo;
+using SymbolInfoList = std::vector<std::shared_ptr<IdeSymbolInfo>>;
+using GroupedSymbolInfoList = std::map<IdeSymbolKind, SymbolInfoList>;
+
+// Data structure for the in-memory UNO type hierarchy
+struct UnoApiHierarchy
+{
+    std::map<OUString, SymbolInfoList> m_hierarchyCache;
+    void addNode(std::u16string_view sQualifiedName, css::uno::TypeClass 
eTypeClass);
+    static IdeSymbolKind typeClassToSymbolKind(css::uno::TypeClass eTypeClass);
+};
+
 class IdeDataProviderInterface
 {
 public:
     virtual ~IdeDataProviderInterface() = default;
-    virtual void AsyncInitialize(const Link<void*, void>& rFinishCallback) = 0;
+
+    virtual void Initialize() = 0;
     virtual bool IsInitialized() const = 0;
+    virtual void Reset() = 0;
+
+    // Data Access Methods
+    virtual SymbolInfoList GetTopLevelNodes() = 0;
+    virtual GroupedSymbolInfoList GetMembers(const IdeSymbolInfo& rNode) = 0;
+    virtual SymbolInfoList GetChildNodes(const IdeSymbolInfo& rParent) = 0;
 };
 
 class IdeDataProvider : public IdeDataProviderInterface
 {
 public:
     IdeDataProvider();
-    ~IdeDataProvider() override;
-    void AsyncInitialize(const Link<void*, void>& rFinishCallback) override;
-    bool IsInitialized() const override;
+
+    void Initialize() override;
+    bool IsInitialized() const override { return m_bInitialized; }
+    void Reset() override;
+
+    SymbolInfoList GetTopLevelNodes() override;
+    GroupedSymbolInfoList GetMembers(const IdeSymbolInfo& rNode) override;
+    SymbolInfoList GetChildNodes(const IdeSymbolInfo& rParent) override;
 
 private:
+    void performFullUnoScan();
+
+    // Core data
+    std::unique_ptr<UnoApiHierarchy> m_pUnoHierarchy;
+    SymbolInfoList m_aTopLevelNodes;
+
+    // State management
     bool m_bInitialized = false;
 };
 
diff --git a/basctl/source/inc/objectbrowser.hxx 
b/basctl/source/inc/objectbrowser.hxx
index d280b395b524..196d009bba22 100644
--- a/basctl/source/inc/objectbrowser.hxx
+++ b/basctl/source/inc/objectbrowser.hxx
@@ -15,12 +15,9 @@
 
 #include <basctl/idecodecompletiontypes.hxx>
 
-#include <atomic>
 #include <memory>
-#include <set>
 #include <vector>
 
-#include <vcl/status.hxx>
 #include <vcl/weld.hxx>
 
 namespace basctl
@@ -28,7 +25,6 @@ namespace basctl
 class Shell;
 class IdeDataProviderInterface;
 class ObjectBrowserSearch;
-class ObjectBrowserNavigation;
 
 enum class ObjectBrowserInitState
 {
@@ -45,12 +41,13 @@ public:
     ObjectBrowser(Shell& rShell, vcl::Window* pParent);
     ~ObjectBrowser() override;
 
-    virtual void dispose() override;
+    void dispose() override;
     virtual bool Close() override;
 
     void Show(bool bVisible = true);
     void RefreshUI(bool bForceKeepUno = false);
 
+    // DocumentEventListener stubs
     void onDocumentCreated(const ScriptDocument& _rDocument) override;
     void onDocumentOpened(const ScriptDocument& _rDocument) override;
     void onDocumentSave(const ScriptDocument& _rDocument) override;
@@ -61,6 +58,7 @@ public:
     void onDocumentTitleChanged(const ScriptDocument& _rDocument) override;
     void onDocumentModeChanged(const ScriptDocument& _rDocument) override;
 
+    // Accessors for the Search Handler
     weld::Entry* GetFilterBox() { return m_pFilterBox.get(); }
     weld::Button* GetClearSearchButton() { return m_xClearSearchButton.get(); }
 
@@ -70,6 +68,7 @@ private:
     // Core tree management methods
     static void ClearTreeView(weld::TreeView& rTree,
                               
std::vector<std::shared_ptr<basctl::IdeSymbolInfo>>& rStore);
+    void PopulateLeftTree();
     void ShowLoadingState();
 
     // Core References
@@ -95,7 +94,7 @@ private:
     std::unique_ptr<weld::Button> m_xForwardButton;
     std::unique_ptr<weld::Button> m_xClearSearchButton;
 
-    // Data Storage
+    // Data Storage for TreeViews
     std::vector<std::shared_ptr<basctl::IdeSymbolInfo>> m_aLeftTreeSymbolStore;
     std::vector<std::shared_ptr<basctl::IdeSymbolInfo>> 
m_aRightTreeSymbolStore;
     std::map<OUString, size_t> m_aNextChunk; // For lazy-loading nodes
@@ -106,8 +105,7 @@ private:
     // Event Handling
     std::unique_ptr<basctl::DocumentEventNotifier> m_pDocNotifier;
 
-    // Event Handlers
-    DECL_STATIC_LINK(ObjectBrowser, OnDataProviderInitialized, void*, void);
+    // UI Event Handlers
     DECL_STATIC_LINK(ObjectBrowser, OnLeftTreeSelect, weld::TreeView&, void);
     DECL_STATIC_LINK(ObjectBrowser, OnRightTreeSelect, weld::TreeView&, void);
     DECL_STATIC_LINK(ObjectBrowser, OnNodeExpand, const weld::TreeIter&, bool);
diff --git a/include/basctl/idecodecompletiontypes.hxx 
b/include/basctl/idecodecompletiontypes.hxx
index 45ab8785fbae..ff31a273e8b5 100644
--- a/include/basctl/idecodecompletiontypes.hxx
+++ b/include/basctl/idecodecompletiontypes.hxx
@@ -169,6 +169,8 @@ struct IdeSymbolInfo
 using SymbolInfoList = std::vector<std::shared_ptr<IdeSymbolInfo>>;
 using ParamInfoList = std::vector<IdeParamInfo>;
 
+OUString CreateRootIdentifier(IdeSymbolKind eKind, std::u16string_view 
sOptionalPayload = u"");
+
 } // namespace basctl
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s 
cinkeys+=0=break: */

Reply via email to