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
.getValueType().getTypeName()),
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("Name"))
206 uno::Any aAny
= xInvocation
->getValue("Name");
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
.getValueType().getTypeName();
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 OUString
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
);
370 // appends the node to the parent
371 OUString
lclAppendNodeToParent(const std::unique_ptr
<weld::TreeView
>& pTree
,
372 const weld::TreeIter
* pParent
, ObjectInspectorNodeInterface
* pEntry
)
374 OUString sName
= pEntry
->getObjectName();
375 OUString
sId(weld::toId(pEntry
));
376 std::unique_ptr
<weld::TreeIter
> pCurrent
= pTree
->make_iterator();
377 pTree
->insert(pParent
, -1, &sName
, &sId
, nullptr, nullptr, pEntry
->shouldShowExpander(),
379 pTree
->set_text_emphasis(*pCurrent
, true, 0);
381 for (auto const& rPair
: pEntry
->getColumnValues())
383 pTree
->set_text(*pCurrent
, rPair
.second
, rPair
.first
);
389 /** Node that represent just a simple string with no children or columns */
390 class SimpleStringNode
: public ObjectInspectorNodeInterface
396 SimpleStringNode(OUString sName
)
397 : msName(std::move(sName
))
401 void fillChildren(std::unique_ptr
<weld::TreeView
>& /*rTree*/,
402 const weld::TreeIter
* /*pParent*/) override
406 OUString
getObjectName() override
{ return msName
; }
409 /** Node represents a method of an object */
410 class MethodNode
: public ObjectInspectorNodeInterface
413 uno::Reference
<reflection::XIdlMethod
> mxMethod
;
416 MethodNode(uno::Reference
<reflection::XIdlMethod
> xMethod
)
417 : mxMethod(std::move(xMethod
))
421 OUString
getObjectName() override
{ return mxMethod
->getName(); }
423 static OUString
simpleTypeName(uno::Reference
<reflection::XIdlClass
> const& xClass
)
425 switch (xClass
->getTypeClass())
427 case uno::TypeClass_INTERFACE
:
428 return SfxResId(STR_METHOD_TYPE_OBJECT
);
429 case uno::TypeClass_STRUCT
:
430 return SfxResId(STR_METHOD_TYPE_STRUCT
);
431 case uno::TypeClass_ENUM
:
432 return SfxResId(STR_METHOD_TYPE_ENUM
);
433 case uno::TypeClass_SEQUENCE
:
434 return SfxResId(STR_METHOD_TYPE_SEQUENCE
);
438 return xClass
->getName();
441 std::vector
<std::pair
<sal_Int32
, OUString
>> getColumnValues() override
444 auto xClass
= mxMethod
->getReturnType();
445 aOutString
= simpleTypeName(xClass
);
448 const auto aParameters
= mxMethod
->getParameterInfos();
450 for (auto const& rParameterInfo
: aParameters
)
457 switch (rParameterInfo
.aMode
)
459 case reflection::ParamMode_IN
:
460 aInString
+= SfxResId(STR_PARMETER_MODE_IN
) + " ";
462 case reflection::ParamMode_OUT
:
463 aInString
+= SfxResId(STR_PARMETER_MODE_OUT
) + " ";
465 case reflection::ParamMode_INOUT
:
466 aInString
+= SfxResId(STR_PARMETER_MODE_IN_AND_OUT
) + " ";
472 aInString
+= rParameterInfo
.aName
+ " : " + simpleTypeName(rParameterInfo
.aType
);
475 OUString aImplementationClass
= mxMethod
->getDeclaringClass()->getName();
480 { 3, aImplementationClass
},
484 void fillChildren(std::unique_ptr
<weld::TreeView
>& /*rTree*/,
485 const weld::TreeIter
* /*pParent*/) override
490 /** Node represents a class (XIdlClass) of an object.
492 * Children are superclasses of the current class. XInterface superclass
496 class ClassNode
: public ObjectInspectorNodeInterface
499 uno::Reference
<reflection::XIdlClass
> mxClass
;
501 static bool isXInterface(uno::Reference
<reflection::XIdlClass
> const& xClass
)
503 return xClass
->getName() == "com.sun.star.uno.XInterface";
507 ClassNode(uno::Reference
<reflection::XIdlClass
> xClass
)
508 : mxClass(std::move(xClass
))
512 bool shouldShowExpander() override
514 auto const& xSuperClasses
= mxClass
->getSuperclasses();
515 return xSuperClasses
.getLength() > 2
516 || (xSuperClasses
.getLength() == 1 && !isXInterface(xSuperClasses
[0]));
519 OUString
getObjectName() override
{ return mxClass
->getName(); }
522 void fillChildren(std::unique_ptr
<weld::TreeView
>& rTree
,
523 const weld::TreeIter
* pParent
) override
525 auto const& xSuperClasses
= mxClass
->getSuperclasses();
526 for (auto const& xSuper
: xSuperClasses
)
528 if (!isXInterface(xSuper
))
529 lclAppendNodeToParent(rTree
, pParent
, new ClassNode(xSuper
));
534 /** Node represents a basic value, that can be any object, sequence, struct */
535 class BasicValueNode
: public SimpleStringNode
540 uno::Reference
<uno::XComponentContext
> mxContext
;
542 ObjectInspectorNodeInterface
*
543 createNodeObjectForAny(OUString
const& rName
, const uno::Any
& rAny
, OUString
const& mrInfo
);
546 BasicValueNode(OUString
const& rName
, uno::Any aAny
, OUString aInfo
,
547 uno::Reference
<uno::XComponentContext
> xContext
)
548 : SimpleStringNode(rName
)
549 , maAny(std::move(aAny
))
550 , mrInfo(std::move(aInfo
))
551 , mxContext(std::move(xContext
))
555 const uno::Any
& getAny() const { return maAny
; }
557 bool shouldShowExpander() override
559 if (maAny
.hasValue())
561 switch (maAny
.getValueType().getTypeClass())
563 case uno::TypeClass_INTERFACE
:
565 uno::Reference
<uno::XInterface
> xInterface(maAny
, uno::UNO_QUERY
);
566 return xInterface
.is();
568 case uno::TypeClass_SEQUENCE
:
577 std::vector
<std::pair
<sal_Int32
, OUString
>> getColumnValues() override
579 OUString aValue
= convertAnyToShortenedString(maAny
, mxContext
);
580 OUString aType
= getAnyType(maAny
);
582 return { { 1, aValue
}, { 2, aType
}, { 3, mrInfo
} };
586 /** Node represents a property */
587 class GenericPropertiesNode
: public BasicValueNode
590 GenericPropertiesNode(OUString
const& rName
, uno::Any
const& rAny
, OUString
const& rInfo
,
591 uno::Reference
<uno::XComponentContext
> const& xContext
)
592 : BasicValueNode(rName
, rAny
, rInfo
, xContext
)
596 void fillChildren(std::unique_ptr
<weld::TreeView
>& pTree
,
597 const weld::TreeIter
* pParent
) override
;
600 /** Node represents a struct */
601 class StructNode
: public BasicValueNode
604 StructNode(OUString
const& rName
, uno::Any
const& rAny
, OUString
const& rInfo
,
605 uno::Reference
<uno::XComponentContext
> const& xContext
)
606 : BasicValueNode(rName
, rAny
, rInfo
, xContext
)
610 bool shouldShowExpander() override
{ return true; }
612 void fillChildren(std::unique_ptr
<weld::TreeView
>& pTree
,
613 const weld::TreeIter
* pParent
) override
;
616 /** Node represents a sequence */
617 class SequenceNode
: public BasicValueNode
619 uno::Reference
<reflection::XIdlArray
> mxIdlArray
;
622 SequenceNode(OUString
const& rName
, uno::Any
const& rAny
, OUString
const& rInfo
,
623 uno::Reference
<uno::XComponentContext
> const& xContext
)
624 : BasicValueNode(rName
, rAny
, rInfo
, xContext
)
626 auto xClass
= convertTypeToIdlClass(maAny
.getValueType(), mxContext
);
627 mxIdlArray
= xClass
->getArray();
630 bool shouldShowExpander() override
632 // Show expander only if the sequence has elements
633 int nLength
= mxIdlArray
->getLen(maAny
);
637 void fillChildren(std::unique_ptr
<weld::TreeView
>& pTree
,
638 const weld::TreeIter
* pParent
) override
640 int nLength
= mxIdlArray
->getLen(maAny
);
642 for (int i
= 0; i
< nLength
; i
++)
644 uno::Any aArrayValue
= mxIdlArray
->get(maAny
, i
);
646 auto* pObjectInspectorNode
647 = createNodeObjectForAny(OUString::number(i
), aArrayValue
, "");
648 if (pObjectInspectorNode
)
649 lclAppendNodeToParent(pTree
, pParent
, pObjectInspectorNode
);
653 std::vector
<std::pair
<sal_Int32
, OUString
>> getColumnValues() override
655 int nLength
= mxIdlArray
->getLen(maAny
);
658 = getAnyType(maAny
).replaceAll(u
"[]", u
"") + u
"[" + OUString::number(nLength
) + u
"]";
661 = SfxResId(STR_PROPERTY_VALUE_SEQUENCE
).replaceFirst("%1", OUString::number(nLength
));
670 void GenericPropertiesNode::fillChildren(std::unique_ptr
<weld::TreeView
>& pTree
,
671 const weld::TreeIter
* pParent
)
673 if (!maAny
.hasValue())
678 const auto xNameAccess
= uno::Reference
<container::XNameAccess
>(maAny
, uno::UNO_QUERY
);
679 if (xNameAccess
.is())
681 const uno::Sequence
<OUString
> aNames
= xNameAccess
->getElementNames();
682 for (OUString
const& rName
: aNames
)
684 uno::Any aAny
= xNameAccess
->getByName(rName
);
685 auto* pObjectInspectorNode
= createNodeObjectForAny(
686 u
"@" + rName
, aAny
, SfxResId(STR_PROPERTY_TYPE_IS_NAMED_CONTAINER
));
687 lclAppendNodeToParent(pTree
, pParent
, pObjectInspectorNode
);
697 const auto xIndexAccess
= uno::Reference
<container::XIndexAccess
>(maAny
, uno::UNO_QUERY
);
698 if (xIndexAccess
.is())
700 for (sal_Int32 nIndex
= 0; nIndex
< xIndexAccess
->getCount(); ++nIndex
)
702 uno::Any aAny
= xIndexAccess
->getByIndex(nIndex
);
703 auto* pObjectInspectorNode
704 = createNodeObjectForAny(u
"@" + OUString::number(nIndex
), aAny
,
705 SfxResId(STR_PROPERTY_TYPE_IS_INDEX_CONTAINER
));
706 lclAppendNodeToParent(pTree
, pParent
, pObjectInspectorNode
);
716 const auto xEnumAccess
717 = uno::Reference
<container::XEnumerationAccess
>(maAny
, uno::UNO_QUERY
);
718 if (xEnumAccess
.is())
720 uno::Reference
<container::XEnumeration
> xEnumeration
= xEnumAccess
->createEnumeration();
721 if (xEnumeration
.is())
723 for (sal_Int32 nIndex
= 0; xEnumeration
->hasMoreElements(); nIndex
++)
725 uno::Any aAny
= xEnumeration
->nextElement();
726 auto* pObjectInspectorNode
727 = createNodeObjectForAny(u
"@" + OUString::number(nIndex
), aAny
,
728 SfxResId(STR_PROPERTY_TYPE_IS_ENUMERATION
));
729 lclAppendNodeToParent(pTree
, pParent
, pObjectInspectorNode
);
738 auto xInvocationFactory
= css::script::Invocation::create(mxContext
);
739 uno::Sequence
<uno::Any
> aParameters
= { maAny
};
740 auto xInvocationInterface
= xInvocationFactory
->createInstanceWithArguments(aParameters
);
741 if (!xInvocationInterface
.is())
744 uno::Reference
<script::XInvocation2
> xInvocation(xInvocationInterface
, uno::UNO_QUERY
);
745 if (!xInvocation
.is())
748 auto const& xInvocationAccess
= xInvocation
->getIntrospection();
749 if (!xInvocationAccess
.is())
752 uno::Sequence
<script::InvocationInfo
> aInvocationInfoSequence
;
755 aInvocationInfoSequence
= xInvocation
->getInfo();
761 for (auto const& aInvocationInfo
: std::as_const(aInvocationInfoSequence
))
763 if (aInvocationInfo
.eMemberType
== script::MemberType_PROPERTY
)
765 uno::Any aCurrentAny
;
766 auto const& aPropertyName
= aInvocationInfo
.aName
;
768 bool bIsAttribute
= false;
769 bool bIsGetSetMethod
= false;
770 bool bMethodGet
= false;
771 bool bMethodSet
= false;
772 bool bMethodIs
= false;
775 aCurrentAny
= xInvocation
->getValue(aPropertyName
);
776 bIsAttribute
= xInvocationAccess
->hasProperty(aPropertyName
,
777 beans::PropertyConcept::ATTRIBUTES
);
778 bIsGetSetMethod
= xInvocationAccess
->hasProperty(aPropertyName
,
779 beans::PropertyConcept::METHODS
);
782 bMethodGet
= xInvocationAccess
->hasMethod(u
"get" + aPropertyName
,
783 beans::MethodConcept::PROPERTY
);
784 bMethodSet
= xInvocationAccess
->hasMethod(u
"set" + aPropertyName
,
785 beans::MethodConcept::PROPERTY
);
786 bMethodIs
= xInvocationAccess
->hasMethod(u
"is" + aPropertyName
,
787 beans::MethodConcept::PROPERTY
);
794 std::vector
<OUString
> aInfoCollection
;
796 aInfoCollection
.push_back(SfxResId(STR_PROPERTY_ATTRIBUTE_IS_ATTRIBUTE
));
799 bool bHasGet
= false;
801 if (bMethodGet
|| bMethodIs
)
803 aString
+= SfxResId(STR_PROPERTY_ATTRIBUTE_GET
);
810 aString
+= SfxResId(STR_PROPERTY_ATTRIBUTE_SET
);
812 aInfoCollection
.push_back(aString
);
813 if (bMethodSet
&& !bHasGet
)
814 aInfoCollection
.push_back(SfxResId(STR_PROPERTY_ATTRIBUTE_WRITEONLY
));
816 if (aInvocationInfo
.PropertyAttribute
& beans::PropertyAttribute::MAYBEVOID
)
817 aInfoCollection
.push_back(SfxResId(STR_PROPERTY_ATTRIBUTE_MAYBEVOID
));
818 if (aInvocationInfo
.PropertyAttribute
& beans::PropertyAttribute::READONLY
)
819 aInfoCollection
.push_back(SfxResId(STR_PROPERTY_ATTRIBUTE_READONLY
));
820 if (aInvocationInfo
.PropertyAttribute
& beans::PropertyAttribute::REMOVABLE
)
821 aInfoCollection
.push_back(SfxResId(STR_PROPERTY_ATTRIBUTE_REMOVABLE
));
822 if (aInvocationInfo
.PropertyAttribute
& beans::PropertyAttribute::BOUND
)
823 aInfoCollection
.push_back(SfxResId(STR_PROPERTY_ATTRIBUTE_BOUND
));
824 if (aInvocationInfo
.PropertyAttribute
& beans::PropertyAttribute::CONSTRAINED
)
825 aInfoCollection
.push_back(SfxResId(STR_PROPERTY_ATTRIBUTE_CONSTRAINED
));
826 if (aInvocationInfo
.PropertyAttribute
& beans::PropertyAttribute::TRANSIENT
)
827 aInfoCollection
.push_back(SfxResId(STR_PROPERTY_ATTRIBUTE_TRANSIENT
));
828 if (aInvocationInfo
.PropertyAttribute
& beans::PropertyAttribute::MAYBEAMBIGUOUS
)
829 aInfoCollection
.push_back(SfxResId(STR_PROPERTY_ATTRIBUTE_MAYBEAMBIGUOUS
));
830 if (aInvocationInfo
.PropertyAttribute
& beans::PropertyAttribute::MAYBEDEFAULT
)
831 aInfoCollection
.push_back(SfxResId(STR_PROPERTY_ATTRIBUTE_MAYBEDEFAULT
));
834 OUString aInfoString
;
835 for (auto const& rString
: aInfoCollection
)
842 aInfoString
+= rString
;
845 auto* pObjectInspectorNode
846 = createNodeObjectForAny(aPropertyName
, aCurrentAny
, aInfoString
);
847 if (pObjectInspectorNode
)
848 lclAppendNodeToParent(pTree
, pParent
, pObjectInspectorNode
);
853 void StructNode::fillChildren(std::unique_ptr
<weld::TreeView
>& pTree
, const weld::TreeIter
* pParent
)
855 auto xReflection
= reflection::theCoreReflection::get(mxContext
);
856 uno::Reference
<reflection::XIdlClass
> xClass
857 = xReflection
->forName(maAny
.getValueType().getTypeName());
859 const auto xFields
= xClass
->getFields();
861 for (auto const& xField
: xFields
)
863 OUString aFieldName
= xField
->getName();
864 uno::Any aFieldValue
= xField
->get(maAny
);
866 auto* pObjectInspectorNode
= createNodeObjectForAny(aFieldName
, aFieldValue
, "");
867 if (pObjectInspectorNode
)
869 lclAppendNodeToParent(pTree
, pParent
, pObjectInspectorNode
);
874 ObjectInspectorNodeInterface
* BasicValueNode::createNodeObjectForAny(OUString
const& rName
,
875 const uno::Any
& rAny
,
876 OUString
const& rInfo
)
878 switch (rAny
.getValueType().getTypeClass())
880 case uno::TypeClass_INTERFACE
:
881 return new GenericPropertiesNode(rName
, rAny
, rInfo
, mxContext
);
883 case uno::TypeClass_SEQUENCE
:
884 return new SequenceNode(rName
, rAny
, rInfo
, mxContext
);
886 case uno::TypeClass_STRUCT
:
887 return new StructNode(rName
, rAny
, rInfo
, mxContext
);
893 return new BasicValueNode(rName
, rAny
, rInfo
, mxContext
);
896 } // end anonymous namespace
898 // Object inspector tree view helper functions
901 ObjectInspectorNodeInterface
* getSelectedNode(weld::TreeView
const& rTreeView
)
903 OUString sID
= rTreeView
.get_selected_id();
907 if (auto* pNode
= weld::fromId
<ObjectInspectorNodeInterface
*>(sID
))
913 uno::Reference
<uno::XInterface
> getSelectedXInterface(weld::TreeView
const& rTreeView
)
915 uno::Reference
<uno::XInterface
> xInterface
;
917 if (auto* pNode
= getSelectedNode(rTreeView
))
919 if (auto* pBasicValueNode
= dynamic_cast<BasicValueNode
*>(pNode
))
921 uno::Any aAny
= pBasicValueNode
->getAny();
922 xInterface
.set(aAny
, uno::UNO_QUERY
);
929 } // end anonymous namespace
931 ObjectInspectorTreeHandler::ObjectInspectorTreeHandler(
932 std::unique_ptr
<ObjectInspectorWidgets
>& pObjectInspectorWidgets
)
933 : mpObjectInspectorWidgets(pObjectInspectorWidgets
)
934 , mxContext(comphelper::getProcessComponentContext())
935 , mxSorter(mxContext
, Application::GetSettings().GetLanguageTag().getLocale())
937 mpObjectInspectorWidgets
->mpInterfacesTreeView
->connect_expanding(
938 LINK(this, ObjectInspectorTreeHandler
, ExpandingHandlerInterfaces
));
939 mpObjectInspectorWidgets
->mpServicesTreeView
->connect_expanding(
940 LINK(this, ObjectInspectorTreeHandler
, ExpandingHandlerServices
));
941 mpObjectInspectorWidgets
->mpPropertiesTreeView
->connect_expanding(
942 LINK(this, ObjectInspectorTreeHandler
, ExpandingHandlerProperties
));
943 mpObjectInspectorWidgets
->mpMethodsTreeView
->connect_expanding(
944 LINK(this, ObjectInspectorTreeHandler
, ExpandingHandlerMethods
));
946 mpObjectInspectorWidgets
->mpPropertiesTreeView
->connect_popup_menu(
947 LINK(this, ObjectInspectorTreeHandler
, PopupMenuHandler
));
949 mpObjectInspectorWidgets
->mpInterfacesTreeView
->connect_changed(
950 LINK(this, ObjectInspectorTreeHandler
, SelectionChanged
));
951 mpObjectInspectorWidgets
->mpServicesTreeView
->connect_changed(
952 LINK(this, ObjectInspectorTreeHandler
, SelectionChanged
));
953 mpObjectInspectorWidgets
->mpPropertiesTreeView
->connect_changed(
954 LINK(this, ObjectInspectorTreeHandler
, SelectionChanged
));
955 mpObjectInspectorWidgets
->mpMethodsTreeView
->connect_changed(
956 LINK(this, ObjectInspectorTreeHandler
, SelectionChanged
));
958 mpObjectInspectorWidgets
->mpInterfacesTreeView
->make_sorted();
959 mpObjectInspectorWidgets
->mpServicesTreeView
->make_sorted();
960 mpObjectInspectorWidgets
->mpPropertiesTreeView
->make_sorted();
961 mpObjectInspectorWidgets
->mpMethodsTreeView
->make_sorted();
963 setSortFunction(mpObjectInspectorWidgets
->mpInterfacesTreeView
);
964 setSortFunction(mpObjectInspectorWidgets
->mpServicesTreeView
);
965 setSortFunction(mpObjectInspectorWidgets
->mpPropertiesTreeView
);
966 setSortFunction(mpObjectInspectorWidgets
->mpMethodsTreeView
);
968 mpObjectInspectorWidgets
->mpInterfacesTreeView
->connect_column_clicked(
969 LINK(this, ObjectInspectorTreeHandler
, HeaderBarClick
));
970 mpObjectInspectorWidgets
->mpServicesTreeView
->connect_column_clicked(
971 LINK(this, ObjectInspectorTreeHandler
, HeaderBarClick
));
972 mpObjectInspectorWidgets
->mpPropertiesTreeView
->connect_column_clicked(
973 LINK(this, ObjectInspectorTreeHandler
, HeaderBarClick
));
974 mpObjectInspectorWidgets
->mpMethodsTreeView
->connect_column_clicked(
975 LINK(this, ObjectInspectorTreeHandler
, HeaderBarClick
));
977 mpObjectInspectorWidgets
->mpToolbar
->connect_clicked(
978 LINK(this, ObjectInspectorTreeHandler
, ToolbarButtonClicked
));
979 mpObjectInspectorWidgets
->mpToolbar
->set_item_sensitive("inspect", false);
980 mpObjectInspectorWidgets
->mpToolbar
->set_item_sensitive("back", false);
982 mpObjectInspectorWidgets
->mpNotebook
->connect_leave_page(
983 LINK(this, ObjectInspectorTreeHandler
, NotebookLeavePage
));
984 mpObjectInspectorWidgets
->mpNotebook
->connect_enter_page(
985 LINK(this, ObjectInspectorTreeHandler
, NotebookEnterPage
));
987 auto nPropertiesDigitWidth
988 = mpObjectInspectorWidgets
->mpPropertiesTreeView
->get_approximate_digit_width();
989 std::vector
<int> aPropertiesWidths(4, nPropertiesDigitWidth
* 30);
990 mpObjectInspectorWidgets
->mpPropertiesTreeView
->set_column_fixed_widths(aPropertiesWidths
);
992 auto nMethodsDigitWidth
993 = mpObjectInspectorWidgets
->mpMethodsTreeView
->get_approximate_digit_width();
994 std::vector
<int> aMethodsWidths
{ static_cast<int>(nMethodsDigitWidth
* 30),
995 static_cast<int>(nMethodsDigitWidth
* 15),
996 static_cast<int>(nMethodsDigitWidth
* 30),
997 static_cast<int>(nMethodsDigitWidth
* 50) };
998 mpObjectInspectorWidgets
->mpMethodsTreeView
->set_column_fixed_widths(aMethodsWidths
);
1000 mpObjectInspectorWidgets
->mpPaned
->set_position(160);
1003 void ObjectInspectorTreeHandler::setSortFunction(std::unique_ptr
<weld::TreeView
>& pTreeView
)
1005 pTreeView
->set_sort_func(
1006 [this, &pTreeView
](const weld::TreeIter
& rLeft
, const weld::TreeIter
& rRight
) {
1007 return compare(pTreeView
, rLeft
, rRight
);
1011 sal_Int32
ObjectInspectorTreeHandler::compare(std::unique_ptr
<weld::TreeView
>& pTreeView
,
1012 const weld::TreeIter
& rLeft
,
1013 const weld::TreeIter
& rRight
)
1015 int nSortColumn
= pTreeView
->get_sort_column();
1017 OUString sLeft
= pTreeView
->get_text(rLeft
, nSortColumn
);
1018 OUString sRight
= pTreeView
->get_text(rRight
, nSortColumn
);
1019 sal_Int32 nCompare
= mxSorter
.compare(sLeft
, sRight
);
1023 void ObjectInspectorTreeHandler::handleExpanding(std::unique_ptr
<weld::TreeView
>& pTreeView
,
1024 weld::TreeIter
const& rParent
)
1026 OUString sID
= pTreeView
->get_id(rParent
);
1030 clearObjectInspectorChildren(pTreeView
, rParent
);
1031 auto* pNode
= weld::fromId
<ObjectInspectorNodeInterface
*>(sID
);
1032 pNode
->fillChildren(pTreeView
, &rParent
);
1035 IMPL_LINK(ObjectInspectorTreeHandler
, ExpandingHandlerInterfaces
, weld::TreeIter
const&, rParent
,
1038 handleExpanding(mpObjectInspectorWidgets
->mpInterfacesTreeView
, rParent
);
1042 IMPL_LINK(ObjectInspectorTreeHandler
, ExpandingHandlerServices
, weld::TreeIter
const&, rParent
,
1045 handleExpanding(mpObjectInspectorWidgets
->mpServicesTreeView
, rParent
);
1049 IMPL_LINK(ObjectInspectorTreeHandler
, ExpandingHandlerProperties
, weld::TreeIter
const&, rParent
,
1052 handleExpanding(mpObjectInspectorWidgets
->mpPropertiesTreeView
, rParent
);
1056 IMPL_LINK(ObjectInspectorTreeHandler
, ExpandingHandlerMethods
, weld::TreeIter
const&, rParent
, bool)
1058 handleExpanding(mpObjectInspectorWidgets
->mpMethodsTreeView
, rParent
);
1062 IMPL_LINK(ObjectInspectorTreeHandler
, SelectionChanged
, weld::TreeView
&, rTreeView
, void)
1064 bool bHaveNodeWithObject
= false;
1065 mpObjectInspectorWidgets
->mpTextView
->set_text("");
1066 if (mpObjectInspectorWidgets
->mpPropertiesTreeView
.get() == &rTreeView
)
1068 auto* pNode
= getSelectedNode(rTreeView
);
1069 if (auto* pBasicValueNode
= dynamic_cast<BasicValueNode
*>(pNode
))
1071 uno::Any aAny
= pBasicValueNode
->getAny();
1072 uno::Reference
<uno::XInterface
> xInterface(aAny
, uno::UNO_QUERY
);
1073 bHaveNodeWithObject
= xInterface
.is();
1074 mpObjectInspectorWidgets
->mpTextView
->set_text(convertAnyToString(aAny
, mxContext
));
1078 mpObjectInspectorWidgets
->mpToolbar
->set_item_sensitive("inspect", bHaveNodeWithObject
);
1081 static void updateOrder(const std::unique_ptr
<weld::TreeView
>& pTreeView
, sal_Int32 nColumn
)
1083 pTreeView
->set_sort_column(nColumn
);
1085 bool bSortAtoZ
= pTreeView
->get_sort_order();
1086 pTreeView
->set_sort_order(!bSortAtoZ
);
1087 pTreeView
->set_sort_indicator(!bSortAtoZ
? TRISTATE_TRUE
: TRISTATE_FALSE
, nColumn
);
1090 IMPL_LINK(ObjectInspectorTreeHandler
, HeaderBarClick
, int, nColumn
, void)
1092 auto rPageId
= mpObjectInspectorWidgets
->mpNotebook
->get_current_page_ident();
1094 if (rPageId
== "object_inspector_interfaces_tab")
1095 updateOrder(mpObjectInspectorWidgets
->mpInterfacesTreeView
, nColumn
);
1096 else if (rPageId
== "object_inspector_services_tab")
1097 updateOrder(mpObjectInspectorWidgets
->mpServicesTreeView
, nColumn
);
1098 else if (rPageId
== "object_inspector_properties_tab")
1099 updateOrder(mpObjectInspectorWidgets
->mpPropertiesTreeView
, nColumn
);
1100 else if (rPageId
== "object_inspector_methods_tab")
1101 updateOrder(mpObjectInspectorWidgets
->mpMethodsTreeView
, nColumn
);
1104 IMPL_LINK(ObjectInspectorTreeHandler
, PopupMenuHandler
, const CommandEvent
&, rCommandEvent
, bool)
1106 if (rCommandEvent
.GetCommand() != CommandEventId::ContextMenu
)
1109 auto xInterface
= getSelectedXInterface(*mpObjectInspectorWidgets
->mpPropertiesTreeView
);
1110 if (xInterface
.is())
1112 std::unique_ptr
<weld::Builder
> xBuilder(Application::CreateBuilder(
1113 mpObjectInspectorWidgets
->mpPropertiesTreeView
.get(), "sfx/ui/devtoolsmenu.ui"));
1114 std::unique_ptr
<weld::Menu
> xMenu(xBuilder
->weld_menu("inspect_menu"));
1117 xMenu
->popup_at_rect(mpObjectInspectorWidgets
->mpPropertiesTreeView
.get(),
1118 tools::Rectangle(rCommandEvent
.GetMousePosPixel(), Size(1, 1))));
1120 if (sCommand
== "inspect")
1122 addToStack(uno::Any(xInterface
));
1123 inspectObject(xInterface
);
1129 IMPL_LINK(ObjectInspectorTreeHandler
, ToolbarButtonClicked
, const OUString
&, rSelectionId
, void)
1131 if (rSelectionId
== "inspect")
1133 auto xInterface
= getSelectedXInterface(*mpObjectInspectorWidgets
->mpPropertiesTreeView
);
1134 if (xInterface
.is())
1136 addToStack(uno::Any(xInterface
));
1137 inspectObject(xInterface
);
1140 else if (rSelectionId
== "back")
1142 uno::Any aAny
= popFromStack();
1143 if (aAny
.hasValue())
1145 uno::Reference
<uno::XInterface
> xInterface(aAny
, uno::UNO_QUERY
);
1146 inspectObject(xInterface
);
1149 else if (rSelectionId
== "refresh")
1151 auto rPageId
= mpObjectInspectorWidgets
->mpNotebook
->get_current_page_ident();
1152 NotebookEnterPage(rPageId
);
1156 IMPL_LINK(ObjectInspectorTreeHandler
, NotebookEnterPage
, const OUString
&, rPageId
, void)
1158 uno::Any aAny
= maInspectionStack
.back();
1159 if (!aAny
.hasValue())
1162 uno::Reference
<uno::XInterface
> xInterface(aAny
, uno::UNO_QUERY
);
1163 if (rPageId
== "object_inspector_interfaces_tab")
1165 mpObjectInspectorWidgets
->mpInterfacesTreeView
->freeze();
1166 clearAll(mpObjectInspectorWidgets
->mpInterfacesTreeView
);
1167 appendInterfaces(xInterface
);
1168 mpObjectInspectorWidgets
->mpInterfacesTreeView
->thaw();
1170 else if (rPageId
== "object_inspector_services_tab")
1172 mpObjectInspectorWidgets
->mpServicesTreeView
->freeze();
1173 clearAll(mpObjectInspectorWidgets
->mpServicesTreeView
);
1174 appendServices(xInterface
);
1175 mpObjectInspectorWidgets
->mpServicesTreeView
->thaw();
1177 else if (rPageId
== "object_inspector_properties_tab")
1179 mpObjectInspectorWidgets
->mpPropertiesTreeView
->freeze();
1180 clearAll(mpObjectInspectorWidgets
->mpPropertiesTreeView
);
1181 appendProperties(xInterface
);
1182 mpObjectInspectorWidgets
->mpPropertiesTreeView
->thaw();
1184 else if (rPageId
== "object_inspector_methods_tab")
1186 mpObjectInspectorWidgets
->mpMethodsTreeView
->freeze();
1187 clearAll(mpObjectInspectorWidgets
->mpMethodsTreeView
);
1188 appendMethods(xInterface
);
1189 mpObjectInspectorWidgets
->mpMethodsTreeView
->thaw();
1193 IMPL_LINK(ObjectInspectorTreeHandler
, NotebookLeavePage
, const OUString
&, rPageId
, bool)
1195 if (rPageId
== "object_inspector_interfaces_tab")
1197 mpObjectInspectorWidgets
->mpInterfacesTreeView
->freeze();
1198 clearAll(mpObjectInspectorWidgets
->mpInterfacesTreeView
);
1199 mpObjectInspectorWidgets
->mpInterfacesTreeView
->thaw();
1201 else if (rPageId
== "object_inspector_services_tab")
1203 mpObjectInspectorWidgets
->mpServicesTreeView
->freeze();
1204 clearAll(mpObjectInspectorWidgets
->mpServicesTreeView
);
1205 mpObjectInspectorWidgets
->mpServicesTreeView
->thaw();
1207 else if (rPageId
== "object_inspector_properties_tab")
1209 mpObjectInspectorWidgets
->mpPropertiesTreeView
->freeze();
1210 clearAll(mpObjectInspectorWidgets
->mpPropertiesTreeView
);
1211 mpObjectInspectorWidgets
->mpPropertiesTreeView
->thaw();
1213 else if (rPageId
== "object_inspector_methods_tab")
1215 mpObjectInspectorWidgets
->mpMethodsTreeView
->freeze();
1216 clearAll(mpObjectInspectorWidgets
->mpMethodsTreeView
);
1217 mpObjectInspectorWidgets
->mpMethodsTreeView
->thaw();
1222 void ObjectInspectorTreeHandler::clearObjectInspectorChildren(
1223 std::unique_ptr
<weld::TreeView
>& pTreeView
, weld::TreeIter
const& rParent
)
1225 bool bChild
= false;
1228 bChild
= pTreeView
->iter_has_child(rParent
);
1231 std::unique_ptr
<weld::TreeIter
> pChild
= pTreeView
->make_iterator(&rParent
);
1232 bChild
= pTreeView
->iter_children(*pChild
);
1235 clearObjectInspectorChildren(pTreeView
, *pChild
);
1236 OUString sID
= pTreeView
->get_id(*pChild
);
1237 auto* pEntry
= weld::fromId
<ObjectInspectorNodeInterface
*>(sID
);
1239 pTreeView
->remove(*pChild
);
1245 /** Deletes all the node objects in a tree view */
1246 void ObjectInspectorTreeHandler::clearAll(std::unique_ptr
<weld::TreeView
>& pTreeView
)
1248 // destroy all ObjectInspectorNodes from the tree
1249 pTreeView
->all_foreach([&pTreeView
](weld::TreeIter
& rEntry
) {
1250 OUString sID
= pTreeView
->get_id(rEntry
);
1251 auto* pEntry
= weld::fromId
<ObjectInspectorNodeInterface
*>(sID
);
1258 /** Append interfaces to the "interfaces" tree view */
1259 void ObjectInspectorTreeHandler::appendInterfaces(uno::Reference
<uno::XInterface
> const& xInterface
)
1261 if (!xInterface
.is())
1264 uno::Reference
<lang::XTypeProvider
> xTypeProvider(xInterface
, uno::UNO_QUERY
);
1265 if (xTypeProvider
.is())
1267 const auto xSequenceTypes
= xTypeProvider
->getTypes();
1268 for (auto const& xType
: xSequenceTypes
)
1270 auto xClass
= convertTypeToIdlClass(xType
, mxContext
);
1271 lclAppendNode(mpObjectInspectorWidgets
->mpInterfacesTreeView
, new ClassNode(xClass
));
1276 /** Append services to the "services" tree view */
1277 void ObjectInspectorTreeHandler::appendServices(uno::Reference
<uno::XInterface
> const& xInterface
)
1279 if (!xInterface
.is())
1282 auto xServiceInfo
= uno::Reference
<lang::XServiceInfo
>(xInterface
, uno::UNO_QUERY
);
1283 const uno::Sequence
<OUString
> aServiceNames(xServiceInfo
->getSupportedServiceNames());
1284 for (auto const& aServiceName
: aServiceNames
)
1286 lclAppendNode(mpObjectInspectorWidgets
->mpServicesTreeView
,
1287 new SimpleStringNode(aServiceName
));
1291 /** Append properties to the "properties" tree view */
1292 void ObjectInspectorTreeHandler::appendProperties(uno::Reference
<uno::XInterface
> const& xInterface
)
1294 if (!xInterface
.is())
1296 GenericPropertiesNode
aNode("", uno::Any(xInterface
), "", mxContext
);
1297 aNode
.fillChildren(mpObjectInspectorWidgets
->mpPropertiesTreeView
, nullptr);
1300 /** Append methods to the "methods" tree view */
1301 void ObjectInspectorTreeHandler::appendMethods(uno::Reference
<uno::XInterface
> const& xInterface
)
1303 if (!xInterface
.is())
1306 uno::Reference
<beans::XIntrospection
> xIntrospection
= beans::theIntrospection::get(mxContext
);
1307 auto xIntrospectionAccess
= xIntrospection
->inspect(uno::Any(xInterface
));
1309 const auto xMethods
= xIntrospectionAccess
->getMethods(beans::MethodConcept::ALL
);
1310 for (auto const& xMethod
: xMethods
)
1312 lclAppendNode(mpObjectInspectorWidgets
->mpMethodsTreeView
, new MethodNode(xMethod
));
1316 // Update the back button state depending if there are objects in the stack
1317 void ObjectInspectorTreeHandler::updateBackButtonState()
1319 mpObjectInspectorWidgets
->mpToolbar
->set_item_sensitive("back", maInspectionStack
.size() > 1);
1322 // Clears all the objects from the stack
1323 void ObjectInspectorTreeHandler::clearStack()
1325 maInspectionStack
.clear();
1326 updateBackButtonState();
1329 // Adds an object to the stack
1330 void ObjectInspectorTreeHandler::addToStack(css::uno::Any
const& rAny
)
1332 maInspectionStack
.push_back(rAny
);
1333 updateBackButtonState();
1336 // Removes an object from the back of the stack and return it
1337 css::uno::Any
ObjectInspectorTreeHandler::popFromStack()
1339 maInspectionStack
.pop_back();
1340 uno::Any aAny
= maInspectionStack
.back();
1341 updateBackButtonState();
1345 // Inspect the input object in the object inspector
1346 void ObjectInspectorTreeHandler::inspectObject(uno::Reference
<uno::XInterface
> const& xInterface
)
1348 if (!xInterface
.is())
1351 // Set implementation name
1352 OUString aImplementationName
= getInterfaceImplementationClass(xInterface
);
1353 mpObjectInspectorWidgets
->mpClassNameLabel
->set_label(aImplementationName
);
1354 sal_Int32 nStrLen
= aImplementationName
.getLength();
1355 sal_Int32 nDigitWidth
1356 = mpObjectInspectorWidgets
->mpClassNameLabel
->get_approximate_digit_width();
1358 //get_about_digit_width() returns an approximate value. To always see the full class name (nStrLen+2)
1359 mpObjectInspectorWidgets
->mpClassNameLabel
->set_size_request((nStrLen
+ 2) * nDigitWidth
, -1);
1361 // Fire entering the current opened page manually
1362 auto rPageId
= mpObjectInspectorWidgets
->mpNotebook
->get_current_page_ident();
1363 NotebookEnterPage(rPageId
);
1366 // Inspect the input object in the object inspector.
1367 // Make the input object the root of the stack (clear all other
1368 // objects from the stack).
1369 void ObjectInspectorTreeHandler::introspect(uno::Reference
<uno::XInterface
> const& xInterface
)
1372 addToStack(uno::Any(xInterface
));
1373 inspectObject(xInterface
);
1376 void ObjectInspectorTreeHandler::dispose()
1378 // We need to clear all the nodes
1379 clearAll(mpObjectInspectorWidgets
->mpInterfacesTreeView
);
1380 clearAll(mpObjectInspectorWidgets
->mpServicesTreeView
);
1381 clearAll(mpObjectInspectorWidgets
->mpPropertiesTreeView
);
1382 clearAll(mpObjectInspectorWidgets
->mpMethodsTreeView
);
1385 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */