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;
|
||||
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: {
|
||||
struct {
|
||||
float xp;
|
||||
|
@ -2275,6 +2286,19 @@ bool QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache *propertyCa
|
|||
}
|
||||
}
|
||||
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:
|
||||
recordError(binding->valueLocation, tr("Invalid property assignment: regular expression expected; use /pattern/ syntax"));
|
||||
return false;
|
||||
|
|
|
@ -1058,6 +1058,8 @@ bool Codegen::visit(ArrayLiteral *ast)
|
|||
current->expr = _block->CONST(IR::MissingType, 0);
|
||||
}
|
||||
Result expr = expression(it->expression);
|
||||
if (hasError)
|
||||
return false;
|
||||
|
||||
IR::ExprList *arg = _function->New<IR::ExprList>();
|
||||
if (!current) {
|
||||
|
@ -1100,6 +1102,8 @@ bool Codegen::visit(ArrayMemberExpression *ast)
|
|||
|
||||
Result base = expression(ast->base);
|
||||
Result index = expression(ast->expression);
|
||||
if (hasError)
|
||||
return false;
|
||||
_expr.code = subscript(*base, *index);
|
||||
return false;
|
||||
}
|
||||
|
@ -1139,10 +1143,16 @@ bool Codegen::visit(BinaryExpression *ast)
|
|||
|
||||
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);
|
||||
_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);
|
||||
|
||||
_expr.code = _block->TEMP(r);
|
||||
|
@ -1160,10 +1170,16 @@ bool Codegen::visit(BinaryExpression *ast)
|
|||
IR::BasicBlock *endif = _function->newBasicBlock(exceptionHandler());
|
||||
|
||||
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);
|
||||
_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 = endif;
|
||||
|
@ -1173,6 +1189,8 @@ bool Codegen::visit(BinaryExpression *ast)
|
|||
}
|
||||
|
||||
IR::Expr* left = *expression(ast->left);
|
||||
if (hasError)
|
||||
return false;
|
||||
|
||||
switch (ast->op) {
|
||||
case QSOperator::Or:
|
||||
|
@ -1182,17 +1200,19 @@ bool Codegen::visit(BinaryExpression *ast)
|
|||
case QSOperator::Assign: {
|
||||
if (throwSyntaxErrorOnEvalOrArgumentsInStrictMode(left, ast->left->lastSourceLocation()))
|
||||
return false;
|
||||
IR::Expr* right = *expression(ast->right);
|
||||
Result right = expression(ast->right);
|
||||
if (hasError)
|
||||
return false;
|
||||
if (!left->isLValue()) {
|
||||
throwReferenceError(ast->operatorToken, QStringLiteral("left-hand side of assignment operator is not an lvalue"));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_expr.accept(nx)) {
|
||||
move(left, right);
|
||||
move(left, *right);
|
||||
} else {
|
||||
const unsigned t = _block->newTemp();
|
||||
move(_block->TEMP(t), right);
|
||||
move(_block->TEMP(t), *right);
|
||||
move(left, _block->TEMP(t));
|
||||
_expr.code = _block->TEMP(t);
|
||||
}
|
||||
|
@ -1212,17 +1232,19 @@ bool Codegen::visit(BinaryExpression *ast)
|
|||
case QSOperator::InplaceXor: {
|
||||
if (throwSyntaxErrorOnEvalOrArgumentsInStrictMode(left, ast->left->lastSourceLocation()))
|
||||
return false;
|
||||
IR::Expr* right = *expression(ast->right);
|
||||
Result right = expression(ast->right);
|
||||
if (hasError)
|
||||
return false;
|
||||
if (!left->isLValue()) {
|
||||
throwSyntaxError(ast->operatorToken, QStringLiteral("left-hand side of inplace operator is not an lvalue"));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_expr.accept(nx)) {
|
||||
move(left, right, baseOp(ast->op));
|
||||
move(left, *right, baseOp(ast->op));
|
||||
} else {
|
||||
const unsigned t = _block->newTemp();
|
||||
move(_block->TEMP(t), right);
|
||||
move(_block->TEMP(t), *right);
|
||||
move(left, _block->TEMP(t), baseOp(ast->op));
|
||||
_expr.code = left;
|
||||
}
|
||||
|
@ -1245,12 +1267,14 @@ bool Codegen::visit(BinaryExpression *ast)
|
|||
left = _block->TEMP(t);
|
||||
}
|
||||
|
||||
IR::Expr* right = *expression(ast->right);
|
||||
Result right = expression(ast->right);
|
||||
if (hasError)
|
||||
return false;
|
||||
|
||||
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 {
|
||||
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())
|
||||
_expr.code = e;
|
||||
else {
|
||||
|
@ -1279,9 +1303,11 @@ bool Codegen::visit(BinaryExpression *ast)
|
|||
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())
|
||||
_expr.code = e;
|
||||
else {
|
||||
|
@ -1306,11 +1332,15 @@ bool Codegen::visit(CallExpression *ast)
|
|||
IR::ExprList *args = 0, **args_it = &args;
|
||||
for (ArgumentList *it = ast->arguments; it; it = it->next) {
|
||||
Result arg = expression(it->expression);
|
||||
if (hasError)
|
||||
return false;
|
||||
IR::Expr *actual = argument(*arg);
|
||||
*args_it = _function->New<IR::ExprList>();
|
||||
(*args_it)->init(actual);
|
||||
args_it = &(*args_it)->next;
|
||||
}
|
||||
if (hasError)
|
||||
return false;
|
||||
_expr.code = call(*base, args);
|
||||
return false;
|
||||
}
|
||||
|
@ -1329,11 +1359,17 @@ bool Codegen::visit(ConditionalExpression *ast)
|
|||
condition(ast->expression, iftrue, iffalse);
|
||||
|
||||
_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 = 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 = endif;
|
||||
|
@ -1349,6 +1385,8 @@ bool Codegen::visit(DeleteExpression *ast)
|
|||
return false;
|
||||
|
||||
IR::Expr* expr = *expression(ast->expression);
|
||||
if (hasError)
|
||||
return false;
|
||||
// Temporaries cannot be deleted
|
||||
IR::ArgLocal *al = expr->asArgLocal();
|
||||
if (al && al->index < static_cast<unsigned>(_env->members.size())) {
|
||||
|
@ -1410,7 +1448,8 @@ bool Codegen::visit(FieldMemberExpression *ast)
|
|||
return false;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -1501,6 +1540,8 @@ bool Codegen::visit(NewExpression *ast)
|
|||
return false;
|
||||
|
||||
Result base = expression(ast->expression);
|
||||
if (hasError)
|
||||
return false;
|
||||
IR::Expr *expr = *base;
|
||||
if (expr && !expr->asTemp() && !expr->asArgLocal() && !expr->asName() && !expr->asMember()) {
|
||||
const unsigned t = _block->newTemp();
|
||||
|
@ -1517,6 +1558,8 @@ bool Codegen::visit(NewMemberExpression *ast)
|
|||
return false;
|
||||
|
||||
Result base = expression(ast->base);
|
||||
if (hasError)
|
||||
return false;
|
||||
IR::Expr *expr = *base;
|
||||
if (expr && !expr->asTemp() && !expr->asArgLocal() && !expr->asName() && !expr->asMember()) {
|
||||
const unsigned t = _block->newTemp();
|
||||
|
@ -1527,6 +1570,8 @@ bool Codegen::visit(NewMemberExpression *ast)
|
|||
IR::ExprList *args = 0, **args_it = &args;
|
||||
for (ArgumentList *it = ast->arguments; it; it = it->next) {
|
||||
Result arg = expression(it->expression);
|
||||
if (hasError)
|
||||
return false;
|
||||
IR::Expr *actual = argument(*arg);
|
||||
*args_it = _function->New<IR::ExprList>();
|
||||
(*args_it)->init(actual);
|
||||
|
@ -1544,6 +1589,8 @@ bool Codegen::visit(NotExpression *ast)
|
|||
return false;
|
||||
|
||||
Result expr = expression(ast->expression);
|
||||
if (hasError)
|
||||
return false;
|
||||
const unsigned r = _block->newTemp();
|
||||
setLocation(move(_block->TEMP(r), unop(IR::OpNot, *expr, ast->notToken)), ast->notToken);
|
||||
_expr.code = _block->TEMP(r);
|
||||
|
@ -1601,6 +1648,8 @@ bool Codegen::visit(ObjectLiteral *ast)
|
|||
QString name = it->assignment->name->asString();
|
||||
if (PropertyNameAndValue *nv = AST::cast<AST::PropertyNameAndValue *>(it->assignment)) {
|
||||
Result value = expression(nv->value);
|
||||
if (hasError)
|
||||
return false;
|
||||
ObjectPropertyValue &v = valueMap[name];
|
||||
if (v.hasGetter() || v.hasSetter() || (_function->isStrict && v.value)) {
|
||||
throwSyntaxError(nv->lastSourceLocation(),
|
||||
|
@ -1731,6 +1780,8 @@ bool Codegen::visit(PostDecrementExpression *ast)
|
|||
return false;
|
||||
|
||||
Result expr = expression(ast->base);
|
||||
if (hasError)
|
||||
return false;
|
||||
if (!expr->isLValue()) {
|
||||
throwReferenceError(ast->base->lastSourceLocation(), QStringLiteral("Invalid left-hand side expression in postfix operation"));
|
||||
return false;
|
||||
|
@ -1757,6 +1808,8 @@ bool Codegen::visit(PostIncrementExpression *ast)
|
|||
return false;
|
||||
|
||||
Result expr = expression(ast->base);
|
||||
if (hasError)
|
||||
return false;
|
||||
if (!expr->isLValue()) {
|
||||
throwReferenceError(ast->base->lastSourceLocation(), QStringLiteral("Invalid left-hand side expression in postfix operation"));
|
||||
return false;
|
||||
|
@ -1783,6 +1836,8 @@ bool Codegen::visit(PreDecrementExpression *ast)
|
|||
return false;
|
||||
|
||||
Result expr = expression(ast->expression);
|
||||
if (hasError)
|
||||
return false;
|
||||
if (!expr->isLValue()) {
|
||||
throwReferenceError(ast->expression->lastSourceLocation(), QStringLiteral("Prefix ++ operator applied to value that is not a reference."));
|
||||
return false;
|
||||
|
@ -1808,6 +1863,8 @@ bool Codegen::visit(PreIncrementExpression *ast)
|
|||
return false;
|
||||
|
||||
Result expr = expression(ast->expression);
|
||||
if (hasError)
|
||||
return false;
|
||||
if (!expr->isLValue()) {
|
||||
throwReferenceError(ast->expression->lastSourceLocation(), QStringLiteral("Prefix ++ operator applied to value that is not a reference."));
|
||||
return false;
|
||||
|
@ -1860,6 +1917,8 @@ bool Codegen::visit(TildeExpression *ast)
|
|||
return false;
|
||||
|
||||
Result expr = expression(ast->expression);
|
||||
if (hasError)
|
||||
return false;
|
||||
const unsigned t = _block->newTemp();
|
||||
setLocation(move(_block->TEMP(t), unop(IR::OpCompl, *expr, ast->tildeToken)), ast->tildeToken);
|
||||
_expr.code = _block->TEMP(t);
|
||||
|
@ -1885,6 +1944,8 @@ bool Codegen::visit(TypeOfExpression *ast)
|
|||
return false;
|
||||
|
||||
Result expr = expression(ast->expression);
|
||||
if (hasError)
|
||||
return false;
|
||||
IR::ExprList *args = _function->New<IR::ExprList>();
|
||||
args->init(reference(*expr));
|
||||
_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;
|
||||
|
||||
Result expr = expression(ast->expression);
|
||||
if (hasError)
|
||||
return false;
|
||||
const unsigned t = _block->newTemp();
|
||||
setLocation(move(_block->TEMP(t), unop(IR::OpUMinus, *expr, ast->minusToken)), ast->minusToken);
|
||||
_expr.code = _block->TEMP(t);
|
||||
|
@ -1909,6 +1972,8 @@ bool Codegen::visit(UnaryPlusExpression *ast)
|
|||
return false;
|
||||
|
||||
Result expr = expression(ast->expression);
|
||||
if (hasError)
|
||||
return false;
|
||||
const unsigned t = _block->newTemp();
|
||||
setLocation(move(_block->TEMP(t), unop(IR::OpUPlus, *expr, ast->plusToken)), ast->plusToken);
|
||||
_expr.code = _block->TEMP(t);
|
||||
|
@ -2223,7 +2288,10 @@ bool Codegen::visit(ForEachStatement *ast)
|
|||
IR::BasicBlock *foreachend = _function->newBasicBlock(exceptionHandler());
|
||||
|
||||
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>();
|
||||
args->init(_block->TEMP(objectToIterateOn));
|
||||
|
||||
|
@ -2235,7 +2303,10 @@ bool Codegen::visit(ForEachStatement *ast)
|
|||
|
||||
_block = foreachbody;
|
||||
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);
|
||||
_block->JUMP(foreachin);
|
||||
|
||||
|
@ -2725,7 +2796,10 @@ bool Codegen::visit(WithStatement *ast)
|
|||
_function->hasWith = true;
|
||||
|
||||
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
|
||||
IR::BasicBlock *withExceptionHandler = _function->newBasicBlock(exceptionHandler());
|
||||
|
|
|
@ -381,6 +381,8 @@ Message {
|
|||
}
|
||||
\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
|
||||
be accessible from QML.
|
||||
|
||||
|
|
|
@ -102,13 +102,13 @@ public:
|
|||
Q_ALWAYS_INLINE quint64 rawValue() const { return _val; }
|
||||
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 tagOffset() { return 4; }
|
||||
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 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 tagOffset() { return 0; }
|
||||
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
|
||||
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);
|
||||
}
|
||||
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: {
|
||||
struct {
|
||||
float xp;
|
||||
|
@ -541,6 +553,20 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const
|
|||
QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
|
||||
}
|
||||
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:
|
||||
Q_ASSERT(!"not possible");
|
||||
break;
|
||||
|
|
|
@ -278,7 +278,7 @@ int QQmlOpenMetaObject::metaCall(QObject *o, QMetaObject::Call c, int id, void *
|
|||
propertyRead(propId);
|
||||
*reinterpret_cast<QVariant *>(a[0]) = d->getData(propId);
|
||||
} 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);
|
||||
QPair<QVariant, bool> &prop = d->getDataRef(propId);
|
||||
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
|
||||
\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
|
||||
|
||||
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,
|
||||
QQmlProperties &modified,
|
||||
TransitionDirection direction,
|
||||
|
@ -207,27 +228,6 @@ QAbstractAnimationJob* QQuickParentAnimation::transition(QQuickStateActions &act
|
|||
{
|
||||
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 *viaData = new QQuickParentAnimationData;
|
||||
|
||||
|
|
|
@ -1633,6 +1633,12 @@ bool QQuickWindowPrivate::deliverMouseEvent(QMouseEvent *event)
|
|||
}
|
||||
|
||||
if (mouseGrabberItem) {
|
||||
if (event->button() != Qt::NoButton
|
||||
&& mouseGrabberItem->acceptedMouseButtons()
|
||||
&& !(mouseGrabberItem->acceptedMouseButtons() & event->button())) {
|
||||
event->ignore();
|
||||
return false;
|
||||
}
|
||||
QPointF localPos = mouseGrabberItem->mapFromScene(event->windowPos());
|
||||
QScopedPointer<QMouseEvent> me(cloneMouseEvent(event, &localPos));
|
||||
me->accept();
|
||||
|
|
|
@ -48,29 +48,6 @@ DEFINE_BOOL_CONFIG_OPTION(qmlFboOverlay, QML_FBO_OVERLAY)
|
|||
#endif
|
||||
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
|
||||
{
|
||||
class BindableFbo : public QSGBindable
|
||||
|
@ -353,7 +330,7 @@ void QSGDefaultLayer::grab()
|
|||
|
||||
format.setInternalTextureFormat(m_format);
|
||||
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);
|
||||
} else {
|
||||
QOpenGLFramebufferObjectFormat format;
|
||||
|
@ -362,14 +339,14 @@ void QSGDefaultLayer::grab()
|
|||
if (m_recursive) {
|
||||
deleteFboLater = true;
|
||||
delete m_secondaryFbo;
|
||||
m_secondaryFbo = createFramebuffer(m_size, format);
|
||||
m_secondaryFbo = new QOpenGLFramebufferObject(m_size, format);
|
||||
funcs->glBindTexture(GL_TEXTURE_2D, m_secondaryFbo->texture());
|
||||
updateBindOptions(true);
|
||||
m_depthStencilBuffer = m_context->depthStencilBufferForFbo(m_secondaryFbo);
|
||||
} else {
|
||||
delete m_fbo;
|
||||
delete m_secondaryFbo;
|
||||
m_fbo = createFramebuffer(m_size, format);
|
||||
m_fbo = new QOpenGLFramebufferObject(m_size, format);
|
||||
m_secondaryFbo = 0;
|
||||
funcs->glBindTexture(GL_TEXTURE_2D, m_fbo->texture());
|
||||
updateBindOptions(true);
|
||||
|
@ -383,7 +360,7 @@ void QSGDefaultLayer::grab()
|
|||
Q_ASSERT(m_fbo);
|
||||
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());
|
||||
updateBindOptions(true);
|
||||
}
|
||||
|
|
|
@ -599,7 +599,7 @@ void QSGRenderThread::syncAndRender()
|
|||
#endif
|
||||
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";
|
||||
int waitTime = vsyncDelta - (int) waitTimer.elapsed();
|
||||
if (waitTime > 0)
|
||||
|
|
|
@ -324,6 +324,7 @@ private slots:
|
|||
void qtbug_46022();
|
||||
void qtbug_52340();
|
||||
void qtbug_54589();
|
||||
void qtbug_54687();
|
||||
|
||||
private:
|
||||
// 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);
|
||||
}
|
||||
|
||||
void tst_qqmlecmascript::qtbug_54687()
|
||||
{
|
||||
QJSEngine e;
|
||||
// it's simple: this shouldn't crash.
|
||||
engine.evaluate("12\n----12");
|
||||
}
|
||||
|
||||
QTEST_MAIN(tst_qqmlecmascript)
|
||||
|
||||
|
|
|
@ -26,7 +26,9 @@ MyTypeObject {
|
|||
boolProperty: true
|
||||
variantProperty: "Hello World!"
|
||||
vectorProperty: "10,1,2.2"
|
||||
vector2Property: "2, 3"
|
||||
vector4Property: "10,1,2.2,2.3"
|
||||
quaternionProperty: "4,5,6,7"
|
||||
urlProperty: "main.qml?with%3cencoded%3edata"
|
||||
|
||||
objectProperty: MyTypeObject { intProperty: 8 }
|
||||
|
|
|
@ -33,8 +33,10 @@
|
|||
#include <QtCore/qdatetime.h>
|
||||
#include <QtGui/qmatrix.h>
|
||||
#include <QtGui/qcolor.h>
|
||||
#include <QtGui/qvector2d.h>
|
||||
#include <QtGui/qvector3d.h>
|
||||
#include <QtGui/qvector4d.h>
|
||||
#include <QtGui/qquaternion.h>
|
||||
#include <QtQml/qqml.h>
|
||||
#include <QtQml/qqmlcomponent.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(bool boolProperty READ boolProperty WRITE setBoolProperty NOTIFY boolPropertyChanged)
|
||||
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(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(QQmlScriptString scriptProperty READ scriptProperty WRITE setScriptProperty)
|
||||
|
@ -524,6 +528,15 @@ public:
|
|||
emit vectorPropertyChanged();
|
||||
}
|
||||
|
||||
QVector2D vector2PropertyValue;
|
||||
QVector2D vector2Property() const {
|
||||
return vector2PropertyValue;
|
||||
}
|
||||
void setVector2Property(const QVector2D &v) {
|
||||
vector2PropertyValue = v;
|
||||
emit vector2PropertyChanged();
|
||||
}
|
||||
|
||||
QVector4D vector4PropertyValue;
|
||||
QVector4D vector4Property() const {
|
||||
return vector4PropertyValue;
|
||||
|
@ -533,6 +546,15 @@ public:
|
|||
emit vector4PropertyChanged();
|
||||
}
|
||||
|
||||
QQuaternion quaternionPropertyValue;
|
||||
QQuaternion quaternionProperty() const {
|
||||
return quaternionPropertyValue;
|
||||
}
|
||||
void setQuaternionProperty(const QQuaternion &v) {
|
||||
quaternionPropertyValue = v;
|
||||
emit quaternionPropertyChanged();
|
||||
}
|
||||
|
||||
QUrl urlPropertyValue;
|
||||
QUrl urlProperty() const {
|
||||
return urlPropertyValue;
|
||||
|
@ -586,7 +608,9 @@ signals:
|
|||
void boolPropertyChanged();
|
||||
void variantPropertyChanged();
|
||||
void vectorPropertyChanged();
|
||||
void vector2PropertyChanged();
|
||||
void vector4PropertyChanged();
|
||||
void quaternionPropertyChanged();
|
||||
void urlPropertyChanged();
|
||||
|
||||
};
|
||||
|
|
|
@ -677,6 +677,7 @@ void tst_qqmllanguage::assignBasicTypes()
|
|||
QCOMPARE(object->boolProperty(), true);
|
||||
QCOMPARE(object->variantProperty(), QVariant("Hello World!"));
|
||||
QCOMPARE(object->vectorProperty(), QVector3D(10, 1, 2.2f));
|
||||
QCOMPARE(object->vector2Property(), QVector2D(2, 3));
|
||||
QCOMPARE(object->vector4Property(), QVector4D(10, 1, 2.2f, 2.3f));
|
||||
const QUrl encoded = QUrl::fromEncoded("main.qml?with%3cencoded%3edata", QUrl::TolerantMode);
|
||||
QCOMPARE(object->urlProperty(), component.url().resolved(encoded));
|
||||
|
|
|
@ -60,6 +60,7 @@ private slots:
|
|||
void QTBUG_35233();
|
||||
void disallowExtending();
|
||||
void QTBUG_35906();
|
||||
void QTBUG_48136();
|
||||
};
|
||||
|
||||
class LazyPropertyMap : public QQmlPropertyMap, public QQmlParserStatus
|
||||
|
@ -462,6 +463,40 @@ void tst_QQmlPropertyMap::QTBUG_35906()
|
|||
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)
|
||||
|
||||
#include "tst_qqmlpropertymap.moc"
|
||||
|
|
|
@ -169,6 +169,8 @@ private slots:
|
|||
|
||||
void childAt();
|
||||
|
||||
void ignoreButtonPressNotInAcceptedMouseButtons();
|
||||
|
||||
private:
|
||||
|
||||
enum PaintOrderOp {
|
||||
|
@ -2009,6 +2011,28 @@ void tst_qquickitem::childAt()
|
|||
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)
|
||||
|
||||
#include "tst_qquickitem.moc"
|
||||
|
|
|
@ -5,6 +5,7 @@ SUBDIRS += \
|
|||
compilation \
|
||||
javascript \
|
||||
holistic \
|
||||
qqmlchangeset \
|
||||
qqmlcomponent \
|
||||
qqmlimage \
|
||||
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[])
|
||||
{
|
||||
|
|
|
@ -17,7 +17,7 @@ macx {
|
|||
# Prevent qmlplugindump from popping up in the dock when launched.
|
||||
# We embed the Info.plist file, so the application doesn't need to
|
||||
# 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
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue