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-12 19:00:19 +09:00
|
|
|
#include <com/sun/star/reflection/XEnumTypeDescription.hpp>
|
|
|
|
|
|
|
|
#include <com/sun/star/container/XHierarchicalNameAccess.hpp>
|
2021-02-23 22:04:30 +09:00
|
|
|
#include <com/sun/star/container/XIndexAccess.hpp>
|
|
|
|
#include <com/sun/star/container/XNameAccess.hpp>
|
2021-03-03 21:28:32 +09:00
|
|
|
#include <com/sun/star/container/XEnumerationAccess.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>
|
2021-02-12 19:00:19 +09:00
|
|
|
#include <comphelper/extract.hxx>
|
2021-02-08 22:41:36 +09:00
|
|
|
|
|
|
|
using namespace css;
|
|
|
|
|
|
|
|
namespace
|
|
|
|
{
|
2021-02-12 19:00:19 +09:00
|
|
|
constexpr OUStringLiteral constTypeDescriptionManagerSingletonName
|
|
|
|
= u"/singletons/com.sun.star.reflection.theTypeDescriptionManager";
|
|
|
|
|
|
|
|
OUString AnyToString(const uno::Any& aValue, const uno::Reference<uno::XComponentContext>& xContext)
|
2021-02-08 22:41:36 +09:00
|
|
|
{
|
2021-02-12 19:00:19 +09:00
|
|
|
OUString aRetStr;
|
|
|
|
|
|
|
|
// return early if we don't have any value
|
|
|
|
if (!aValue.hasValue())
|
2021-03-04 22:02:33 +09:00
|
|
|
return "NULL";
|
2021-02-12 19:00:19 +09:00
|
|
|
|
2021-02-08 22:41:36 +09:00
|
|
|
uno::Type aValType = aValue.getValueType();
|
|
|
|
uno::TypeClass eType = aValType.getTypeClass();
|
|
|
|
|
|
|
|
switch (eType)
|
|
|
|
{
|
2021-02-10 17:38:14 +09:00
|
|
|
case uno::TypeClass_INTERFACE:
|
|
|
|
{
|
2021-03-04 22:02:33 +09:00
|
|
|
uno::Reference<uno::XInterface> xInterface(aValue, uno::UNO_QUERY);
|
|
|
|
if (!xInterface.is())
|
|
|
|
aRetStr = "NULL";
|
|
|
|
else
|
|
|
|
aRetStr = "<Object>";
|
2021-02-10 17:38:14 +09:00
|
|
|
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;
|
|
|
|
}
|
2021-02-12 18:53:34 +09:00
|
|
|
case uno::TypeClass_UNSIGNED_SHORT:
|
|
|
|
{
|
|
|
|
auto aNumber = aValue.get<sal_uInt16>();
|
|
|
|
aRetStr = OUString::number(aNumber);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case uno::TypeClass_UNSIGNED_LONG:
|
|
|
|
{
|
|
|
|
auto aNumber = aValue.get<sal_uInt32>();
|
|
|
|
aRetStr = OUString::number(aNumber);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case uno::TypeClass_UNSIGNED_HYPER:
|
|
|
|
{
|
|
|
|
auto aNumber = aValue.get<sal_uInt64>();
|
|
|
|
aRetStr = OUString::number(aNumber);
|
|
|
|
break;
|
|
|
|
}
|
2021-02-24 15:56:54 +09:00
|
|
|
case uno::TypeClass_TYPE:
|
|
|
|
{
|
|
|
|
auto aType = aValue.get<uno::Type>();
|
|
|
|
aRetStr = aType.getTypeName();
|
|
|
|
break;
|
|
|
|
}
|
2021-02-12 19:00:19 +09:00
|
|
|
case uno::TypeClass_ENUM:
|
|
|
|
{
|
|
|
|
sal_Int32 nIntValue = 0;
|
|
|
|
if (cppu::enum2int(nIntValue, aValue))
|
|
|
|
{
|
|
|
|
uno::Reference<container::XHierarchicalNameAccess> xManager;
|
|
|
|
xManager.set(xContext->getValueByName(constTypeDescriptionManagerSingletonName),
|
|
|
|
uno::UNO_QUERY);
|
|
|
|
|
|
|
|
uno::Reference<reflection::XEnumTypeDescription> xTypeDescription;
|
|
|
|
xTypeDescription.set(xManager->getByHierarchicalName(aValType.getTypeName()),
|
|
|
|
uno::UNO_QUERY);
|
|
|
|
|
|
|
|
uno::Sequence<sal_Int32> aValues = xTypeDescription->getEnumValues();
|
|
|
|
sal_Int32 nValuesIndex
|
|
|
|
= std::find(aValues.begin(), aValues.end(), nIntValue) - aValues.begin();
|
|
|
|
uno::Sequence<OUString> aNames = xTypeDescription->getEnumNames();
|
|
|
|
aRetStr = aNames[nValuesIndex];
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2021-02-08 22:41:36 +09:00
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return aRetStr;
|
|
|
|
}
|
|
|
|
|
2021-03-04 22:19:11 +09:00
|
|
|
OUString getAnyType(const uno::Any& aValue)
|
|
|
|
{
|
|
|
|
OUString aTypeName = aValue.getValueType().getTypeName();
|
|
|
|
return aTypeName.replaceAll("com.sun.star", "css");
|
|
|
|
}
|
2021-02-09 19:29:50 +09:00
|
|
|
|
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-17 11:49:56 +09:00
|
|
|
virtual void fillChildren(std::unique_ptr<weld::TreeView>& rTree, const weld::TreeIter* pParent)
|
2021-02-10 16:54:59 +09:00
|
|
|
= 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
|
|
|
};
|
|
|
|
|
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-17 11:49:56 +09:00
|
|
|
const weld::TreeIter* pParent, 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-17 11:49:56 +09:00
|
|
|
pTree->insert(pParent, -1, &sName, &sId, nullptr, nullptr, pEntry->shouldShowExpander(),
|
2021-02-10 17:33:33 +09:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2021-02-10 21:58:22 +09:00
|
|
|
class SimpleStringNode : public ObjectInspectorNodeInterface
|
2021-02-08 22:41:36 +09:00
|
|
|
{
|
2021-02-10 17:33:33 +09:00
|
|
|
protected:
|
2021-02-08 22:41:36 +09:00
|
|
|
OUString msName;
|
2021-02-10 21:58:22 +09:00
|
|
|
|
|
|
|
public:
|
|
|
|
SimpleStringNode(OUString const& rName)
|
|
|
|
: msName(rName)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void fillChildren(std::unique_ptr<weld::TreeView>& /*rTree*/,
|
2021-02-17 11:49:56 +09:00
|
|
|
const weld::TreeIter* /*pParent*/) override
|
2021-02-10 21:58:22 +09:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
OUString getObjectName() override { return msName; }
|
|
|
|
};
|
|
|
|
|
2021-02-18 12:02:06 +09:00
|
|
|
class MethodNode : public ObjectInspectorNodeInterface
|
|
|
|
{
|
|
|
|
private:
|
|
|
|
uno::Reference<reflection::XIdlMethod> mxMethod;
|
|
|
|
|
|
|
|
public:
|
|
|
|
MethodNode(uno::Reference<reflection::XIdlMethod> const& xMethod)
|
|
|
|
: mxMethod(xMethod)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
OUString getObjectName() override { return mxMethod->getName(); }
|
|
|
|
|
|
|
|
static OUString simpleTypeName(uno::Reference<reflection::XIdlClass> const& xClass)
|
|
|
|
{
|
|
|
|
switch (xClass->getTypeClass())
|
|
|
|
{
|
|
|
|
case uno::TypeClass_INTERFACE:
|
|
|
|
return "object";
|
|
|
|
case uno::TypeClass_STRUCT:
|
|
|
|
return "struct";
|
|
|
|
case uno::TypeClass_ENUM:
|
|
|
|
return "enum";
|
|
|
|
case uno::TypeClass_SEQUENCE:
|
|
|
|
return "sequence";
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return xClass->getName();
|
|
|
|
}
|
|
|
|
|
|
|
|
std::vector<std::pair<sal_Int32, OUString>> getColumnValues() override
|
|
|
|
{
|
|
|
|
OUString aOutString;
|
|
|
|
auto xClass = mxMethod->getReturnType();
|
|
|
|
aOutString = simpleTypeName(xClass);
|
|
|
|
|
2021-02-22 09:15:39 +09:00
|
|
|
OUString aInString;
|
2021-02-18 12:02:06 +09:00
|
|
|
const auto aParameters = mxMethod->getParameterInfos();
|
|
|
|
bool bFirst = true;
|
|
|
|
for (auto const& rParameterInfo : aParameters)
|
|
|
|
{
|
|
|
|
if (!bFirst)
|
|
|
|
aInString += ", ";
|
|
|
|
else
|
|
|
|
bFirst = false;
|
|
|
|
|
|
|
|
switch (rParameterInfo.aMode)
|
|
|
|
{
|
|
|
|
case reflection::ParamMode_IN:
|
|
|
|
aInString += "[in] ";
|
|
|
|
break;
|
|
|
|
case reflection::ParamMode_OUT:
|
|
|
|
aInString += "[out] ";
|
|
|
|
break;
|
|
|
|
case reflection::ParamMode_INOUT:
|
|
|
|
aInString += "[in&out] ";
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
aInString += rParameterInfo.aName + " : " + simpleTypeName(rParameterInfo.aType);
|
|
|
|
}
|
|
|
|
|
2021-02-22 09:15:39 +09:00
|
|
|
OUString aImplementationClass = mxMethod->getDeclaringClass()->getName();
|
|
|
|
|
2021-02-18 12:02:06 +09:00
|
|
|
return {
|
|
|
|
{ 1, aOutString },
|
|
|
|
{ 2, aInString },
|
2021-02-22 09:15:39 +09:00
|
|
|
{ 3, aImplementationClass },
|
2021-02-18 12:02:06 +09:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
void fillChildren(std::unique_ptr<weld::TreeView>& /*rTree*/,
|
|
|
|
const weld::TreeIter* /*pParent*/) override
|
|
|
|
{
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2021-02-10 21:58:22 +09:00
|
|
|
class BasicValueNode : public SimpleStringNode
|
|
|
|
{
|
|
|
|
protected:
|
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-11 21:14:36 +09:00
|
|
|
ObjectInspectorNodeInterface* createNodeObjectForAny(OUString const& rName, uno::Any& rAny);
|
|
|
|
|
2021-02-10 17:33:33 +09:00
|
|
|
public:
|
2021-02-10 21:58:22 +09:00
|
|
|
BasicValueNode(OUString const& rName, uno::Any const& rAny,
|
|
|
|
uno::Reference<uno::XComponentContext> const& xContext)
|
|
|
|
: SimpleStringNode(rName)
|
|
|
|
, maAny(rAny)
|
2021-02-10 17:33:33 +09:00
|
|
|
, mxContext(xContext)
|
2021-02-08 22:41:36 +09:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2021-02-23 22:54:06 +09:00
|
|
|
uno::Any getAny() { return maAny; }
|
|
|
|
|
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:
|
2021-03-04 22:11:56 +09:00
|
|
|
{
|
|
|
|
uno::Reference<uno::XInterface> xInterface(maAny, uno::UNO_QUERY);
|
|
|
|
return xInterface.is();
|
|
|
|
}
|
2021-02-10 20:56:32 +09:00
|
|
|
case uno::TypeClass_SEQUENCE:
|
|
|
|
return true;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2021-02-10 18:12:38 +09:00
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2021-02-10 17:33:33 +09:00
|
|
|
std::vector<std::pair<sal_Int32, OUString>> getColumnValues() override
|
|
|
|
{
|
2021-03-04 22:02:33 +09:00
|
|
|
OUString aValue = AnyToString(maAny, mxContext);
|
2021-03-04 22:08:32 +09:00
|
|
|
OUString aType = getAnyType(maAny);
|
2021-02-10 17:33:33 +09:00
|
|
|
|
2021-03-04 22:02:33 +09:00
|
|
|
return {
|
|
|
|
{ 1, aValue },
|
|
|
|
{ 2, aType },
|
|
|
|
};
|
2021-02-10 17:33:33 +09:00
|
|
|
}
|
2021-02-08 22:41:36 +09:00
|
|
|
};
|
|
|
|
|
2021-02-10 21:58:22 +09:00
|
|
|
class GenericPropertiesNode : public BasicValueNode
|
2021-02-08 22:41:36 +09:00
|
|
|
{
|
|
|
|
public:
|
2021-02-10 21:58:22 +09:00
|
|
|
GenericPropertiesNode(OUString const& rName, uno::Any const& rAny,
|
|
|
|
uno::Reference<uno::XComponentContext> const& xContext)
|
|
|
|
: BasicValueNode(rName, rAny, xContext)
|
2021-02-08 22:41:36 +09:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void fillChildren(std::unique_ptr<weld::TreeView>& pTree,
|
2021-02-17 11:49:56 +09:00
|
|
|
const weld::TreeIter* pParent) override;
|
2021-02-08 22:41:36 +09:00
|
|
|
};
|
|
|
|
|
2021-02-11 16:50:19 +09:00
|
|
|
class StructNode : public BasicValueNode
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
StructNode(OUString const& rName, uno::Any const& rAny,
|
|
|
|
uno::Reference<uno::XComponentContext> const& xContext)
|
|
|
|
: BasicValueNode(rName, rAny, xContext)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
bool shouldShowExpander() override { return true; }
|
|
|
|
|
|
|
|
void fillChildren(std::unique_ptr<weld::TreeView>& pTree,
|
2021-02-17 11:49:56 +09:00
|
|
|
const weld::TreeIter* pParent) override;
|
2021-02-11 16:50:19 +09:00
|
|
|
};
|
|
|
|
|
2021-02-10 21:58:22 +09:00
|
|
|
class SequenceNode : public BasicValueNode
|
2021-02-10 18:12:38 +09:00
|
|
|
{
|
2021-03-04 22:36:55 +09:00
|
|
|
uno::Reference<reflection::XIdlArray> mxIdlArray;
|
|
|
|
|
2021-02-10 18:12:38 +09:00
|
|
|
public:
|
2021-02-10 21:58:22 +09:00
|
|
|
SequenceNode(OUString const& rName, uno::Any const& rAny,
|
2021-02-10 18:12:38 +09:00
|
|
|
uno::Reference<uno::XComponentContext> const& xContext)
|
2021-02-10 21:58:22 +09:00
|
|
|
: BasicValueNode(rName, rAny, xContext)
|
2021-02-10 18:12:38 +09:00
|
|
|
{
|
2021-03-04 22:36:55 +09:00
|
|
|
auto xReflection = reflection::theCoreReflection::get(mxContext);
|
|
|
|
OUString aTypeName = maAny.getValueType().getTypeName();
|
|
|
|
auto xClass = xReflection->forName(aTypeName);
|
|
|
|
mxIdlArray = xClass->getArray();
|
2021-02-10 18:12:38 +09:00
|
|
|
}
|
|
|
|
|
2021-03-04 22:36:55 +09:00
|
|
|
bool shouldShowExpander() override
|
|
|
|
{
|
|
|
|
// Show expnder only if the sequence has elements
|
|
|
|
int nLength = mxIdlArray->getLen(maAny);
|
|
|
|
return nLength > 0;
|
|
|
|
}
|
2021-02-10 18:12:38 +09:00
|
|
|
|
|
|
|
void fillChildren(std::unique_ptr<weld::TreeView>& pTree,
|
2021-02-17 11:49:56 +09:00
|
|
|
const weld::TreeIter* pParent) override
|
2021-02-10 18:12:38 +09:00
|
|
|
{
|
2021-03-04 22:36:55 +09:00
|
|
|
int nLength = mxIdlArray->getLen(maAny);
|
2021-02-10 18:12:38 +09:00
|
|
|
|
|
|
|
for (int i = 0; i < nLength; i++)
|
|
|
|
{
|
2021-03-04 22:36:55 +09:00
|
|
|
uno::Any aArrayValue = mxIdlArray->get(maAny, i);
|
2021-02-10 18:12:38 +09:00
|
|
|
uno::Reference<uno::XInterface> xCurrent;
|
2021-02-11 16:50:19 +09:00
|
|
|
|
2021-02-11 21:14:36 +09:00
|
|
|
auto* pObjectInspectorNode = createNodeObjectForAny(OUString::number(i), aArrayValue);
|
|
|
|
if (pObjectInspectorNode)
|
2021-02-17 11:49:56 +09:00
|
|
|
lclAppendNodeToParent(pTree, pParent, pObjectInspectorNode);
|
2021-02-10 18:12:38 +09:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
std::vector<std::pair<sal_Int32, OUString>> getColumnValues() override
|
|
|
|
{
|
2021-03-04 22:36:55 +09:00
|
|
|
int nLength = mxIdlArray->getLen(maAny);
|
2021-02-10 18:12:38 +09:00
|
|
|
|
2021-03-04 22:19:11 +09:00
|
|
|
OUString aValue = "<Sequence>";
|
|
|
|
OUString aType = getAnyType(maAny).replaceAll(u"[]", u"");
|
|
|
|
aType += u"[" + OUString::number(nLength) + u"]";
|
2021-02-10 18:12:38 +09:00
|
|
|
|
|
|
|
return {
|
|
|
|
{ 1, aValue },
|
|
|
|
{ 2, aType },
|
|
|
|
};
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2021-02-10 16:50:26 +09:00
|
|
|
void GenericPropertiesNode::fillChildren(std::unique_ptr<weld::TreeView>& pTree,
|
2021-02-17 11:49:56 +09:00
|
|
|
const weld::TreeIter* pParent)
|
2021-02-10 16:50:26 +09:00
|
|
|
{
|
2021-02-10 20:56:32 +09:00
|
|
|
if (!maAny.hasValue())
|
2021-02-10 21:58:22 +09:00
|
|
|
return;
|
2021-02-10 18:12:38 +09:00
|
|
|
|
2021-02-23 22:04:30 +09:00
|
|
|
const auto xNameAccess = uno::Reference<container::XNameAccess>(maAny, uno::UNO_QUERY);
|
|
|
|
if (xNameAccess.is())
|
|
|
|
{
|
|
|
|
const uno::Sequence<OUString> aNames = xNameAccess->getElementNames();
|
|
|
|
for (OUString const& rName : aNames)
|
|
|
|
{
|
|
|
|
uno::Any aAny = xNameAccess->getByName(rName);
|
|
|
|
auto* pObjectInspectorNode = createNodeObjectForAny("@" + rName, aAny);
|
|
|
|
lclAppendNodeToParent(pTree, pParent, pObjectInspectorNode);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const auto xIndexAccess = uno::Reference<container::XIndexAccess>(maAny, uno::UNO_QUERY);
|
|
|
|
if (xIndexAccess.is())
|
|
|
|
{
|
|
|
|
for (sal_Int32 nIndex = 0; nIndex < xIndexAccess->getCount(); ++nIndex)
|
|
|
|
{
|
|
|
|
uno::Any aAny = xIndexAccess->getByIndex(nIndex);
|
|
|
|
auto* pObjectInspectorNode
|
|
|
|
= createNodeObjectForAny("@" + OUString::number(nIndex), aAny);
|
|
|
|
lclAppendNodeToParent(pTree, pParent, pObjectInspectorNode);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-03 21:28:32 +09:00
|
|
|
const auto xEnumAccess = uno::Reference<container::XEnumerationAccess>(maAny, uno::UNO_QUERY);
|
|
|
|
if (xEnumAccess.is())
|
|
|
|
{
|
|
|
|
uno::Reference<container::XEnumeration> xEnumeration = xEnumAccess->createEnumeration();
|
|
|
|
if (xEnumeration.is())
|
|
|
|
{
|
|
|
|
for (sal_Int32 nIndex = 0; xEnumeration->hasMoreElements(); nIndex++)
|
|
|
|
{
|
|
|
|
uno::Any aAny = xEnumeration->nextElement();
|
|
|
|
auto* pObjectInspectorNode
|
|
|
|
= createNodeObjectForAny("@{" + OUString::number(nIndex) + "}", aAny);
|
|
|
|
lclAppendNodeToParent(pTree, pParent, pObjectInspectorNode);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-02-10 16:50:26 +09:00
|
|
|
uno::Reference<beans::XIntrospection> xIntrospection = beans::theIntrospection::get(mxContext);
|
2021-03-04 21:57:49 +09:00
|
|
|
if (!xIntrospection.is())
|
|
|
|
return;
|
|
|
|
|
2021-02-10 21:58:22 +09:00
|
|
|
auto xIntrospectionAccess = xIntrospection->inspect(maAny);
|
2021-03-04 21:57:49 +09:00
|
|
|
if (!xIntrospectionAccess.is())
|
|
|
|
return;
|
|
|
|
|
2021-02-10 16:50:26 +09:00
|
|
|
auto xInvocationFactory = css::script::Invocation::create(mxContext);
|
2021-02-10 21:58:22 +09:00
|
|
|
uno::Sequence<uno::Any> aParameters = { maAny };
|
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-11 21:14:36 +09:00
|
|
|
auto* pObjectInspectorNode = createNodeObjectForAny(xProperty.Name, aCurrentAny);
|
|
|
|
if (pObjectInspectorNode)
|
2021-02-17 11:49:56 +09:00
|
|
|
lclAppendNodeToParent(pTree, pParent, pObjectInspectorNode);
|
2021-02-11 16:50:19 +09:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-02-17 11:49:56 +09:00
|
|
|
void StructNode::fillChildren(std::unique_ptr<weld::TreeView>& pTree, const weld::TreeIter* pParent)
|
2021-02-11 16:50:19 +09:00
|
|
|
{
|
|
|
|
auto xReflection = reflection::theCoreReflection::get(mxContext);
|
|
|
|
uno::Reference<reflection::XIdlClass> xClass
|
|
|
|
= xReflection->forName(maAny.getValueType().getTypeName());
|
|
|
|
|
|
|
|
const auto xFields = xClass->getFields();
|
|
|
|
|
|
|
|
for (auto const& xField : xFields)
|
|
|
|
{
|
|
|
|
OUString aFieldName = xField->getName();
|
|
|
|
uno::Any aFieldValue = xField->get(maAny);
|
|
|
|
|
2021-02-11 21:14:36 +09:00
|
|
|
auto* pObjectInspectorNode = createNodeObjectForAny(aFieldName, aFieldValue);
|
|
|
|
if (pObjectInspectorNode)
|
2021-02-17 11:49:56 +09:00
|
|
|
{
|
|
|
|
lclAppendNodeToParent(pTree, pParent, pObjectInspectorNode);
|
|
|
|
}
|
2021-02-11 21:14:36 +09:00
|
|
|
}
|
|
|
|
}
|
2021-02-11 16:50:19 +09:00
|
|
|
|
2021-02-11 21:14:36 +09:00
|
|
|
ObjectInspectorNodeInterface* BasicValueNode::createNodeObjectForAny(OUString const& rName,
|
|
|
|
uno::Any& rAny)
|
|
|
|
{
|
|
|
|
switch (rAny.getValueType().getTypeClass())
|
|
|
|
{
|
|
|
|
case uno::TypeClass_INTERFACE:
|
|
|
|
return new GenericPropertiesNode(rName, rAny, mxContext);
|
2021-02-11 16:50:19 +09:00
|
|
|
|
2021-02-11 21:14:36 +09:00
|
|
|
case uno::TypeClass_SEQUENCE:
|
|
|
|
return new SequenceNode(rName, rAny, mxContext);
|
|
|
|
|
|
|
|
case uno::TypeClass_STRUCT:
|
|
|
|
return new StructNode(rName, rAny, mxContext);
|
|
|
|
|
|
|
|
default:
|
2021-02-10 21:58:22 +09:00
|
|
|
break;
|
2021-02-10 16:50:26 +09:00
|
|
|
}
|
2021-02-11 21:14:36 +09:00
|
|
|
|
|
|
|
return new BasicValueNode(rName, rAny, mxContext);
|
2021-02-10 16:50:26 +09:00
|
|
|
}
|
2021-02-10 18:12:38 +09:00
|
|
|
|
2021-03-04 21:57:49 +09:00
|
|
|
// helper functions
|
|
|
|
|
2021-02-25 20:58:42 +09:00
|
|
|
ObjectInspectorNodeInterface* getSelectedNode(weld::TreeView const& rTreeView)
|
|
|
|
{
|
|
|
|
OUString sID = rTreeView.get_selected_id();
|
|
|
|
if (sID.isEmpty())
|
|
|
|
return nullptr;
|
|
|
|
|
|
|
|
if (auto* pNode = reinterpret_cast<ObjectInspectorNodeInterface*>(sID.toInt64()))
|
|
|
|
return pNode;
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
uno::Reference<uno::XInterface> getSelectedXInterface(weld::TreeView const& rTreeView)
|
|
|
|
{
|
|
|
|
uno::Reference<uno::XInterface> xInterface;
|
|
|
|
|
|
|
|
if (auto* pNode = getSelectedNode(rTreeView))
|
|
|
|
{
|
|
|
|
if (auto* pBasicValueNode = dynamic_cast<BasicValueNode*>(pNode))
|
|
|
|
{
|
|
|
|
uno::Any aAny = pBasicValueNode->getAny();
|
|
|
|
xInterface.set(aAny, uno::UNO_QUERY);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return xInterface;
|
|
|
|
}
|
|
|
|
|
2021-02-08 22:41:36 +09:00
|
|
|
} // end anonymous namespace
|
|
|
|
|
2021-02-09 17:43:42 +09:00
|
|
|
ObjectInspectorTreeHandler::ObjectInspectorTreeHandler(
|
2021-02-17 11:49:56 +09:00
|
|
|
std::unique_ptr<weld::TreeView>& pInterfacesTreeView,
|
|
|
|
std::unique_ptr<weld::TreeView>& pServicesTreeView,
|
|
|
|
std::unique_ptr<weld::TreeView>& pPropertiesTreeView,
|
|
|
|
std::unique_ptr<weld::TreeView>& pMethodsTreeView,
|
2021-02-25 20:58:42 +09:00
|
|
|
std::unique_ptr<weld::Label>& pClassNameLabel,
|
2021-02-25 21:11:39 +09:00
|
|
|
std::unique_ptr<weld::Toolbar>& pObjectInspectorToolbar,
|
|
|
|
std::unique_ptr<weld::Notebook>& pObjectInspectorNotebook)
|
2021-02-17 11:49:56 +09:00
|
|
|
: mpInterfacesTreeView(pInterfacesTreeView)
|
|
|
|
, mpServicesTreeView(pServicesTreeView)
|
|
|
|
, mpPropertiesTreeView(pPropertiesTreeView)
|
|
|
|
, mpMethodsTreeView(pMethodsTreeView)
|
2021-02-09 17:43:42 +09:00
|
|
|
, mpClassNameLabel(pClassNameLabel)
|
2021-02-25 20:58:42 +09:00
|
|
|
, mpObjectInspectorToolbar(pObjectInspectorToolbar)
|
2021-02-25 21:11:39 +09:00
|
|
|
, mpObjectInspectorNotebook(pObjectInspectorNotebook)
|
2021-02-09 17:43:42 +09:00
|
|
|
{
|
2021-02-17 11:49:56 +09:00
|
|
|
mpInterfacesTreeView->connect_expanding(
|
|
|
|
LINK(this, ObjectInspectorTreeHandler, ExpandingHandlerInterfaces));
|
|
|
|
mpServicesTreeView->connect_expanding(
|
|
|
|
LINK(this, ObjectInspectorTreeHandler, ExpandingHandlerServices));
|
|
|
|
mpPropertiesTreeView->connect_expanding(
|
|
|
|
LINK(this, ObjectInspectorTreeHandler, ExpandingHandlerProperties));
|
|
|
|
mpMethodsTreeView->connect_expanding(
|
|
|
|
LINK(this, ObjectInspectorTreeHandler, ExpandingHandlerMethods));
|
2021-02-23 22:54:06 +09:00
|
|
|
|
|
|
|
mpPropertiesTreeView->connect_popup_menu(
|
|
|
|
LINK(this, ObjectInspectorTreeHandler, PopupMenuHandler));
|
2021-02-25 20:58:42 +09:00
|
|
|
|
|
|
|
mpInterfacesTreeView->connect_changed(LINK(this, ObjectInspectorTreeHandler, SelectionChanged));
|
|
|
|
mpServicesTreeView->connect_changed(LINK(this, ObjectInspectorTreeHandler, SelectionChanged));
|
|
|
|
mpPropertiesTreeView->connect_changed(LINK(this, ObjectInspectorTreeHandler, SelectionChanged));
|
|
|
|
mpMethodsTreeView->connect_changed(LINK(this, ObjectInspectorTreeHandler, SelectionChanged));
|
|
|
|
|
|
|
|
mpObjectInspectorToolbar->connect_clicked(
|
|
|
|
LINK(this, ObjectInspectorTreeHandler, ToolbarButtonClicked));
|
|
|
|
mpObjectInspectorToolbar->set_item_sensitive("inspect", false);
|
|
|
|
mpObjectInspectorToolbar->set_item_sensitive("back", false);
|
2021-02-25 21:11:39 +09:00
|
|
|
|
|
|
|
mpObjectInspectorNotebook->connect_leave_page(
|
|
|
|
LINK(this, ObjectInspectorTreeHandler, NotebookLeavePage));
|
|
|
|
mpObjectInspectorNotebook->connect_enter_page(
|
|
|
|
LINK(this, ObjectInspectorTreeHandler, NotebookEnterPage));
|
2021-02-09 17:43:42 +09:00
|
|
|
}
|
|
|
|
|
2021-02-17 11:49:56 +09:00
|
|
|
void ObjectInspectorTreeHandler::handleExpanding(std::unique_ptr<weld::TreeView>& pTreeView,
|
|
|
|
weld::TreeIter const& rParent)
|
2021-02-08 22:41:36 +09:00
|
|
|
{
|
2021-02-17 11:49:56 +09:00
|
|
|
OUString sID = pTreeView->get_id(rParent);
|
2021-02-08 22:41:36 +09:00
|
|
|
if (sID.isEmpty())
|
2021-02-17 11:49:56 +09:00
|
|
|
return;
|
2021-02-08 22:41:36 +09:00
|
|
|
|
2021-02-17 11:49:56 +09:00
|
|
|
clearObjectInspectorChildren(pTreeView, rParent);
|
2021-02-10 16:54:59 +09:00
|
|
|
auto* pNode = reinterpret_cast<ObjectInspectorNodeInterface*>(sID.toInt64());
|
2021-02-17 11:49:56 +09:00
|
|
|
pNode->fillChildren(pTreeView, &rParent);
|
|
|
|
}
|
2021-02-08 22:41:36 +09:00
|
|
|
|
2021-02-17 11:49:56 +09:00
|
|
|
IMPL_LINK(ObjectInspectorTreeHandler, ExpandingHandlerInterfaces, weld::TreeIter const&, rParent,
|
|
|
|
bool)
|
|
|
|
{
|
|
|
|
handleExpanding(mpInterfacesTreeView, rParent);
|
2021-02-08 22:41:36 +09:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2021-02-17 11:49:56 +09:00
|
|
|
IMPL_LINK(ObjectInspectorTreeHandler, ExpandingHandlerServices, weld::TreeIter const&, rParent,
|
|
|
|
bool)
|
|
|
|
{
|
|
|
|
handleExpanding(mpServicesTreeView, rParent);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
IMPL_LINK(ObjectInspectorTreeHandler, ExpandingHandlerProperties, weld::TreeIter const&, rParent,
|
|
|
|
bool)
|
|
|
|
{
|
|
|
|
handleExpanding(mpPropertiesTreeView, rParent);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
IMPL_LINK(ObjectInspectorTreeHandler, ExpandingHandlerMethods, weld::TreeIter const&, rParent, bool)
|
|
|
|
{
|
|
|
|
handleExpanding(mpMethodsTreeView, rParent);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2021-02-25 20:58:42 +09:00
|
|
|
IMPL_LINK(ObjectInspectorTreeHandler, SelectionChanged, weld::TreeView&, rTreeView, void)
|
|
|
|
{
|
|
|
|
bool bHaveNodeWithObject = false;
|
|
|
|
|
|
|
|
if (mpPropertiesTreeView.get() == &rTreeView)
|
|
|
|
{
|
|
|
|
auto* pNode = getSelectedNode(rTreeView);
|
|
|
|
if (auto* pBasicValueNode = dynamic_cast<BasicValueNode*>(pNode))
|
|
|
|
{
|
|
|
|
uno::Any aAny = pBasicValueNode->getAny();
|
|
|
|
uno::Reference<uno::XInterface> xInterface(aAny, uno::UNO_QUERY);
|
|
|
|
bHaveNodeWithObject = xInterface.is();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
mpObjectInspectorToolbar->set_item_sensitive("inspect", bHaveNodeWithObject);
|
|
|
|
}
|
|
|
|
|
2021-02-23 22:54:06 +09:00
|
|
|
IMPL_LINK(ObjectInspectorTreeHandler, PopupMenuHandler, const CommandEvent&, rCommandEvent, bool)
|
|
|
|
{
|
|
|
|
if (rCommandEvent.GetCommand() != CommandEventId::ContextMenu)
|
|
|
|
return false;
|
|
|
|
|
2021-02-25 20:58:42 +09:00
|
|
|
auto xInterface = getSelectedXInterface(*mpPropertiesTreeView);
|
|
|
|
if (xInterface.is())
|
|
|
|
{
|
|
|
|
std::unique_ptr<weld::Builder> xBuilder(
|
|
|
|
Application::CreateBuilder(mpPropertiesTreeView.get(), "sfx/ui/devtoolsmenu.ui"));
|
|
|
|
std::unique_ptr<weld::Menu> xMenu(xBuilder->weld_menu("inspect_menu"));
|
2021-02-23 22:54:06 +09:00
|
|
|
|
2021-02-25 20:58:42 +09:00
|
|
|
OString sCommand(
|
|
|
|
xMenu->popup_at_rect(mpPropertiesTreeView.get(),
|
|
|
|
tools::Rectangle(rCommandEvent.GetMousePosPixel(), Size(1, 1))));
|
|
|
|
|
|
|
|
if (sCommand == "inspect")
|
|
|
|
{
|
|
|
|
addToStack(uno::Any(xInterface));
|
|
|
|
inspectObject(xInterface);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
IMPL_LINK(ObjectInspectorTreeHandler, ToolbarButtonClicked, const OString&, rSelectionId, void)
|
|
|
|
{
|
|
|
|
if (rSelectionId == "inspect")
|
2021-02-23 22:54:06 +09:00
|
|
|
{
|
2021-02-25 20:58:42 +09:00
|
|
|
auto xInterface = getSelectedXInterface(*mpPropertiesTreeView);
|
|
|
|
if (xInterface.is())
|
|
|
|
{
|
|
|
|
addToStack(uno::Any(xInterface));
|
|
|
|
inspectObject(xInterface);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (rSelectionId == "back")
|
|
|
|
{
|
|
|
|
uno::Any aAny = popFromStack();
|
|
|
|
if (aAny.hasValue())
|
2021-02-23 22:54:06 +09:00
|
|
|
{
|
|
|
|
uno::Reference<uno::XInterface> xInterface(aAny, uno::UNO_QUERY);
|
2021-02-25 20:58:42 +09:00
|
|
|
inspectObject(xInterface);
|
2021-02-23 22:54:06 +09:00
|
|
|
}
|
|
|
|
}
|
2021-03-04 15:30:19 +09:00
|
|
|
else if (rSelectionId == "refresh")
|
|
|
|
{
|
|
|
|
auto rPageId = mpObjectInspectorNotebook->get_current_page_ident();
|
|
|
|
NotebookEnterPage(rPageId);
|
|
|
|
}
|
2021-02-23 22:54:06 +09:00
|
|
|
}
|
|
|
|
|
2021-02-25 21:11:39 +09:00
|
|
|
IMPL_LINK(ObjectInspectorTreeHandler, NotebookEnterPage, const OString&, rPageId, void)
|
|
|
|
{
|
|
|
|
uno::Any aAny = maInspectionStack.back();
|
|
|
|
if (aAny.hasValue())
|
|
|
|
{
|
|
|
|
uno::Reference<uno::XInterface> xInterface(aAny, uno::UNO_QUERY);
|
|
|
|
if (rPageId == "object_inspector_interfaces_tab")
|
|
|
|
{
|
|
|
|
mpInterfacesTreeView->freeze();
|
|
|
|
clearAll(mpInterfacesTreeView);
|
|
|
|
appendInterfaces(xInterface);
|
|
|
|
mpInterfacesTreeView->thaw();
|
|
|
|
}
|
|
|
|
else if (rPageId == "object_inspector_services_tab")
|
|
|
|
{
|
|
|
|
mpServicesTreeView->freeze();
|
|
|
|
clearAll(mpServicesTreeView);
|
|
|
|
appendServices(xInterface);
|
|
|
|
mpServicesTreeView->thaw();
|
|
|
|
}
|
|
|
|
else if (rPageId == "object_inspector_properties_tab")
|
|
|
|
{
|
|
|
|
mpPropertiesTreeView->freeze();
|
|
|
|
clearAll(mpPropertiesTreeView);
|
|
|
|
appendProperties(xInterface);
|
|
|
|
mpPropertiesTreeView->thaw();
|
|
|
|
}
|
|
|
|
else if (rPageId == "object_inspector_methods_tab")
|
|
|
|
{
|
|
|
|
mpMethodsTreeView->freeze();
|
|
|
|
clearAll(mpMethodsTreeView);
|
|
|
|
appendMethods(xInterface);
|
|
|
|
mpMethodsTreeView->thaw();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
IMPL_LINK(ObjectInspectorTreeHandler, NotebookLeavePage, const OString&, rPageId, bool)
|
|
|
|
{
|
|
|
|
if (rPageId == "object_inspector_interfaces_tab")
|
|
|
|
{
|
|
|
|
mpInterfacesTreeView->freeze();
|
|
|
|
clearAll(mpInterfacesTreeView);
|
|
|
|
mpInterfacesTreeView->thaw();
|
|
|
|
}
|
|
|
|
else if (rPageId == "object_inspector_services_tab")
|
|
|
|
{
|
|
|
|
mpServicesTreeView->freeze();
|
|
|
|
clearAll(mpServicesTreeView);
|
|
|
|
mpServicesTreeView->thaw();
|
|
|
|
}
|
|
|
|
else if (rPageId == "object_inspector_properties_tab")
|
|
|
|
{
|
|
|
|
mpPropertiesTreeView->freeze();
|
|
|
|
clearAll(mpPropertiesTreeView);
|
|
|
|
mpPropertiesTreeView->thaw();
|
|
|
|
}
|
|
|
|
else if (rPageId == "object_inspector_methods_tab")
|
|
|
|
{
|
|
|
|
mpMethodsTreeView->freeze();
|
|
|
|
clearAll(mpMethodsTreeView);
|
|
|
|
mpMethodsTreeView->thaw();
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2021-02-17 11:49:56 +09:00
|
|
|
void ObjectInspectorTreeHandler::clearObjectInspectorChildren(
|
|
|
|
std::unique_ptr<weld::TreeView>& pTreeView, weld::TreeIter const& rParent)
|
2021-02-08 22:41:36 +09:00
|
|
|
{
|
|
|
|
bool bChild = false;
|
|
|
|
do
|
|
|
|
{
|
2021-02-17 11:49:56 +09:00
|
|
|
bChild = pTreeView->iter_has_child(rParent);
|
2021-02-08 22:41:36 +09:00
|
|
|
if (bChild)
|
|
|
|
{
|
2021-02-17 11:49:56 +09:00
|
|
|
std::unique_ptr<weld::TreeIter> pChild = pTreeView->make_iterator(&rParent);
|
|
|
|
bChild = pTreeView->iter_children(*pChild);
|
2021-02-08 22:41:36 +09:00
|
|
|
if (bChild)
|
|
|
|
{
|
2021-02-17 11:49:56 +09:00
|
|
|
clearObjectInspectorChildren(pTreeView, *pChild);
|
|
|
|
OUString sID = pTreeView->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;
|
2021-02-17 11:49:56 +09:00
|
|
|
pTreeView->remove(*pChild);
|
2021-02-08 22:41:36 +09:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} while (bChild);
|
|
|
|
}
|
|
|
|
|
2021-02-17 11:49:56 +09:00
|
|
|
void ObjectInspectorTreeHandler::clearAll(std::unique_ptr<weld::TreeView>& pTreeView)
|
|
|
|
{
|
|
|
|
// destroy all ObjectInspectorNodes from the tree
|
|
|
|
pTreeView->all_foreach([&pTreeView](weld::TreeIter& rEntry) {
|
|
|
|
OUString sID = pTreeView->get_id(rEntry);
|
|
|
|
auto* pEntry = reinterpret_cast<ObjectInspectorNodeInterface*>(sID.toInt64());
|
|
|
|
delete pEntry;
|
|
|
|
return false;
|
|
|
|
});
|
|
|
|
pTreeView->clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
void ObjectInspectorTreeHandler::appendInterfaces(uno::Reference<uno::XInterface> const& xInterface)
|
|
|
|
{
|
|
|
|
if (!xInterface.is())
|
|
|
|
return;
|
|
|
|
uno::Reference<lang::XTypeProvider> xTypeProvider(xInterface, uno::UNO_QUERY);
|
|
|
|
if (xTypeProvider.is())
|
|
|
|
{
|
|
|
|
const auto xSequenceTypes = xTypeProvider->getTypes();
|
|
|
|
for (auto const& xType : xSequenceTypes)
|
|
|
|
{
|
|
|
|
OUString aName = xType.getTypeName();
|
|
|
|
lclAppendNode(mpInterfacesTreeView, new SimpleStringNode(aName));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ObjectInspectorTreeHandler::appendServices(uno::Reference<uno::XInterface> const& xInterface)
|
|
|
|
{
|
|
|
|
if (!xInterface.is())
|
|
|
|
return;
|
|
|
|
|
|
|
|
auto xServiceInfo = uno::Reference<lang::XServiceInfo>(xInterface, uno::UNO_QUERY);
|
|
|
|
const uno::Sequence<OUString> aServiceNames(xServiceInfo->getSupportedServiceNames());
|
|
|
|
for (auto const& aServiceName : aServiceNames)
|
|
|
|
{
|
|
|
|
lclAppendNode(mpServicesTreeView, new SimpleStringNode(aServiceName));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ObjectInspectorTreeHandler::appendProperties(uno::Reference<uno::XInterface> const& xInterface)
|
|
|
|
{
|
|
|
|
if (!xInterface.is())
|
|
|
|
return;
|
|
|
|
GenericPropertiesNode aNode("", uno::Any(xInterface), comphelper::getProcessComponentContext());
|
|
|
|
aNode.fillChildren(mpPropertiesTreeView, nullptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ObjectInspectorTreeHandler::appendMethods(uno::Reference<uno::XInterface> const& xInterface)
|
|
|
|
{
|
|
|
|
if (!xInterface.is())
|
|
|
|
return;
|
|
|
|
|
|
|
|
uno::Reference<beans::XIntrospection> xIntrospection
|
|
|
|
= beans::theIntrospection::get(comphelper::getProcessComponentContext());
|
|
|
|
auto xIntrospectionAccess = xIntrospection->inspect(uno::Any(xInterface));
|
|
|
|
|
|
|
|
const auto xMethods = xIntrospectionAccess->getMethods(beans::MethodConcept::ALL);
|
|
|
|
for (auto const& xMethod : xMethods)
|
|
|
|
{
|
2021-02-18 12:02:06 +09:00
|
|
|
lclAppendNode(mpMethodsTreeView, new MethodNode(xMethod));
|
2021-02-17 11:49:56 +09:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-02-25 20:58:42 +09:00
|
|
|
void ObjectInspectorTreeHandler::updateBackButtonState()
|
|
|
|
{
|
|
|
|
mpObjectInspectorToolbar->set_item_sensitive("back", maInspectionStack.size() > 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ObjectInspectorTreeHandler::clearStack()
|
|
|
|
{
|
|
|
|
maInspectionStack.clear();
|
|
|
|
updateBackButtonState();
|
|
|
|
}
|
|
|
|
|
|
|
|
void ObjectInspectorTreeHandler::addToStack(css::uno::Any const& rAny)
|
|
|
|
{
|
|
|
|
maInspectionStack.push_back(rAny);
|
|
|
|
updateBackButtonState();
|
|
|
|
}
|
|
|
|
|
|
|
|
css::uno::Any ObjectInspectorTreeHandler::popFromStack()
|
|
|
|
{
|
|
|
|
maInspectionStack.pop_back();
|
|
|
|
uno::Any aAny = maInspectionStack.back();
|
|
|
|
updateBackButtonState();
|
|
|
|
return aAny;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ObjectInspectorTreeHandler::inspectObject(uno::Reference<uno::XInterface> const& xInterface)
|
2021-02-08 22:41:36 +09:00
|
|
|
{
|
|
|
|
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);
|
|
|
|
|
2021-02-25 21:11:39 +09:00
|
|
|
auto rPageId = mpObjectInspectorNotebook->get_current_page_ident();
|
|
|
|
NotebookEnterPage(rPageId);
|
2021-02-08 22:41:36 +09:00
|
|
|
}
|
|
|
|
|
2021-02-25 20:58:42 +09:00
|
|
|
void ObjectInspectorTreeHandler::introspect(uno::Reference<uno::XInterface> const& xInterface)
|
|
|
|
{
|
|
|
|
clearStack();
|
|
|
|
addToStack(uno::Any(xInterface));
|
|
|
|
inspectObject(xInterface);
|
|
|
|
}
|
|
|
|
|
2021-02-08 22:41:36 +09:00
|
|
|
void ObjectInspectorTreeHandler::dispose()
|
|
|
|
{
|
2021-02-17 11:49:56 +09:00
|
|
|
clearAll(mpInterfacesTreeView);
|
|
|
|
clearAll(mpServicesTreeView);
|
|
|
|
clearAll(mpPropertiesTreeView);
|
|
|
|
clearAll(mpMethodsTreeView);
|
2021-02-08 22:41:36 +09:00
|
|
|
}
|
|
|
|
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|