1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
13 #include <sfx2/devtools/ObjectInspectorTreeHandler.hxx>
14 #include <sfx2/sfxresid.hxx>
16 #include <vcl/svapp.hxx>
17 #include "DevToolsStrings.hrc"
19 #include <com/sun/star/beans/theIntrospection.hpp>
20 #include <com/sun/star/beans/XIntrospection.hpp>
21 #include <com/sun/star/beans/XIntrospectionAccess.hpp>
22 #include <com/sun/star/beans/PropertyConcept.hpp>
23 #include <com/sun/star/beans/PropertyAttribute.hpp>
24 #include <com/sun/star/beans/MethodConcept.hpp>
26 #include <com/sun/star/reflection/theCoreReflection.hpp>
27 #include <com/sun/star/reflection/XIdlReflection.hpp>
28 #include <com/sun/star/reflection/XIdlMethod.hpp>
29 #include <com/sun/star/reflection/XIdlArray.hpp>
30 #include <com/sun/star/reflection/XEnumTypeDescription.hpp>
32 #include <com/sun/star/container/XNamed.hpp>
33 #include <com/sun/star/container/XHierarchicalNameAccess.hpp>
34 #include <com/sun/star/container/XIndexAccess.hpp>
35 #include <com/sun/star/container/XNameAccess.hpp>
36 #include <com/sun/star/container/XEnumerationAccess.hpp>
38 #include <com/sun/star/script/Invocation.hpp>
39 #include <com/sun/star/script/XInvocation2.hpp>
40 #include <com/sun/star/script/MemberType.hpp>
42 #include <com/sun/star/lang/XServiceInfo.hpp>
43 #include <com/sun/star/lang/XTypeProvider.hpp>
45 #include <comphelper/processfactory.hxx>
46 #include <comphelper/extract.hxx>
48 #include <vcl/settings.hxx>
49 #include <i18nlangtag/languagetag.hxx>
55 constexpr OUStringLiteral constTypeDescriptionManagerSingletonName
56 = u
"/singletons/com.sun.star.reflection.theTypeDescriptionManager";
58 OUString
enumValueToEnumName(uno::Any
const& aValue
,
59 uno::Reference
<uno::XComponentContext
> const& xContext
)
61 sal_Int32 nIntValue
= 0;
62 if (!cppu::enum2int(nIntValue
, aValue
))
65 uno::Reference
<container::XHierarchicalNameAccess
> xManager
;
66 xManager
.set(xContext
->getValueByName(constTypeDescriptionManagerSingletonName
),
69 uno::Reference
<reflection::XEnumTypeDescription
> xTypeDescription
;
70 xTypeDescription
.set(xManager
->getByHierarchicalName(aValue
.getValueTypeName()),
73 const uno::Sequence
<sal_Int32
> aValues
= xTypeDescription
->getEnumValues();
74 sal_Int32 nValuesIndex
= std::find(aValues
.begin(), aValues
.end(), nIntValue
) - aValues
.begin();
75 uno::Sequence
<OUString
> aNames
= xTypeDescription
->getEnumNames();
76 return aNames
[nValuesIndex
];
79 OUString
getInterfaceImplementationClass(uno::Reference
<uno::XInterface
> const& xInterface
)
81 auto xServiceInfo
= uno::Reference
<lang::XServiceInfo
>(xInterface
, uno::UNO_QUERY
);
82 if (xServiceInfo
.is())
83 return xServiceInfo
->getImplementationName();
87 /** converts basic any value to a string */
88 OUString
convertBasicValueToString(const uno::Any
& aValue
,
89 const uno::Reference
<uno::XComponentContext
>& xContext
)
93 // return early if we don't have any value
94 if (!aValue
.hasValue())
95 return SfxResId(STR_ANY_VALUE_NULL
);
97 uno::TypeClass eType
= aValue
.getValueTypeClass();
101 case uno::TypeClass_BOOLEAN
:
103 bool bBool
= aValue
.get
<bool>();
104 aRetStr
= bBool
? SfxResId(STR_ANY_VALUE_TRUE
) : SfxResId(STR_ANY_VALUE_FALSE
);
107 case uno::TypeClass_CHAR
:
109 sal_Unicode aChar
= aValue
.get
<sal_Unicode
>();
110 aRetStr
= OUString::number(aChar
);
113 case uno::TypeClass_STRING
:
115 aRetStr
= u
"\"" + aValue
.get
<OUString
>() + u
"\"";
118 case uno::TypeClass_FLOAT
:
120 auto aNumber
= aValue
.get
<float>();
121 aRetStr
= OUString::number(aNumber
);
124 case uno::TypeClass_DOUBLE
:
126 auto aNumber
= aValue
.get
<double>();
127 aRetStr
= OUString::number(aNumber
);
130 case uno::TypeClass_BYTE
:
132 auto aNumber
= aValue
.get
<sal_Int8
>();
133 aRetStr
= OUString::number(aNumber
);
136 case uno::TypeClass_SHORT
:
138 auto aNumber
= aValue
.get
<sal_Int16
>();
139 aRetStr
= OUString::number(aNumber
);
142 case uno::TypeClass_LONG
:
144 auto aNumber
= aValue
.get
<sal_Int32
>();
145 aRetStr
= OUString::number(aNumber
);
148 case uno::TypeClass_HYPER
:
150 auto aNumber
= aValue
.get
<sal_Int64
>();
151 aRetStr
= OUString::number(aNumber
);
154 case uno::TypeClass_UNSIGNED_SHORT
:
156 auto aNumber
= aValue
.get
<sal_uInt16
>();
157 aRetStr
= OUString::number(aNumber
);
160 case uno::TypeClass_UNSIGNED_LONG
:
162 auto aNumber
= aValue
.get
<sal_uInt32
>();
163 aRetStr
= OUString::number(aNumber
);
166 case uno::TypeClass_UNSIGNED_HYPER
:
168 auto aNumber
= aValue
.get
<sal_uInt64
>();
169 aRetStr
= OUString::number(aNumber
);
172 case uno::TypeClass_TYPE
:
174 auto aType
= aValue
.get
<uno::Type
>();
175 aRetStr
= aType
.getTypeName();
178 case uno::TypeClass_ENUM
:
180 aRetStr
= enumValueToEnumName(aValue
, xContext
);
190 // returns a name of the object, if available
191 OUString
getInterfaceName(uno::Reference
<uno::XInterface
> const& xInterface
,
192 const uno::Reference
<uno::XComponentContext
>& xContext
)
194 uno::Reference
<container::XNamed
> xNamed(xInterface
, uno::UNO_QUERY
);
196 return xNamed
->getName();
198 auto xInvocationFactory
= css::script::Invocation::create(xContext
);
199 uno::Sequence
<uno::Any
> aParameters
= { uno::Any(xInterface
) };
200 auto xInvocationInterface
= xInvocationFactory
->createInstanceWithArguments(aParameters
);
201 if (xInvocationInterface
.is())
203 uno::Reference
<script::XInvocation2
> xInvocation(xInvocationInterface
, uno::UNO_QUERY
);
204 if (xInvocation
.is() && xInvocation
->hasProperty(u
"Name"_ustr
))
206 uno::Any aAny
= xInvocation
->getValue(u
"Name"_ustr
);
207 if (aAny
.hasValue() && aAny
.getValueTypeClass() == uno::TypeClass_STRING
)
208 return aAny
.get
<OUString
>();
214 OUString
convertAnyToString(const uno::Any
& aValue
,
215 const uno::Reference
<uno::XComponentContext
>& xContext
)
217 // return early if we don't have any value
218 if (!aValue
.hasValue())
219 return SfxResId(STR_ANY_VALUE_NULL
);
223 uno::TypeClass eType
= aValue
.getValueTypeClass();
227 case uno::TypeClass_INTERFACE
:
229 uno::Reference
<uno::XInterface
> xInterface(aValue
, uno::UNO_QUERY
);
230 if (!xInterface
.is())
231 aRetStr
= SfxResId(STR_ANY_VALUE_NULL
);
234 OUString aImplementationClass
= getInterfaceImplementationClass(xInterface
);
235 if (aImplementationClass
.isEmpty())
236 aImplementationClass
= SfxResId(STR_CLASS_UNKNOWN
);
238 = SfxResId(STR_PROPERTY_VALUE_OBJECT
).replaceFirst("%1", aImplementationClass
);
240 OUString aString
= getInterfaceName(xInterface
, xContext
);
241 if (!aString
.isEmpty())
242 aRetStr
+= " {" + aString
+ "}";
246 case uno::TypeClass_STRUCT
:
248 aRetStr
= SfxResId(STR_PROPERTY_VALUE_STRUCT
);
253 aRetStr
= convertBasicValueToString(aValue
, xContext
);
260 OUString
convertAnyToShortenedString(const uno::Any
& aValue
,
261 const uno::Reference
<uno::XComponentContext
>& xContext
)
263 // return early if we don't have any value
264 if (!aValue
.hasValue())
265 return SfxResId(STR_ANY_VALUE_NULL
);
269 uno::TypeClass eType
= aValue
.getValueTypeClass();
271 constexpr const sal_Int32 constMaxStringLength
= 60;
275 case uno::TypeClass_INTERFACE
:
277 aRetStr
= convertAnyToString(aValue
, xContext
);
279 if (aRetStr
.getLength() > constMaxStringLength
+ 3)
280 aRetStr
= OUString::Concat(aRetStr
.subView(0, constMaxStringLength
)) + u
"...";
283 case uno::TypeClass_STRING
:
285 OUString aString
= convertAnyToString(aValue
, xContext
);
286 if (aString
.getLength() > constMaxStringLength
+ 4)
287 aString
= OUString::Concat(aString
.subView(0, constMaxStringLength
)) + u
"\"...";
288 aRetStr
= aString
.replaceAll("\n", " ");
293 aRetStr
= convertAnyToString(aValue
, xContext
);
300 /** converts an any's type to a string (in a short form) */
301 OUString
getAnyType(const uno::Any
& aValue
)
303 OUString aTypeName
= aValue
.getValueTypeName();
304 return aTypeName
.replaceAll("com.sun.star", "css");
307 /** converts a Type to a XIdlClass */
308 uno::Reference
<reflection::XIdlClass
>
309 convertTypeToIdlClass(const uno::Type
& rType
,
310 const uno::Reference
<uno::XComponentContext
>& xContext
)
312 auto xReflection
= reflection::theCoreReflection::get(xContext
);
313 return xReflection
->forName(rType
.getTypeName());
316 // Object inspector nodes
318 /** Object inspector node's main interface
320 * The interface for the "attached" object to a tree view nodes that
321 * are added to the tree views of the object inspector part. The node
322 * can return the main value of the node (object name) and if present
323 * also the values for additional columns. It signals if a tree needs
324 * an expander and fills the children of the tree is any exists.
327 class ObjectInspectorNodeInterface
330 ObjectInspectorNodeInterface() = default;
332 virtual ~ObjectInspectorNodeInterface() {}
334 // main value (object name) of the tree view node
335 virtual OUString
getObjectName() = 0;
337 // should show the expander for the tree view node
338 virtual bool shouldShowExpander() { return false; }
340 // fill the children for the current tree view node
341 virtual void fillChildren(std::unique_ptr
<weld::TreeView
>& rTree
, const weld::TreeIter
* pParent
)
344 // fill any additional column values for the current tree view node
345 virtual std::vector
<std::pair
<sal_Int32
, OUString
>> getColumnValues()
347 return std::vector
<std::pair
<sal_Int32
, OUString
>>();
351 // appends the node to the root of the tree view
352 void lclAppendNode(const std::unique_ptr
<weld::TreeView
>& pTree
,
353 ObjectInspectorNodeInterface
* pEntry
)
355 OUString sName
= pEntry
->getObjectName();
356 OUString
sId(weld::toId(pEntry
));
357 std::unique_ptr
<weld::TreeIter
> pCurrent
= pTree
->make_iterator();
358 pTree
->insert(nullptr, -1, &sName
, &sId
, nullptr, nullptr, pEntry
->shouldShowExpander(),
360 pTree
->set_text_emphasis(*pCurrent
, true, 0);
362 for (auto const& rPair
: pEntry
->getColumnValues())
364 pTree
->set_text(*pCurrent
, rPair
.second
, rPair
.first
);
368 // appends the node to the parent
369 void lclAppendNodeToParent(const std::unique_ptr
<weld::TreeView
>& pTree
,
370 const weld::TreeIter
* pParent
, ObjectInspectorNodeInterface
* pEntry
)
372 OUString sName
= pEntry
->getObjectName();
373 OUString
sId(weld::toId(pEntry
));
374 std::unique_ptr
<weld::TreeIter
> pCurrent
= pTree
->make_iterator();
375 pTree
->insert(pParent
, -1, &sName
, &sId
, nullptr, nullptr, pEntry
->shouldShowExpander(),
377 pTree
->set_text_emphasis(*pCurrent
, true, 0);
379 for (auto const& rPair
: pEntry
->getColumnValues())
381 pTree
->set_text(*pCurrent
, rPair
.second
, rPair
.first
);
385 /** Node that represent just a simple string with no children or columns */
386 class SimpleStringNode
: public ObjectInspectorNodeInterface
392 SimpleStringNode(OUString sName
)
393 : msName(std::move(sName
))
397 void fillChildren(std::unique_ptr
<weld::TreeView
>& /*rTree*/,
398 const weld::TreeIter
* /*pParent*/) override
402 OUString
getObjectName() override
{ return msName
; }
405 /** Node represents a method of an object */
406 class MethodNode
: public ObjectInspectorNodeInterface
409 uno::Reference
<reflection::XIdlMethod
> mxMethod
;
412 MethodNode(uno::Reference
<reflection::XIdlMethod
> xMethod
)
413 : mxMethod(std::move(xMethod
))
417 OUString
getObjectName() override
{ return mxMethod
->getName(); }
419 static OUString
simpleTypeName(uno::Reference
<reflection::XIdlClass
> const& xClass
)
421 switch (xClass
->getTypeClass())
423 case uno::TypeClass_INTERFACE
:
424 return SfxResId(STR_METHOD_TYPE_OBJECT
);
425 case uno::TypeClass_STRUCT
:
426 return SfxResId(STR_METHOD_TYPE_STRUCT
);
427 case uno::TypeClass_ENUM
:
428 return SfxResId(STR_METHOD_TYPE_ENUM
);
429 case uno::TypeClass_SEQUENCE
:
430 return SfxResId(STR_METHOD_TYPE_SEQUENCE
);
434 return xClass
->getName();
437 std::vector
<std::pair
<sal_Int32
, OUString
>> getColumnValues() override
440 auto xClass
= mxMethod
->getReturnType();
441 aOutString
= simpleTypeName(xClass
);
444 const auto aParameters
= mxMethod
->getParameterInfos();
446 for (auto const& rParameterInfo
: aParameters
)
453 switch (rParameterInfo
.aMode
)
455 case reflection::ParamMode_IN
:
456 aInString
+= SfxResId(STR_PARMETER_MODE_IN
) + " ";
458 case reflection::ParamMode_OUT
:
459 aInString
+= SfxResId(STR_PARMETER_MODE_OUT
) + " ";
461 case reflection::ParamMode_INOUT
:
462 aInString
+= SfxResId(STR_PARMETER_MODE_IN_AND_OUT
) + " ";
468 aInString
+= rParameterInfo
.aName
+ " : " + simpleTypeName(rParameterInfo
.aType
);
471 OUString aImplementationClass
= mxMethod
->getDeclaringClass()->getName();
476 { 3, aImplementationClass
},
480 void fillChildren(std::unique_ptr
<weld::TreeView
>& /*rTree*/,
481 const weld::TreeIter
* /*pParent*/) override
486 /** Node represents a class (XIdlClass) of an object.
488 * Children are superclasses of the current class. XInterface superclass
492 class ClassNode
: public ObjectInspectorNodeInterface
495 uno::Reference
<reflection::XIdlClass
> mxClass
;
497 static bool isXInterface(uno::Reference
<reflection::XIdlClass
> const& xClass
)
499 return xClass
->getName() == "com.sun.star.uno.XInterface";
503 ClassNode(uno::Reference
<reflection::XIdlClass
> xClass
)
504 : mxClass(std::move(xClass
))
508 bool shouldShowExpander() override
510 auto const xSuperClasses
= mxClass
->getSuperclasses();
511 return xSuperClasses
.getLength() > 2
512 || (xSuperClasses
.getLength() == 1 && !isXInterface(xSuperClasses
[0]));
515 OUString
getObjectName() override
{ return mxClass
->getName(); }
518 void fillChildren(std::unique_ptr
<weld::TreeView
>& rTree
,
519 const weld::TreeIter
* pParent
) override
521 auto const xSuperClasses
= mxClass
->getSuperclasses();
522 for (auto const& xSuper
: xSuperClasses
)
524 if (!isXInterface(xSuper
))
525 lclAppendNodeToParent(rTree
, pParent
, new ClassNode(xSuper
));
530 /** Node represents a basic value, that can be any object, sequence, struct */
531 class BasicValueNode
: public SimpleStringNode
536 uno::Reference
<uno::XComponentContext
> mxContext
;
538 ObjectInspectorNodeInterface
*
539 createNodeObjectForAny(OUString
const& rName
, const uno::Any
& rAny
, OUString
const& mrInfo
);
542 BasicValueNode(OUString
const& rName
, uno::Any aAny
, OUString aInfo
,
543 uno::Reference
<uno::XComponentContext
> xContext
)
544 : SimpleStringNode(rName
)
545 , maAny(std::move(aAny
))
546 , mrInfo(std::move(aInfo
))
547 , mxContext(std::move(xContext
))
551 const uno::Any
& getAny() const { return maAny
; }
553 bool shouldShowExpander() override
555 if (maAny
.hasValue())
557 switch (maAny
.getValueTypeClass())
559 case uno::TypeClass_INTERFACE
:
561 uno::Reference
<uno::XInterface
> xInterface(maAny
, uno::UNO_QUERY
);
562 return xInterface
.is();
564 case uno::TypeClass_SEQUENCE
:
573 std::vector
<std::pair
<sal_Int32
, OUString
>> getColumnValues() override
575 OUString aValue
= convertAnyToShortenedString(maAny
, mxContext
);
576 OUString aType
= getAnyType(maAny
);
578 return { { 1, aValue
}, { 2, aType
}, { 3, mrInfo
} };
582 /** Node represents a property */
583 class GenericPropertiesNode
: public BasicValueNode
586 GenericPropertiesNode(OUString
const& rName
, uno::Any
const& rAny
, OUString
const& rInfo
,
587 uno::Reference
<uno::XComponentContext
> const& xContext
)
588 : BasicValueNode(rName
, rAny
, rInfo
, xContext
)
592 void fillChildren(std::unique_ptr
<weld::TreeView
>& pTree
,
593 const weld::TreeIter
* pParent
) override
;
596 /** Node represents a struct */
597 class StructNode
: public BasicValueNode
600 StructNode(OUString
const& rName
, uno::Any
const& rAny
, OUString
const& rInfo
,
601 uno::Reference
<uno::XComponentContext
> const& xContext
)
602 : BasicValueNode(rName
, rAny
, rInfo
, xContext
)
606 bool shouldShowExpander() override
{ return true; }
608 void fillChildren(std::unique_ptr
<weld::TreeView
>& pTree
,
609 const weld::TreeIter
* pParent
) override
;
612 /** Node represents a sequence */
613 class SequenceNode
: public BasicValueNode
615 uno::Reference
<reflection::XIdlArray
> mxIdlArray
;
618 SequenceNode(OUString
const& rName
, uno::Any
const& rAny
, OUString
const& rInfo
,
619 uno::Reference
<uno::XComponentContext
> const& xContext
)
620 : BasicValueNode(rName
, rAny
, rInfo
, xContext
)
622 auto xClass
= convertTypeToIdlClass(maAny
.getValueType(), mxContext
);
623 mxIdlArray
= xClass
->getArray();
626 bool shouldShowExpander() override
628 // Show expander only if the sequence has elements
629 int nLength
= mxIdlArray
->getLen(maAny
);
633 void fillChildren(std::unique_ptr
<weld::TreeView
>& pTree
,
634 const weld::TreeIter
* pParent
) override
636 int nLength
= mxIdlArray
->getLen(maAny
);
638 for (int i
= 0; i
< nLength
; i
++)
640 uno::Any aArrayValue
= mxIdlArray
->get(maAny
, i
);
642 auto* pObjectInspectorNode
643 = createNodeObjectForAny(OUString::number(i
), aArrayValue
, u
""_ustr
);
644 if (pObjectInspectorNode
)
645 lclAppendNodeToParent(pTree
, pParent
, pObjectInspectorNode
);
649 std::vector
<std::pair
<sal_Int32
, OUString
>> getColumnValues() override
651 int nLength
= mxIdlArray
->getLen(maAny
);
654 = getAnyType(maAny
).replaceAll(u
"[]", u
"") + u
"[" + OUString::number(nLength
) + u
"]";
657 = SfxResId(STR_PROPERTY_VALUE_SEQUENCE
).replaceFirst("%1", OUString::number(nLength
));
666 void GenericPropertiesNode::fillChildren(std::unique_ptr
<weld::TreeView
>& pTree
,
667 const weld::TreeIter
* pParent
)
669 if (!maAny
.hasValue())
674 const auto xNameAccess
= uno::Reference
<container::XNameAccess
>(maAny
, uno::UNO_QUERY
);
675 if (xNameAccess
.is())
677 const uno::Sequence
<OUString
> aNames
= xNameAccess
->getElementNames();
678 for (OUString
const& rName
: aNames
)
680 uno::Any aAny
= xNameAccess
->getByName(rName
);
681 auto* pObjectInspectorNode
= createNodeObjectForAny(
682 u
"@" + rName
, aAny
, SfxResId(STR_PROPERTY_TYPE_IS_NAMED_CONTAINER
));
683 lclAppendNodeToParent(pTree
, pParent
, pObjectInspectorNode
);
693 const auto xIndexAccess
= uno::Reference
<container::XIndexAccess
>(maAny
, uno::UNO_QUERY
);
694 if (xIndexAccess
.is())
696 for (sal_Int32 nIndex
= 0; nIndex
< xIndexAccess
->getCount(); ++nIndex
)
698 uno::Any aAny
= xIndexAccess
->getByIndex(nIndex
);
699 auto* pObjectInspectorNode
700 = createNodeObjectForAny(u
"@" + OUString::number(nIndex
), aAny
,
701 SfxResId(STR_PROPERTY_TYPE_IS_INDEX_CONTAINER
));
702 lclAppendNodeToParent(pTree
, pParent
, pObjectInspectorNode
);
712 const auto xEnumAccess
713 = uno::Reference
<container::XEnumerationAccess
>(maAny
, uno::UNO_QUERY
);
714 if (xEnumAccess
.is())
716 uno::Reference
<container::XEnumeration
> xEnumeration
= xEnumAccess
->createEnumeration();
717 if (xEnumeration
.is())
719 for (sal_Int32 nIndex
= 0; xEnumeration
->hasMoreElements(); nIndex
++)
721 uno::Any aAny
= xEnumeration
->nextElement();
722 auto* pObjectInspectorNode
723 = createNodeObjectForAny(u
"@" + OUString::number(nIndex
), aAny
,
724 SfxResId(STR_PROPERTY_TYPE_IS_ENUMERATION
));
725 lclAppendNodeToParent(pTree
, pParent
, pObjectInspectorNode
);
734 auto xInvocationFactory
= css::script::Invocation::create(mxContext
);
735 uno::Sequence
<uno::Any
> aParameters
= { maAny
};
736 auto xInvocationInterface
= xInvocationFactory
->createInstanceWithArguments(aParameters
);
737 if (!xInvocationInterface
.is())
740 uno::Reference
<script::XInvocation2
> xInvocation(xInvocationInterface
, uno::UNO_QUERY
);
741 if (!xInvocation
.is())
744 auto const xInvocationAccess
= xInvocation
->getIntrospection();
745 if (!xInvocationAccess
.is())
748 uno::Sequence
<script::InvocationInfo
> aInvocationInfoSequence
;
751 aInvocationInfoSequence
= xInvocation
->getInfo();
757 for (auto const& aInvocationInfo
: aInvocationInfoSequence
)
759 if (aInvocationInfo
.eMemberType
== script::MemberType_PROPERTY
)
761 uno::Any aCurrentAny
;
762 auto const& aPropertyName
= aInvocationInfo
.aName
;
764 bool bIsAttribute
= false;
765 bool bIsGetSetMethod
= false;
766 bool bMethodGet
= false;
767 bool bMethodSet
= false;
768 bool bMethodIs
= false;
771 aCurrentAny
= xInvocation
->getValue(aPropertyName
);
772 bIsAttribute
= xInvocationAccess
->hasProperty(aPropertyName
,
773 beans::PropertyConcept::ATTRIBUTES
);
774 bIsGetSetMethod
= xInvocationAccess
->hasProperty(aPropertyName
,
775 beans::PropertyConcept::METHODS
);
778 bMethodGet
= xInvocationAccess
->hasMethod(u
"get" + aPropertyName
,
779 beans::MethodConcept::PROPERTY
);
780 bMethodSet
= xInvocationAccess
->hasMethod(u
"set" + aPropertyName
,
781 beans::MethodConcept::PROPERTY
);
782 bMethodIs
= xInvocationAccess
->hasMethod(u
"is" + aPropertyName
,
783 beans::MethodConcept::PROPERTY
);
790 std::vector
<OUString
> aInfoCollection
;
792 aInfoCollection
.push_back(SfxResId(STR_PROPERTY_ATTRIBUTE_IS_ATTRIBUTE
));
795 bool bHasGet
= false;
797 if (bMethodGet
|| bMethodIs
)
799 aString
+= SfxResId(STR_PROPERTY_ATTRIBUTE_GET
);
806 aString
+= SfxResId(STR_PROPERTY_ATTRIBUTE_SET
);
808 aInfoCollection
.push_back(aString
);
809 if (bMethodSet
&& !bHasGet
)
810 aInfoCollection
.push_back(SfxResId(STR_PROPERTY_ATTRIBUTE_WRITEONLY
));
812 if (aInvocationInfo
.PropertyAttribute
& beans::PropertyAttribute::MAYBEVOID
)
813 aInfoCollection
.push_back(SfxResId(STR_PROPERTY_ATTRIBUTE_MAYBEVOID
));
814 if (aInvocationInfo
.PropertyAttribute
& beans::PropertyAttribute::READONLY
)
815 aInfoCollection
.push_back(SfxResId(STR_PROPERTY_ATTRIBUTE_READONLY
));
816 if (aInvocationInfo
.PropertyAttribute
& beans::PropertyAttribute::REMOVABLE
)
817 aInfoCollection
.push_back(SfxResId(STR_PROPERTY_ATTRIBUTE_REMOVABLE
));
818 if (aInvocationInfo
.PropertyAttribute
& beans::PropertyAttribute::BOUND
)
819 aInfoCollection
.push_back(SfxResId(STR_PROPERTY_ATTRIBUTE_BOUND
));
820 if (aInvocationInfo
.PropertyAttribute
& beans::PropertyAttribute::CONSTRAINED
)
821 aInfoCollection
.push_back(SfxResId(STR_PROPERTY_ATTRIBUTE_CONSTRAINED
));
822 if (aInvocationInfo
.PropertyAttribute
& beans::PropertyAttribute::TRANSIENT
)
823 aInfoCollection
.push_back(SfxResId(STR_PROPERTY_ATTRIBUTE_TRANSIENT
));
824 if (aInvocationInfo
.PropertyAttribute
& beans::PropertyAttribute::MAYBEAMBIGUOUS
)
825 aInfoCollection
.push_back(SfxResId(STR_PROPERTY_ATTRIBUTE_MAYBEAMBIGUOUS
));
826 if (aInvocationInfo
.PropertyAttribute
& beans::PropertyAttribute::MAYBEDEFAULT
)
827 aInfoCollection
.push_back(SfxResId(STR_PROPERTY_ATTRIBUTE_MAYBEDEFAULT
));
830 OUString aInfoString
;
831 for (auto const& rString
: aInfoCollection
)
838 aInfoString
+= rString
;
841 auto* pObjectInspectorNode
842 = createNodeObjectForAny(aPropertyName
, aCurrentAny
, aInfoString
);
843 if (pObjectInspectorNode
)
844 lclAppendNodeToParent(pTree
, pParent
, pObjectInspectorNode
);
849 void StructNode::fillChildren(std::unique_ptr
<weld::TreeView
>& pTree
, const weld::TreeIter
* pParent
)
851 auto xReflection
= reflection::theCoreReflection::get(mxContext
);
852 uno::Reference
<reflection::XIdlClass
> xClass
= xReflection
->forName(maAny
.getValueTypeName());
854 const auto xFields
= xClass
->getFields();
856 for (auto const& xField
: xFields
)
858 OUString aFieldName
= xField
->getName();
859 uno::Any aFieldValue
= xField
->get(maAny
);
861 auto* pObjectInspectorNode
= createNodeObjectForAny(aFieldName
, aFieldValue
, u
""_ustr
);
862 if (pObjectInspectorNode
)
864 lclAppendNodeToParent(pTree
, pParent
, pObjectInspectorNode
);
869 ObjectInspectorNodeInterface
* BasicValueNode::createNodeObjectForAny(OUString
const& rName
,
870 const uno::Any
& rAny
,
871 OUString
const& rInfo
)
873 switch (rAny
.getValueTypeClass())
875 case uno::TypeClass_INTERFACE
:
876 return new GenericPropertiesNode(rName
, rAny
, rInfo
, mxContext
);
878 case uno::TypeClass_SEQUENCE
:
879 return new SequenceNode(rName
, rAny
, rInfo
, mxContext
);
881 case uno::TypeClass_STRUCT
:
882 return new StructNode(rName
, rAny
, rInfo
, mxContext
);
888 return new BasicValueNode(rName
, rAny
, rInfo
, mxContext
);
891 } // end anonymous namespace
893 // Object inspector tree view helper functions
896 ObjectInspectorNodeInterface
* getSelectedNode(weld::TreeView
const& rTreeView
)
898 OUString sID
= rTreeView
.get_selected_id();
902 if (auto* pNode
= weld::fromId
<ObjectInspectorNodeInterface
*>(sID
))
908 uno::Reference
<uno::XInterface
> getSelectedXInterface(weld::TreeView
const& rTreeView
)
910 uno::Reference
<uno::XInterface
> xInterface
;
912 if (auto* pNode
= getSelectedNode(rTreeView
))
914 if (auto* pBasicValueNode
= dynamic_cast<BasicValueNode
*>(pNode
))
916 uno::Any aAny
= pBasicValueNode
->getAny();
917 xInterface
.set(aAny
, uno::UNO_QUERY
);
924 } // end anonymous namespace
926 ObjectInspectorTreeHandler::ObjectInspectorTreeHandler(
927 std::unique_ptr
<ObjectInspectorWidgets
>& pObjectInspectorWidgets
)
928 : mpObjectInspectorWidgets(pObjectInspectorWidgets
)
929 , mxContext(comphelper::getProcessComponentContext())
930 , mxSorter(mxContext
, Application::GetSettings().GetLanguageTag().getLocale())
932 mpObjectInspectorWidgets
->mpInterfacesTreeView
->connect_expanding(
933 LINK(this, ObjectInspectorTreeHandler
, ExpandingHandlerInterfaces
));
934 mpObjectInspectorWidgets
->mpServicesTreeView
->connect_expanding(
935 LINK(this, ObjectInspectorTreeHandler
, ExpandingHandlerServices
));
936 mpObjectInspectorWidgets
->mpPropertiesTreeView
->connect_expanding(
937 LINK(this, ObjectInspectorTreeHandler
, ExpandingHandlerProperties
));
938 mpObjectInspectorWidgets
->mpMethodsTreeView
->connect_expanding(
939 LINK(this, ObjectInspectorTreeHandler
, ExpandingHandlerMethods
));
941 mpObjectInspectorWidgets
->mpPropertiesTreeView
->connect_popup_menu(
942 LINK(this, ObjectInspectorTreeHandler
, PopupMenuHandler
));
944 mpObjectInspectorWidgets
->mpInterfacesTreeView
->connect_selection_changed(
945 LINK(this, ObjectInspectorTreeHandler
, SelectionChanged
));
946 mpObjectInspectorWidgets
->mpServicesTreeView
->connect_selection_changed(
947 LINK(this, ObjectInspectorTreeHandler
, SelectionChanged
));
948 mpObjectInspectorWidgets
->mpPropertiesTreeView
->connect_selection_changed(
949 LINK(this, ObjectInspectorTreeHandler
, SelectionChanged
));
950 mpObjectInspectorWidgets
->mpMethodsTreeView
->connect_selection_changed(
951 LINK(this, ObjectInspectorTreeHandler
, SelectionChanged
));
953 mpObjectInspectorWidgets
->mpInterfacesTreeView
->make_sorted();
954 mpObjectInspectorWidgets
->mpServicesTreeView
->make_sorted();
955 mpObjectInspectorWidgets
->mpPropertiesTreeView
->make_sorted();
956 mpObjectInspectorWidgets
->mpMethodsTreeView
->make_sorted();
958 setSortFunction(mpObjectInspectorWidgets
->mpInterfacesTreeView
);
959 setSortFunction(mpObjectInspectorWidgets
->mpServicesTreeView
);
960 setSortFunction(mpObjectInspectorWidgets
->mpPropertiesTreeView
);
961 setSortFunction(mpObjectInspectorWidgets
->mpMethodsTreeView
);
963 mpObjectInspectorWidgets
->mpInterfacesTreeView
->connect_column_clicked(
964 LINK(this, ObjectInspectorTreeHandler
, HeaderBarClick
));
965 mpObjectInspectorWidgets
->mpServicesTreeView
->connect_column_clicked(
966 LINK(this, ObjectInspectorTreeHandler
, HeaderBarClick
));
967 mpObjectInspectorWidgets
->mpPropertiesTreeView
->connect_column_clicked(
968 LINK(this, ObjectInspectorTreeHandler
, HeaderBarClick
));
969 mpObjectInspectorWidgets
->mpMethodsTreeView
->connect_column_clicked(
970 LINK(this, ObjectInspectorTreeHandler
, HeaderBarClick
));
972 mpObjectInspectorWidgets
->mpToolbar
->connect_clicked(
973 LINK(this, ObjectInspectorTreeHandler
, ToolbarButtonClicked
));
974 mpObjectInspectorWidgets
->mpToolbar
->set_item_sensitive(u
"inspect"_ustr
, false);
975 mpObjectInspectorWidgets
->mpToolbar
->set_item_sensitive(u
"back"_ustr
, false);
977 mpObjectInspectorWidgets
->mpNotebook
->connect_leave_page(
978 LINK(this, ObjectInspectorTreeHandler
, NotebookLeavePage
));
979 mpObjectInspectorWidgets
->mpNotebook
->connect_enter_page(
980 LINK(this, ObjectInspectorTreeHandler
, NotebookEnterPage
));
982 auto nPropertiesDigitWidth
983 = mpObjectInspectorWidgets
->mpPropertiesTreeView
->get_approximate_digit_width();
984 std::vector
<int> aPropertiesWidths(4, nPropertiesDigitWidth
* 30);
985 mpObjectInspectorWidgets
->mpPropertiesTreeView
->set_column_fixed_widths(aPropertiesWidths
);
987 auto nMethodsDigitWidth
988 = mpObjectInspectorWidgets
->mpMethodsTreeView
->get_approximate_digit_width();
989 std::vector
<int> aMethodsWidths
{ static_cast<int>(nMethodsDigitWidth
* 30),
990 static_cast<int>(nMethodsDigitWidth
* 15),
991 static_cast<int>(nMethodsDigitWidth
* 30),
992 static_cast<int>(nMethodsDigitWidth
* 50) };
993 mpObjectInspectorWidgets
->mpMethodsTreeView
->set_column_fixed_widths(aMethodsWidths
);
995 mpObjectInspectorWidgets
->mpPaned
->set_position(160);
998 void ObjectInspectorTreeHandler::setSortFunction(std::unique_ptr
<weld::TreeView
>& pTreeView
)
1000 pTreeView
->set_sort_func(
1001 [this, &pTreeView
](const weld::TreeIter
& rLeft
, const weld::TreeIter
& rRight
) {
1002 return compare(pTreeView
, rLeft
, rRight
);
1006 sal_Int32
ObjectInspectorTreeHandler::compare(std::unique_ptr
<weld::TreeView
>& pTreeView
,
1007 const weld::TreeIter
& rLeft
,
1008 const weld::TreeIter
& rRight
)
1010 int nSortColumn
= pTreeView
->get_sort_column();
1012 OUString sLeft
= pTreeView
->get_text(rLeft
, nSortColumn
);
1013 OUString sRight
= pTreeView
->get_text(rRight
, nSortColumn
);
1014 sal_Int32 nCompare
= mxSorter
.compare(sLeft
, sRight
);
1018 void ObjectInspectorTreeHandler::handleExpanding(std::unique_ptr
<weld::TreeView
>& pTreeView
,
1019 weld::TreeIter
const& rParent
)
1021 OUString sID
= pTreeView
->get_id(rParent
);
1025 clearObjectInspectorChildren(pTreeView
, rParent
);
1026 auto* pNode
= weld::fromId
<ObjectInspectorNodeInterface
*>(sID
);
1027 pNode
->fillChildren(pTreeView
, &rParent
);
1030 IMPL_LINK(ObjectInspectorTreeHandler
, ExpandingHandlerInterfaces
, weld::TreeIter
const&, rParent
,
1033 handleExpanding(mpObjectInspectorWidgets
->mpInterfacesTreeView
, rParent
);
1037 IMPL_LINK(ObjectInspectorTreeHandler
, ExpandingHandlerServices
, weld::TreeIter
const&, rParent
,
1040 handleExpanding(mpObjectInspectorWidgets
->mpServicesTreeView
, rParent
);
1044 IMPL_LINK(ObjectInspectorTreeHandler
, ExpandingHandlerProperties
, weld::TreeIter
const&, rParent
,
1047 handleExpanding(mpObjectInspectorWidgets
->mpPropertiesTreeView
, rParent
);
1051 IMPL_LINK(ObjectInspectorTreeHandler
, ExpandingHandlerMethods
, weld::TreeIter
const&, rParent
, bool)
1053 handleExpanding(mpObjectInspectorWidgets
->mpMethodsTreeView
, rParent
);
1057 IMPL_LINK(ObjectInspectorTreeHandler
, SelectionChanged
, weld::TreeView
&, rTreeView
, void)
1059 bool bHaveNodeWithObject
= false;
1060 mpObjectInspectorWidgets
->mpTextView
->set_text(u
""_ustr
);
1061 if (mpObjectInspectorWidgets
->mpPropertiesTreeView
.get() == &rTreeView
)
1063 auto* pNode
= getSelectedNode(rTreeView
);
1064 if (auto* pBasicValueNode
= dynamic_cast<BasicValueNode
*>(pNode
))
1066 uno::Any aAny
= pBasicValueNode
->getAny();
1067 uno::Reference
<uno::XInterface
> xInterface(aAny
, uno::UNO_QUERY
);
1068 bHaveNodeWithObject
= xInterface
.is();
1069 mpObjectInspectorWidgets
->mpTextView
->set_text(convertAnyToString(aAny
, mxContext
));
1073 mpObjectInspectorWidgets
->mpToolbar
->set_item_sensitive(u
"inspect"_ustr
, bHaveNodeWithObject
);
1076 static void updateOrder(const std::unique_ptr
<weld::TreeView
>& pTreeView
, sal_Int32 nColumn
)
1078 pTreeView
->set_sort_column(nColumn
);
1080 bool bSortAtoZ
= pTreeView
->get_sort_order();
1081 pTreeView
->set_sort_order(!bSortAtoZ
);
1082 pTreeView
->set_sort_indicator(!bSortAtoZ
? TRISTATE_TRUE
: TRISTATE_FALSE
, nColumn
);
1085 IMPL_LINK(ObjectInspectorTreeHandler
, HeaderBarClick
, int, nColumn
, void)
1087 auto rPageId
= mpObjectInspectorWidgets
->mpNotebook
->get_current_page_ident();
1089 if (rPageId
== "object_inspector_interfaces_tab")
1090 updateOrder(mpObjectInspectorWidgets
->mpInterfacesTreeView
, nColumn
);
1091 else if (rPageId
== "object_inspector_services_tab")
1092 updateOrder(mpObjectInspectorWidgets
->mpServicesTreeView
, nColumn
);
1093 else if (rPageId
== "object_inspector_properties_tab")
1094 updateOrder(mpObjectInspectorWidgets
->mpPropertiesTreeView
, nColumn
);
1095 else if (rPageId
== "object_inspector_methods_tab")
1096 updateOrder(mpObjectInspectorWidgets
->mpMethodsTreeView
, nColumn
);
1099 IMPL_LINK(ObjectInspectorTreeHandler
, PopupMenuHandler
, const CommandEvent
&, rCommandEvent
, bool)
1101 if (rCommandEvent
.GetCommand() != CommandEventId::ContextMenu
)
1104 auto xInterface
= getSelectedXInterface(*mpObjectInspectorWidgets
->mpPropertiesTreeView
);
1105 if (xInterface
.is())
1107 std::unique_ptr
<weld::Builder
> xBuilder(Application::CreateBuilder(
1108 mpObjectInspectorWidgets
->mpPropertiesTreeView
.get(), u
"sfx/ui/devtoolsmenu.ui"_ustr
));
1109 std::unique_ptr
<weld::Menu
> xMenu(xBuilder
->weld_menu(u
"inspect_menu"_ustr
));
1112 xMenu
->popup_at_rect(mpObjectInspectorWidgets
->mpPropertiesTreeView
.get(),
1113 tools::Rectangle(rCommandEvent
.GetMousePosPixel(), Size(1, 1))));
1115 if (sCommand
== "inspect")
1117 addToStack(uno::Any(xInterface
));
1118 inspectObject(xInterface
);
1124 IMPL_LINK(ObjectInspectorTreeHandler
, ToolbarButtonClicked
, const OUString
&, rSelectionId
, void)
1126 if (rSelectionId
== "inspect")
1128 auto xInterface
= getSelectedXInterface(*mpObjectInspectorWidgets
->mpPropertiesTreeView
);
1129 if (xInterface
.is())
1131 addToStack(uno::Any(xInterface
));
1132 inspectObject(xInterface
);
1135 else if (rSelectionId
== "back")
1137 uno::Any aAny
= popFromStack();
1138 if (aAny
.hasValue())
1140 uno::Reference
<uno::XInterface
> xInterface(aAny
, uno::UNO_QUERY
);
1141 inspectObject(xInterface
);
1144 else if (rSelectionId
== "refresh")
1146 auto rPageId
= mpObjectInspectorWidgets
->mpNotebook
->get_current_page_ident();
1147 NotebookEnterPage(rPageId
);
1151 IMPL_LINK(ObjectInspectorTreeHandler
, NotebookEnterPage
, const OUString
&, rPageId
, void)
1153 uno::Any aAny
= maInspectionStack
.back();
1154 if (!aAny
.hasValue())
1157 uno::Reference
<uno::XInterface
> xInterface(aAny
, uno::UNO_QUERY
);
1158 if (rPageId
== "object_inspector_interfaces_tab")
1160 mpObjectInspectorWidgets
->mpInterfacesTreeView
->freeze();
1161 clearAll(mpObjectInspectorWidgets
->mpInterfacesTreeView
);
1162 appendInterfaces(xInterface
);
1163 mpObjectInspectorWidgets
->mpInterfacesTreeView
->thaw();
1165 else if (rPageId
== "object_inspector_services_tab")
1167 mpObjectInspectorWidgets
->mpServicesTreeView
->freeze();
1168 clearAll(mpObjectInspectorWidgets
->mpServicesTreeView
);
1169 appendServices(xInterface
);
1170 mpObjectInspectorWidgets
->mpServicesTreeView
->thaw();
1172 else if (rPageId
== "object_inspector_properties_tab")
1174 mpObjectInspectorWidgets
->mpPropertiesTreeView
->freeze();
1175 clearAll(mpObjectInspectorWidgets
->mpPropertiesTreeView
);
1176 appendProperties(xInterface
);
1177 mpObjectInspectorWidgets
->mpPropertiesTreeView
->thaw();
1179 else if (rPageId
== "object_inspector_methods_tab")
1181 mpObjectInspectorWidgets
->mpMethodsTreeView
->freeze();
1182 clearAll(mpObjectInspectorWidgets
->mpMethodsTreeView
);
1183 appendMethods(xInterface
);
1184 mpObjectInspectorWidgets
->mpMethodsTreeView
->thaw();
1188 IMPL_LINK(ObjectInspectorTreeHandler
, NotebookLeavePage
, const OUString
&, rPageId
, bool)
1190 if (rPageId
== "object_inspector_interfaces_tab")
1192 mpObjectInspectorWidgets
->mpInterfacesTreeView
->freeze();
1193 clearAll(mpObjectInspectorWidgets
->mpInterfacesTreeView
);
1194 mpObjectInspectorWidgets
->mpInterfacesTreeView
->thaw();
1196 else if (rPageId
== "object_inspector_services_tab")
1198 mpObjectInspectorWidgets
->mpServicesTreeView
->freeze();
1199 clearAll(mpObjectInspectorWidgets
->mpServicesTreeView
);
1200 mpObjectInspectorWidgets
->mpServicesTreeView
->thaw();
1202 else if (rPageId
== "object_inspector_properties_tab")
1204 mpObjectInspectorWidgets
->mpPropertiesTreeView
->freeze();
1205 clearAll(mpObjectInspectorWidgets
->mpPropertiesTreeView
);
1206 mpObjectInspectorWidgets
->mpPropertiesTreeView
->thaw();
1208 else if (rPageId
== "object_inspector_methods_tab")
1210 mpObjectInspectorWidgets
->mpMethodsTreeView
->freeze();
1211 clearAll(mpObjectInspectorWidgets
->mpMethodsTreeView
);
1212 mpObjectInspectorWidgets
->mpMethodsTreeView
->thaw();
1217 void ObjectInspectorTreeHandler::clearObjectInspectorChildren(
1218 std::unique_ptr
<weld::TreeView
>& pTreeView
, weld::TreeIter
const& rParent
)
1220 bool bChild
= false;
1223 bChild
= pTreeView
->iter_has_child(rParent
);
1226 std::unique_ptr
<weld::TreeIter
> pChild
= pTreeView
->make_iterator(&rParent
);
1227 bChild
= pTreeView
->iter_children(*pChild
);
1230 clearObjectInspectorChildren(pTreeView
, *pChild
);
1231 OUString sID
= pTreeView
->get_id(*pChild
);
1232 auto* pEntry
= weld::fromId
<ObjectInspectorNodeInterface
*>(sID
);
1234 pTreeView
->remove(*pChild
);
1240 /** Deletes all the node objects in a tree view */
1241 void ObjectInspectorTreeHandler::clearAll(std::unique_ptr
<weld::TreeView
>& pTreeView
)
1243 // destroy all ObjectInspectorNodes from the tree
1244 pTreeView
->all_foreach([&pTreeView
](weld::TreeIter
& rEntry
) {
1245 OUString sID
= pTreeView
->get_id(rEntry
);
1246 auto* pEntry
= weld::fromId
<ObjectInspectorNodeInterface
*>(sID
);
1253 /** Append interfaces to the "interfaces" tree view */
1254 void ObjectInspectorTreeHandler::appendInterfaces(uno::Reference
<uno::XInterface
> const& xInterface
)
1256 if (!xInterface
.is())
1259 uno::Reference
<lang::XTypeProvider
> xTypeProvider(xInterface
, uno::UNO_QUERY
);
1260 if (xTypeProvider
.is())
1262 const auto xSequenceTypes
= xTypeProvider
->getTypes();
1263 for (auto const& xType
: xSequenceTypes
)
1265 auto xClass
= convertTypeToIdlClass(xType
, mxContext
);
1266 lclAppendNode(mpObjectInspectorWidgets
->mpInterfacesTreeView
, new ClassNode(xClass
));
1271 /** Append services to the "services" tree view */
1272 void ObjectInspectorTreeHandler::appendServices(uno::Reference
<uno::XInterface
> const& xInterface
)
1274 if (!xInterface
.is())
1277 auto xServiceInfo
= uno::Reference
<lang::XServiceInfo
>(xInterface
, uno::UNO_QUERY
);
1278 const uno::Sequence
<OUString
> aServiceNames(xServiceInfo
->getSupportedServiceNames());
1279 for (auto const& aServiceName
: aServiceNames
)
1281 lclAppendNode(mpObjectInspectorWidgets
->mpServicesTreeView
,
1282 new SimpleStringNode(aServiceName
));
1286 /** Append properties to the "properties" tree view */
1287 void ObjectInspectorTreeHandler::appendProperties(uno::Reference
<uno::XInterface
> const& xInterface
)
1289 if (!xInterface
.is())
1291 GenericPropertiesNode
aNode(u
""_ustr
, uno::Any(xInterface
), u
""_ustr
, mxContext
);
1292 aNode
.fillChildren(mpObjectInspectorWidgets
->mpPropertiesTreeView
, nullptr);
1295 /** Append methods to the "methods" tree view */
1296 void ObjectInspectorTreeHandler::appendMethods(uno::Reference
<uno::XInterface
> const& xInterface
)
1298 if (!xInterface
.is())
1301 uno::Reference
<beans::XIntrospection
> xIntrospection
= beans::theIntrospection::get(mxContext
);
1302 auto xIntrospectionAccess
= xIntrospection
->inspect(uno::Any(xInterface
));
1304 const auto xMethods
= xIntrospectionAccess
->getMethods(beans::MethodConcept::ALL
);
1305 for (auto const& xMethod
: xMethods
)
1307 lclAppendNode(mpObjectInspectorWidgets
->mpMethodsTreeView
, new MethodNode(xMethod
));
1311 // Update the back button state depending if there are objects in the stack
1312 void ObjectInspectorTreeHandler::updateBackButtonState()
1314 mpObjectInspectorWidgets
->mpToolbar
->set_item_sensitive(u
"back"_ustr
,
1315 maInspectionStack
.size() > 1);
1318 // Clears all the objects from the stack
1319 void ObjectInspectorTreeHandler::clearStack()
1321 maInspectionStack
.clear();
1322 updateBackButtonState();
1325 // Adds an object to the stack
1326 void ObjectInspectorTreeHandler::addToStack(css::uno::Any
const& rAny
)
1328 maInspectionStack
.push_back(rAny
);
1329 updateBackButtonState();
1332 // Removes an object from the back of the stack and return it
1333 css::uno::Any
ObjectInspectorTreeHandler::popFromStack()
1335 maInspectionStack
.pop_back();
1336 uno::Any aAny
= maInspectionStack
.back();
1337 updateBackButtonState();
1341 // Inspect the input object in the object inspector
1342 void ObjectInspectorTreeHandler::inspectObject(uno::Reference
<uno::XInterface
> const& xInterface
)
1344 if (!xInterface
.is())
1347 // Set implementation name
1348 OUString aImplementationName
= getInterfaceImplementationClass(xInterface
);
1349 mpObjectInspectorWidgets
->mpClassNameLabel
->set_label(aImplementationName
);
1350 sal_Int32 nStrLen
= aImplementationName
.getLength();
1351 sal_Int32 nDigitWidth
1352 = mpObjectInspectorWidgets
->mpClassNameLabel
->get_approximate_digit_width();
1354 //get_about_digit_width() returns an approximate value. To always see the full class name (nStrLen+2)
1355 mpObjectInspectorWidgets
->mpClassNameLabel
->set_size_request((nStrLen
+ 2) * nDigitWidth
, -1);
1357 // Fire entering the current opened page manually
1358 auto rPageId
= mpObjectInspectorWidgets
->mpNotebook
->get_current_page_ident();
1359 NotebookEnterPage(rPageId
);
1362 // Inspect the input object in the object inspector.
1363 // Make the input object the root of the stack (clear all other
1364 // objects from the stack).
1365 void ObjectInspectorTreeHandler::introspect(uno::Reference
<uno::XInterface
> const& xInterface
)
1368 addToStack(uno::Any(xInterface
));
1369 inspectObject(xInterface
);
1372 void ObjectInspectorTreeHandler::dispose()
1374 // We need to clear all the nodes
1375 clearAll(mpObjectInspectorWidgets
->mpInterfacesTreeView
);
1376 clearAll(mpObjectInspectorWidgets
->mpServicesTreeView
);
1377 clearAll(mpObjectInspectorWidgets
->mpPropertiesTreeView
);
1378 clearAll(mpObjectInspectorWidgets
->mpMethodsTreeView
);
1381 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */