[Libreoffice-commits] core.git: include/sfx2 sfx2/Library_sfx.mk sfx2/source

Tomaž Vajngerl (via logerrit) logerrit at kemper.freedesktop.org
Thu Feb 11 11:55:36 UTC 2021


 include/sfx2/devtools/DevelopmentToolDockingWindow.hxx |    6 
 include/sfx2/devtools/ObjectInspectorTreeHandler.hxx   |   44 +
 sfx2/Library_sfx.mk                                    |    1 
 sfx2/source/devtools/DevelopmentToolDockingWindow.cxx  |  501 ----------------
 sfx2/source/devtools/ObjectInspectorTreeHandler.cxx    |  503 +++++++++++++++++
 5 files changed, 557 insertions(+), 498 deletions(-)

New commits:
commit e44639f50056b843913573b4635517019e00431c
Author:     Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
AuthorDate: Mon Feb 8 22:41:36 2021 +0900
Commit:     Tomaž Vajngerl <quikee at gmail.com>
CommitDate: Thu Feb 11 12:54:47 2021 +0100

    devtools: move handling of object inspector tree to own class/files
    
    To make handling of object inspector tree view easier, move the
    functionality to its own class and file.
    
    Change-Id: I47ae1bc06b582d0d146e7e97bc08a3b5f82ce794
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/110734
    Tested-by: Jenkins
    Reviewed-by: Tomaž Vajngerl <quikee at gmail.com>

diff --git a/include/sfx2/devtools/DevelopmentToolDockingWindow.hxx b/include/sfx2/devtools/DevelopmentToolDockingWindow.hxx
index 1ed166239949..4721a424e66d 100644
--- a/include/sfx2/devtools/DevelopmentToolDockingWindow.hxx
+++ b/include/sfx2/devtools/DevelopmentToolDockingWindow.hxx
@@ -16,6 +16,7 @@
 #include <vcl/weld.hxx>
 
 #include <sfx2/devtools/DocumentModelTreeHandler.hxx>
+#include <sfx2/devtools/ObjectInspectorTreeHandler.hxx>
 
 #include <com/sun/star/uno/XInterface.hpp>
 #include <com/sun/star/uno/Reference.hxx>
@@ -37,18 +38,15 @@ private:
     css::uno::Reference<css::view::XSelectionChangeListener> mxSelectionListener;
 
     DocumentModelTreeHandler maDocumentModelTreeHandler;
+    ObjectInspectorTreeHandler maObjectInspectorTreeHandler;
 
     DECL_LINK(DocumentModelTreeViewSelectionHandler, weld::TreeView&, void);
     DECL_LINK(SelectionToggled, weld::ToggleButton&, void);
 
-    DECL_LINK(ObjectInspectorExpandingHandler, const weld::TreeIter&, bool);
-
     void inspectDocument();
     void updateSelection();
     void inspectSelectionOrRoot(css::uno::Reference<css::frame::XController> const& xController);
 
-    void clearObjectInspectorChildren(weld::TreeIter const& rParent);
-
 public:
     DevelopmentToolDockingWindow(SfxBindings* pBindings, SfxChildWindow* pChildWindow,
                                  vcl::Window* pParent);
diff --git a/include/sfx2/devtools/ObjectInspectorTreeHandler.hxx b/include/sfx2/devtools/ObjectInspectorTreeHandler.hxx
new file mode 100644
index 000000000000..aa6e353e6549
--- /dev/null
+++ b/include/sfx2/devtools/ObjectInspectorTreeHandler.hxx
@@ -0,0 +1,44 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ */
+
+#pragma once
+
+#include <sfx2/dllapi.h>
+#include <vcl/weld.hxx>
+
+#include <com/sun/star/uno/XInterface.hpp>
+#include <com/sun/star/uno/Reference.hxx>
+
+class ObjectInspectorTreeHandler
+{
+private:
+    std::unique_ptr<weld::TreeView>& mpObjectInspectorTree;
+    std::unique_ptr<weld::Label>& mpClassNameLabel;
+
+    void clearObjectInspectorChildren(weld::TreeIter const& rParent);
+
+public:
+    ObjectInspectorTreeHandler(std::unique_ptr<weld::TreeView>& pObjectInspectorTree,
+                               std::unique_ptr<weld::Label>& pClassNameLabel)
+        : mpObjectInspectorTree(pObjectInspectorTree)
+        , mpClassNameLabel(pClassNameLabel)
+    {
+        mpObjectInspectorTree->connect_expanding(
+            LINK(this, ObjectInspectorTreeHandler, ExpandingHandler));
+    }
+
+    DECL_LINK(ExpandingHandler, const weld::TreeIter&, bool);
+
+    void introspect(css::uno::Reference<css::uno::XInterface> const& xInterface);
+
+    void dispose();
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sfx2/Library_sfx.mk b/sfx2/Library_sfx.mk
index 52ace3c503fe..b5126ca87893 100644
--- a/sfx2/Library_sfx.mk
+++ b/sfx2/Library_sfx.mk
@@ -165,6 +165,7 @@ $(eval $(call gb_Library_add_exception_objects,sfx,\
     sfx2/source/devtools/DevelopmentToolChildWindow \
     sfx2/source/devtools/DevelopmentToolDockingWindow \
     sfx2/source/devtools/DocumentModelTreeHandler \
+    sfx2/source/devtools/ObjectInspectorTreeHandler \
     sfx2/source/dialog/alienwarn \
     sfx2/source/dialog/backingcomp \
     sfx2/source/dialog/backingwindow \
diff --git a/sfx2/source/devtools/DevelopmentToolDockingWindow.cxx b/sfx2/source/devtools/DevelopmentToolDockingWindow.cxx
index 89f9e878d69b..0d335b5118cc 100644
--- a/sfx2/source/devtools/DevelopmentToolDockingWindow.cxx
+++ b/sfx2/source/devtools/DevelopmentToolDockingWindow.cxx
@@ -12,433 +12,16 @@
 
 #include <sfx2/devtools/DevelopmentToolDockingWindow.hxx>
 
-#include <com/sun/star/uno/XComponentContext.hpp>
-#include <com/sun/star/lang/XServiceInfo.hpp>
-
-#include <com/sun/star/beans/theIntrospection.hpp>
-#include <com/sun/star/beans/XIntrospection.hpp>
-#include <com/sun/star/beans/XIntrospectionAccess.hpp>
-#include <com/sun/star/beans/Property.hpp>
-#include <com/sun/star/beans/PropertyConcept.hpp>
-#include <com/sun/star/beans/MethodConcept.hpp>
-#include <com/sun/star/beans/XPropertySet.hpp>
-
-#include <com/sun/star/reflection/theCoreReflection.hpp>
-#include <com/sun/star/reflection/XIdlReflection.hpp>
-#include <com/sun/star/reflection/XIdlMethod.hpp>
-
-#include <com/sun/star/script/XInvocation.hpp>
-#include <com/sun/star/script/Invocation.hpp>
-
 #include <com/sun/star/view/XSelectionSupplier.hpp>
 
-#include <comphelper/processfactory.hxx>
-
 #include <sfx2/dispatch.hxx>
-#include <sfx2/sfxmodelfactory.hxx>
-
 #include <sfx2/objsh.hxx>
-
 #include <sfx2/viewfrm.hxx>
 
-#include <cppuhelper/compbase.hxx>
-#include <cppuhelper/basemutex.hxx>
-
 #include "SelectionChangeHandler.hxx"
 
 using namespace css;
 
-namespace
-{
-uno::Reference<reflection::XIdlClass>
-TypeToIdlClass(const uno::Type& rType, const uno::Reference<uno::XComponentContext>& xContext)
-{
-    auto xReflection = reflection::theCoreReflection::get(xContext);
-
-    uno::Reference<reflection::XIdlClass> xRetClass;
-    typelib_TypeDescription* pTD = nullptr;
-    rType.getDescription(&pTD);
-    if (pTD)
-    {
-        OUString sOWName(pTD->pTypeName);
-        xRetClass = xReflection->forName(sOWName);
-    }
-    return xRetClass;
-}
-
-OUString AnyToString(const uno::Any& aValue, const uno::Reference<uno::XComponentContext>& xContext)
-{
-    uno::Type aValType = aValue.getValueType();
-    uno::TypeClass eType = aValType.getTypeClass();
-
-    OUString aRetStr;
-    switch (eType)
-    {
-        case uno::TypeClass_TYPE:
-        {
-            auto xIdlClass = TypeToIdlClass(aValType, xContext);
-            aRetStr = xIdlClass->getName() + " <TYPE>";
-            break;
-        }
-        case uno::TypeClass_INTERFACE:
-        {
-            auto xIdlClass = TypeToIdlClass(aValType, xContext);
-            aRetStr = xIdlClass->getName() + " <INTERFACE>";
-            break;
-        }
-        case uno::TypeClass_SERVICE:
-        {
-            auto xIdlClass = TypeToIdlClass(aValType, xContext);
-            aRetStr = xIdlClass->getName() + " <SERVICE>";
-            break;
-        }
-        case uno::TypeClass_STRUCT:
-        {
-            auto xIdlClass = TypeToIdlClass(aValType, xContext);
-            aRetStr = xIdlClass->getName() + " <STRUCT>";
-            break;
-        }
-        case uno::TypeClass_TYPEDEF:
-        {
-            auto xIdlClass = TypeToIdlClass(aValType, xContext);
-            aRetStr = xIdlClass->getName() + " <TYPEDEF>";
-            break;
-        }
-        case uno::TypeClass_ENUM:
-        {
-            auto xIdlClass = TypeToIdlClass(aValType, xContext);
-            aRetStr = xIdlClass->getName() + " <ENUM>";
-            break;
-        }
-        case uno::TypeClass_EXCEPTION:
-        {
-            auto xIdlClass = TypeToIdlClass(aValType, xContext);
-            aRetStr = xIdlClass->getName() + " <EXCEPTION>";
-            break;
-        }
-        case uno::TypeClass_SEQUENCE:
-        {
-            auto xIdlClass = TypeToIdlClass(aValType, xContext);
-            aRetStr = xIdlClass->getName() + " <SEQUENCE>";
-            break;
-        }
-        case uno::TypeClass_VOID:
-        {
-            auto xIdlClass = TypeToIdlClass(aValType, xContext);
-            aRetStr = xIdlClass->getName() + " <VOID>";
-            break;
-        }
-        case uno::TypeClass_ANY:
-        {
-            auto xIdlClass = TypeToIdlClass(aValType, xContext);
-            aRetStr = xIdlClass->getName() + " <ANY>";
-            break;
-        }
-        case uno::TypeClass_UNKNOWN:
-            aRetStr = "<Unknown>";
-            break;
-        case uno::TypeClass_BOOLEAN:
-        {
-            bool bBool = aValue.get<bool>();
-            aRetStr = bBool ? u"True" : u"False";
-            break;
-        }
-        case uno::TypeClass_CHAR:
-        {
-            sal_Unicode aChar = aValue.get<sal_Unicode>();
-            aRetStr = OUString::number(aChar);
-            break;
-        }
-        case uno::TypeClass_STRING:
-        {
-            aRetStr = "\"" + aValue.get<OUString>() + "\"";
-            break;
-        }
-        case uno::TypeClass_FLOAT:
-        {
-            auto aNumber = aValue.get<float>();
-            aRetStr = OUString::number(aNumber);
-            break;
-        }
-        case uno::TypeClass_DOUBLE:
-        {
-            auto aNumber = aValue.get<double>();
-            aRetStr = OUString::number(aNumber);
-            break;
-        }
-        case uno::TypeClass_BYTE:
-        {
-            auto aNumber = aValue.get<sal_Int8>();
-            aRetStr = OUString::number(aNumber);
-            break;
-        }
-        case uno::TypeClass_SHORT:
-        {
-            auto aNumber = aValue.get<sal_Int16>();
-            aRetStr = OUString::number(aNumber);
-            break;
-        }
-        case uno::TypeClass_LONG:
-        {
-            auto aNumber = aValue.get<sal_Int32>();
-            aRetStr = OUString::number(aNumber);
-            break;
-        }
-        case uno::TypeClass_HYPER:
-        {
-            auto aNumber = aValue.get<sal_Int64>();
-            aRetStr = OUString::number(aNumber);
-            break;
-        }
-
-        default:
-            break;
-    }
-    return aRetStr;
-}
-
-// Object inspector nodes
-
-class ObjectInspectorNode
-{
-public:
-    css::uno::Reference<css::uno::XInterface> mxObject;
-
-    ObjectInspectorNode() = default;
-
-    ObjectInspectorNode(css::uno::Reference<css::uno::XInterface> const& xObject)
-        : mxObject(xObject)
-    {
-    }
-
-    virtual ~ObjectInspectorNode() {}
-
-    virtual OUString getObjectName() = 0;
-
-    virtual void fillChildren(std::unique_ptr<weld::TreeView>& rTree, weld::TreeIter const& rParent)
-        = 0;
-};
-
-OUString lclAppendNode(std::unique_ptr<weld::TreeView>& pTree, ObjectInspectorNode* pEntry,
-                       bool bChildrenOnDemand = false)
-{
-    OUString sName = pEntry->getObjectName();
-    OUString sId(OUString::number(reinterpret_cast<sal_Int64>(pEntry)));
-    std::unique_ptr<weld::TreeIter> pCurrent = pTree->make_iterator();
-    pTree->insert(nullptr, -1, &sName, &sId, nullptr, nullptr, bChildrenOnDemand, pCurrent.get());
-    pTree->set_text_emphasis(*pCurrent, true, 0);
-    return sId;
-}
-
-OUString lclAppendNodeToParent(std::unique_ptr<weld::TreeView>& pTree,
-                               weld::TreeIter const& rParent, ObjectInspectorNode* pEntry,
-                               bool bChildrenOnDemand = false)
-{
-    OUString sName = pEntry->getObjectName();
-    OUString sId(OUString::number(reinterpret_cast<sal_Int64>(pEntry)));
-    std::unique_ptr<weld::TreeIter> pCurrent = pTree->make_iterator();
-    pTree->insert(&rParent, -1, &sName, &sId, nullptr, nullptr, bChildrenOnDemand, nullptr);
-    pTree->set_text_emphasis(*pCurrent, true, 0);
-    return sId;
-}
-
-OUString lclAppendNodeWithIterToParent(std::unique_ptr<weld::TreeView>& pTree,
-                                       weld::TreeIter const& rParent, weld::TreeIter& rCurrent,
-                                       ObjectInspectorNode* pEntry, bool bChildrenOnDemand = false)
-{
-    OUString sName = pEntry->getObjectName();
-    OUString sId(OUString::number(reinterpret_cast<sal_Int64>(pEntry)));
-    pTree->insert(&rParent, -1, &sName, &sId, nullptr, nullptr, bChildrenOnDemand, &rCurrent);
-    pTree->set_text_emphasis(rCurrent, true, 0);
-    return sId;
-}
-
-class ObjectInspectorNamedNode : public ObjectInspectorNode
-{
-public:
-    OUString msName;
-
-    ObjectInspectorNamedNode(OUString const& rName,
-                             css::uno::Reference<css::uno::XInterface> const& xObject)
-        : ObjectInspectorNode(xObject)
-        , msName(rName)
-    {
-    }
-
-    OUString getObjectName() override { return msName; }
-
-    void fillChildren(std::unique_ptr<weld::TreeView>& /*rTree*/,
-                      weld::TreeIter const& /*rParent*/) override
-    {
-    }
-};
-
-class ServicesNode : public ObjectInspectorNamedNode
-{
-public:
-    ServicesNode(css::uno::Reference<css::uno::XInterface> const& xObject)
-        : ObjectInspectorNamedNode("Services", xObject)
-    {
-    }
-
-    void fillChildren(std::unique_ptr<weld::TreeView>& pTree,
-                      weld::TreeIter const& rParent) override
-    {
-        auto xServiceInfo = uno::Reference<lang::XServiceInfo>(mxObject, uno::UNO_QUERY);
-        const uno::Sequence<OUString> aServiceNames(xServiceInfo->getSupportedServiceNames());
-        for (auto const& aServiceName : aServiceNames)
-        {
-            lclAppendNodeToParent(pTree, rParent,
-                                  new ObjectInspectorNamedNode(aServiceName, mxObject));
-        }
-    }
-};
-
-class GenericPropertiesNode : public ObjectInspectorNamedNode
-{
-public:
-    uno::Reference<uno::XComponentContext> mxContext;
-
-    GenericPropertiesNode(OUString const& rName, uno::Reference<uno::XInterface> const& xObject,
-                          uno::Reference<uno::XComponentContext> const& xContext)
-        : ObjectInspectorNamedNode(rName, xObject)
-        , mxContext(xContext)
-    {
-    }
-
-    void fillChildren(std::unique_ptr<weld::TreeView>& pTree,
-                      weld::TreeIter const& rParent) override
-    {
-        uno::Reference<beans::XIntrospection> xIntrospection
-            = beans::theIntrospection::get(mxContext);
-        auto xIntrospectionAccess = xIntrospection->inspect(uno::makeAny(mxObject));
-        auto xInvocationFactory = css::script::Invocation::create(mxContext);
-        uno::Sequence<uno::Any> aParameters = { uno::Any(mxObject) };
-        auto xInvocationInterface = xInvocationFactory->createInstanceWithArguments(aParameters);
-        uno::Reference<script::XInvocation> xInvocation(xInvocationInterface, uno::UNO_QUERY);
-
-        const auto xProperties = xIntrospectionAccess->getProperties(
-            beans::PropertyConcept::ALL - beans::PropertyConcept::DANGEROUS);
-
-        for (auto const& xProperty : xProperties)
-        {
-            OUString aValue;
-            uno::Any aAny;
-            uno::Reference<uno::XInterface> xCurrent = mxObject;
-
-            try
-            {
-                if (xInvocation->hasProperty(xProperty.Name))
-                {
-                    aAny = xInvocation->getValue(xProperty.Name);
-                    aValue = AnyToString(aAny, mxContext);
-                }
-            }
-            catch (...)
-            {
-                aValue = "<?>";
-            }
-
-            bool bComplex = false;
-            if (aAny.hasValue())
-            {
-                auto xInterface = uno::Reference<uno::XInterface>(aAny, uno::UNO_QUERY);
-                if (xInterface.is())
-                {
-                    xCurrent = xInterface;
-                    bComplex = true;
-                }
-            }
-
-            std::unique_ptr<weld::TreeIter> pCurrent = pTree->make_iterator();
-            if (bComplex)
-            {
-                lclAppendNodeWithIterToParent(
-                    pTree, rParent, *pCurrent,
-                    new GenericPropertiesNode(xProperty.Name, xCurrent, mxContext), true);
-            }
-            else
-            {
-                lclAppendNodeWithIterToParent(
-                    pTree, rParent, *pCurrent,
-                    new ObjectInspectorNamedNode(xProperty.Name, xCurrent), false);
-            }
-
-            if (!aValue.isEmpty())
-            {
-                pTree->set_text(*pCurrent, aValue, 1);
-            }
-        }
-    }
-};
-
-class PropertiesNode : public GenericPropertiesNode
-{
-public:
-    PropertiesNode(uno::Reference<uno::XInterface> const& xObject,
-                   uno::Reference<uno::XComponentContext> const& xContext)
-        : GenericPropertiesNode("Properties", xObject, xContext)
-    {
-    }
-};
-
-class InterfacesNode : public ObjectInspectorNamedNode
-{
-public:
-    InterfacesNode(css::uno::Reference<css::uno::XInterface> const& xObject)
-        : ObjectInspectorNamedNode("Interfaces", xObject)
-    {
-    }
-
-    void fillChildren(std::unique_ptr<weld::TreeView>& pTree,
-                      weld::TreeIter const& rParent) override
-    {
-        uno::Reference<lang::XTypeProvider> xTypeProvider(mxObject, uno::UNO_QUERY);
-        if (xTypeProvider.is())
-        {
-            const auto xSequenceTypes = xTypeProvider->getTypes();
-            for (auto const& xType : xSequenceTypes)
-            {
-                OUString aName = xType.getTypeName();
-                lclAppendNodeToParent(pTree, rParent,
-                                      new ObjectInspectorNamedNode(aName, mxObject));
-            }
-        }
-    }
-};
-
-class MethodsNode : public ObjectInspectorNamedNode
-{
-public:
-    uno::Reference<uno::XComponentContext> mxContext;
-
-    MethodsNode(css::uno::Reference<css::uno::XInterface> const& xObject,
-                uno::Reference<uno::XComponentContext> const& xContext)
-        : ObjectInspectorNamedNode("Methods", xObject)
-        , mxContext(xContext)
-    {
-    }
-
-    void fillChildren(std::unique_ptr<weld::TreeView>& pTree,
-                      weld::TreeIter const& rParent) override
-    {
-        uno::Reference<beans::XIntrospection> xIntrospection
-            = beans::theIntrospection::get(mxContext);
-        auto xIntrospectionAccess = xIntrospection->inspect(uno::makeAny(mxObject));
-
-        const auto xMethods = xIntrospectionAccess->getMethods(beans::MethodConcept::ALL);
-        for (auto const& xMethod : xMethods)
-        {
-            OUString aMethodName = xMethod->getName();
-
-            lclAppendNodeToParent(pTree, rParent,
-                                  new ObjectInspectorNamedNode(aMethodName, mxObject));
-        }
-    }
-};
-
-} // end anonymous namespace
-
 DevelopmentToolDockingWindow::DevelopmentToolDockingWindow(SfxBindings* pInputBindings,
                                                            SfxChildWindow* pChildWindow,
                                                            vcl::Window* pParent)
@@ -451,12 +34,11 @@ DevelopmentToolDockingWindow::DevelopmentToolDockingWindow(SfxBindings* pInputBi
     , maDocumentModelTreeHandler(
           mpDocumentModelTreeView,
           pInputBindings->GetDispatcher()->GetFrame()->GetObjectShell()->GetBaseModel())
+    , maObjectInspectorTreeHandler(mpClassListBox, mpClassNameLabel)
 {
     mpDocumentModelTreeView->connect_changed(
         LINK(this, DevelopmentToolDockingWindow, DocumentModelTreeViewSelectionHandler));
     mpSelectionToggle->connect_toggled(LINK(this, DevelopmentToolDockingWindow, SelectionToggled));
-    mpClassListBox->connect_expanding(
-        LINK(this, DevelopmentToolDockingWindow, ObjectInspectorExpandingHandler));
 
     auto* pViewFrame = pInputBindings->GetDispatcher()->GetFrame();
 
@@ -482,14 +64,14 @@ void DevelopmentToolDockingWindow::inspectSelectionOrRoot(
             auto xInterface = aAny.get<css::uno::Reference<css::uno::XInterface>>();
             if (xInterface.is())
             {
-                introspect(xInterface);
+                maObjectInspectorTreeHandler.introspect(xInterface);
                 mpSelectionToggle->set_state(TRISTATE_TRUE);
                 return;
             }
         }
     }
     mpSelectionToggle->set_state(TRISTATE_FALSE);
-    introspect(mxRoot);
+    maObjectInspectorTreeHandler.introspect(mxRoot);
 }
 
 IMPL_LINK(DevelopmentToolDockingWindow, DocumentModelTreeViewSelectionHandler, weld::TreeView&,
@@ -501,7 +83,7 @@ IMPL_LINK(DevelopmentToolDockingWindow, DocumentModelTreeViewSelectionHandler, w
     OUString sID = rView.get_selected_id();
     auto xObject = DocumentModelTreeHandler::getObjectByID(sID);
     if (xObject.is())
-        introspect(xObject);
+        maObjectInspectorTreeHandler.introspect(xObject);
 }
 
 IMPL_LINK_NOARG(DevelopmentToolDockingWindow, SelectionToggled, weld::ToggleButton&, void)
@@ -509,28 +91,6 @@ IMPL_LINK_NOARG(DevelopmentToolDockingWindow, SelectionToggled, weld::ToggleButt
     updateSelection();
 }
 
-void DevelopmentToolDockingWindow::clearObjectInspectorChildren(weld::TreeIter const& rParent)
-{
-    bool bChild = false;
-    do
-    {
-        bChild = mpClassListBox->iter_has_child(rParent);
-        if (bChild)
-        {
-            std::unique_ptr<weld::TreeIter> pChild = mpClassListBox->make_iterator(&rParent);
-            bChild = mpClassListBox->iter_children(*pChild);
-            if (bChild)
-            {
-                clearObjectInspectorChildren(*pChild);
-                OUString sID = mpClassListBox->get_id(*pChild);
-                auto* pEntry = reinterpret_cast<ObjectInspectorNode*>(sID.toInt64());
-                delete pEntry;
-                mpClassListBox->remove(*pChild);
-            }
-        }
-    } while (bChild);
-}
-
 DevelopmentToolDockingWindow::~DevelopmentToolDockingWindow() { disposeOnce(); }
 
 void DevelopmentToolDockingWindow::dispose()
@@ -541,15 +101,9 @@ void DevelopmentToolDockingWindow::dispose()
         pSelectionChangeHandler->stopListening();
 
     mxSelectionListener = uno::Reference<view::XSelectionChangeListener>();
-    maDocumentModelTreeHandler.dispose();
 
-    // destroy all ObjectInspectorNodes from the tree
-    mpClassListBox->all_foreach([this](weld::TreeIter& rEntry) {
-        OUString sID = mpClassListBox->get_id(rEntry);
-        auto* pEntry = reinterpret_cast<ObjectInspectorNode*>(sID.toInt64());
-        delete pEntry;
-        return false;
-    });
+    maDocumentModelTreeHandler.dispose();
+    maObjectInspectorTreeHandler.dispose();
 
     // dispose welded objects
     mpClassNameLabel.reset();
@@ -565,7 +119,7 @@ void DevelopmentToolDockingWindow::updateSelection()
     TriState eTriState = mpSelectionToggle->get_state();
     if (eTriState == TRISTATE_TRUE)
     {
-        introspect(mxCurrentSelection);
+        maObjectInspectorTreeHandler.introspect(mxCurrentSelection);
         maDocumentModelTreeHandler.selectObject(mxCurrentSelection);
     }
     else
@@ -584,20 +138,6 @@ void DevelopmentToolDockingWindow::ToggleFloatingMode()
     Invalidate();
 }
 
-IMPL_LINK(DevelopmentToolDockingWindow, ObjectInspectorExpandingHandler, weld::TreeIter const&,
-          rParent, bool)
-{
-    OUString sID = mpClassListBox->get_id(rParent);
-    if (sID.isEmpty())
-        return true;
-
-    clearObjectInspectorChildren(rParent);
-    auto* pNode = reinterpret_cast<ObjectInspectorNode*>(sID.toInt64());
-    pNode->fillChildren(mpClassListBox, rParent);
-
-    return true;
-}
-
 void DevelopmentToolDockingWindow::selectionChanged(
     uno::Reference<uno::XInterface> const& xInterface)
 {
@@ -605,31 +145,4 @@ void DevelopmentToolDockingWindow::selectionChanged(
     updateSelection();
 }
 
-void DevelopmentToolDockingWindow::introspect(uno::Reference<uno::XInterface> const& xInterface)
-{
-    if (!xInterface.is())
-        return;
-
-    uno::Reference<uno::XComponentContext> xContext = comphelper::getProcessComponentContext();
-    if (!xContext.is())
-        return;
-
-    // Set implementation name
-    auto xServiceInfo = uno::Reference<lang::XServiceInfo>(xInterface, uno::UNO_QUERY);
-    OUString aImplementationName = xServiceInfo->getImplementationName();
-    mpClassNameLabel->set_label(aImplementationName);
-
-    // fill object inspector
-
-    mpClassListBox->freeze();
-    mpClassListBox->clear();
-
-    lclAppendNode(mpClassListBox, new ServicesNode(xInterface), true);
-    lclAppendNode(mpClassListBox, new InterfacesNode(xInterface), true);
-    lclAppendNode(mpClassListBox, new PropertiesNode(xInterface, xContext), true);
-    lclAppendNode(mpClassListBox, new MethodsNode(xInterface, xContext), true);
-
-    mpClassListBox->thaw();
-}
-
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sfx2/source/devtools/ObjectInspectorTreeHandler.cxx b/sfx2/source/devtools/ObjectInspectorTreeHandler.cxx
new file mode 100644
index 000000000000..d69f8130f82b
--- /dev/null
+++ b/sfx2/source/devtools/ObjectInspectorTreeHandler.cxx
@@ -0,0 +1,503 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ */
+
+#include <memory>
+
+#include <sfx2/devtools/ObjectInspectorTreeHandler.hxx>
+
+#include <com/sun/star/uno/XInterface.hpp>
+#include <com/sun/star/uno/Reference.hxx>
+
+#include <com/sun/star/beans/theIntrospection.hpp>
+#include <com/sun/star/beans/XIntrospection.hpp>
+#include <com/sun/star/beans/XIntrospectionAccess.hpp>
+#include <com/sun/star/beans/Property.hpp>
+#include <com/sun/star/beans/PropertyConcept.hpp>
+#include <com/sun/star/beans/MethodConcept.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+
+#include <com/sun/star/reflection/theCoreReflection.hpp>
+#include <com/sun/star/reflection/XIdlReflection.hpp>
+#include <com/sun/star/reflection/XIdlMethod.hpp>
+
+#include <com/sun/star/script/XInvocation.hpp>
+#include <com/sun/star/script/Invocation.hpp>
+
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/lang/XTypeProvider.hpp>
+
+#include <comphelper/processfactory.hxx>
+
+using namespace css;
+
+namespace
+{
+uno::Reference<reflection::XIdlClass>
+TypeToIdlClass(const uno::Type& rType, const uno::Reference<uno::XComponentContext>& xContext)
+{
+    auto xReflection = reflection::theCoreReflection::get(xContext);
+
+    uno::Reference<reflection::XIdlClass> xRetClass;
+    typelib_TypeDescription* pTD = nullptr;
+    rType.getDescription(&pTD);
+    if (pTD)
+    {
+        OUString sOWName(pTD->pTypeName);
+        xRetClass = xReflection->forName(sOWName);
+    }
+    return xRetClass;
+}
+
+OUString AnyToString(const uno::Any& aValue, const uno::Reference<uno::XComponentContext>& xContext)
+{
+    uno::Type aValType = aValue.getValueType();
+    uno::TypeClass eType = aValType.getTypeClass();
+
+    OUString aRetStr;
+    switch (eType)
+    {
+        case uno::TypeClass_TYPE:
+        {
+            auto xIdlClass = TypeToIdlClass(aValType, xContext);
+            aRetStr = xIdlClass->getName() + " <TYPE>";
+            break;
+        }
+        case uno::TypeClass_INTERFACE:
+        {
+            auto xIdlClass = TypeToIdlClass(aValType, xContext);
+            aRetStr = xIdlClass->getName() + " <INTERFACE>";
+            break;
+        }
+        case uno::TypeClass_SERVICE:
+        {
+            auto xIdlClass = TypeToIdlClass(aValType, xContext);
+            aRetStr = xIdlClass->getName() + " <SERVICE>";
+            break;
+        }
+        case uno::TypeClass_STRUCT:
+        {
+            auto xIdlClass = TypeToIdlClass(aValType, xContext);
+            aRetStr = xIdlClass->getName() + " <STRUCT>";
+            break;
+        }
+        case uno::TypeClass_TYPEDEF:
+        {
+            auto xIdlClass = TypeToIdlClass(aValType, xContext);
+            aRetStr = xIdlClass->getName() + " <TYPEDEF>";
+            break;
+        }
+        case uno::TypeClass_ENUM:
+        {
+            auto xIdlClass = TypeToIdlClass(aValType, xContext);
+            aRetStr = xIdlClass->getName() + " <ENUM>";
+            break;
+        }
+        case uno::TypeClass_EXCEPTION:
+        {
+            auto xIdlClass = TypeToIdlClass(aValType, xContext);
+            aRetStr = xIdlClass->getName() + " <EXCEPTION>";
+            break;
+        }
+        case uno::TypeClass_SEQUENCE:
+        {
+            auto xIdlClass = TypeToIdlClass(aValType, xContext);
+            aRetStr = xIdlClass->getName() + " <SEQUENCE>";
+            break;
+        }
+        case uno::TypeClass_VOID:
+        {
+            auto xIdlClass = TypeToIdlClass(aValType, xContext);
+            aRetStr = xIdlClass->getName() + " <VOID>";
+            break;
+        }
+        case uno::TypeClass_ANY:
+        {
+            auto xIdlClass = TypeToIdlClass(aValType, xContext);
+            aRetStr = xIdlClass->getName() + " <ANY>";
+            break;
+        }
+        case uno::TypeClass_UNKNOWN:
+            aRetStr = "<Unknown>";
+            break;
+        case uno::TypeClass_BOOLEAN:
+        {
+            bool bBool = aValue.get<bool>();
+            aRetStr = bBool ? u"True" : u"False";
+            break;
+        }
+        case uno::TypeClass_CHAR:
+        {
+            sal_Unicode aChar = aValue.get<sal_Unicode>();
+            aRetStr = OUString::number(aChar);
+            break;
+        }
+        case uno::TypeClass_STRING:
+        {
+            aRetStr = "\"" + aValue.get<OUString>() + "\"";
+            break;
+        }
+        case uno::TypeClass_FLOAT:
+        {
+            auto aNumber = aValue.get<float>();
+            aRetStr = OUString::number(aNumber);
+            break;
+        }
+        case uno::TypeClass_DOUBLE:
+        {
+            auto aNumber = aValue.get<double>();
+            aRetStr = OUString::number(aNumber);
+            break;
+        }
+        case uno::TypeClass_BYTE:
+        {
+            auto aNumber = aValue.get<sal_Int8>();
+            aRetStr = OUString::number(aNumber);
+            break;
+        }
+        case uno::TypeClass_SHORT:
+        {
+            auto aNumber = aValue.get<sal_Int16>();
+            aRetStr = OUString::number(aNumber);
+            break;
+        }
+        case uno::TypeClass_LONG:
+        {
+            auto aNumber = aValue.get<sal_Int32>();
+            aRetStr = OUString::number(aNumber);
+            break;
+        }
+        case uno::TypeClass_HYPER:
+        {
+            auto aNumber = aValue.get<sal_Int64>();
+            aRetStr = OUString::number(aNumber);
+            break;
+        }
+
+        default:
+            break;
+    }
+    return aRetStr;
+}
+
+// Object inspector nodes
+
+class ObjectInspectorNode
+{
+public:
+    css::uno::Reference<css::uno::XInterface> mxObject;
+
+    ObjectInspectorNode() = default;
+
+    ObjectInspectorNode(css::uno::Reference<css::uno::XInterface> const& xObject)
+        : mxObject(xObject)
+    {
+    }
+
+    virtual ~ObjectInspectorNode() {}
+
+    virtual OUString getObjectName() = 0;
+
+    virtual void fillChildren(std::unique_ptr<weld::TreeView>& rTree, weld::TreeIter const& rParent)
+        = 0;
+};
+
+OUString lclAppendNode(std::unique_ptr<weld::TreeView>& pTree, ObjectInspectorNode* pEntry,
+                       bool bChildrenOnDemand = false)
+{
+    OUString sName = pEntry->getObjectName();
+    OUString sId(OUString::number(reinterpret_cast<sal_Int64>(pEntry)));
+    std::unique_ptr<weld::TreeIter> pCurrent = pTree->make_iterator();
+    pTree->insert(nullptr, -1, &sName, &sId, nullptr, nullptr, bChildrenOnDemand, pCurrent.get());
+    pTree->set_text_emphasis(*pCurrent, true, 0);
+    return sId;
+}
+
+OUString lclAppendNodeToParent(std::unique_ptr<weld::TreeView>& pTree,
+                               weld::TreeIter const& rParent, ObjectInspectorNode* pEntry,
+                               bool bChildrenOnDemand = false)
+{
+    OUString sName = pEntry->getObjectName();
+    OUString sId(OUString::number(reinterpret_cast<sal_Int64>(pEntry)));
+    std::unique_ptr<weld::TreeIter> pCurrent = pTree->make_iterator();
+    pTree->insert(&rParent, -1, &sName, &sId, nullptr, nullptr, bChildrenOnDemand, nullptr);
+    pTree->set_text_emphasis(*pCurrent, true, 0);
+    return sId;
+}
+
+OUString lclAppendNodeWithIterToParent(std::unique_ptr<weld::TreeView>& pTree,
+                                       weld::TreeIter const& rParent, weld::TreeIter& rCurrent,
+                                       ObjectInspectorNode* pEntry, bool bChildrenOnDemand = false)
+{
+    OUString sName = pEntry->getObjectName();
+    OUString sId(OUString::number(reinterpret_cast<sal_Int64>(pEntry)));
+    pTree->insert(&rParent, -1, &sName, &sId, nullptr, nullptr, bChildrenOnDemand, &rCurrent);
+    pTree->set_text_emphasis(rCurrent, true, 0);
+    return sId;
+}
+
+class ObjectInspectorNamedNode : public ObjectInspectorNode
+{
+public:
+    OUString msName;
+
+    ObjectInspectorNamedNode(OUString const& rName,
+                             css::uno::Reference<css::uno::XInterface> const& xObject)
+        : ObjectInspectorNode(xObject)
+        , msName(rName)
+    {
+    }
+
+    OUString getObjectName() override { return msName; }
+
+    void fillChildren(std::unique_ptr<weld::TreeView>& /*rTree*/,
+                      weld::TreeIter const& /*rParent*/) override
+    {
+    }
+};
+
+class ServicesNode : public ObjectInspectorNamedNode
+{
+public:
+    ServicesNode(css::uno::Reference<css::uno::XInterface> const& xObject)
+        : ObjectInspectorNamedNode("Services", xObject)
+    {
+    }
+
+    void fillChildren(std::unique_ptr<weld::TreeView>& pTree,
+                      weld::TreeIter const& rParent) override
+    {
+        auto xServiceInfo = uno::Reference<lang::XServiceInfo>(mxObject, uno::UNO_QUERY);
+        const uno::Sequence<OUString> aServiceNames(xServiceInfo->getSupportedServiceNames());
+        for (auto const& aServiceName : aServiceNames)
+        {
+            lclAppendNodeToParent(pTree, rParent,
+                                  new ObjectInspectorNamedNode(aServiceName, mxObject));
+        }
+    }
+};
+
+class GenericPropertiesNode : public ObjectInspectorNamedNode
+{
+public:
+    uno::Reference<uno::XComponentContext> mxContext;
+
+    GenericPropertiesNode(OUString const& rName, uno::Reference<uno::XInterface> const& xObject,
+                          uno::Reference<uno::XComponentContext> const& xContext)
+        : ObjectInspectorNamedNode(rName, xObject)
+        , mxContext(xContext)
+    {
+    }
+
+    void fillChildren(std::unique_ptr<weld::TreeView>& pTree,
+                      weld::TreeIter const& rParent) override
+    {
+        uno::Reference<beans::XIntrospection> xIntrospection
+            = beans::theIntrospection::get(mxContext);
+        auto xIntrospectionAccess = xIntrospection->inspect(uno::makeAny(mxObject));
+        auto xInvocationFactory = css::script::Invocation::create(mxContext);
+        uno::Sequence<uno::Any> aParameters = { uno::Any(mxObject) };
+        auto xInvocationInterface = xInvocationFactory->createInstanceWithArguments(aParameters);
+        uno::Reference<script::XInvocation> xInvocation(xInvocationInterface, uno::UNO_QUERY);
+
+        const auto xProperties = xIntrospectionAccess->getProperties(
+            beans::PropertyConcept::ALL - beans::PropertyConcept::DANGEROUS);
+
+        for (auto const& xProperty : xProperties)
+        {
+            OUString aValue;
+            uno::Any aAny;
+            uno::Reference<uno::XInterface> xCurrent = mxObject;
+
+            try
+            {
+                if (xInvocation->hasProperty(xProperty.Name))
+                {
+                    aAny = xInvocation->getValue(xProperty.Name);
+                    aValue = AnyToString(aAny, mxContext);
+                }
+            }
+            catch (...)
+            {
+                aValue = "<?>";
+            }
+
+            bool bComplex = false;
+            if (aAny.hasValue())
+            {
+                auto xInterface = uno::Reference<uno::XInterface>(aAny, uno::UNO_QUERY);
+                if (xInterface.is())
+                {
+                    xCurrent = xInterface;
+                    bComplex = true;
+                }
+            }
+
+            std::unique_ptr<weld::TreeIter> pCurrent = pTree->make_iterator();
+            if (bComplex)
+            {
+                lclAppendNodeWithIterToParent(
+                    pTree, rParent, *pCurrent,
+                    new GenericPropertiesNode(xProperty.Name, xCurrent, mxContext), true);
+            }
+            else
+            {
+                lclAppendNodeWithIterToParent(
+                    pTree, rParent, *pCurrent,
+                    new ObjectInspectorNamedNode(xProperty.Name, xCurrent), false);
+            }
+
+            if (!aValue.isEmpty())
+            {
+                pTree->set_text(*pCurrent, aValue, 1);
+            }
+        }
+    }
+};
+
+class PropertiesNode : public GenericPropertiesNode
+{
+public:
+    PropertiesNode(uno::Reference<uno::XInterface> const& xObject,
+                   uno::Reference<uno::XComponentContext> const& xContext)
+        : GenericPropertiesNode("Properties", xObject, xContext)
+    {
+    }
+};
+
+class InterfacesNode : public ObjectInspectorNamedNode
+{
+public:
+    InterfacesNode(css::uno::Reference<css::uno::XInterface> const& xObject)
+        : ObjectInspectorNamedNode("Interfaces", xObject)
+    {
+    }
+
+    void fillChildren(std::unique_ptr<weld::TreeView>& pTree,
+                      weld::TreeIter const& rParent) override
+    {
+        uno::Reference<lang::XTypeProvider> xTypeProvider(mxObject, uno::UNO_QUERY);
+        if (xTypeProvider.is())
+        {
+            const auto xSequenceTypes = xTypeProvider->getTypes();
+            for (auto const& xType : xSequenceTypes)
+            {
+                OUString aName = xType.getTypeName();
+                lclAppendNodeToParent(pTree, rParent,
+                                      new ObjectInspectorNamedNode(aName, mxObject));
+            }
+        }
+    }
+};
+
+class MethodsNode : public ObjectInspectorNamedNode
+{
+public:
+    uno::Reference<uno::XComponentContext> mxContext;
+
+    MethodsNode(css::uno::Reference<css::uno::XInterface> const& xObject,
+                uno::Reference<uno::XComponentContext> const& xContext)
+        : ObjectInspectorNamedNode("Methods", xObject)
+        , mxContext(xContext)
+    {
+    }
+
+    void fillChildren(std::unique_ptr<weld::TreeView>& pTree,
+                      weld::TreeIter const& rParent) override
+    {
+        uno::Reference<beans::XIntrospection> xIntrospection
+            = beans::theIntrospection::get(mxContext);
+        auto xIntrospectionAccess = xIntrospection->inspect(uno::makeAny(mxObject));
+
+        const auto xMethods = xIntrospectionAccess->getMethods(beans::MethodConcept::ALL);
+        for (auto const& xMethod : xMethods)
+        {
+            OUString aMethodName = xMethod->getName();
+
+            lclAppendNodeToParent(pTree, rParent,
+                                  new ObjectInspectorNamedNode(aMethodName, mxObject));
+        }
+    }
+};
+
+} // end anonymous namespace
+
+IMPL_LINK(ObjectInspectorTreeHandler, ExpandingHandler, weld::TreeIter const&, rParent, bool)
+{
+    OUString sID = mpObjectInspectorTree->get_id(rParent);
+    if (sID.isEmpty())
+        return true;
+
+    clearObjectInspectorChildren(rParent);
+    auto* pNode = reinterpret_cast<ObjectInspectorNode*>(sID.toInt64());
+    pNode->fillChildren(mpObjectInspectorTree, rParent);
+
+    return true;
+}
+
+void ObjectInspectorTreeHandler::clearObjectInspectorChildren(weld::TreeIter const& rParent)
+{
+    bool bChild = false;
+    do
+    {
+        bChild = mpObjectInspectorTree->iter_has_child(rParent);
+        if (bChild)
+        {
+            std::unique_ptr<weld::TreeIter> pChild = mpObjectInspectorTree->make_iterator(&rParent);
+            bChild = mpObjectInspectorTree->iter_children(*pChild);
+            if (bChild)
+            {
+                clearObjectInspectorChildren(*pChild);
+                OUString sID = mpObjectInspectorTree->get_id(*pChild);
+                auto* pEntry = reinterpret_cast<ObjectInspectorNode*>(sID.toInt64());
+                delete pEntry;
+                mpObjectInspectorTree->remove(*pChild);
+            }
+        }
+    } while (bChild);
+}
+
+void ObjectInspectorTreeHandler::introspect(uno::Reference<uno::XInterface> const& xInterface)
+{
+    if (!xInterface.is())
+        return;
+
+    uno::Reference<uno::XComponentContext> xContext = comphelper::getProcessComponentContext();
+    if (!xContext.is())
+        return;
+
+    // Set implementation name
+    auto xServiceInfo = uno::Reference<lang::XServiceInfo>(xInterface, uno::UNO_QUERY);
+    OUString aImplementationName = xServiceInfo->getImplementationName();
+    mpClassNameLabel->set_label(aImplementationName);
+
+    // fill object inspector
+    mpObjectInspectorTree->freeze();
+    mpObjectInspectorTree->clear();
+
+    lclAppendNode(mpObjectInspectorTree, new ServicesNode(xInterface), true);
+    lclAppendNode(mpObjectInspectorTree, new InterfacesNode(xInterface), true);
+    lclAppendNode(mpObjectInspectorTree, new PropertiesNode(xInterface, xContext), true);
+    lclAppendNode(mpObjectInspectorTree, new MethodsNode(xInterface, xContext), true);
+
+    mpObjectInspectorTree->thaw();
+}
+
+void ObjectInspectorTreeHandler::dispose()
+{
+    // destroy all ObjectInspectorNodes from the tree
+    mpObjectInspectorTree->all_foreach([this](weld::TreeIter& rEntry) {
+        OUString sID = mpObjectInspectorTree->get_id(rEntry);
+        auto* pEntry = reinterpret_cast<ObjectInspectorNode*>(sID.toInt64());
+        delete pEntry;
+        return false;
+    });
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */


More information about the Libreoffice-commits mailing list