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>
|
2021-03-15 23:41:33 +09:00
|
|
|
#include <sfx2/sfxresid.hxx>
|
2022-07-14 10:12:44 +02:00
|
|
|
#include <utility>
|
2021-04-01 09:40:51 +02:00
|
|
|
#include <vcl/svapp.hxx>
|
2021-03-15 23:41:33 +09:00
|
|
|
#include "DevToolsStrings.hrc"
|
2021-02-08 22:41:36 +09:00
|
|
|
|
|
|
|
#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/PropertyConcept.hpp>
|
2021-03-05 22:28:40 +09:00
|
|
|
#include <com/sun/star/beans/PropertyAttribute.hpp>
|
2021-02-08 22:41:36 +09:00
|
|
|
#include <com/sun/star/beans/MethodConcept.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>
|
|
|
|
|
2021-03-15 23:41:33 +09:00
|
|
|
#include <com/sun/star/container/XNamed.hpp>
|
2021-02-12 19:00:19 +09:00
|
|
|
#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/Invocation.hpp>
|
2021-03-05 19:53:28 +09:00
|
|
|
#include <com/sun/star/script/XInvocation2.hpp>
|
|
|
|
#include <com/sun/star/script/MemberType.hpp>
|
2021-02-08 22:41:36 +09:00
|
|
|
|
|
|
|
#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
|
|
|
|
2022-05-19 00:33:37 +09:00
|
|
|
#include <vcl/settings.hxx>
|
|
|
|
#include <i18nlangtag/languagetag.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";
|
|
|
|
|
2021-03-15 16:22:40 +09:00
|
|
|
OUString enumValueToEnumName(uno::Any const& aValue,
|
|
|
|
uno::Reference<uno::XComponentContext> const& xContext)
|
|
|
|
{
|
|
|
|
sal_Int32 nIntValue = 0;
|
|
|
|
if (!cppu::enum2int(nIntValue, aValue))
|
|
|
|
return OUString();
|
|
|
|
|
|
|
|
uno::Reference<container::XHierarchicalNameAccess> xManager;
|
|
|
|
xManager.set(xContext->getValueByName(constTypeDescriptionManagerSingletonName),
|
|
|
|
uno::UNO_QUERY);
|
|
|
|
|
|
|
|
uno::Reference<reflection::XEnumTypeDescription> xTypeDescription;
|
2024-11-07 01:07:51 +05:00
|
|
|
xTypeDescription.set(xManager->getByHierarchicalName(aValue.getValueTypeName()),
|
2021-03-15 16:22:40 +09:00
|
|
|
uno::UNO_QUERY);
|
|
|
|
|
Avoid COW overhead using css::uno::Sequence
The scenarios are:
1. Calling sequence's begin() and end() in pairs to pass to algorithms
(both calls use getArray(), which does the COW checks)
2. In addition to #1, calling end() again when checking result of find
algorithms, and/or begin() to calculate result's distance
3. Using non-const sequences in range-based for loops, which internally
do #1
4. Assigning sequence to another sequence variable, and then modifying
one of them
In many cases, the sequences could be made const, or treated as const
for the purposes of the algorithms (using std::as_const, std::cbegin,
and std::cend). Where algorithm modifies the sequence, it was changed
to only call getArray() once. For that, css::uno::toNonConstRange was
introduced, which returns a struct (sublclass of std::pair) with two
iterators [begin, end], that are calculated using one call to begin()
and one call to getLength().
To handle #4, css::uno::Sequence::swap was introduced, that swaps the
internal pointer to uno_Sequence. So when a local Sequence variable
should be assigned to another variable, and the latter will be modified
further, it's now possible to use swap instead, so the two sequences
are kept independent.
The modified places were found by temporarily removing non-const end().
Change-Id: I8fe2787f200eecb70744e8b77fbdf7a49653f628
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/123542
Tested-by: Jenkins
Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
2021-10-13 09:02:48 +03:00
|
|
|
const uno::Sequence<sal_Int32> aValues = xTypeDescription->getEnumValues();
|
2021-03-15 16:22:40 +09:00
|
|
|
sal_Int32 nValuesIndex = std::find(aValues.begin(), aValues.end(), nIntValue) - aValues.begin();
|
|
|
|
uno::Sequence<OUString> aNames = xTypeDescription->getEnumNames();
|
|
|
|
return aNames[nValuesIndex];
|
|
|
|
}
|
|
|
|
|
2021-03-15 23:41:33 +09:00
|
|
|
OUString getInterfaceImplementationClass(uno::Reference<uno::XInterface> const& xInterface)
|
|
|
|
{
|
|
|
|
auto xServiceInfo = uno::Reference<lang::XServiceInfo>(xInterface, uno::UNO_QUERY);
|
|
|
|
if (xServiceInfo.is())
|
|
|
|
return xServiceInfo->getImplementationName();
|
|
|
|
return OUString();
|
|
|
|
}
|
|
|
|
|
|
|
|
/** converts basic any value to a string */
|
|
|
|
OUString convertBasicValueToString(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-15 23:41:33 +09:00
|
|
|
return SfxResId(STR_ANY_VALUE_NULL);
|
2021-02-12 19:00:19 +09:00
|
|
|
|
2021-03-19 17:39:28 +09:00
|
|
|
uno::TypeClass eType = aValue.getValueTypeClass();
|
2021-02-08 22:41:36 +09:00
|
|
|
|
|
|
|
switch (eType)
|
|
|
|
{
|
|
|
|
case uno::TypeClass_BOOLEAN:
|
|
|
|
{
|
|
|
|
bool bBool = aValue.get<bool>();
|
2021-03-15 23:41:33 +09:00
|
|
|
aRetStr = bBool ? SfxResId(STR_ANY_VALUE_TRUE) : SfxResId(STR_ANY_VALUE_FALSE);
|
2021-02-08 22:41:36 +09:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case uno::TypeClass_CHAR:
|
|
|
|
{
|
|
|
|
sal_Unicode aChar = aValue.get<sal_Unicode>();
|
|
|
|
aRetStr = OUString::number(aChar);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case uno::TypeClass_STRING:
|
|
|
|
{
|
2021-03-15 16:22:40 +09:00
|
|
|
aRetStr = u"\"" + aValue.get<OUString>() + u"\"";
|
2021-02-08 22:41:36 +09:00
|
|
|
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:
|
|
|
|
{
|
2021-03-15 16:22:40 +09:00
|
|
|
aRetStr = enumValueToEnumName(aValue, xContext);
|
2021-02-12 19:00:19 +09:00
|
|
|
break;
|
|
|
|
}
|
2021-02-08 22:41:36 +09:00
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return aRetStr;
|
|
|
|
}
|
|
|
|
|
2021-03-15 23:41:33 +09:00
|
|
|
// returns a name of the object, if available
|
|
|
|
OUString getInterfaceName(uno::Reference<uno::XInterface> const& xInterface,
|
|
|
|
const uno::Reference<uno::XComponentContext>& xContext)
|
|
|
|
{
|
|
|
|
uno::Reference<container::XNamed> xNamed(xInterface, uno::UNO_QUERY);
|
|
|
|
if (xNamed.is())
|
|
|
|
return xNamed->getName();
|
|
|
|
|
|
|
|
auto xInvocationFactory = css::script::Invocation::create(xContext);
|
|
|
|
uno::Sequence<uno::Any> aParameters = { uno::Any(xInterface) };
|
|
|
|
auto xInvocationInterface = xInvocationFactory->createInstanceWithArguments(aParameters);
|
|
|
|
if (xInvocationInterface.is())
|
|
|
|
{
|
|
|
|
uno::Reference<script::XInvocation2> xInvocation(xInvocationInterface, uno::UNO_QUERY);
|
2024-05-10 13:18:37 +02:00
|
|
|
if (xInvocation.is() && xInvocation->hasProperty(u"Name"_ustr))
|
2021-03-15 23:41:33 +09:00
|
|
|
{
|
2024-05-10 13:18:37 +02:00
|
|
|
uno::Any aAny = xInvocation->getValue(u"Name"_ustr);
|
2021-03-15 23:41:33 +09:00
|
|
|
if (aAny.hasValue() && aAny.getValueTypeClass() == uno::TypeClass_STRING)
|
|
|
|
return aAny.get<OUString>();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return OUString();
|
|
|
|
}
|
|
|
|
|
|
|
|
OUString convertAnyToString(const uno::Any& aValue,
|
|
|
|
const uno::Reference<uno::XComponentContext>& xContext)
|
|
|
|
{
|
|
|
|
// return early if we don't have any value
|
|
|
|
if (!aValue.hasValue())
|
|
|
|
return SfxResId(STR_ANY_VALUE_NULL);
|
|
|
|
|
|
|
|
OUString aRetStr;
|
|
|
|
|
|
|
|
uno::TypeClass eType = aValue.getValueTypeClass();
|
|
|
|
|
|
|
|
switch (eType)
|
|
|
|
{
|
|
|
|
case uno::TypeClass_INTERFACE:
|
|
|
|
{
|
|
|
|
uno::Reference<uno::XInterface> xInterface(aValue, uno::UNO_QUERY);
|
|
|
|
if (!xInterface.is())
|
|
|
|
aRetStr = SfxResId(STR_ANY_VALUE_NULL);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
OUString aImplementationClass = getInterfaceImplementationClass(xInterface);
|
|
|
|
if (aImplementationClass.isEmpty())
|
|
|
|
aImplementationClass = SfxResId(STR_CLASS_UNKNOWN);
|
|
|
|
aRetStr
|
2021-03-19 17:39:28 +09:00
|
|
|
= SfxResId(STR_PROPERTY_VALUE_OBJECT).replaceFirst("%1", aImplementationClass);
|
|
|
|
|
|
|
|
OUString aString = getInterfaceName(xInterface, xContext);
|
|
|
|
if (!aString.isEmpty())
|
|
|
|
aRetStr += " {" + aString + "}";
|
2021-03-15 23:41:33 +09:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case uno::TypeClass_STRUCT:
|
|
|
|
{
|
|
|
|
aRetStr = SfxResId(STR_PROPERTY_VALUE_STRUCT);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
{
|
|
|
|
aRetStr = convertBasicValueToString(aValue, xContext);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return aRetStr;
|
|
|
|
}
|
|
|
|
|
|
|
|
OUString convertAnyToShortenedString(const uno::Any& aValue,
|
|
|
|
const uno::Reference<uno::XComponentContext>& xContext)
|
|
|
|
{
|
|
|
|
// return early if we don't have any value
|
|
|
|
if (!aValue.hasValue())
|
|
|
|
return SfxResId(STR_ANY_VALUE_NULL);
|
|
|
|
|
|
|
|
OUString aRetStr;
|
|
|
|
|
|
|
|
uno::TypeClass eType = aValue.getValueTypeClass();
|
|
|
|
|
2021-03-19 17:39:28 +09:00
|
|
|
constexpr const sal_Int32 constMaxStringLength = 60;
|
|
|
|
|
2021-03-15 23:41:33 +09:00
|
|
|
switch (eType)
|
|
|
|
{
|
|
|
|
case uno::TypeClass_INTERFACE:
|
|
|
|
{
|
2021-03-19 17:39:28 +09:00
|
|
|
aRetStr = convertAnyToString(aValue, xContext);
|
2021-03-15 23:41:33 +09:00
|
|
|
|
2021-03-19 17:39:28 +09:00
|
|
|
if (aRetStr.getLength() > constMaxStringLength + 3)
|
|
|
|
aRetStr = OUString::Concat(aRetStr.subView(0, constMaxStringLength)) + u"...";
|
2021-03-15 23:41:33 +09:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case uno::TypeClass_STRING:
|
|
|
|
{
|
2021-03-19 17:39:28 +09:00
|
|
|
OUString aString = convertAnyToString(aValue, xContext);
|
|
|
|
if (aString.getLength() > constMaxStringLength + 4)
|
|
|
|
aString = OUString::Concat(aString.subView(0, constMaxStringLength)) + u"\"...";
|
|
|
|
aRetStr = aString.replaceAll("\n", " ");
|
2021-03-15 23:41:33 +09:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
{
|
|
|
|
aRetStr = convertAnyToString(aValue, xContext);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return aRetStr;
|
|
|
|
}
|
|
|
|
|
2021-03-12 19:27:11 +09:00
|
|
|
/** converts an any's type to a string (in a short form) */
|
2021-03-04 22:19:11 +09:00
|
|
|
OUString getAnyType(const uno::Any& aValue)
|
|
|
|
{
|
2024-11-07 01:07:51 +05:00
|
|
|
OUString aTypeName = aValue.getValueTypeName();
|
2021-03-04 22:19:11 +09:00
|
|
|
return aTypeName.replaceAll("com.sun.star", "css");
|
|
|
|
}
|
2021-02-09 19:29:50 +09:00
|
|
|
|
2021-03-12 19:27:11 +09:00
|
|
|
/** converts a Type to a XIdlClass */
|
2021-03-11 23:26:29 +09:00
|
|
|
uno::Reference<reflection::XIdlClass>
|
|
|
|
convertTypeToIdlClass(const uno::Type& rType,
|
|
|
|
const uno::Reference<uno::XComponentContext>& xContext)
|
|
|
|
{
|
|
|
|
auto xReflection = reflection::theCoreReflection::get(xContext);
|
|
|
|
return xReflection->forName(rType.getTypeName());
|
|
|
|
}
|
|
|
|
|
2021-02-08 22:41:36 +09:00
|
|
|
// Object inspector nodes
|
|
|
|
|
2021-03-12 19:27:11 +09:00
|
|
|
/** Object inspector node's main interface
|
|
|
|
*
|
|
|
|
* The interface for the "attached" object to a tree view nodes that
|
|
|
|
* are added to the tree views of the object inspector part. The node
|
|
|
|
* can return the main value of the node (object name) and if present
|
|
|
|
* also the values for additional columns. It signals if a tree needs
|
|
|
|
* an expander and fills the children of the tree is any exists.
|
|
|
|
*
|
|
|
|
*/
|
2021-02-10 16:54:59 +09:00
|
|
|
class ObjectInspectorNodeInterface
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
ObjectInspectorNodeInterface() = default;
|
|
|
|
|
|
|
|
virtual ~ObjectInspectorNodeInterface() {}
|
|
|
|
|
2021-03-12 19:27:11 +09:00
|
|
|
// main value (object name) of the tree view node
|
2021-02-10 16:54:59 +09:00
|
|
|
virtual OUString getObjectName() = 0;
|
|
|
|
|
2021-03-12 19:27:11 +09:00
|
|
|
// should show the expander for the tree view node
|
2021-02-10 17:33:33 +09:00
|
|
|
virtual bool shouldShowExpander() { return false; }
|
|
|
|
|
2021-03-12 19:27:11 +09:00
|
|
|
// fill the children for the current tree view node
|
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
|
|
|
|
2021-03-12 19:27:11 +09:00
|
|
|
// fill any additional column values for the current tree view node
|
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-03-12 19:27:11 +09:00
|
|
|
// appends the node to the root of the tree view
|
2021-08-18 18:31:05 +02:00
|
|
|
OUString lclAppendNode(const std::unique_ptr<weld::TreeView>& pTree,
|
|
|
|
ObjectInspectorNodeInterface* pEntry)
|
2021-02-08 22:41:36 +09:00
|
|
|
{
|
|
|
|
OUString sName = pEntry->getObjectName();
|
2022-02-04 09:13:52 +00:00
|
|
|
OUString sId(weld::toId(pEntry));
|
2021-02-08 22:41:36 +09:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2021-03-12 19:27:11 +09:00
|
|
|
// appends the node to the parent
|
2021-08-18 18:31:05 +02:00
|
|
|
OUString lclAppendNodeToParent(const 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();
|
2022-02-04 09:13:52 +00:00
|
|
|
OUString sId(weld::toId(pEntry));
|
2021-02-08 22:41:36 +09:00
|
|
|
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-03-12 19:27:11 +09:00
|
|
|
/** Node that represent just a simple string with no children or columns */
|
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:
|
2022-07-14 10:12:44 +02:00
|
|
|
SimpleStringNode(OUString sName)
|
|
|
|
: msName(std::move(sName))
|
2021-02-10 21:58:22 +09:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
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-03-12 19:27:11 +09:00
|
|
|
/** Node represents a method of an object */
|
2021-02-18 12:02:06 +09:00
|
|
|
class MethodNode : public ObjectInspectorNodeInterface
|
|
|
|
{
|
|
|
|
private:
|
|
|
|
uno::Reference<reflection::XIdlMethod> mxMethod;
|
|
|
|
|
|
|
|
public:
|
2022-07-14 10:12:44 +02:00
|
|
|
MethodNode(uno::Reference<reflection::XIdlMethod> xMethod)
|
|
|
|
: mxMethod(std::move(xMethod))
|
2021-02-18 12:02:06 +09:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
OUString getObjectName() override { return mxMethod->getName(); }
|
|
|
|
|
|
|
|
static OUString simpleTypeName(uno::Reference<reflection::XIdlClass> const& xClass)
|
|
|
|
{
|
|
|
|
switch (xClass->getTypeClass())
|
|
|
|
{
|
|
|
|
case uno::TypeClass_INTERFACE:
|
2021-03-15 23:41:33 +09:00
|
|
|
return SfxResId(STR_METHOD_TYPE_OBJECT);
|
2021-02-18 12:02:06 +09:00
|
|
|
case uno::TypeClass_STRUCT:
|
2021-03-15 23:41:33 +09:00
|
|
|
return SfxResId(STR_METHOD_TYPE_STRUCT);
|
2021-02-18 12:02:06 +09:00
|
|
|
case uno::TypeClass_ENUM:
|
2021-03-15 23:41:33 +09:00
|
|
|
return SfxResId(STR_METHOD_TYPE_ENUM);
|
2021-02-18 12:02:06 +09:00
|
|
|
case uno::TypeClass_SEQUENCE:
|
2021-03-15 23:41:33 +09:00
|
|
|
return SfxResId(STR_METHOD_TYPE_SEQUENCE);
|
2021-02-18 12:02:06 +09:00
|
|
|
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:
|
2021-03-15 23:41:33 +09:00
|
|
|
aInString += SfxResId(STR_PARMETER_MODE_IN) + " ";
|
2021-02-18 12:02:06 +09:00
|
|
|
break;
|
|
|
|
case reflection::ParamMode_OUT:
|
2021-03-15 23:41:33 +09:00
|
|
|
aInString += SfxResId(STR_PARMETER_MODE_OUT) + " ";
|
2021-02-18 12:02:06 +09:00
|
|
|
break;
|
|
|
|
case reflection::ParamMode_INOUT:
|
2021-03-15 23:41:33 +09:00
|
|
|
aInString += SfxResId(STR_PARMETER_MODE_IN_AND_OUT) + " ";
|
2021-02-18 12:02:06 +09:00
|
|
|
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-03-12 19:27:11 +09:00
|
|
|
/** Node represents a class (XIdlClass) of an object.
|
|
|
|
*
|
|
|
|
* Children are superclasses of the current class. XInterface superclass
|
|
|
|
* is ignored.
|
|
|
|
*
|
|
|
|
*/
|
2021-03-11 23:26:29 +09:00
|
|
|
class ClassNode : public ObjectInspectorNodeInterface
|
|
|
|
{
|
|
|
|
private:
|
|
|
|
uno::Reference<reflection::XIdlClass> mxClass;
|
|
|
|
|
|
|
|
static bool isXInterface(uno::Reference<reflection::XIdlClass> const& xClass)
|
|
|
|
{
|
|
|
|
return xClass->getName() == "com.sun.star.uno.XInterface";
|
|
|
|
}
|
|
|
|
|
|
|
|
public:
|
2022-07-14 10:12:44 +02:00
|
|
|
ClassNode(uno::Reference<reflection::XIdlClass> xClass)
|
|
|
|
: mxClass(std::move(xClass))
|
2021-03-11 23:26:29 +09:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
bool shouldShowExpander() override
|
|
|
|
{
|
|
|
|
auto const& xSuperClasses = mxClass->getSuperclasses();
|
|
|
|
return xSuperClasses.getLength() > 2
|
|
|
|
|| (xSuperClasses.getLength() == 1 && !isXInterface(xSuperClasses[0]));
|
|
|
|
}
|
|
|
|
|
|
|
|
OUString getObjectName() override { return mxClass->getName(); }
|
|
|
|
|
2021-03-12 19:27:11 +09:00
|
|
|
// Fill superclasses
|
2021-03-11 23:26:29 +09:00
|
|
|
void fillChildren(std::unique_ptr<weld::TreeView>& rTree,
|
|
|
|
const weld::TreeIter* pParent) override
|
|
|
|
{
|
|
|
|
auto const& xSuperClasses = mxClass->getSuperclasses();
|
|
|
|
for (auto const& xSuper : xSuperClasses)
|
|
|
|
{
|
|
|
|
if (!isXInterface(xSuper))
|
|
|
|
lclAppendNodeToParent(rTree, pParent, new ClassNode(xSuper));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2021-03-14 22:05:11 +01:00
|
|
|
/** Node represents a basic value, that can be any object, sequence, struct */
|
2021-02-10 21:58:22 +09:00
|
|
|
class BasicValueNode : public SimpleStringNode
|
|
|
|
{
|
|
|
|
protected:
|
2021-02-10 17:33:33 +09:00
|
|
|
uno::Any maAny;
|
2021-03-05 22:28:40 +09:00
|
|
|
OUString mrInfo;
|
2021-02-10 17:33:33 +09:00
|
|
|
uno::Reference<uno::XComponentContext> mxContext;
|
2021-02-08 22:41:36 +09:00
|
|
|
|
2021-08-18 18:31:05 +02:00
|
|
|
ObjectInspectorNodeInterface*
|
|
|
|
createNodeObjectForAny(OUString const& rName, const uno::Any& rAny, OUString const& mrInfo);
|
2021-02-11 21:14:36 +09:00
|
|
|
|
2021-02-10 17:33:33 +09:00
|
|
|
public:
|
2022-07-14 10:12:44 +02:00
|
|
|
BasicValueNode(OUString const& rName, uno::Any aAny, OUString aInfo,
|
|
|
|
uno::Reference<uno::XComponentContext> xContext)
|
2021-02-10 21:58:22 +09:00
|
|
|
: SimpleStringNode(rName)
|
2022-07-14 10:12:44 +02:00
|
|
|
, maAny(std::move(aAny))
|
|
|
|
, mrInfo(std::move(aInfo))
|
|
|
|
, mxContext(std::move(xContext))
|
2021-02-08 22:41:36 +09:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2021-05-05 14:20:11 +02:00
|
|
|
const uno::Any& getAny() const { return maAny; }
|
2021-02-23 22:54:06 +09:00
|
|
|
|
2021-02-10 18:12:38 +09:00
|
|
|
bool shouldShowExpander() override
|
|
|
|
{
|
|
|
|
if (maAny.hasValue())
|
|
|
|
{
|
2024-11-07 01:07:51 +05:00
|
|
|
switch (maAny.getValueTypeClass())
|
2021-02-10 20:56:32 +09:00
|
|
|
{
|
|
|
|
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-15 23:41:33 +09:00
|
|
|
OUString aValue = convertAnyToShortenedString(maAny, mxContext);
|
2021-03-04 22:08:32 +09:00
|
|
|
OUString aType = getAnyType(maAny);
|
2021-02-10 17:33:33 +09:00
|
|
|
|
2021-03-05 22:28:40 +09:00
|
|
|
return { { 1, aValue }, { 2, aType }, { 3, mrInfo } };
|
2021-02-10 17:33:33 +09:00
|
|
|
}
|
2021-02-08 22:41:36 +09:00
|
|
|
};
|
|
|
|
|
2021-03-12 19:27:11 +09:00
|
|
|
/** Node represents a property */
|
2021-02-10 21:58:22 +09:00
|
|
|
class GenericPropertiesNode : public BasicValueNode
|
2021-02-08 22:41:36 +09:00
|
|
|
{
|
|
|
|
public:
|
2021-03-05 22:28:40 +09:00
|
|
|
GenericPropertiesNode(OUString const& rName, uno::Any const& rAny, OUString const& rInfo,
|
2021-02-10 21:58:22 +09:00
|
|
|
uno::Reference<uno::XComponentContext> const& xContext)
|
2021-03-05 22:28:40 +09:00
|
|
|
: BasicValueNode(rName, rAny, rInfo, 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-03-12 19:27:11 +09:00
|
|
|
/** Node represents a struct */
|
2021-02-11 16:50:19 +09:00
|
|
|
class StructNode : public BasicValueNode
|
|
|
|
{
|
|
|
|
public:
|
2021-03-05 22:28:40 +09:00
|
|
|
StructNode(OUString const& rName, uno::Any const& rAny, OUString const& rInfo,
|
2021-02-11 16:50:19 +09:00
|
|
|
uno::Reference<uno::XComponentContext> const& xContext)
|
2021-03-05 22:28:40 +09:00
|
|
|
: BasicValueNode(rName, rAny, rInfo, xContext)
|
2021-02-11 16:50:19 +09:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
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-03-12 19:27:11 +09:00
|
|
|
/** Node represents a sequence */
|
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-03-05 22:28:40 +09:00
|
|
|
SequenceNode(OUString const& rName, uno::Any const& rAny, OUString const& rInfo,
|
2021-02-10 18:12:38 +09:00
|
|
|
uno::Reference<uno::XComponentContext> const& xContext)
|
2021-03-05 22:28:40 +09:00
|
|
|
: BasicValueNode(rName, rAny, rInfo, xContext)
|
2021-02-10 18:12:38 +09:00
|
|
|
{
|
2021-03-11 23:26:29 +09:00
|
|
|
auto xClass = convertTypeToIdlClass(maAny.getValueType(), mxContext);
|
2021-03-04 22:36:55 +09:00
|
|
|
mxIdlArray = xClass->getArray();
|
2021-02-10 18:12:38 +09:00
|
|
|
}
|
|
|
|
|
2021-03-04 22:36:55 +09:00
|
|
|
bool shouldShowExpander() override
|
|
|
|
{
|
2021-03-12 17:19:32 +01:00
|
|
|
// Show expander only if the sequence has elements
|
2021-03-04 22:36:55 +09:00
|
|
|
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-11 16:50:19 +09:00
|
|
|
|
2021-03-05 22:28:40 +09:00
|
|
|
auto* pObjectInspectorNode
|
2024-05-10 13:18:37 +02:00
|
|
|
= createNodeObjectForAny(OUString::number(i), aArrayValue, u""_ustr);
|
2021-02-11 21:14:36 +09:00
|
|
|
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
|
|
|
|
2023-05-25 14:24:11 +02:00
|
|
|
OUString aType
|
|
|
|
= getAnyType(maAny).replaceAll(u"[]", u"") + u"[" + OUString::number(nLength) + u"]";
|
2021-02-10 18:12:38 +09:00
|
|
|
|
2021-03-15 23:41:33 +09:00
|
|
|
OUString aValue
|
|
|
|
= SfxResId(STR_PROPERTY_VALUE_SEQUENCE).replaceFirst("%1", OUString::number(nLength));
|
|
|
|
|
2021-02-10 18:12:38 +09:00
|
|
|
return {
|
2021-03-15 23:41:33 +09:00
|
|
|
{ 1, aValue },
|
2021-02-10 18:12:38 +09:00
|
|
|
{ 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-03-19 15:48:33 +09:00
|
|
|
try
|
2021-02-23 22:04:30 +09:00
|
|
|
{
|
2021-03-19 15:48:33 +09:00
|
|
|
const auto xNameAccess = uno::Reference<container::XNameAccess>(maAny, uno::UNO_QUERY);
|
|
|
|
if (xNameAccess.is())
|
2021-02-23 22:04:30 +09:00
|
|
|
{
|
2021-03-19 15:48:33 +09:00
|
|
|
const uno::Sequence<OUString> aNames = xNameAccess->getElementNames();
|
|
|
|
for (OUString const& rName : aNames)
|
|
|
|
{
|
|
|
|
uno::Any aAny = xNameAccess->getByName(rName);
|
|
|
|
auto* pObjectInspectorNode = createNodeObjectForAny(
|
|
|
|
u"@" + rName, aAny, SfxResId(STR_PROPERTY_TYPE_IS_NAMED_CONTAINER));
|
|
|
|
lclAppendNodeToParent(pTree, pParent, pObjectInspectorNode);
|
|
|
|
}
|
2021-02-23 22:04:30 +09:00
|
|
|
}
|
|
|
|
}
|
2021-03-19 15:48:33 +09:00
|
|
|
catch (...)
|
2021-02-23 22:04:30 +09:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2021-03-19 15:48:33 +09:00
|
|
|
try
|
2021-03-03 21:28:32 +09:00
|
|
|
{
|
2021-03-19 15:48:33 +09:00
|
|
|
const auto xIndexAccess = uno::Reference<container::XIndexAccess>(maAny, uno::UNO_QUERY);
|
|
|
|
if (xIndexAccess.is())
|
2021-03-03 21:28:32 +09:00
|
|
|
{
|
2021-03-19 15:48:33 +09:00
|
|
|
for (sal_Int32 nIndex = 0; nIndex < xIndexAccess->getCount(); ++nIndex)
|
2021-03-03 21:28:32 +09:00
|
|
|
{
|
2021-03-19 15:48:33 +09:00
|
|
|
uno::Any aAny = xIndexAccess->getByIndex(nIndex);
|
2021-03-03 21:28:32 +09:00
|
|
|
auto* pObjectInspectorNode
|
2021-03-15 23:41:33 +09:00
|
|
|
= createNodeObjectForAny(u"@" + OUString::number(nIndex), aAny,
|
2021-03-19 15:48:33 +09:00
|
|
|
SfxResId(STR_PROPERTY_TYPE_IS_INDEX_CONTAINER));
|
2021-03-03 21:28:32 +09:00
|
|
|
lclAppendNodeToParent(pTree, pParent, pObjectInspectorNode);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-03-19 15:48:33 +09:00
|
|
|
catch (...)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
try
|
|
|
|
{
|
|
|
|
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(u"@" + OUString::number(nIndex), aAny,
|
|
|
|
SfxResId(STR_PROPERTY_TYPE_IS_ENUMERATION));
|
|
|
|
lclAppendNodeToParent(pTree, pParent, pObjectInspectorNode);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
catch (...)
|
|
|
|
{
|
|
|
|
}
|
2021-03-03 21:28:32 +09:00
|
|
|
|
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);
|
2021-03-05 19:53:28 +09:00
|
|
|
if (!xInvocationInterface.is())
|
|
|
|
return;
|
2021-02-10 16:50:26 +09:00
|
|
|
|
2021-03-05 19:53:28 +09:00
|
|
|
uno::Reference<script::XInvocation2> xInvocation(xInvocationInterface, uno::UNO_QUERY);
|
|
|
|
if (!xInvocation.is())
|
|
|
|
return;
|
2021-02-10 16:50:26 +09:00
|
|
|
|
2021-03-19 15:48:33 +09:00
|
|
|
auto const& xInvocationAccess = xInvocation->getIntrospection();
|
|
|
|
if (!xInvocationAccess.is())
|
|
|
|
return;
|
|
|
|
|
|
|
|
uno::Sequence<script::InvocationInfo> aInvocationInfoSequence;
|
|
|
|
try
|
|
|
|
{
|
|
|
|
aInvocationInfoSequence = xInvocation->getInfo();
|
|
|
|
}
|
|
|
|
catch (...)
|
|
|
|
{
|
|
|
|
}
|
2021-03-05 22:28:40 +09:00
|
|
|
|
2024-01-27 15:42:54 +06:00
|
|
|
for (auto const& aInvocationInfo : aInvocationInfoSequence)
|
2021-02-10 16:50:26 +09:00
|
|
|
{
|
2021-03-05 19:53:28 +09:00
|
|
|
if (aInvocationInfo.eMemberType == script::MemberType_PROPERTY)
|
2021-02-10 16:50:26 +09:00
|
|
|
{
|
2021-03-05 19:53:28 +09:00
|
|
|
uno::Any aCurrentAny;
|
|
|
|
auto const& aPropertyName = aInvocationInfo.aName;
|
2021-03-05 22:28:40 +09:00
|
|
|
|
|
|
|
bool bIsAttribute = false;
|
|
|
|
bool bIsGetSetMethod = false;
|
|
|
|
bool bMethodGet = false;
|
|
|
|
bool bMethodSet = false;
|
|
|
|
bool bMethodIs = false;
|
2021-03-05 19:53:28 +09:00
|
|
|
try
|
|
|
|
{
|
|
|
|
aCurrentAny = xInvocation->getValue(aPropertyName);
|
2021-03-05 22:28:40 +09:00
|
|
|
bIsAttribute = xInvocationAccess->hasProperty(aPropertyName,
|
|
|
|
beans::PropertyConcept::ATTRIBUTES);
|
|
|
|
bIsGetSetMethod = xInvocationAccess->hasProperty(aPropertyName,
|
|
|
|
beans::PropertyConcept::METHODS);
|
|
|
|
if (bIsGetSetMethod)
|
|
|
|
{
|
|
|
|
bMethodGet = xInvocationAccess->hasMethod(u"get" + aPropertyName,
|
|
|
|
beans::MethodConcept::PROPERTY);
|
|
|
|
bMethodSet = xInvocationAccess->hasMethod(u"set" + aPropertyName,
|
|
|
|
beans::MethodConcept::PROPERTY);
|
|
|
|
bMethodIs = xInvocationAccess->hasMethod(u"is" + aPropertyName,
|
|
|
|
beans::MethodConcept::PROPERTY);
|
|
|
|
}
|
2021-03-05 19:53:28 +09:00
|
|
|
}
|
|
|
|
catch (...)
|
2021-02-10 16:50:26 +09:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2021-03-05 22:28:40 +09:00
|
|
|
std::vector<OUString> aInfoCollection;
|
|
|
|
if (bIsAttribute)
|
2021-03-15 23:41:33 +09:00
|
|
|
aInfoCollection.push_back(SfxResId(STR_PROPERTY_ATTRIBUTE_IS_ATTRIBUTE));
|
2021-03-05 22:28:40 +09:00
|
|
|
if (bIsGetSetMethod)
|
|
|
|
{
|
2021-03-15 23:41:33 +09:00
|
|
|
bool bHasGet = false;
|
2021-03-05 22:28:40 +09:00
|
|
|
OUString aString;
|
|
|
|
if (bMethodGet || bMethodIs)
|
|
|
|
{
|
2021-03-15 23:41:33 +09:00
|
|
|
aString += SfxResId(STR_PROPERTY_ATTRIBUTE_GET);
|
|
|
|
bHasGet = true;
|
2021-03-05 22:28:40 +09:00
|
|
|
}
|
|
|
|
if (bMethodSet)
|
|
|
|
{
|
2021-03-15 23:41:33 +09:00
|
|
|
if (bHasGet)
|
|
|
|
aString += u"+";
|
|
|
|
aString += SfxResId(STR_PROPERTY_ATTRIBUTE_SET);
|
2021-03-05 22:28:40 +09:00
|
|
|
}
|
2021-03-15 23:41:33 +09:00
|
|
|
aInfoCollection.push_back(aString);
|
|
|
|
if (bMethodSet && !bHasGet)
|
|
|
|
aInfoCollection.push_back(SfxResId(STR_PROPERTY_ATTRIBUTE_WRITEONLY));
|
2021-03-05 22:28:40 +09:00
|
|
|
}
|
|
|
|
if (aInvocationInfo.PropertyAttribute & beans::PropertyAttribute::MAYBEVOID)
|
2021-03-15 23:41:33 +09:00
|
|
|
aInfoCollection.push_back(SfxResId(STR_PROPERTY_ATTRIBUTE_MAYBEVOID));
|
2021-03-05 22:28:40 +09:00
|
|
|
if (aInvocationInfo.PropertyAttribute & beans::PropertyAttribute::READONLY)
|
2021-03-15 23:41:33 +09:00
|
|
|
aInfoCollection.push_back(SfxResId(STR_PROPERTY_ATTRIBUTE_READONLY));
|
2021-03-05 22:28:40 +09:00
|
|
|
if (aInvocationInfo.PropertyAttribute & beans::PropertyAttribute::REMOVABLE)
|
2021-03-15 23:41:33 +09:00
|
|
|
aInfoCollection.push_back(SfxResId(STR_PROPERTY_ATTRIBUTE_REMOVABLE));
|
2021-03-05 22:28:40 +09:00
|
|
|
if (aInvocationInfo.PropertyAttribute & beans::PropertyAttribute::BOUND)
|
2021-03-15 23:41:33 +09:00
|
|
|
aInfoCollection.push_back(SfxResId(STR_PROPERTY_ATTRIBUTE_BOUND));
|
2021-03-05 22:28:40 +09:00
|
|
|
if (aInvocationInfo.PropertyAttribute & beans::PropertyAttribute::CONSTRAINED)
|
2021-03-15 23:41:33 +09:00
|
|
|
aInfoCollection.push_back(SfxResId(STR_PROPERTY_ATTRIBUTE_CONSTRAINED));
|
2021-03-05 22:28:40 +09:00
|
|
|
if (aInvocationInfo.PropertyAttribute & beans::PropertyAttribute::TRANSIENT)
|
2021-03-15 23:41:33 +09:00
|
|
|
aInfoCollection.push_back(SfxResId(STR_PROPERTY_ATTRIBUTE_TRANSIENT));
|
2021-03-05 22:28:40 +09:00
|
|
|
if (aInvocationInfo.PropertyAttribute & beans::PropertyAttribute::MAYBEAMBIGUOUS)
|
2021-03-15 23:41:33 +09:00
|
|
|
aInfoCollection.push_back(SfxResId(STR_PROPERTY_ATTRIBUTE_MAYBEAMBIGUOUS));
|
2021-03-05 22:28:40 +09:00
|
|
|
if (aInvocationInfo.PropertyAttribute & beans::PropertyAttribute::MAYBEDEFAULT)
|
2021-03-15 23:41:33 +09:00
|
|
|
aInfoCollection.push_back(SfxResId(STR_PROPERTY_ATTRIBUTE_MAYBEDEFAULT));
|
2021-03-05 22:28:40 +09:00
|
|
|
|
|
|
|
bool bSet = false;
|
|
|
|
OUString aInfoString;
|
|
|
|
for (auto const& rString : aInfoCollection)
|
|
|
|
{
|
|
|
|
if (bSet)
|
|
|
|
aInfoString += ", ";
|
|
|
|
else
|
|
|
|
bSet = true;
|
|
|
|
|
|
|
|
aInfoString += rString;
|
|
|
|
}
|
|
|
|
|
|
|
|
auto* pObjectInspectorNode
|
|
|
|
= createNodeObjectForAny(aPropertyName, aCurrentAny, aInfoString);
|
2021-03-05 19:53:28 +09:00
|
|
|
if (pObjectInspectorNode)
|
|
|
|
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);
|
2024-11-07 01:07:51 +05:00
|
|
|
uno::Reference<reflection::XIdlClass> xClass = xReflection->forName(maAny.getValueTypeName());
|
2021-02-11 16:50:19 +09:00
|
|
|
|
|
|
|
const auto xFields = xClass->getFields();
|
|
|
|
|
|
|
|
for (auto const& xField : xFields)
|
|
|
|
{
|
|
|
|
OUString aFieldName = xField->getName();
|
|
|
|
uno::Any aFieldValue = xField->get(maAny);
|
|
|
|
|
2024-05-10 13:18:37 +02:00
|
|
|
auto* pObjectInspectorNode = createNodeObjectForAny(aFieldName, aFieldValue, u""_ustr);
|
2021-02-11 21:14:36 +09:00
|
|
|
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-08-18 18:31:05 +02:00
|
|
|
ObjectInspectorNodeInterface* BasicValueNode::createNodeObjectForAny(OUString const& rName,
|
|
|
|
const uno::Any& rAny,
|
|
|
|
OUString const& rInfo)
|
2021-02-11 21:14:36 +09:00
|
|
|
{
|
2024-11-07 01:07:51 +05:00
|
|
|
switch (rAny.getValueTypeClass())
|
2021-02-11 21:14:36 +09:00
|
|
|
{
|
|
|
|
case uno::TypeClass_INTERFACE:
|
2021-03-05 22:28:40 +09:00
|
|
|
return new GenericPropertiesNode(rName, rAny, rInfo, mxContext);
|
2021-02-11 16:50:19 +09:00
|
|
|
|
2021-02-11 21:14:36 +09:00
|
|
|
case uno::TypeClass_SEQUENCE:
|
2021-03-05 22:28:40 +09:00
|
|
|
return new SequenceNode(rName, rAny, rInfo, mxContext);
|
2021-02-11 21:14:36 +09:00
|
|
|
|
|
|
|
case uno::TypeClass_STRUCT:
|
2021-03-05 22:28:40 +09:00
|
|
|
return new StructNode(rName, rAny, rInfo, mxContext);
|
2021-02-11 21:14:36 +09:00
|
|
|
|
|
|
|
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
|
|
|
|
2021-03-05 22:28:40 +09:00
|
|
|
return new BasicValueNode(rName, rAny, rInfo, mxContext);
|
2021-02-10 16:50:26 +09:00
|
|
|
}
|
2021-02-10 18:12:38 +09:00
|
|
|
|
2021-03-12 19:27:11 +09:00
|
|
|
} // end anonymous namespace
|
2021-03-04 21:57:49 +09:00
|
|
|
|
2021-03-12 19:27:11 +09:00
|
|
|
// Object inspector tree view helper functions
|
|
|
|
namespace
|
|
|
|
{
|
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;
|
|
|
|
|
2022-02-04 09:13:52 +00:00
|
|
|
if (auto* pNode = weld::fromId<ObjectInspectorNodeInterface*>(sID))
|
2021-02-25 20:58:42 +09:00
|
|
|
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-03-15 14:56:57 +09:00
|
|
|
std::unique_ptr<ObjectInspectorWidgets>& pObjectInspectorWidgets)
|
|
|
|
: mpObjectInspectorWidgets(pObjectInspectorWidgets)
|
2021-03-11 23:26:29 +09:00
|
|
|
, mxContext(comphelper::getProcessComponentContext())
|
2022-05-19 00:33:37 +09:00
|
|
|
, mxSorter(mxContext, Application::GetSettings().GetLanguageTag().getLocale())
|
2021-02-09 17:43:42 +09:00
|
|
|
{
|
2021-03-15 14:56:57 +09:00
|
|
|
mpObjectInspectorWidgets->mpInterfacesTreeView->connect_expanding(
|
2021-02-17 11:49:56 +09:00
|
|
|
LINK(this, ObjectInspectorTreeHandler, ExpandingHandlerInterfaces));
|
2021-03-15 14:56:57 +09:00
|
|
|
mpObjectInspectorWidgets->mpServicesTreeView->connect_expanding(
|
2021-02-17 11:49:56 +09:00
|
|
|
LINK(this, ObjectInspectorTreeHandler, ExpandingHandlerServices));
|
2021-03-15 14:56:57 +09:00
|
|
|
mpObjectInspectorWidgets->mpPropertiesTreeView->connect_expanding(
|
2021-02-17 11:49:56 +09:00
|
|
|
LINK(this, ObjectInspectorTreeHandler, ExpandingHandlerProperties));
|
2021-03-15 14:56:57 +09:00
|
|
|
mpObjectInspectorWidgets->mpMethodsTreeView->connect_expanding(
|
2021-02-17 11:49:56 +09:00
|
|
|
LINK(this, ObjectInspectorTreeHandler, ExpandingHandlerMethods));
|
2021-02-23 22:54:06 +09:00
|
|
|
|
2021-03-15 14:56:57 +09:00
|
|
|
mpObjectInspectorWidgets->mpPropertiesTreeView->connect_popup_menu(
|
2021-02-23 22:54:06 +09:00
|
|
|
LINK(this, ObjectInspectorTreeHandler, PopupMenuHandler));
|
2021-02-25 20:58:42 +09:00
|
|
|
|
2021-03-15 14:56:57 +09:00
|
|
|
mpObjectInspectorWidgets->mpInterfacesTreeView->connect_changed(
|
|
|
|
LINK(this, ObjectInspectorTreeHandler, SelectionChanged));
|
|
|
|
mpObjectInspectorWidgets->mpServicesTreeView->connect_changed(
|
|
|
|
LINK(this, ObjectInspectorTreeHandler, SelectionChanged));
|
|
|
|
mpObjectInspectorWidgets->mpPropertiesTreeView->connect_changed(
|
|
|
|
LINK(this, ObjectInspectorTreeHandler, SelectionChanged));
|
|
|
|
mpObjectInspectorWidgets->mpMethodsTreeView->connect_changed(
|
|
|
|
LINK(this, ObjectInspectorTreeHandler, SelectionChanged));
|
|
|
|
|
|
|
|
mpObjectInspectorWidgets->mpInterfacesTreeView->make_sorted();
|
|
|
|
mpObjectInspectorWidgets->mpServicesTreeView->make_sorted();
|
|
|
|
mpObjectInspectorWidgets->mpPropertiesTreeView->make_sorted();
|
|
|
|
mpObjectInspectorWidgets->mpMethodsTreeView->make_sorted();
|
|
|
|
|
2022-05-19 00:33:37 +09:00
|
|
|
setSortFunction(mpObjectInspectorWidgets->mpInterfacesTreeView);
|
|
|
|
setSortFunction(mpObjectInspectorWidgets->mpServicesTreeView);
|
|
|
|
setSortFunction(mpObjectInspectorWidgets->mpPropertiesTreeView);
|
|
|
|
setSortFunction(mpObjectInspectorWidgets->mpMethodsTreeView);
|
|
|
|
|
2021-05-17 00:08:12 +03:00
|
|
|
mpObjectInspectorWidgets->mpInterfacesTreeView->connect_column_clicked(
|
|
|
|
LINK(this, ObjectInspectorTreeHandler, HeaderBarClick));
|
|
|
|
mpObjectInspectorWidgets->mpServicesTreeView->connect_column_clicked(
|
|
|
|
LINK(this, ObjectInspectorTreeHandler, HeaderBarClick));
|
|
|
|
mpObjectInspectorWidgets->mpPropertiesTreeView->connect_column_clicked(
|
|
|
|
LINK(this, ObjectInspectorTreeHandler, HeaderBarClick));
|
|
|
|
mpObjectInspectorWidgets->mpMethodsTreeView->connect_column_clicked(
|
|
|
|
LINK(this, ObjectInspectorTreeHandler, HeaderBarClick));
|
|
|
|
|
2021-03-15 14:56:57 +09:00
|
|
|
mpObjectInspectorWidgets->mpToolbar->connect_clicked(
|
2021-02-25 20:58:42 +09:00
|
|
|
LINK(this, ObjectInspectorTreeHandler, ToolbarButtonClicked));
|
2024-05-10 13:18:37 +02:00
|
|
|
mpObjectInspectorWidgets->mpToolbar->set_item_sensitive(u"inspect"_ustr, false);
|
|
|
|
mpObjectInspectorWidgets->mpToolbar->set_item_sensitive(u"back"_ustr, false);
|
2021-02-25 21:11:39 +09:00
|
|
|
|
2021-03-15 14:56:57 +09:00
|
|
|
mpObjectInspectorWidgets->mpNotebook->connect_leave_page(
|
2021-02-25 21:11:39 +09:00
|
|
|
LINK(this, ObjectInspectorTreeHandler, NotebookLeavePage));
|
2021-03-15 14:56:57 +09:00
|
|
|
mpObjectInspectorWidgets->mpNotebook->connect_enter_page(
|
2021-02-25 21:11:39 +09:00
|
|
|
LINK(this, ObjectInspectorTreeHandler, NotebookEnterPage));
|
2021-03-15 16:16:05 +09:00
|
|
|
|
2021-05-12 10:09:16 +03:00
|
|
|
auto nPropertiesDigitWidth
|
|
|
|
= mpObjectInspectorWidgets->mpPropertiesTreeView->get_approximate_digit_width();
|
2021-05-14 09:50:31 +02:00
|
|
|
std::vector<int> aPropertiesWidths(4, nPropertiesDigitWidth * 30);
|
2021-05-12 10:09:16 +03:00
|
|
|
mpObjectInspectorWidgets->mpPropertiesTreeView->set_column_fixed_widths(aPropertiesWidths);
|
|
|
|
|
2021-05-14 11:28:17 +02:00
|
|
|
auto nMethodsDigitWidth
|
|
|
|
= mpObjectInspectorWidgets->mpMethodsTreeView->get_approximate_digit_width();
|
|
|
|
std::vector<int> aMethodsWidths{ static_cast<int>(nMethodsDigitWidth * 30),
|
|
|
|
static_cast<int>(nMethodsDigitWidth * 15),
|
|
|
|
static_cast<int>(nMethodsDigitWidth * 30),
|
|
|
|
static_cast<int>(nMethodsDigitWidth * 50) };
|
2021-05-12 10:09:16 +03:00
|
|
|
mpObjectInspectorWidgets->mpMethodsTreeView->set_column_fixed_widths(aMethodsWidths);
|
|
|
|
|
2022-05-19 00:33:37 +09:00
|
|
|
mpObjectInspectorWidgets->mpPaned->set_position(160);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ObjectInspectorTreeHandler::setSortFunction(std::unique_ptr<weld::TreeView>& pTreeView)
|
|
|
|
{
|
|
|
|
pTreeView->set_sort_func(
|
|
|
|
[this, &pTreeView](const weld::TreeIter& rLeft, const weld::TreeIter& rRight) {
|
|
|
|
return compare(pTreeView, rLeft, rRight);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
sal_Int32 ObjectInspectorTreeHandler::compare(std::unique_ptr<weld::TreeView>& pTreeView,
|
|
|
|
const weld::TreeIter& rLeft,
|
|
|
|
const weld::TreeIter& rRight)
|
|
|
|
{
|
|
|
|
int nSortColumn = pTreeView->get_sort_column();
|
|
|
|
|
|
|
|
OUString sLeft = pTreeView->get_text(rLeft, nSortColumn);
|
|
|
|
OUString sRight = pTreeView->get_text(rRight, nSortColumn);
|
|
|
|
sal_Int32 nCompare = mxSorter.compare(sLeft, sRight);
|
|
|
|
return nCompare;
|
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);
|
2022-02-04 09:13:52 +00:00
|
|
|
auto* pNode = weld::fromId<ObjectInspectorNodeInterface*>(sID);
|
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)
|
|
|
|
{
|
2021-03-15 14:56:57 +09:00
|
|
|
handleExpanding(mpObjectInspectorWidgets->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)
|
|
|
|
{
|
2021-03-15 14:56:57 +09:00
|
|
|
handleExpanding(mpObjectInspectorWidgets->mpServicesTreeView, rParent);
|
2021-02-17 11:49:56 +09:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
IMPL_LINK(ObjectInspectorTreeHandler, ExpandingHandlerProperties, weld::TreeIter const&, rParent,
|
|
|
|
bool)
|
|
|
|
{
|
2021-03-15 14:56:57 +09:00
|
|
|
handleExpanding(mpObjectInspectorWidgets->mpPropertiesTreeView, rParent);
|
2021-02-17 11:49:56 +09:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
IMPL_LINK(ObjectInspectorTreeHandler, ExpandingHandlerMethods, weld::TreeIter const&, rParent, bool)
|
|
|
|
{
|
2021-03-15 14:56:57 +09:00
|
|
|
handleExpanding(mpObjectInspectorWidgets->mpMethodsTreeView, rParent);
|
2021-02-17 11:49:56 +09:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2021-02-25 20:58:42 +09:00
|
|
|
IMPL_LINK(ObjectInspectorTreeHandler, SelectionChanged, weld::TreeView&, rTreeView, void)
|
|
|
|
{
|
|
|
|
bool bHaveNodeWithObject = false;
|
2024-05-10 13:18:37 +02:00
|
|
|
mpObjectInspectorWidgets->mpTextView->set_text(u""_ustr);
|
2021-03-15 14:56:57 +09:00
|
|
|
if (mpObjectInspectorWidgets->mpPropertiesTreeView.get() == &rTreeView)
|
2021-02-25 20:58:42 +09:00
|
|
|
{
|
|
|
|
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();
|
2021-03-15 23:41:33 +09:00
|
|
|
mpObjectInspectorWidgets->mpTextView->set_text(convertAnyToString(aAny, mxContext));
|
2021-02-25 20:58:42 +09:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-05-10 13:18:37 +02:00
|
|
|
mpObjectInspectorWidgets->mpToolbar->set_item_sensitive(u"inspect"_ustr, bHaveNodeWithObject);
|
2021-02-25 20:58:42 +09:00
|
|
|
}
|
|
|
|
|
2021-08-18 18:31:05 +02:00
|
|
|
static void updateOrder(const std::unique_ptr<weld::TreeView>& pTreeView, sal_Int32 nColumn)
|
2021-05-17 00:08:12 +03:00
|
|
|
{
|
|
|
|
pTreeView->set_sort_column(nColumn);
|
|
|
|
|
|
|
|
bool bSortAtoZ = pTreeView->get_sort_order();
|
|
|
|
pTreeView->set_sort_order(!bSortAtoZ);
|
|
|
|
pTreeView->set_sort_indicator(!bSortAtoZ ? TRISTATE_TRUE : TRISTATE_FALSE, nColumn);
|
|
|
|
}
|
|
|
|
|
|
|
|
IMPL_LINK(ObjectInspectorTreeHandler, HeaderBarClick, int, nColumn, void)
|
|
|
|
{
|
|
|
|
auto rPageId = mpObjectInspectorWidgets->mpNotebook->get_current_page_ident();
|
|
|
|
|
|
|
|
if (rPageId == "object_inspector_interfaces_tab")
|
|
|
|
updateOrder(mpObjectInspectorWidgets->mpInterfacesTreeView, nColumn);
|
|
|
|
else if (rPageId == "object_inspector_services_tab")
|
|
|
|
updateOrder(mpObjectInspectorWidgets->mpServicesTreeView, nColumn);
|
|
|
|
else if (rPageId == "object_inspector_properties_tab")
|
|
|
|
updateOrder(mpObjectInspectorWidgets->mpPropertiesTreeView, nColumn);
|
|
|
|
else if (rPageId == "object_inspector_methods_tab")
|
|
|
|
updateOrder(mpObjectInspectorWidgets->mpMethodsTreeView, nColumn);
|
|
|
|
}
|
|
|
|
|
2021-02-23 22:54:06 +09:00
|
|
|
IMPL_LINK(ObjectInspectorTreeHandler, PopupMenuHandler, const CommandEvent&, rCommandEvent, bool)
|
|
|
|
{
|
|
|
|
if (rCommandEvent.GetCommand() != CommandEventId::ContextMenu)
|
|
|
|
return false;
|
|
|
|
|
2021-03-15 14:56:57 +09:00
|
|
|
auto xInterface = getSelectedXInterface(*mpObjectInspectorWidgets->mpPropertiesTreeView);
|
2021-02-25 20:58:42 +09:00
|
|
|
if (xInterface.is())
|
|
|
|
{
|
2021-03-15 14:56:57 +09:00
|
|
|
std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(
|
2024-05-10 13:18:37 +02:00
|
|
|
mpObjectInspectorWidgets->mpPropertiesTreeView.get(), u"sfx/ui/devtoolsmenu.ui"_ustr));
|
|
|
|
std::unique_ptr<weld::Menu> xMenu(xBuilder->weld_menu(u"inspect_menu"_ustr));
|
2021-02-23 22:54:06 +09:00
|
|
|
|
2023-04-02 01:18:42 +03:00
|
|
|
OUString sCommand(
|
2021-03-15 14:56:57 +09:00
|
|
|
xMenu->popup_at_rect(mpObjectInspectorWidgets->mpPropertiesTreeView.get(),
|
2021-02-25 20:58:42 +09:00
|
|
|
tools::Rectangle(rCommandEvent.GetMousePosPixel(), Size(1, 1))));
|
|
|
|
|
|
|
|
if (sCommand == "inspect")
|
|
|
|
{
|
|
|
|
addToStack(uno::Any(xInterface));
|
|
|
|
inspectObject(xInterface);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2023-04-02 01:18:42 +03:00
|
|
|
IMPL_LINK(ObjectInspectorTreeHandler, ToolbarButtonClicked, const OUString&, rSelectionId, void)
|
2021-02-25 20:58:42 +09:00
|
|
|
{
|
|
|
|
if (rSelectionId == "inspect")
|
2021-02-23 22:54:06 +09:00
|
|
|
{
|
2021-03-15 14:56:57 +09:00
|
|
|
auto xInterface = getSelectedXInterface(*mpObjectInspectorWidgets->mpPropertiesTreeView);
|
2021-02-25 20:58:42 +09:00
|
|
|
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")
|
|
|
|
{
|
2021-03-15 14:56:57 +09:00
|
|
|
auto rPageId = mpObjectInspectorWidgets->mpNotebook->get_current_page_ident();
|
2021-03-04 15:30:19 +09:00
|
|
|
NotebookEnterPage(rPageId);
|
|
|
|
}
|
2021-02-23 22:54:06 +09:00
|
|
|
}
|
|
|
|
|
2023-04-02 01:18:42 +03:00
|
|
|
IMPL_LINK(ObjectInspectorTreeHandler, NotebookEnterPage, const OUString&, rPageId, void)
|
2021-02-25 21:11:39 +09:00
|
|
|
{
|
|
|
|
uno::Any aAny = maInspectionStack.back();
|
2021-03-26 13:35:54 +02:00
|
|
|
if (!aAny.hasValue())
|
|
|
|
return;
|
|
|
|
|
|
|
|
uno::Reference<uno::XInterface> xInterface(aAny, uno::UNO_QUERY);
|
|
|
|
if (rPageId == "object_inspector_interfaces_tab")
|
2021-02-25 21:11:39 +09:00
|
|
|
{
|
2021-03-26 13:35:54 +02:00
|
|
|
mpObjectInspectorWidgets->mpInterfacesTreeView->freeze();
|
|
|
|
clearAll(mpObjectInspectorWidgets->mpInterfacesTreeView);
|
|
|
|
appendInterfaces(xInterface);
|
|
|
|
mpObjectInspectorWidgets->mpInterfacesTreeView->thaw();
|
|
|
|
}
|
|
|
|
else if (rPageId == "object_inspector_services_tab")
|
|
|
|
{
|
|
|
|
mpObjectInspectorWidgets->mpServicesTreeView->freeze();
|
|
|
|
clearAll(mpObjectInspectorWidgets->mpServicesTreeView);
|
|
|
|
appendServices(xInterface);
|
|
|
|
mpObjectInspectorWidgets->mpServicesTreeView->thaw();
|
|
|
|
}
|
|
|
|
else if (rPageId == "object_inspector_properties_tab")
|
|
|
|
{
|
|
|
|
mpObjectInspectorWidgets->mpPropertiesTreeView->freeze();
|
|
|
|
clearAll(mpObjectInspectorWidgets->mpPropertiesTreeView);
|
|
|
|
appendProperties(xInterface);
|
|
|
|
mpObjectInspectorWidgets->mpPropertiesTreeView->thaw();
|
|
|
|
}
|
|
|
|
else if (rPageId == "object_inspector_methods_tab")
|
|
|
|
{
|
|
|
|
mpObjectInspectorWidgets->mpMethodsTreeView->freeze();
|
|
|
|
clearAll(mpObjectInspectorWidgets->mpMethodsTreeView);
|
|
|
|
appendMethods(xInterface);
|
|
|
|
mpObjectInspectorWidgets->mpMethodsTreeView->thaw();
|
2021-02-25 21:11:39 +09:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-04-02 01:18:42 +03:00
|
|
|
IMPL_LINK(ObjectInspectorTreeHandler, NotebookLeavePage, const OUString&, rPageId, bool)
|
2021-02-25 21:11:39 +09:00
|
|
|
{
|
|
|
|
if (rPageId == "object_inspector_interfaces_tab")
|
|
|
|
{
|
2021-03-15 14:56:57 +09:00
|
|
|
mpObjectInspectorWidgets->mpInterfacesTreeView->freeze();
|
|
|
|
clearAll(mpObjectInspectorWidgets->mpInterfacesTreeView);
|
|
|
|
mpObjectInspectorWidgets->mpInterfacesTreeView->thaw();
|
2021-02-25 21:11:39 +09:00
|
|
|
}
|
|
|
|
else if (rPageId == "object_inspector_services_tab")
|
|
|
|
{
|
2021-03-15 14:56:57 +09:00
|
|
|
mpObjectInspectorWidgets->mpServicesTreeView->freeze();
|
|
|
|
clearAll(mpObjectInspectorWidgets->mpServicesTreeView);
|
|
|
|
mpObjectInspectorWidgets->mpServicesTreeView->thaw();
|
2021-02-25 21:11:39 +09:00
|
|
|
}
|
|
|
|
else if (rPageId == "object_inspector_properties_tab")
|
|
|
|
{
|
2021-03-15 14:56:57 +09:00
|
|
|
mpObjectInspectorWidgets->mpPropertiesTreeView->freeze();
|
|
|
|
clearAll(mpObjectInspectorWidgets->mpPropertiesTreeView);
|
|
|
|
mpObjectInspectorWidgets->mpPropertiesTreeView->thaw();
|
2021-02-25 21:11:39 +09:00
|
|
|
}
|
|
|
|
else if (rPageId == "object_inspector_methods_tab")
|
|
|
|
{
|
2021-03-15 14:56:57 +09:00
|
|
|
mpObjectInspectorWidgets->mpMethodsTreeView->freeze();
|
|
|
|
clearAll(mpObjectInspectorWidgets->mpMethodsTreeView);
|
|
|
|
mpObjectInspectorWidgets->mpMethodsTreeView->thaw();
|
2021-02-25 21:11:39 +09:00
|
|
|
}
|
|
|
|
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);
|
2022-02-04 09:13:52 +00:00
|
|
|
auto* pEntry = weld::fromId<ObjectInspectorNodeInterface*>(sID);
|
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-03-12 19:27:11 +09:00
|
|
|
/** Deletes all the node objects in a tree view */
|
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);
|
2022-02-04 09:13:52 +00:00
|
|
|
auto* pEntry = weld::fromId<ObjectInspectorNodeInterface*>(sID);
|
2021-02-17 11:49:56 +09:00
|
|
|
delete pEntry;
|
|
|
|
return false;
|
|
|
|
});
|
|
|
|
pTreeView->clear();
|
|
|
|
}
|
|
|
|
|
2021-03-12 19:27:11 +09:00
|
|
|
/** Append interfaces to the "interfaces" tree view */
|
2021-02-17 11:49:56 +09:00
|
|
|
void ObjectInspectorTreeHandler::appendInterfaces(uno::Reference<uno::XInterface> const& xInterface)
|
|
|
|
{
|
|
|
|
if (!xInterface.is())
|
|
|
|
return;
|
2021-03-11 23:26:29 +09:00
|
|
|
|
2021-02-17 11:49:56 +09:00
|
|
|
uno::Reference<lang::XTypeProvider> xTypeProvider(xInterface, uno::UNO_QUERY);
|
|
|
|
if (xTypeProvider.is())
|
|
|
|
{
|
|
|
|
const auto xSequenceTypes = xTypeProvider->getTypes();
|
|
|
|
for (auto const& xType : xSequenceTypes)
|
|
|
|
{
|
2021-03-11 23:26:29 +09:00
|
|
|
auto xClass = convertTypeToIdlClass(xType, mxContext);
|
2021-03-15 14:56:57 +09:00
|
|
|
lclAppendNode(mpObjectInspectorWidgets->mpInterfacesTreeView, new ClassNode(xClass));
|
2021-02-17 11:49:56 +09:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-12 19:27:11 +09:00
|
|
|
/** Append services to the "services" tree view */
|
2021-02-17 11:49:56 +09:00
|
|
|
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)
|
|
|
|
{
|
2021-03-15 14:56:57 +09:00
|
|
|
lclAppendNode(mpObjectInspectorWidgets->mpServicesTreeView,
|
|
|
|
new SimpleStringNode(aServiceName));
|
2021-02-17 11:49:56 +09:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-12 19:27:11 +09:00
|
|
|
/** Append properties to the "properties" tree view */
|
2021-02-17 11:49:56 +09:00
|
|
|
void ObjectInspectorTreeHandler::appendProperties(uno::Reference<uno::XInterface> const& xInterface)
|
|
|
|
{
|
|
|
|
if (!xInterface.is())
|
|
|
|
return;
|
2024-05-10 13:18:37 +02:00
|
|
|
GenericPropertiesNode aNode(u""_ustr, uno::Any(xInterface), u""_ustr, mxContext);
|
2021-03-15 14:56:57 +09:00
|
|
|
aNode.fillChildren(mpObjectInspectorWidgets->mpPropertiesTreeView, nullptr);
|
2021-02-17 11:49:56 +09:00
|
|
|
}
|
|
|
|
|
2021-03-12 19:27:11 +09:00
|
|
|
/** Append methods to the "methods" tree view */
|
2021-02-17 11:49:56 +09:00
|
|
|
void ObjectInspectorTreeHandler::appendMethods(uno::Reference<uno::XInterface> const& xInterface)
|
|
|
|
{
|
|
|
|
if (!xInterface.is())
|
|
|
|
return;
|
|
|
|
|
2021-03-11 23:26:29 +09:00
|
|
|
uno::Reference<beans::XIntrospection> xIntrospection = beans::theIntrospection::get(mxContext);
|
2021-02-17 11:49:56 +09:00
|
|
|
auto xIntrospectionAccess = xIntrospection->inspect(uno::Any(xInterface));
|
|
|
|
|
|
|
|
const auto xMethods = xIntrospectionAccess->getMethods(beans::MethodConcept::ALL);
|
|
|
|
for (auto const& xMethod : xMethods)
|
|
|
|
{
|
2021-03-15 14:56:57 +09:00
|
|
|
lclAppendNode(mpObjectInspectorWidgets->mpMethodsTreeView, new MethodNode(xMethod));
|
2021-02-17 11:49:56 +09:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-17 20:37:26 +09:00
|
|
|
// Update the back button state depending if there are objects in the stack
|
2021-02-25 20:58:42 +09:00
|
|
|
void ObjectInspectorTreeHandler::updateBackButtonState()
|
|
|
|
{
|
2024-05-10 13:18:37 +02:00
|
|
|
mpObjectInspectorWidgets->mpToolbar->set_item_sensitive(u"back"_ustr,
|
|
|
|
maInspectionStack.size() > 1);
|
2021-02-25 20:58:42 +09:00
|
|
|
}
|
|
|
|
|
2021-03-12 19:27:11 +09:00
|
|
|
// Clears all the objects from the stack
|
2021-02-25 20:58:42 +09:00
|
|
|
void ObjectInspectorTreeHandler::clearStack()
|
|
|
|
{
|
|
|
|
maInspectionStack.clear();
|
|
|
|
updateBackButtonState();
|
|
|
|
}
|
|
|
|
|
2021-03-12 19:27:11 +09:00
|
|
|
// Adds an object to the stack
|
2021-02-25 20:58:42 +09:00
|
|
|
void ObjectInspectorTreeHandler::addToStack(css::uno::Any const& rAny)
|
|
|
|
{
|
|
|
|
maInspectionStack.push_back(rAny);
|
|
|
|
updateBackButtonState();
|
|
|
|
}
|
|
|
|
|
2021-03-12 19:27:11 +09:00
|
|
|
// Removes an object from the back of the stack and return it
|
2021-02-25 20:58:42 +09:00
|
|
|
css::uno::Any ObjectInspectorTreeHandler::popFromStack()
|
|
|
|
{
|
|
|
|
maInspectionStack.pop_back();
|
|
|
|
uno::Any aAny = maInspectionStack.back();
|
|
|
|
updateBackButtonState();
|
|
|
|
return aAny;
|
|
|
|
}
|
|
|
|
|
2021-03-12 19:27:11 +09:00
|
|
|
// Inspect the input object in the object inspector
|
2021-02-25 20:58:42 +09:00
|
|
|
void ObjectInspectorTreeHandler::inspectObject(uno::Reference<uno::XInterface> const& xInterface)
|
2021-02-08 22:41:36 +09:00
|
|
|
{
|
|
|
|
if (!xInterface.is())
|
|
|
|
return;
|
|
|
|
|
|
|
|
// Set implementation name
|
2021-03-15 23:41:33 +09:00
|
|
|
OUString aImplementationName = getInterfaceImplementationClass(xInterface);
|
2021-03-15 14:56:57 +09:00
|
|
|
mpObjectInspectorWidgets->mpClassNameLabel->set_label(aImplementationName);
|
2021-06-28 23:55:42 +03:00
|
|
|
sal_Int32 nStrLen = aImplementationName.getLength();
|
|
|
|
sal_Int32 nDigitWidth
|
|
|
|
= mpObjectInspectorWidgets->mpClassNameLabel->get_approximate_digit_width();
|
|
|
|
|
|
|
|
//get_about_digit_width() returns an approximate value. To always see the full class name (nStrLen+2)
|
|
|
|
mpObjectInspectorWidgets->mpClassNameLabel->set_size_request((nStrLen + 2) * nDigitWidth, -1);
|
2021-02-08 22:41:36 +09:00
|
|
|
|
2021-03-12 19:27:11 +09:00
|
|
|
// Fire entering the current opened page manually
|
2021-03-15 14:56:57 +09:00
|
|
|
auto rPageId = mpObjectInspectorWidgets->mpNotebook->get_current_page_ident();
|
2021-02-25 21:11:39 +09:00
|
|
|
NotebookEnterPage(rPageId);
|
2021-02-08 22:41:36 +09:00
|
|
|
}
|
|
|
|
|
2021-03-12 19:27:11 +09:00
|
|
|
// Inspect the input object in the object inspector.
|
|
|
|
// Make the input object the root of the stack (clear all other
|
|
|
|
// objects from the stack).
|
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-03-12 19:27:11 +09:00
|
|
|
// We need to clear all the nodes
|
2021-03-15 14:56:57 +09:00
|
|
|
clearAll(mpObjectInspectorWidgets->mpInterfacesTreeView);
|
|
|
|
clearAll(mpObjectInspectorWidgets->mpServicesTreeView);
|
|
|
|
clearAll(mpObjectInspectorWidgets->mpPropertiesTreeView);
|
|
|
|
clearAll(mpObjectInspectorWidgets->mpMethodsTreeView);
|
2021-02-08 22:41:36 +09:00
|
|
|
}
|
|
|
|
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|