2021-02-08 22:41:36 +09:00
|
|
|
/* -*- 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>
|
2021-02-10 18:12:38 +09:00
|
|
|
#include <com/sun/star/reflection/XIdlArray.hpp>
|
2021-02-08 22:41:36 +09:00
|
|
|
|
|
|
|
#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;
|
|
|
|
}
|
|
|
|
|
2021-02-09 19:29:50 +09:00
|
|
|
OUString AnyToString(const uno::Any& aValue)
|
2021-02-08 22:41:36 +09:00
|
|
|
{
|
|
|
|
uno::Type aValType = aValue.getValueType();
|
|
|
|
uno::TypeClass eType = aValType.getTypeClass();
|
|
|
|
|
|
|
|
OUString aRetStr;
|
|
|
|
switch (eType)
|
|
|
|
{
|
2021-02-10 17:38:14 +09:00
|
|
|
case uno::TypeClass_INTERFACE:
|
|
|
|
{
|
|
|
|
aRetStr = "<Object>";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case uno::TypeClass_STRUCT:
|
|
|
|
{
|
|
|
|
aRetStr = "<Struct>";
|
|
|
|
break;
|
|
|
|
}
|
2021-02-08 22:41:36 +09:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2021-02-09 19:29:50 +09:00
|
|
|
OUString getAnyType(const uno::Any& aValue, const uno::Reference<uno::XComponentContext>& xContext)
|
|
|
|
{
|
|
|
|
uno::Type aValType = aValue.getValueType();
|
|
|
|
auto xIdlClass = TypeToIdlClass(aValType, xContext);
|
|
|
|
return xIdlClass->getName();
|
|
|
|
}
|
|
|
|
|
2021-02-08 22:41:36 +09:00
|
|
|
// Object inspector nodes
|
|
|
|
|
2021-02-10 16:54:59 +09:00
|
|
|
class ObjectInspectorNodeInterface
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
ObjectInspectorNodeInterface() = default;
|
|
|
|
|
|
|
|
virtual ~ObjectInspectorNodeInterface() {}
|
|
|
|
|
|
|
|
virtual OUString getObjectName() = 0;
|
|
|
|
|
2021-02-10 17:33:33 +09:00
|
|
|
virtual bool shouldShowExpander() { return false; }
|
|
|
|
|
2021-02-10 16:54:59 +09:00
|
|
|
virtual void fillChildren(std::unique_ptr<weld::TreeView>& rTree, weld::TreeIter const& rParent)
|
|
|
|
= 0;
|
2021-02-10 17:33:33 +09:00
|
|
|
|
|
|
|
virtual std::vector<std::pair<sal_Int32, OUString>> getColumnValues()
|
|
|
|
{
|
|
|
|
return std::vector<std::pair<sal_Int32, OUString>>();
|
|
|
|
}
|
2021-02-10 16:54:59 +09:00
|
|
|
};
|
|
|
|
|
|
|
|
class ObjectInspectorNode : public ObjectInspectorNodeInterface
|
2021-02-08 22:41:36 +09:00
|
|
|
{
|
|
|
|
public:
|
|
|
|
css::uno::Reference<css::uno::XInterface> mxObject;
|
|
|
|
|
|
|
|
ObjectInspectorNode() = default;
|
|
|
|
|
|
|
|
ObjectInspectorNode(css::uno::Reference<css::uno::XInterface> const& xObject)
|
|
|
|
: mxObject(xObject)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2021-02-10 17:33:33 +09:00
|
|
|
OUString lclAppendNode(std::unique_ptr<weld::TreeView>& pTree, ObjectInspectorNodeInterface* pEntry)
|
2021-02-08 22:41:36 +09:00
|
|
|
{
|
|
|
|
OUString sName = pEntry->getObjectName();
|
|
|
|
OUString sId(OUString::number(reinterpret_cast<sal_Int64>(pEntry)));
|
|
|
|
std::unique_ptr<weld::TreeIter> pCurrent = pTree->make_iterator();
|
2021-02-10 17:33:33 +09:00
|
|
|
pTree->insert(nullptr, -1, &sName, &sId, nullptr, nullptr, pEntry->shouldShowExpander(),
|
|
|
|
pCurrent.get());
|
2021-02-08 22:41:36 +09:00
|
|
|
pTree->set_text_emphasis(*pCurrent, true, 0);
|
2021-02-10 17:33:33 +09:00
|
|
|
|
|
|
|
for (auto const& rPair : pEntry->getColumnValues())
|
|
|
|
{
|
|
|
|
pTree->set_text(*pCurrent, rPair.second, rPair.first);
|
|
|
|
}
|
|
|
|
|
2021-02-08 22:41:36 +09:00
|
|
|
return sId;
|
|
|
|
}
|
|
|
|
|
|
|
|
OUString lclAppendNodeToParent(std::unique_ptr<weld::TreeView>& pTree,
|
2021-02-10 17:33:33 +09:00
|
|
|
weld::TreeIter const& rParent, ObjectInspectorNodeInterface* pEntry)
|
2021-02-08 22:41:36 +09:00
|
|
|
{
|
|
|
|
OUString sName = pEntry->getObjectName();
|
|
|
|
OUString sId(OUString::number(reinterpret_cast<sal_Int64>(pEntry)));
|
|
|
|
std::unique_ptr<weld::TreeIter> pCurrent = pTree->make_iterator();
|
2021-02-10 17:33:33 +09:00
|
|
|
pTree->insert(&rParent, -1, &sName, &sId, nullptr, nullptr, pEntry->shouldShowExpander(),
|
|
|
|
pCurrent.get());
|
2021-02-08 22:41:36 +09:00
|
|
|
pTree->set_text_emphasis(*pCurrent, true, 0);
|
|
|
|
|
2021-02-10 17:33:33 +09:00
|
|
|
for (auto const& rPair : pEntry->getColumnValues())
|
|
|
|
{
|
|
|
|
pTree->set_text(*pCurrent, rPair.second, rPair.first);
|
|
|
|
}
|
|
|
|
|
2021-02-08 22:41:36 +09:00
|
|
|
return sId;
|
|
|
|
}
|
|
|
|
|
|
|
|
class ObjectInspectorNamedNode : public ObjectInspectorNode
|
|
|
|
{
|
2021-02-10 17:33:33 +09:00
|
|
|
protected:
|
2021-02-08 22:41:36 +09:00
|
|
|
OUString msName;
|
2021-02-10 17:33:33 +09:00
|
|
|
uno::Any maAny;
|
|
|
|
uno::Reference<uno::XComponentContext> mxContext;
|
2021-02-08 22:41:36 +09:00
|
|
|
|
2021-02-10 17:33:33 +09:00
|
|
|
public:
|
2021-02-08 22:41:36 +09:00
|
|
|
ObjectInspectorNamedNode(OUString const& rName,
|
2021-02-10 17:33:33 +09:00
|
|
|
css::uno::Reference<css::uno::XInterface> const& xObject,
|
|
|
|
uno::Any aAny = uno::Any(),
|
|
|
|
uno::Reference<uno::XComponentContext> const& xContext
|
|
|
|
= uno::Reference<uno::XComponentContext>())
|
2021-02-08 22:41:36 +09:00
|
|
|
: ObjectInspectorNode(xObject)
|
|
|
|
, msName(rName)
|
2021-02-10 17:33:33 +09:00
|
|
|
, maAny(aAny)
|
|
|
|
, mxContext(xContext)
|
2021-02-08 22:41:36 +09:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2021-02-10 18:12:38 +09:00
|
|
|
bool shouldShowExpander() override
|
|
|
|
{
|
|
|
|
if (maAny.hasValue())
|
|
|
|
{
|
2021-02-10 20:56:32 +09:00
|
|
|
switch (maAny.getValueType().getTypeClass())
|
|
|
|
{
|
|
|
|
case uno::TypeClass_INTERFACE:
|
|
|
|
case uno::TypeClass_SEQUENCE:
|
|
|
|
return true;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2021-02-10 18:12:38 +09:00
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2021-02-08 22:41:36 +09:00
|
|
|
OUString getObjectName() override { return msName; }
|
|
|
|
|
|
|
|
void fillChildren(std::unique_ptr<weld::TreeView>& /*rTree*/,
|
|
|
|
weld::TreeIter const& /*rParent*/) override
|
|
|
|
{
|
|
|
|
}
|
2021-02-10 17:33:33 +09:00
|
|
|
|
|
|
|
std::vector<std::pair<sal_Int32, OUString>> getColumnValues() override
|
|
|
|
{
|
|
|
|
if (maAny.hasValue())
|
|
|
|
{
|
|
|
|
OUString aValue = AnyToString(maAny);
|
|
|
|
OUString aType = getAnyType(maAny, mxContext);
|
|
|
|
|
|
|
|
return {
|
|
|
|
{ 1, aValue },
|
|
|
|
{ 2, aType },
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
return ObjectInspectorNodeInterface::getColumnValues();
|
|
|
|
}
|
2021-02-08 22:41:36 +09:00
|
|
|
};
|
|
|
|
|
|
|
|
class ServicesNode : public ObjectInspectorNamedNode
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
ServicesNode(css::uno::Reference<css::uno::XInterface> const& xObject)
|
|
|
|
: ObjectInspectorNamedNode("Services", xObject)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2021-02-10 17:33:33 +09:00
|
|
|
bool shouldShowExpander() override { return true; }
|
|
|
|
|
2021-02-08 22:41:36 +09:00
|
|
|
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:
|
|
|
|
GenericPropertiesNode(OUString const& rName, uno::Reference<uno::XInterface> const& xObject,
|
2021-02-10 17:33:33 +09:00
|
|
|
uno::Any aAny, uno::Reference<uno::XComponentContext> const& xContext)
|
|
|
|
: ObjectInspectorNamedNode(rName, xObject, aAny, xContext)
|
2021-02-08 22:41:36 +09:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void fillChildren(std::unique_ptr<weld::TreeView>& pTree,
|
2021-02-10 16:50:26 +09:00
|
|
|
weld::TreeIter const& rParent) override;
|
2021-02-08 22:41:36 +09:00
|
|
|
};
|
|
|
|
|
|
|
|
class PropertiesNode : public GenericPropertiesNode
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
PropertiesNode(uno::Reference<uno::XInterface> const& xObject,
|
|
|
|
uno::Reference<uno::XComponentContext> const& xContext)
|
2021-02-10 17:33:33 +09:00
|
|
|
: GenericPropertiesNode("Properties", xObject, uno::Any(), xContext)
|
2021-02-08 22:41:36 +09:00
|
|
|
{
|
|
|
|
}
|
2021-02-10 18:12:38 +09:00
|
|
|
|
|
|
|
bool shouldShowExpander() override { return true; }
|
2021-02-08 22:41:36 +09:00
|
|
|
};
|
|
|
|
|
|
|
|
class InterfacesNode : public ObjectInspectorNamedNode
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
InterfacesNode(css::uno::Reference<css::uno::XInterface> const& xObject)
|
|
|
|
: ObjectInspectorNamedNode("Interfaces", xObject)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2021-02-10 17:33:33 +09:00
|
|
|
bool shouldShowExpander() override { return true; }
|
|
|
|
|
2021-02-08 22:41:36 +09:00
|
|
|
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:
|
|
|
|
MethodsNode(css::uno::Reference<css::uno::XInterface> const& xObject,
|
|
|
|
uno::Reference<uno::XComponentContext> const& xContext)
|
2021-02-10 17:33:33 +09:00
|
|
|
: ObjectInspectorNamedNode("Methods", xObject, uno::Any(xObject), xContext)
|
2021-02-08 22:41:36 +09:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2021-02-10 17:33:33 +09:00
|
|
|
bool shouldShowExpander() override { return true; }
|
|
|
|
|
2021-02-08 22:41:36 +09:00
|
|
|
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));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2021-02-10 18:12:38 +09:00
|
|
|
class SequenceNode : public ObjectInspectorNodeInterface
|
|
|
|
{
|
|
|
|
private:
|
|
|
|
OUString maString;
|
|
|
|
uno::Any maAny;
|
|
|
|
uno::Reference<uno::XComponentContext> mxContext;
|
|
|
|
|
|
|
|
public:
|
|
|
|
SequenceNode(OUString const& rString, uno::Any const& rAny,
|
|
|
|
uno::Reference<uno::XComponentContext> const& xContext)
|
|
|
|
: maString(rString)
|
|
|
|
, maAny(rAny)
|
|
|
|
, mxContext(xContext)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
bool shouldShowExpander() override { return true; }
|
|
|
|
|
|
|
|
OUString getObjectName() override { return maString; }
|
|
|
|
|
|
|
|
void fillChildren(std::unique_ptr<weld::TreeView>& pTree,
|
|
|
|
weld::TreeIter const& rParent) override
|
|
|
|
{
|
|
|
|
auto xReflection = reflection::theCoreReflection::get(mxContext);
|
|
|
|
uno::Reference<reflection::XIdlClass> xClass
|
|
|
|
= xReflection->forName(maAny.getValueType().getTypeName());
|
|
|
|
uno::Reference<reflection::XIdlArray> xIdlArray = xClass->getArray();
|
|
|
|
|
|
|
|
int nLength = xIdlArray->getLen(maAny);
|
|
|
|
|
|
|
|
for (int i = 0; i < nLength; i++)
|
|
|
|
{
|
|
|
|
uno::Any aCurrentAny = xIdlArray->get(maAny, i);
|
|
|
|
uno::Reference<uno::XInterface> xCurrent;
|
|
|
|
if (aCurrentAny.hasValue())
|
|
|
|
{
|
2021-02-10 20:56:32 +09:00
|
|
|
switch (aCurrentAny.getValueType().getTypeClass())
|
|
|
|
{
|
|
|
|
case uno::TypeClass_INTERFACE:
|
|
|
|
{
|
|
|
|
auto xInterface
|
|
|
|
= uno::Reference<uno::XInterface>(aCurrentAny, uno::UNO_QUERY);
|
|
|
|
lclAppendNodeToParent(pTree, rParent,
|
|
|
|
new GenericPropertiesNode(OUString::number(i),
|
|
|
|
xInterface, aCurrentAny,
|
|
|
|
mxContext));
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case uno::TypeClass_SEQUENCE:
|
|
|
|
{
|
|
|
|
lclAppendNodeToParent(
|
|
|
|
pTree, rParent,
|
|
|
|
new SequenceNode(OUString::number(i), aCurrentAny, mxContext));
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
{
|
|
|
|
lclAppendNodeToParent(
|
|
|
|
pTree, rParent,
|
|
|
|
new ObjectInspectorNamedNode(OUString::number(i),
|
|
|
|
uno::Reference<uno::XInterface>(),
|
|
|
|
aCurrentAny, mxContext));
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2021-02-10 18:12:38 +09:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
std::vector<std::pair<sal_Int32, OUString>> getColumnValues() override
|
|
|
|
{
|
|
|
|
auto xReflection = reflection::theCoreReflection::get(mxContext);
|
|
|
|
uno::Reference<reflection::XIdlClass> xClass
|
|
|
|
= xReflection->forName(maAny.getValueType().getTypeName());
|
|
|
|
uno::Reference<reflection::XIdlArray> xIdlArray = xClass->getArray();
|
|
|
|
|
|
|
|
int nLength = xIdlArray->getLen(maAny);
|
|
|
|
|
|
|
|
OUString aValue = "0 to " + OUString::number(nLength - 1);
|
|
|
|
OUString aType = getAnyType(maAny, mxContext);
|
|
|
|
|
|
|
|
return {
|
|
|
|
{ 1, aValue },
|
|
|
|
{ 2, aType },
|
|
|
|
};
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2021-02-10 16:50:26 +09:00
|
|
|
void GenericPropertiesNode::fillChildren(std::unique_ptr<weld::TreeView>& pTree,
|
|
|
|
weld::TreeIter const& rParent)
|
|
|
|
{
|
2021-02-10 20:56:32 +09:00
|
|
|
uno::Any aAny = maAny;
|
|
|
|
if (!maAny.hasValue())
|
|
|
|
{
|
|
|
|
aAny = uno::makeAny(mxObject);
|
|
|
|
}
|
2021-02-10 18:12:38 +09:00
|
|
|
|
2021-02-10 16:50:26 +09:00
|
|
|
uno::Reference<beans::XIntrospection> xIntrospection = beans::theIntrospection::get(mxContext);
|
2021-02-10 20:56:32 +09:00
|
|
|
auto xIntrospectionAccess = xIntrospection->inspect(aAny);
|
2021-02-10 16:50:26 +09:00
|
|
|
auto xInvocationFactory = css::script::Invocation::create(mxContext);
|
2021-02-10 20:56:32 +09:00
|
|
|
uno::Sequence<uno::Any> aParameters = { aAny };
|
2021-02-10 16:50:26 +09:00
|
|
|
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)
|
|
|
|
{
|
2021-02-10 20:56:32 +09:00
|
|
|
uno::Any aCurrentAny;
|
2021-02-10 16:50:26 +09:00
|
|
|
|
|
|
|
try
|
|
|
|
{
|
|
|
|
if (xInvocation->hasProperty(xProperty.Name))
|
|
|
|
{
|
2021-02-10 20:56:32 +09:00
|
|
|
aCurrentAny = xInvocation->getValue(xProperty.Name);
|
2021-02-10 16:50:26 +09:00
|
|
|
}
|
|
|
|
}
|
|
|
|
catch (...)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2021-02-10 20:56:32 +09:00
|
|
|
if (aCurrentAny.hasValue())
|
2021-02-10 16:50:26 +09:00
|
|
|
{
|
2021-02-10 20:56:32 +09:00
|
|
|
switch (aCurrentAny.getValueType().getTypeClass())
|
2021-02-10 16:50:26 +09:00
|
|
|
{
|
2021-02-10 20:56:32 +09:00
|
|
|
case uno::TypeClass_INTERFACE:
|
|
|
|
{
|
|
|
|
auto xInterface = uno::Reference<uno::XInterface>(aCurrentAny, uno::UNO_QUERY);
|
|
|
|
if (xInterface.is())
|
|
|
|
{
|
|
|
|
lclAppendNodeToParent(pTree, rParent,
|
|
|
|
new GenericPropertiesNode(xProperty.Name, xInterface,
|
|
|
|
aCurrentAny, mxContext));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case uno::TypeClass_SEQUENCE:
|
|
|
|
{
|
|
|
|
lclAppendNodeToParent(pTree, rParent,
|
|
|
|
new SequenceNode(xProperty.Name, aCurrentAny, mxContext));
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
{
|
|
|
|
lclAppendNodeToParent(pTree, rParent,
|
|
|
|
new ObjectInspectorNamedNode(xProperty.Name, mxObject,
|
|
|
|
aCurrentAny, mxContext));
|
|
|
|
}
|
|
|
|
break;
|
2021-02-10 16:50:26 +09:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-02-10 18:12:38 +09:00
|
|
|
|
2021-02-08 22:41:36 +09:00
|
|
|
} // end anonymous namespace
|
|
|
|
|
2021-02-09 17:43:42 +09:00
|
|
|
ObjectInspectorTreeHandler::ObjectInspectorTreeHandler(
|
|
|
|
std::unique_ptr<weld::TreeView>& pObjectInspectorTree,
|
|
|
|
std::unique_ptr<weld::Label>& pClassNameLabel)
|
|
|
|
: mpObjectInspectorTree(pObjectInspectorTree)
|
|
|
|
, mpClassNameLabel(pClassNameLabel)
|
|
|
|
{
|
|
|
|
mpObjectInspectorTree->connect_expanding(
|
|
|
|
LINK(this, ObjectInspectorTreeHandler, ExpandingHandler));
|
|
|
|
}
|
|
|
|
|
2021-02-08 22:41:36 +09:00
|
|
|
IMPL_LINK(ObjectInspectorTreeHandler, ExpandingHandler, weld::TreeIter const&, rParent, bool)
|
|
|
|
{
|
|
|
|
OUString sID = mpObjectInspectorTree->get_id(rParent);
|
|
|
|
if (sID.isEmpty())
|
|
|
|
return true;
|
|
|
|
|
|
|
|
clearObjectInspectorChildren(rParent);
|
2021-02-10 16:54:59 +09:00
|
|
|
auto* pNode = reinterpret_cast<ObjectInspectorNodeInterface*>(sID.toInt64());
|
2021-02-08 22:41:36 +09:00
|
|
|
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);
|
2021-02-10 16:54:59 +09:00
|
|
|
auto* pEntry = reinterpret_cast<ObjectInspectorNodeInterface*>(sID.toInt64());
|
2021-02-08 22:41:36 +09:00
|
|
|
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();
|
|
|
|
|
2021-02-10 17:33:33 +09:00
|
|
|
lclAppendNode(mpObjectInspectorTree, new ServicesNode(xInterface));
|
|
|
|
lclAppendNode(mpObjectInspectorTree, new InterfacesNode(xInterface));
|
|
|
|
lclAppendNode(mpObjectInspectorTree, new PropertiesNode(xInterface, xContext));
|
|
|
|
lclAppendNode(mpObjectInspectorTree, new MethodsNode(xInterface, xContext));
|
2021-02-08 22:41:36 +09:00
|
|
|
|
|
|
|
mpObjectInspectorTree->thaw();
|
|
|
|
}
|
|
|
|
|
|
|
|
void ObjectInspectorTreeHandler::dispose()
|
|
|
|
{
|
|
|
|
// destroy all ObjectInspectorNodes from the tree
|
|
|
|
mpObjectInspectorTree->all_foreach([this](weld::TreeIter& rEntry) {
|
|
|
|
OUString sID = mpObjectInspectorTree->get_id(rEntry);
|
2021-02-10 16:54:59 +09:00
|
|
|
auto* pEntry = reinterpret_cast<ObjectInspectorNodeInterface*>(sID.toInt64());
|
2021-02-08 22:41:36 +09:00
|
|
|
delete pEntry;
|
|
|
|
return false;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|