Merge remote-tracking branch 'origin/5.6' into 5.7
Conflicts: tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp tests/auto/quick/qquickitem/tst_qquickitem.cpp Change-Id: If261f8eea84dfa5944bb55de999d1f70aba528fd
This commit is contained in:
commit
6839f03051
|
@ -2250,6 +2250,17 @@ bool QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache *propertyCa
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case QVariant::Vector2D: {
|
||||||
|
struct {
|
||||||
|
float xp;
|
||||||
|
float yp;
|
||||||
|
} vec;
|
||||||
|
if (!QQmlStringConverters::createFromString(QMetaType::QVector2D, binding->valueAsString(qmlUnit), &vec, sizeof(vec))) {
|
||||||
|
recordError(binding->valueLocation, tr("Invalid property assignment: 2D vector expected"));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
case QVariant::Vector3D: {
|
case QVariant::Vector3D: {
|
||||||
struct {
|
struct {
|
||||||
float xp;
|
float xp;
|
||||||
|
@ -2275,6 +2286,19 @@ bool QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache *propertyCa
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case QVariant::Quaternion: {
|
||||||
|
struct {
|
||||||
|
float wp;
|
||||||
|
float xp;
|
||||||
|
float yp;
|
||||||
|
float zp;
|
||||||
|
} vec;
|
||||||
|
if (!QQmlStringConverters::createFromString(QMetaType::QQuaternion, binding->valueAsString(qmlUnit), &vec, sizeof(vec))) {
|
||||||
|
recordError(binding->valueLocation, tr("Invalid property assignment: quaternion expected"));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
case QVariant::RegExp:
|
case QVariant::RegExp:
|
||||||
recordError(binding->valueLocation, tr("Invalid property assignment: regular expression expected; use /pattern/ syntax"));
|
recordError(binding->valueLocation, tr("Invalid property assignment: regular expression expected; use /pattern/ syntax"));
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -1058,6 +1058,8 @@ bool Codegen::visit(ArrayLiteral *ast)
|
||||||
current->expr = _block->CONST(IR::MissingType, 0);
|
current->expr = _block->CONST(IR::MissingType, 0);
|
||||||
}
|
}
|
||||||
Result expr = expression(it->expression);
|
Result expr = expression(it->expression);
|
||||||
|
if (hasError)
|
||||||
|
return false;
|
||||||
|
|
||||||
IR::ExprList *arg = _function->New<IR::ExprList>();
|
IR::ExprList *arg = _function->New<IR::ExprList>();
|
||||||
if (!current) {
|
if (!current) {
|
||||||
|
@ -1100,6 +1102,8 @@ bool Codegen::visit(ArrayMemberExpression *ast)
|
||||||
|
|
||||||
Result base = expression(ast->base);
|
Result base = expression(ast->base);
|
||||||
Result index = expression(ast->expression);
|
Result index = expression(ast->expression);
|
||||||
|
if (hasError)
|
||||||
|
return false;
|
||||||
_expr.code = subscript(*base, *index);
|
_expr.code = subscript(*base, *index);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -1139,10 +1143,16 @@ bool Codegen::visit(BinaryExpression *ast)
|
||||||
|
|
||||||
const unsigned r = _block->newTemp();
|
const unsigned r = _block->newTemp();
|
||||||
|
|
||||||
move(_block->TEMP(r), *expression(ast->left));
|
Result lhs = expression(ast->left);
|
||||||
|
if (hasError)
|
||||||
|
return false;
|
||||||
|
move(_block->TEMP(r), *lhs);
|
||||||
setLocation(cjump(_block->TEMP(r), iftrue, endif), ast->operatorToken);
|
setLocation(cjump(_block->TEMP(r), iftrue, endif), ast->operatorToken);
|
||||||
_block = iftrue;
|
_block = iftrue;
|
||||||
move(_block->TEMP(r), *expression(ast->right));
|
Result rhs = expression(ast->right);
|
||||||
|
if (hasError)
|
||||||
|
return false;
|
||||||
|
move(_block->TEMP(r), *rhs);
|
||||||
_block->JUMP(endif);
|
_block->JUMP(endif);
|
||||||
|
|
||||||
_expr.code = _block->TEMP(r);
|
_expr.code = _block->TEMP(r);
|
||||||
|
@ -1160,10 +1170,16 @@ bool Codegen::visit(BinaryExpression *ast)
|
||||||
IR::BasicBlock *endif = _function->newBasicBlock(exceptionHandler());
|
IR::BasicBlock *endif = _function->newBasicBlock(exceptionHandler());
|
||||||
|
|
||||||
const unsigned r = _block->newTemp();
|
const unsigned r = _block->newTemp();
|
||||||
move(_block->TEMP(r), *expression(ast->left));
|
Result lhs = expression(ast->left);
|
||||||
|
if (hasError)
|
||||||
|
return false;
|
||||||
|
move(_block->TEMP(r), *lhs);
|
||||||
setLocation(cjump(_block->TEMP(r), endif, iffalse), ast->operatorToken);
|
setLocation(cjump(_block->TEMP(r), endif, iffalse), ast->operatorToken);
|
||||||
_block = iffalse;
|
_block = iffalse;
|
||||||
move(_block->TEMP(r), *expression(ast->right));
|
Result rhs = expression(ast->right);
|
||||||
|
if (hasError)
|
||||||
|
return false;
|
||||||
|
move(_block->TEMP(r), *rhs);
|
||||||
_block->JUMP(endif);
|
_block->JUMP(endif);
|
||||||
|
|
||||||
_block = endif;
|
_block = endif;
|
||||||
|
@ -1173,6 +1189,8 @@ bool Codegen::visit(BinaryExpression *ast)
|
||||||
}
|
}
|
||||||
|
|
||||||
IR::Expr* left = *expression(ast->left);
|
IR::Expr* left = *expression(ast->left);
|
||||||
|
if (hasError)
|
||||||
|
return false;
|
||||||
|
|
||||||
switch (ast->op) {
|
switch (ast->op) {
|
||||||
case QSOperator::Or:
|
case QSOperator::Or:
|
||||||
|
@ -1182,17 +1200,19 @@ bool Codegen::visit(BinaryExpression *ast)
|
||||||
case QSOperator::Assign: {
|
case QSOperator::Assign: {
|
||||||
if (throwSyntaxErrorOnEvalOrArgumentsInStrictMode(left, ast->left->lastSourceLocation()))
|
if (throwSyntaxErrorOnEvalOrArgumentsInStrictMode(left, ast->left->lastSourceLocation()))
|
||||||
return false;
|
return false;
|
||||||
IR::Expr* right = *expression(ast->right);
|
Result right = expression(ast->right);
|
||||||
|
if (hasError)
|
||||||
|
return false;
|
||||||
if (!left->isLValue()) {
|
if (!left->isLValue()) {
|
||||||
throwReferenceError(ast->operatorToken, QStringLiteral("left-hand side of assignment operator is not an lvalue"));
|
throwReferenceError(ast->operatorToken, QStringLiteral("left-hand side of assignment operator is not an lvalue"));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_expr.accept(nx)) {
|
if (_expr.accept(nx)) {
|
||||||
move(left, right);
|
move(left, *right);
|
||||||
} else {
|
} else {
|
||||||
const unsigned t = _block->newTemp();
|
const unsigned t = _block->newTemp();
|
||||||
move(_block->TEMP(t), right);
|
move(_block->TEMP(t), *right);
|
||||||
move(left, _block->TEMP(t));
|
move(left, _block->TEMP(t));
|
||||||
_expr.code = _block->TEMP(t);
|
_expr.code = _block->TEMP(t);
|
||||||
}
|
}
|
||||||
|
@ -1212,17 +1232,19 @@ bool Codegen::visit(BinaryExpression *ast)
|
||||||
case QSOperator::InplaceXor: {
|
case QSOperator::InplaceXor: {
|
||||||
if (throwSyntaxErrorOnEvalOrArgumentsInStrictMode(left, ast->left->lastSourceLocation()))
|
if (throwSyntaxErrorOnEvalOrArgumentsInStrictMode(left, ast->left->lastSourceLocation()))
|
||||||
return false;
|
return false;
|
||||||
IR::Expr* right = *expression(ast->right);
|
Result right = expression(ast->right);
|
||||||
|
if (hasError)
|
||||||
|
return false;
|
||||||
if (!left->isLValue()) {
|
if (!left->isLValue()) {
|
||||||
throwSyntaxError(ast->operatorToken, QStringLiteral("left-hand side of inplace operator is not an lvalue"));
|
throwSyntaxError(ast->operatorToken, QStringLiteral("left-hand side of inplace operator is not an lvalue"));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_expr.accept(nx)) {
|
if (_expr.accept(nx)) {
|
||||||
move(left, right, baseOp(ast->op));
|
move(left, *right, baseOp(ast->op));
|
||||||
} else {
|
} else {
|
||||||
const unsigned t = _block->newTemp();
|
const unsigned t = _block->newTemp();
|
||||||
move(_block->TEMP(t), right);
|
move(_block->TEMP(t), *right);
|
||||||
move(left, _block->TEMP(t), baseOp(ast->op));
|
move(left, _block->TEMP(t), baseOp(ast->op));
|
||||||
_expr.code = left;
|
_expr.code = left;
|
||||||
}
|
}
|
||||||
|
@ -1245,12 +1267,14 @@ bool Codegen::visit(BinaryExpression *ast)
|
||||||
left = _block->TEMP(t);
|
left = _block->TEMP(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
IR::Expr* right = *expression(ast->right);
|
Result right = expression(ast->right);
|
||||||
|
if (hasError)
|
||||||
|
return false;
|
||||||
|
|
||||||
if (_expr.accept(cx)) {
|
if (_expr.accept(cx)) {
|
||||||
setLocation(cjump(binop(IR::binaryOperator(ast->op), left, right, ast->operatorToken), _expr.iftrue, _expr.iffalse), ast->operatorToken);
|
setLocation(cjump(binop(IR::binaryOperator(ast->op), left, *right, ast->operatorToken), _expr.iftrue, _expr.iffalse), ast->operatorToken);
|
||||||
} else {
|
} else {
|
||||||
IR::Expr *e = binop(IR::binaryOperator(ast->op), left, right, ast->operatorToken);
|
IR::Expr *e = binop(IR::binaryOperator(ast->op), left, *right, ast->operatorToken);
|
||||||
if (e->asConst() || e->asString())
|
if (e->asConst() || e->asString())
|
||||||
_expr.code = e;
|
_expr.code = e;
|
||||||
else {
|
else {
|
||||||
|
@ -1279,9 +1303,11 @@ bool Codegen::visit(BinaryExpression *ast)
|
||||||
left = _block->TEMP(t);
|
left = _block->TEMP(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
IR::Expr* right = *expression(ast->right);
|
Result right = expression(ast->right);
|
||||||
|
if (hasError)
|
||||||
|
return false;
|
||||||
|
|
||||||
IR::Expr *e = binop(IR::binaryOperator(ast->op), left, right, ast->operatorToken);
|
IR::Expr *e = binop(IR::binaryOperator(ast->op), left, *right, ast->operatorToken);
|
||||||
if (e->asConst() || e->asString())
|
if (e->asConst() || e->asString())
|
||||||
_expr.code = e;
|
_expr.code = e;
|
||||||
else {
|
else {
|
||||||
|
@ -1306,11 +1332,15 @@ bool Codegen::visit(CallExpression *ast)
|
||||||
IR::ExprList *args = 0, **args_it = &args;
|
IR::ExprList *args = 0, **args_it = &args;
|
||||||
for (ArgumentList *it = ast->arguments; it; it = it->next) {
|
for (ArgumentList *it = ast->arguments; it; it = it->next) {
|
||||||
Result arg = expression(it->expression);
|
Result arg = expression(it->expression);
|
||||||
|
if (hasError)
|
||||||
|
return false;
|
||||||
IR::Expr *actual = argument(*arg);
|
IR::Expr *actual = argument(*arg);
|
||||||
*args_it = _function->New<IR::ExprList>();
|
*args_it = _function->New<IR::ExprList>();
|
||||||
(*args_it)->init(actual);
|
(*args_it)->init(actual);
|
||||||
args_it = &(*args_it)->next;
|
args_it = &(*args_it)->next;
|
||||||
}
|
}
|
||||||
|
if (hasError)
|
||||||
|
return false;
|
||||||
_expr.code = call(*base, args);
|
_expr.code = call(*base, args);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -1329,11 +1359,17 @@ bool Codegen::visit(ConditionalExpression *ast)
|
||||||
condition(ast->expression, iftrue, iffalse);
|
condition(ast->expression, iftrue, iffalse);
|
||||||
|
|
||||||
_block = iftrue;
|
_block = iftrue;
|
||||||
move(_block->TEMP(t), *expression(ast->ok));
|
Result ok = expression(ast->ok);
|
||||||
|
if (hasError)
|
||||||
|
return false;
|
||||||
|
move(_block->TEMP(t), *ok);
|
||||||
_block->JUMP(endif);
|
_block->JUMP(endif);
|
||||||
|
|
||||||
_block = iffalse;
|
_block = iffalse;
|
||||||
move(_block->TEMP(t), *expression(ast->ko));
|
Result ko = expression(ast->ko);
|
||||||
|
if (hasError)
|
||||||
|
return false;
|
||||||
|
move(_block->TEMP(t), *ko);
|
||||||
_block->JUMP(endif);
|
_block->JUMP(endif);
|
||||||
|
|
||||||
_block = endif;
|
_block = endif;
|
||||||
|
@ -1349,6 +1385,8 @@ bool Codegen::visit(DeleteExpression *ast)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
IR::Expr* expr = *expression(ast->expression);
|
IR::Expr* expr = *expression(ast->expression);
|
||||||
|
if (hasError)
|
||||||
|
return false;
|
||||||
// Temporaries cannot be deleted
|
// Temporaries cannot be deleted
|
||||||
IR::ArgLocal *al = expr->asArgLocal();
|
IR::ArgLocal *al = expr->asArgLocal();
|
||||||
if (al && al->index < static_cast<unsigned>(_env->members.size())) {
|
if (al && al->index < static_cast<unsigned>(_env->members.size())) {
|
||||||
|
@ -1410,7 +1448,8 @@ bool Codegen::visit(FieldMemberExpression *ast)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
Result base = expression(ast->base);
|
Result base = expression(ast->base);
|
||||||
_expr.code = member(*base, _function->newString(ast->name.toString()));
|
if (!hasError)
|
||||||
|
_expr.code = member(*base, _function->newString(ast->name.toString()));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1501,6 +1540,8 @@ bool Codegen::visit(NewExpression *ast)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
Result base = expression(ast->expression);
|
Result base = expression(ast->expression);
|
||||||
|
if (hasError)
|
||||||
|
return false;
|
||||||
IR::Expr *expr = *base;
|
IR::Expr *expr = *base;
|
||||||
if (expr && !expr->asTemp() && !expr->asArgLocal() && !expr->asName() && !expr->asMember()) {
|
if (expr && !expr->asTemp() && !expr->asArgLocal() && !expr->asName() && !expr->asMember()) {
|
||||||
const unsigned t = _block->newTemp();
|
const unsigned t = _block->newTemp();
|
||||||
|
@ -1517,6 +1558,8 @@ bool Codegen::visit(NewMemberExpression *ast)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
Result base = expression(ast->base);
|
Result base = expression(ast->base);
|
||||||
|
if (hasError)
|
||||||
|
return false;
|
||||||
IR::Expr *expr = *base;
|
IR::Expr *expr = *base;
|
||||||
if (expr && !expr->asTemp() && !expr->asArgLocal() && !expr->asName() && !expr->asMember()) {
|
if (expr && !expr->asTemp() && !expr->asArgLocal() && !expr->asName() && !expr->asMember()) {
|
||||||
const unsigned t = _block->newTemp();
|
const unsigned t = _block->newTemp();
|
||||||
|
@ -1527,6 +1570,8 @@ bool Codegen::visit(NewMemberExpression *ast)
|
||||||
IR::ExprList *args = 0, **args_it = &args;
|
IR::ExprList *args = 0, **args_it = &args;
|
||||||
for (ArgumentList *it = ast->arguments; it; it = it->next) {
|
for (ArgumentList *it = ast->arguments; it; it = it->next) {
|
||||||
Result arg = expression(it->expression);
|
Result arg = expression(it->expression);
|
||||||
|
if (hasError)
|
||||||
|
return false;
|
||||||
IR::Expr *actual = argument(*arg);
|
IR::Expr *actual = argument(*arg);
|
||||||
*args_it = _function->New<IR::ExprList>();
|
*args_it = _function->New<IR::ExprList>();
|
||||||
(*args_it)->init(actual);
|
(*args_it)->init(actual);
|
||||||
|
@ -1544,6 +1589,8 @@ bool Codegen::visit(NotExpression *ast)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
Result expr = expression(ast->expression);
|
Result expr = expression(ast->expression);
|
||||||
|
if (hasError)
|
||||||
|
return false;
|
||||||
const unsigned r = _block->newTemp();
|
const unsigned r = _block->newTemp();
|
||||||
setLocation(move(_block->TEMP(r), unop(IR::OpNot, *expr, ast->notToken)), ast->notToken);
|
setLocation(move(_block->TEMP(r), unop(IR::OpNot, *expr, ast->notToken)), ast->notToken);
|
||||||
_expr.code = _block->TEMP(r);
|
_expr.code = _block->TEMP(r);
|
||||||
|
@ -1601,6 +1648,8 @@ bool Codegen::visit(ObjectLiteral *ast)
|
||||||
QString name = it->assignment->name->asString();
|
QString name = it->assignment->name->asString();
|
||||||
if (PropertyNameAndValue *nv = AST::cast<AST::PropertyNameAndValue *>(it->assignment)) {
|
if (PropertyNameAndValue *nv = AST::cast<AST::PropertyNameAndValue *>(it->assignment)) {
|
||||||
Result value = expression(nv->value);
|
Result value = expression(nv->value);
|
||||||
|
if (hasError)
|
||||||
|
return false;
|
||||||
ObjectPropertyValue &v = valueMap[name];
|
ObjectPropertyValue &v = valueMap[name];
|
||||||
if (v.hasGetter() || v.hasSetter() || (_function->isStrict && v.value)) {
|
if (v.hasGetter() || v.hasSetter() || (_function->isStrict && v.value)) {
|
||||||
throwSyntaxError(nv->lastSourceLocation(),
|
throwSyntaxError(nv->lastSourceLocation(),
|
||||||
|
@ -1731,6 +1780,8 @@ bool Codegen::visit(PostDecrementExpression *ast)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
Result expr = expression(ast->base);
|
Result expr = expression(ast->base);
|
||||||
|
if (hasError)
|
||||||
|
return false;
|
||||||
if (!expr->isLValue()) {
|
if (!expr->isLValue()) {
|
||||||
throwReferenceError(ast->base->lastSourceLocation(), QStringLiteral("Invalid left-hand side expression in postfix operation"));
|
throwReferenceError(ast->base->lastSourceLocation(), QStringLiteral("Invalid left-hand side expression in postfix operation"));
|
||||||
return false;
|
return false;
|
||||||
|
@ -1757,6 +1808,8 @@ bool Codegen::visit(PostIncrementExpression *ast)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
Result expr = expression(ast->base);
|
Result expr = expression(ast->base);
|
||||||
|
if (hasError)
|
||||||
|
return false;
|
||||||
if (!expr->isLValue()) {
|
if (!expr->isLValue()) {
|
||||||
throwReferenceError(ast->base->lastSourceLocation(), QStringLiteral("Invalid left-hand side expression in postfix operation"));
|
throwReferenceError(ast->base->lastSourceLocation(), QStringLiteral("Invalid left-hand side expression in postfix operation"));
|
||||||
return false;
|
return false;
|
||||||
|
@ -1783,6 +1836,8 @@ bool Codegen::visit(PreDecrementExpression *ast)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
Result expr = expression(ast->expression);
|
Result expr = expression(ast->expression);
|
||||||
|
if (hasError)
|
||||||
|
return false;
|
||||||
if (!expr->isLValue()) {
|
if (!expr->isLValue()) {
|
||||||
throwReferenceError(ast->expression->lastSourceLocation(), QStringLiteral("Prefix ++ operator applied to value that is not a reference."));
|
throwReferenceError(ast->expression->lastSourceLocation(), QStringLiteral("Prefix ++ operator applied to value that is not a reference."));
|
||||||
return false;
|
return false;
|
||||||
|
@ -1808,6 +1863,8 @@ bool Codegen::visit(PreIncrementExpression *ast)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
Result expr = expression(ast->expression);
|
Result expr = expression(ast->expression);
|
||||||
|
if (hasError)
|
||||||
|
return false;
|
||||||
if (!expr->isLValue()) {
|
if (!expr->isLValue()) {
|
||||||
throwReferenceError(ast->expression->lastSourceLocation(), QStringLiteral("Prefix ++ operator applied to value that is not a reference."));
|
throwReferenceError(ast->expression->lastSourceLocation(), QStringLiteral("Prefix ++ operator applied to value that is not a reference."));
|
||||||
return false;
|
return false;
|
||||||
|
@ -1860,6 +1917,8 @@ bool Codegen::visit(TildeExpression *ast)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
Result expr = expression(ast->expression);
|
Result expr = expression(ast->expression);
|
||||||
|
if (hasError)
|
||||||
|
return false;
|
||||||
const unsigned t = _block->newTemp();
|
const unsigned t = _block->newTemp();
|
||||||
setLocation(move(_block->TEMP(t), unop(IR::OpCompl, *expr, ast->tildeToken)), ast->tildeToken);
|
setLocation(move(_block->TEMP(t), unop(IR::OpCompl, *expr, ast->tildeToken)), ast->tildeToken);
|
||||||
_expr.code = _block->TEMP(t);
|
_expr.code = _block->TEMP(t);
|
||||||
|
@ -1885,6 +1944,8 @@ bool Codegen::visit(TypeOfExpression *ast)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
Result expr = expression(ast->expression);
|
Result expr = expression(ast->expression);
|
||||||
|
if (hasError)
|
||||||
|
return false;
|
||||||
IR::ExprList *args = _function->New<IR::ExprList>();
|
IR::ExprList *args = _function->New<IR::ExprList>();
|
||||||
args->init(reference(*expr));
|
args->init(reference(*expr));
|
||||||
_expr.code = call(_block->NAME(IR::Name::builtin_typeof, ast->typeofToken.startLine, ast->typeofToken.startColumn), args);
|
_expr.code = call(_block->NAME(IR::Name::builtin_typeof, ast->typeofToken.startLine, ast->typeofToken.startColumn), args);
|
||||||
|
@ -1897,6 +1958,8 @@ bool Codegen::visit(UnaryMinusExpression *ast)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
Result expr = expression(ast->expression);
|
Result expr = expression(ast->expression);
|
||||||
|
if (hasError)
|
||||||
|
return false;
|
||||||
const unsigned t = _block->newTemp();
|
const unsigned t = _block->newTemp();
|
||||||
setLocation(move(_block->TEMP(t), unop(IR::OpUMinus, *expr, ast->minusToken)), ast->minusToken);
|
setLocation(move(_block->TEMP(t), unop(IR::OpUMinus, *expr, ast->minusToken)), ast->minusToken);
|
||||||
_expr.code = _block->TEMP(t);
|
_expr.code = _block->TEMP(t);
|
||||||
|
@ -1909,6 +1972,8 @@ bool Codegen::visit(UnaryPlusExpression *ast)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
Result expr = expression(ast->expression);
|
Result expr = expression(ast->expression);
|
||||||
|
if (hasError)
|
||||||
|
return false;
|
||||||
const unsigned t = _block->newTemp();
|
const unsigned t = _block->newTemp();
|
||||||
setLocation(move(_block->TEMP(t), unop(IR::OpUPlus, *expr, ast->plusToken)), ast->plusToken);
|
setLocation(move(_block->TEMP(t), unop(IR::OpUPlus, *expr, ast->plusToken)), ast->plusToken);
|
||||||
_expr.code = _block->TEMP(t);
|
_expr.code = _block->TEMP(t);
|
||||||
|
@ -2223,7 +2288,10 @@ bool Codegen::visit(ForEachStatement *ast)
|
||||||
IR::BasicBlock *foreachend = _function->newBasicBlock(exceptionHandler());
|
IR::BasicBlock *foreachend = _function->newBasicBlock(exceptionHandler());
|
||||||
|
|
||||||
int objectToIterateOn = _block->newTemp();
|
int objectToIterateOn = _block->newTemp();
|
||||||
move(_block->TEMP(objectToIterateOn), *expression(ast->expression));
|
Result expr = expression(ast->expression);
|
||||||
|
if (hasError)
|
||||||
|
return false;
|
||||||
|
move(_block->TEMP(objectToIterateOn), *expr);
|
||||||
IR::ExprList *args = _function->New<IR::ExprList>();
|
IR::ExprList *args = _function->New<IR::ExprList>();
|
||||||
args->init(_block->TEMP(objectToIterateOn));
|
args->init(_block->TEMP(objectToIterateOn));
|
||||||
|
|
||||||
|
@ -2235,7 +2303,10 @@ bool Codegen::visit(ForEachStatement *ast)
|
||||||
|
|
||||||
_block = foreachbody;
|
_block = foreachbody;
|
||||||
int temp = _block->newTemp();
|
int temp = _block->newTemp();
|
||||||
move(*expression(ast->initialiser), _block->TEMP(temp));
|
Result init = expression(ast->initialiser);
|
||||||
|
if (hasError)
|
||||||
|
return false;
|
||||||
|
move(*init, _block->TEMP(temp));
|
||||||
statement(ast->statement);
|
statement(ast->statement);
|
||||||
_block->JUMP(foreachin);
|
_block->JUMP(foreachin);
|
||||||
|
|
||||||
|
@ -2725,7 +2796,10 @@ bool Codegen::visit(WithStatement *ast)
|
||||||
_function->hasWith = true;
|
_function->hasWith = true;
|
||||||
|
|
||||||
const int withObject = _block->newTemp();
|
const int withObject = _block->newTemp();
|
||||||
_block->MOVE(_block->TEMP(withObject), *expression(ast->expression));
|
Result src = expression(ast->expression);
|
||||||
|
if (hasError)
|
||||||
|
return false;
|
||||||
|
_block->MOVE(_block->TEMP(withObject), *src);
|
||||||
|
|
||||||
// need an exception handler for with to cleanup the with scope
|
// need an exception handler for with to cleanup the with scope
|
||||||
IR::BasicBlock *withExceptionHandler = _function->newBasicBlock(exceptionHandler());
|
IR::BasicBlock *withExceptionHandler = _function->newBasicBlock(exceptionHandler());
|
||||||
|
|
|
@ -381,6 +381,8 @@ Message {
|
||||||
}
|
}
|
||||||
\endqml
|
\endqml
|
||||||
|
|
||||||
|
To use an enum as a \l {QFlags}{flags} type in QML, see \l Q_FLAG().
|
||||||
|
|
||||||
\note The names of enum values must begin with a capital letter in order to
|
\note The names of enum values must begin with a capital letter in order to
|
||||||
be accessible from QML.
|
be accessible from QML.
|
||||||
|
|
||||||
|
|
|
@ -102,13 +102,13 @@ public:
|
||||||
Q_ALWAYS_INLINE quint64 rawValue() const { return _val; }
|
Q_ALWAYS_INLINE quint64 rawValue() const { return _val; }
|
||||||
Q_ALWAYS_INLINE void setRawValue(quint64 raw) { _val = raw; }
|
Q_ALWAYS_INLINE void setRawValue(quint64 raw) { _val = raw; }
|
||||||
|
|
||||||
#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
|
#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN || defined(QV4_USE_64_BIT_VALUE_ENCODING)
|
||||||
static inline int valueOffset() { return 0; }
|
static inline int valueOffset() { return 0; }
|
||||||
static inline int tagOffset() { return 4; }
|
static inline int tagOffset() { return 4; }
|
||||||
Q_ALWAYS_INLINE void setTagValue(quint32 tag, quint32 value) { _val = quint64(tag) << 32 | value; }
|
Q_ALWAYS_INLINE void setTagValue(quint32 tag, quint32 value) { _val = quint64(tag) << 32 | value; }
|
||||||
Q_ALWAYS_INLINE quint32 value() const { return _val & quint64(~quint32(0)); }
|
Q_ALWAYS_INLINE quint32 value() const { return _val & quint64(~quint32(0)); }
|
||||||
Q_ALWAYS_INLINE quint32 tag() const { return _val >> 32; }
|
Q_ALWAYS_INLINE quint32 tag() const { return _val >> 32; }
|
||||||
#else // !Q_LITTLE_ENDIAN
|
#else // !Q_LITTLE_ENDIAN && !defined(QV4_USE_64_BIT_VALUE_ENCODING)
|
||||||
static inline int valueOffset() { return 4; }
|
static inline int valueOffset() { return 4; }
|
||||||
static inline int tagOffset() { return 0; }
|
static inline int tagOffset() { return 0; }
|
||||||
Q_ALWAYS_INLINE void setTagValue(quint32 tag, quint32 value) { _val = quint64(value) << 32 | tag; }
|
Q_ALWAYS_INLINE void setTagValue(quint32 tag, quint32 value) { _val = quint64(value) << 32 | tag; }
|
||||||
|
|
|
@ -1152,7 +1152,7 @@ static void QQmlComponent_setQmlParent(QObject *me, QObject *parent)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\qmlmethod object Component::createObject(Item parent, object properties)
|
\qmlmethod object Component::createObject(QtObject parent, object properties)
|
||||||
|
|
||||||
Creates and returns an object instance of this component that will have
|
Creates and returns an object instance of this component that will have
|
||||||
the given \a parent and \a properties. The \a properties argument is optional.
|
the given \a parent and \a properties. The \a properties argument is optional.
|
||||||
|
|
|
@ -514,6 +514,18 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const
|
||||||
QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
|
QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case QVariant::Vector2D: {
|
||||||
|
struct {
|
||||||
|
float xp;
|
||||||
|
float yp;
|
||||||
|
} vec;
|
||||||
|
bool ok = QQmlStringConverters::createFromString(QMetaType::QVector2D, binding->valueAsString(qmlUnit), &vec, sizeof(vec));
|
||||||
|
Q_ASSERT(ok);
|
||||||
|
Q_UNUSED(ok);
|
||||||
|
argv[0] = reinterpret_cast<void *>(&vec);
|
||||||
|
QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
|
||||||
|
}
|
||||||
|
break;
|
||||||
case QVariant::Vector3D: {
|
case QVariant::Vector3D: {
|
||||||
struct {
|
struct {
|
||||||
float xp;
|
float xp;
|
||||||
|
@ -541,6 +553,20 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const
|
||||||
QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
|
QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case QVariant::Quaternion: {
|
||||||
|
struct {
|
||||||
|
float wp;
|
||||||
|
float xp;
|
||||||
|
float yp;
|
||||||
|
float zp;
|
||||||
|
} vec;
|
||||||
|
bool ok = QQmlStringConverters::createFromString(QMetaType::QQuaternion, binding->valueAsString(qmlUnit), &vec, sizeof(vec));
|
||||||
|
Q_ASSERT(ok);
|
||||||
|
Q_UNUSED(ok);
|
||||||
|
argv[0] = reinterpret_cast<void *>(&vec);
|
||||||
|
QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
|
||||||
|
}
|
||||||
|
break;
|
||||||
case QVariant::RegExp:
|
case QVariant::RegExp:
|
||||||
Q_ASSERT(!"not possible");
|
Q_ASSERT(!"not possible");
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -278,7 +278,7 @@ int QQmlOpenMetaObject::metaCall(QObject *o, QMetaObject::Call c, int id, void *
|
||||||
propertyRead(propId);
|
propertyRead(propId);
|
||||||
*reinterpret_cast<QVariant *>(a[0]) = d->getData(propId);
|
*reinterpret_cast<QVariant *>(a[0]) = d->getData(propId);
|
||||||
} else if (c == QMetaObject::WriteProperty) {
|
} else if (c == QMetaObject::WriteProperty) {
|
||||||
if (propId <= d->data.count() || d->data[propId].first != *reinterpret_cast<QVariant *>(a[0])) {
|
if (propId >= d->data.count() || d->data[propId].first != *reinterpret_cast<QVariant *>(a[0])) {
|
||||||
propertyWrite(propId);
|
propertyWrite(propId);
|
||||||
QPair<QVariant, bool> &prop = d->getDataRef(propId);
|
QPair<QVariant, bool> &prop = d->getDataRef(propId);
|
||||||
prop.first = propertyWriteValue(propId, *reinterpret_cast<QVariant *>(a[0]));
|
prop.first = propertyWriteValue(propId, *reinterpret_cast<QVariant *>(a[0]));
|
||||||
|
|
|
@ -156,6 +156,111 @@ with list models of QAbstractItemModel type:
|
||||||
\li \l DelegateModel::parentModelIndex() returns a QModelIndex which can be assigned to DelegateModel::rootIndex
|
\li \l DelegateModel::parentModelIndex() returns a QModelIndex which can be assigned to DelegateModel::rootIndex
|
||||||
\endlist
|
\endlist
|
||||||
|
|
||||||
|
\section2 SQL Models
|
||||||
|
|
||||||
|
Qt provides C++ classes that support SQL data models. These classes work
|
||||||
|
transparently on the underlying SQL data, reducing the need to run SQL
|
||||||
|
queries for basic SQL operations such as create, insert, or update.
|
||||||
|
For more details about these classes, see \l{Using the SQL Model Classes}.
|
||||||
|
|
||||||
|
Although the C++ classes provide complete feature sets to operate on SQL
|
||||||
|
data, they do not provide data access to QML. So you must implement a
|
||||||
|
C++ custom data model as a subclass of one of these classes, and expose it
|
||||||
|
to QML either as a type or context property.
|
||||||
|
|
||||||
|
\section3 Read-only Data Model
|
||||||
|
|
||||||
|
The custom model must reimplement the following methods to enable read-only
|
||||||
|
access to the data from QML:
|
||||||
|
|
||||||
|
\list
|
||||||
|
\li \l{QAbstractItemModel::}{roleNames}() to expose the role names to the
|
||||||
|
QML frontend. For example, the following version returns the selected
|
||||||
|
table's field names as role names:
|
||||||
|
\code
|
||||||
|
QHash<int, QByteArray> SqlQueryModel::roleNames() const
|
||||||
|
{
|
||||||
|
QHash<int, QByteArray> roles;
|
||||||
|
// record() returns an empty QSqlRecord
|
||||||
|
for (int i = 0; i < this->record().count(); i ++) {
|
||||||
|
roles.insert(Qt::UserRole + i + 1, record().fieldName(i).toUtf8());
|
||||||
|
}
|
||||||
|
return roles;
|
||||||
|
}
|
||||||
|
\endcode
|
||||||
|
\li \l{QSqlQueryModel::}{data}() to expose SQL data to the QML frontend.
|
||||||
|
For example, the following implementation returns data for the given
|
||||||
|
model index:
|
||||||
|
\code
|
||||||
|
QVariant SqlQueryModel::data(const QModelIndex &index, int role) const
|
||||||
|
{
|
||||||
|
QVariant value;
|
||||||
|
|
||||||
|
if (index.isValid()) {
|
||||||
|
if (role < Qt::UserRole) {
|
||||||
|
value = QSqlQueryModel::data(index, role);
|
||||||
|
} else {
|
||||||
|
int columnIdx = role - Qt::UserRole - 1;
|
||||||
|
QModelIndex modelIndex = this->index(index.row(), columnIdx);
|
||||||
|
value = QSqlQueryModel::data(modelIndex, Qt::DisplayRole);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
\endcode
|
||||||
|
\endlist
|
||||||
|
|
||||||
|
The QSqlQueryModel class is good enough to implement a custom read-only
|
||||||
|
model that represents data in an SQL database. The
|
||||||
|
\l{Qt Quick Controls 2 - Chat Tutorial}{chat tutorial} example
|
||||||
|
demonstrates this very well by implementing a custom model to fetch the
|
||||||
|
contact details from an SQLite database.
|
||||||
|
|
||||||
|
\section3 Editable Data Model
|
||||||
|
|
||||||
|
Besides the \c roleNames() and \c data(), the editable models must reimplement
|
||||||
|
the \l{QSqlTableModel::}{setData} method to save changes to existing SQL data.
|
||||||
|
The following version of the method checks if the given model index is valid
|
||||||
|
and the \c role is equal to \l Qt::EditRole, before calling the parent class
|
||||||
|
version:
|
||||||
|
|
||||||
|
\code
|
||||||
|
bool SqlEditableModel::setData(const QModelIndex &item, const QVariant &value, int role)
|
||||||
|
{
|
||||||
|
if (item.isValid() && role == Qt::EditRole) {
|
||||||
|
QSqlTableModel::setData(item, value,role);
|
||||||
|
emit dataChanged(item, item);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
|
||||||
|
}
|
||||||
|
\endcode
|
||||||
|
|
||||||
|
\note It is important to emit the \l{QAbstractItemModel::}{dataChanged}()
|
||||||
|
signal after saving the changes.
|
||||||
|
|
||||||
|
Unlike the C++ item views such as QListView or QTableView, the \c setData()
|
||||||
|
method must be explicitly invoked from QML whenever appropriate. For example,
|
||||||
|
on the \l[QML]{TextField::}{editingFinished}() or \l[QML]{TextField::}{accepted}()
|
||||||
|
signal of \l[QtQuickControls]{TextField}. Depending on the
|
||||||
|
\l{QSqlTableModel::}{EditStrategy} used by the model, the changes are either
|
||||||
|
queued for submission later or submitted immediately.
|
||||||
|
|
||||||
|
You can also insert new data into the model by calling
|
||||||
|
\l {QSqlTableModel::insertRecord}(). In the following example snippet,
|
||||||
|
a QSqlRecord is populated with book details and appended to the
|
||||||
|
model:
|
||||||
|
|
||||||
|
\code
|
||||||
|
...
|
||||||
|
QSqlRecord newRecord = record();
|
||||||
|
newRecord.setValue("author", "John Grisham");
|
||||||
|
newRecord.setValue("booktitle", "The Litigators");
|
||||||
|
insertRecord(rowCount(), newRecord);
|
||||||
|
...
|
||||||
|
\endcode
|
||||||
|
|
||||||
\section2 Exposing C++ Data Models to QML
|
\section2 Exposing C++ Data Models to QML
|
||||||
|
|
||||||
The above examples use QQmlContext::setContextProperty() to set
|
The above examples use QQmlContext::setContextProperty() to set
|
||||||
|
|
|
@ -200,6 +200,27 @@ QPointF QQuickParentAnimationPrivate::computeTransformOrigin(QQuickItem::Transfo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct QQuickParentAnimationData : public QAbstractAnimationAction
|
||||||
|
{
|
||||||
|
QQuickParentAnimationData() : reverse(false) {}
|
||||||
|
~QQuickParentAnimationData() { qDeleteAll(pc); }
|
||||||
|
|
||||||
|
QQuickStateActions actions;
|
||||||
|
//### reverse should probably apply on a per-action basis
|
||||||
|
bool reverse;
|
||||||
|
QList<QQuickParentChange *> pc;
|
||||||
|
void doAction() Q_DECL_OVERRIDE
|
||||||
|
{
|
||||||
|
for (int ii = 0; ii < actions.count(); ++ii) {
|
||||||
|
const QQuickStateAction &action = actions.at(ii);
|
||||||
|
if (reverse)
|
||||||
|
action.event->reverse();
|
||||||
|
else
|
||||||
|
action.event->execute();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
QAbstractAnimationJob* QQuickParentAnimation::transition(QQuickStateActions &actions,
|
QAbstractAnimationJob* QQuickParentAnimation::transition(QQuickStateActions &actions,
|
||||||
QQmlProperties &modified,
|
QQmlProperties &modified,
|
||||||
TransitionDirection direction,
|
TransitionDirection direction,
|
||||||
|
@ -207,27 +228,6 @@ QAbstractAnimationJob* QQuickParentAnimation::transition(QQuickStateActions &act
|
||||||
{
|
{
|
||||||
Q_D(QQuickParentAnimation);
|
Q_D(QQuickParentAnimation);
|
||||||
|
|
||||||
struct QQuickParentAnimationData : public QAbstractAnimationAction
|
|
||||||
{
|
|
||||||
QQuickParentAnimationData() : reverse(false) {}
|
|
||||||
~QQuickParentAnimationData() { qDeleteAll(pc); }
|
|
||||||
|
|
||||||
QQuickStateActions actions;
|
|
||||||
//### reverse should probably apply on a per-action basis
|
|
||||||
bool reverse;
|
|
||||||
QList<QQuickParentChange *> pc;
|
|
||||||
void doAction() Q_DECL_OVERRIDE
|
|
||||||
{
|
|
||||||
for (int ii = 0; ii < actions.count(); ++ii) {
|
|
||||||
const QQuickStateAction &action = actions.at(ii);
|
|
||||||
if (reverse)
|
|
||||||
action.event->reverse();
|
|
||||||
else
|
|
||||||
action.event->execute();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
QQuickParentAnimationData *data = new QQuickParentAnimationData;
|
QQuickParentAnimationData *data = new QQuickParentAnimationData;
|
||||||
QQuickParentAnimationData *viaData = new QQuickParentAnimationData;
|
QQuickParentAnimationData *viaData = new QQuickParentAnimationData;
|
||||||
|
|
||||||
|
|
|
@ -1633,6 +1633,12 @@ bool QQuickWindowPrivate::deliverMouseEvent(QMouseEvent *event)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mouseGrabberItem) {
|
if (mouseGrabberItem) {
|
||||||
|
if (event->button() != Qt::NoButton
|
||||||
|
&& mouseGrabberItem->acceptedMouseButtons()
|
||||||
|
&& !(mouseGrabberItem->acceptedMouseButtons() & event->button())) {
|
||||||
|
event->ignore();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
QPointF localPos = mouseGrabberItem->mapFromScene(event->windowPos());
|
QPointF localPos = mouseGrabberItem->mapFromScene(event->windowPos());
|
||||||
QScopedPointer<QMouseEvent> me(cloneMouseEvent(event, &localPos));
|
QScopedPointer<QMouseEvent> me(cloneMouseEvent(event, &localPos));
|
||||||
me->accept();
|
me->accept();
|
||||||
|
|
|
@ -48,29 +48,6 @@ DEFINE_BOOL_CONFIG_OPTION(qmlFboOverlay, QML_FBO_OVERLAY)
|
||||||
#endif
|
#endif
|
||||||
DEFINE_BOOL_CONFIG_OPTION(qmlFboFlushBeforeDetach, QML_FBO_FLUSH_BEFORE_DETACH)
|
DEFINE_BOOL_CONFIG_OPTION(qmlFboFlushBeforeDetach, QML_FBO_FLUSH_BEFORE_DETACH)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static QOpenGLFramebufferObject *createFramebuffer(const QSize &size,
|
|
||||||
QOpenGLFramebufferObjectFormat format)
|
|
||||||
{
|
|
||||||
#ifdef Q_OS_MACOS
|
|
||||||
QOpenGLContext *context = QOpenGLContext::currentContext();
|
|
||||||
if (context->hasExtension("GL_ARB_framebuffer_sRGB")
|
|
||||||
&& context->hasExtension("GL_EXT_texture_sRGB")
|
|
||||||
&& context->hasExtension("GL_EXT_texture_sRGB_decode"))
|
|
||||||
format.setInternalTextureFormat(GL_SRGB8_ALPHA8_EXT);
|
|
||||||
#endif
|
|
||||||
QOpenGLFramebufferObject *fbo = new QOpenGLFramebufferObject(size, format);
|
|
||||||
#ifdef Q_OS_MACOS
|
|
||||||
if (format.internalTextureFormat() == GL_SRGB8_ALPHA8_EXT) {
|
|
||||||
QOpenGLFunctions *funcs = context->functions();
|
|
||||||
funcs->glBindTexture(GL_TEXTURE_2D, fbo->texture());
|
|
||||||
funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SRGB_DECODE_EXT, GL_SKIP_DECODE_EXT);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return fbo;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
class BindableFbo : public QSGBindable
|
class BindableFbo : public QSGBindable
|
||||||
|
@ -353,7 +330,7 @@ void QSGDefaultLayer::grab()
|
||||||
|
|
||||||
format.setInternalTextureFormat(m_format);
|
format.setInternalTextureFormat(m_format);
|
||||||
format.setSamples(m_context->openglContext()->format().samples());
|
format.setSamples(m_context->openglContext()->format().samples());
|
||||||
m_secondaryFbo = createFramebuffer(m_size, format);
|
m_secondaryFbo = new QOpenGLFramebufferObject(m_size, format);
|
||||||
m_depthStencilBuffer = m_context->depthStencilBufferForFbo(m_secondaryFbo);
|
m_depthStencilBuffer = m_context->depthStencilBufferForFbo(m_secondaryFbo);
|
||||||
} else {
|
} else {
|
||||||
QOpenGLFramebufferObjectFormat format;
|
QOpenGLFramebufferObjectFormat format;
|
||||||
|
@ -362,14 +339,14 @@ void QSGDefaultLayer::grab()
|
||||||
if (m_recursive) {
|
if (m_recursive) {
|
||||||
deleteFboLater = true;
|
deleteFboLater = true;
|
||||||
delete m_secondaryFbo;
|
delete m_secondaryFbo;
|
||||||
m_secondaryFbo = createFramebuffer(m_size, format);
|
m_secondaryFbo = new QOpenGLFramebufferObject(m_size, format);
|
||||||
funcs->glBindTexture(GL_TEXTURE_2D, m_secondaryFbo->texture());
|
funcs->glBindTexture(GL_TEXTURE_2D, m_secondaryFbo->texture());
|
||||||
updateBindOptions(true);
|
updateBindOptions(true);
|
||||||
m_depthStencilBuffer = m_context->depthStencilBufferForFbo(m_secondaryFbo);
|
m_depthStencilBuffer = m_context->depthStencilBufferForFbo(m_secondaryFbo);
|
||||||
} else {
|
} else {
|
||||||
delete m_fbo;
|
delete m_fbo;
|
||||||
delete m_secondaryFbo;
|
delete m_secondaryFbo;
|
||||||
m_fbo = createFramebuffer(m_size, format);
|
m_fbo = new QOpenGLFramebufferObject(m_size, format);
|
||||||
m_secondaryFbo = 0;
|
m_secondaryFbo = 0;
|
||||||
funcs->glBindTexture(GL_TEXTURE_2D, m_fbo->texture());
|
funcs->glBindTexture(GL_TEXTURE_2D, m_fbo->texture());
|
||||||
updateBindOptions(true);
|
updateBindOptions(true);
|
||||||
|
@ -383,7 +360,7 @@ void QSGDefaultLayer::grab()
|
||||||
Q_ASSERT(m_fbo);
|
Q_ASSERT(m_fbo);
|
||||||
Q_ASSERT(!m_multisampling);
|
Q_ASSERT(!m_multisampling);
|
||||||
|
|
||||||
m_secondaryFbo = createFramebuffer(m_size, m_fbo->format());
|
m_secondaryFbo = new QOpenGLFramebufferObject(m_size, m_fbo->format());
|
||||||
funcs->glBindTexture(GL_TEXTURE_2D, m_secondaryFbo->texture());
|
funcs->glBindTexture(GL_TEXTURE_2D, m_secondaryFbo->texture());
|
||||||
updateBindOptions(true);
|
updateBindOptions(true);
|
||||||
}
|
}
|
||||||
|
|
|
@ -599,7 +599,7 @@ void QSGRenderThread::syncAndRender()
|
||||||
#endif
|
#endif
|
||||||
Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphRenderLoopFrame);
|
Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphRenderLoopFrame);
|
||||||
|
|
||||||
if (!syncResultedInChanges && !repaintRequested) {
|
if (!syncResultedInChanges && !repaintRequested && sgrc->isValid()) {
|
||||||
qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "- no changes, render aborted";
|
qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "- no changes, render aborted";
|
||||||
int waitTime = vsyncDelta - (int) waitTimer.elapsed();
|
int waitTime = vsyncDelta - (int) waitTimer.elapsed();
|
||||||
if (waitTime > 0)
|
if (waitTime > 0)
|
||||||
|
|
|
@ -324,6 +324,7 @@ private slots:
|
||||||
void qtbug_46022();
|
void qtbug_46022();
|
||||||
void qtbug_52340();
|
void qtbug_52340();
|
||||||
void qtbug_54589();
|
void qtbug_54589();
|
||||||
|
void qtbug_54687();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// static void propertyVarWeakRefCallback(v8::Persistent<v8::Value> object, void* parameter);
|
// static void propertyVarWeakRefCallback(v8::Persistent<v8::Value> object, void* parameter);
|
||||||
|
@ -7925,6 +7926,12 @@ void tst_qqmlecmascript::qtbug_54589()
|
||||||
QCOMPARE(obj->property("result").toBool(), true);
|
QCOMPARE(obj->property("result").toBool(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void tst_qqmlecmascript::qtbug_54687()
|
||||||
|
{
|
||||||
|
QJSEngine e;
|
||||||
|
// it's simple: this shouldn't crash.
|
||||||
|
engine.evaluate("12\n----12");
|
||||||
|
}
|
||||||
|
|
||||||
QTEST_MAIN(tst_qqmlecmascript)
|
QTEST_MAIN(tst_qqmlecmascript)
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,9 @@ MyTypeObject {
|
||||||
boolProperty: true
|
boolProperty: true
|
||||||
variantProperty: "Hello World!"
|
variantProperty: "Hello World!"
|
||||||
vectorProperty: "10,1,2.2"
|
vectorProperty: "10,1,2.2"
|
||||||
|
vector2Property: "2, 3"
|
||||||
vector4Property: "10,1,2.2,2.3"
|
vector4Property: "10,1,2.2,2.3"
|
||||||
|
quaternionProperty: "4,5,6,7"
|
||||||
urlProperty: "main.qml?with%3cencoded%3edata"
|
urlProperty: "main.qml?with%3cencoded%3edata"
|
||||||
|
|
||||||
objectProperty: MyTypeObject { intProperty: 8 }
|
objectProperty: MyTypeObject { intProperty: 8 }
|
||||||
|
|
|
@ -33,8 +33,10 @@
|
||||||
#include <QtCore/qdatetime.h>
|
#include <QtCore/qdatetime.h>
|
||||||
#include <QtGui/qmatrix.h>
|
#include <QtGui/qmatrix.h>
|
||||||
#include <QtGui/qcolor.h>
|
#include <QtGui/qcolor.h>
|
||||||
|
#include <QtGui/qvector2d.h>
|
||||||
#include <QtGui/qvector3d.h>
|
#include <QtGui/qvector3d.h>
|
||||||
#include <QtGui/qvector4d.h>
|
#include <QtGui/qvector4d.h>
|
||||||
|
#include <QtGui/qquaternion.h>
|
||||||
#include <QtQml/qqml.h>
|
#include <QtQml/qqml.h>
|
||||||
#include <QtQml/qqmlcomponent.h>
|
#include <QtQml/qqmlcomponent.h>
|
||||||
#include <QtQml/qqmlparserstatus.h>
|
#include <QtQml/qqmlparserstatus.h>
|
||||||
|
@ -242,8 +244,10 @@ class MyTypeObject : public QObject
|
||||||
Q_PROPERTY(QRectF rectFProperty READ rectFProperty WRITE setRectFProperty NOTIFY rectFPropertyChanged)
|
Q_PROPERTY(QRectF rectFProperty READ rectFProperty WRITE setRectFProperty NOTIFY rectFPropertyChanged)
|
||||||
Q_PROPERTY(bool boolProperty READ boolProperty WRITE setBoolProperty NOTIFY boolPropertyChanged)
|
Q_PROPERTY(bool boolProperty READ boolProperty WRITE setBoolProperty NOTIFY boolPropertyChanged)
|
||||||
Q_PROPERTY(QVariant variantProperty READ variantProperty WRITE setVariantProperty NOTIFY variantPropertyChanged)
|
Q_PROPERTY(QVariant variantProperty READ variantProperty WRITE setVariantProperty NOTIFY variantPropertyChanged)
|
||||||
|
Q_PROPERTY(QVector2D vector2Property READ vector2Property WRITE setVector2Property NOTIFY vector2PropertyChanged)
|
||||||
Q_PROPERTY(QVector3D vectorProperty READ vectorProperty WRITE setVectorProperty NOTIFY vectorPropertyChanged)
|
Q_PROPERTY(QVector3D vectorProperty READ vectorProperty WRITE setVectorProperty NOTIFY vectorPropertyChanged)
|
||||||
Q_PROPERTY(QVector4D vector4Property READ vector4Property WRITE setVector4Property NOTIFY vector4PropertyChanged)
|
Q_PROPERTY(QVector4D vector4Property READ vector4Property WRITE setVector4Property NOTIFY vector4PropertyChanged)
|
||||||
|
Q_PROPERTY(QQuaternion quaternionProperty READ quaternionProperty WRITE setQuaternionProperty NOTIFY quaternionPropertyChanged)
|
||||||
Q_PROPERTY(QUrl urlProperty READ urlProperty WRITE setUrlProperty NOTIFY urlPropertyChanged)
|
Q_PROPERTY(QUrl urlProperty READ urlProperty WRITE setUrlProperty NOTIFY urlPropertyChanged)
|
||||||
|
|
||||||
Q_PROPERTY(QQmlScriptString scriptProperty READ scriptProperty WRITE setScriptProperty)
|
Q_PROPERTY(QQmlScriptString scriptProperty READ scriptProperty WRITE setScriptProperty)
|
||||||
|
@ -524,6 +528,15 @@ public:
|
||||||
emit vectorPropertyChanged();
|
emit vectorPropertyChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QVector2D vector2PropertyValue;
|
||||||
|
QVector2D vector2Property() const {
|
||||||
|
return vector2PropertyValue;
|
||||||
|
}
|
||||||
|
void setVector2Property(const QVector2D &v) {
|
||||||
|
vector2PropertyValue = v;
|
||||||
|
emit vector2PropertyChanged();
|
||||||
|
}
|
||||||
|
|
||||||
QVector4D vector4PropertyValue;
|
QVector4D vector4PropertyValue;
|
||||||
QVector4D vector4Property() const {
|
QVector4D vector4Property() const {
|
||||||
return vector4PropertyValue;
|
return vector4PropertyValue;
|
||||||
|
@ -533,6 +546,15 @@ public:
|
||||||
emit vector4PropertyChanged();
|
emit vector4PropertyChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QQuaternion quaternionPropertyValue;
|
||||||
|
QQuaternion quaternionProperty() const {
|
||||||
|
return quaternionPropertyValue;
|
||||||
|
}
|
||||||
|
void setQuaternionProperty(const QQuaternion &v) {
|
||||||
|
quaternionPropertyValue = v;
|
||||||
|
emit quaternionPropertyChanged();
|
||||||
|
}
|
||||||
|
|
||||||
QUrl urlPropertyValue;
|
QUrl urlPropertyValue;
|
||||||
QUrl urlProperty() const {
|
QUrl urlProperty() const {
|
||||||
return urlPropertyValue;
|
return urlPropertyValue;
|
||||||
|
@ -586,7 +608,9 @@ signals:
|
||||||
void boolPropertyChanged();
|
void boolPropertyChanged();
|
||||||
void variantPropertyChanged();
|
void variantPropertyChanged();
|
||||||
void vectorPropertyChanged();
|
void vectorPropertyChanged();
|
||||||
|
void vector2PropertyChanged();
|
||||||
void vector4PropertyChanged();
|
void vector4PropertyChanged();
|
||||||
|
void quaternionPropertyChanged();
|
||||||
void urlPropertyChanged();
|
void urlPropertyChanged();
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -677,6 +677,7 @@ void tst_qqmllanguage::assignBasicTypes()
|
||||||
QCOMPARE(object->boolProperty(), true);
|
QCOMPARE(object->boolProperty(), true);
|
||||||
QCOMPARE(object->variantProperty(), QVariant("Hello World!"));
|
QCOMPARE(object->variantProperty(), QVariant("Hello World!"));
|
||||||
QCOMPARE(object->vectorProperty(), QVector3D(10, 1, 2.2f));
|
QCOMPARE(object->vectorProperty(), QVector3D(10, 1, 2.2f));
|
||||||
|
QCOMPARE(object->vector2Property(), QVector2D(2, 3));
|
||||||
QCOMPARE(object->vector4Property(), QVector4D(10, 1, 2.2f, 2.3f));
|
QCOMPARE(object->vector4Property(), QVector4D(10, 1, 2.2f, 2.3f));
|
||||||
const QUrl encoded = QUrl::fromEncoded("main.qml?with%3cencoded%3edata", QUrl::TolerantMode);
|
const QUrl encoded = QUrl::fromEncoded("main.qml?with%3cencoded%3edata", QUrl::TolerantMode);
|
||||||
QCOMPARE(object->urlProperty(), component.url().resolved(encoded));
|
QCOMPARE(object->urlProperty(), component.url().resolved(encoded));
|
||||||
|
|
|
@ -60,6 +60,7 @@ private slots:
|
||||||
void QTBUG_35233();
|
void QTBUG_35233();
|
||||||
void disallowExtending();
|
void disallowExtending();
|
||||||
void QTBUG_35906();
|
void QTBUG_35906();
|
||||||
|
void QTBUG_48136();
|
||||||
};
|
};
|
||||||
|
|
||||||
class LazyPropertyMap : public QQmlPropertyMap, public QQmlParserStatus
|
class LazyPropertyMap : public QQmlPropertyMap, public QQmlParserStatus
|
||||||
|
@ -462,6 +463,40 @@ void tst_QQmlPropertyMap::QTBUG_35906()
|
||||||
QCOMPARE(value.toInt(), 42);
|
QCOMPARE(value.toInt(), 42);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void tst_QQmlPropertyMap::QTBUG_48136()
|
||||||
|
{
|
||||||
|
static const char key[] = "mykey";
|
||||||
|
QQmlPropertyMap map;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Test that the notify signal is emitted correctly
|
||||||
|
//
|
||||||
|
|
||||||
|
const int propIndex = map.metaObject()->indexOfProperty(key);
|
||||||
|
const QMetaProperty prop = map.metaObject()->property(propIndex);
|
||||||
|
QSignalSpy notifySpy(&map, QByteArray::number(QSIGNAL_CODE) + prop.notifySignal().methodSignature());
|
||||||
|
|
||||||
|
map.insert(key, 42);
|
||||||
|
QCOMPARE(notifySpy.count(), 1);
|
||||||
|
map.insert(key, 43);
|
||||||
|
QCOMPARE(notifySpy.count(), 2);
|
||||||
|
map.insert(key, 43);
|
||||||
|
QCOMPARE(notifySpy.count(), 2);
|
||||||
|
map.insert(key, 44);
|
||||||
|
QCOMPARE(notifySpy.count(), 3);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Test that the valueChanged signal is emitted correctly
|
||||||
|
//
|
||||||
|
QSignalSpy valueChangedSpy(&map, &QQmlPropertyMap::valueChanged);
|
||||||
|
map.setProperty(key, 44);
|
||||||
|
QCOMPARE(valueChangedSpy.count(), 0);
|
||||||
|
map.setProperty(key, 45);
|
||||||
|
QCOMPARE(valueChangedSpy.count(), 1);
|
||||||
|
map.setProperty(key, 45);
|
||||||
|
QCOMPARE(valueChangedSpy.count(), 1);
|
||||||
|
}
|
||||||
|
|
||||||
QTEST_MAIN(tst_QQmlPropertyMap)
|
QTEST_MAIN(tst_QQmlPropertyMap)
|
||||||
|
|
||||||
#include "tst_qqmlpropertymap.moc"
|
#include "tst_qqmlpropertymap.moc"
|
||||||
|
|
|
@ -169,6 +169,8 @@ private slots:
|
||||||
|
|
||||||
void childAt();
|
void childAt();
|
||||||
|
|
||||||
|
void ignoreButtonPressNotInAcceptedMouseButtons();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
enum PaintOrderOp {
|
enum PaintOrderOp {
|
||||||
|
@ -2009,6 +2011,28 @@ void tst_qquickitem::childAt()
|
||||||
QVERIFY(!root->childAt(19,19));
|
QVERIFY(!root->childAt(19,19));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void tst_qquickitem::ignoreButtonPressNotInAcceptedMouseButtons()
|
||||||
|
{
|
||||||
|
// Verify the fix for QTBUG-31861
|
||||||
|
TestItem item;
|
||||||
|
QCOMPARE(item.acceptedMouseButtons(), Qt::MouseButtons(Qt::NoButton));
|
||||||
|
|
||||||
|
QQuickWindow window;
|
||||||
|
item.setSize(QSizeF(200,100));
|
||||||
|
item.setParentItem(window.contentItem());
|
||||||
|
|
||||||
|
item.setAcceptedMouseButtons(Qt::LeftButton);
|
||||||
|
QCOMPARE(item.acceptedMouseButtons(), Qt::MouseButtons(Qt::LeftButton));
|
||||||
|
|
||||||
|
QTest::mousePress(&window, Qt::LeftButton, 0, QPoint(50, 50));
|
||||||
|
QTest::mousePress(&window, Qt::RightButton, 0, QPoint(50, 50)); // ignored because it's not LeftButton
|
||||||
|
QTest::mouseRelease(&window, Qt::RightButton, 0, QPoint(50, 50)); // ignored because it didn't grab the RightButton press
|
||||||
|
QTest::mouseRelease(&window, Qt::LeftButton, 0, QPoint(50, 50));
|
||||||
|
|
||||||
|
QCOMPARE(item.pressCount, 1);
|
||||||
|
QCOMPARE(item.releaseCount, 1);
|
||||||
|
}
|
||||||
|
|
||||||
QTEST_MAIN(tst_qquickitem)
|
QTEST_MAIN(tst_qquickitem)
|
||||||
|
|
||||||
#include "tst_qquickitem.moc"
|
#include "tst_qquickitem.moc"
|
||||||
|
|
|
@ -5,6 +5,7 @@ SUBDIRS += \
|
||||||
compilation \
|
compilation \
|
||||||
javascript \
|
javascript \
|
||||||
holistic \
|
holistic \
|
||||||
|
qqmlchangeset \
|
||||||
qqmlcomponent \
|
qqmlcomponent \
|
||||||
qqmlimage \
|
qqmlimage \
|
||||||
qqmlmetaproperty \
|
qqmlmetaproperty \
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
CONFIG += benchmark
|
||||||
|
TEMPLATE = app
|
||||||
|
TARGET = tst_qqmlchangeset
|
||||||
|
QT += qml quick-private testlib
|
||||||
|
osx:CONFIG -= app_bundle
|
||||||
|
|
||||||
|
SOURCES += tst_qqmlchangeset.cpp
|
||||||
|
|
||||||
|
DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0
|
||||||
|
|
|
@ -0,0 +1,60 @@
|
||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2016 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Milian Wolff <milian.wolff@kdab.com>
|
||||||
|
** Contact: http://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of the test suite of the Qt Toolkit.
|
||||||
|
**
|
||||||
|
** $QT_BEGIN_LICENSE:LGPL21$
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and The Qt Company. For licensing terms
|
||||||
|
** and conditions see http://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at http://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
|
** General Public License version 2.1 or version 3 as published by the Free
|
||||||
|
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
|
||||||
|
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
|
||||||
|
** following information to ensure the GNU Lesser General Public License
|
||||||
|
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
|
||||||
|
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
**
|
||||||
|
** As a special exception, The Qt Company gives you certain additional
|
||||||
|
** rights. These rights are described in The Qt Company LGPL Exception
|
||||||
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||||
|
**
|
||||||
|
** $QT_END_LICENSE$
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include <qtest.h>
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
#include <private/qqmlchangeset_p.h>
|
||||||
|
|
||||||
|
class tst_qqmlchangeset : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void move();
|
||||||
|
};
|
||||||
|
|
||||||
|
void tst_qqmlchangeset::move()
|
||||||
|
{
|
||||||
|
QBENCHMARK {
|
||||||
|
QQmlChangeSet set;
|
||||||
|
const int MAX_ROWS = 30000;
|
||||||
|
for (int i = 0; i < MAX_ROWS; ++i) {
|
||||||
|
set.move(i, MAX_ROWS - 1 - i, 1, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QTEST_MAIN(tst_qqmlchangeset)
|
||||||
|
#include "tst_qqmlchangeset.moc"
|
|
@ -134,7 +134,7 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
extern uint qt_qhash_seed;
|
Q_CORE_EXPORT extern QBasicAtomicInt qt_qhash_seed;
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
|
|
|
@ -17,7 +17,7 @@ macx {
|
||||||
# Prevent qmlplugindump from popping up in the dock when launched.
|
# Prevent qmlplugindump from popping up in the dock when launched.
|
||||||
# We embed the Info.plist file, so the application doesn't need to
|
# We embed the Info.plist file, so the application doesn't need to
|
||||||
# be a bundle.
|
# be a bundle.
|
||||||
QMAKE_LFLAGS += -sectcreate __TEXT __info_plist $$shell_quote($$PWD/Info.plist)
|
QMAKE_LFLAGS += -Wl,-sectcreate,__TEXT,__info_plist,$$shell_quote($$PWD/Info.plist)
|
||||||
CONFIG -= app_bundle
|
CONFIG -= app_bundle
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue