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:
committed by
Tomaž Vajngerl
parent
a1ca311061
commit
e44639f500
@@ -16,6 +16,7 @@
|
|||||||
#include <vcl/weld.hxx>
|
#include <vcl/weld.hxx>
|
||||||
|
|
||||||
#include <sfx2/devtools/DocumentModelTreeHandler.hxx>
|
#include <sfx2/devtools/DocumentModelTreeHandler.hxx>
|
||||||
|
#include <sfx2/devtools/ObjectInspectorTreeHandler.hxx>
|
||||||
|
|
||||||
#include <com/sun/star/uno/XInterface.hpp>
|
#include <com/sun/star/uno/XInterface.hpp>
|
||||||
#include <com/sun/star/uno/Reference.hxx>
|
#include <com/sun/star/uno/Reference.hxx>
|
||||||
@@ -37,18 +38,15 @@ private:
|
|||||||
css::uno::Reference<css::view::XSelectionChangeListener> mxSelectionListener;
|
css::uno::Reference<css::view::XSelectionChangeListener> mxSelectionListener;
|
||||||
|
|
||||||
DocumentModelTreeHandler maDocumentModelTreeHandler;
|
DocumentModelTreeHandler maDocumentModelTreeHandler;
|
||||||
|
ObjectInspectorTreeHandler maObjectInspectorTreeHandler;
|
||||||
|
|
||||||
DECL_LINK(DocumentModelTreeViewSelectionHandler, weld::TreeView&, void);
|
DECL_LINK(DocumentModelTreeViewSelectionHandler, weld::TreeView&, void);
|
||||||
DECL_LINK(SelectionToggled, weld::ToggleButton&, void);
|
DECL_LINK(SelectionToggled, weld::ToggleButton&, void);
|
||||||
|
|
||||||
DECL_LINK(ObjectInspectorExpandingHandler, const weld::TreeIter&, bool);
|
|
||||||
|
|
||||||
void inspectDocument();
|
void inspectDocument();
|
||||||
void updateSelection();
|
void updateSelection();
|
||||||
void inspectSelectionOrRoot(css::uno::Reference<css::frame::XController> const& xController);
|
void inspectSelectionOrRoot(css::uno::Reference<css::frame::XController> const& xController);
|
||||||
|
|
||||||
void clearObjectInspectorChildren(weld::TreeIter const& rParent);
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
DevelopmentToolDockingWindow(SfxBindings* pBindings, SfxChildWindow* pChildWindow,
|
DevelopmentToolDockingWindow(SfxBindings* pBindings, SfxChildWindow* pChildWindow,
|
||||||
vcl::Window* pParent);
|
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/DevelopmentToolChildWindow \
|
||||||
sfx2/source/devtools/DevelopmentToolDockingWindow \
|
sfx2/source/devtools/DevelopmentToolDockingWindow \
|
||||||
sfx2/source/devtools/DocumentModelTreeHandler \
|
sfx2/source/devtools/DocumentModelTreeHandler \
|
||||||
|
sfx2/source/devtools/ObjectInspectorTreeHandler \
|
||||||
sfx2/source/dialog/alienwarn \
|
sfx2/source/dialog/alienwarn \
|
||||||
sfx2/source/dialog/backingcomp \
|
sfx2/source/dialog/backingcomp \
|
||||||
sfx2/source/dialog/backingwindow \
|
sfx2/source/dialog/backingwindow \
|
||||||
|
@@ -12,433 +12,16 @@
|
|||||||
|
|
||||||
#include <sfx2/devtools/DevelopmentToolDockingWindow.hxx>
|
#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 <com/sun/star/view/XSelectionSupplier.hpp>
|
||||||
|
|
||||||
#include <comphelper/processfactory.hxx>
|
|
||||||
|
|
||||||
#include <sfx2/dispatch.hxx>
|
#include <sfx2/dispatch.hxx>
|
||||||
#include <sfx2/sfxmodelfactory.hxx>
|
|
||||||
|
|
||||||
#include <sfx2/objsh.hxx>
|
#include <sfx2/objsh.hxx>
|
||||||
|
|
||||||
#include <sfx2/viewfrm.hxx>
|
#include <sfx2/viewfrm.hxx>
|
||||||
|
|
||||||
#include <cppuhelper/compbase.hxx>
|
|
||||||
#include <cppuhelper/basemutex.hxx>
|
|
||||||
|
|
||||||
#include "SelectionChangeHandler.hxx"
|
#include "SelectionChangeHandler.hxx"
|
||||||
|
|
||||||
using namespace css;
|
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,
|
DevelopmentToolDockingWindow::DevelopmentToolDockingWindow(SfxBindings* pInputBindings,
|
||||||
SfxChildWindow* pChildWindow,
|
SfxChildWindow* pChildWindow,
|
||||||
vcl::Window* pParent)
|
vcl::Window* pParent)
|
||||||
@@ -451,12 +34,11 @@ DevelopmentToolDockingWindow::DevelopmentToolDockingWindow(SfxBindings* pInputBi
|
|||||||
, maDocumentModelTreeHandler(
|
, maDocumentModelTreeHandler(
|
||||||
mpDocumentModelTreeView,
|
mpDocumentModelTreeView,
|
||||||
pInputBindings->GetDispatcher()->GetFrame()->GetObjectShell()->GetBaseModel())
|
pInputBindings->GetDispatcher()->GetFrame()->GetObjectShell()->GetBaseModel())
|
||||||
|
, maObjectInspectorTreeHandler(mpClassListBox, mpClassNameLabel)
|
||||||
{
|
{
|
||||||
mpDocumentModelTreeView->connect_changed(
|
mpDocumentModelTreeView->connect_changed(
|
||||||
LINK(this, DevelopmentToolDockingWindow, DocumentModelTreeViewSelectionHandler));
|
LINK(this, DevelopmentToolDockingWindow, DocumentModelTreeViewSelectionHandler));
|
||||||
mpSelectionToggle->connect_toggled(LINK(this, DevelopmentToolDockingWindow, SelectionToggled));
|
mpSelectionToggle->connect_toggled(LINK(this, DevelopmentToolDockingWindow, SelectionToggled));
|
||||||
mpClassListBox->connect_expanding(
|
|
||||||
LINK(this, DevelopmentToolDockingWindow, ObjectInspectorExpandingHandler));
|
|
||||||
|
|
||||||
auto* pViewFrame = pInputBindings->GetDispatcher()->GetFrame();
|
auto* pViewFrame = pInputBindings->GetDispatcher()->GetFrame();
|
||||||
|
|
||||||
@@ -482,14 +64,14 @@ void DevelopmentToolDockingWindow::inspectSelectionOrRoot(
|
|||||||
auto xInterface = aAny.get<css::uno::Reference<css::uno::XInterface>>();
|
auto xInterface = aAny.get<css::uno::Reference<css::uno::XInterface>>();
|
||||||
if (xInterface.is())
|
if (xInterface.is())
|
||||||
{
|
{
|
||||||
introspect(xInterface);
|
maObjectInspectorTreeHandler.introspect(xInterface);
|
||||||
mpSelectionToggle->set_state(TRISTATE_TRUE);
|
mpSelectionToggle->set_state(TRISTATE_TRUE);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mpSelectionToggle->set_state(TRISTATE_FALSE);
|
mpSelectionToggle->set_state(TRISTATE_FALSE);
|
||||||
introspect(mxRoot);
|
maObjectInspectorTreeHandler.introspect(mxRoot);
|
||||||
}
|
}
|
||||||
|
|
||||||
IMPL_LINK(DevelopmentToolDockingWindow, DocumentModelTreeViewSelectionHandler, weld::TreeView&,
|
IMPL_LINK(DevelopmentToolDockingWindow, DocumentModelTreeViewSelectionHandler, weld::TreeView&,
|
||||||
@@ -501,7 +83,7 @@ IMPL_LINK(DevelopmentToolDockingWindow, DocumentModelTreeViewSelectionHandler, w
|
|||||||
OUString sID = rView.get_selected_id();
|
OUString sID = rView.get_selected_id();
|
||||||
auto xObject = DocumentModelTreeHandler::getObjectByID(sID);
|
auto xObject = DocumentModelTreeHandler::getObjectByID(sID);
|
||||||
if (xObject.is())
|
if (xObject.is())
|
||||||
introspect(xObject);
|
maObjectInspectorTreeHandler.introspect(xObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
IMPL_LINK_NOARG(DevelopmentToolDockingWindow, SelectionToggled, weld::ToggleButton&, void)
|
IMPL_LINK_NOARG(DevelopmentToolDockingWindow, SelectionToggled, weld::ToggleButton&, void)
|
||||||
@@ -509,28 +91,6 @@ IMPL_LINK_NOARG(DevelopmentToolDockingWindow, SelectionToggled, weld::ToggleButt
|
|||||||
updateSelection();
|
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(); }
|
DevelopmentToolDockingWindow::~DevelopmentToolDockingWindow() { disposeOnce(); }
|
||||||
|
|
||||||
void DevelopmentToolDockingWindow::dispose()
|
void DevelopmentToolDockingWindow::dispose()
|
||||||
@@ -541,15 +101,9 @@ void DevelopmentToolDockingWindow::dispose()
|
|||||||
pSelectionChangeHandler->stopListening();
|
pSelectionChangeHandler->stopListening();
|
||||||
|
|
||||||
mxSelectionListener = uno::Reference<view::XSelectionChangeListener>();
|
mxSelectionListener = uno::Reference<view::XSelectionChangeListener>();
|
||||||
maDocumentModelTreeHandler.dispose();
|
|
||||||
|
|
||||||
// destroy all ObjectInspectorNodes from the tree
|
maDocumentModelTreeHandler.dispose();
|
||||||
mpClassListBox->all_foreach([this](weld::TreeIter& rEntry) {
|
maObjectInspectorTreeHandler.dispose();
|
||||||
OUString sID = mpClassListBox->get_id(rEntry);
|
|
||||||
auto* pEntry = reinterpret_cast<ObjectInspectorNode*>(sID.toInt64());
|
|
||||||
delete pEntry;
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
|
|
||||||
// dispose welded objects
|
// dispose welded objects
|
||||||
mpClassNameLabel.reset();
|
mpClassNameLabel.reset();
|
||||||
@@ -565,7 +119,7 @@ void DevelopmentToolDockingWindow::updateSelection()
|
|||||||
TriState eTriState = mpSelectionToggle->get_state();
|
TriState eTriState = mpSelectionToggle->get_state();
|
||||||
if (eTriState == TRISTATE_TRUE)
|
if (eTriState == TRISTATE_TRUE)
|
||||||
{
|
{
|
||||||
introspect(mxCurrentSelection);
|
maObjectInspectorTreeHandler.introspect(mxCurrentSelection);
|
||||||
maDocumentModelTreeHandler.selectObject(mxCurrentSelection);
|
maDocumentModelTreeHandler.selectObject(mxCurrentSelection);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -584,20 +138,6 @@ void DevelopmentToolDockingWindow::ToggleFloatingMode()
|
|||||||
Invalidate();
|
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(
|
void DevelopmentToolDockingWindow::selectionChanged(
|
||||||
uno::Reference<uno::XInterface> const& xInterface)
|
uno::Reference<uno::XInterface> const& xInterface)
|
||||||
{
|
{
|
||||||
@@ -605,31 +145,4 @@ void DevelopmentToolDockingWindow::selectionChanged(
|
|||||||
updateSelection();
|
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: */
|
/* 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: */
|
Reference in New Issue
Block a user