Merge remote-tracking branch 'origin/5.7' into dev

Conflicts:
	src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.cpp

Change-Id: I26d6435a29cac3840bb567ade5149c2562a94bf9
This commit is contained in:
Liang Qi 2016-06-13 09:04:09 +02:00
commit 4d2f743baa
62 changed files with 410 additions and 77 deletions

View File

@ -1,5 +1,4 @@
load(qt_build_config)
CONFIG += qt_example_installs
CONFIG += warning_clean
MODULE_VERSION = 5.8.0

4
dist/changes-5.6.1 vendored
View File

@ -4,7 +4,7 @@ compatibility (source and binary) with Qt 5.6.0.
For more details, refer to the online documentation included in this
distribution. The documentation is also available online:
http://qt-project.org/doc/qt-5.6
https://doc.qt.io/qt-5.6
The Qt version 5.6 series is binary compatible with the 5.5.x series.
Applications compiled for 5.5 will continue to run with 5.6.
@ -12,7 +12,7 @@ Applications compiled for 5.5 will continue to run with 5.6.
Some of the changes listed in this file include issue tracking numbers
corresponding to tasks in the Qt Bug Tracker:
http://bugreports.qt-project.org/
https://bugreports.qt.io/
Each of these identifiers can be entered in the bug tracker to obtain more
information about a particular change.

View File

@ -106,7 +106,7 @@ inline bool isinf(double x) { return !finite(x) && !isnand(x); }
#endif
#if OS(OPENBSD)
#if OS(OPENBSD) && __cplusplus < 201103L
namespace std {

View File

@ -491,10 +491,11 @@ QUrl QQuickFolderListModel::parentFolder() const
return QUrl();
localFile = dir.path();
} else {
const int pos = d->currentDir.path().lastIndexOf(QLatin1Char('/'));
const QString path = d->currentDir.path();
const int pos = path.lastIndexOf(QLatin1Char('/'));
if (pos <= 0)
return QUrl();
localFile = d->currentDir.path().left(pos);
localFile = path.left(pos);
}
return QUrl::fromLocalFile(localFile);
}

View File

@ -270,6 +270,15 @@ static ReturnedValue qmlsqldatabase_rows_item(CallContext *ctx)
return qmlsqldatabase_rows_index(r, scope.engine, ctx->argc() ? ctx->args()[0].toUInt32() : 0);
}
static QVariant toSqlVariant(QV4::ExecutionEngine *engine, const QV4::ScopedValue &value)
{
// toVariant() maps a null JS value to QVariant(VoidStar), but the SQL module
// expects a null variant. (this is because of QTBUG-40880)
if (value->isNull())
return QVariant();
return engine->toVariant(value, /*typehint*/-1);
}
static ReturnedValue qmlsqldatabase_executeSql(CallContext *ctx)
{
QV4::Scope scope(ctx);
@ -300,8 +309,9 @@ static ReturnedValue qmlsqldatabase_executeSql(CallContext *ctx)
ScopedArrayObject array(scope, values);
quint32 size = array->getLength();
QV4::ScopedValue v(scope);
for (quint32 ii = 0; ii < size; ++ii)
query.bindValue(ii, scope.engine->toVariant((v = array->getIndexed(ii)), -1));
for (quint32 ii = 0; ii < size; ++ii) {
query.bindValue(ii, toSqlVariant(scope.engine, (v = array->getIndexed(ii))));
}
} else if (values->as<Object>()) {
ScopedObject object(scope, values);
ObjectIterator it(scope, object, ObjectIterator::WithProtoChain|ObjectIterator::EnumerableOnly);
@ -311,7 +321,7 @@ static ReturnedValue qmlsqldatabase_executeSql(CallContext *ctx)
key = it.nextPropertyName(val);
if (key->isNull())
break;
QVariant v = scope.engine->toVariant(val, -1);
QVariant v = toSqlVariant(scope.engine, val);
if (key->isString()) {
query.bindValue(key->stringValue()->toQString(), v);
} else {
@ -320,7 +330,7 @@ static ReturnedValue qmlsqldatabase_executeSql(CallContext *ctx)
}
}
} else {
query.bindValue(0, scope.engine->toVariant(values, -1));
query.bindValue(0, toSqlVariant(scope.engine, values));
}
}
if (query.exec()) {

View File

@ -78,8 +78,9 @@ bool SignalTransition::eventTest(QEvent *event)
// Set arguments as context properties
int count = e->arguments().count();
QMetaMethod metaMethod = e->sender()->metaObject()->method(e->signalIndex());
const auto parameterNames = metaMethod.parameterNames();
for (int i = 0; i < count; i++)
context.setContextProperty(metaMethod.parameterNames()[i], QVariant::fromValue(e->arguments().at(i)));
context.setContextProperty(parameterNames[i], QVariant::fromValue(e->arguments().at(i)));
QQmlExpression expr(m_guard, &context, this);
QVariant result = expr.evaluate();
@ -111,15 +112,27 @@ void SignalTransition::setSignal(const QJSValue &signal)
QV4::ExecutionEngine *jsEngine = QV8Engine::getV4(QQmlEngine::contextForObject(this)->engine());
QV4::Scope scope(jsEngine);
QV4::Scoped<QV4::QObjectMethod> qobjectSignal(scope, QJSValuePrivate::convertedToValue(jsEngine, m_signal));
Q_ASSERT(qobjectSignal);
QObject *sender;
QMetaMethod signalMethod;
QObject *sender = qobjectSignal->object();
Q_ASSERT(sender);
QMetaMethod metaMethod = sender->metaObject()->method(qobjectSignal->methodIndex());
QV4::ScopedValue value(scope, QJSValuePrivate::convertedToValue(jsEngine, m_signal));
// Did we get the "slot" that can be used to invoke the signal?
if (QV4::QObjectMethod *signalSlot = value->as<QV4::QObjectMethod>()) {
sender = signalSlot->object();
Q_ASSERT(sender);
signalMethod = sender->metaObject()->method(signalSlot->methodIndex());
} else if (QV4::QmlSignalHandler *signalObject = value->as<QV4::QmlSignalHandler>()) { // or did we get the signal object (the one with the connect()/disconnect() functions) ?
sender = signalObject->object();
Q_ASSERT(sender);
signalMethod = sender->metaObject()->method(signalObject->signalIndex());
} else {
qmlInfo(this) << tr("Specified signal does not exist.");
return;
}
QSignalTransition::setSenderObject(sender);
QSignalTransition::setSignal(metaMethod.methodSignature());
QSignalTransition::setSignal(signalMethod.methodSignature());
connectTriggered();
}

View File

@ -434,20 +434,24 @@ void QQmlProfilerServiceImpl::messageReceived(const QByteArray &message)
void QQmlProfilerServiceImpl::flush()
{
QMutexLocker lock(&m_configMutex);
QList<QQmlAbstractProfilerAdapter *> reporting;
foreach (QQmlAbstractProfilerAdapter *profiler, m_engineProfilers) {
if (profiler->isRunning()) {
m_startTimes.insert(-1, profiler);
profiler->reportData(m_useMessageTypes);
reporting.append(profiler);
}
}
foreach (QQmlAbstractProfilerAdapter *profiler, m_globalProfilers) {
if (profiler->isRunning()) {
m_startTimes.insert(-1, profiler);
profiler->reportData(m_useMessageTypes);
reporting.append(profiler);
}
}
foreach (QQmlAbstractProfilerAdapter *profiler, reporting)
profiler->reportData(m_useMessageTypes);
}
QT_END_NAMESPACE

View File

@ -2724,6 +2724,9 @@ bool Codegen::visit(WithStatement *ast)
_function->hasWith = true;
const int withObject = _block->newTemp();
_block->MOVE(_block->TEMP(withObject), *expression(ast->expression));
// need an exception handler for with to cleanup the with scope
IR::BasicBlock *withExceptionHandler = _function->newBasicBlock(exceptionHandler());
withExceptionHandler->EXP(withExceptionHandler->CALL(withExceptionHandler->NAME(IR::Name::builtin_pop_scope, 0, 0), 0));
@ -2738,8 +2741,6 @@ bool Codegen::visit(WithStatement *ast)
_block->JUMP(withBlock);
_block = withBlock;
int withObject = _block->newTemp();
_block->MOVE(_block->TEMP(withObject), *expression(ast->expression));
IR::ExprList *args = _function->New<IR::ExprList>();
args->init(_block->TEMP(withObject));
_block->EXP(_block->CALL(_block->NAME(IR::Name::builtin_push_with_scope, 0, 0), args));

View File

@ -840,6 +840,7 @@ public:
, _assignedSpillSlots(assignedSpillSlots)
, _intRegs(intRegs)
, _fpRegs(fpRegs)
, _currentStmt(0)
{
_unprocessed = unprocessed;
_liveAtStart.reserve(function->basicBlockCount());

View File

@ -188,6 +188,10 @@ ExecutionEngine::ExecutionEngine(EvalISelFactory *factory)
/* writable */ true, /* executable */ false,
/* includesGuardPages */ true);
jsStackBase = (Value *)jsStack->base();
#ifdef V4_USE_VALGRIND
VALGRIND_MAKE_MEM_UNDEFINED(jsStackBase, 2*JSStackLimit);
#endif
jsStackTop = jsStackBase;
exceptionValue = jsAlloca(1);
@ -197,10 +201,6 @@ ExecutionEngine::ExecutionEngine(EvalISelFactory *factory)
typedArrayCtors = static_cast<FunctionObject *>(jsAlloca(NTypedArrayTypes));
jsStrings = jsAlloca(NJSStrings);
#ifdef V4_USE_VALGRIND
VALGRIND_MAKE_MEM_UNDEFINED(jsStackBase, 2*JSStackLimit);
#endif
// set up stack limits
jsStackLimit = jsStackBase + JSStackLimit/sizeof(Value);

View File

@ -222,7 +222,7 @@ private:
};
struct QmlSignalHandler : public QV4::Object
struct Q_QML_EXPORT QmlSignalHandler : public QV4::Object
{
V4_OBJECT2(QmlSignalHandler, QV4::Object)
V4_PROTOTYPE(signalHandlerPrototype)

View File

@ -88,7 +88,7 @@ struct Scope {
memset(mark, 0, (engine->jsStackTop - mark)*sizeof(Value));
#endif
#ifdef V4_USE_VALGRIND
VALGRIND_MAKE_MEM_UNDEFINED(mark, engine->jsStackLimit - mark);
VALGRIND_MAKE_MEM_UNDEFINED(mark, (engine->jsStackLimit - mark) * sizeof(Value));
#endif
engine->jsStackTop = mark;
}

View File

@ -22,6 +22,11 @@ exists("qqml_enable_gcov") {
LIBS_PRIVATE += -lgcov
}
greaterThan(QT_GCC_MAJOR_VERSION, 5) {
# Our code is bad. Temporary workaround.
QMAKE_CXXFLAGS += -fno-delete-null-pointer-checks
}
QMAKE_DOCS = $$PWD/doc/qtqml.qdocconf
# 2415: variable "xx" of static storage duration was declared but never referenced

View File

@ -398,6 +398,8 @@ void ListModel::updateCacheIndices()
QVariant ListModel::getProperty(int elementIndex, int roleIndex, const QQmlListModel *owner, QV4::ExecutionEngine *eng)
{
if (roleIndex >= m_layout->roleCount())
return QVariant();
ListElement *e = elements[elementIndex];
const ListLayout::Role &r = m_layout->getExistingRole(roleIndex);
return e->getProperty(r, owner, eng);

View File

@ -186,8 +186,8 @@ dedicated thread. Qt attempts to choose a suitable loop based on the
platform and possibly the graphics drivers in use. When this is not
satisfactory, or for testing purposes, the environment variable
\c QSG_RENDER_LOOP can be used to force the usage of a given loop. To
verify which render loop is in use, launch the application with
\c QSG_INFO set to \c 1.
verify which render loop is in use, enable the \c qt.scenegraph.info
\l {QLoggingCategory}{logging category}.
\note The \c threaded and \c windows render loops rely on the OpenGL
implementation for throttling by requesting a swap interval of 1. Some
@ -220,7 +220,7 @@ user input. An event is posted to the render thread to initiate a new
frame.
\li The render thread prepares to draw a new frame and makes the
OpenGL context current and initiates a blocks on the GUI thread.
OpenGL context current and initiates a block on the GUI thread.
\li While the render thread is preparing the new frame, the GUI thread
calls QQuickItem::updatePolish() to do final touch-up of items before

View File

@ -679,10 +679,14 @@ void QQuickCanvasItem::itemChange(QQuickItem::ItemChange change, const QQuickIte
QSGRenderContext *context = QQuickWindowPrivate::get(d->window)->context;
// Rendering to FramebufferObject needs a valid OpenGL context.
if (context != 0 && (d->renderTarget != FramebufferObject || context->isValid()))
sceneGraphInitialized();
else
if (context != 0 && (d->renderTarget != FramebufferObject || context->isValid())) {
// Defer the call. In some (arguably incorrect) cases we get here due
// to ItemSceneChange with the user-supplied property values not yet
// set. Work this around by a deferred invoke. (QTBUG-49692)
QMetaObject::invokeMethod(this, "sceneGraphInitialized", Qt::QueuedConnection);
} else {
connect(d->window, SIGNAL(sceneGraphInitialized()), SLOT(sceneGraphInitialized()));
}
}
void QQuickCanvasItem::updatePolish()

View File

@ -65,7 +65,9 @@ static const int FlickThreshold = 15;
// will ensure the Flickable retains the grab on consecutive flicks.
static const int RetainGrabVelocity = 100;
#ifdef Q_OS_OSX
static const int MovementEndingTimerInterval = 100;
#endif
static qreal EaseOvershoot(qreal t) {
return qAtan(t);

View File

@ -423,21 +423,44 @@ void QQuickItemKeyFilter::componentComplete()
/*!
\qmlproperty Item QtQuick::KeyNavigation::left
This property holds the item to assign focus to
when the left cursor key is pressed.
*/
/*!
\qmlproperty Item QtQuick::KeyNavigation::right
This property holds the item to assign focus to
when the right cursor key is pressed.
*/
/*!
\qmlproperty Item QtQuick::KeyNavigation::up
This property holds the item to assign focus to
when the up cursor key is pressed.
*/
/*!
\qmlproperty Item QtQuick::KeyNavigation::down
These properties hold the item to assign focus to
when the left, right, up or down cursor keys
are pressed.
This property holds the item to assign focus to
when the down cursor key is pressed.
*/
/*!
\qmlproperty Item QtQuick::KeyNavigation::tab
This property holds the item to assign focus to
when the Tab key is pressed.
*/
/*!
\qmlproperty Item QtQuick::KeyNavigation::backtab
These properties hold the item to assign focus to
when the Tab key or Shift+Tab key combination (Backtab) are pressed.
This property holds the item to assign focus to
when the Shift+Tab key combination (Backtab) is pressed.
*/
QQuickKeyNavigationAttached::QQuickKeyNavigationAttached(QObject *parent)

View File

@ -299,7 +299,7 @@ QQuickItemGrabResult *QQuickItemGrabResultPrivate::create(QQuickItem *item, cons
* Use \a targetSize to specify the size of the target image. By default, the
* result will have the same size as item.
*
* If the grab could not be initiated, the function returns a \c null.
* If the grab could not be initiated, the function returns \c null.
*
* \note This function will render the item to an offscreen surface and
* copy that surface from the GPU's memory into the CPU's memory, which can
@ -326,7 +326,8 @@ QSharedPointer<QQuickItemGrabResult> QQuickItem::grabToImage(const QSize &target
* Grabs the item into an in-memory image.
*
* The grab happens asynchronously and the JavaScript function \a callback is
* invoked when the grab is completed.
* invoked when the grab is completed. The callback takes one argument, which
* is the result of the grab operation; an \l ItemGrabResult object.
*
* Use \a targetSize to specify the size of the target image. By default, the result
* will have the same size as the item.

View File

@ -57,7 +57,7 @@ DEFINE_BOOL_CONFIG_OPTION(qmlVisualTouchDebugging, QML_VISUAL_TOUCH_DEBUGGING)
QQuickMouseAreaPrivate::QQuickMouseAreaPrivate()
: enabled(true), scrollGestureEnabled(true), hovered(false), longPress(false),
moved(false), stealMouse(false), doubleClick(false), preventStealing(false),
propagateComposedEvents(false), pressed(0)
propagateComposedEvents(false), overThreshold(false), pressed(0)
#ifndef QT_NO_DRAGANDDROP
, drag(0)
#endif
@ -720,7 +720,7 @@ void QQuickMouseArea::mouseMoveEvent(QMouseEvent *event)
curLocalPos = event->windowPos();
}
if (keepMouseGrab() && d->stealMouse && !d->drag->active())
if (keepMouseGrab() && d->stealMouse && d->overThreshold && !d->drag->active())
d->drag->setActive(true);
QPointF startPos = d->drag->target()->parentItem()
@ -746,16 +746,19 @@ void QQuickMouseArea::mouseMoveEvent(QMouseEvent *event)
if (d->drag->active())
d->drag->target()->setPosition(dragPos);
if (!keepMouseGrab()
&& (QQuickWindowPrivate::dragOverThreshold(dragPos.x() - startPos.x(), Qt::XAxis, event, d->drag->threshold())
|| QQuickWindowPrivate::dragOverThreshold(dragPos.y() - startPos.y(), Qt::YAxis, event, d->drag->threshold()))) {
setKeepMouseGrab(true);
d->stealMouse = true;
if (!d->overThreshold && (QQuickWindowPrivate::dragOverThreshold(dragPos.x() - startPos.x(), Qt::XAxis, event, d->drag->threshold())
|| QQuickWindowPrivate::dragOverThreshold(dragPos.y() - startPos.y(), Qt::YAxis, event, d->drag->threshold())))
{
d->overThreshold = true;
if (d->drag->smoothed())
d->startScene = event->windowPos();
}
if (!keepMouseGrab() && d->overThreshold) {
setKeepMouseGrab(true);
d->stealMouse = true;
}
d->moved = true;
}
#endif
@ -774,6 +777,7 @@ void QQuickMouseArea::mouseReleaseEvent(QMouseEvent *event)
{
Q_D(QQuickMouseArea);
d->stealMouse = false;
d->overThreshold = false;
if (!d->enabled && !d->pressed) {
QQuickItem::mouseReleaseEvent(event);
} else {
@ -887,6 +891,7 @@ void QQuickMouseArea::ungrabMouse()
d->pressed = 0;
d->stealMouse = false;
d->doubleClick = false;
d->overThreshold = false;
setKeepMouseGrab(false);
#ifndef QT_NO_DRAGANDDROP

View File

@ -93,6 +93,7 @@ public:
bool doubleClick : 1;
bool preventStealing : 1;
bool propagateComposedEvents : 1;
bool overThreshold : 1;
Qt::MouseButtons pressed;
#ifndef QT_NO_DRAGANDDROP
QQuickDrag *drag;

View File

@ -1026,7 +1026,7 @@ void QQuickPathView::setHighlightMoveDuration(int duration)
/*!
\qmlproperty real QtQuick::PathView::dragMargin
This property holds the maximum distance from the path that initiate mouse dragging.
This property holds the maximum distance from the path that initiates mouse dragging.
By default the path can only be dragged by clicking on an item. If
dragMargin is greater than zero, a drag can be initiated by clicking

View File

@ -642,9 +642,12 @@ void QQuickTextNodeEngine::addBorder(const QRectF &rect, qreal border,
void QQuickTextNodeEngine::addFrameDecorations(QTextDocument *document, QTextFrame *frame)
{
QTextDocumentLayout *documentLayout = qobject_cast<QTextDocumentLayout *>(document->documentLayout());
QTextFrameFormat frameFormat = frame->format().toFrameFormat();
if (Q_UNLIKELY(!documentLayout))
return;
QTextFrameFormat frameFormat = frame->format().toFrameFormat();
QTextTable *table = qobject_cast<QTextTable *>(frame);
QRectF boundingRect = table == 0
? documentLayout->frameBoundingRect(frame)
: documentLayout->tableBoundingRect(table);

View File

@ -834,8 +834,10 @@ void QQuickWindowPrivate::setFocusInScope(QQuickItem *scope, QQuickItem *item, Q
QQuickItemPrivate *scopePrivate = scope ? QQuickItemPrivate::get(scope) : 0;
QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
QQuickItem *oldActiveFocusItem = 0;
QQuickItem *currentActiveFocusItem = activeFocusItem;
QQuickItem *newActiveFocusItem = 0;
bool sendFocusIn = false;
lastFocusReason = reason;
@ -843,7 +845,6 @@ void QQuickWindowPrivate::setFocusInScope(QQuickItem *scope, QQuickItem *item, Q
// Does this change the active focus?
if (item == contentItem || scopePrivate->activeFocus) {
QQuickItem *oldActiveFocusItem = 0;
oldActiveFocusItem = activeFocusItem;
if (item->isEnabled()) {
newActiveFocusItem = item;
@ -862,8 +863,6 @@ void QQuickWindowPrivate::setFocusInScope(QQuickItem *scope, QQuickItem *item, Q
#endif
activeFocusItem = 0;
QFocusEvent event(QEvent::FocusOut, reason);
q->sendEvent(oldActiveFocusItem, &event);
QQuickItem *afi = oldActiveFocusItem;
while (afi && afi != scope) {
@ -908,7 +907,19 @@ void QQuickWindowPrivate::setFocusInScope(QQuickItem *scope, QQuickItem *item, Q
afi = afi->parentItem();
}
updateFocusItemTransform();
sendFocusIn = true;
}
// Now that all the state is changed, emit signals & events
// We must do this last, as this process may result in further changes to
// focus.
if (oldActiveFocusItem) {
QFocusEvent event(QEvent::FocusOut, reason);
q->sendEvent(oldActiveFocusItem, &event);
}
// Make sure that the FocusOut didn't result in another focus change.
if (sendFocusIn && activeFocusItem == newActiveFocusItem) {
QFocusEvent event(QEvent::FocusIn, reason);
q->sendEvent(newActiveFocusItem, &event);
}
@ -961,9 +972,6 @@ void QQuickWindowPrivate::clearFocusInScope(QQuickItem *scope, QQuickItem *item,
activeFocusItem = 0;
if (oldActiveFocusItem) {
QFocusEvent event(QEvent::FocusOut, reason);
q->sendEvent(oldActiveFocusItem, &event);
QQuickItem *afi = oldActiveFocusItem;
while (afi && afi != scope) {
if (QQuickItemPrivate::get(afi)->activeFocus) {
@ -993,7 +1001,18 @@ void QQuickWindowPrivate::clearFocusInScope(QQuickItem *scope, QQuickItem *item,
Q_ASSERT(newActiveFocusItem == scope);
activeFocusItem = scope;
updateFocusItemTransform();
}
// Now that all the state is changed, emit signals & events
// We must do this last, as this process may result in further changes to
// focus.
if (oldActiveFocusItem) {
QFocusEvent event(QEvent::FocusOut, reason);
q->sendEvent(oldActiveFocusItem, &event);
}
// Make sure that the FocusOut didn't result in another focus change.
if (newActiveFocusItem && activeFocusItem == newActiveFocusItem) {
QFocusEvent event(QEvent::FocusIn, reason);
q->sendEvent(newActiveFocusItem, &event);
}

View File

@ -337,12 +337,12 @@ QSGNode::~QSGNode()
to the scene graph and will cause the preprocess() function to be called
for every frame the node is rendered.
The preprocess function is called before the update pass that propegates
The preprocess function is called before the update pass that propagates
opacity and transformations through the scene graph. That means that
functions like QSGOpacityNode::combinedOpacity() and
QSGTransformNode::combinedMatrix() will not contain up-to-date values.
If such values are changed during the preprocess, these changes will be
propegated through the scene graph before it is rendered.
propagated through the scene graph before it is rendered.
\warning Beware of deleting nodes while they are being preprocessed. It is
possible, with a small performance hit, to delete a single node during its
@ -1349,7 +1349,7 @@ const qreal OPACITY_THRESHOLD = 0.001;
Sets the opacity of this node to \a opacity.
Before rendering the graph, the renderer will do an update pass
over the subtree to propegate the opacity to its children.
over the subtree to propagate the opacity to its children.
The value will be bounded to the range 0 to 1.
*/

View File

@ -189,6 +189,8 @@ private slots:
void v4FunctionWithoutQML();
void withNoContext();
signals:
void testSignal();
};
@ -3985,6 +3987,13 @@ void tst_QJSEngine::v4FunctionWithoutQML()
QVERIFY(obj.called);
}
void tst_QJSEngine::withNoContext()
{
// Don't crash (QTBUG-53794)
QJSEngine engine;
engine.evaluate("with (noContext) true");
}
QTEST_MAIN(tst_QJSEngine)
#include "tst_qjsengine.moc"

View File

@ -105,6 +105,7 @@ private slots:
void get_nested();
void get_nested_data();
void crash_model_with_multiple_roles();
void crash_model_with_unknown_roles();
void set_model_cache();
void property_changes();
void property_changes_data();
@ -963,6 +964,21 @@ void tst_qqmllistmodel::crash_model_with_multiple_roles()
delete rootItem;
}
void tst_qqmllistmodel::crash_model_with_unknown_roles()
{
QQmlEngine eng;
QQmlComponent component(&eng, testFileUrl("multipleroles.qml"));
QScopedPointer<QObject> rootItem(component.create());
QVERIFY(component.errorString().isEmpty());
QVERIFY(rootItem != 0);
QQmlListModel *model = rootItem->findChild<QQmlListModel*>("listModel");
QVERIFY(model != 0);
// used to cause a crash in debug builds
model->index(0, 0, QModelIndex()).data(Qt::DisplayRole);
model->index(0, 0, QModelIndex()).data(Qt::UserRole);
}
//QTBUG-15190
void tst_qqmllistmodel::set_model_cache()
{

View File

@ -0,0 +1,24 @@
.import QtQuick.LocalStorage 2.0 as Sql
function test() {
var db = Sql.LocalStorage.openDatabaseSync("QmlTestDB-nullvalues", "", "Test database from Qt autotests", 1000000);
var r="transaction_not_finished";
db.transaction(
function(tx) {
tx.executeSql('CREATE TABLE IF NOT EXISTS NullValues(salutation TEXT, salutee TEXT)');
tx.executeSql('INSERT INTO NullValues VALUES(?, ?)', [ 'hello', null ]);
var firstRow = tx.executeSql("SELECT * FROM NullValues").rows.item(0);
if (firstRow.salutation !== "hello")
return
if (firstRow.salutee === "") {
r = "wrong_data_type"
return
}
if (firstRow.salutee === null)
r = "passed";
}
);
return r;
}

View File

@ -122,7 +122,7 @@ void tst_qqmlsqldatabase::checkDatabasePath()
QVERIFY(engine->offlineStoragePath().contains("OfflineStorage"));
}
static const int total_databases_created_by_tests = 12;
static const int total_databases_created_by_tests = 13;
void tst_qqmlsqldatabase::testQml_data()
{
QTest::addColumn<QString>("jsfile"); // The input file
@ -144,6 +144,7 @@ void tst_qqmlsqldatabase::testQml_data()
QTest::newRow("error-outsidetransaction") << "error-outsidetransaction.js"; // reuse above
QTest::newRow("reopen1") << "reopen1.js";
QTest::newRow("reopen2") << "reopen2.js"; // re-uses above DB
QTest::newRow("null-values") << "nullvalues.js";
// If you add a test, you should usually use a new database in the
// test - in which case increment total_databases_created_by_tests above.

View File

@ -3,3 +3,12 @@
*
[SelfTests::test_blacklistWithData:test2]
*
[shadersource-dynamic-sourceobject::test_endresult]
linux
[tst_grabImage::test_equals]
linux
[Text::test_linecount]
osx
windows
[TextInput::test_doublevalidators]
osx

View File

@ -288,6 +288,7 @@ Item {
}
function test_asyncLoaderCurrentIndexChange() {
skip("more details in QTBUG-53780")
for (var i = 0; i < 500; i++) {
asyncLoaderCurrentIndexListView.currentIndex = 0;
asyncLoaderCurrentIndexListView.currentIndex = 1;
@ -300,6 +301,7 @@ Item {
}
function test_asyncListViewLoader() {
skip("more details in QTBUG-53780")
for (var i = 0; i < 50; i++) {
wait(10);
asyncListViewLoaderView.currentIndex = 0;

View File

@ -10,5 +10,5 @@ importFiles.files = borderimage buttonclick createbenchmark events qqmlbindi
importFiles.path = .
DEPLOYMENT += importFiles
CONFIG+=insignificant_test # QTBUG-33723
# Please do not make this test insignificant again, thanks.
# Just skip those unstable ones. See also QTBUG-33723.

View File

@ -0,0 +1,76 @@
/****************************************************************************
**
** Copyright (C) 2014 Ford Motor Company
** Copyright (C) 2016 The Qt Company
** Contact: https://www.qt.io/licensing/
**
** This file is part of the test suite module 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$
**
****************************************************************************/
import QtTest 1.1
import QtQml.StateMachine 1.0
TestCase {
id: testCase
StateMachine {
id: machine
initialState: startState
State {
id: startState
SignalTransition {
id: signalTrans
signal: testCase.onMysignal
targetState: finalState
}
}
FinalState {
id: finalState
}
}
SignalSpy {
id: finalStateActive
target: finalState
signalName: "activeChanged"
}
signal mysignal()
name: "testSignalTransition"
function test_signalTransition()
{
// Start statemachine, should not have reached finalState yet.
machine.start()
tryCompare(finalStateActive, "count", 0)
tryCompare(machine, "running", true)
testCase.mysignal()
tryCompare(finalStateActive, "count", 1)
tryCompare(machine, "running", false)
}
}

View File

@ -75,6 +75,8 @@ Item {
when: windowShown
function test_clickBothWindows() {
if (Qt.platform.os === "linux" || Qt.platform.os === "windows")
skip("more details in QTBUG-53785")
mouseClick(ma, 20, 20);
verify(ma.everClicked);
mouseClick(ma2, 20, 20);

View File

@ -735,7 +735,7 @@ void tst_QQuickListView::inserted_more_data()
<< 15 << 1
<< 0.0;
QTest::newRow("add 1, at end of visible, content at start")
QTest::newRow("add multiple, at end of visible, content at start")
<< 0.0
<< 15 << 3
<< 0.0;
@ -756,7 +756,7 @@ void tst_QQuickListView::inserted_more_data()
<< 16 << 1
<< 0.0;
QTest::newRow("add 1, after visible, content at start")
QTest::newRow("add multiple, after visible, content at start")
<< 0.0
<< 16 << 3
<< 0.0;

View File

@ -82,6 +82,7 @@ private slots:
void dragging_data() { acceptedButton_data(); }
void dragging();
void dragSmoothed();
void dragThreshold_data();
void dragThreshold();
void invalidDrag_data() { rejectedButton_data(); }
void invalidDrag();
@ -390,8 +391,17 @@ void tst_QQuickMouseArea::dragSmoothed()
QTest::mouseRelease(&window, Qt::LeftButton, 0, QPoint(100, 122));
}
void tst_QQuickMouseArea::dragThreshold_data()
{
QTest::addColumn<bool>("preventStealing");
QTest::newRow("without preventStealing") << false;
QTest::newRow("with preventStealing") << true;
}
void tst_QQuickMouseArea::dragThreshold()
{
QFETCH(bool, preventStealing);
QQuickView window;
QByteArray errorMessage;
QVERIFY2(initView(window, testFileUrl("dragging.qml"), true, &errorMessage), errorMessage.constData());
@ -401,6 +411,7 @@ void tst_QQuickMouseArea::dragThreshold()
QVERIFY(window.rootObject() != 0);
QQuickMouseArea *mouseRegion = window.rootObject()->findChild<QQuickMouseArea*>("mouseregion");
mouseRegion->setPreventStealing(preventStealing);
QQuickDrag *drag = mouseRegion->drag();
drag->setThreshold(5);

View File

@ -2771,18 +2771,19 @@ void tst_qquicktext::lineLaidOutRelayout()
QVERIFY(!textPrivate->extra.isAllocated());
qreal maxH = 0;
qreal y = 0.0;
for (int i = 0; i < textPrivate->layout.lineCount(); ++i) {
QTextLine line = textPrivate->layout.lineAt(i);
const QRectF r = line.rect();
const qreal h = line.height();
if (r.x() == 0) {
QCOMPARE(r.y(), i * h);
maxH = qMax(maxH, r.y() + h);
QCOMPARE(r.y(), y);
} else {
if (qFuzzyIsNull(r.y()))
y = 0.0;
QCOMPARE(r.x(), myText->width() / 2);
QCOMPARE(r.y(), i * h - maxH);
QCOMPARE(r.y(), y);
}
y += line.height();
}
}

View File

@ -0,0 +1,32 @@
import QtQuick 2.2
Rectangle {
width: 400
height: 400
Column {
spacing: 5
TextInput {
objectName: "first"
onEditingFinished: second.focus = true
width: 100
Rectangle { anchors.fill: parent; color: parent.activeFocus ? "red" : "blue"; opacity: 0.3 }
}
TextInput {
id: second
objectName: "second"
onEditingFinished: third.focus = true
width: 100
Rectangle { anchors.fill: parent; color: parent.activeFocus ? "red" : "blue"; opacity: 0.3 }
}
TextInput {
objectName: "third"
id: third
width: 100
Rectangle { anchors.fill: parent; color: parent.activeFocus ? "red" : "blue"; opacity: 0.3 }
}
Component.onCompleted: {
second.focus = true
}
}
}

View File

@ -154,6 +154,7 @@ private slots:
#endif
void readOnly();
void focusOnPress();
void focusOnPressOnlyOneItem();
void openInputPanel();
void setHAlignClearCache();
@ -3511,6 +3512,46 @@ void tst_qquicktextinput::focusOnPress()
QTest::mouseRelease(&window, Qt::LeftButton, noModifiers);
}
void tst_qquicktextinput::focusOnPressOnlyOneItem()
{
QQuickView window(testFileUrl("focusOnlyOneOnPress.qml"));
window.show();
window.requestActivate();
QTest::qWaitForWindowActive(&window);
QQuickTextInput *first = window.rootObject()->findChild<QQuickTextInput*>("first");
QQuickTextInput *second = window.rootObject()->findChild<QQuickTextInput*>("second");
QQuickTextInput *third = window.rootObject()->findChild<QQuickTextInput*>("third");
// second is focused onComplete
QVERIFY(second->hasActiveFocus());
// and first will try focus when we press it
QVERIFY(first->focusOnPress());
// write some text to start editing
QTest::keyClick(&window, Qt::Key_A);
// click the first input. naturally, we are giving focus on press, but
// second's editingFinished also attempts to assign focus. lastly, focus
// should bounce back to second from first's editingFinished signal.
//
// this is a contrived example to be sure, but at the end of this, the
// important thing is that only one thing should have activeFocus.
Qt::KeyboardModifiers noModifiers = 0;
QTest::mousePress(&window, Qt::LeftButton, noModifiers, QPoint(10, 10));
// make sure the press is processed.
QGuiApplication::processEvents();
QVERIFY(second->hasActiveFocus()); // make sure it's still there
QVERIFY(!third->hasActiveFocus()); // make sure it didn't end up anywhere else
QVERIFY(!first->hasActiveFocus()); // make sure it didn't end up anywhere else
// reset state
QTest::mouseRelease(&window, Qt::LeftButton, noModifiers, QPoint(10, 10));
}
void tst_qquicktextinput::openInputPanel()
{
PlatformInputContext platformInputContext;

View File

@ -75,6 +75,12 @@
static const uint qtQmlMajorVersion = 2;
static const uint qtQmlMinorVersion = 2;
static const uint qtQuickMajorVersion = 2;
static const uint qtQuickMinorVersion = 7;
const QString qtQuickQualifiedName = QString::fromLatin1("QtQuick %1.%2")
.arg(qtQuickMajorVersion)
.arg(qtQuickMinorVersion);
QString pluginImportPath;
bool verbose = false;
@ -730,7 +736,7 @@ void sigSegvHandler(int) {
void printUsage(const QString &appName)
{
std::cerr << qPrintable(QString(
"Usage: %1 [-v] [-noinstantiate] [-defaultplatform] [-[non]relocatable] [-dependencies <dependencies.json>] [-merge <file-to-merge.qmltypes>] module.uri version [module/import/path]\n"
"Usage: %1 [-v] [-noinstantiate] [-defaultplatform] [-[non]relocatable] [-dependencies <dependencies.json>] [-merge <file-to-merge.qmltypes>] [-noforceqtquick] module.uri version [module/import/path]\n"
" %1 [-v] [-noinstantiate] -path path/to/qmldir/directory [version]\n"
" %1 [-v] -builtins\n"
"Example: %1 Qt.labs.folderlistmodel 2.0 /home/user/dev/qt-install/imports").arg(
@ -738,7 +744,8 @@ void printUsage(const QString &appName)
}
static bool readDependenciesData(QString dependenciesFile, const QByteArray &fileData,
QStringList *dependencies, const QStringList &urisToSkip) {
QStringList *dependencies, const QStringList &urisToSkip,
bool forceQtQuickDependency = true) {
if (verbose) {
std::cerr << "parsing "
<< qPrintable( dependenciesFile ) << " skipping";
@ -793,8 +800,8 @@ static bool readDependenciesData(QString dependenciesFile, const QByteArray &fil
// qmlplugindump used to import QtQuick, so all types defined in QtQuick used to be skipped when dumping.
// Now that it imports only Qt, it is no longer the case: if no dependency is found all the types defined
// in QtQuick will be dumped, causing conflicts.
if (dependencies->isEmpty())
dependencies->push_back(QLatin1String("QtQuick 2.0"));
if (forceQtQuickDependency && dependencies->isEmpty())
dependencies->push_back(qtQuickQualifiedName);
return true;
}
@ -812,11 +819,12 @@ static bool readDependenciesFile(const QString &dependenciesFile, QStringList *d
return false;
}
QByteArray fileData = f.readAll();
return readDependenciesData(dependenciesFile, fileData, dependencies, urisToSkip);
return readDependenciesData(dependenciesFile, fileData, dependencies, urisToSkip, false);
}
static bool getDependencies(const QQmlEngine &engine, const QString &pluginImportUri,
const QString &pluginImportVersion, QStringList *dependencies)
const QString &pluginImportVersion, QStringList *dependencies,
bool forceQtQuickDependency)
{
QFileInfo selfExe(QCoreApplication::applicationFilePath());
QString command = selfExe.absoluteDir().filePath(QLatin1String("qmlimportscanner")
@ -849,7 +857,7 @@ static bool getDependencies(const QQmlEngine &engine, const QString &pluginImpor
}
QByteArray depencenciesData = importScanner.readAllStandardOutput();
if (!readDependenciesData(QLatin1String("<outputOfQmlimportscanner>"), depencenciesData,
dependencies, QStringList(pluginImportUri))) {
dependencies, QStringList(pluginImportUri), forceQtQuickDependency)) {
std::cerr << "failed to proecess output of qmlimportscanner" << std::endl;
return false;
}
@ -986,6 +994,7 @@ int main(int argc, char *argv[])
bool relocatable = true;
QString dependenciesFile;
QString mergeFile;
bool forceQtQuickDependency = true;
enum Action { Uri, Path, Builtins };
Action action = Uri;
{
@ -1030,6 +1039,9 @@ int main(int argc, char *argv[])
action = Builtins;
} else if (arg == QLatin1String("-v")) {
verbose = true;
} else if (arg == QLatin1String("--noforceqtquick")
|| arg == QLatin1String("-noforceqtquick")){
forceQtQuickDependency = false;
} else if (arg == QLatin1String("--defaultplatform")
|| arg == QLatin1String("-defaultplatform")) {
continue;
@ -1098,9 +1110,12 @@ int main(int argc, char *argv[])
calculateDependencies = !readDependenciesFile(dependenciesFile, &dependencies,
QStringList(pluginImportUri)) && calculateDependencies;
if (calculateDependencies)
getDependencies(engine, pluginImportUri, pluginImportVersion, &dependencies);
getDependencies(engine, pluginImportUri, pluginImportVersion, &dependencies,
forceQtQuickDependency);
compactDependencies(&dependencies);
QString qtQmlImportString = QString::fromLatin1("import QtQml %1.%2")
.arg(qtQmlMajorVersion)
.arg(qtQmlMinorVersion);