diff options
author | Liang Qi <liang.qi@qt.io> | 2017-12-20 08:32:22 +0100 |
---|---|---|
committer | Liang Qi <liang.qi@qt.io> | 2017-12-20 08:50:58 +0100 |
commit | 9a38fdcf8f9b734808bb54422e306872f3bfa944 (patch) | |
tree | 20fd361db6c505d99a40ab7a695511b97dcdcbd3 /src/qml | |
parent | 1db9405128972d5ba77e33181bee40356f718cea (diff) | |
parent | 4fff2bb14e55484eacec0a1b49a2b02958f75eca (diff) |
Merge remote-tracking branch 'origin/5.10' into dev
Conflicts:
tests/auto/quick/pointerhandlers/flickableinterop/data/FlashAnimation.qml
tests/auto/quick/pointerhandlers/flickableinterop/data/Slider.qml
tests/auto/quick/pointerhandlers/flickableinterop/data/TapHandlerButton.qml
tests/auto/quick/pointerhandlers/flickableinterop/data/flickableWithHandlers.qml
tests/auto/quick/pointerhandlers/multipointtoucharea_interop/data/pinchDragMPTA.qml
tests/auto/quick/pointerhandlers/qquickdraghandler/data/DragAnywhereSlider.qml
tests/auto/quick/pointerhandlers/qquickdraghandler/data/FlashAnimation.qml
tests/auto/quick/pointerhandlers/qquickdraghandler/data/Slider.qml
tests/auto/quick/pointerhandlers/qquickdraghandler/data/draggables.qml
tests/auto/quick/pointerhandlers/qquickdraghandler/data/multipleSliders.qml
tests/auto/quick/pointerhandlers/qquicktaphandler/data/Button.qml
tests/auto/quick/pointerhandlers/qquicktaphandler/data/FlashAnimation.qml
tests/auto/quick/pointerhandlers/qquicktaphandler/data/buttons.qml
tests/manual/pointer/content/FakeFlickable.qml
tests/manual/pointer/content/FlashAnimation.qml
tests/manual/pointer/content/MomentumAnimation.qml
tests/manual/pointer/content/MouseAreaButton.qml
tests/manual/pointer/content/MouseAreaSlider.qml
tests/manual/pointer/content/MptaButton.qml
tests/manual/pointer/content/MultiButton.qml
tests/manual/pointer/content/ScrollBar.qml
tests/manual/pointer/content/Slider.qml
tests/manual/pointer/content/TapHandlerButton.qml
tests/manual/pointer/fakeFlickable.qml
tests/manual/pointer/flickableWithHandlers.qml
tests/manual/pointer/flingAnimation.qml
tests/manual/pointer/joystick.qml
tests/manual/pointer/main.cpp
tests/manual/pointer/main.qml
tests/manual/pointer/map.qml
tests/manual/pointer/map2.qml
tests/manual/pointer/mixer.qml
tests/manual/pointer/multibuttons.qml
tests/manual/pointer/photosurface.qml
tests/manual/pointer/pinchDragFlingMPTA.qml
tests/manual/pointer/pinchHandler.qml
tests/manual/pointer/singlePointHandlerProperties.qml
tests/manual/pointer/tapHandler.qml
tests/manual/pointer/tapWithModifiers.qml
tests/manual/shapestest/main.cpp
Change-Id: I4f233a521305fab1ebfecbac801da192434ed524
Diffstat (limited to 'src/qml')
-rw-r--r-- | src/qml/debugger/qqmlprofiler_p.h | 11 | ||||
-rw-r--r-- | src/qml/doc/qtqml.qdocconf | 2 | ||||
-rw-r--r-- | src/qml/doc/src/cppintegration/interactqmlfromcpp.qdoc | 12 | ||||
-rw-r--r-- | src/qml/doc/src/cppintegration/topic.qdoc | 2 | ||||
-rw-r--r-- | src/qml/doc/src/cppintegration/warning.qdocinc | 6 | ||||
-rw-r--r-- | src/qml/qml/qqmlengine.cpp | 2 | ||||
-rw-r--r-- | src/qml/qml/qqmlglobal_p.h | 16 | ||||
-rw-r--r-- | src/qml/qml/qqmlimport.cpp | 12 | ||||
-rw-r--r-- | src/qml/qml/qqmlmetatype.cpp | 4 | ||||
-rw-r--r-- | src/qml/qml/qqmltypeloader.cpp | 20 | ||||
-rw-r--r-- | src/qml/qml/qqmltypeloader_p.h | 1 | ||||
-rw-r--r-- | src/qml/types/qqmldelegatemodel.cpp | 2 |
12 files changed, 57 insertions, 33 deletions
diff --git a/src/qml/debugger/qqmlprofiler_p.h b/src/qml/debugger/qqmlprofiler_p.h index f17b1a7528..ef38887303 100644 --- a/src/qml/debugger/qqmlprofiler_p.h +++ b/src/qml/debugger/qqmlprofiler_p.h @@ -290,14 +290,19 @@ public: // Add 1 to the ID, to make it different from the IDs the V4 profiler produces. The +1 makes // the pointer point into the middle of the QV4::Function. Thus it still points to valid // memory but we cannot accidentally create a duplicate key from another object. - quintptr locationId(id(function) + 1); + // If there is no function, use a static but valid address: The profiler itself. + quintptr locationId = function ? id(function) + 1 : id(this); m_data.append(QQmlProfilerData(m_timer.nsecsElapsed(), (1 << RangeStart | 1 << RangeLocation), Binding, locationId)); RefLocation &location = m_locations[locationId]; - if (!location.isValid()) - location = RefLocation(function); + if (!location.isValid()) { + if (function) + location = RefLocation(function); + else // Make it valid without actually providing a location + location.locationType = Binding; + } } // Have toByteArrays() construct another RangeData event from the same QString later. diff --git a/src/qml/doc/qtqml.qdocconf b/src/qml/doc/qtqml.qdocconf index 74b61fd6e1..6161760471 100644 --- a/src/qml/doc/qtqml.qdocconf +++ b/src/qml/doc/qtqml.qdocconf @@ -53,6 +53,8 @@ manifestmeta.thumbnail.names += "QtQml/Chapter 4*" \ "QtQml/Chapter 6*" \ "QtQml/C++ Extensions: *" +manifestmeta.highlighted.names = "QtQml/Writing QML Extensions with C++" + navigation.landingpage = "Qt QML" navigation.cppclassespage = "Qt QML C++ Classes" navigation.qmltypespage = "Qt QML QML Types" diff --git a/src/qml/doc/src/cppintegration/interactqmlfromcpp.qdoc b/src/qml/doc/src/cppintegration/interactqmlfromcpp.qdoc index 4dc32e3588..7c2ff703c6 100644 --- a/src/qml/doc/src/cppintegration/interactqmlfromcpp.qdoc +++ b/src/qml/doc/src/cppintegration/interactqmlfromcpp.qdoc @@ -114,17 +114,7 @@ multiple children with the same \c objectName. In this case, QObject::findChildren() can be used to find all children with a matching \c objectName. -\warning While it is possible to use C++ to access and manipulate QML objects -deep into the object tree, we recommend that you do not take this approach -outside of application testing and prototyping. One strength of QML and C++ -integration is the ability to implement the QML user interface separately -from the C++ logic and dataset backend, and this strategy breaks if the C++ -side reaches deep into the QML components to manipulate them directly. This -would make it difficult to, for example, swap a QML view component for -another view, if the new component was missing a required \c objectName. It -is better for the C++ implementation to know as little as possible about the -QML user interface implementation and the composition of the QML object tree. - +\include warning.qdocinc \section1 Accessing Members of a QML Object Type from C++ diff --git a/src/qml/doc/src/cppintegration/topic.qdoc b/src/qml/doc/src/cppintegration/topic.qdoc index da06c195dc..6b6e308edf 100644 --- a/src/qml/doc/src/cppintegration/topic.qdoc +++ b/src/qml/doc/src/cppintegration/topic.qdoc @@ -190,6 +190,8 @@ invoke their methods and receive their signal notifications. This is possible du all QML object types are implemented using QObject-derived classes, enabling the QML engine to dynamically load and introspect objects through the Qt meta object system. +\include warning.qdocinc + For more information on accessing QML objects from C++, see the documentation on \l{qtqml-cppintegration-interactqmlfromcpp.html}{Interacting with QML Objects from C++}. diff --git a/src/qml/doc/src/cppintegration/warning.qdocinc b/src/qml/doc/src/cppintegration/warning.qdocinc new file mode 100644 index 0000000000..a5da22b2a7 --- /dev/null +++ b/src/qml/doc/src/cppintegration/warning.qdocinc @@ -0,0 +1,6 @@ +\warning Although it is possible to access QML objects from C++ and manipulate +them, it is not the recommended approach, except for testing and prototyping +purposes. One of the strengths of QML and C++ integration is the ability to +implement UIs in QML separate from the C++ logic and dataset backend, and this +fails if the C++ side starts manipulating QML directly. Such an approach also +makes changing the QML UI difficult without affecting its C++ counterpart. diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp index 9ef47b2c2e..61345f05a8 100644 --- a/src/qml/qml/qqmlengine.cpp +++ b/src/qml/qml/qqmlengine.cpp @@ -897,6 +897,8 @@ void QQmlData::setQueuedForDeletion(QObject *object) if (ddata->ownContext) { Q_ASSERT(ddata->ownContext == ddata->context); ddata->context->emitDestruction(); + if (ddata->ownContext->contextObject == object) + ddata->ownContext->contextObject = nullptr; ddata->ownContext = 0; ddata->context = 0; } diff --git a/src/qml/qml/qqmlglobal_p.h b/src/qml/qml/qqmlglobal_p.h index a6c113f5a7..5c46da0ea4 100644 --- a/src/qml/qml/qqmlglobal_p.h +++ b/src/qml/qml/qqmlglobal_p.h @@ -193,16 +193,6 @@ do { \ return QObjectPrivate::get(sender)->isSignalConnected(signalIdx); \ } while (0) -struct QQmlGraphics_DerivedObject : public QObject -{ - void setParent_noEvent(QObject *parent) { - bool sce = d_ptr->sendChildEvents; - d_ptr->sendChildEvents = false; - setParent(parent); - d_ptr->sendChildEvents = sce; - } -}; - /*! Returns true if the case of \a fileName is equivalent to the file case of \a fileName on disk, and false otherwise. @@ -230,7 +220,11 @@ bool QQml_isFileCaseCorrect(const QString &fileName, int length = -1); */ inline void QQml_setParent_noEvent(QObject *object, QObject *parent) { - static_cast<QQmlGraphics_DerivedObject *>(object)->setParent_noEvent(parent); + QObjectPrivate *d_ptr = QObjectPrivate::get(object); + bool sce = d_ptr->sendChildEvents; + d_ptr->sendChildEvents = false; + object->setParent(parent); + d_ptr->sendChildEvents = sce; } class Q_QML_PRIVATE_EXPORT QQmlValueTypeProvider diff --git a/src/qml/qml/qqmlimport.cpp b/src/qml/qml/qqmlimport.cpp index a85166da65..a7cafa1a93 100644 --- a/src/qml/qml/qqmlimport.cpp +++ b/src/qml/qml/qqmlimport.cpp @@ -1231,10 +1231,12 @@ QString QQmlImportsPrivate::resolvedUri(const QString &dir_arg, QQmlImportDataba stableRelativePath.replace(Backslash, Slash); // remove optional versioning in dot notation from uri - int lastSlash = stableRelativePath.lastIndexOf(Slash); - if (lastSlash >= 0) { - int versionDot = stableRelativePath.indexOf(Dot, lastSlash); - if (versionDot >= 0) + int versionDot = stableRelativePath.lastIndexOf(Dot); + if (versionDot >= 0) { + int nextSlash = stableRelativePath.indexOf(Slash, versionDot); + if (nextSlash >= 0) + stableRelativePath.remove(versionDot, nextSlash - versionDot); + else stableRelativePath = stableRelativePath.left(versionDot); } @@ -1539,7 +1541,7 @@ bool QQmlImportsPrivate::addFileImport(const QString& uri, const QString &prefix if (isImplicitImport) { for (QList<QQmlImportInstance *>::const_iterator it = nameSpace->imports.constBegin(); it != nameSpace->imports.constEnd(); ++it) { - if ((*it)->uri == importUri) { + if ((*it)->url == url) { (*it)->implicitlyImported = true; return true; } diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp index 5836c85666..e696dc0362 100644 --- a/src/qml/qml/qqmlmetatype.cpp +++ b/src/qml/qml/qqmlmetatype.cpp @@ -272,8 +272,10 @@ void QQmlType::SingletonInstanceInfo::init(QQmlEngine *e) QQmlData::ensurePropertyCache(e, o); } else if (!url.isEmpty() && !qobjectApi(e)) { QQmlComponent component(e, url, QQmlComponent::PreferSynchronous); - QObject *o = component.create(); + QObject *o = component.beginCreate(e->rootContext()); setQObjectApi(e, o); + if (o) + component.completeCreate(); } } diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp index 55e05afdaa..2b895994d2 100644 --- a/src/qml/qml/qqmltypeloader.cpp +++ b/src/qml/qml/qqmltypeloader.cpp @@ -317,7 +317,8 @@ Returns true if the status is WaitingForDependencies. */ bool QQmlDataBlob::isWaiting() const { - return status() == WaitingForDependencies; + return status() == WaitingForDependencies || + status() == ResolvingDependencies; } /*! @@ -609,6 +610,7 @@ The default implementation does nothing. */ void QQmlDataBlob::allDependenciesDone() { + m_data.setStatus(QQmlDataBlob::ResolvingDependencies); } /*! @@ -2408,7 +2410,15 @@ void QQmlTypeData::dataReceived(const SourceCodeData &data) void QQmlTypeData::initializeFromCachedUnit(const QQmlPrivate::CachedQmlUnit *unit) { m_document.reset(new QmlIR::Document(isDebugging())); - unit->loadIR(m_document.data(), unit); + if (unit->loadIR) { + // old code path for older generated code + unit->loadIR(m_document.data(), unit); + } else { + // new code path + QmlIR::IRLoader loader(unit->qmlData, m_document.data()); + loader.load(); + m_document->javaScriptCompilationUnit.adopt(unit->createCompilationUnit()); + } continueLoadFromIR(); } @@ -2500,6 +2510,8 @@ void QQmlTypeData::continueLoadFromIR() void QQmlTypeData::allDependenciesDone() { + QQmlTypeLoader::Blob::allDependenciesDone(); + if (!m_typesResolved) { // Check that all imports were resolved QList<QQmlError> errors; @@ -2619,6 +2631,10 @@ void QQmlTypeData::resolveTypes() if (ref.type.isCompositeSingleton()) { ref.typeData = typeLoader()->getType(ref.type.sourceUrl()); + if (ref.typeData->status() == QQmlDataBlob::ResolvingDependencies) { + // TODO: give an error message? If so, we should record and show the path of the cycle. + continue; + } addDependency(ref.typeData); ref.prefix = csRef.prefix; diff --git a/src/qml/qml/qqmltypeloader_p.h b/src/qml/qml/qqmltypeloader_p.h index 94552cd5a0..0ec9f9240e 100644 --- a/src/qml/qml/qqmltypeloader_p.h +++ b/src/qml/qml/qqmltypeloader_p.h @@ -98,6 +98,7 @@ public: Null, // Prior to QQmlTypeLoader::load() Loading, // Prior to data being received and dataReceived() being called WaitingForDependencies, // While there are outstanding addDependency()s + ResolvingDependencies, // While resolving outstanding dependencies, to detect cycles Complete, // Finished Error // Error }; diff --git a/src/qml/types/qqmldelegatemodel.cpp b/src/qml/types/qqmldelegatemodel.cpp index 967f89971d..2a1b11661e 100644 --- a/src/qml/types/qqmldelegatemodel.cpp +++ b/src/qml/types/qqmldelegatemodel.cpp @@ -1953,6 +1953,8 @@ void QQmlDelegateModelItem::destroyObject() Q_ASSERT(data); if (data->ownContext) { data->ownContext->clearContext(); + if (data->ownContext->contextObject == object) + data->ownContext->contextObject = nullptr; data->ownContext = 0; data->context = 0; } |