Merge "Merge remote-tracking branch 'origin/5.3' into 5.4" into refs/staging/5.4

This commit is contained in:
Simon Hausmann 2014-08-26 09:51:49 +02:00 committed by The Qt Project
commit e525c55139
21 changed files with 246 additions and 27 deletions

41
dist/changes-5.3.2 vendored Normal file
View File

@ -0,0 +1,41 @@
Qt 5.3.2 is a bug-fix release. It maintains both forward and backward
compatibility (source and binary) with Qt 5.3.1.
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.3
The Qt version 5.3 series is binary compatible with the 5.2.x series.
Applications compiled for 5.2 will continue to run with 5.3.
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/
Each of these identifiers can be entered in the bug tracker to obtain more
information about a particular change.
****************************************************************************
* Library *
****************************************************************************
QtQuick
-------
- Bug fixes:
* QTBUG-37859 Synchronize PathView gesture grabbing with other items
* QTBUG-38485 Add support for disabling @2x behavior with QT_HIGHDPI_DISABLE_2X_IMAGE_LOADING.
* QTBUG-40000 Fix crash in Flickble with pressDelay
* QTBUG-33436 Avoid double deletion of QQuickWindow
QtQml
-----
- Bug fixes:
* QTBUG-40685 Avoid double deletion when deleting an incubating component.
* QTBUG-40369 Fix crash when loading invalid QML with behavior on invalid group property
* QTBUG-40448 Fix crash in QQmlData::wasDeleted()
* QTBUG-38635 Fix crash in QObjectWrapper

View File

@ -51,6 +51,7 @@ Rectangle {
color: "#272822"
onWidthChanged: controller.reload()
onHeightChanged: controller.reload()
function operatorPressed(operator) { CalcEngine.operatorPressed(operator) }
function digitPressed(digit) { CalcEngine.digitPressed(digit) }

View File

@ -1,6 +1,6 @@
TEMPLATE = app
QT += qml quick
QT += qml quick sql
SOURCES += main.cpp
RESOURCES += samegame.qrc

View File

@ -644,7 +644,7 @@ public:
inline ArrayElementLessThan(ExecutionContext *context, Object *thisObject, const ValueRef comparefn)
: m_context(context), thisObject(thisObject), m_comparefn(comparefn) {}
bool operator()(const Value &v1, const Value &v2) const;
bool operator()(Value v1, Value v2) const;
private:
ExecutionContext *m_context;
@ -653,7 +653,7 @@ private:
};
bool ArrayElementLessThan::operator()(const Value &v1, const Value &v2) const
bool ArrayElementLessThan::operator()(Value v1, Value v2) const
{
Scope scope(m_context);

View File

@ -478,7 +478,7 @@ ReturnedValue GlobalFunctions::method_parseInt(CallContext *ctx)
if (pos == end) // 12
return Encode(std::numeric_limits<double>::quiet_NaN());
bool overflow = false;
qint64 v_overflow;
qint64 v_overflow = 0;
unsigned overflow_digit_count = 0;
int d = toInt(*pos++, R);
if (d == -1)

View File

@ -376,7 +376,7 @@ finishIncubate:
enginePriv->erroredBindings->removeError();
}
}
} else {
} else if (!creator.isNull()) {
vmeGuard.guard(creator.data());
}
}

View File

@ -1021,6 +1021,13 @@ void QQmlObjectCreator::recordError(const QV4::CompiledData::Location &location,
errors << error;
}
void QQmlObjectCreator::registerObjectWithContextById(int objectIndex, QObject *instance) const
{
QHash<int, int>::ConstIterator idEntry = objectIndexToId.find(objectIndex);
if (idEntry != objectIndexToId.constEnd())
context->setIdProperty(idEntry.value(), instance);
}
QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isContextObject)
{
QQmlObjectCreationProfiler profiler(sharedState->profiler.profiler);
@ -1120,10 +1127,6 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo
parserStatus->d = &sharedState->allParserStatusCallbacks.top();
}
QHash<int, int>::ConstIterator idEntry = objectIndexToId.find(index);
if (idEntry != objectIndexToId.constEnd())
context->setIdProperty(idEntry.value(), instance);
// Register the context object in the context early on in order for pending binding
// initialization to find it available.
if (isContextObject)
@ -1147,8 +1150,10 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo
}
}
if (isComponent)
if (isComponent) {
registerObjectWithContextById(index, instance);
return instance;
}
QQmlRefPointer<QQmlPropertyCache> cache = propertyCaches.at(index);
Q_ASSERT(!cache.isNull());
@ -1313,6 +1318,9 @@ bool QQmlObjectCreator::populateInstance(int index, QObject *instance, QObject *
} else {
vmeMetaObject = QQmlVMEMetaObject::get(_qobject);
}
registerObjectWithContextById(index, _qobject);
qSwap(_propertyCache, cache);
qSwap(_vmeMetaObject, vmeMetaObject);

View File

@ -42,6 +42,8 @@
#include <private/qrecursionwatcher_p.h>
#include <private/qqmlprofiler_p.h>
#include <qpointer.h>
QT_BEGIN_NAMESPACE
class QQmlAbstractBinding;
@ -55,7 +57,7 @@ struct QQmlObjectCreatorSharedState : public QSharedData
QQmlContextData *creationContext;
QFiniteStack<QQmlAbstractBinding*> allCreatedBindings;
QFiniteStack<QQmlParserStatus*> allParserStatusCallbacks;
QFiniteStack<QObject*> allCreatedObjects;
QFiniteStack<QPointer<QObject> > allCreatedObjects;
QV4::Value *allJavaScriptObjects; // pointer to vector on JS stack to reference JS wrappers during creation phase.
QQmlComponentAttached *componentAttached;
QList<QQmlEnginePrivate::FinalizeCallback> finalizeCallbacks;
@ -81,8 +83,8 @@ public:
QList<QQmlError> errors;
QQmlContextData *parentContextData() const { return parentContext; }
QFiniteStack<QObject*> &allCreatedObjects() const { return sharedState->allCreatedObjects; }
QQmlContextData *parentContextData() { return parentContext.contextData(); }
QFiniteStack<QPointer<QObject> > &allCreatedObjects() const { return sharedState->allCreatedObjects; }
private:
QQmlObjectCreator(QQmlContextData *contextData, QQmlCompiledData *compiledData, QQmlObjectCreatorSharedState *inheritedSharedState);
@ -103,6 +105,8 @@ private:
QString stringAt(int idx) const { return qmlUnit->stringAt(idx); }
void recordError(const QV4::CompiledData::Location &location, const QString &description);
void registerObjectWithContextById(int objectIndex, QObject *instance) const;
enum Phase {
Startup,
CreatingObjects,
@ -115,7 +119,7 @@ private:
QQmlEngine *engine;
QQmlCompiledData *compiledData;
const QV4::CompiledData::Unit *qmlUnit;
QQmlContextData *parentContext;
QQmlGuardedContextData parentContext;
QQmlContextData *context;
const QHash<int, QQmlCompiledData::TypeReference*> &resolvedTypes;
const QVector<QQmlPropertyCache *> &propertyCaches;

View File

@ -140,6 +140,7 @@ public:
void loadWithStaticData(QQmlDataBlob *b, const QByteArray &);
void loadWithStaticDataAsync(QQmlDataBlob *b, const QByteArray &);
void loadWithCachedUnit(QQmlDataBlob *b, const QQmlPrivate::CachedQmlUnit *unit);
void loadWithCachedUnitAsync(QQmlDataBlob *b, const QQmlPrivate::CachedQmlUnit *unit);
void callCompleted(QQmlDataBlob *b);
void callDownloadProgressChanged(QQmlDataBlob *b, qreal p);
void initializeEngine(QQmlExtensionInterface *, const char *);
@ -777,6 +778,12 @@ void QQmlDataLoaderThread::loadWithCachedUnit(QQmlDataBlob *b, const QQmlPrivate
callMethodInThread(&This::loadWithCachedUnitThread, b, unit);
}
void QQmlDataLoaderThread::loadWithCachedUnitAsync(QQmlDataBlob *b, const QQmlPrivate::CachedQmlUnit *unit)
{
b->addref();
postMethodToThread(&This::loadWithCachedUnitThread, b, unit);
}
void QQmlDataLoaderThread::callCompleted(QQmlDataBlob *b)
{
b->addref();
@ -980,7 +987,7 @@ void QQmlDataLoader::loadWithStaticData(QQmlDataBlob *blob, const QByteArray &da
}
}
void QQmlDataLoader::loadWithCachedUnit(QQmlDataBlob *blob, const QQmlPrivate::CachedQmlUnit *unit)
void QQmlDataLoader::loadWithCachedUnit(QQmlDataBlob *blob, const QQmlPrivate::CachedQmlUnit *unit, Mode mode)
{
#ifdef DATABLOB_DEBUG
qWarning("QQmlDataLoader::loadWithUnitFcatory(%s, data): %s thread", qPrintable(blob->m_url.toString()),
@ -993,12 +1000,18 @@ void QQmlDataLoader::loadWithCachedUnit(QQmlDataBlob *blob, const QQmlPrivate::C
unlock();
loadWithCachedUnitThread(blob, unit);
lock();
} else {
} else if (mode == PreferSynchronous) {
unlock();
m_thread->loadWithCachedUnit(blob, unit);
lock();
if (!blob->isCompleteOrError())
blob->m_data.setIsAsync(true);
} else {
Q_ASSERT(mode == Asynchronous);
blob->m_data.setIsAsync(true);
unlock();
m_thread->loadWithCachedUnitAsync(blob, unit);
lock();
}
}
@ -1602,7 +1615,7 @@ QQmlTypeData *QQmlTypeLoader::getType(const QUrl &url, Mode mode)
// TODO: if (compiledData == 0), is it safe to omit this insertion?
m_typeCache.insert(url, typeData);
if (const QQmlPrivate::CachedQmlUnit *cachedUnit = QQmlMetaType::findCachedCompilationUnit(url)) {
QQmlDataLoader::loadWithCachedUnit(typeData, cachedUnit);
QQmlDataLoader::loadWithCachedUnit(typeData, cachedUnit, mode);
} else {
QQmlDataLoader::load(typeData, mode);
}

View File

@ -221,7 +221,7 @@ public:
void load(QQmlDataBlob *, Mode = PreferSynchronous);
void loadWithStaticData(QQmlDataBlob *, const QByteArray &, Mode = PreferSynchronous);
void loadWithCachedUnit(QQmlDataBlob *blob, const QQmlPrivate::CachedQmlUnit *unit);
void loadWithCachedUnit(QQmlDataBlob *blob, const QQmlPrivate::CachedQmlUnit *unit, Mode mode = PreferSynchronous);
QQmlEngine *engine() const;
void initializeEngine(QQmlExtensionInterface *, const char *);

View File

@ -105,7 +105,7 @@ void QQmlVMEGuard::guard(QQmlObjectCreator *creator)
{
clear();
QFiniteStack<QObject*> &objects = creator->allCreatedObjects();
QFiniteStack<QPointer<QObject> > &objects = creator->allCreatedObjects();
m_objectCount = objects.count();
m_objects = new QPointer<QObject>[m_objectCount];
for (int ii = 0; ii < m_objectCount; ++ii)

View File

@ -135,7 +135,7 @@ public:
QV4::ExecutionEngine *v4;
QQmlDelegateModelItemMetaType * const metaType;
QQmlContextData *contextData;
QObject *object;
QPointer<QObject> object;
QPointer<QQmlDelegateModelAttached> attached;
QQDMIncubationTask *incubationTask;
int objectRef;

View File

@ -368,6 +368,7 @@ void QQmlInstantiator::setModel(const QVariant &v)
if (object && (vim = qobject_cast<QQmlInstanceModel *>(object))) {
if (d->ownModel) {
delete d->instanceModel;
prevModel = 0;
d->ownModel = false;
}
d->instanceModel = vim;

View File

@ -802,7 +802,7 @@ int ListElement::setDoubleProperty(const ListLayout::Role &role, double d)
if (role.type == ListLayout::Role::Number) {
char *mem = getPropertyMemory(role);
double *value = new (mem) double;
double *value = reinterpret_cast<double *>(mem);
bool changed = *value != d;
*value = d;
if (changed)
@ -818,7 +818,7 @@ int ListElement::setBoolProperty(const ListLayout::Role &role, bool b)
if (role.type == ListLayout::Role::Bool) {
char *mem = getPropertyMemory(role);
bool *value = new (mem) bool;
bool *value = reinterpret_cast<bool *>(mem);
bool changed = *value != b;
*value = b;
if (changed)
@ -834,8 +834,8 @@ int ListElement::setListProperty(const ListLayout::Role &role, ListModel *m)
if (role.type == ListLayout::Role::List) {
char *mem = getPropertyMemory(role);
ListModel **value = new (mem) ListModel *;
if (*value) {
ListModel **value = reinterpret_cast<ListModel **>(mem);
if (*value && *value != m) {
(*value)->destroy();
delete *value;
}

View File

@ -2808,7 +2808,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_strokeText(QV4::CallContex
\brief Provides a Context2D TextMetrics interface
The TextMetrics object can be created by QtQuick::Context2D::measureText method.
See \l{http://www.w3.org/TR/2dcontext/#textmetrics}{W3C 2d context TexMetrics} for more details.
See \l{http://www.w3.org/TR/2dcontext/#textmetrics}{W3C 2d context TextMetrics} for more details.
\sa Context2D::measureText
\sa width

View File

@ -1037,6 +1037,18 @@ void QSGThreadedRenderLoop::releaseResources(Window *w, bool inDestructor)
w->thread->postEvent(new WMTryReleaseEvent(window, inDestructor, fallback));
w->thread->waitCondition.wait(&w->thread->mutex);
delete fallback;
// Avoid a shutdown race condition.
// If SG is invalidated and 'active' becomes false, the thread's run()
// method will exit. handleExposure() relies on QThread::isRunning() (because it
// potentially needs to start the thread again) and our mutex cannot be used to
// track the thread stopping, so we wait a few nanoseconds extra so the thread
// can exit properly.
if (!w->thread->active) {
qCDebug(QSG_LOG_RENDERLOOP) << " - waiting for render thread to exit" << w->window;
w->thread->wait();
qCDebug(QSG_LOG_RENDERLOOP) << " - render thread finished" << w->window;
}
}
w->thread->mutex.unlock();
}

View File

@ -67,7 +67,7 @@ public:
A StateChangeScript is run upon entering a state. You can optionally use
ScriptAction to specify the point in the transition at which
the StateChangeScript should to be run.
the StateChangeScript should be run.
\snippet qml/states/statechangescript.qml state and transition

View File

@ -0,0 +1,23 @@
import QtQuick 2.0
Item {
visible: false
property bool success: false
property bool loading: true
Item {
visible: someOtherItem.someProperty
onVisibleChanged: {
if (!visible) {
success = loading
}
}
}
Item {
id: someOtherItem
property bool someProperty: true
}
Component.onCompleted: loading = false
}

View File

@ -235,6 +235,8 @@ private slots:
void noChildEvents();
void earlyIdObjectAccess();
private:
QQmlEngine engine;
QStringList defaultImportPathList;
@ -3970,6 +3972,14 @@ void tst_qqmllanguage::noChildEvents()
QCOMPARE(object->childAddedEventCount(), 0);
}
void tst_qqmllanguage::earlyIdObjectAccess()
{
QQmlComponent component(&engine, testFileUrl("earlyIdObjectAccess.qml"));
QScopedPointer<QObject> o(component.create());
QVERIFY(!o.isNull());
QVERIFY(o->property("success").toBool());
}
QTEST_MAIN(tst_qqmllanguage)
#include "tst_qqmllanguage.moc"

View File

@ -0,0 +1,103 @@
/****************************************************************************
**
** Copyright (C) 2014 Jolla Ltd, author: <gunnar.sletta@jollamobile.com>
** Contact: http://www.qt-project.org/legal
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** 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 Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/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 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
import QtQuick 2.2
import QtTest 1.0
Item {
width : 800
height : 600
Timer {
id: probablyOkNow
interval: 2000
running: true
repeat: false
onTriggered: testCase.when = true;
}
TestCase {
id: testCase
name: "unloaded-repeater"
when: false
function test_endresult()
{
havocTimer.running = false;
verify(true, "If we didn't crash by now, all is good")
}
}
Timer {
id: havocTimer
interval: 1
running: true
repeat: true
onTriggered: {
loader.sourceComponent = null
loader.sourceComponent = component1
}
}
Loader {
id : loader
asynchronous : true
}
Component {
id : component1
Grid {
columns: 70
spacing: 2
Repeater {
model : 2000
Rectangle {
width : 3
height : 3
color : "blue"
}
}
}
}
}

View File

@ -65,6 +65,7 @@ void tst_dialogs::fileDialogDefaultModality()
window->setGeometry(240,240,1024,320);
window->show();
QVERIFY(QTest::qWaitForWindowExposed(window));
QVERIFY(window->rootObject());
// Click to show
QObject *dlg = qvariant_cast<QObject *>(window->rootObject()->property("fileDialog"));
@ -110,14 +111,15 @@ void tst_dialogs::fileDialogNonModal()
window->setGeometry(240,240,1024,320);
window->show();
QVERIFY(QTest::qWaitForWindowExposed(window));
QVERIFY(window->rootObject());
// Click to toggle visibility
QObject *dlg = qvariant_cast<QObject *>(window->rootObject()->property("fileDialog"));
dlg->setProperty("modality", QVariant((int)Qt::NonModal));
QSignalSpy spyVisibilityChanged(dlg, SIGNAL(visibilityChanged()));
QTest::mouseClick(window, Qt::LeftButton, 0, QPoint(1000, 100)); // show
QTRY_VERIFY(spyVisibilityChanged.count() > 0);
int visibilityChangedCount = spyVisibilityChanged.count();
QTRY_VERIFY(visibilityChangedCount > 0);
QCOMPARE(dlg->property("visible").toBool(), true);
QTest::mouseClick(window, Qt::LeftButton, 0, QPoint(1000, 100)); // hide
QTRY_VERIFY(spyVisibilityChanged.count() > visibilityChangedCount);
@ -134,6 +136,7 @@ void tst_dialogs::fileDialogNameFilters()
window->setGeometry(240,240,1024,320);
window->show();
QVERIFY(QTest::qWaitForWindowExposed(window));
QVERIFY(window->rootObject());
QObject *dlg = qvariant_cast<QObject *>(window->rootObject()->property("fileDialog"));
QStringList filters;