summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--examples/qml/tutorials/extending-qml/chapter4-customPropertyTypes/piechart.cpp2
-rw-r--r--examples/qml/tutorials/extending-qml/chapter5-listproperties/pieslice.cpp2
-rw-r--r--examples/quick/demos/demos.pro3
-rw-r--r--examples/quick/demos/photoviewer/deployment.pri19
-rw-r--r--examples/quick/demos/photoviewer/photoviewer.pro7
-rw-r--r--examples/quick/scenegraph/simplematerial/doc/src/simplematerial.qdoc4
-rw-r--r--src/imports/localstorage/plugin.cpp5
-rw-r--r--src/qml/compiler/qqmlpropertyvalidator.cpp22
-rw-r--r--src/qml/compiler/qv4codegen.cpp116
-rw-r--r--src/qml/doc/src/cppintegration/data.qdoc2
-rw-r--r--src/qml/doc/src/qmllanguageref/syntax/objectattributes.qdoc2
-rw-r--r--src/qml/jsruntime/qv4internalclass.cpp8
-rw-r--r--src/qml/jsruntime/qv4value_p.h4
-rw-r--r--src/qml/qml/qqmlcomponent.cpp2
-rw-r--r--src/qml/qml/qqmlobjectcreator.cpp24
-rw-r--r--src/qml/qml/qqmlopenmetaobject.cpp2
-rw-r--r--src/quick/doc/src/concepts/modelviewsdata/cppmodels.qdoc105
-rw-r--r--src/quick/items/qquickflickable.cpp4
-rw-r--r--src/quick/items/qquickitem.cpp3
-rw-r--r--src/quick/items/qquickitemanimation.cpp42
-rw-r--r--src/quick/items/qquicktextedit.cpp4
-rw-r--r--src/quick/items/qquickwindow.cpp36
-rw-r--r--src/quick/items/qquickwindow_p.h6
-rw-r--r--src/quick/scenegraph/qsgthreadedrenderloop.cpp2
-rw-r--r--src/quick/scenegraph/util/qsgatlastexture.cpp4
-rw-r--r--tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp18
-rw-r--r--tests/auto/qml/qqmlecmascript/data/qtbug_54589.qml16
-rw-r--r--tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp18
-rw-r--r--tests/auto/qml/qqmllanguage/data/assignBasicTypes.qml2
-rw-r--r--tests/auto/qml/qqmllanguage/testtypes.h24
-rw-r--r--tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp1
-rw-r--r--tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp6
-rw-r--r--tests/auto/qml/qqmlpropertymap/tst_qqmlpropertymap.cpp35
-rw-r--r--tests/auto/quick/qquickflickable/data/ratios_smallContent.qml19
-rw-r--r--tests/auto/quick/qquickflickable/tst_qquickflickable.cpp28
-rw-r--r--tests/auto/quick/qquickitem/tst_qquickitem.cpp24
-rw-r--r--tests/auto/quick/qquicklistview/tst_qquicklistview.cpp6
-rw-r--r--tests/auto/quick/qquickshadereffect/data/MyIcon.qml76
-rw-r--r--tests/auto/quick/qquickshadereffect/data/twoImagesOneShaderEffect.qml61
-rw-r--r--tests/auto/quick/qquickshadereffect/tst_qquickshadereffect.cpp14
-rw-r--r--tests/auto/quick/qquickwindow/tst_qquickwindow.cpp85
-rw-r--r--tests/benchmarks/qml/qml.pro1
-rw-r--r--tests/benchmarks/qml/qqmlchangeset/qqmlchangeset.pro10
-rw-r--r--tests/benchmarks/qml/qqmlchangeset/tst_qqmlchangeset.cpp60
-rw-r--r--tests/manual/scenegraph_lancelot/scenegrabber/main.cpp2
m---------tests/manual/v4/test2620
-rw-r--r--tools/qmlplugindump/qmlplugindump.pro2
47 files changed, 817 insertions, 121 deletions
diff --git a/examples/qml/tutorials/extending-qml/chapter4-customPropertyTypes/piechart.cpp b/examples/qml/tutorials/extending-qml/chapter4-customPropertyTypes/piechart.cpp
index 965e5152c1..d963b6d1b4 100644
--- a/examples/qml/tutorials/extending-qml/chapter4-customPropertyTypes/piechart.cpp
+++ b/examples/qml/tutorials/extending-qml/chapter4-customPropertyTypes/piechart.cpp
@@ -41,7 +41,7 @@
#include "pieslice.h"
PieChart::PieChart(QQuickItem *parent)
- : QQuickItem(parent)
+ : QQuickItem(parent), m_pieSlice(0)
{
}
diff --git a/examples/qml/tutorials/extending-qml/chapter5-listproperties/pieslice.cpp b/examples/qml/tutorials/extending-qml/chapter5-listproperties/pieslice.cpp
index ceb0041ec8..50c018e33e 100644
--- a/examples/qml/tutorials/extending-qml/chapter5-listproperties/pieslice.cpp
+++ b/examples/qml/tutorials/extending-qml/chapter5-listproperties/pieslice.cpp
@@ -42,7 +42,7 @@
#include <QPainter>
PieSlice::PieSlice(QQuickItem *parent)
- : QQuickPaintedItem(parent)
+ : QQuickPaintedItem(parent), m_fromAngle(0), m_angleSpan(0)
{
}
diff --git a/examples/quick/demos/demos.pro b/examples/quick/demos/demos.pro
index 9aac7bf6f7..e6937683ab 100644
--- a/examples/quick/demos/demos.pro
+++ b/examples/quick/demos/demos.pro
@@ -5,9 +5,8 @@ SUBDIRS = samegame \
tweetsearch \
maroon \
photosurface \
+ photoviewer \
stocqt
qtHaveModule(xmlpatterns): SUBDIRS += rssnews
-EXAMPLE_FILES = \
- photoviewer
diff --git a/examples/quick/demos/photoviewer/deployment.pri b/examples/quick/demos/photoviewer/deployment.pri
deleted file mode 100644
index 0d58a25c61..0000000000
--- a/examples/quick/demos/photoviewer/deployment.pri
+++ /dev/null
@@ -1,19 +0,0 @@
-android {
- x86 {
- target.path = /libs/x86
- } else: armeabi-v7a {
- target.path = /libs/armeabi-v7a
- } else {
- target.path = /libs/armeabi
- }
- export(target.path)
- INSTALLS += target
-} else:unix {
- isEmpty(target.path) {
- target.path = /opt/$${TARGET}/bin
- export(target.path)
- }
- INSTALLS += target
-}
-
-export(INSTALLS)
diff --git a/examples/quick/demos/photoviewer/photoviewer.pro b/examples/quick/demos/photoviewer/photoviewer.pro
index 704e2ce003..4bfdb86f31 100644
--- a/examples/quick/demos/photoviewer/photoviewer.pro
+++ b/examples/quick/demos/photoviewer/photoviewer.pro
@@ -15,8 +15,5 @@ TRANSLATIONS += i18n/qml_fr.ts \
RESOURCES += qml.qrc
-# Additional import path used to resolve QML modules in Qt Creator's code model
-QML_IMPORT_PATH =
-
-# Default rules for deployment.
-include(deployment.pri)
+target.path = $$[QT_INSTALL_EXAMPLES]/quick/demos/photoviewer
+INSTALLS += target
diff --git a/examples/quick/scenegraph/simplematerial/doc/src/simplematerial.qdoc b/examples/quick/scenegraph/simplematerial/doc/src/simplematerial.qdoc
index 278f154781..d6eb711929 100644
--- a/examples/quick/scenegraph/simplematerial/doc/src/simplematerial.qdoc
+++ b/examples/quick/scenegraph/simplematerial/doc/src/simplematerial.qdoc
@@ -102,8 +102,8 @@
state and we use it to update the shader program with the current
color. The previous state is passed in as a second parameter so
that the user can update only that which has changed. In our
- usecase, where all the colors are different, the updateState will
- be called once for every node.
+ use case, where all the colors are different, the updateState()
+ function will be called once for every node.
\snippet scenegraph/simplematerial/simplematerial.cpp 7
diff --git a/src/imports/localstorage/plugin.cpp b/src/imports/localstorage/plugin.cpp
index 7d96f11768..f59ccc551e 100644
--- a/src/imports/localstorage/plugin.cpp
+++ b/src/imports/localstorage/plugin.cpp
@@ -149,7 +149,12 @@ public:
using namespace QV4;
+QT_WARNING_PUSH
+#if (Q_CC_GNU >= 600)
+QT_WARNING_DISABLE_GCC("-Wtautological-compare")
+#endif
DEFINE_OBJECT_VTABLE(QV4::QQmlSqlDatabaseWrapper);
+QT_WARNING_POP
diff --git a/src/qml/compiler/qqmlpropertyvalidator.cpp b/src/qml/compiler/qqmlpropertyvalidator.cpp
index 9ea52e240d..c644330e97 100644
--- a/src/qml/compiler/qqmlpropertyvalidator.cpp
+++ b/src/qml/compiler/qqmlpropertyvalidator.cpp
@@ -492,6 +492,16 @@ QQmlCompileError QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache
}
}
break;
+ case QVariant::Vector2D: {
+ struct {
+ float xp;
+ float yp;
+ } vec;
+ if (!QQmlStringConverters::createFromString(QMetaType::QVector2D, binding->valueAsString(qmlUnit), &vec, sizeof(vec))) {
+ return QQmlCompileError(binding->valueLocation, tr("Invalid property assignment: 2D vector expected"));
+ }
+ }
+ break;
case QVariant::Vector3D: {
struct {
float xp;
@@ -515,6 +525,18 @@ QQmlCompileError QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache
}
}
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))) {
+ return QQmlCompileError(binding->valueLocation, tr("Invalid property assignment: quaternion expected"));
+ }
+ }
+ break;
case QVariant::RegExp:
return QQmlCompileError(binding->valueLocation, tr("Invalid property assignment: regular expression expected; use /pattern/ syntax"));
default: {
diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp
index 7a444e8c57..4130ad08d7 100644
--- a/src/qml/compiler/qv4codegen.cpp
+++ b/src/qml/compiler/qv4codegen.cpp
@@ -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);
@@ -2224,7 +2289,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));
@@ -2236,7 +2304,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);
@@ -2726,7 +2797,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());
diff --git a/src/qml/doc/src/cppintegration/data.qdoc b/src/qml/doc/src/cppintegration/data.qdoc
index 0d875bd10f..7bb4d701e2 100644
--- a/src/qml/doc/src/cppintegration/data.qdoc
+++ b/src/qml/doc/src/cppintegration/data.qdoc
@@ -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.
diff --git a/src/qml/doc/src/qmllanguageref/syntax/objectattributes.qdoc b/src/qml/doc/src/qmllanguageref/syntax/objectattributes.qdoc
index 04d0d0ed2e..de0515e5d0 100644
--- a/src/qml/doc/src/qmllanguageref/syntax/objectattributes.qdoc
+++ b/src/qml/doc/src/qmllanguageref/syntax/objectattributes.qdoc
@@ -729,7 +729,7 @@ Rectangle {
MouseArea {
anchors.fill: parent
onPressed: root.activated(mouse.x, mouse.y)
- onRelased: root.deactivated()
+ onReleased: root.deactivated()
}
}
\endqml
diff --git a/src/qml/jsruntime/qv4internalclass.cpp b/src/qml/jsruntime/qv4internalclass.cpp
index f46f581168..bac45e18c8 100644
--- a/src/qml/jsruntime/qv4internalclass.cpp
+++ b/src/qml/jsruntime/qv4internalclass.cpp
@@ -147,8 +147,8 @@ static void insertHoleIntoPropertyData(Object *object, int idx)
static void removeFromPropertyData(Object *object, int idx, bool accessor = false)
{
int inlineSize = object->d()->inlineMemberSize;
- int icSize = object->internalClass()->size;
int delta = (accessor ? 2 : 1);
+ int oldSize = object->internalClass()->size + delta;
int to = idx;
int from = to + delta;
if (from < inlineSize) {
@@ -156,15 +156,15 @@ static void removeFromPropertyData(Object *object, int idx, bool accessor = fals
to = inlineSize - delta;
from = inlineSize;
}
- if (to < inlineSize && from < icSize) {
+ if (to < inlineSize && from < oldSize) {
Q_ASSERT(from >= inlineSize);
memcpy(object->propertyData(to), object->d()->propertyData(from), (inlineSize - to)*sizeof(Value));
to = inlineSize;
from = inlineSize + delta;
}
- if (from < icSize + delta) {
+ if (from < oldSize) {
Q_ASSERT(to >= inlineSize && from > to);
- memmove(object->propertyData(to), object->d()->propertyData(from), (icSize + delta - to)*sizeof(Value));
+ memmove(object->propertyData(to), object->d()->propertyData(from), (oldSize - to)*sizeof(Value));
}
}
diff --git a/src/qml/jsruntime/qv4value_p.h b/src/qml/jsruntime/qv4value_p.h
index d24a5c4c76..dae4d11767 100644
--- a/src/qml/jsruntime/qv4value_p.h
+++ b/src/qml/jsruntime/qv4value_p.h
@@ -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; }
diff --git a/src/qml/qml/qqmlcomponent.cpp b/src/qml/qml/qqmlcomponent.cpp
index 175b84e7c5..9c7b4fe1c0 100644
--- a/src/qml/qml/qqmlcomponent.cpp
+++ b/src/qml/qml/qqmlcomponent.cpp
@@ -1135,7 +1135,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.
diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp
index f2b3276778..3000f3e695 100644
--- a/src/qml/qml/qqmlobjectcreator.cpp
+++ b/src/qml/qml/qqmlobjectcreator.cpp
@@ -480,6 +480,17 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const
property->writeProperty(_qobject, &value, propertyWriteFlags);
}
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);
+ property->writeProperty(_qobject, &vec, propertyWriteFlags);
+ }
+ break;
case QVariant::Vector3D: {
struct {
float xp;
@@ -505,6 +516,19 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const
property->writeProperty(_qobject, &vec, propertyWriteFlags);
}
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);
+ property->writeProperty(_qobject, &vec, propertyWriteFlags);
+ }
+ break;
case QVariant::RegExp:
Q_ASSERT(!"not possible");
break;
diff --git a/src/qml/qml/qqmlopenmetaobject.cpp b/src/qml/qml/qqmlopenmetaobject.cpp
index 22c4072aec..0fd9e63bde 100644
--- a/src/qml/qml/qqmlopenmetaobject.cpp
+++ b/src/qml/qml/qqmlopenmetaobject.cpp
@@ -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]));
diff --git a/src/quick/doc/src/concepts/modelviewsdata/cppmodels.qdoc b/src/quick/doc/src/concepts/modelviewsdata/cppmodels.qdoc
index cb281a2d4a..a764402c2f 100644
--- a/src/quick/doc/src/concepts/modelviewsdata/cppmodels.qdoc
+++ b/src/quick/doc/src/concepts/modelviewsdata/cppmodels.qdoc
@@ -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
diff --git a/src/quick/items/qquickflickable.cpp b/src/quick/items/qquickflickable.cpp
index a09088dfed..dcba5c2d71 100644
--- a/src/quick/items/qquickflickable.cpp
+++ b/src/quick/items/qquickflickable.cpp
@@ -1590,13 +1590,13 @@ qreal QQuickFlickable::minXExtent() const
qreal QQuickFlickable::maxXExtent() const
{
Q_D(const QQuickFlickable);
- return qMin<qreal>(0, width() - vWidth() - d->hData.endMargin);
+ return qMin<qreal>(minXExtent(), width() - vWidth() - d->hData.endMargin);
}
/* returns -ve */
qreal QQuickFlickable::maxYExtent() const
{
Q_D(const QQuickFlickable);
- return qMin<qreal>(0, height() - vHeight() - d->vData.endMargin);
+ return qMin<qreal>(minYExtent(), height() - vHeight() - d->vData.endMargin);
}
void QQuickFlickable::componentComplete()
diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp
index 07a415eecd..8905faf973 100644
--- a/src/quick/items/qquickitem.cpp
+++ b/src/quick/items/qquickitem.cpp
@@ -2090,6 +2090,9 @@ void QQuickItemPrivate::updateSubFocusItem(QQuickItem *scope, bool focus)
\value ItemDevicePixelRatioHasChanged The device pixel ratio of the screen
the item is on has changed. ItemChangedData::realValue contains the new
device pixel ratio.
+
+ \value ItemAntialiasingHasChanged The antialiasing has changed. The current
+ (boolean) value can be found in QQuickItem::antialiasing.
*/
/*!
diff --git a/src/quick/items/qquickitemanimation.cpp b/src/quick/items/qquickitemanimation.cpp
index 962f410095..027c07ec07 100644
--- a/src/quick/items/qquickitemanimation.cpp
+++ b/src/quick/items/qquickitemanimation.cpp
@@ -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;
diff --git a/src/quick/items/qquicktextedit.cpp b/src/quick/items/qquicktextedit.cpp
index eb568c48d4..d6d9d53a3b 100644
--- a/src/quick/items/qquicktextedit.cpp
+++ b/src/quick/items/qquicktextedit.cpp
@@ -1489,8 +1489,8 @@ void QQuickTextEdit::setSelectByKeyboard(bool on)
If true, the user can use the mouse to select text in some
platform-specific way. Note that for some platforms this may
- not be an appropriate interaction (eg. may conflict with how
- the text needs to behave inside a Flickable.
+ not be an appropriate interaction; it may conflict with how
+ the text needs to behave inside a Flickable, for example.
*/
bool QQuickTextEdit::selectByMouse() const
{
diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp
index 56466fdbd1..a2c82c30a0 100644
--- a/src/quick/items/qquickwindow.cpp
+++ b/src/quick/items/qquickwindow.cpp
@@ -707,10 +707,10 @@ bool QQuickWindowPrivate::translateTouchToMouse(QQuickItem *item, QTouchEvent *e
lastMousePosition = me->windowPos();
bool accepted = me->isAccepted();
- bool delivered = deliverHoverEvent(contentItem, me->windowPos(), last, me->modifiers(), accepted);
+ bool delivered = deliverHoverEvent(contentItem, me->windowPos(), last, me->modifiers(), me->timestamp(), accepted);
if (!delivered) {
//take care of any exits
- accepted = clearHover();
+ accepted = clearHover(me->timestamp());
}
me->setAccepted(accepted);
break;
@@ -1488,7 +1488,7 @@ QQuickItem *QQuickWindow::mouseGrabberItem() const
}
-bool QQuickWindowPrivate::clearHover()
+bool QQuickWindowPrivate::clearHover(ulong timestamp)
{
Q_Q(QQuickWindow);
if (hoverItems.isEmpty())
@@ -1498,7 +1498,7 @@ bool QQuickWindowPrivate::clearHover()
bool accepted = false;
foreach (QQuickItem* item, hoverItems)
- accepted = sendHoverEvent(QEvent::HoverLeave, item, pos, pos, QGuiApplication::keyboardModifiers(), true) || accepted;
+ accepted = sendHoverEvent(QEvent::HoverLeave, item, pos, pos, QGuiApplication::keyboardModifiers(), timestamp, true) || accepted;
hoverItems.clear();
return accepted;
}
@@ -1678,6 +1678,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();
@@ -1692,13 +1698,15 @@ bool QQuickWindowPrivate::deliverMouseEvent(QMouseEvent *event)
bool QQuickWindowPrivate::sendHoverEvent(QEvent::Type type, QQuickItem *item,
const QPointF &scenePos, const QPointF &lastScenePos,
- Qt::KeyboardModifiers modifiers, bool accepted)
+ Qt::KeyboardModifiers modifiers, ulong timestamp,
+ bool accepted)
{
Q_Q(QQuickWindow);
const QTransform transform = QQuickItemPrivate::get(item)->windowToItemTransform();
//create copy of event
QHoverEvent hoverEvent(type, transform.map(scenePos), transform.map(lastScenePos), modifiers);
+ hoverEvent.setTimestamp(timestamp);
hoverEvent.setAccepted(accepted);
QSet<QQuickItem *> hasFiltered;
@@ -1712,7 +1720,7 @@ bool QQuickWindowPrivate::sendHoverEvent(QEvent::Type type, QQuickItem *item,
}
bool QQuickWindowPrivate::deliverHoverEvent(QQuickItem *item, const QPointF &scenePos, const QPointF &lastScenePos,
- Qt::KeyboardModifiers modifiers, bool &accepted)
+ Qt::KeyboardModifiers modifiers, ulong timestamp, bool &accepted)
{
Q_Q(QQuickWindow);
QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
@@ -1730,7 +1738,7 @@ bool QQuickWindowPrivate::deliverHoverEvent(QQuickItem *item, const QPointF &sce
QQuickItem *child = children.at(ii);
if (!child->isVisible() || !child->isEnabled() || QQuickItemPrivate::get(child)->culled)
continue;
- if (deliverHoverEvent(child, scenePos, lastScenePos, modifiers, accepted))
+ if (deliverHoverEvent(child, scenePos, lastScenePos, modifiers, timestamp, accepted))
return true;
}
}
@@ -1740,7 +1748,7 @@ bool QQuickWindowPrivate::deliverHoverEvent(QQuickItem *item, const QPointF &sce
if (item->contains(p)) {
if (!hoverItems.isEmpty() && hoverItems[0] == item) {
//move
- accepted = sendHoverEvent(QEvent::HoverMove, item, scenePos, lastScenePos, modifiers, accepted);
+ accepted = sendHoverEvent(QEvent::HoverMove, item, scenePos, lastScenePos, modifiers, timestamp, accepted);
} else {
QList<QQuickItem *> itemsToHover;
QQuickItem* parent = item;
@@ -1751,12 +1759,12 @@ bool QQuickWindowPrivate::deliverHoverEvent(QQuickItem *item, const QPointF &sce
// Leaving from previous hovered items until we reach the item or one of its ancestors.
while (!hoverItems.isEmpty() && !itemsToHover.contains(hoverItems[0])) {
QQuickItem *hoverLeaveItem = hoverItems.takeFirst();
- sendHoverEvent(QEvent::HoverLeave, hoverLeaveItem, scenePos, lastScenePos, modifiers, accepted);
+ sendHoverEvent(QEvent::HoverLeave, hoverLeaveItem, scenePos, lastScenePos, modifiers, timestamp, accepted);
}
if (!hoverItems.isEmpty() && hoverItems[0] == item){//Not entering a new Item
// ### Shouldn't we send moves for the parent items as well?
- accepted = sendHoverEvent(QEvent::HoverMove, item, scenePos, lastScenePos, modifiers, accepted);
+ accepted = sendHoverEvent(QEvent::HoverMove, item, scenePos, lastScenePos, modifiers, timestamp, accepted);
} else {
// Enter items that are not entered yet.
int startIdx = -1;
@@ -1775,7 +1783,7 @@ bool QQuickWindowPrivate::deliverHoverEvent(QQuickItem *item, const QPointF &sce
// itemToHoverPrivate->window here prevents that case.
if (itemToHoverPrivate->window == q && itemToHoverPrivate->hoverEnabled) {
hoverItems.prepend(itemToHover);
- sendHoverEvent(QEvent::HoverEnter, itemToHover, scenePos, lastScenePos, modifiers, accepted);
+ sendHoverEvent(QEvent::HoverEnter, itemToHover, scenePos, lastScenePos, modifiers, timestamp, accepted);
}
}
}
@@ -2076,10 +2084,10 @@ void QQuickWindowPrivate::handleMouseEvent(QMouseEvent *event)
lastMousePosition = event->windowPos();
bool accepted = event->isAccepted();
- bool delivered = deliverHoverEvent(contentItem, event->windowPos(), last, event->modifiers(), accepted);
+ bool delivered = deliverHoverEvent(contentItem, event->windowPos(), last, event->modifiers(), event->timestamp(), accepted);
if (!delivered) {
//take care of any exits
- accepted = clearHover();
+ accepted = clearHover(event->timestamp());
}
event->setAccepted(accepted);
return;
@@ -2110,7 +2118,7 @@ void QQuickWindowPrivate::flushFrameSynchronousEvents()
// whether it has moved into a position where it is now under the cursor.
if (!mouseGrabberItem && !lastMousePosition.isNull()) {
bool accepted = false;
- bool delivered = deliverHoverEvent(contentItem, lastMousePosition, lastMousePosition, QGuiApplication::keyboardModifiers(), accepted);
+ bool delivered = deliverHoverEvent(contentItem, lastMousePosition, lastMousePosition, QGuiApplication::keyboardModifiers(), 0, accepted);
if (!delivered)
clearHover(); // take care of any exits
}
diff --git a/src/quick/items/qquickwindow_p.h b/src/quick/items/qquickwindow_p.h
index 71f2bb5778..40a361a897 100644
--- a/src/quick/items/qquickwindow_p.h
+++ b/src/quick/items/qquickwindow_p.h
@@ -165,14 +165,14 @@ public:
bool deliverTouchCancelEvent(QTouchEvent *);
void deliverDelayedTouchEvent();
void flushFrameSynchronousEvents();
- bool deliverHoverEvent(QQuickItem *, const QPointF &scenePos, const QPointF &lastScenePos, Qt::KeyboardModifiers modifiers, bool &accepted);
+ bool deliverHoverEvent(QQuickItem *, const QPointF &scenePos, const QPointF &lastScenePos, Qt::KeyboardModifiers modifiers, ulong timestamp, bool &accepted);
bool deliverMatchingPointsToItem(QQuickItem *item, QTouchEvent *event, QSet<int> *acceptedNewPoints, const QSet<int> &matchingNewPoints, const QList<QTouchEvent::TouchPoint> &matchingPoints, QSet<QQuickItem*> *filtered);
static QTouchEvent *touchEventForItem(QQuickItem *target, const QTouchEvent &originalEvent, bool alwaysCheckBounds = false);
static QTouchEvent *touchEventWithPoints(const QTouchEvent &event, const QList<QTouchEvent::TouchPoint> &newPoints);
bool sendFilteredTouchEvent(QQuickItem *target, QQuickItem *item, QTouchEvent *event, QSet<QQuickItem*> *filtered);
bool sendHoverEvent(QEvent::Type, QQuickItem *, const QPointF &scenePos, const QPointF &lastScenePos,
- Qt::KeyboardModifiers modifiers, bool accepted);
- bool clearHover();
+ Qt::KeyboardModifiers modifiers, ulong timestamp, bool accepted);
+ bool clearHover(ulong timestamp = 0);
#ifndef QT_NO_DRAGANDDROP
void deliverDragEvent(QQuickDragGrabber *, QEvent *);
bool deliverDragEvent(QQuickDragGrabber *, QQuickItem *, QDragMoveEvent *);
diff --git a/src/quick/scenegraph/qsgthreadedrenderloop.cpp b/src/quick/scenegraph/qsgthreadedrenderloop.cpp
index 3ff32b360d..6b9c67b2bd 100644
--- a/src/quick/scenegraph/qsgthreadedrenderloop.cpp
+++ b/src/quick/scenegraph/qsgthreadedrenderloop.cpp
@@ -600,7 +600,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)
diff --git a/src/quick/scenegraph/util/qsgatlastexture.cpp b/src/quick/scenegraph/util/qsgatlastexture.cpp
index 098a4a666b..40c3293c7b 100644
--- a/src/quick/scenegraph/util/qsgatlastexture.cpp
+++ b/src/quick/scenegraph/util/qsgatlastexture.cpp
@@ -158,13 +158,13 @@ Atlas::Atlas(const QSize &size)
wrongfullyReportsBgra8888Support = false;
const char *ext = (const char *) QOpenGLContext::currentContext()->functions()->glGetString(GL_EXTENSIONS);
- if (!wrongfullyReportsBgra8888Support
+ if (ext && !wrongfullyReportsBgra8888Support
&& (strstr(ext, "GL_EXT_bgra")
|| strstr(ext, "GL_EXT_texture_format_BGRA8888")
|| strstr(ext, "GL_IMG_texture_format_BGRA8888"))) {
m_internalFormat = m_externalFormat = GL_BGRA;
#if defined(Q_OS_DARWIN) && !defined(Q_OS_OSX)
- } else if (strstr(ext, "GL_APPLE_texture_format_BGRA8888")) {
+ } else if (ext && strstr(ext, "GL_APPLE_texture_format_BGRA8888")) {
m_internalFormat = GL_RGBA;
m_externalFormat = GL_BGRA;
#endif // IOS || TVOS
diff --git a/tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp b/tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp
index 52c9953970..c4b17aa60a 100644
--- a/tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp
+++ b/tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp
@@ -609,12 +609,11 @@ void tst_QQmlProfilerService::scenegraphData()
checkTraceReceived();
checkJsHeap();
-
- // check that at least one frame was rendered
- // there should be a SGPolishAndSync + SGRendererFrame + SGRenderLoopFrame sequence
- // (though we can't be sure to get the SGRenderLoopFrame in the threaded renderer)
+ // Check that at least one frame was rendered.
+ // There should be a SGContextFrame + SGRendererFrame + SGRenderLoopFrame sequence,
+ // but we can't be sure to get the SGRenderLoopFrame in the threaded renderer.
//
- // since the rendering happens in a different thread, there could be other unrelated events
+ // Since the rendering happens in a different thread, there could be other unrelated events
// interleaved. Also, events could carry the same time stamps and be sorted in an unexpected way
// if the clocks are acting up.
qint64 contextFrameTime = -1;
@@ -643,8 +642,13 @@ void tst_QQmlProfilerService::scenegraphData()
foreach (const QQmlProfilerData &msg, m_client->asynchronousMessages) {
if (msg.detailType == QQmlProfilerDefinitions::SceneGraphRenderLoopFrame) {
- QVERIFY(msg.time >= renderFrameTime);
- break;
+ if (msg.time >= contextFrameTime) {
+ // Make sure SceneGraphRenderLoopFrame is not between SceneGraphContextFrame and
+ // SceneGraphRendererFrame. A SceneGraphRenderLoopFrame before everything else is
+ // OK as the scene graph might decide to do an initial rendering.
+ QVERIFY(msg.time >= renderFrameTime);
+ break;
+ }
}
}
}
diff --git a/tests/auto/qml/qqmlecmascript/data/qtbug_54589.qml b/tests/auto/qml/qqmlecmascript/data/qtbug_54589.qml
new file mode 100644
index 0000000000..8f7d5f2a70
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/qtbug_54589.qml
@@ -0,0 +1,16 @@
+import QtQuick 2.0
+
+QtObject {
+ function checkPropertyDeletion() {
+ var o = {
+ x: 1,
+ y: 2
+ };
+ o.z = 3
+ delete o.y;
+
+ return (o.x === 1 && o.y === undefined && o.z === 3)
+ }
+
+ property bool result: checkPropertyDeletion()
+}
diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
index 07b5e55384..de3ead917f 100644
--- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
+++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
@@ -324,6 +324,8 @@ private slots:
void switchExpression();
void qtbug_46022();
void qtbug_52340();
+ void qtbug_54589();
+ void qtbug_54687();
private:
// static void propertyVarWeakRefCallback(v8::Persistent<v8::Value> object, void* parameter);
@@ -7965,6 +7967,22 @@ void tst_qqmlecmascript::qtbug_52340()
QVERIFY(returnValue.toBool());
}
+void tst_qqmlecmascript::qtbug_54589()
+{
+ QQmlComponent component(&engine, testFileUrl("qtbug_54589.qml"));
+
+ QScopedPointer<QObject> obj(component.create());
+ QVERIFY(obj != 0);
+ 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)
#include "tst_qqmlecmascript.moc"
diff --git a/tests/auto/qml/qqmllanguage/data/assignBasicTypes.qml b/tests/auto/qml/qqmllanguage/data/assignBasicTypes.qml
index c91cf581b3..52027232db 100644
--- a/tests/auto/qml/qqmllanguage/data/assignBasicTypes.qml
+++ b/tests/auto/qml/qqmllanguage/data/assignBasicTypes.qml
@@ -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 }
diff --git a/tests/auto/qml/qqmllanguage/testtypes.h b/tests/auto/qml/qqmllanguage/testtypes.h
index f41f13c561..af7dc155d0 100644
--- a/tests/auto/qml/qqmllanguage/testtypes.h
+++ b/tests/auto/qml/qqmllanguage/testtypes.h
@@ -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>
@@ -241,8 +243,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)
@@ -523,6 +527,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;
@@ -532,6 +545,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;
@@ -585,7 +607,9 @@ signals:
void boolPropertyChanged();
void variantPropertyChanged();
void vectorPropertyChanged();
+ void vector2PropertyChanged();
void vector4PropertyChanged();
+ void quaternionPropertyChanged();
void urlPropertyChanged();
};
diff --git a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
index 1df7c4157e..1a035be5e0 100644
--- a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
+++ b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
@@ -682,6 +682,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));
diff --git a/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp b/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp
index 7e00147963..63d7f1c12b 100644
--- a/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp
+++ b/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp
@@ -2078,15 +2078,15 @@ void tst_qqmlproperty::floatToStringPrecision()
QFETCH(QString, qtString);
QFETCH(QString, jsString);
- const char *name = propertyName.toLatin1().constData();
+ QByteArray name = propertyName.toLatin1();
QCOMPARE(obj->property(name).toDouble(), number);
QCOMPARE(obj->property(name).toString(), qtString);
- const char *name1 = (propertyName + QLatin1Char('1')).toLatin1().constData();
+ QByteArray name1 = (propertyName + QLatin1Char('1')).toLatin1();
QCOMPARE(obj->property(name1).toDouble(), number);
QCOMPARE(obj->property(name1).toString(), qtString);
- const char *name2 = (propertyName + QLatin1Char('2')).toLatin1().constData();
+ QByteArray name2 = (propertyName + QLatin1Char('2')).toLatin1();
QCOMPARE(obj->property(name2).toDouble(), number);
QCOMPARE(obj->property(name2).toString(), jsString);
diff --git a/tests/auto/qml/qqmlpropertymap/tst_qqmlpropertymap.cpp b/tests/auto/qml/qqmlpropertymap/tst_qqmlpropertymap.cpp
index e0c2324dc6..b8ea98df2b 100644
--- a/tests/auto/qml/qqmlpropertymap/tst_qqmlpropertymap.cpp
+++ b/tests/auto/qml/qqmlpropertymap/tst_qqmlpropertymap.cpp
@@ -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"
diff --git a/tests/auto/quick/qquickflickable/data/ratios_smallContent.qml b/tests/auto/quick/qquickflickable/data/ratios_smallContent.qml
new file mode 100644
index 0000000000..07bad683ee
--- /dev/null
+++ b/tests/auto/quick/qquickflickable/data/ratios_smallContent.qml
@@ -0,0 +1,19 @@
+import QtQuick 2.0
+
+Flickable {
+ property double heightRatioIs: visibleArea.heightRatio
+ property double widthRatioIs: visibleArea.widthRatio
+
+ width: 200
+ height: 200
+ contentWidth: item.width
+ contentHeight: item.height
+ topMargin: 20
+ leftMargin: 40
+
+ Item {
+ id: item
+ width: 100
+ height: 100
+ }
+}
diff --git a/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp b/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp
index 2742f5c1e2..e1678b9acd 100644
--- a/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp
+++ b/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp
@@ -90,6 +90,7 @@ private slots:
void movementFromProgrammaticFlick();
void cleanup();
void contentSize();
+ void ratios_smallContent();
private:
void flickWithTouch(QQuickWindow *window, QTouchDevice *touchDevice, const QPoint &from, const QPoint &to);
@@ -1814,6 +1815,33 @@ void tst_qquickflickable::contentSize()
QCOMPARE(chspy.count(), 1);
}
+// QTBUG-53726
+void tst_qquickflickable::ratios_smallContent()
+{
+ QScopedPointer<QQuickView> window(new QQuickView);
+ window->setSource(testFileUrl("ratios_smallContent.qml"));
+ QTRY_COMPARE(window->status(), QQuickView::Ready);
+ QQuickViewTestUtil::centerOnScreen(window.data());
+ QQuickViewTestUtil::moveMouseAway(window.data());
+ window->setTitle(QTest::currentTestFunction());
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window.data()));
+ QQuickItem *root = window->rootObject();
+ QVERIFY(root);
+ QQuickFlickable *obj = qobject_cast<QQuickFlickable*>(root);
+ QVERIFY(obj != 0);
+
+ //doublecheck the item, as specified by contentWidth/Height, fits in the view
+ //use tryCompare to allow a bit of stabilization in component's properties
+ QTRY_COMPARE(obj->leftMargin() + obj->contentWidth() + obj->rightMargin() <= obj->width(), true);
+ QTRY_COMPARE(obj->topMargin() + obj->contentHeight() + obj->bottomMargin() <= obj->height(), true);
+
+ //the whole item fits in the flickable, heightRatio should be 1
+ QCOMPARE(obj->property("heightRatioIs").toDouble(), 1.);
+ QCOMPARE(obj->property("widthRatioIs").toDouble(), 1.);
+}
+
+
QTEST_MAIN(tst_qquickflickable)
#include "tst_qquickflickable.moc"
diff --git a/tests/auto/quick/qquickitem/tst_qquickitem.cpp b/tests/auto/quick/qquickitem/tst_qquickitem.cpp
index 4b2c86697e..9fedfb21ab 100644
--- a/tests/auto/quick/qquickitem/tst_qquickitem.cpp
+++ b/tests/auto/quick/qquickitem/tst_qquickitem.cpp
@@ -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"
diff --git a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp
index b83edec996..bf9df7850d 100644
--- a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp
+++ b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp
@@ -653,11 +653,9 @@ void tst_QQuickListView::inserted_more(QQuickItemView::VerticalLayoutDirection v
#endif
QList<FxViewItem *> visibleItems = QQuickItemViewPrivate::get(listview)->visibleItems;
- for (QList<FxViewItem *>::const_iterator itemIt = visibleItems.begin(); itemIt != visibleItems.end(); ++itemIt)
- {
+ for (QList<FxViewItem *>::const_iterator itemIt = visibleItems.begin(); itemIt != visibleItems.end(); ++itemIt) {
FxViewItem *item = *itemIt;
- if (item->item->position().y() >= 0 && item->item->position().y() < listview->height())
- {
+ if (item->item->position().y() >= 0 && item->item->position().y() < listview->height()) {
QVERIFY(!QQuickItemPrivate::get(item->item)->culled);
}
}
diff --git a/tests/auto/quick/qquickshadereffect/data/MyIcon.qml b/tests/auto/quick/qquickshadereffect/data/MyIcon.qml
new file mode 100644
index 0000000000..b83da321f2
--- /dev/null
+++ b/tests/auto/quick/qquickshadereffect/data/MyIcon.qml
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 Canonical Limited and/or its subsidiary(-ies).
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.4
+
+Item {
+ id: root
+
+ property alias source: image.source
+ property bool shaderActive: false
+
+ implicitWidth: image.width
+
+ Image {
+ id: image
+ objectName: "image"
+ anchors { top: parent.top; bottom: parent.bottom }
+ sourceSize.height: height
+
+ visible: !shaderActive
+ }
+
+ ShaderEffect {
+ id: colorizedImage
+
+ anchors.fill: parent
+ visible: shaderActive && image.status == Image.Ready
+ supportsAtlasTextures: true
+
+ property Image source: visible ? image : null
+
+ fragmentShader: "
+ varying highp vec2 qt_TexCoord0;
+ uniform sampler2D source;
+ void main() {
+ gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
+ }"
+ }
+}
diff --git a/tests/auto/quick/qquickshadereffect/data/twoImagesOneShaderEffect.qml b/tests/auto/quick/qquickshadereffect/data/twoImagesOneShaderEffect.qml
new file mode 100644
index 0000000000..d1292f74b8
--- /dev/null
+++ b/tests/auto/quick/qquickshadereffect/data/twoImagesOneShaderEffect.qml
@@ -0,0 +1,61 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 Canonical Limited and/or its subsidiary(-ies).
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.4
+
+Item {
+ width: 400
+ height: 700
+
+ MyIcon {
+ id: icon
+
+ height: 24
+ source: "star.png"
+ shaderActive: true
+ }
+
+ MyIcon {
+ anchors.top: icon.bottom
+
+ height: 24
+ source: "star.png"
+ }
+}
diff --git a/tests/auto/quick/qquickshadereffect/tst_qquickshadereffect.cpp b/tests/auto/quick/qquickshadereffect/tst_qquickshadereffect.cpp
index 54b64fdee9..fe33dbd4d8 100644
--- a/tests/auto/quick/qquickshadereffect/tst_qquickshadereffect.cpp
+++ b/tests/auto/quick/qquickshadereffect/tst_qquickshadereffect.cpp
@@ -77,6 +77,7 @@ private slots:
void deleteSourceItem();
void deleteShaderEffectSource();
+ void twoImagesOneShaderEffect();
private:
enum PresenceFlags {
@@ -306,6 +307,19 @@ void tst_qquickshadereffect::deleteShaderEffectSource()
delete view;
}
+void tst_qquickshadereffect::twoImagesOneShaderEffect()
+{
+ // purely to ensure that deleting the sourceItem of a shader doesn't cause a crash
+ QQuickView *view = new QQuickView(0);
+ view->setSource(QUrl::fromLocalFile(testFile("twoImagesOneShaderEffect.qml")));
+ view->show();
+ QVERIFY(QTest::qWaitForWindowExposed(view));
+ QVERIFY(view);
+ QObject *obj = view->rootObject();
+ QVERIFY(obj);
+ delete view;
+}
+
QTEST_MAIN(tst_qquickshadereffect)
#include "tst_qquickshadereffect.moc"
diff --git a/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp b/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp
index 329bbbed60..d9bdf47041 100644
--- a/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp
+++ b/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp
@@ -361,6 +361,7 @@ private slots:
void testRenderJob();
void testHoverChildMouseEventFilter();
+ void testHoverTimestamp();
private:
QTouchDevice *touchDevice;
QTouchDevice *touchDeviceWithVelocity;
@@ -2317,6 +2318,90 @@ void tst_qquickwindow::testHoverChildMouseEventFilter()
QCOMPARE(middleItem->eventCount(QEvent::HoverEnter), 0);
}
+class HoverTimestampConsumer : public QQuickItem
+{
+ Q_OBJECT
+public:
+ HoverTimestampConsumer(QQuickItem *parent = 0)
+ : QQuickItem(parent)
+ {
+ setAcceptHoverEvents(true);
+ }
+
+ void hoverEnterEvent(QHoverEvent *event) { hoverTimestamps << event->timestamp(); }
+ void hoverLeaveEvent(QHoverEvent *event) { hoverTimestamps << event->timestamp(); }
+ void hoverMoveEvent(QHoverEvent *event) { hoverTimestamps << event->timestamp(); }
+
+ QList<ulong> hoverTimestamps;
+};
+
+// Checks that a QHoverEvent carries the timestamp of the QMouseEvent that caused it.
+// QTBUG-54600
+void tst_qquickwindow::testHoverTimestamp()
+{
+ QQuickWindow window;
+
+ window.resize(200, 200);
+ window.setPosition(100, 100);
+ window.setTitle(QTest::currentTestFunction());
+ window.show();
+ QVERIFY(QTest::qWaitForWindowActive(&window));
+
+ HoverTimestampConsumer *hoverConsumer = new HoverTimestampConsumer(window.contentItem());
+ hoverConsumer->setWidth(100);
+ hoverConsumer->setHeight(100);
+ hoverConsumer->setX(50);
+ hoverConsumer->setY(50);
+
+ // First position, outside
+ {
+ QMouseEvent mouseEvent(QEvent::MouseMove, QPointF(40, 40), QPointF(40, 40), QPointF(140, 140),
+ Qt::NoButton, Qt::NoButton, Qt::NoModifier, Qt::MouseEventNotSynthesized);
+ mouseEvent.setTimestamp(10);
+ QVERIFY(QCoreApplication::sendEvent(&window, &mouseEvent));
+ }
+
+ // Enter
+ {
+ QMouseEvent mouseEvent(QEvent::MouseMove, QPointF(50, 50), QPointF(50, 50), QPointF(150, 150),
+ Qt::NoButton, Qt::NoButton, Qt::NoModifier, Qt::MouseEventNotSynthesized);
+ mouseEvent.setTimestamp(20);
+ QVERIFY(QCoreApplication::sendEvent(&window, &mouseEvent));
+ }
+ QCOMPARE(hoverConsumer->hoverTimestamps.size(), 1);
+ QCOMPARE(hoverConsumer->hoverTimestamps.last(), 20UL);
+
+ // Move
+ {
+ QMouseEvent mouseEvent(QEvent::MouseMove, QPointF(60, 60), QPointF(60, 60), QPointF(160, 160),
+ Qt::NoButton, Qt::NoButton, Qt::NoModifier, Qt::MouseEventNotSynthesized);
+ mouseEvent.setTimestamp(30);
+ QVERIFY(QCoreApplication::sendEvent(&window, &mouseEvent));
+ }
+ QCOMPARE(hoverConsumer->hoverTimestamps.size(), 2);
+ QCOMPARE(hoverConsumer->hoverTimestamps.last(), 30UL);
+
+ // Move
+ {
+ QMouseEvent mouseEvent(QEvent::MouseMove, QPointF(100, 100), QPointF(100, 100), QPointF(200, 200),
+ Qt::NoButton, Qt::NoButton, Qt::NoModifier, Qt::MouseEventNotSynthesized);
+ mouseEvent.setTimestamp(40);
+ QVERIFY(QCoreApplication::sendEvent(&window, &mouseEvent));
+ }
+ QCOMPARE(hoverConsumer->hoverTimestamps.size(), 3);
+ QCOMPARE(hoverConsumer->hoverTimestamps.last(), 40UL);
+
+ // Leave
+ {
+ QMouseEvent mouseEvent(QEvent::MouseMove, QPointF(160, 160), QPointF(160, 160), QPointF(260, 260),
+ Qt::NoButton, Qt::NoButton, Qt::NoModifier, Qt::MouseEventNotSynthesized);
+ mouseEvent.setTimestamp(5);
+ QVERIFY(QCoreApplication::sendEvent(&window, &mouseEvent));
+ }
+ QCOMPARE(hoverConsumer->hoverTimestamps.size(), 4);
+ QCOMPARE(hoverConsumer->hoverTimestamps.last(), 5UL);
+}
+
QTEST_MAIN(tst_qquickwindow)
#include "tst_qquickwindow.moc"
diff --git a/tests/benchmarks/qml/qml.pro b/tests/benchmarks/qml/qml.pro
index d3ce69c713..5d48ec0067 100644
--- a/tests/benchmarks/qml/qml.pro
+++ b/tests/benchmarks/qml/qml.pro
@@ -5,6 +5,7 @@ SUBDIRS += \
compilation \
javascript \
holistic \
+ qqmlchangeset \
qqmlcomponent \
qqmlimage \
qqmlmetaproperty \
diff --git a/tests/benchmarks/qml/qqmlchangeset/qqmlchangeset.pro b/tests/benchmarks/qml/qqmlchangeset/qqmlchangeset.pro
new file mode 100644
index 0000000000..fc0ccdf8ed
--- /dev/null
+++ b/tests/benchmarks/qml/qqmlchangeset/qqmlchangeset.pro
@@ -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
+
diff --git a/tests/benchmarks/qml/qqmlchangeset/tst_qqmlchangeset.cpp b/tests/benchmarks/qml/qqmlchangeset/tst_qqmlchangeset.cpp
new file mode 100644
index 0000000000..bbfb52343c
--- /dev/null
+++ b/tests/benchmarks/qml/qqmlchangeset/tst_qqmlchangeset.cpp
@@ -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"
diff --git a/tests/manual/scenegraph_lancelot/scenegrabber/main.cpp b/tests/manual/scenegraph_lancelot/scenegrabber/main.cpp
index a4b1a1be70..5098d51134 100644
--- a/tests/manual/scenegraph_lancelot/scenegrabber/main.cpp
+++ b/tests/manual/scenegraph_lancelot/scenegrabber/main.cpp
@@ -134,7 +134,7 @@ private:
};
-extern uint qt_qhash_seed;
+Q_CORE_EXPORT extern QBasicAtomicInt qt_qhash_seed;
int main(int argc, char *argv[])
{
diff --git a/tests/manual/v4/test262 b/tests/manual/v4/test262
-Subproject 0b5af3dcec772bb06b4d685a20b2859cda59d18
+Subproject 9741ac4655808ac46c127e3d1d8ba3d27ada618
diff --git a/tools/qmlplugindump/qmlplugindump.pro b/tools/qmlplugindump/qmlplugindump.pro
index e45a7fad83..b38eea2554 100644
--- a/tools/qmlplugindump/qmlplugindump.pro
+++ b/tools/qmlplugindump/qmlplugindump.pro
@@ -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
}