Commit 659b2a7e authored by Roberto Raggi's avatar Roberto Raggi
Browse files

Complete QML properties.

parent 3c37eaa5
......@@ -39,13 +39,13 @@ SOURCES += \
contains(QT_CONFIG, declarative) {
QT += declarative
DEFINES += BUILD_DECLARATIVE_BACKEND
HEADERS += \
$$PWD/qtdeclarativemetatypebackend.h
SOURCES += \
$$PWD/qtdeclarativemetatypebackend.cpp
} else {
DEFINES += NO_DECLARATIVE_BACKEND
}
contains(QT, gui) {
......
......@@ -30,10 +30,93 @@
#include "qmljsinterpreter.h"
#include <QtCore/QDebug>
#ifndef NO_DECLARATIVE_BACKEND
# include <QtDeclarative/QmlType>
# include <QtDeclarative/QmlMetaType>
# include <QtDeclarative/private/qmlgraphicsanchors_p.h> // ### remove me
# include <QtCore/QMetaObject>
# include <QtCore/QMetaProperty>
#endif
using namespace QmlJS::Interpreter;
namespace {
#ifndef NO_DECLARATIVE_BACKEND
class QmlObjectValue: public ObjectValue
{
public:
QmlObjectValue(const QMetaObject *metaObject, Engine *engine)
: ObjectValue(engine), _metaObject(metaObject) {}
virtual ~QmlObjectValue() {}
virtual const Value *lookupMember(const QString &name) const
{
for (int index = 0; index < _metaObject->propertyCount(); ++index) {
QMetaProperty prop = _metaObject->property(index);
if (name == QString::fromUtf8(prop.name()))
return propertyValue(prop);
}
return ObjectValue::lookupMember(name);
}
virtual void processMembers(MemberProcessor *processor) const
{
for (int index = 0; index < _metaObject->propertyCount(); ++index) {
QMetaProperty prop = _metaObject->property(index);
processor->process(prop.name(), propertyValue(prop));
}
}
const Value *propertyValue(const QMetaProperty &prop) const {
const Value *value = engine()->undefinedValue();
if (QmlMetaType::isObject(prop.userType())) {
QString typeName = QString::fromUtf8(prop.typeName());
if (typeName.endsWith(QLatin1Char('*')))
typeName.truncate(typeName.length() - 1);
typeName.replace(QLatin1Char('.'), QLatin1Char('/'));
if (const ObjectValue *objectValue = engine()->newQmlObject(typeName))
return objectValue;
}
switch (prop.type()) {
case QMetaType::QByteArray:
case QMetaType::QString:
value = engine()->stringValue();
break;
case QMetaType::Bool:
value = engine()->booleanValue();
break;
case QMetaType::Int:
case QMetaType::Float:
case QMetaType::Double:
value = engine()->numberValue();
break;
default:
break;
} // end of switch
return value;
}
private:
const QMetaObject *_metaObject;
};
#endif
////////////////////////////////////////////////////////////////////////////////
// constructors
////////////////////////////////////////////////////////////////////////////////
......@@ -511,21 +594,11 @@ void ObjectValue::processMembers(MemberProcessor *processor) const
while (it.hasNext()) {
it.next();
if (! processor->processMember(it.key(), it.value()))
if (! processor->process(it.key(), it.value()))
break;
}
}
const Value *ObjectValue::member(const QString &name) const
{
QHash<QString, const Value *>::const_iterator it = _members.find(name);
if (it != _members.end())
return it.value();
else
return 0;
}
const Environment *ObjectValue::parent() const
{
return _scope;
......@@ -533,7 +606,7 @@ const Environment *ObjectValue::parent() const
const Value *ObjectValue::lookupMember(const QString &name) const
{
if (const Value *m = member(name))
if (const Value *m = _members.value(name))
return m;
if (_prototype) {
......@@ -1325,6 +1398,38 @@ void Engine::initializePrototypes()
_globalObject->setProperty("RegExp", regexpCtor());
}
const ObjectValue *Engine::newQmlObject(const QString &name)
{
if (const ObjectValue *object = _qmlObjects.value(name))
return object;
#ifndef NO_DECLARATIVE_BACKEND
if (name == QLatin1String("QmlGraphicsAnchors")) {
QmlObjectValue *object = new QmlObjectValue(&QmlGraphicsAnchors::staticMetaObject, this);
_objects.append(object);
return object;
}
// ### TODO: add support for QML packages
QString componentName;
componentName += QLatin1String("Qt/");
componentName += name;
componentName.replace(QLatin1Char('.'), QLatin1Char('/'));
if (QmlType *qmlType = QmlMetaType::qmlType(componentName.toUtf8(), 4, 6)) {
QmlObjectValue *object = new QmlObjectValue(qmlType->metaObject(), this);
_qmlObjects.insert(name, object);
_objects.append(object);
return object;
}
#endif
//qDebug() << name;
return 0;
}
const Value *FunctionValue::invoke(const Activation *activation) const
{
return activation->thisObject(); // ### FIXME: it should return undefined
......
......@@ -202,7 +202,7 @@ public:
virtual ~MemberProcessor() {}
// Returns false to stop the processor.
virtual bool processMember(const QString &name, const Value *value) = 0;
virtual bool process(const QString &name, const Value *value) = 0;
};
class QMLJS_EXPORT ObjectValue: public Value, public Environment
......@@ -224,7 +224,6 @@ public:
virtual void processMembers(MemberProcessor *processor) const;
virtual const Value *member(const QString &name) const;
virtual const Value *property(const QString &name) const;
virtual void setProperty(const QString &name, const Value *value);
virtual void removeProperty(const QString &name);
......@@ -435,6 +434,9 @@ public:
Function *newFunction();
const Value *newArray(); // ### remove me
// QML objects
const ObjectValue *newQmlObject(const QString &name);
// global object
ObjectValue *globalObject() const;
const ObjectValue *mathObject() const;
......@@ -500,6 +502,7 @@ private:
BooleanValue _booleanValue;
StringValue _stringValue;
QList<ObjectValue *> _objects;
QHash<QString, const ObjectValue *> _qmlObjects;
ConvertToNumber _convertToNumber;
ConvertToString _convertToString;
......
......@@ -30,9 +30,9 @@
#include "qmljsmetatypebackend.h"
#include "qmljstypesystem.h"
#ifdef BUILD_DECLARATIVE_BACKEND
#ifndef NO_DECLARATIVE_BACKEND
# include "qtdeclarativemetatypebackend.h"
#endif // BUILD_DECLARATIVE_BACKEND
#endif // NO_DECLARATIVE_BACKEND
#include <QDebug>
......@@ -40,9 +40,9 @@ using namespace QmlJS;
TypeSystem::TypeSystem()
{
#ifdef BUILD_DECLARATIVE_BACKEND
#ifndef NO_DECLARATIVE_BACKEND
backends.append(new Internal::QtDeclarativeMetaTypeBackend(this));
#endif // BUILD_DECLARATIVE_BACKEND
#endif // NO_DECLARATIVE_BACKEND
}
TypeSystem::~TypeSystem()
......
......@@ -315,7 +315,7 @@ public:
}
private:
virtual bool processMember(const QString &name, const Interpreter::Value *value)
virtual bool process(const QString &name, const Interpreter::Value *value)
{
_properties.insert(name, value);
return true;
......@@ -703,6 +703,35 @@ int QmlCodeCompletion::startCompletion(TextEditor::ITextEditable *editor)
if (exprDoc->ast()) {
Interpreter::Engine interp;
foreach (Document::Ptr doc, snapshot) {
const QFileInfo fileInfo(doc->fileName());
if (fileInfo.suffix() != QLatin1String("qml"))
continue;
else if (fileInfo.absolutePath() != currentFilePath) // ### FIXME includ `imported' components
continue;
const QString typeName = fileInfo.baseName();
if (typeName.isEmpty())
continue;
QMapIterator<QString, IdSymbol *> it(doc->ids());
while (it.hasNext()) {
it.next();
if (IdSymbol *symbol = it.value()) {
const QString id = it.key();
if (symbol->parentNode()) {
const QString component = symbol->parentNode()->name();
if (const Interpreter::ObjectValue *object = interp.newQmlObject(component))
interp.globalObject()->setProperty(id, object);
}
}
}
}
Evaluate evaluate(&interp);
SearchPropertyDefinitions searchPropertyDefinitions;
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment