aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/qml
diff options
context:
space:
mode:
authorMatthew Vogt <matthew.vogt@nokia.com>2012-03-30 09:09:51 +1000
committerQt by Nokia <qt-info@nokia.com>2012-04-16 01:26:12 +0200
commit82a3fef9104ef449ecae56a2b228f4e820d928fa (patch)
tree4c87df2570d47f652589f8e2d787ae67a861772b /src/qml/qml
parentf189b8934dc405cbd45258abc5aba2713428b1cc (diff)
Add support for variant properties in V4
Support initialization of variant properties in V4. Variants can be set to contain basic types in V4, but we can't extract data from them since they may contain data types that V4 does not comprehend. Task-number: QTBUG-25022 Change-Id: I1935d77b50c5a3481c4c8ddd86b9d3d970571217 Reviewed-by: Michael Brasser <michael.brasser@nokia.com> Reviewed-by: Roberto Raggi <roberto.raggi@nokia.com>
Diffstat (limited to 'src/qml/qml')
-rw-r--r--src/qml/qml/v4/qv4bindings.cpp128
-rw-r--r--src/qml/qml/v4/qv4compiler.cpp21
-rw-r--r--src/qml/qml/v4/qv4instruction.cpp24
-rw-r--r--src/qml/qml/v4/qv4instruction_p.h8
-rw-r--r--src/qml/qml/v4/qv4ir.cpp2
-rw-r--r--src/qml/qml/v4/qv4ir_p.h2
-rw-r--r--src/qml/qml/v4/qv4irbuilder.cpp12
7 files changed, 193 insertions, 4 deletions
diff --git a/src/qml/qml/v4/qv4bindings.cpp b/src/qml/qml/v4/qv4bindings.cpp
index e5d98e63fa..db015b07d6 100644
--- a/src/qml/qml/v4/qv4bindings.cpp
+++ b/src/qml/qml/v4/qv4bindings.cpp
@@ -456,7 +456,7 @@ static void testBindingResult(const QString &binding, int line, int column,
if (expression.hasError()) {
iserror = true;
qtscriptResult = "exception";
- } else if (value.userType() != resultType) {
+ } else if ((value.userType() != resultType) && (resultType != QMetaType::QVariant)) {
// Override the QMetaType conversions to make them more JS friendly.
if (value.userType() == QMetaType::Double && (resultType == QMetaType::QString ||
resultType == QMetaType::QUrl)) {
@@ -506,6 +506,12 @@ static void testBindingResult(const QString &binding, int line, int column,
case QMetaType::Double:
v4value = result.getnumber();
break;
+ case QMetaType::QColor:
+ v4value = *result.getcolorptr();
+ break;
+ case QMetaType::QVariant:
+ v4value = *result.getvariantptr();
+ break;
default:
if (resultType == QQmlMetaType::QQuickAnchorLineMetaTypeId()) {
v4value = QVariant(QQmlMetaType::QQuickAnchorLineMetaTypeId(), result.typeDataPtr());
@@ -882,6 +888,19 @@ void QV4Bindings::run(int instrIndex, quint32 &executedBlocks,
}
QML_V4_END_INSTR(ConvertBoolToString, unaryop)
+ QML_V4_BEGIN_INSTR(ConvertBoolToVariant, unaryop)
+ {
+ const Register &src = registers[instr->unaryop.src];
+ Register &output = registers[instr->unaryop.output];
+ if (src.isUndefined()) {
+ output.setUndefined();
+ } else {
+ new (output.getvariantptr()) QVariant(src.getbool());
+ VARIANT_REGISTER(instr->unaryop.output);
+ }
+ }
+ QML_V4_END_INSTR(ConvertBoolToVariant, unaryop)
+
QML_V4_BEGIN_INSTR(ConvertIntToBool, unaryop)
{
const Register &src = registers[instr->unaryop.src];
@@ -906,13 +925,26 @@ void QV4Bindings::run(int instrIndex, quint32 &executedBlocks,
Register &output = registers[instr->unaryop.output];
if (src.isUndefined()) {
output.setUndefined();
- } else {
+ } else {
new (output.getstringptr()) QString(QString::number(src.getint()));
STRING_REGISTER(instr->unaryop.output);
}
}
QML_V4_END_INSTR(ConvertIntToString, unaryop)
+ QML_V4_BEGIN_INSTR(ConvertIntToVariant, unaryop)
+ {
+ const Register &src = registers[instr->unaryop.src];
+ Register &output = registers[instr->unaryop.output];
+ if (src.isUndefined()) {
+ output.setUndefined();
+ } else {
+ new (output.getvariantptr()) QVariant(src.getint());
+ VARIANT_REGISTER(instr->unaryop.output);
+ }
+ }
+ QML_V4_END_INSTR(ConvertIntToVariant, unaryop)
+
QML_V4_BEGIN_INSTR(ConvertNumberToBool, unaryop)
{
const Register &src = registers[instr->unaryop.src];
@@ -945,6 +977,19 @@ void QV4Bindings::run(int instrIndex, quint32 &executedBlocks,
}
QML_V4_END_INSTR(ConvertNumberToString, unaryop)
+ QML_V4_BEGIN_INSTR(ConvertNumberToVariant, unaryop)
+ {
+ const Register &src = registers[instr->unaryop.src];
+ Register &output = registers[instr->unaryop.output];
+ if (src.isUndefined()) {
+ output.setUndefined();
+ } else {
+ new (output.getvariantptr()) QVariant(src.getnumber());
+ VARIANT_REGISTER(instr->unaryop.output);
+ }
+ }
+ QML_V4_END_INSTR(ConvertNumberToVariant, unaryop)
+
QML_V4_BEGIN_INSTR(ConvertStringToBool, unaryop)
{
const Register &src = registers[instr->unaryop.src];
@@ -1048,6 +1093,25 @@ void QV4Bindings::run(int instrIndex, quint32 &executedBlocks,
}
QML_V4_END_INSTR(ConvertStringToUrl, unaryop)
+ QML_V4_BEGIN_INSTR(ConvertStringToVariant, unaryop)
+ {
+ const Register &src = registers[instr->unaryop.src];
+ Register &output = registers[instr->unaryop.output];
+ if (src.isUndefined()) {
+ output.setUndefined();
+ } else {
+ const QString tmp(*src.getstringptr());
+ if (instr->unaryop.src == instr->unaryop.output) {
+ output.cleanupString();
+ MARK_CLEAN_REGISTER(instr->unaryop.output);
+ }
+ new (output.getvariantptr()) QVariant(tmp);
+
+ VARIANT_REGISTER(instr->unaryop.output);
+ }
+ }
+ QML_V4_END_INSTR(ConvertStringToVariant, unaryop)
+
QML_V4_BEGIN_INSTR(ConvertUrlToBool, unaryop)
{
const Register &src = registers[instr->unaryop.src];
@@ -1085,6 +1149,25 @@ void QV4Bindings::run(int instrIndex, quint32 &executedBlocks,
}
QML_V4_END_INSTR(ConvertUrlToString, unaryop)
+ QML_V4_BEGIN_INSTR(ConvertUrlToVariant, unaryop)
+ {
+ const Register &src = registers[instr->unaryop.src];
+ Register &output = registers[instr->unaryop.output];
+ // ### NaN
+ if (src.isUndefined()) {
+ output.setUndefined();
+ } else {
+ const QUrl tmp(*src.geturlptr());
+ if (instr->unaryop.src == instr->unaryop.output) {
+ output.cleanupUrl();
+ MARK_CLEAN_REGISTER(instr->unaryop.output);
+ }
+ new (output.getvariantptr()) QVariant(tmp);
+ VARIANT_REGISTER(instr->unaryop.output);
+ }
+ }
+ QML_V4_END_INSTR(ConvertUrlToVariant, unaryop)
+
QML_V4_BEGIN_INSTR(ConvertColorToBool, unaryop)
{
const Register &src = registers[instr->unaryop.src];
@@ -1119,6 +1202,25 @@ void QV4Bindings::run(int instrIndex, quint32 &executedBlocks,
}
QML_V4_END_INSTR(ConvertColorToString, unaryop)
+ QML_V4_BEGIN_INSTR(ConvertColorToVariant, unaryop)
+ {
+ const Register &src = registers[instr->unaryop.src];
+ Register &output = registers[instr->unaryop.output];
+ // ### NaN
+ if (src.isUndefined()) {
+ output.setUndefined();
+ } else {
+ const QColor tmp(*src.getcolorptr());
+ if (instr->unaryop.src == instr->unaryop.output) {
+ output.cleanupColor();
+ MARK_CLEAN_REGISTER(instr->unaryop.output);
+ }
+ new (output.getvariantptr()) QVariant(tmp);
+ VARIANT_REGISTER(instr->unaryop.output);
+ }
+ }
+ QML_V4_END_INSTR(ConvertColorToVariant, unaryop)
+
QML_V4_BEGIN_INSTR(ConvertObjectToBool, unaryop)
{
const Register &src = registers[instr->unaryop.src];
@@ -1131,6 +1233,20 @@ void QV4Bindings::run(int instrIndex, quint32 &executedBlocks,
}
QML_V4_END_INSTR(ConvertObjectToBool, unaryop)
+ QML_V4_BEGIN_INSTR(ConvertObjectToVariant, unaryop)
+ {
+ const Register &src = registers[instr->unaryop.src];
+ Register &output = registers[instr->unaryop.output];
+ // ### NaN
+ if (src.isUndefined())
+ output.setUndefined();
+ else {
+ new (output.getvariantptr()) QVariant(qVariantFromValue<QObject *>(src.getQObject()));
+ VARIANT_REGISTER(instr->unaryop.output);
+ }
+ }
+ QML_V4_END_INSTR(ConvertObjectToVariant, unaryop)
+
QML_V4_BEGIN_INSTR(ConvertNullToObject, unaryop)
{
Register &output = registers[instr->unaryop.output];
@@ -1138,6 +1254,14 @@ void QV4Bindings::run(int instrIndex, quint32 &executedBlocks,
}
QML_V4_END_INSTR(ConvertNullToObject, unaryop)
+ QML_V4_BEGIN_INSTR(ConvertNullToVariant, unaryop)
+ {
+ Register &output = registers[instr->unaryop.output];
+ new (output.getvariantptr()) QVariant();
+ VARIANT_REGISTER(instr->unaryop.output);
+ }
+ QML_V4_END_INSTR(ConvertNullToVariant, unaryop)
+
QML_V4_BEGIN_INSTR(ResolveUrl, unaryop)
{
const Register &src = registers[instr->unaryop.src];
diff --git a/src/qml/qml/v4/qv4compiler.cpp b/src/qml/qml/v4/qv4compiler.cpp
index 045a14fbb5..e03270cf1d 100644
--- a/src/qml/qml/v4/qv4compiler.cpp
+++ b/src/qml/qml/v4/qv4compiler.cpp
@@ -377,6 +377,9 @@ void QV4CompilerPrivate::visitName(IR::Name *e)
case QMetaType::QColor:
regType = QColorType;
break;
+ case QMetaType::QVariant:
+ regType = QVariantType;
+ break;
default:
if (propTy == QQmlMetaType::QQuickAnchorLineMetaTypeId()) {
@@ -966,6 +969,7 @@ void QV4CompilerPrivate::visitMove(IR::Move *s)
switch (targetTy) {
case IR::BoolType:
case IR::StringType:
+ case IR::VariantType:
// nothing to do. V4 will generate optimized
// url-to-xxx conversions.
break;
@@ -1068,6 +1072,20 @@ void QV4CompilerPrivate::visitMove(IR::Move *s)
case IR::NullType: opcode = V4Instr::ConvertNullToObject; break;
default: break;
} // switch
+ } else if (targetTy == IR::VariantType) {
+ if (s->isMoveForReturn) {
+ switch (sourceTy) {
+ case IR::BoolType: opcode = V4Instr::ConvertBoolToVariant; break;
+ case IR::IntType: opcode = V4Instr::ConvertIntToVariant; break;
+ case IR::NumberType: opcode = V4Instr::ConvertNumberToVariant; break;
+ case IR::UrlType: opcode = V4Instr::ConvertUrlToVariant; break;
+ case IR::ColorType: opcode = V4Instr::ConvertColorToVariant; break;
+ case IR::StringType: opcode = V4Instr::ConvertStringToVariant; break;
+ case IR::ObjectType: opcode = V4Instr::ConvertObjectToVariant; break;
+ case IR::NullType: opcode = V4Instr::ConvertNullToVariant; break;
+ default: break;
+ } // switch
+ }
}
if (opcode != V4Instr::Noop) {
V4Instr conv;
@@ -1141,6 +1159,9 @@ void QV4CompilerPrivate::visitRet(IR::Ret *s)
case IR::ObjectType:
test.regType = QMetaType::QObjectStar;
break;
+ case IR::VariantType:
+ test.regType = QMetaType::QVariant;
+ break;
case IR::BoolType:
test.regType = QMetaType::Bool;
break;
diff --git a/src/qml/qml/v4/qv4instruction.cpp b/src/qml/qml/v4/qv4instruction.cpp
index ecd4f01ef3..c20297975d 100644
--- a/src/qml/qml/v4/qv4instruction.cpp
+++ b/src/qml/qml/v4/qv4instruction.cpp
@@ -144,6 +144,9 @@ void Bytecode::dump(const V4Instr *i, int address) const
case V4Instr::ConvertBoolToString:
INSTR_DUMP << "\t" << "ConvertBoolToString" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
break;
+ case V4Instr::ConvertBoolToVariant:
+ INSTR_DUMP << "\t" << "ConvertBoolToVariant" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
+ break;
case V4Instr::ConvertIntToBool:
INSTR_DUMP << "\t" << "ConvertIntToBool" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
break;
@@ -153,6 +156,9 @@ void Bytecode::dump(const V4Instr *i, int address) const
case V4Instr::ConvertIntToString:
INSTR_DUMP << "\t" << "ConvertIntToString" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
break;
+ case V4Instr::ConvertIntToVariant:
+ INSTR_DUMP << "\t" << "ConvertIntToVariant" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
+ break;
case V4Instr::ConvertNumberToBool:
INSTR_DUMP << "\t" << "ConvertNumberToBool" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
break;
@@ -162,6 +168,9 @@ void Bytecode::dump(const V4Instr *i, int address) const
case V4Instr::ConvertNumberToString:
INSTR_DUMP << "\t" << "ConvertNumberToString" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
break;
+ case V4Instr::ConvertNumberToVariant:
+ INSTR_DUMP << "\t" << "ConvertNumberToVariant" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
+ break;
case V4Instr::ConvertStringToBool:
INSTR_DUMP << "\t" << "ConvertStringToBool" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
break;
@@ -177,24 +186,39 @@ void Bytecode::dump(const V4Instr *i, int address) const
case V4Instr::ConvertStringToColor:
INSTR_DUMP << "\t" << "ConvertStringToColor" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
break;
+ case V4Instr::ConvertStringToVariant:
+ INSTR_DUMP << "\t" << "ConvertStringToVariant" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
+ break;
case V4Instr::ConvertUrlToBool:
INSTR_DUMP << "\t" << "ConvertUrlToBool" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
break;
case V4Instr::ConvertUrlToString:
INSTR_DUMP << "\t" << "ConvertUrlToString" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
break;
+ case V4Instr::ConvertUrlToVariant:
+ INSTR_DUMP << "\t" << "ConvertUrlToVariant" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
+ break;
case V4Instr::ConvertColorToBool:
INSTR_DUMP << "\t" << "ConvertColorToBool" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
break;
case V4Instr::ConvertColorToString:
INSTR_DUMP << "\t" << "ConvertColorToString" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
break;
+ case V4Instr::ConvertColorToVariant:
+ INSTR_DUMP << "\t" << "ConvertColorToVariant" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
+ break;
case V4Instr::ConvertObjectToBool:
INSTR_DUMP << "\t" << "ConvertObjectToBool" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
break;
+ case V4Instr::ConvertObjectToVariant:
+ INSTR_DUMP << "\t" << "ConvertObjectToVariant" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
+ break;
case V4Instr::ConvertNullToObject:
INSTR_DUMP << "\t" << "ConvertNullToObject" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
break;
+ case V4Instr::ConvertNullToVariant:
+ INSTR_DUMP << "\t" << "ConvertNullToVariant" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
+ break;
case V4Instr::ResolveUrl:
INSTR_DUMP << "\t" << "ResolveUrl" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
break;
diff --git a/src/qml/qml/v4/qv4instruction_p.h b/src/qml/qml/v4/qv4instruction_p.h
index 310bfbaff5..6eb9efa50f 100644
--- a/src/qml/qml/v4/qv4instruction_p.h
+++ b/src/qml/qml/v4/qv4instruction_p.h
@@ -83,23 +83,31 @@ QT_BEGIN_NAMESPACE
F(ConvertBoolToInt, unaryop) \
F(ConvertBoolToNumber, unaryop) \
F(ConvertBoolToString, unaryop) \
+ F(ConvertBoolToVariant, unaryop) \
F(ConvertIntToBool, unaryop) \
F(ConvertIntToNumber, unaryop) \
F(ConvertIntToString, unaryop) \
+ F(ConvertIntToVariant, unaryop) \
F(ConvertNumberToBool, unaryop) \
F(ConvertNumberToInt, unaryop) \
F(ConvertNumberToString, unaryop) \
+ F(ConvertNumberToVariant, unaryop) \
F(ConvertStringToBool, unaryop) \
F(ConvertStringToInt, unaryop) \
F(ConvertStringToNumber, unaryop) \
F(ConvertStringToUrl, unaryop) \
F(ConvertStringToColor, unaryop) \
+ F(ConvertStringToVariant, unaryop) \
F(ConvertUrlToBool, unaryop) \
F(ConvertUrlToString, unaryop) \
+ F(ConvertUrlToVariant, unaryop) \
F(ConvertColorToBool, unaryop) \
F(ConvertColorToString, unaryop) \
+ F(ConvertColorToVariant, unaryop) \
F(ConvertObjectToBool, unaryop) \
+ F(ConvertObjectToVariant, unaryop) \
F(ConvertNullToObject, unaryop) \
+ F(ConvertNullToVariant, unaryop) \
F(ResolveUrl, unaryop) \
F(MathSinNumber, unaryop) \
F(MathCosNumber, unaryop) \
diff --git a/src/qml/qml/v4/qv4ir.cpp b/src/qml/qml/v4/qv4ir.cpp
index ba0faec80e..45e909f54b 100644
--- a/src/qml/qml/v4/qv4ir.cpp
+++ b/src/qml/qml/v4/qv4ir.cpp
@@ -63,6 +63,8 @@ const char *typeName(Type t)
case SGAnchorLineType: return "SGAnchorLine";
case AttachType: return "AttachType";
case ObjectType: return "object";
+ case VariantType: return "variant";
+ case VarType: return "var";
case BoolType: return "bool";
case IntType: return "int";
case FloatType: return "float";
diff --git a/src/qml/qml/v4/qv4ir_p.h b/src/qml/qml/v4/qv4ir_p.h
index 26bd43c406..254b810403 100644
--- a/src/qml/qml/v4/qv4ir_p.h
+++ b/src/qml/qml/v4/qv4ir_p.h
@@ -146,6 +146,8 @@ enum Type {
SGAnchorLineType,
AttachType,
ObjectType,
+ VariantType,
+ VarType,
FirstNumberType,
BoolType = FirstNumberType,
diff --git a/src/qml/qml/v4/qv4irbuilder.cpp b/src/qml/qml/v4/qv4irbuilder.cpp
index 31ed9a5a6a..82da09f485 100644
--- a/src/qml/qml/v4/qv4irbuilder.cpp
+++ b/src/qml/qml/v4/qv4irbuilder.cpp
@@ -116,8 +116,16 @@ bool QV4IRBuilder::operator()(QQmlJS::IR::Function *function,
//_block->MOVE(_block->TEMP(IR::InvalidType), r.code);
if (r.code) {
- const QMetaObject *m = 0;
- const IR::Type targetType = irTypeFromVariantType(m_expression->property->type, m_engine, m);
+ IR::Type targetType = IR::InvalidType;
+
+ // This is the only operation where variant is supported:
+ QQmlPropertyData *data = &m_expression->property->core;
+ if (data->propType == QMetaType::QVariant) {
+ targetType = (data->isVMEProperty() ? IR::VarType : IR::VariantType);
+ } else {
+ targetType = irTypeFromVariantType(data->propType, m_engine, 0);
+ }
+
if (targetType != r.type()) {
IR::Expr *x = _block->TEMP(targetType);
_block->MOVE(x, r, true);