diff options
21 files changed, 246 insertions, 27 deletions
diff --git a/dist/changes-5.3.2 b/dist/changes-5.3.2 new file mode 100644 index 0000000000..5434c8fc94 --- /dev/null +++ b/dist/changes-5.3.2 @@ -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 diff --git a/examples/quick/demos/calqlatr/calqlatr.qml b/examples/quick/demos/calqlatr/calqlatr.qml index 0a092c25da..5f0ebe85a8 100644 --- a/examples/quick/demos/calqlatr/calqlatr.qml +++ b/examples/quick/demos/calqlatr/calqlatr.qml @@ -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) } diff --git a/examples/quick/demos/samegame/samegame.pro b/examples/quick/demos/samegame/samegame.pro index b9b316871c..51e6f00321 100644 --- a/examples/quick/demos/samegame/samegame.pro +++ b/examples/quick/demos/samegame/samegame.pro @@ -1,6 +1,6 @@ TEMPLATE = app -QT += qml quick +QT += qml quick sql SOURCES += main.cpp RESOURCES += samegame.qrc diff --git a/src/qml/jsruntime/qv4arraydata.cpp b/src/qml/jsruntime/qv4arraydata.cpp index 2c975fef70..f7940c9602 100644 --- a/src/qml/jsruntime/qv4arraydata.cpp +++ b/src/qml/jsruntime/qv4arraydata.cpp @@ -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); diff --git a/src/qml/jsruntime/qv4globalobject.cpp b/src/qml/jsruntime/qv4globalobject.cpp index 9e53d51d79..49032e5bcf 100644 --- a/src/qml/jsruntime/qv4globalobject.cpp +++ b/src/qml/jsruntime/qv4globalobject.cpp @@ -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) diff --git a/src/qml/qml/qqmlincubator.cpp b/src/qml/qml/qqmlincubator.cpp index edd5573a02..b40ac5fdeb 100644 --- a/src/qml/qml/qqmlincubator.cpp +++ b/src/qml/qml/qqmlincubator.cpp @@ -376,7 +376,7 @@ finishIncubate: enginePriv->erroredBindings->removeError(); } } - } else { + } else if (!creator.isNull()) { vmeGuard.guard(creator.data()); } } diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp index 4efe72d862..0ad60e01ab 100644 --- a/src/qml/qml/qqmlobjectcreator.cpp +++ b/src/qml/qml/qqmlobjectcreator.cpp @@ -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); diff --git a/src/qml/qml/qqmlobjectcreator_p.h b/src/qml/qml/qqmlobjectcreator_p.h index 5c6a4b4476..6919281b77 100644 --- a/src/qml/qml/qqmlobjectcreator_p.h +++ b/src/qml/qml/qqmlobjectcreator_p.h @@ -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; diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp index 72a62ed065..6913019562 100644 --- a/src/qml/qml/qqmltypeloader.cpp +++ b/src/qml/qml/qqmltypeloader.cpp @@ -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); } diff --git a/src/qml/qml/qqmltypeloader_p.h b/src/qml/qml/qqmltypeloader_p.h index 06838478b9..3d3ad28091 100644 --- a/src/qml/qml/qqmltypeloader_p.h +++ b/src/qml/qml/qqmltypeloader_p.h @@ -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 *); diff --git a/src/qml/qml/qqmlvme.cpp b/src/qml/qml/qqmlvme.cpp index 23cf74eaf7..6ecc3bda2e 100644 --- a/src/qml/qml/qqmlvme.cpp +++ b/src/qml/qml/qqmlvme.cpp @@ -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) diff --git a/src/qml/types/qqmldelegatemodel_p_p.h b/src/qml/types/qqmldelegatemodel_p_p.h index f8002a43ad..a7def0ad50 100644 --- a/src/qml/types/qqmldelegatemodel_p_p.h +++ b/src/qml/types/qqmldelegatemodel_p_p.h @@ -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; diff --git a/src/qml/types/qqmlinstantiator.cpp b/src/qml/types/qqmlinstantiator.cpp index eba2d4b668..891011081d 100644 --- a/src/qml/types/qqmlinstantiator.cpp +++ b/src/qml/types/qqmlinstantiator.cpp @@ -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; diff --git a/src/qml/types/qqmllistmodel.cpp b/src/qml/types/qqmllistmodel.cpp index 4fca11b511..25879972ca 100644 --- a/src/qml/types/qqmllistmodel.cpp +++ b/src/qml/types/qqmllistmodel.cpp @@ -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; } diff --git a/src/quick/items/context2d/qquickcontext2d.cpp b/src/quick/items/context2d/qquickcontext2d.cpp index 228f0be3fe..28c84facb5 100644 --- a/src/quick/items/context2d/qquickcontext2d.cpp +++ b/src/quick/items/context2d/qquickcontext2d.cpp @@ -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 diff --git a/src/quick/scenegraph/qsgthreadedrenderloop.cpp b/src/quick/scenegraph/qsgthreadedrenderloop.cpp index b69058a504..7bf1d759f7 100644 --- a/src/quick/scenegraph/qsgthreadedrenderloop.cpp +++ b/src/quick/scenegraph/qsgthreadedrenderloop.cpp @@ -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(); } diff --git a/src/quick/util/qquickstatechangescript.cpp b/src/quick/util/qquickstatechangescript.cpp index 89fa22205f..02a9507ce9 100644 --- a/src/quick/util/qquickstatechangescript.cpp +++ b/src/quick/util/qquickstatechangescript.cpp @@ -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 diff --git a/tests/auto/qml/qqmllanguage/data/earlyIdObjectAccess.qml b/tests/auto/qml/qqmllanguage/data/earlyIdObjectAccess.qml new file mode 100644 index 0000000000..22c335b1a7 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/earlyIdObjectAccess.qml @@ -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 +} diff --git a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp index d6d1cef36b..363dd0244e 100644 --- a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp +++ b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp @@ -234,6 +234,8 @@ private slots: void noChildEvents(); + void earlyIdObjectAccess(); + private: QQmlEngine engine; QStringList defaultImportPathList; @@ -3888,6 +3890,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" diff --git a/tests/auto/qmltest/stability/tst_unloadrepeater.qml b/tests/auto/qmltest/stability/tst_unloadrepeater.qml new file mode 100644 index 0000000000..dfb631493b --- /dev/null +++ b/tests/auto/qmltest/stability/tst_unloadrepeater.qml @@ -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" + } + } + } + } +} diff --git a/tests/auto/quick/dialogs/tst_dialogs.cpp b/tests/auto/quick/dialogs/tst_dialogs.cpp index 7dd360c9b0..01fe6c3722 100644 --- a/tests/auto/quick/dialogs/tst_dialogs.cpp +++ b/tests/auto/quick/dialogs/tst_dialogs.cpp @@ -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; |