/* -*- 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/. *
*/
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)
{
OUString aRetStr;
// return early if we don't have any value if (!aValue.hasValue()) return SfxResId(STR_ANY_VALUE_NULL);
switch (eType)
{ case uno::TypeClass_BOOLEAN:
{ bool bBool = aValue.get<bool>();
aRetStr = bBool ? SfxResId(STR_ANY_VALUE_TRUE) : SfxResId(STR_ANY_VALUE_FALSE); break;
} case uno::TypeClass_CHAR:
{
sal_Unicode aChar = aValue.get<sal_Unicode>();
aRetStr = OUString::number(aChar); break;
} case uno::TypeClass_STRING:
{
aRetStr = u"\"" + aValue.get() + u"\""; 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;
} 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;
} case uno::TypeClass_TYPE:
{ auto aType = aValue.get<uno::Type>();
aRetStr = aType.getTypeName(); break;
} case uno::TypeClass_ENUM:
{
aRetStr = enumValueToEnumName(aValue, xContext); break;
}
default: break;
} return aRetStr;
}
// 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); if (xInvocation.is() && xInvocation->hasProperty(u"Name"_ustr))
{
uno::Any aAny = xInvocation->getValue(u"Name"_ustr); 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 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);
/** converts an any's type to a string (in a short form) */
OUString getAnyType(const uno::Any& aValue)
{
OUString aTypeName = aValue.getValueTypeName(); return aTypeName.replaceAll("com.sun.star", "css");
}
/** converts a Type to a XIdlClass */
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());
}
// Object inspector nodes
/** 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. *
*/ class ObjectInspectorNodeInterface
{ public:
ObjectInspectorNodeInterface() = default;
virtual ~ObjectInspectorNodeInterface() {}
// main value (object name) of the tree view node virtual OUString getObjectName() = 0;
// should show the expander for the tree view node virtualbool shouldShowExpander() { returnfalse; }
// fill the children for the current tree view node virtualvoid fillChildren(std::unique_ptr<weld::TreeView>& rTree, const weld::TreeIter* pParent)
= 0;
// fill any additional column values for the current tree view node virtual std::vector<std::pair<sal_Int32, OUString>> getColumnValues()
{ return std::vector<std::pair<sal_Int32, OUString>>();
}
};
// appends the node to the root of the tree view void lclAppendNode(const std::unique_ptr<weld::TreeView>& pTree,
ObjectInspectorNodeInterface* pEntry)
{
OUString sName = pEntry->getObjectName();
OUString sId(weld::toId(pEntry));
std::unique_ptr<weld::TreeIter> pCurrent = pTree->make_iterator();
pTree->insert(nullptr, -1, &sName, &sId, nullptr, nullptr, pEntry->shouldShowExpander(),
pCurrent.get());
pTree->set_text_emphasis(*pCurrent, true, 0);
/** Node that represent just a simple string with no children or columns */ class SimpleStringNode : public ObjectInspectorNodeInterface
{ protected:
OUString msName;
/** Node represents a method of an object */ class MethodNode : public ObjectInspectorNodeInterface
{ private:
uno::Reference<reflection::XIdlMethod> mxMethod;
/** Node represents a class (XIdlClass) of an object. * * Children are superclasses of the current class. XInterface superclass * is ignored. *
*/ class ClassNode : public ObjectInspectorNodeInterface
{ private:
uno::Reference<reflection::XIdlClass> mxClass;
// Fill superclasses void fillChildren(std::unique_ptr<weld::TreeView>& rTree, const weld::TreeIter* pParent) override
{ autoconst xSuperClasses = mxClass->getSuperclasses(); for (autoconst& xSuper : xSuperClasses)
{ if (!isXInterface(xSuper))
lclAppendNodeToParent(rTree, pParent, new ClassNode(xSuper));
}
}
};
/** Node represents a basic value, that can be any object, sequence, struct */ class BasicValueNode : public SimpleStringNode
{ protected:
uno::Any maAny;
OUString mrInfo;
uno::Reference<uno::XComponentContext> mxContext;
/** Deletes all the node objects in a tree view */ void ObjectInspectorTreeHandler::clearAll(std::unique_ptr<weld::TreeView>& pTreeView)
{ // destroy all ObjectInspectorNodes from the tree
pTreeView->all_foreach([&pTreeView](weld::TreeIter& rEntry) {
OUString sID = pTreeView->get_id(rEntry); auto* pEntry = weld::fromId<ObjectInspectorNodeInterface*>(sID); delete pEntry; returnfalse;
});
pTreeView->clear();
}
/** Append interfaces to the "interfaces" tree view */ void ObjectInspectorTreeHandler::appendInterfaces(uno::Reference<uno::XInterface> const& xInterface)
{ if (!xInterface.is()) return;
uno::Reference<lang::XTypeProvider> xTypeProvider(xInterface, uno::UNO_QUERY); if (xTypeProvider.is())
{ constauto xSequenceTypes = xTypeProvider->getTypes(); for (autoconst& xType : xSequenceTypes)
{ auto xClass = convertTypeToIdlClass(xType, mxContext);
lclAppendNode(mpObjectInspectorWidgets->mpInterfacesTreeView, new ClassNode(xClass));
}
}
}
/** Append services to the "services" tree view */ void ObjectInspectorTreeHandler::appendServices(uno::Reference<uno::XInterface> const& xInterface)
{ if (!xInterface.is()) return;
auto xServiceInfo = uno::Reference<lang::XServiceInfo>(xInterface, uno::UNO_QUERY); if (!xServiceInfo) return;
const uno::Sequence<OUString> aServiceNames(xServiceInfo->getSupportedServiceNames()); for (autoconst& aServiceName : aServiceNames)
{
lclAppendNode(mpObjectInspectorWidgets->mpServicesTreeView, new SimpleStringNode(aServiceName));
}
}
/** Append properties to the "properties" tree view */ void ObjectInspectorTreeHandler::appendProperties(uno::Reference<uno::XInterface> const& xInterface)
{ if (!xInterface.is()) return;
GenericPropertiesNode aNode(u""_ustr, uno::Any(xInterface), u""_ustr, mxContext);
aNode.fillChildren(mpObjectInspectorWidgets->mpPropertiesTreeView, nullptr);
}
/** Append methods to the "methods" tree view */ void ObjectInspectorTreeHandler::appendMethods(uno::Reference<uno::XInterface> const& xInterface)
{ if (!xInterface.is()) return;
uno::Reference<beans::XIntrospection> xIntrospection = beans::theIntrospection::get(mxContext); auto xIntrospectionAccess = xIntrospection->inspect(uno::Any(xInterface));
constauto xMethods = xIntrospectionAccess->getMethods(beans::MethodConcept::ALL); for (autoconst& xMethod : xMethods)
{
lclAppendNode(mpObjectInspectorWidgets->mpMethodsTreeView, new MethodNode(xMethod));
}
}
// Update the back button state depending if there are objects in the stack void ObjectInspectorTreeHandler::updateBackButtonState()
{
mpObjectInspectorWidgets->mpToolbar->set_item_sensitive(u"back"_ustr,
maInspectionStack.size() > 1);
}
// Clears all the objects from the stack void ObjectInspectorTreeHandler::clearStack()
{
maInspectionStack.clear();
updateBackButtonState();
}
// Adds an object to the stack void ObjectInspectorTreeHandler::addToStack(css::uno::Any const& rAny)
{
maInspectionStack.push_back(rAny);
updateBackButtonState();
}
// Removes an object from the back of the stack and return it
css::uno::Any ObjectInspectorTreeHandler::popFromStack()
{
maInspectionStack.pop_back();
uno::Any aAny = maInspectionStack.back();
updateBackButtonState(); return aAny;
}
// Inspect the input object in the object inspector void ObjectInspectorTreeHandler::inspectObject(uno::Reference<uno::XInterface> const& xInterface)
{ if (!xInterface.is()) return;
// Set implementation name
OUString aImplementationName = getInterfaceImplementationClass(xInterface);
mpObjectInspectorWidgets->mpClassNameLabel->set_label(aImplementationName);
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);
// Fire entering the current opened page manually auto rPageId = mpObjectInspectorWidgets->mpNotebook->get_current_page_ident();
NotebookEnterPage(rPageId);
}
// Inspect the input object in the object inspector. // Make the input object the root of the stack (clear all other // objects from the stack). void ObjectInspectorTreeHandler::introspect(uno::Reference<uno::XInterface> const& xInterface)
{
clearStack();
addToStack(uno::Any(xInterface));
inspectObject(xInterface);
}
void ObjectInspectorTreeHandler::dispose()
{ // We need to clear all the nodes
clearAll(mpObjectInspectorWidgets->mpInterfacesTreeView);
clearAll(mpObjectInspectorWidgets->mpServicesTreeView);
clearAll(mpObjectInspectorWidgets->mpPropertiesTreeView);
clearAll(mpObjectInspectorWidgets->mpMethodsTreeView);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.