1 /**************************************************************************
3 ** This file is part of Qt Creator
5 ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
7 ** Contact: Nokia Corporation (info@qt.nokia.com)
10 ** GNU Lesser General Public License Usage
12 ** This file may be used under the terms of the GNU Lesser General Public
13 ** License version 2.1 as published by the Free Software Foundation and
14 ** appearing in the file LICENSE.LGPL included in the packaging of this file.
15 ** Please review the following information to ensure the GNU Lesser General
16 ** Public License version 2.1 requirements will be met:
17 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
19 ** In addition, as a special exception, Nokia gives you certain additional
20 ** rights. These rights are described in the Nokia Qt LGPL Exception
21 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
25 ** Alternatively, this file may be used in accordance with the terms and
26 ** conditions contained in a signed written agreement between you and Nokia.
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
31 **************************************************************************/
33 #include "nodemetainfo.h"
35 #include "widgetqueryview.h"
36 #include "invalidargumentexception.h"
40 #include <rewriterview.h>
42 #include <QSharedData>
45 #include <QDeclarativeContext>
46 #include <QDeclarativeEngine>
47 #include <QDeclarativeComponent>
49 #include <qmljs/qmljslookupcontext.h>
50 #include <qmljs/qmljsdocument.h>
51 #include <qmljs/qmljsinterpreter.h>
52 #include <qmljs/qmljsbind.h>
53 #include <qmljs/parser/qmljsast_p.h>
54 #include <languageutils/fakemetaobject.h>
55 #include <private/qdeclarativemetatype_p.h>
56 #include <private/qdeclarativestringconverters_p.h>
58 namespace QmlDesigner {
62 struct TypeDescription
72 \class QmlDesigner::NodeMetaInfo
74 \brief The NodeMetaInfo class provides meta information about a qml type.
76 A NodeMetaInfo object can be created via ModelNode::metaInfo, or MetaInfo::nodeMetaInfo.
78 The object can be invalid - you can check this by calling isValid().
79 The object is invalid if you ask for meta information for
80 an non-existing qml property. Also the node meta info can become invalid
81 if the enclosing type is deregistered from the meta type system (e.g.
82 a sub component qml file is deleted). Trying to call any accessor methods on an invalid
83 NodeMetaInfo object will result in an InvalidMetaInfoException being thrown.
85 \see QmlDesigner::MetaInfo, QmlDesigner::PropertyMetaInfo, QmlDesigner::EnumeratorMetaInfo
90 using namespace QmlJS;
92 typedef QPair<QString, QString> PropertyInfo;
94 class PropertyMemberProcessor : public Interpreter::MemberProcessor
97 virtual bool processProperty(const QString &name, const Interpreter::Value *value)
99 const Interpreter::ASTPropertyReference *ref = dynamic_cast<const Interpreter::ASTPropertyReference*>(value);
101 QString type = "unknown";
102 if (ref->ast()->memberType)
103 type = ref->ast()->memberType->asString();
104 m_properties.append(qMakePair(name, type));
106 if (const Interpreter::QmlObjectValue * ov = dynamic_cast<const Interpreter::QmlObjectValue *>(value)) {
107 QString qualifiedTypeName = ov->packageName().isEmpty() ? ov->className() : ov->packageName() + '.' + ov->className();
108 m_properties.append(qMakePair(name, qualifiedTypeName));
110 Interpreter::TypeId typeId;
111 QString typeName = typeId(value);
112 if (typeName == QLatin1String("number")) {
113 if (value->asRealValue()) {
119 m_properties.append(qMakePair(name, typeName));
125 QList<PropertyInfo> properties() const { return m_properties; }
128 QList<PropertyInfo> m_properties;
131 static inline bool isValueType(const QString &type)
133 QStringList objectValuesList;
134 objectValuesList << "QFont" << "QPoint" << "QPointF" << "QSize" << "QSizeF" << "QVector3D" << "QVector2D";
135 return objectValuesList.contains(type);
138 const Interpreter::QmlObjectValue *findQmlPrototype(const Interpreter::ObjectValue *ov, LookupContext *context)
143 const Interpreter::QmlObjectValue * qmlValue = dynamic_cast<const Interpreter::QmlObjectValue *>(ov);
147 return findQmlPrototype(ov->prototype(context->context()), context);
150 QStringList prototypes(const Interpreter::ObjectValue *ov, LookupContext::Ptr context, bool versions = false)
155 ov = ov->prototype(context->context());
157 const Interpreter::QmlObjectValue * qmlValue = dynamic_cast<const Interpreter::QmlObjectValue *>(ov);
160 list << qmlValue->packageName() + '.' + qmlValue->className() +
161 ' ' + QString::number(qmlValue->version().majorVersion()) +
162 '.' + QString::number(qmlValue->version().minorVersion());
164 list << qmlValue->packageName() + "." + qmlValue->className();
168 list << ov->className() + " -1.-1";
170 list << ov->className();
173 ov = ov->prototype(context->context());
178 QList<PropertyInfo> getObjectTypes(const Interpreter::ObjectValue *ov, LookupContext *context, bool local = false);
180 QList<PropertyInfo> getQmlTypes(const Interpreter::QmlObjectValue *ov, LookupContext *context, bool local = false)
182 QList<PropertyInfo> list;
186 PropertyMemberProcessor processor;
187 ov->processMembers(&processor);
189 QList<PropertyInfo> newList = processor.properties();
191 foreach (PropertyInfo property, newList) {
192 QString name = property.first;
193 if (!ov->isWritable(name) && ov->isPointer(name)) {
195 const Interpreter::QmlObjectValue * qmlValue = dynamic_cast<const Interpreter::QmlObjectValue *>(ov->property(name, context->context()));
197 QList<PropertyInfo> dotProperties = getQmlTypes(qmlValue, context);
198 foreach (const PropertyInfo &propertyInfo, dotProperties) {
199 QString dotName = propertyInfo.first;
200 QString type = propertyInfo.second;
201 dotName = name + '.' + dotName;
202 list.append(qMakePair(dotName, type));
206 if (isValueType(ov->propertyType(name))) {
207 const Interpreter::ObjectValue *dotObjectValue = dynamic_cast<const Interpreter::ObjectValue *>(ov->property(name, context->context()));
208 if (dotObjectValue) {
209 QList<PropertyInfo> dotProperties = getObjectTypes(dotObjectValue, context);
210 foreach (const PropertyInfo &propertyInfo, dotProperties) {
211 QString dotName = propertyInfo.first;
212 QString type = propertyInfo.second;
213 dotName = name + '.' + dotName;
214 list.append(qMakePair(dotName, type));
218 QString type = property.second;
219 if (!ov->isPointer(name) && !ov->isListProperty(name))
220 type = ov->propertyType(name);
221 list.append(qMakePair(name, type));
225 const Interpreter::ObjectValue* prototype = ov->prototype(context->context());
227 const Interpreter::QmlObjectValue * qmlObjectValue = dynamic_cast<const Interpreter::QmlObjectValue *>(prototype);
229 if (qmlObjectValue) {
230 list << getQmlTypes(qmlObjectValue, context);
232 list << getObjectTypes(prototype, context);
239 QList<PropertyInfo> getTypes(const Interpreter::ObjectValue *ov, LookupContext *context, bool local = false)
241 QList<PropertyInfo> list;
243 const Interpreter::QmlObjectValue * qmlObjectValue = dynamic_cast<const Interpreter::QmlObjectValue *>(ov);
245 if (qmlObjectValue) {
246 list << getQmlTypes(qmlObjectValue, context, local);
248 list << getObjectTypes(ov, context, local);
254 QList<PropertyInfo> getObjectTypes(const Interpreter::ObjectValue *ov, LookupContext *context, bool local)
256 QList<PropertyInfo> list;
259 PropertyMemberProcessor processor;
260 ov->processMembers(&processor);
262 list << processor.properties();
265 const Interpreter::ObjectValue* prototype = ov->prototype(context->context());
267 const Interpreter::QmlObjectValue * qmlObjectValue = dynamic_cast<const Interpreter::QmlObjectValue *>(prototype);
269 if (qmlObjectValue) {
270 list << getQmlTypes(qmlObjectValue, context);
272 list << getObjectTypes(prototype, context);
279 class NodeMetaInfoPrivate
282 typedef QSharedPointer<NodeMetaInfoPrivate> Pointer;
283 NodeMetaInfoPrivate();
284 ~NodeMetaInfoPrivate() {}
286 bool isValid() const;
288 bool isComponent() const
290 return m_isComponent;
293 QStringList properties() const
298 QStringList localProperties() const
300 return m_localProperties;
303 QString defaultPropertyName() const
305 return m_defaultPropertyName;
308 QString propertyType(const QString &propertyName) const;
310 void setupPrototypes();
311 QList<TypeDescription> prototypes() const;
313 bool isPropertyWritable(const QString &propertyName) const;
314 bool isPropertyPointer(const QString &propertyName) const;
315 bool isPropertyList(const QString &propertyName) const;
316 bool isPropertyEnum(const QString &propertyName) const;
317 QString propertyEnumScope(const QString &propertyName) const;
318 QStringList keysForEnum(const QString &enumName) const;
319 bool cleverCheckType(const QString &otherType) const;
320 QVariant::Type variantTypeId(const QString &properyName) const;
322 int majorVersion() const
323 { return m_majorVersion; }
325 int minorVersion() const
326 { return m_minorVersion; }
328 QString qualfiedTypeName() const
329 { return m_qualfiedTypeName; }
334 QString packageName() const;
336 QString componentSource() const;
337 QString componentFileName() const;
339 static Pointer create(Model *model, const QString &type, int maj = -1, int min = -1);
341 QSet<QString> &prototypeCachePositives()
343 return m_prototypeCachePositives;
346 QSet<QString> &prototypeCacheNegatives()
348 return m_prototypeCacheNegatives;
351 static void clearCache()
353 m_nodeMetaInfoCache.clear();
357 NodeMetaInfoPrivate(Model *model, QString type, int maj = -1, int min = -1);
359 const QmlJS::Interpreter::QmlObjectValue *getQmlObjectValue() const;
360 const QmlJS::Interpreter::ObjectValue *getObjectValue() const;
361 void setupPropertyInfo(QList<PropertyInfo> propertyInfos);
362 void setupLocalPropertyInfo(QList<PropertyInfo> propertyInfos);
363 QString lookupName() const;
364 QStringList lookupNameComponent() const;
365 const QmlJS::Interpreter::QmlObjectValue *getNearestQmlObjectValue() const;
367 QString m_qualfiedTypeName;
372 QStringList m_properties;
373 QStringList m_propertyTypes;
374 QStringList m_localProperties;
375 QString m_defaultPropertyName;
376 QList<TypeDescription> m_prototypes;
377 QSet<QString> m_prototypeCachePositives;
378 QSet<QString> m_prototypeCacheNegatives;
380 //storing the pointer would not be save
381 QmlJS::LookupContext *lookupContext() const;
382 QmlJS::Document *document() const;
384 QPointer<Model> m_model;
385 static QHash<QString, Pointer> m_nodeMetaInfoCache;
388 QHash<QString, NodeMetaInfoPrivate::Pointer> NodeMetaInfoPrivate::m_nodeMetaInfoCache;
391 static inline QString stringIdentifier( const QString &type, int maj, int min)
393 return type + QString::number(maj) + '_' + QString::number(min);
396 NodeMetaInfoPrivate::Pointer NodeMetaInfoPrivate::create(Model *model, const QString &type, int maj, int min)
398 if (m_nodeMetaInfoCache.contains(stringIdentifier(type, maj, min))) {
399 const Pointer &info = m_nodeMetaInfoCache.value(stringIdentifier(type, maj, min));
400 if (info->model() == model) {
403 m_nodeMetaInfoCache.clear();
407 Pointer newData(new NodeMetaInfoPrivate(model, type, maj, min));
408 if (newData->isValid())
409 m_nodeMetaInfoCache.insert(stringIdentifier(type, maj, min), newData);
413 NodeMetaInfoPrivate::NodeMetaInfoPrivate() : m_isValid(false)
418 NodeMetaInfoPrivate::NodeMetaInfoPrivate(Model *model, QString type, int maj, int min) :
419 m_qualfiedTypeName(type), m_majorVersion(maj),
420 m_minorVersion(min), m_isValid(false), m_isComponent(false),
423 if (lookupContext()) {
424 const Interpreter::QmlObjectValue *objectValue = getQmlObjectValue();
426 setupPropertyInfo(getTypes(objectValue, lookupContext()));
427 setupLocalPropertyInfo(getTypes(objectValue, lookupContext(), true));
428 m_defaultPropertyName = objectValue->defaultPropertyName();
432 m_qualfiedTypeName = m_qualfiedTypeName.split('.').last();
433 const Interpreter::ObjectValue *objectValue = getObjectValue();
435 const Interpreter::QmlObjectValue *qmlValue = dynamic_cast<const Interpreter::QmlObjectValue *>(objectValue);
437 m_majorVersion = qmlValue->version().majorVersion();
438 m_minorVersion = qmlValue->version().minorVersion();
439 m_qualfiedTypeName = qmlValue->packageName() + '.' + qmlValue->className();
441 m_isComponent = true;
443 setupPropertyInfo(getTypes(objectValue, lookupContext()));
444 setupLocalPropertyInfo(getTypes(objectValue, lookupContext(), true));
445 m_defaultPropertyName = lookupContext()->context()->defaultPropertyName(objectValue);
453 const QmlJS::Interpreter::QmlObjectValue *NodeMetaInfoPrivate::getQmlObjectValue() const
455 return lookupContext()->engine()->cppQmlTypes().typeByQualifiedName(lookupName());
458 const QmlJS::Interpreter::ObjectValue *NodeMetaInfoPrivate::getObjectValue() const
460 return lookupContext()->context()->lookupType(document(), lookupNameComponent());
463 QmlJS::LookupContext *NodeMetaInfoPrivate::lookupContext() const
465 if (m_model && m_model->rewriterView()) {
466 return m_model->rewriterView()->lookupContext();
471 QmlJS::Document *NodeMetaInfoPrivate::document() const
473 if (m_model && m_model->rewriterView()) {
474 return m_model->rewriterView()->document();
479 void NodeMetaInfoPrivate::setupLocalPropertyInfo(QList<PropertyInfo> localPropertyInfos)
481 foreach (const PropertyInfo &propertyInfo, localPropertyInfos) {
482 m_localProperties.append(propertyInfo.first);
486 void NodeMetaInfoPrivate::setupPropertyInfo(QList<PropertyInfo> propertyInfos)
488 foreach (const PropertyInfo &propertyInfo, propertyInfos) {
489 m_properties.append(propertyInfo.first);
490 m_propertyTypes.append(propertyInfo.second);
494 bool NodeMetaInfoPrivate::isPropertyWritable(const QString &propertyName) const
499 if (propertyName.contains('.')) {
500 const QStringList parts = propertyName.split('.');
501 const QString objectName = parts.first();
502 const QString rawPropertyName = parts.last();
503 const QString objectType = propertyType(objectName);
505 if (isValueType(objectType)) {
509 QSharedPointer<NodeMetaInfoPrivate> objectInfo(create(m_model, objectType));
510 if (objectInfo->isValid())
511 return objectInfo->isPropertyWritable(rawPropertyName);
516 const QmlJS::Interpreter::QmlObjectValue *qmlObjectValue = getNearestQmlObjectValue();
519 if (qmlObjectValue->hasProperty(propertyName))
520 return qmlObjectValue->isWritable(propertyName);
522 return true; //all properties of components are writable
526 bool NodeMetaInfoPrivate::isPropertyList(const QString &propertyName) const
531 if (propertyName.contains('.')) {
532 const QStringList parts = propertyName.split('.');
533 const QString objectName = parts.first();
534 const QString rawPropertyName = parts.last();
535 const QString objectType = propertyType(objectName);
537 if (isValueType(objectType)) {
541 QSharedPointer<NodeMetaInfoPrivate> objectInfo(create(m_model, objectType));
542 if (objectInfo->isValid())
543 return objectInfo->isPropertyList(rawPropertyName);
548 const QmlJS::Interpreter::QmlObjectValue *qmlObjectValue = getNearestQmlObjectValue();
551 return qmlObjectValue->isListProperty(propertyName);
554 bool NodeMetaInfoPrivate::isPropertyPointer(const QString &propertyName) const
559 if (propertyName.contains('.')) {
560 const QStringList parts = propertyName.split('.');
561 const QString objectName = parts.first();
562 const QString rawPropertyName = parts.last();
563 const QString objectType = propertyType(objectName);
565 if (isValueType(objectType)) {
569 QSharedPointer<NodeMetaInfoPrivate> objectInfo(create(m_model, objectType));
570 if (objectInfo->isValid())
571 return objectInfo->isPropertyPointer(rawPropertyName);
576 const QmlJS::Interpreter::QmlObjectValue *qmlObjectValue = getNearestQmlObjectValue();
579 return qmlObjectValue->isPointer(propertyName);
582 bool NodeMetaInfoPrivate::isPropertyEnum(const QString &propertyName) const
587 if (propertyName.contains('.')) {
588 const QStringList parts = propertyName.split('.');
589 const QString objectName = parts.first();
590 const QString rawPropertyName = parts.last();
591 const QString objectType = propertyType(objectName);
593 if (isValueType(objectType)) {
597 QSharedPointer<NodeMetaInfoPrivate> objectInfo(create(m_model, objectType));
598 if (objectInfo->isValid())
599 return objectInfo->isPropertyEnum(rawPropertyName);
604 QList<const Interpreter::ObjectValue *> objects;
605 objects = Interpreter::PrototypeIterator(getNearestQmlObjectValue(), lookupContext()->context()).all();
607 //We have to run the prototype chain
608 foreach (const Interpreter::ObjectValue *ov, objects) {
609 if (const Interpreter::QmlObjectValue * qmlValue = dynamic_cast<const Interpreter::QmlObjectValue *>(ov)) {
610 if (qmlValue->isEnum(propertyType(propertyName)))
618 QString NodeMetaInfoPrivate::propertyEnumScope(const QString &propertyName) const
623 if (propertyName.contains('.')) {
624 const QStringList parts = propertyName.split('.');
625 const QString objectName = parts.first();
626 const QString rawPropertyName = parts.last();
627 const QString objectType = propertyType(objectName);
629 if (isValueType(objectType)) {
633 QSharedPointer<NodeMetaInfoPrivate> objectInfo(create(m_model, objectType));
634 if (objectInfo->isValid())
635 return objectInfo->propertyEnumScope(rawPropertyName);
640 QList<const Interpreter::ObjectValue *> objects;
641 objects = Interpreter::PrototypeIterator(getNearestQmlObjectValue(), lookupContext()->context()).all();
643 //We have to run the prototype chain
644 foreach (const Interpreter::ObjectValue *ov, objects) {
645 if (const Interpreter::QmlObjectValue * qmlValue = dynamic_cast<const Interpreter::QmlObjectValue *>(ov)) {
646 if (qmlValue->isEnum(propertyType(propertyName)))
647 return qmlValue->className();
654 bool NodeMetaInfoPrivate::cleverCheckType(const QString &otherType) const
656 if (otherType == qualfiedTypeName())
662 QStringList split = otherType.split('.');
664 QString typeName = otherType;
665 if (split.count() > 1) {
666 package = split.first();
667 typeName = split.at(1);
669 if (packageName() == package)
670 return QString(package + '.' + typeName) == qualfiedTypeName();
672 const LanguageUtils::FakeMetaObject::Export exp =
673 getQmlObjectValue()->metaObject()->exportInPackage(package);
674 const QString convertedName = exp.type;
676 return typeName == convertedName;
679 QVariant::Type NodeMetaInfoPrivate::variantTypeId(const QString &properyName) const
681 QString typeName = propertyType(properyName);
682 if (typeName == "string")
683 return QVariant::String;
685 if (typeName == "color")
686 return QVariant::Color;
688 if (typeName == "int")
689 return QVariant::Int;
691 if (typeName == "url")
692 return QVariant::Url;
694 if (typeName == "real")
695 return QVariant::Double;
697 if (typeName == "bool")
698 return QVariant::Bool;
700 if (typeName == "boolean")
701 return QVariant::Bool;
703 if (typeName == "date")
704 return QVariant::Date;
706 if (typeName == "alias")
707 return QVariant::UserType;
709 if (typeName == "var")
710 return QVariant::UserType;
712 return QVariant::nameToType(typeName.toLatin1().data());
716 QStringList NodeMetaInfoPrivate::keysForEnum(const QString &enumName) const
719 return QStringList();
721 return getNearestQmlObjectValue()->keysForEnum(enumName);
724 QString NodeMetaInfoPrivate::packageName() const
727 return getQmlObjectValue()->packageName();
731 QString NodeMetaInfoPrivate::componentSource() const
734 const Interpreter::ASTObjectValue * astObjectValue = dynamic_cast<const Interpreter::ASTObjectValue *>(getObjectValue());
736 return astObjectValue->document()->source().mid(astObjectValue->typeName()->identifierToken.begin(),
737 astObjectValue->initializer()->rbraceToken.end());
742 QString NodeMetaInfoPrivate::componentFileName() const
745 const Interpreter::ASTObjectValue * astObjectValue = dynamic_cast<const Interpreter::ASTObjectValue *>(getObjectValue());
746 if (astObjectValue) {
750 if (astObjectValue->getSourceLocation(&fileName, &line, &column))
758 QString NodeMetaInfoPrivate::lookupName() const
760 QString className = m_qualfiedTypeName;
763 QStringList packageClassName = m_qualfiedTypeName.split(QLatin1Char('.'));
764 if (packageClassName.size() > 1) {
765 className = packageClassName.takeLast();
766 packageName = packageClassName.join(QLatin1String("."));
769 return Interpreter::CppQmlTypes::qualifiedName(
772 LanguageUtils::ComponentVersion(m_majorVersion, m_minorVersion));
775 QStringList NodeMetaInfoPrivate::lookupNameComponent() const
777 QString tempString = m_qualfiedTypeName;
778 return tempString.split('.');
781 bool NodeMetaInfoPrivate::isValid() const
783 return m_isValid && lookupContext() && document();
786 QString NodeMetaInfoPrivate::propertyType(const QString &propertyName) const
788 if (!m_properties.contains(propertyName))
790 return m_propertyTypes.at(m_properties.indexOf(propertyName));
793 void NodeMetaInfoPrivate::setupPrototypes()
795 QList<const Interpreter::ObjectValue *> objects;
797 objects = Interpreter::PrototypeIterator(getObjectValue(), lookupContext()->context()).all();
799 objects = Interpreter::PrototypeIterator(getQmlObjectValue(), lookupContext()->context()).all();
800 foreach (const Interpreter::ObjectValue *ov, objects) {
801 TypeDescription description;
802 description.className = ov->className();
803 description.minorVersion = -1;
804 description.majorVersion = -1;
805 if (const Interpreter::QmlObjectValue * qmlValue = dynamic_cast<const Interpreter::QmlObjectValue *>(ov)) {
806 description.minorVersion = qmlValue->version().minorVersion();
807 description.majorVersion = qmlValue->version().majorVersion();
808 if (!qmlValue->packageName().isEmpty())
809 description.className = qmlValue->packageName() + '.' + description.className;
810 m_prototypes.append(description);
812 if (lookupContext()->context()->lookupType(document(), QStringList() << ov->className()))
813 m_prototypes.append(description);
819 QList<TypeDescription> NodeMetaInfoPrivate::prototypes() const
824 const QmlJS::Interpreter::QmlObjectValue *NodeMetaInfoPrivate::getNearestQmlObjectValue() const
827 return findQmlPrototype(getObjectValue(), lookupContext());
828 return getQmlObjectValue();
831 } //namespace Internal
833 NodeMetaInfo::NodeMetaInfo() : m_privateData(new Internal::NodeMetaInfoPrivate())
838 NodeMetaInfo::NodeMetaInfo(Model *model, QString type, int maj, int min) : m_privateData(Internal::NodeMetaInfoPrivate::create(model, type, maj, min))
843 NodeMetaInfo::~NodeMetaInfo()
847 NodeMetaInfo::NodeMetaInfo(const NodeMetaInfo &other)
848 : m_privateData(other.m_privateData)
852 NodeMetaInfo &NodeMetaInfo::operator=(const NodeMetaInfo &other)
855 this->m_privateData = other.m_privateData;
860 bool NodeMetaInfo::isValid() const
862 return m_privateData->isValid();
865 bool NodeMetaInfo::isComponent() const
867 return m_privateData->isComponent();
870 bool NodeMetaInfo::hasProperty(const QString &propertyName) const
872 return propertyNames().contains(propertyName);
875 QStringList NodeMetaInfo::propertyNames() const
877 return m_privateData->properties();
880 QStringList NodeMetaInfo::directPropertyNames() const
882 return m_privateData->localProperties();
885 QString NodeMetaInfo::defaultPropertyName() const
887 return m_privateData->defaultPropertyName();
890 bool NodeMetaInfo::hasDefaultProperty() const
892 return !defaultPropertyName().isEmpty();
895 QString NodeMetaInfo::propertyTypeName(const QString &propertyName) const
897 return m_privateData->propertyType(propertyName);
900 bool NodeMetaInfo::propertyIsWritable(const QString &propertyName) const
902 return m_privateData->isPropertyWritable(propertyName);
905 bool NodeMetaInfo::propertyIsListProperty(const QString &propertyName) const
907 return m_privateData->isPropertyList(propertyName);
910 bool NodeMetaInfo::propertyIsEnumType(const QString &propertyName) const
912 return m_privateData->isPropertyEnum(propertyName);
915 QString NodeMetaInfo::propertyEnumScope(const QString &propertyName) const
917 return m_privateData->propertyEnumScope(propertyName);
920 QStringList NodeMetaInfo::propertyKeysForEnum(const QString &propertyName) const
922 return m_privateData->keysForEnum(propertyTypeName(propertyName));
925 QVariant NodeMetaInfo::propertyCastedValue(const QString &propertyName, const QVariant &value) const
928 QVariant variant = value;
929 if (propertyIsEnumType(propertyName)) {
933 const QString typeName = propertyTypeName(propertyName);
935 QVariant::Type typeId = m_privateData->variantTypeId(propertyName);
937 if (variant.type() == QVariant::UserType && variant.userType() == ModelNode::variantUserType()) {
939 } else if (typeId == QVariant::UserType && typeName == QLatin1String("QVariant")) {
941 } else if (typeId == QVariant::UserType && typeName == QLatin1String("variant")) {
943 } else if (typeId == QVariant::UserType && typeName == QLatin1String("var")) {
945 } else if (variant.type() == QVariant::List && variant.type() == QVariant::List) {
946 // TODO: check the contents of the list
948 } else if (typeName == "var" || typeName == "variant") {
950 } else if (typeName == "alias") {
951 // TODO: The QML compiler resolves the alias type. We probably should do the same.
953 } else if (variant.convert(typeId)) {
957 return QDeclarativeStringConverters::variantFromString(variant.toString());
961 QList<NodeMetaInfo> NodeMetaInfo::superClasses() const
963 QList<NodeMetaInfo> list;
965 foreach (const Internal::TypeDescription &type, m_privateData->prototypes()) {
966 list.append(NodeMetaInfo(m_privateData->model(), type.className, type.majorVersion, type.minorVersion));
971 NodeMetaInfo NodeMetaInfo::directSuperClass() const
973 QList<NodeMetaInfo> superClassesList = superClasses();
974 if (superClassesList.count() > 1)
975 return superClassesList.at(1);
976 return NodeMetaInfo();
979 QString NodeMetaInfo::typeName() const
981 return m_privateData->qualfiedTypeName();
983 int NodeMetaInfo::majorVersion() const
985 return m_privateData->majorVersion();
987 int NodeMetaInfo::minorVersion() const
989 return m_privateData->minorVersion();
992 QString NodeMetaInfo::componentSource() const
994 return m_privateData->componentSource();
997 QString NodeMetaInfo::componentFileName() const
999 return NodeMetaInfo::m_privateData->componentFileName();
1002 bool NodeMetaInfo::availableInVersion(int majorVersion, int minorVersion) const
1004 if (majorVersion == -1 && minorVersion == -1)
1007 return (m_privateData->majorVersion() >= majorVersion)
1008 || (majorVersion == m_privateData->majorVersion() && m_privateData->minorVersion() >= minorVersion);
1011 bool NodeMetaInfo::isSubclassOf(const QString &type, int majorVersion, int minorVersion) const
1014 qWarning() << "NodeMetaInfo is invalid";
1018 if (typeName() == type
1019 && availableInVersion(majorVersion, minorVersion))
1022 if (m_privateData->prototypeCachePositives().contains(Internal::stringIdentifier(type, majorVersion, minorVersion)))
1023 return true; //take a shortcut - optimization
1025 if (m_privateData->prototypeCacheNegatives().contains(Internal::stringIdentifier(type, majorVersion, minorVersion)))
1026 return false; //take a shortcut - optimization
1028 foreach (const NodeMetaInfo &superClass, superClasses()) {
1029 if (superClass.m_privateData->cleverCheckType(type)
1030 && superClass.availableInVersion(majorVersion, minorVersion)) {
1031 m_privateData->prototypeCachePositives().insert(Internal::stringIdentifier(type, majorVersion, minorVersion));
1035 m_privateData->prototypeCacheNegatives().insert(Internal::stringIdentifier(type, majorVersion, minorVersion));
1039 void NodeMetaInfo::clearCache()
1041 Internal::NodeMetaInfoPrivate::clearCache();
1044 } // namespace QmlDesigner