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@gmail.com>
This commit is contained in:
parent
a1ca311061
commit
e44639f500
@ -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);
|
||||
|
44
include/sfx2/devtools/ObjectInspectorTreeHandler.hxx
Normal file
44
include/sfx2/devtools/ObjectInspectorTreeHandler.hxx
Normal file
@ -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: */
|
@ -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 \
|
||||
|
@ -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: */
|
||||
|
503
sfx2/source/devtools/ObjectInspectorTreeHandler.cxx
Normal file
503
sfx2/source/devtools/ObjectInspectorTreeHandler.cxx
Normal file
@ -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: */
|
Loading…
x
Reference in New Issue
Block a user