diff options
40 files changed, 382 insertions, 152 deletions
diff --git a/dist/changes-5.1.0 b/dist/changes-5.1.0 index 8633d22eef..eaf6d05094 100644 --- a/dist/changes-5.1.0 +++ b/dist/changes-5.1.0 @@ -46,6 +46,13 @@ Third party components - tryCompare now correctly fails when it only gets two parameters + - If a QObject has a property and a slot (or invokable method) with the same + name, in QML the previous behavior was to let the property obscure the + method; from Qt 5.1 things work in the opposite way, that is a property can + never obscure a method having the same name. This is especially important + for objects having dynamic properties, such as QQmlPropertyMap. This change + was a consequence of the fix for QTBUG-29836. + **************************************************************************** * Library * **************************************************************************** diff --git a/examples/quick/customitems/painteditem/painteditem.pro b/examples/quick/customitems/painteditem/painteditem.pro index 77e4d146e1..3ec6420abf 100644 --- a/examples/quick/customitems/painteditem/painteditem.pro +++ b/examples/quick/customitems/painteditem/painteditem.pro @@ -18,3 +18,6 @@ qmldir.files = TextBalloonPlugin/qmldir qmldir.path = $$[QT_INSTALL_EXAMPLES]/quick/customitems/painteditem/TextBalloonPlugin INSTALLS += qmldir target + +OTHER_FILES += \ + textballoons.qml diff --git a/src/imports/dialogs/doc/qtquickdialogs.qdocconf b/src/imports/dialogs/doc/qtquickdialogs.qdocconf index 5caa1c0588..34f19b5ff3 100644 --- a/src/imports/dialogs/doc/qtquickdialogs.qdocconf +++ b/src/imports/dialogs/doc/qtquickdialogs.qdocconf @@ -19,10 +19,9 @@ qhp.QtQuickDialogs.customFilters.Qt.filterAttributes = qtquickdialogs $QT_VERSIO qhp.QtQuickDialogs.subprojects = qtquickdialogsqmltypes qhp.QtQuickDialogs.subprojects.qtquickdialogsqmltypes.title = QML Types -qhp.QtQuickDialogs.subprojects.qtquickdialogsqmltypes.indexTitle = Qt Quick Dialogs +qhp.QtQuickDialogs.subprojects.qtquickdialogsqmltypes.indexTitle = Qt Quick Dialogs QML Types qhp.QtQuickDialogs.subprojects.qtquickdialogsqmltypes.selectors = fake:qmlclass qhp.QtQuickDialogs.subprojects.qtquickdialogsqmltypes.sortPages = true -qhp.QtQuickDialogs.subprojects.qtquickdialogsqmltypes.type = manual depends = qtqml qtquick qtgui qtwidgets qtdoc diff --git a/src/imports/models/plugin.cpp b/src/imports/models/plugin.cpp index 2181562098..90e8a56399 100644 --- a/src/imports/models/plugin.cpp +++ b/src/imports/models/plugin.cpp @@ -47,7 +47,7 @@ QT_BEGIN_NAMESPACE /*! \qmlmodule QtQml.Models 2 - \title Qt QML Model QML Types + \title Qt QML Models QML Types \ingroup qmlmodules \brief Provides QML types for data models \since 5.1 @@ -60,7 +60,8 @@ QT_BEGIN_NAMESPACE import QtQml.Models 2.1 \endcode - Note that QtQml.Models module started at version 2.1 to match the version of the parent module. + Note that QtQml.Models module started at version 2.1 to match the version + of the parent module, \l{Qt QML}. */ diff --git a/src/qml/doc/qtqml.qdocconf b/src/qml/doc/qtqml.qdocconf index 84cf64eddd..2198428a38 100644 --- a/src/qml/doc/qtqml.qdocconf +++ b/src/qml/doc/qtqml.qdocconf @@ -18,7 +18,7 @@ qhp.QtQml.indexRoot = qhp.QtQml.filterAttributes = qtqml $QT_VERSION qtrefdoc qhp.QtQml.customFilters.Qt.name = QtQml $QT_VERSION qhp.QtQml.customFilters.Qt.filterAttributes = qtqml $QT_VERSION -qhp.QtQml.subprojects = classes examples +qhp.QtQml.subprojects = qmltypes classes examples qhp.QtQml.subprojects.classes.title = C++ Classes qhp.QtQml.subprojects.classes.indexTitle = Qt QML C++ Classes qhp.QtQml.subprojects.classes.selectors = class fake:headerfile @@ -26,15 +26,21 @@ qhp.QtQml.subprojects.classes.sortPages = true qhp.QtQml.subprojects.examples.title = Examples qhp.QtQml.subprojects.examples.indexTitle = Qt Quick Code Samples qhp.QtQml.subprojects.examples.selectors = fake:example +qhp.QtQml.subprojects.qmltypes.title = QML Types +qhp.QtQml.subprojects.qmltypes.indexTitle = Qt QML QML Types +qhp.QtQml.subprojects.qmltypes.selectors = fake:qmlclass +qhp.QtQml.subprojects.qmltypes.sortPages = true tagfile = ../../../doc/qtqml/qtqml.tags depends += qtcore qtxmlpatterns qtgui qtquick qtdoc -headerdirs += .. +headerdirs += .. \ + ../../imports/models -sourcedirs += .. +sourcedirs += .. \ + ../../imports/models exampledirs += ../../../examples/qml \ ../ \ diff --git a/src/qml/doc/src/javascript/hostenvironment.qdoc b/src/qml/doc/src/javascript/hostenvironment.qdoc index a63ef617c0..3bd64ac115 100644 --- a/src/qml/doc/src/javascript/hostenvironment.qdoc +++ b/src/qml/doc/src/javascript/hostenvironment.qdoc @@ -166,6 +166,15 @@ Item { } \endqml +\li The \c with statement is deprecated. Using the \c with statement will issue a warning +at loading time and we plan on removing support for it in Qt 5.2. It is generally considered +a language feature that is not recommended for use due reducing the readability of code and disabling +many optimizations in the engine. It is also forbidden in ECMAScript 5 strict mode. + +\li JavaScript binding expressions are executed in non-strict mode. However we +plan on changing the default for bindings in Qt 5.2 to execute always in +ECMAScript 5 strict mode. + \endlist diff --git a/src/qml/doc/src/qmltypereference.qdoc b/src/qml/doc/src/qmltypereference.qdoc index f0aadbaf32..3def3209cc 100644 --- a/src/qml/doc/src/qmltypereference.qdoc +++ b/src/qml/doc/src/qmltypereference.qdoc @@ -58,8 +58,13 @@ follows: import QtQuick 2.0 \endqml -See the \l{Qt Quick} module documentation for more information about the -\c QtQuick namespace and what it provides to QML application developers. +See the \l{Qt Quick} module documentation for more information about the \c +QtQuick namespace and what it provides to QML application developers. + +The QML types for creating lists and models, such as \l ListModel and \l +ListElement, are moved to a submodule, \c QtQml.Models. The \l{Qt QML Models QML +Types}{Qt QML Models} page has more information. + The documentation for the types below applies equally to the types of the same name provided by the \l{Qt Quick} module, as they are in fact identical. diff --git a/src/qml/doc/src/qtqml.qdoc b/src/qml/doc/src/qtqml.qdoc index 2c6bc640ff..26e4867bbc 100644 --- a/src/qml/doc/src/qtqml.qdoc +++ b/src/qml/doc/src/qtqml.qdoc @@ -84,6 +84,19 @@ various QML object types: \li \l Timer \endlist +\section2 Lists and Models + +New in Qt 5.1, the model types are moved to a submodule, \c QtQml.Models. The +\l{Qt QML Models QML Types}{Qt QML Models} page has more information. + +\list +\li \l DelegateModel +\li \l DelegateModelGroup +\li \l ListElement +\li \l ListModel +\li \l ObjectModel +\endlist + \section1 JavaScript Environment for QML Applications JavaScript expressions allow QML code to contain application logic. Qt QML diff --git a/src/qml/doc/src/whatsnew.qdoc b/src/qml/doc/src/whatsnew.qdoc index 38713a1976..eece3bcaab 100644 --- a/src/qml/doc/src/whatsnew.qdoc +++ b/src/qml/doc/src/whatsnew.qdoc @@ -39,13 +39,14 @@ a summary of the new changes: \li New properties for \l Qt.application: arguments, name, and version. \endlist -\section2 New Submodules +\section2 New Submodule -The Qt QML Models is a new submodule in Qt 5.1 and provides several QML types -for handling data with models and lists. +The \l{Qt QML Models QML Types}{Qt QML Models} is a new submodule in Qt 5.1 and +provides several QML types for handling data with models and lists. These types +replace types such as \l VisualItem, \l VisualDataModel, and \l VisualDataGroup. \list -\li \l{QtQml.Models}{Models} +\li \l{Qt QML Models QML Types}{Models} \endlist The \l{What's New in Qt 5.1} has more information about the Qt 5.1 release. diff --git a/src/qml/qml/parser/qqmljs.g b/src/qml/qml/parser/qqmljs.g index ff4f54374b..5d279ef1a2 100644 --- a/src/qml/qml/parser/qqmljs.g +++ b/src/qml/qml/parser/qqmljs.g @@ -2615,6 +2615,10 @@ case $rule_number: { node->lparenToken = loc(2); node->rparenToken = loc(4); sym(1).Node = node; + if (lexer->qmlMode()) { + const QString msg = qApp->translate("QQmlParser", "Deprecated JavaScript `with' statement detected in QML expression. Support for this will be removed in Qt 5.2!"); + diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Warning, node->withToken, msg)); + } } break; ./ diff --git a/src/qml/qml/parser/qqmljsparser.cpp b/src/qml/qml/parser/qqmljsparser.cpp index a0fa7a4711..46b5c041d4 100644 --- a/src/qml/qml/parser/qqmljsparser.cpp +++ b/src/qml/qml/parser/qqmljsparser.cpp @@ -1515,6 +1515,10 @@ case 311: { node->lparenToken = loc(2); node->rparenToken = loc(4); sym(1).Node = node; + if (lexer->qmlMode()) { + const QString msg = qApp->translate("QQmlParser", "Deprecated JavaScript `with' statement detected in QML expression. Support for this will be removed in Qt 5.2!"); + diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Warning, node->withToken, msg)); + } } break; case 312: { diff --git a/src/qml/qml/qqmlapplicationengine.cpp b/src/qml/qml/qqmlapplicationengine.cpp index 25095a465e..9181dad519 100644 --- a/src/qml/qml/qqmlapplicationengine.cpp +++ b/src/qml/qml/qqmlapplicationengine.cpp @@ -72,6 +72,7 @@ void QQmlApplicationEnginePrivate::init() QCoreApplication::installTranslator(qtTranslator); translators << qtTranslator; #endif + QCoreApplication::instance()->setProperty("__qml_using_qqmlapplicationengine", QVariant(true)); } void QQmlApplicationEnginePrivate::loadTranslations(const QUrl &rootFile) @@ -166,9 +167,14 @@ void QQmlApplicationEnginePrivate::_q_finishLoad(QObject *o) \list \li Connecting Qt.quit() to QCoreApplication::quit() \li Automatically loads translation files from an i18n directory adjacent to the main QML file. + \li Automatically sets an incubuation controller if the scene contains a QQuickWindow. \endlist The engine behavior can be further tweaked by using the inherited methods from QQmlEngine. + + \note In the future QQmlApplicationEngine may automatically apply file selectors. + To ensure forwards compatibility, do not use folder names containing a '+' character in your QML file + structure. */ /*! diff --git a/src/qml/qml/qqmlpropertycache.cpp b/src/qml/qml/qqmlpropertycache.cpp index b1ffc9a2d5..4712fbd614 100644 --- a/src/qml/qml/qqmlpropertycache.cpp +++ b/src/qml/qml/qqmlpropertycache.cpp @@ -1317,25 +1317,10 @@ QQmlPropertyData qQmlPropertyCacheCreate(const QMetaObject *metaObject, const QS Q_ASSERT(metaObject); QQmlPropertyData rv; - { - const QMetaObject *cmo = metaObject; - const QByteArray propertyName = property.toUtf8(); - while (cmo) { - int idx = cmo->indexOfProperty(propertyName); - if (idx != -1) { - QMetaProperty p = cmo->property(idx); - if (p.isScriptable()) { - rv.load(p); - return rv; - } else { - while (cmo && cmo->propertyOffset() >= idx) - cmo = cmo->superClass(); - } - } else { - cmo = 0; - } - } - } + + /* It's important to check the method list before checking for properties; + * otherwise, if the meta object is dynamic, a property will be created even + * if not found and it might obscure a method having the same name. */ //Used to block access to QObject::destroyed() and QObject::deleteLater() from QML static const int destroyedIdx1 = QObject::staticMetaObject.indexOfSignal("destroyed(QObject*)"); @@ -1357,6 +1342,31 @@ QQmlPropertyData qQmlPropertyCacheCreate(const QMetaObject *metaObject, const QS } } + { + const QMetaObject *cmo = metaObject; + const QByteArray propertyName = property.toUtf8(); + while (cmo) { + int idx = cmo->indexOfProperty(propertyName); + if (idx != -1) { + QMetaProperty p = cmo->property(idx); + if (p.isScriptable()) { + rv.load(p); + return rv; + } else { + bool changed = false; + while (cmo && cmo->propertyOffset() >= idx) { + cmo = cmo->superClass(); + changed = true; + } + /* If the "cmo" variable didn't change, set it to 0 to + * avoid running into an infinite loop */ + if (!changed) cmo = 0; + } + } else { + cmo = 0; + } + } + } return rv; } @@ -1395,7 +1405,8 @@ qQmlPropertyCacheProperty(QQmlEngine *engine, QObject *obj, const T &name, if (cache) { rv = cache->property(name, obj, context); - } else { + } + if (!rv) { local = qQmlPropertyCacheCreate(obj->metaObject(), qQmlPropertyCacheToString(name)); if (local.isValid()) rv = &local; diff --git a/src/qml/qml/qqmlscript.cpp b/src/qml/qml/qqmlscript.cpp index 613ff24f20..ba2882f3e7 100644 --- a/src/qml/qml/qqmlscript.cpp +++ b/src/qml/qml/qqmlscript.cpp @@ -1318,13 +1318,15 @@ bool QQmlScript::Parser::parse(const QString &qmlcode, const QByteArray & /* pre QQmlJS::Parser parser(&data->engine); - if (! parser.parse() || !_errors.isEmpty()) { + if (! parser.parse() || !parser.diagnosticMessages().isEmpty()) { // Extract errors from the parser foreach (const DiagnosticMessage &m, parser.diagnosticMessages()) { - if (m.isWarning()) + if (m.isWarning()) { + qWarning("%s:%d : %s", qPrintable(_scriptFile), m.loc.startLine, qPrintable(m.message)); continue; + } QQmlError error; error.setUrl(url); diff --git a/src/qml/qml/v8/qv8qobjectwrapper.cpp b/src/qml/qml/v8/qv8qobjectwrapper.cpp index 0336457027..53f70ad132 100644 --- a/src/qml/qml/v8/qv8qobjectwrapper.cpp +++ b/src/qml/qml/v8/qv8qobjectwrapper.cpp @@ -524,7 +524,7 @@ v8::Handle<v8::Value> QV8QObjectWrapper::GetProperty(QV8Engine *engine, QObject QQmlData *ddata = QQmlData::get(object, false); if (ddata && ddata->propertyCache) result = ddata->propertyCache->property(property, object, context); - else + if (!result) result = QQmlPropertyCache::property(engine->engine(), object, property, context, local); } diff --git a/src/qml/types/qqmldelegatemodel.cpp b/src/qml/types/qqmldelegatemodel.cpp index 53b8a3c79d..747c9391e9 100644 --- a/src/qml/types/qqmldelegatemodel.cpp +++ b/src/qml/types/qqmldelegatemodel.cpp @@ -121,15 +121,16 @@ QQmlDelegateModelParts::QQmlDelegateModelParts(QQmlDelegateModel *parent) /*! \qmltype VisualDataModel \instantiates QQmlDelegateModel - \inqmlmodule QtQml 2 + \inqmlmodule QtQuick 2 \ingroup qtquick-models \brief Encapsulates a model and delegate The VisualDataModel type encapsulates a model and the delegate that will be instantiated for items in a model. - This type is provided by \c {QtQuick 2} for compatibility reasons. The same implementation - is now primarily available as DelegateModel in the QtQml.Models module. + This type is provided by the \l{Qt QML} module due to compatibility reasons. + The same implementation is now primarily available as DelegateModel in the + \l{Qt QML Models QML Types}{Qt QML Models} module. \sa {QtQml.Models2::DelegateModel} */ @@ -142,12 +143,6 @@ QQmlDelegateModelParts::QQmlDelegateModelParts(QQmlDelegateModel *parent) The DelegateModel type encapsulates a model and the delegate that will be instantiated for items in the model. - This element is also available as DelegateModel in the \c QtQuick module. For full details, - see the \l DelegateModel documentation. - - The DelegateModel type encapsulates a model and the delegate that will - be instantiated for items in the model. - It is usually not necessary to create a DelegateModel. However, it can be useful for manipulating and accessing the \l modelIndex when a QAbstractItemModel subclass is used as the @@ -158,6 +153,9 @@ QQmlDelegateModelParts::QQmlDelegateModelParts(QQmlDelegateModel *parent) The example below illustrates using a DelegateModel with a ListView. \snippet delegatemodel/visualdatamodel.qml 0 + + \note This type is also available as \l VisualDataModel in the \l{Qt QML} + module due to compatibility reasons. */ QQmlDelegateModelPrivate::QQmlDelegateModelPrivate(QQmlContext *ctxt) @@ -856,7 +854,8 @@ void QQmlDelegateModelPrivate::incubatorStatusChanged(QQDMIncubationTask *incuba delete cacheItem->object; cacheItem->object = 0; cacheItem->scriptRef -= 1; - cacheItem->contextData->destroy(); + if (cacheItem->contextData) + cacheItem->contextData->destroy(); cacheItem->contextData = 0; if (!cacheItem->isReferenced()) { @@ -2169,14 +2168,31 @@ void QQmlDelegateModelGroupPrivate::destroyingPackage(QQuickPackage *package) } /*! + \qmltype VisualDataGroup + \instantiates QQmlDelegateModelGroup + \inqmlmodule QtQuick 2 + \ingroup qtquick-models + \brief Encapsulates a filtered set of visual data items + + The VisualDataGroup type provides a means to address the model data of a + model's delegate items, as well as sort and filter these delegate items. + + This type is provided by the \l{Qt QML} module due to compatibility reasons. + The same implementation is now primarily available as \l DelegateModelGroup + in the \l{Qt QML Models QML Types}{Qt QML Models} module. + + \sa {QtQml.Models2::DelegateModelGroup} +*/ +/*! \qmltype DelegateModelGroup \instantiates QQmlDelegateModelGroup - \inqmlmodule QtQml 2 + \inqmlmodule QtQml.Models 2 \ingroup qtquick-models \brief Encapsulates a filtered set of visual data items - The DelegateModelGroup type provides a means to address the model data of a DelegateModel's - delegate items, as well as sort and filter these delegate items. + The DelegateModelGroup type provides a means to address the model data of a + DelegateModel's delegate items, as well as sort and filter these delegate + items. The initial set of instantiable delegate items in a DelegateModel is represented by its \l {QtQml.Models2::DelegateModel::items}{items} group, which normally directly reflects @@ -2200,24 +2216,11 @@ void QQmlDelegateModelGroupPrivate::destroyingPackage(QQuickPackage *package) type or to cherry-pick specific items that should be instantiated irregardless of whether they're currently within a view's visible area. - \sa {QML Dynamic View Ordering Tutorial} -*/ -/*! - \qmltype DelegateModelGroup - \instantiates QQmlDelegateModelGroup - \inqmlmodule QtQml.Models 2 - \brief Encapsulates a filtered set of visual data items - - The DelegateModelGroup type provides a means to address the model data of a DelegateModel's - delegate items, as well as sort and filter these delegate items. - - This element is also available as DelegateModelGroup in the \c QtQuick module. For full details, - see the \l DelegateModelGroup documentation. + \note This type is also available as \l VisualDataGroup in the \l{Qt QML} + module due to compatibility reasons. - \sa {QtQuick::DelegateModelGroup} + \sa {QML Dynamic View Ordering Tutorial} */ - - QQmlDelegateModelGroup::QQmlDelegateModelGroup(QObject *parent) : QObject(*new QQmlDelegateModelGroupPrivate, parent) { diff --git a/src/qml/types/qqmllistmodel.cpp b/src/qml/types/qqmllistmodel.cpp index 5ddc0f52bd..0cfd9c6ccb 100644 --- a/src/qml/types/qqmllistmodel.cpp +++ b/src/qml/types/qqmllistmodel.cpp @@ -1426,24 +1426,12 @@ QQmlListModelParser::ListInstruction *QQmlListModelParser::ListModelData::instru \qmltype ListModel \instantiates QQmlListModel \inqmlmodule QtQml.Models 2 - \brief Defines a free-form list data source - - The ListModel is a simple container of ListElement definitions, each containing data roles. - The contents can be defined dynamically, or explicitly in QML. - - This type is also available in the \c {QtQuick 2} import. - - \sa {QtQml2::ListModel}{Full documentation for ListModel} -*/ -/*! - \qmltype ListModel - \instantiates QQmlListModel - \inqmlmodule QtQml 2 - \brief Defines a free-form list data source \ingroup qtquick-models + \brief Defines a free-form list data source - The ListModel is a simple container of ListElement definitions, each containing data roles. - The contents can be defined dynamically, or explicitly in QML. + The ListModel is a simple container of ListElement definitions, each + containing data roles. The contents can be defined dynamically, or + explicitly in QML. The number of elements in the model can be obtained from its \l count property. A number of familiar methods are also provided to manipulate the contents of the @@ -1803,7 +1791,7 @@ QHash<int, QByteArray> QQmlListModel::roleNames() const } /*! - \qmlproperty bool QtQml2::ListModel::dynamicRoles + \qmlproperty bool ListModel::dynamicRoles By default, the type of a role is fixed the first time the role is used. For example, if you create a role called @@ -1849,7 +1837,7 @@ void QQmlListModel::setDynamicRoles(bool enableDynamicRoles) } /*! - \qmlproperty int QtQml2::ListModel::count + \qmlproperty int ListModel::count The number of data entries in the model. */ int QQmlListModel::count() const @@ -2539,18 +2527,6 @@ bool QQmlListModelParser::definesEmptyList(const QString &s) \instantiates QQmlListElement \inqmlmodule QtQml.Models 2 \brief Defines a data item in a ListModel - - List elements are defined inside ListModel definitions, and represent items in a list. - - This type is also available in the \c {QtQuick 2} import. - - \sa {QtQml2::ListElement}{Full documentation for ListElement} -*/ -/*! - \qmltype ListElement - \instantiates QQmlListElement - \inqmlmodule QtQml 2 - \brief Defines a data item in a ListModel \ingroup qtquick-models List elements are defined inside ListModel definitions, and represent items in a diff --git a/src/qml/types/qqmllistmodel_p_p.h b/src/qml/types/qqmllistmodel_p_p.h index 0190081320..44c349fbe6 100644 --- a/src/qml/types/qqmllistmodel_p_p.h +++ b/src/qml/types/qqmllistmodel_p_p.h @@ -229,6 +229,9 @@ private: QStringHash<Role *> roleHash; }; +/*! +\internal +*/ class ListElement { public: @@ -292,6 +295,9 @@ private: friend class ListModel; }; +/*! +\internal +*/ class ListModel { public: @@ -375,4 +381,3 @@ QT_END_NAMESPACE Q_DECLARE_METATYPE(ListModel *); #endif // QQUICKLISTMODEL_P_P_H - diff --git a/src/qml/types/qqmlobjectmodel.cpp b/src/qml/types/qqmlobjectmodel.cpp index 3e8a67a7d2..f2a7477c1b 100644 --- a/src/qml/types/qqmlobjectmodel.cpp +++ b/src/qml/types/qqmlobjectmodel.cpp @@ -169,7 +169,7 @@ public: /*! \qmltype VisualItemModel \instantiates QQmlObjectModel - \inqmlmodule QtQml 2 + \inqmlmodule QtQuick 2 \brief Defines a set of objects to be used as a model The VisualItemModel type encapsulates contains the objects to be used diff --git a/src/quick/designer/designerwindowmanager_p.h b/src/quick/designer/designerwindowmanager_p.h index 02aacf06bd..3bbd0c2825 100644 --- a/src/quick/designer/designerwindowmanager_p.h +++ b/src/quick/designer/designerwindowmanager_p.h @@ -67,7 +67,7 @@ class QSGContext; class QAnimationDriver; class QOpenGLContext; -class DesignerWindowManager : public QObject, public QSGRenderLoop +class DesignerWindowManager : public QSGRenderLoop { Q_OBJECT public: diff --git a/src/quick/doc/qtquick.qdocconf b/src/quick/doc/qtquick.qdocconf index a27b0f82f7..f20890c378 100644 --- a/src/quick/doc/qtquick.qdocconf +++ b/src/quick/doc/qtquick.qdocconf @@ -60,4 +60,5 @@ headerdirs += ../../plugins sourcedirs += ../../plugins #exclude certain directories -excludedirs = ../../imports/dialogs +excludedirs += ../../imports/dialogs \ + ../../imports/models diff --git a/src/quick/doc/src/qmltypereference.qdoc b/src/quick/doc/src/qmltypereference.qdoc index bb488ac2f2..6863758455 100644 --- a/src/quick/doc/src/qmltypereference.qdoc +++ b/src/quick/doc/src/qmltypereference.qdoc @@ -56,19 +56,19 @@ information about the concepts which are central to \c QtQuick. Qt Quick includes several submodules which contain additional types. \list - \li \l{QtQuick.XmlListModel 2}{XML List Model} - contains types + \li \l{Qt Quick XmlListModel QML Types}{XML List Model} - contains types for creating models from XML data - \li \l{QtQuick.LocalStorage 2}{Local Storage} - a submodule + \li \l{Qt Quick Local Storage QML Types}{Local Storage} - a submodule containing a JavaScript interface for an SQLite database - \li \l{QtQuick.Particles 2}{Particles} - provides a particle + \li \l{Qt Quick Particles QML Types}{Particles} - provides a particle system for QML applications - \li \l{QtQuick.Window 2}{Window} - contains types for creating + \li \l{Qt Quick Window QML Types}{Window} - contains types for creating top-level windows and accessing screen information - \li \l{QtQuick.Dialogs 1}{Dialogs} - contains types for creating and + \li \l{Qt Quick Dialogs QML Types}{Dialogs} - contains types for creating and interacting with system dialogs - \li \l{QtQuick.Controls 1.0}{Controls} - provides a set of reusable + \li \l{Qt Quick Controls QML Types}{Controls} - provides a set of reusable UI components - \li \l{QtQuick.Layouts 1.0}{Layouts} - contains types that are used + \li \l{Qt Quick Layouts QML Types}{Layouts} - contains types that are used to arrange items in the user interface \endlist @@ -234,13 +234,26 @@ Animation paths \section2 Model/View Types And Data Storage And Access -Models And Model Data +QML Lists and Models + +The \l{Qt QML Models QML Types}{Qt QML Models} submodule provides the types for +structuring data with models and lists. +\list +\li \l ListModel - Defines a list of data +\li \l ListElement - Defines a data item in a \l ListModel +\endlist + +These QML types are part of Qt Quick for backwards compatibility, but for +newer applications, \l{Qt QML Models QML Types}{Qt QML Models} provides +the same functionality. \list -\li \l {QtQml2::ListModel}{ListModel} - Defines a list of data -\li \l {QtQml2::ListElement}{ListElement} - Defines a data item in a \l {QtQml2::ListModel}{ListModel} \li \l {VisualItemModel} - Contains items that already defines its own visual delegate \li \l {VisualDataModel} - Encapsulates a model and a delegate \li \l {VisualDataGroup} - Encapsulates a filtered set of visual data items +\endlist + +XML Lists +\list \li \l {XmlListModel} - Specifies a model using XPath expressions \li \l {XmlRole} - Specifies a role for an \l {XmlListModel} \endlist diff --git a/src/quick/doc/src/qtquick.qdoc b/src/quick/doc/src/qtquick.qdoc index 0a4d276cb8..deb6aa164c 100644 --- a/src/quick/doc/src/qtquick.qdoc +++ b/src/quick/doc/src/qtquick.qdoc @@ -43,7 +43,7 @@ QML types for creating user interfaces with the QML language, and a \l{Qt Quick C++ Classes}{C++ API} for extending QML applications with C++ code. \note From Qt 5.1, a set of Qt Quick based UI controls is available to -create classic desktop-style user interfaces. Please see \l{Qt Quick Controls} +create user interfaces. Please see \l{Qt Quick Controls} for more information. For those new to QML and Qt Quick, please see diff --git a/src/quick/doc/src/whatsnew.qdoc b/src/quick/doc/src/whatsnew.qdoc index 2b865073d3..973d41dca2 100644 --- a/src/quick/doc/src/whatsnew.qdoc +++ b/src/quick/doc/src/whatsnew.qdoc @@ -44,6 +44,15 @@ features introduced by the new import and new classes in Qt 5.1: \li New \l TextEdit properties: selectByKeyboard and textDocument \li A \l Window declared inside another Window or \l Item will automatically be transient for (centered upon) the outer window. +\li These types are now part of \l{Qt QML}: + \list + \li \l {VisualItemModel} + \li \l {VisualDataModel} - Encapsulates a model and a delegate + \li \l {VisualDataGroup} + \endlist + These types are kept due to compatibility reasons and are replaced by the + \l{Qt QML Models QML Types}{Qt QML Models} types. + \endlist \endlist \section2 New Submodules diff --git a/src/quick/items/context2d/qquickcontext2d.cpp b/src/quick/items/context2d/qquickcontext2d.cpp index 5709d58d58..c948d87cc0 100644 --- a/src/quick/items/context2d/qquickcontext2d.cpp +++ b/src/quick/items/context2d/qquickcontext2d.cpp @@ -2624,7 +2624,7 @@ static v8::Handle<v8::Value> ctx2d_createImageData(const v8::Arguments &args) } /*! - \qmlmethod CanvasImageData QtQuick2::Canvas::getImageData(real sx, real sy, real sw, real sh) + \qmlmethod CanvasImageData QtQuick2::Context2D::getImageData(real sx, real sy, real sw, real sh) Returns an CanvasImageData object containing the image data for the given rectangle of the canvas. */ static v8::Handle<v8::Value> ctx2d_getImageData(const v8::Arguments &args) diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp index 7137bb165e..7b84168bb9 100644 --- a/src/quick/items/qquickwindow.cpp +++ b/src/quick/items/qquickwindow.cpp @@ -89,44 +89,49 @@ void QQuickWindowPrivate::updateFocusItemTransform() #endif } - class QQuickWindowIncubationController : public QObject, public QQmlIncubationController { Q_OBJECT public: - QQuickWindowIncubationController(const QQuickWindow *window) - : m_window(QQuickWindowPrivate::get(const_cast<QQuickWindow *>(window))) + QQuickWindowIncubationController(QSGRenderLoop *loop) + : m_renderLoop(loop), m_timer(0) { // Allow incubation for 1/3 of a frame. m_incubation_time = qMax(1, int(1000 / QGuiApplication::primaryScreen()->refreshRate()) / 3); - m_animation_driver = m_window->windowManager->animationDriver(); + m_animation_driver = m_renderLoop->animationDriver(); if (m_animation_driver) { connect(m_animation_driver, SIGNAL(stopped()), this, SLOT(animationStopped())); - connect(window, SIGNAL(frameSwapped()), this, SLOT(incubate())); + connect(m_renderLoop, SIGNAL(timeToIncubate()), this, SLOT(incubate())); } } protected: - virtual bool event(QEvent *e) + void timerEvent(QTimerEvent *e) { - if (e->type() == QEvent::User) { - incubate(); - return true; + killTimer(m_timer); + m_timer = 0; + incubate(); + } + + void incubateAgain() { + if (m_timer == 0) { + // Wait for a while before processing the next batch. Using a + // timer to avoid starvation of system events. + m_timer = startTimer(m_incubation_time); } - return QObject::event(e); } public slots: void incubate() { if (incubatingObjectCount()) { - if (m_animation_driver && m_animation_driver->isRunning()) { + if (m_renderLoop->interleaveIncubation()) { incubateFor(m_incubation_time); } else { incubateFor(m_incubation_time * 2); if (incubatingObjectCount()) - QCoreApplication::postEvent(this, new QEvent(QEvent::User)); + incubateAgain(); } } } @@ -136,14 +141,15 @@ public slots: protected: virtual void incubatingObjectCountChanged(int count) { - if (count && (!m_animation_driver || !m_animation_driver->isRunning())) - QCoreApplication::postEvent(this, new QEvent(QEvent::User)); + if (count && !m_renderLoop->interleaveIncubation()) + incubateAgain(); } private: - QQuickWindowPrivate *m_window; + QSGRenderLoop *m_renderLoop; int m_incubation_time; QAnimationDriver *m_animation_driver; + int m_timer; }; #include "qquickwindow.moc" @@ -349,6 +355,7 @@ QQuickWindowPrivate::QQuickWindowPrivate() , persistentGLContext(true) , persistentSceneGraph(true) , lastWheelEventAccepted(false) + , componentCompleted(true) , renderTarget(0) , renderTargetId(0) , incubationController(0) @@ -2779,7 +2786,7 @@ QQmlIncubationController *QQuickWindow::incubationController() const Q_D(const QQuickWindow); if (!d->incubationController) - d->incubationController = new QQuickWindowIncubationController(this); + d->incubationController = new QQuickWindowIncubationController(d->windowManager); return d->incubationController; } diff --git a/src/quick/items/qquickwindow_p.h b/src/quick/items/qquickwindow_p.h index 2465629778..2dddd9ab68 100644 --- a/src/quick/items/qquickwindow_p.h +++ b/src/quick/items/qquickwindow_p.h @@ -209,6 +209,7 @@ public: uint persistentSceneGraph : 1; uint lastWheelEventAccepted : 1; + bool componentCompleted : 1; QOpenGLFramebufferObject *renderTarget; uint renderTargetId; diff --git a/src/quick/items/qquickwindowmodule.cpp b/src/quick/items/qquickwindowmodule.cpp index f826a53a29..b91edc2fd5 100644 --- a/src/quick/items/qquickwindowmodule.cpp +++ b/src/quick/items/qquickwindowmodule.cpp @@ -42,18 +42,40 @@ #include "qquickwindowmodule_p.h" #include "qquickscreen_p.h" #include <QtQuick/QQuickWindow> +#include <QtCore/QCoreApplication> +#include <QtQml/QQmlEngine> QT_BEGIN_NAMESPACE +class QQuickWindowQmlImpl : public QQuickWindow, public QQmlParserStatus +{ + Q_INTERFACES(QQmlParserStatus) + Q_OBJECT +protected: + void classBegin() { + //Give QQuickView behavior when created from QML with QQmlApplicationEngine + if (QCoreApplication::instance()->property("__qml_using_qqmlapplicationengine") == QVariant(true)) { + QQmlEngine* e = qmlEngine(this); + if (e && !e->incubationController()) + e->setIncubationController(incubationController()); + } + } + + void componentComplete() {} +}; + void QQuickWindowModule::defineModule() { const char uri[] = "QtQuick.Window"; qmlRegisterType<QQuickWindow>(uri, 2, 0, "Window"); qmlRegisterRevision<QWindow,1>(uri, 2, 1); - qmlRegisterType<QQuickWindow,1>(uri, 2, 1, "Window"); + qmlRegisterRevision<QQuickWindow,1>(uri, 2, 1);//Type moved to a subclass, but also has new members + qmlRegisterType<QQuickWindowQmlImpl>(uri, 2, 1, "Window"); qmlRegisterUncreatableType<QQuickScreen>(uri, 2, 0, "Screen", QStringLiteral("Screen can only be used via the attached property.")); } +#include "qquickwindowmodule.moc" + QT_END_NAMESPACE diff --git a/src/quick/scenegraph/qsgcontext.cpp b/src/quick/scenegraph/qsgcontext.cpp index c47250662b..6d327b8d80 100644 --- a/src/quick/scenegraph/qsgcontext.cpp +++ b/src/quick/scenegraph/qsgcontext.cpp @@ -47,7 +47,9 @@ #include <QtQuick/private/qsgdefaultimagenode_p.h> #include <QtQuick/private/qsgdefaultglyphnode_p.h> #include <QtQuick/private/qsgdistancefieldglyphnode_p.h> +#include <QtQuick/private/qsgdistancefieldglyphnode_p_p.h> #include <QtQuick/private/qsgshareddistancefieldglyphcache_p.h> +#include <QtQuick/QSGFlatColorMaterial> #include <QtQuick/private/qsgtexture_p.h> #include <QtQuick/private/qquickpixmapcache_p.h> @@ -261,9 +263,35 @@ void QSGContext::initialize(QOpenGLContext *context) Q_ASSERT(!d->gl); d->gl = context; + precompileMaterials(); + emit initialized(); } +#define QSG_PRECOMPILE_MATERIAL(name) { name m; prepareMaterial(&m); } + +/* + * Some glsl compilers take their time compiling materials, and + * the way the scene graph is being processed, these materials + * get compiled when they are first taken into use. This can + * easily lead to skipped frames. By precompiling the most + * common materials, we potentially add a few milliseconds to the + * start up, and reduce the chance of avoiding skipped frames + * later on. + */ +void QSGContext::precompileMaterials() +{ + if (qEnvironmentVariableIsEmpty("QSG_NO_MATERIAL_PRELOADING")) { + QSG_PRECOMPILE_MATERIAL(QSGVertexColorMaterial); + QSG_PRECOMPILE_MATERIAL(QSGFlatColorMaterial); + QSG_PRECOMPILE_MATERIAL(QSGOpaqueTextureMaterial); + QSG_PRECOMPILE_MATERIAL(QSGTextureMaterial); + QSG_PRECOMPILE_MATERIAL(SmoothTextureMaterial); + QSG_PRECOMPILE_MATERIAL(SmoothColorMaterial); + QSG_PRECOMPILE_MATERIAL(QSGDistanceFieldTextMaterial); + } +} + /*! Returns if the scene graph context is ready or not, meaning that it has a valid diff --git a/src/quick/scenegraph/qsgcontext_p.h b/src/quick/scenegraph/qsgcontext_p.h index b069c53dd3..bbc42674c6 100644 --- a/src/quick/scenegraph/qsgcontext_p.h +++ b/src/quick/scenegraph/qsgcontext_p.h @@ -90,6 +90,7 @@ public: bool isReady() const; + virtual void precompileMaterials(); QSGMaterialShader *prepareMaterial(QSGMaterial *material); virtual void renderNextFrame(QSGRenderer *renderer, GLuint fboId); diff --git a/src/quick/scenegraph/qsgrenderloop.cpp b/src/quick/scenegraph/qsgrenderloop.cpp index 3a608a911d..e099d94a53 100644 --- a/src/quick/scenegraph/qsgrenderloop.cpp +++ b/src/quick/scenegraph/qsgrenderloop.cpp @@ -82,7 +82,7 @@ QSGRenderLoop::~QSGRenderLoop() { } -class QSGGuiThreadRenderLoop : public QObject, public QSGRenderLoop +class QSGGuiThreadRenderLoop : public QSGRenderLoop { Q_OBJECT public: diff --git a/src/quick/scenegraph/qsgrenderloop_p.h b/src/quick/scenegraph/qsgrenderloop_p.h index b18e6f00ad..6ff9c4c5f9 100644 --- a/src/quick/scenegraph/qsgrenderloop_p.h +++ b/src/quick/scenegraph/qsgrenderloop_p.h @@ -51,8 +51,10 @@ class QQuickWindow; class QSGContext; class QAnimationDriver; -class Q_QUICK_PRIVATE_EXPORT QSGRenderLoop +class Q_QUICK_PRIVATE_EXPORT QSGRenderLoop : public QObject { + Q_OBJECT + public: virtual ~QSGRenderLoop(); @@ -77,6 +79,11 @@ public: static QSGRenderLoop *instance(); static void setInstance(QSGRenderLoop *instance); + virtual bool interleaveIncubation() const { return false; } + +signals: + void timeToIncubate(); + private: static QSGRenderLoop *s_instance; }; diff --git a/src/quick/scenegraph/qsgthreadedrenderloop.cpp b/src/quick/scenegraph/qsgthreadedrenderloop.cpp index bd69fd5464..bfd9a2fb20 100644 --- a/src/quick/scenegraph/qsgthreadedrenderloop.cpp +++ b/src/quick/scenegraph/qsgthreadedrenderloop.cpp @@ -574,6 +574,7 @@ void QSGRenderThread::syncAndRender() int waitTime = vsyncDelta - (int) waitTimer.elapsed(); if (waitTime > 0) msleep(waitTime); + emit wm->timeToIncubate(); return; } @@ -600,6 +601,7 @@ void QSGRenderThread::syncAndRender() d->fireFrameSwapped(); } RLDEBUG(" Render: - rendering done"); + emit wm->timeToIncubate(); #ifndef QSG_NO_RENDER_TIMING if (qsg_render_timing) @@ -723,7 +725,7 @@ QSGContext *QSGThreadedRenderLoop::sceneGraphContext() const return m_thread->sg; } -bool QSGThreadedRenderLoop::anyoneShowing() +bool QSGThreadedRenderLoop::anyoneShowing() const { for (int i=0; i<m_windows.size(); ++i) { QQuickWindow *c = m_windows.at(i).window; @@ -733,6 +735,11 @@ bool QSGThreadedRenderLoop::anyoneShowing() return false; } +bool QSGThreadedRenderLoop::interleaveIncubation() const +{ + return m_animation_driver->isRunning() && anyoneShowing(); +} + void QSGThreadedRenderLoop::animationStarted() { RLDEBUG("GUI: animationStarted()"); @@ -1011,7 +1018,6 @@ void QSGThreadedRenderLoop::polishAndSync() RLDEBUG("GUI: - animations advancing"); m_animation_driver->advance(); RLDEBUG("GUI: - animations done"); - // We need to trigger another sync to keep animations running... maybePostPolishRequest(); } else if (m_sync_triggered_update) { diff --git a/src/quick/scenegraph/qsgthreadedrenderloop_p.h b/src/quick/scenegraph/qsgthreadedrenderloop_p.h index aab0e8726f..6ff5cabf43 100644 --- a/src/quick/scenegraph/qsgthreadedrenderloop_p.h +++ b/src/quick/scenegraph/qsgthreadedrenderloop_p.h @@ -52,7 +52,7 @@ QT_BEGIN_NAMESPACE class QSGRenderThread; -class QSGThreadedRenderLoop : public QObject, public QSGRenderLoop +class QSGThreadedRenderLoop : public QSGRenderLoop { Q_OBJECT public: @@ -79,7 +79,7 @@ public: bool event(QEvent *); - void wakeup(); + bool interleaveIncubation() const; public slots: void animationStarted(); @@ -91,7 +91,7 @@ private: void releaseResources(QQuickWindow *window, bool inDestructor); bool checkAndResetForceUpdate(QQuickWindow *window); - bool anyoneShowing(); + bool anyoneShowing() const; void initialize(); void maybePostPolishRequest(); diff --git a/src/quick/scenegraph/qsgwindowsrenderloop.cpp b/src/quick/scenegraph/qsgwindowsrenderloop.cpp index ce43ccf531..8e97f65ea5 100644 --- a/src/quick/scenegraph/qsgwindowsrenderloop.cpp +++ b/src/quick/scenegraph/qsgwindowsrenderloop.cpp @@ -102,6 +102,11 @@ QSGWindowsRenderLoop::QSGWindowsRenderLoop() #endif } +bool QSGWindowsRenderLoop::interleaveIncubation() const +{ + return m_animationDriver->isRunning() && anyoneShowing(); +} + QSGWindowsRenderLoop::WindowData *QSGWindowsRenderLoop::windowData(QQuickWindow *window) { for (int i=0; i<m_windows.size(); ++i) { @@ -390,6 +395,8 @@ void QSGWindowsRenderLoop::render() // and thus another render pass, so to keep things running, // make sure there is another frame pending. maybePostUpdateTimer(); + + emit timeToIncubate(); } } diff --git a/src/quick/scenegraph/qsgwindowsrenderloop_p.h b/src/quick/scenegraph/qsgwindowsrenderloop_p.h index dc3a409cd5..218e18c3e2 100644 --- a/src/quick/scenegraph/qsgwindowsrenderloop_p.h +++ b/src/quick/scenegraph/qsgwindowsrenderloop_p.h @@ -51,7 +51,7 @@ QT_BEGIN_NAMESPACE -class QSGWindowsRenderLoop : public QObject, public QSGRenderLoop +class QSGWindowsRenderLoop : public QSGRenderLoop { Q_OBJECT public: @@ -80,6 +80,9 @@ public: void resize(QQuickWindow *, const QSize &) { } bool event(QEvent *event); + bool anyoneShowing() const; + + bool interleaveIncubation() const; public slots: void started(); @@ -93,7 +96,6 @@ private: void handleObscurity(); void maybePostUpdateTimer(); - bool anyoneShowing() const; WindowData *windowData(QQuickWindow *window); QList<WindowData> m_windows; diff --git a/tests/auto/qml/qqmlpropertymap/tst_qqmlpropertymap.cpp b/tests/auto/qml/qqmlpropertymap/tst_qqmlpropertymap.cpp index 327716f1b5..ca212d333b 100644 --- a/tests/auto/qml/qqmlpropertymap/tst_qqmlpropertymap.cpp +++ b/tests/auto/qml/qqmlpropertymap/tst_qqmlpropertymap.cpp @@ -66,6 +66,8 @@ private slots: void crashBug(); void QTBUG_17868(); void metaObjectAccessibility(); + void QTBUG_31226(); + void QTBUG_29836(); }; void tst_QQmlPropertyMap::insert() @@ -286,13 +288,17 @@ class MyEnhancedPropertyMap : public QQmlPropertyMap { Q_OBJECT public: - MyEnhancedPropertyMap() : QQmlPropertyMap(this, 0) {} + MyEnhancedPropertyMap() : QQmlPropertyMap(this, 0), m_testSlotCalled(false) {} + bool testSlotCalled() const { return m_testSlotCalled; } signals: void testSignal(); public slots: - void testSlot() {} + void testSlot() { m_testSlotCalled = true; } + +private: + bool m_testSlotCalled; }; void tst_QQmlPropertyMap::metaObjectAccessibility() @@ -312,6 +318,57 @@ void tst_QQmlPropertyMap::metaObjectAccessibility() QVERIFY2(messageHandler.messages().isEmpty(), qPrintable(messageHandler.messageString())); } +void tst_QQmlPropertyMap::QTBUG_31226() +{ + /* Instantiate a property map from QML, and verify that property changes + * made from C++ are visible from QML */ + QQmlEngine engine; + QQmlContext context(&engine); + qmlRegisterType<QQmlPropertyMap>("QTBUG_31226", 1, 0, "PropertyMap"); + QQmlComponent c(&engine); + c.setData("import QtQuick 2.0\nimport QTBUG_31226 1.0\n" + "Item {\n" + " property string myProp\n" + " PropertyMap { id: qmlPropertyMap; objectName: \"qmlPropertyMap\" }\n" + " Timer { interval: 5; running: true; onTriggered: { myProp = qmlPropertyMap.greeting; } }\n" + "}", + QUrl()); + QObject *obj = c.create(&context); + QVERIFY(obj); + + QQmlPropertyMap *qmlPropertyMap = obj->findChild<QQmlPropertyMap*>(QString("qmlPropertyMap")); + QVERIFY(qmlPropertyMap); + + qmlPropertyMap->insert("greeting", QString("Hello world!")); + QTRY_COMPARE(obj->property("myProp").toString(), QString("Hello world!")); + + delete obj; + +} + +void tst_QQmlPropertyMap::QTBUG_29836() +{ + MyEnhancedPropertyMap map; + QCOMPARE(map.testSlotCalled(), false); + + QQmlEngine engine; + QQmlContext context(&engine); + context.setContextProperty("enhancedMap", &map); + QQmlComponent c(&engine); + c.setData("import QtQuick 2.0\n" + "Item {\n" + " Timer { interval: 5; running: true; onTriggered: enhancedMap.testSlot() }\n" + "}", + QUrl()); + QObject *obj = c.create(&context); + QVERIFY(obj); + + QTRY_COMPARE(map.testSlotCalled(), true); + + delete obj; + +} + QTEST_MAIN(tst_QQmlPropertyMap) #include "tst_qqmlpropertymap.moc" diff --git a/tests/auto/quick/qquickanimatedimage/tst_qquickanimatedimage.cpp b/tests/auto/quick/qquickanimatedimage/tst_qquickanimatedimage.cpp index 73474afbd7..0377eaa71d 100644 --- a/tests/auto/quick/qquickanimatedimage/tst_qquickanimatedimage.cpp +++ b/tests/auto/quick/qquickanimatedimage/tst_qquickanimatedimage.cpp @@ -190,9 +190,6 @@ void tst_qquickanimatedimage::mirror_running() QImage frame0_expected = frame0.transformed(transform); QImage frame1_expected = frame1.transformed(transform); -#ifdef Q_OS_MAC - QSKIP("QTBUG-31370 - sometimes fails on Mac"); -#endif QCOMPARE(frame0_flipped, frame0_expected); QCOMPARE(frame1_flipped, frame1_expected); @@ -204,29 +201,28 @@ void tst_qquickanimatedimage::mirror_notRunning() QFETCH(QUrl, fileUrl); QQuickView window; + window.setSource(fileUrl); window.show(); + QTRY_VERIFY(window.isExposed()); - window.setSource(fileUrl); QQuickAnimatedImage *anim = qobject_cast<QQuickAnimatedImage *>(window.rootObject()); QVERIFY(anim); int width = anim->property("width").toInt(); - QPixmap screenshot = QPixmap::fromImage(window.grabWindow()); + QImage screenshot = window.grabWindow(); QTransform transform; transform.translate(width, 0).scale(-1, 1.0); - QPixmap expected = screenshot.transformed(transform); + QImage expected = screenshot.transformed(transform); int frame = anim->currentFrame(); bool playing = anim->isPlaying(); bool paused = anim->isPlaying(); anim->setProperty("mirror", true); - screenshot = QPixmap::fromImage(window.grabWindow()); + screenshot = window.grabWindow(); -#ifdef Q_OS_MAC - QSKIP("QTBUG-31370 - sometimes fails on Mac"); -#endif + screenshot.save("screen.png"); QCOMPARE(screenshot, expected); // mirroring should not change the current frame or playing status diff --git a/tests/auto/quick/touchmouse/tst_touchmouse.cpp b/tests/auto/quick/touchmouse/tst_touchmouse.cpp index 15a4f0cc27..4779942406 100644 --- a/tests/auto/quick/touchmouse/tst_touchmouse.cpp +++ b/tests/auto/quick/touchmouse/tst_touchmouse.cpp @@ -195,8 +195,9 @@ void tst_TouchMouse::simpleTouchEvent() window->setSource(testFileUrl("singleitem.qml")); window->show(); - window->requestActivate(); QVERIFY(QTest::qWaitForWindowExposed(window)); + window->requestActivate(); + QVERIFY(QTest::qWaitForWindowActive(window)); QVERIFY(window->rootObject() != 0); EventItem *eventItem1 = window->rootObject()->findChild<EventItem*>("eventItem1"); @@ -344,7 +345,9 @@ void tst_TouchMouse::mouse() window->setSource(testFileUrl("twoitems.qml")); window->show(); + QVERIFY(QTest::qWaitForWindowExposed(window)); window->requestActivate(); + QVERIFY(QTest::qWaitForWindowActive(window)); QVERIFY(window->rootObject() != 0); EventItem *eventItem1 = window->rootObject()->findChild<EventItem*>("eventItem1"); @@ -376,7 +379,9 @@ void tst_TouchMouse::touchOverMouse() window->setSource(testFileUrl("twoitems.qml")); window->show(); + QVERIFY(QTest::qWaitForWindowExposed(window)); window->requestActivate(); + QVERIFY(QTest::qWaitForWindowActive(window)); QVERIFY(window->rootObject() != 0); EventItem *eventItem1 = window->rootObject()->findChild<EventItem*>("eventItem1"); @@ -417,7 +422,9 @@ void tst_TouchMouse::mouseOverTouch() window->setSource(testFileUrl("twoitems.qml")); window->show(); + QVERIFY(QTest::qWaitForWindowExposed(window)); window->requestActivate(); + QVERIFY(QTest::qWaitForWindowActive(window)); QVERIFY(window->rootObject() != 0); EventItem *eventItem1 = window->rootObject()->findChild<EventItem*>("eventItem1"); @@ -461,7 +468,9 @@ void tst_TouchMouse::buttonOnFlickable() window->setSource(testFileUrl("buttononflickable.qml")); window->show(); + QVERIFY(QTest::qWaitForWindowExposed(window)); window->requestActivate(); + QVERIFY(QTest::qWaitForWindowActive(window)); QVERIFY(window->rootObject() != 0); QQuickFlickable *flickable = window->rootObject()->findChild<QQuickFlickable*>("flickable"); @@ -569,7 +578,9 @@ void tst_TouchMouse::buttonOnTouch() QQuickView *window = createView(); window->setSource(testFileUrl("buttonontouch.qml")); window->show(); + QVERIFY(QTest::qWaitForWindowExposed(window)); window->requestActivate(); + QVERIFY(QTest::qWaitForWindowActive(window)); QVERIFY(window->rootObject() != 0); QQuickPinchArea *pinchArea = window->rootObject()->findChild<QQuickPinchArea*>("pincharea"); @@ -691,7 +702,9 @@ void tst_TouchMouse::pinchOnFlickable() QQuickView *window = createView(); window->setSource(testFileUrl("pinchonflickable.qml")); window->show(); + QVERIFY(QTest::qWaitForWindowExposed(window)); window->requestActivate(); + QVERIFY(QTest::qWaitForWindowActive(window)); QVERIFY(window->rootObject() != 0); QQuickPinchArea *pinchArea = window->rootObject()->findChild<QQuickPinchArea*>("pincharea"); @@ -758,7 +771,9 @@ void tst_TouchMouse::flickableOnPinch() QQuickView *window = createView(); window->setSource(testFileUrl("flickableonpinch.qml")); window->show(); + QVERIFY(QTest::qWaitForWindowExposed(window)); window->requestActivate(); + QVERIFY(QTest::qWaitForWindowActive(window)); QVERIFY(window->rootObject() != 0); QQuickPinchArea *pinchArea = window->rootObject()->findChild<QQuickPinchArea*>("pincharea"); @@ -935,8 +950,9 @@ void tst_TouchMouse::tapOnDismissiveTopMouseAreaClicksBottomOne() window->setSource(testFileUrl("twoMouseAreas.qml")); window->show(); - window->requestActivate(); QVERIFY(QTest::qWaitForWindowExposed(window)); + window->requestActivate(); + QVERIFY(QTest::qWaitForWindowActive(window)); QVERIFY(window->rootObject() != 0); QQuickMouseArea *bottomMouseArea = diff --git a/tools/qmlscene/main.cpp b/tools/qmlscene/main.cpp index d572487218..8a48445d63 100644 --- a/tools/qmlscene/main.cpp +++ b/tools/qmlscene/main.cpp @@ -483,7 +483,9 @@ int main(int argc, char ** argv) QObject *topLevel = component->create(); QQuickWindow *window = qobject_cast<QQuickWindow *>(topLevel); QQuickView* qxView = 0; - if (!window) { + if (window) { + engine.setIncubationController(window->incubationController()); + } else { QQuickItem *contentItem = qobject_cast<QQuickItem *>(topLevel); if (contentItem) { qxView = new QQuickView(&engine, NULL); |