diff options
author | Ulf Hermann <ulf.hermann@theqtcompany.com> | 2015-08-18 10:29:10 +0200 |
---|---|---|
committer | Ulf Hermann <ulf.hermann@theqtcompany.com> | 2015-08-18 10:29:47 +0200 |
commit | eb30e3d7ee81c48cea720e7ecd2ed45647bc70ee (patch) | |
tree | 810e8ad0642434eeb4043c3a06c82217314300e1 /src | |
parent | 9c9fca5e27bd91da1ea07bebd7569049493c5ccf (diff) | |
parent | 521ace713d8e5230d47f3da8cd941699ca085af2 (diff) |
Merge remote-tracking branch 'origin/5.5' into 5.6
Conflicts:
src/qml/debugger/qv4debugservice.cpp
src/qml/jsruntime/qv4value_inl_p.h
src/qml/jsruntime/qv4value_p.h
src/qml/memory/qv4mm.cpp
src/qml/memory/qv4mm_p.h
src/qml/qml/qqmlnotifier_p.h
src/qml/qml/qqmlproperty.cpp
src/quick/items/qquickflickable.cpp
src/quick/items/qquicktextedit.cpp
tests/auto/quick/qquickwindow/BLACKLIST
The extra changes in qqmlbinding.cpp are ported from changes to
qqmlproperty.cpp that occurred in parallel with writeBinding() being
moved to qqmlbinding.cpp.
Change-Id: I16d1920abf448c29a01822256f52153651a56356
Diffstat (limited to 'src')
84 files changed, 568 insertions, 380 deletions
diff --git a/src/particles/qquickimageparticle.cpp b/src/particles/qquickimageparticle.cpp index a17949130f..d78a350306 100644 --- a/src/particles/qquickimageparticle.cpp +++ b/src/particles/qquickimageparticle.cpp @@ -1273,7 +1273,7 @@ void QQuickImageParticle::finishBuildParticleNodes(QSGNode** node) #endif #ifdef Q_OS_MAC - // Mac OS X 10.8.3 introduced a bug in the AMD drivers, for at least the 2011 macbook pros, + // OS X 10.8.3 introduced a bug in the AMD drivers, for at least the 2011 macbook pros, // causing point sprites who read gl_PointCoord in the frag shader to come out as // green-red blobs. if (perfLevel < Deformable && strstr((char *) glGetString(GL_VENDOR), "ATI")) { diff --git a/src/qml/animations/qabstractanimationjob.cpp b/src/qml/animations/qabstractanimationjob.cpp index 7fcf383bcb..d301c43822 100644 --- a/src/qml/animations/qabstractanimationjob.cpp +++ b/src/qml/animations/qabstractanimationjob.cpp @@ -652,7 +652,7 @@ void QAbstractAnimationJob::removeAnimationChangeListener(QAnimationJobChangeLis void QAbstractAnimationJob::debugAnimation(QDebug d) const { - d << "AbstractAnimationJob(" << hex << (void *) this << dec << ") state:" + d << "AbstractAnimationJob(" << hex << (const void *) this << dec << ") state:" << m_state << "duration:" << duration(); } diff --git a/src/qml/animations/qcontinuinganimationgroupjob.cpp b/src/qml/animations/qcontinuinganimationgroupjob.cpp index c77448f153..88005baf12 100644 --- a/src/qml/animations/qcontinuinganimationgroupjob.cpp +++ b/src/qml/animations/qcontinuinganimationgroupjob.cpp @@ -115,7 +115,7 @@ void QContinuingAnimationGroupJob::uncontrolledAnimationFinished(QAbstractAnimat void QContinuingAnimationGroupJob::debugAnimation(QDebug d) const { - d << "ContinuingAnimationGroupJob(" << hex << (void *) this << dec << ")"; + d << "ContinuingAnimationGroupJob(" << hex << (const void *) this << dec << ")"; debugChildren(d); } diff --git a/src/qml/animations/qparallelanimationgroupjob.cpp b/src/qml/animations/qparallelanimationgroupjob.cpp index 0153794d6f..fe56f2b1e8 100644 --- a/src/qml/animations/qparallelanimationgroupjob.cpp +++ b/src/qml/animations/qparallelanimationgroupjob.cpp @@ -233,7 +233,7 @@ void QParallelAnimationGroupJob::uncontrolledAnimationFinished(QAbstractAnimatio void QParallelAnimationGroupJob::debugAnimation(QDebug d) const { - d << "ParallelAnimationGroupJob(" << hex << (void *) this << dec << ")"; + d << "ParallelAnimationGroupJob(" << hex << (const void *) this << dec << ")"; debugChildren(d); } diff --git a/src/qml/animations/qpauseanimationjob.cpp b/src/qml/animations/qpauseanimationjob.cpp index 8e35c58999..0e95645f41 100644 --- a/src/qml/animations/qpauseanimationjob.cpp +++ b/src/qml/animations/qpauseanimationjob.cpp @@ -62,7 +62,7 @@ void QPauseAnimationJob::updateCurrentTime(int) void QPauseAnimationJob::debugAnimation(QDebug d) const { - d << "PauseAnimationJob(" << hex << (void *) this << dec << ")" << "duration:" << m_duration; + d << "PauseAnimationJob(" << hex << (const void *) this << dec << ")" << "duration:" << m_duration; } QT_END_NAMESPACE diff --git a/src/qml/animations/qsequentialanimationgroupjob.cpp b/src/qml/animations/qsequentialanimationgroupjob.cpp index 5060b7f6cd..b92caf3bc4 100644 --- a/src/qml/animations/qsequentialanimationgroupjob.cpp +++ b/src/qml/animations/qsequentialanimationgroupjob.cpp @@ -411,7 +411,7 @@ void QSequentialAnimationGroupJob::animationRemoved(QAbstractAnimationJob *anim, void QSequentialAnimationGroupJob::debugAnimation(QDebug d) const { - d << "SequentialAnimationGroupJob(" << hex << (void *) this << dec << ")" << "currentAnimation:" << (void *)m_currentAnimation; + d << "SequentialAnimationGroupJob(" << hex << (const void *) this << dec << ")" << "currentAnimation:" << (void *)m_currentAnimation; debugChildren(d); } diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp index 911be238b9..307f945d20 100644 --- a/src/qml/compiler/qqmltypecompiler.cpp +++ b/src/qml/compiler/qqmltypecompiler.cpp @@ -836,7 +836,7 @@ bool QQmlPropertyCacheCreator::createMetaObject(int objectIndex, const QmlIR::Ob propertyFlags |= QQmlPropertyData::IsQList; } - if ((!p->flags & QV4::CompiledData::Property::IsReadOnly) && p->type != QV4::CompiledData::Property::CustomList) + if (!(p->flags & QV4::CompiledData::Property::IsReadOnly) && p->type != QV4::CompiledData::Property::CustomList) propertyFlags |= QQmlPropertyData::IsWritable; @@ -860,7 +860,7 @@ bool QQmlPropertyCacheCreator::createMetaObject(int objectIndex, const QmlIR::Ob continue; quint32 propertyFlags = QQmlPropertyData::IsVarProperty; - if (!p->flags & QV4::CompiledData::Property::IsReadOnly) + if (!(p->flags & QV4::CompiledData::Property::IsReadOnly)) propertyFlags |= QQmlPropertyData::IsWritable; VMD *vmd = (QQmlVMEMetaData *)dynamicData.data(); diff --git a/src/qml/compiler/qv4ssa.cpp b/src/qml/compiler/qv4ssa.cpp index 62e661c98a..c150666a11 100644 --- a/src/qml/compiler/qv4ssa.cpp +++ b/src/qml/compiler/qv4ssa.cpp @@ -530,7 +530,7 @@ class DominatorTree const int bbCount = function->basicBlockCount(); d->vertex = std::vector<int>(bbCount, InvalidBasicBlockIndex); d->parent = std::vector<int>(bbCount, InvalidBasicBlockIndex); - d->dfnum = std::vector<int>(bbCount, 0); + d->dfnum = std::vector<int>(size_t(bbCount), 0); d->semi = std::vector<BasicBlockIndex>(bbCount, InvalidBasicBlockIndex); d->ancestor = std::vector<BasicBlockIndex>(bbCount, InvalidBasicBlockIndex); idom = std::vector<BasicBlockIndex>(bbCount, InvalidBasicBlockIndex); @@ -873,7 +873,7 @@ private: // - set the current node's depth to that of immediate dominator + 1 std::vector<int> calculateNodeDepths() const { - std::vector<int> nodeDepths(function->basicBlockCount(), -1); + std::vector<int> nodeDepths(size_t(function->basicBlockCount()), -1); nodeDepths[0] = 0; foreach (BasicBlock *bb, function->basicBlocks()) { if (bb->isRemoved()) diff --git a/src/qml/doc/qtqml.qdocconf b/src/qml/doc/qtqml.qdocconf index 5729a60ea3..74b61fd6e1 100644 --- a/src/qml/doc/qtqml.qdocconf +++ b/src/qml/doc/qtqml.qdocconf @@ -23,7 +23,7 @@ qhp.QtQml.subprojects.classes.indexTitle = Qt QML C++ Classes qhp.QtQml.subprojects.classes.selectors = class fake:headerfile qhp.QtQml.subprojects.classes.sortPages = true qhp.QtQml.subprojects.examples.title = Examples -qhp.QtQml.subprojects.examples.indexTitle = Qt Quick Examples and Tutorials +qhp.QtQml.subprojects.examples.indexTitle = Qt QML Examples qhp.QtQml.subprojects.examples.selectors = fake:example qhp.QtQml.subprojects.qmltypes.title = QML Types qhp.QtQml.subprojects.qmltypes.indexTitle = Qt QML QML Types @@ -50,7 +50,8 @@ imagedirs += images # Add a thumbnail for examples that do not have images manifestmeta.thumbnail.names += "QtQml/Chapter 4*" \ - "QtQml/Chapter 6*" + "QtQml/Chapter 6*" \ + "QtQml/C++ Extensions: *" navigation.landingpage = "Qt QML" navigation.cppclassespage = "Qt QML C++ Classes" diff --git a/src/qml/doc/src/examples.qdoc b/src/qml/doc/src/examples.qdoc new file mode 100644 index 0000000000..f3550ae199 --- /dev/null +++ b/src/qml/doc/src/examples.qdoc @@ -0,0 +1,35 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Free Documentation License Usage +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. Please review the following information to ensure +** the GNU Free Documentation License version 1.3 requirements +** will be met: http://www.gnu.org/copyleft/fdl.html. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! +\group qmlextendingexamples +\title Qt QML Examples +\brief List of Qt QML examples for reference. + +The list of examples demonstrating how to extend C++ to QML or the other way +around. +*/ diff --git a/src/qml/doc/src/qmlfunctions.qdoc b/src/qml/doc/src/qmlfunctions.qdoc index 25bb0d6068..4203cca8b3 100644 --- a/src/qml/doc/src/qmlfunctions.qdoc +++ b/src/qml/doc/src/qmlfunctions.qdoc @@ -470,8 +470,8 @@ as any other item). Usage: - // First, define your QML singleton type which provides the functionality. \qml + // First, define your QML singleton type which provides the functionality. pragma Singleton import QtQuick 2.0 Item { diff --git a/src/qml/doc/src/qmllanguageref/modules/cppplugins.qdoc b/src/qml/doc/src/qmllanguageref/modules/cppplugins.qdoc index 79bd3df9d9..a2397b6cfb 100644 --- a/src/qml/doc/src/qmllanguageref/modules/cppplugins.qdoc +++ b/src/qml/doc/src/qmllanguageref/modules/cppplugins.qdoc @@ -32,96 +32,13 @@ \section1 Creating a Plugin - The \l{QQmlEngine}{QML engine} load C++ plugins for QML. + The \l{QQmlEngine}{QML engine} loads C++ plugins for QML. Such plugins are usually provided in a QML extension module, and can provide types for use by clients in QML documents which import the module. A module requires at least one type registered in order to be considered valid. - QQmlExtensionPlugin is a plugin interface that makes it possible to - create QML extensions that can be loaded dynamically into QML applications. - These extensions allow custom QML types to be made available to the - QML engine. - - To write a QML extension plugin: - \list 1 - \li Subclass QQmlExtensionPlugin - \list - \li Use the Q_PLUGIN_METADATA() macro to register the plugin with - the Qt meta object system - \li Override the \l{QQmlExtensionPlugin::}{registerTypes()} method - and call qmlRegisterType() to register the types to be exported - by the plugin - \endlist - \li Write a project file for the plugin - \li Create a \l{Module Definition qmldir Files}{qmldir file} to - describe the plugin - \endlist - - QML extension plugins are for either application-specific or library-like - plugins. Library plugins should limit themselves to registering types, as - any manipulation of the engine's root context may cause conflicts or other - issues in the library user's code. - -\section1 Plugin Example - - Suppose there is a new \c TimeModel C++ class that should be made available - as a new QML type. It provides the current time through \c hour and \c minute - properties. - - \snippet qmlextensionplugins/plugin.cpp 0 - \dots - - To make this type available, we create a plugin class named \c QExampleQmlPlugin - which is a subclass of \l QQmlExtensionPlugin. It overrides the - \l{QQmlExtensionPlugin::}{registerTypes()} method in order to register the \c TimeModel - type using qmlRegisterType(). It also uses the Q_PLUGIN_METADATA() macro in the class - definition to register the plugin with the Qt meta object system using a unique - identifier for the plugin. - - \snippet qmlextensionplugins/plugin.cpp plugin - - The \c TimeModel class receives a \c{1.0} version of this plugin library, as - a QML type called \c Time. The Q_ASSERT() macro can ensure the type namespace is - imported correctly by any QML components that use this plugin. The - \l{Defining QML Types from C++} article has more information about registering C++ - types into the runtime. - - For this example, the TimeExample source directory is in - \c{imports/TimeExample}. The plugin's type namespace will mirror - this structure, so the types are registered into the namespace - "TimeExample". - - Additionally, the project file, in a \c .pro file, defines the project as a plugin library, - specifies it should be built into the \c imports/TimeExample directory, and registers - the plugin target name and various other details: - - \code - TEMPLATE = lib - CONFIG += qt plugin - QT += qml - - DESTDIR = imports/TimeExample - TARGET = qmlqtimeexampleplugin - SOURCES += qexampleqmlplugin.cpp - \endcode - - Finally, a \l{Module Definition qmldir Files}{qmldir file} is required - in the \c imports/TimeExample directory to describe the plugin and the types that it - exports. The plugin includes a \c Clock.qml file along with the \c qmlqtimeexampleplugin - that is built by the project (as shown above in the \c .pro file) so both of these - need to be specified in the \c qmldir file: - - \quotefile qmlextensionplugins/imports/TimeExample/qmldir - - Once the project is built and installed, the new \c Time component is - accessible by any QML component that imports the \c TimeExample - module - - \snippet qmlextensionplugins/plugins.qml 0 - - The full source code is available in the \l {qmlextensionplugins}{plugins example}. - + \include qqmlextensionplugin.qdocinc \section1 Reference diff --git a/src/qml/doc/src/qmllanguageref/modules/qqmlextensionplugin.qdocinc b/src/qml/doc/src/qmllanguageref/modules/qqmlextensionplugin.qdocinc new file mode 100644 index 0000000000..7c1d65b095 --- /dev/null +++ b/src/qml/doc/src/qmllanguageref/modules/qqmlextensionplugin.qdocinc @@ -0,0 +1,90 @@ +QQmlExtensionPlugin is a plugin interface that makes it possible to +create QML extensions that can be loaded dynamically into QML applications. +These extensions allow custom QML types to be made available to the +QML engine. + +To write a QML extension plugin: +\list 1 +\li Subclass QQmlExtensionPlugin + \list + \li Use the Q_PLUGIN_METADATA() macro to register the plugin with + the Qt meta object system + \li Override the \l{QQmlExtensionPlugin::}{registerTypes()} method + and call qmlRegisterType() to register the types to be exported + by the plugin + \endlist +\li Write a project file for the plugin +\li Create a \l{Module Definition qmldir Files}{qmldir file} to + describe the plugin +\endlist + +QML extension plugins are for either application-specific or library-like +plugins. Library plugins should limit themselves to registering types, as +any manipulation of the engine's root context may cause conflicts or other +issues in the library user's code. + +\section1 Plugin Example + +Suppose there is a new \c TimeModel C++ class that should be made available +as a new QML type. It provides the current time through \c hour and \c minute +properties. + +\snippet qmlextensionplugins/plugin.cpp 0 +\dots + +To make this type available, we create a plugin class named \c QExampleQmlPlugin +which is a subclass of \l QQmlExtensionPlugin. It overrides the +\l{QQmlExtensionPlugin::}{registerTypes()} method in order to register the \c TimeModel +type using qmlRegisterType(). It also uses the Q_PLUGIN_METADATA() macro in the class +definition to register the plugin with the Qt meta object system using a unique +identifier for the plugin. + +\snippet qmlextensionplugins/plugin.cpp plugin + +This registers the \c TimeModel class with version \c{1.0} of this plugin library, as +a QML type called \c Time. The Q_ASSERT() macro can ensure the type namespace is +imported correctly by any QML components that use this plugin. The +\l{Defining QML Types from C++} article has more information about registering C++ +types into the runtime. + +Additionally, the project file (\c .pro) defines the project as a plugin library, +specifies it should be built into the \c imports/TimeExample directory, and registers +the plugin target name and various other details: + +\code +TEMPLATE = lib +CONFIG += qt plugin +QT += qml + +DESTDIR = imports/TimeExample +TARGET = qmlqtimeexampleplugin +SOURCES += qexampleqmlplugin.cpp +\endcode + +Finally, a \l{Module Definition qmldir Files}{qmldir file} is required +in the \c imports/TimeExample directory to describe the plugin and the types that it +exports. The plugin includes a \c Clock.qml file along with the \c qmlqtimeexampleplugin +that is built by the project (as shown above in the \c .pro file) so both of these +need to be specified in the \c qmldir file: + +\quotefile qmlextensionplugins/imports/TimeExample/qmldir + +To make things easier for this example, the TimeExample source directory is in +\c{imports/TimeExample}, and we build +\l{Source, Build, and Install Directories}{in-source}. However, the structure +of the source directory is not so important, as the \c qmldir file can specify +paths to installed QML files. + +What is important is the name of the directory that the qmldir is installed +into. When the user imports our module, the QML engine uses the +\l{Contents of a Module Definition qmldir File}{module identifier} +(\c TimeExample) to find the plugin, and so the directory in which it is +installed must match the module identifier. + +Once the project is built and installed, the new \c Time component is +accessible by any QML component that imports the \c TimeExample +module + +\snippet qmlextensionplugins/plugins.qml 0 + +The full source code is available in the \l {qmlextensionplugins}{plugins example}. diff --git a/src/qml/doc/src/qtqml.qdoc b/src/qml/doc/src/qtqml.qdoc index 61ebbcf690..64d6bb9ac4 100644 --- a/src/qml/doc/src/qtqml.qdoc +++ b/src/qml/doc/src/qtqml.qdoc @@ -148,6 +148,7 @@ Further information for writing QML applications: \list \li \l{Qt QML C++ Classes}{C++ Classes} \li \l{Qt QML QML Types}{QML Types} +\li \l{Qt QML Examples}{Examples} \endlist */ diff --git a/src/qml/jsruntime/qv4arraybuffer.cpp b/src/qml/jsruntime/qv4arraybuffer.cpp index 3106d3af23..23c9695cf4 100644 --- a/src/qml/jsruntime/qv4arraybuffer.cpp +++ b/src/qml/jsruntime/qv4arraybuffer.cpp @@ -79,7 +79,7 @@ ReturnedValue ArrayBufferCtor::method_isView(CallContext *ctx) QV4::Scoped<DataView> v(scope, ctx->argument(0)); if (!!v) return Encode(true); - return Encode(true); + return Encode(false); } diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp index 320ed59fcc..7424dc4e4c 100644 --- a/src/qml/jsruntime/qv4engine.cpp +++ b/src/qml/jsruntime/qv4engine.cpp @@ -107,6 +107,9 @@ static ReturnedValue throwTypeError(CallContext *ctx) const int MinimumStackSize = 256; // in kbytes +QT_WARNING_PUSH +QT_WARNING_DISABLE_MSVC(4172) // MSVC 2015: warning C4172: returning address of local variable or temporary: dummy + quintptr getStackLimit() { quintptr stackLimit; @@ -171,6 +174,7 @@ quintptr getStackLimit() int dummy; // this is inexact, as part of the stack is used when being called here, // but let's simply default to 1MB from where the stack is right now + // (Note: triggers warning C4172 as of MSVC 2015, returning address of local variable) stackLimit = reinterpret_cast<qintptr>(&dummy) - 1024*1024; #endif @@ -178,6 +182,7 @@ quintptr getStackLimit() return stackLimit + MinimumStackSize*1024; } +QT_WARNING_POP QJSEngine *ExecutionEngine::jsEngine() const { @@ -540,7 +545,7 @@ Heap::Object *ExecutionEngine::newObject(InternalClass *internalClass, QV4::Obje Heap::String *ExecutionEngine::newString(const QString &s) { Scope scope(this); - return ScopedString(scope, memoryManager->alloc<String>(s))->d(); + return ScopedString(scope, memoryManager->allocWithStringData<String>(s.length() * sizeof(QChar), s))->d(); } Heap::String *ExecutionEngine::newIdentifier(const QString &text) @@ -1373,7 +1378,7 @@ QV4::ReturnedValue QV4::ExecutionEngine::fromVariant(const QVariant &variant) QV4::Scope scope(this); if (type == qMetaTypeId<QQmlListReference>()) { typedef QQmlListReferencePrivate QDLRP; - QDLRP *p = QDLRP::get((QQmlListReference*)ptr); + QDLRP *p = QDLRP::get((QQmlListReference*)const_cast<void *>(ptr)); if (p->object) { return QV4::QmlListWrapper::create(scope.engine, p->property, p->propertyType); } else { @@ -1385,7 +1390,7 @@ QV4::ReturnedValue QV4::ExecutionEngine::fromVariant(const QVariant &variant) } else if (type == qMetaTypeId<QList<QObject *> >()) { // XXX Can this be made more by using Array as a prototype and implementing // directly against QList<QObject*>? - const QList<QObject *> &list = *(QList<QObject *>*)ptr; + const QList<QObject *> &list = *(const QList<QObject *>*)ptr; QV4::ScopedArrayObject a(scope, newArrayObject()); a->arrayReserve(list.count()); QV4::ScopedValue v(scope); diff --git a/src/qml/jsruntime/qv4function.cpp b/src/qml/jsruntime/qv4function.cpp index a18a2d4919..98a4490211 100644 --- a/src/qml/jsruntime/qv4function.cpp +++ b/src/qml/jsruntime/qv4function.cpp @@ -66,7 +66,8 @@ Function::Function(ExecutionEngine *engine, CompiledData::CompilationUnit *unit, break; } // duplicate arguments, need some trick to store them - arg = engine->memoryManager->alloc<String>(arg->d(), engine->newString(QString(0xfffe))); + MemoryManager *mm = engine->memoryManager; + arg = mm->alloc<String>(mm, arg->d(), engine->newString(QString(0xfffe))); } } diff --git a/src/qml/jsruntime/qv4numberobject.cpp b/src/qml/jsruntime/qv4numberobject.cpp index 096fe9fb4c..4ae30a7f35 100644 --- a/src/qml/jsruntime/qv4numberobject.cpp +++ b/src/qml/jsruntime/qv4numberobject.cpp @@ -76,14 +76,10 @@ void NumberPrototype::init(ExecutionEngine *engine, Object *ctor) ctor->defineReadonlyProperty(QStringLiteral("POSITIVE_INFINITY"), Primitive::fromDouble(qInf())); ctor->defineReadonlyProperty(QStringLiteral("MAX_VALUE"), Primitive::fromDouble(1.7976931348623158e+308)); -#ifdef __INTEL_COMPILER -# pragma warning( push ) -# pragma warning(disable: 239) -#endif +QT_WARNING_PUSH +QT_WARNING_DISABLE_INTEL(239) ctor->defineReadonlyProperty(QStringLiteral("MIN_VALUE"), Primitive::fromDouble(5e-324)); -#ifdef __INTEL_COMPILER -# pragma warning( pop ) -#endif +QT_WARNING_POP defineDefaultProperty(QStringLiteral("constructor"), (o = ctor)); defineDefaultProperty(engine->id_toString(), method_toString); diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp index 529703bda4..e5946d8be6 100644 --- a/src/qml/jsruntime/qv4qobjectwrapper.cpp +++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp @@ -71,14 +71,9 @@ QT_BEGIN_NAMESPACE -#if defined(__GNUC__) && !defined(__INTEL_COMPILER) -# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 405 // The code in this file does not violate strict aliasing, but GCC thinks it does // so turn off the warnings for us to have a clean build -# pragma GCC diagnostic ignored "-Wstrict-aliasing" -# endif -#endif - +QT_WARNING_DISABLE_GCC("-Wstrict-aliasing") using namespace QV4; diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp index 089922d03e..b8ea6d7a87 100644 --- a/src/qml/jsruntime/qv4runtime.cpp +++ b/src/qml/jsruntime/qv4runtime.cpp @@ -524,7 +524,8 @@ QV4::ReturnedValue RuntimeHelpers::addHelper(ExecutionEngine *engine, const Valu return pright->asReturnedValue(); if (!pright->stringValue()->d()->length()) return pleft->asReturnedValue(); - return (engine->memoryManager->alloc<String>(pleft->stringValue()->d(), pright->stringValue()->d()))->asReturnedValue(); + MemoryManager *mm = engine->memoryManager; + return (mm->alloc<String>(mm, pleft->stringValue()->d(), pright->stringValue()->d()))->asReturnedValue(); } double x = RuntimeHelpers::toNumber(pleft); double y = RuntimeHelpers::toNumber(pright); @@ -540,7 +541,8 @@ QV4::ReturnedValue Runtime::addString(ExecutionEngine *engine, const Value &left return right.asReturnedValue(); if (!right.stringValue()->d()->length()) return left.asReturnedValue(); - return (engine->memoryManager->alloc<String>(left.stringValue()->d(), right.stringValue()->d()))->asReturnedValue(); + MemoryManager *mm = engine->memoryManager; + return (mm->alloc<String>(mm, left.stringValue()->d(), right.stringValue()->d()))->asReturnedValue(); } Scope scope(engine); @@ -557,7 +559,8 @@ QV4::ReturnedValue Runtime::addString(ExecutionEngine *engine, const Value &left return pright->asReturnedValue(); if (!pright->stringValue()->d()->length()) return pleft->asReturnedValue(); - return (engine->memoryManager->alloc<String>(pleft->stringValue()->d(), pright->stringValue()->d()))->asReturnedValue(); + MemoryManager *mm = engine->memoryManager; + return (mm->alloc<String>(mm, pleft->stringValue()->d(), pright->stringValue()->d()))->asReturnedValue(); } void Runtime::setProperty(ExecutionEngine *engine, const Value &object, int nameIndex, const Value &value) diff --git a/src/qml/jsruntime/qv4serialize.cpp b/src/qml/jsruntime/qv4serialize.cpp index 090e9c7e6a..33b40796a4 100644 --- a/src/qml/jsruntime/qv4serialize.cpp +++ b/src/qml/jsruntime/qv4serialize.cpp @@ -116,21 +116,21 @@ static inline void reserve(QByteArray &data, int extra) static inline quint32 popUint32(const char *&data) { - quint32 rv = *((quint32 *)data); + quint32 rv = *((const quint32 *)data); data += sizeof(quint32); return rv; } static inline double popDouble(const char *&data) { - double rv = *((double *)data); + double rv = *((const double *)data); data += sizeof(double); return rv; } static inline void *popPtr(const char *&data) { - void *rv = *((void **)data); + void *rv = *((void *const *)data); data += sizeof(void *); return rv; } @@ -297,7 +297,7 @@ ReturnedValue Serialize::deserialize(const char *&data, ExecutionEngine *engine) case WorkerString: { quint32 size = headersize(header); - QString qstr((QChar *)data, size); + QString qstr((const QChar *)data, size); data += ALIGN(size * sizeof(quint16)); return QV4::Encode(engine->newString(qstr)); } @@ -342,7 +342,7 @@ ReturnedValue Serialize::deserialize(const char *&data, ExecutionEngine *engine) { quint32 flags = headersize(header); quint32 length = popUint32(data); - QString pattern = QString((QChar *)data, length - 1); + QString pattern = QString((const QChar *)data, length - 1); data += ALIGN(length * sizeof(quint16)); return Encode(engine->newRegExpObject(pattern, flags)); } diff --git a/src/qml/jsruntime/qv4string.cpp b/src/qml/jsruntime/qv4string.cpp index 2ab608e64e..24a13ddd10 100644 --- a/src/qml/jsruntime/qv4string.cpp +++ b/src/qml/jsruntime/qv4string.cpp @@ -117,7 +117,8 @@ bool String::isEqualTo(Managed *t, Managed *o) } -Heap::String::String(const QString &t) +Heap::String::String(MemoryManager *mm, const QString &t) + : mm(mm) { subtype = String::StringType_Unknown; @@ -129,7 +130,8 @@ Heap::String::String(const QString &t) len = text->size; } -Heap::String::String(String *l, String *r) +Heap::String::String(MemoryManager *mm, String *l, String *r) + : mm(mm) { subtype = String::StringType_Unknown; @@ -187,6 +189,7 @@ void Heap::String::simplifyString() const text->ref.ref(); identifier = 0; largestSubLength = 0; + mm->growUnmanagedHeapSizeUsage(size_t(text->size) * sizeof(QChar)); } void Heap::String::createHashValue() const diff --git a/src/qml/jsruntime/qv4string_p.h b/src/qml/jsruntime/qv4string_p.h index 568c11261a..93a25d7ed5 100644 --- a/src/qml/jsruntime/qv4string_p.h +++ b/src/qml/jsruntime/qv4string_p.h @@ -53,8 +53,8 @@ struct Q_QML_PRIVATE_EXPORT String : Base { StringType_ArrayIndex }; - String(const QString &text); - String(String *l, String *n); + String(MemoryManager *mm, const QString &text); + String(MemoryManager *mm, String *l, String *n); ~String() { if (!largestSubLength && !text->ref.deref()) QStringData::deallocate(text); @@ -66,6 +66,9 @@ struct Q_QML_PRIVATE_EXPORT String : Base { len == (uint)text->size); return len; } + std::size_t retainedTextSize() const { + return largestSubLength ? 0 : (std::size_t(text->size) * sizeof(QChar)); + } void createHashValue() const; inline unsigned hashValue() const { if (subtype == StringType_Unknown) @@ -107,6 +110,7 @@ struct Q_QML_PRIVATE_EXPORT String : Base { mutable uint stringHash; mutable uint largestSubLength; uint len; + MemoryManager *mm; private: static void append(const String *data, QChar *ch); }; diff --git a/src/qml/jsruntime/qv4typedarray.cpp b/src/qml/jsruntime/qv4typedarray.cpp index fcc6f3dc5d..f06eeb08b9 100644 --- a/src/qml/jsruntime/qv4typedarray.cpp +++ b/src/qml/jsruntime/qv4typedarray.cpp @@ -85,7 +85,7 @@ void UInt8ClampedArrayWrite(ExecutionEngine *e, char *data, int index, const Val return; } if (d >= 255) { - data[index] = (unsigned char)(255); + data[index] = (char)(255); return; } double f = std::floor(d); @@ -107,7 +107,7 @@ void UInt8ClampedArrayWrite(ExecutionEngine *e, char *data, int index, const Val ReturnedValue Int16ArrayRead(const char *data, int index) { - return Encode((int)*(short *)(data + index)); + return Encode((int)*(const short *)(data + index)); } void Int16ArrayWrite(ExecutionEngine *e, char *data, int index, const Value &value) @@ -120,7 +120,7 @@ void Int16ArrayWrite(ExecutionEngine *e, char *data, int index, const Value &val ReturnedValue UInt16ArrayRead(const char *data, int index) { - return Encode((int)*(unsigned short *)(data + index)); + return Encode((int)*(const unsigned short *)(data + index)); } void UInt16ArrayWrite(ExecutionEngine *e, char *data, int index, const Value &value) @@ -133,7 +133,7 @@ void UInt16ArrayWrite(ExecutionEngine *e, char *data, int index, const Value &va ReturnedValue Int32ArrayRead(const char *data, int index) { - return Encode(*(int *)(data + index)); + return Encode(*(const int *)(data + index)); } void Int32ArrayWrite(ExecutionEngine *e, char *data, int index, const Value &value) @@ -146,7 +146,7 @@ void Int32ArrayWrite(ExecutionEngine *e, char *data, int index, const Value &val ReturnedValue UInt32ArrayRead(const char *data, int index) { - return Encode(*(unsigned int *)(data + index)); + return Encode(*(const unsigned int *)(data + index)); } void UInt32ArrayWrite(ExecutionEngine *e, char *data, int index, const Value &value) @@ -159,7 +159,7 @@ void UInt32ArrayWrite(ExecutionEngine *e, char *data, int index, const Value &va ReturnedValue Float32ArrayRead(const char *data, int index) { - return Encode(*(float *)(data + index)); + return Encode(*(const float *)(data + index)); } void Float32ArrayWrite(ExecutionEngine *e, char *data, int index, const Value &value) @@ -172,7 +172,7 @@ void Float32ArrayWrite(ExecutionEngine *e, char *data, int index, const Value &v ReturnedValue Float64ArrayRead(const char *data, int index) { - return Encode(*(double *)(data + index)); + return Encode(*(const double *)(data + index)); } void Float64ArrayWrite(ExecutionEngine *e, char *data, int index, const Value &value) diff --git a/src/qml/jsruntime/qv4value_p.h b/src/qml/jsruntime/qv4value_p.h index c0420a38db..6305e6dfbb 100644 --- a/src/qml/jsruntime/qv4value_p.h +++ b/src/qml/jsruntime/qv4value_p.h @@ -39,6 +39,14 @@ #include "qv4global_p.h" #include <private/qv4heap_p.h> +/* We cannot rely on QT_POINTER_SIZE to be set correctly on host builds. In qmldevtools the Value objects + are only used to store primitives, never object pointers. So we can use the 64-bit encoding. */ +#ifdef V4_BOOTSTRAP +#define QV4_USE_64_BIT_VALUE_ENCODING +#elif QT_POINTER_SIZE == 8 +#define QV4_USE_64_BIT_VALUE_ENCODING +#endif + QT_BEGIN_NAMESPACE namespace QV4 { @@ -94,10 +102,10 @@ struct Q_QML_PRIVATE_EXPORT Value Q_ALWAYS_INLINE quint32 value() const { return _val >> 32; } #endif -#if QT_POINTER_SIZE == 8 +#ifdef QV4_USE_64_BIT_VALUE_ENCODING Q_ALWAYS_INLINE Heap::Base *m() const { Heap::Base *b; memcpy(&b, &_val, 8); return b; } Q_ALWAYS_INLINE void setM(Heap::Base *b) { memcpy(&_val, &b, 8); } -#else // QT_POINTER_SIZE == 4 +#else // !QV4_USE_64_BIT_VALUE_ENCODING Q_ALWAYS_INLINE Heap::Base *m() const { Heap::Base *b; quint32 v = value(); memcpy(&b, &v, 4); return b; } Q_ALWAYS_INLINE void setM(Heap::Base *b) { quint32 v; memcpy(&v, &b, 4); setValue(v); } #endif @@ -106,7 +114,7 @@ struct Q_QML_PRIVATE_EXPORT Value Q_ALWAYS_INLINE void setInt_32(int i) { quint32 u; memcpy(&u, &i, 4); setValue(u); } Q_ALWAYS_INLINE uint uint_32() const { return value(); } -#if QT_POINTER_SIZE == 4 +#ifndef QV4_USE_64_BIT_VALUE_ENCODING enum Masks { SilentNaNBit = 0x00040000, NaN_Mask = 0x7ff80000, @@ -186,7 +194,7 @@ struct Q_QML_PRIVATE_EXPORT Value inline bool isUndefined() const { return tag() == Undefined_Type; } inline bool isNull() const { return tag() == _Null_Type; } inline bool isBoolean() const { return tag ()== _Boolean_Type; } -#if QT_POINTER_SIZE == 8 +#ifdef QV4_USE_64_BIT_VALUE_ENCODING inline bool isInteger() const { return (_val >> IsNumber_Shift) == 1; } inline bool isDouble() const { return (_val >> IsDouble_Shift); } inline bool isNumber() const { return (_val >> IsNumber_Shift); } @@ -219,7 +227,7 @@ struct Q_QML_PRIVATE_EXPORT Value Q_ASSERT(isDouble()); double d; quint64 v = _val; -#if QT_POINTER_SIZE == 8 +#ifdef QV4_USE_64_BIT_VALUE_ENCODING v ^= NaNEncodeMask; #endif memcpy(&d, &v, 8); @@ -227,7 +235,7 @@ struct Q_QML_PRIVATE_EXPORT Value } Q_ALWAYS_INLINE void setDouble(double d) { memcpy(&_val, &d, 8); -#if QT_POINTER_SIZE == 8 +#ifdef QV4_USE_64_BIT_VALUE_ENCODING _val ^= NaNEncodeMask; #endif Q_ASSERT(isDouble()); @@ -287,7 +295,7 @@ struct Q_QML_PRIVATE_EXPORT Value Value v; v.setRawValue(0); v.setM(m); -#if QT_POINTER_SIZE == 4 +#ifndef QV4_USE_64_BIT_VALUE_ENCODING v.setTag(Managed_Type); #endif return v; @@ -368,7 +376,7 @@ struct Q_QML_PRIVATE_EXPORT Value } Value &operator=(Heap::Base *o) { setM(o); -#if QT_POINTER_SIZE == 4 +#ifndef QV4_USE_64_BIT_VALUE_ENCODING setTag(Managed_Type); #endif return *this; @@ -413,7 +421,7 @@ inline double Value::toNumber() const #ifndef V4_BOOTSTRAP inline uint Value::asArrayIndex() const { -#if QT_POINTER_SIZE == 8 +#ifdef QV4_USE_64_BIT_VALUE_ENCODING if (!isNumber()) return UINT_MAX; if (isInteger()) @@ -461,7 +469,7 @@ struct Q_QML_PRIVATE_EXPORT Primitive : public Value inline Primitive Primitive::undefinedValue() { Primitive v; -#if QT_POINTER_SIZE == 8 +#ifdef QV4_USE_64_BIT_VALUE_ENCODING v.setRawValue(quint64(Undefined_Type) << Tag_Shift); #else v.setRawValue(0); @@ -481,7 +489,7 @@ inline Primitive Primitive::emptyValue() inline Primitive Primitive::nullValue() { Primitive v; -#if QT_POINTER_SIZE == 8 +#ifndef QV4_USE_64_BIT_VALUE_ENCODING v.setRawValue(quint64(_Null_Type) << Tag_Shift); #else v.setTagValue(_Null_Type, 0); diff --git a/src/qml/jsruntime/qv4vme_moth.cpp b/src/qml/jsruntime/qv4vme_moth.cpp index d0ae44ccea..0edd7378a7 100644 --- a/src/qml/jsruntime/qv4vme_moth.cpp +++ b/src/qml/jsruntime/qv4vme_moth.cpp @@ -636,7 +636,7 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code MOTH_END_INSTR(CallGlobalLookup) MOTH_BEGIN_INSTR(SetExceptionHandler) - exceptionHandler = instr.offset ? ((uchar *)&instr.offset) + instr.offset : 0; + exceptionHandler = instr.offset ? ((const uchar *)&instr.offset) + instr.offset : 0; MOTH_END_INSTR(SetExceptionHandler) MOTH_BEGIN_INSTR(CallBuiltinThrow) @@ -770,21 +770,21 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code MOTH_END_INSTR(ConstructGlobalLookup) MOTH_BEGIN_INSTR(Jump) - code = ((uchar *)&instr.offset) + instr.offset; + code = ((const uchar *)&instr.offset) + instr.offset; MOTH_END_INSTR(Jump) MOTH_BEGIN_INSTR(JumpEq) bool cond = VALUEPTR(instr.condition)->toBoolean(); TRACE(condition, "%s", cond ? "TRUE" : "FALSE"); if (cond) - code = ((uchar *)&instr.offset) + instr.offset; + code = ((const uchar *)&instr.offset) + instr.offset; MOTH_END_INSTR(JumpEq) MOTH_BEGIN_INSTR(JumpNe) bool cond = VALUEPTR(instr.condition)->toBoolean(); TRACE(condition, "%s", cond ? "TRUE" : "FALSE"); if (!cond) - code = ((uchar *)&instr.offset) + instr.offset; + code = ((const uchar *)&instr.offset) + instr.offset; MOTH_END_INSTR(JumpNe) MOTH_BEGIN_INSTR(UNot) diff --git a/src/qml/memory/qv4mm.cpp b/src/qml/memory/qv4mm.cpp index 03e78df91a..38b4e1eaf1 100644 --- a/src/qml/memory/qv4mm.cpp +++ b/src/qml/memory/qv4mm.cpp @@ -95,6 +95,8 @@ struct MemoryManager::Data uint maxShift; std::size_t maxChunkSize; QVector<PageAllocation> heapChunks; + std::size_t unmanagedHeapSize; // the amount of bytes of heap that is not managed by the memory manager, but which is held onto by managed items. + std::size_t unmanagedHeapSizeGCLimit; struct LargeItem { LargeItem *next; @@ -121,6 +123,8 @@ struct MemoryManager::Data , totalAlloc(0) , maxShift(6) , maxChunkSize(32*1024) + , unmanagedHeapSize(0) + , unmanagedHeapSizeGCLimit(64 * 1024) , largeItems(0) , totalLargeItemsAllocated(0) { @@ -154,8 +158,10 @@ struct MemoryManager::Data namespace { -bool sweepChunk(MemoryManager::Data::ChunkHeader *header, uint *itemsInUse, ExecutionEngine *engine) +bool sweepChunk(MemoryManager::Data::ChunkHeader *header, uint *itemsInUse, ExecutionEngine *engine, std::size_t *unmanagedHeapSize) { + Q_ASSERT(unmanagedHeapSize); + bool isEmpty = true; Heap::Base *tail = &header->freeItems; // qDebug("chunkStart @ %p, size=%x, pos=%x", header->itemStart, header->itemSize, header->itemSize>>4); @@ -164,8 +170,8 @@ bool sweepChunk(MemoryManager::Data::ChunkHeader *header, uint *itemsInUse, Exec #endif for (char *item = header->itemStart; item <= header->itemEnd; item += header->itemSize) { Heap::Base *m = reinterpret_cast<Heap::Base *>(item); -// qDebug("chunk @ %p, size = %lu, in use: %s, mark bit: %s", -// item, m->size, (m->inUse ? "yes" : "no"), (m->markBit ? "true" : "false")); +// qDebug("chunk @ %p, in use: %s, mark bit: %s", +// item, (m->inUse() ? "yes" : "no"), (m->isMarked() ? "true" : "false")); Q_ASSERT((qintptr) item % 16 == 0); @@ -180,6 +186,13 @@ bool sweepChunk(MemoryManager::Data::ChunkHeader *header, uint *itemsInUse, Exec #ifdef V4_USE_VALGRIND VALGRIND_ENABLE_ERROR_REPORTING; #endif + if (std::size_t(header->itemSize) == MemoryManager::align(sizeof(Heap::String)) && m->vtable()->isString) { + std::size_t heapBytes = static_cast<Heap::String *>(m)->retainedTextSize(); + Q_ASSERT(*unmanagedHeapSize >= heapBytes); +// qDebug() << "-- it's a string holding on to" << heapBytes << "bytes"; + *unmanagedHeapSize -= heapBytes; + } + if (m->vtable()->destroy) m->vtable()->destroy(m); @@ -216,7 +229,7 @@ MemoryManager::MemoryManager(ExecutionEngine *engine) m_d->engine = engine; } -Heap::Base *MemoryManager::allocData(std::size_t size) +Heap::Base *MemoryManager::allocData(std::size_t size, std::size_t unmanagedSize) { if (m_d->aggressiveGC) runGC(); @@ -227,11 +240,27 @@ Heap::Base *MemoryManager::allocData(std::size_t size) Q_ASSERT(size >= 16); Q_ASSERT(size % 16 == 0); +// qDebug() << "unmanagedHeapSize:" << m_d->unmanagedHeapSize << "limit:" << m_d->unmanagedHeapSizeGCLimit << "unmanagedSize:" << unmanagedSize; + m_d->unmanagedHeapSize += unmanagedSize; + bool didGCRun = false; + if (m_d->unmanagedHeapSize > m_d->unmanagedHeapSizeGCLimit) { + runGC(); + + if (m_d->unmanagedHeapSizeGCLimit <= m_d->unmanagedHeapSize) + m_d->unmanagedHeapSizeGCLimit = std::max(m_d->unmanagedHeapSizeGCLimit, m_d->unmanagedHeapSize) * 2; + else if (m_d->unmanagedHeapSize * 4 <= m_d->unmanagedHeapSizeGCLimit) + m_d->unmanagedHeapSizeGCLimit /= 2; + else if (m_d->unmanagedHeapSizeGCLimit - m_d->unmanagedHeapSize < 5 * unmanagedSize) + // try preventing running the GC all the time when we're just below the threshold limit and manage to collect just enough to do this one allocation + m_d->unmanagedHeapSizeGCLimit += std::max(std::size_t(8 * 1024), 5 * unmanagedSize); + didGCRun = true; + } + size_t pos = size >> 4; // doesn't fit into a small bucket if (size >= MemoryManager::Data::MaxItemSize) { - if (m_d->totalLargeItemsAllocated > 8 * 1024 * 1024) + if (!didGCRun && m_d->totalLargeItemsAllocated > 8 * 1024 * 1024) runGC(); // we use malloc for this @@ -254,7 +283,7 @@ Heap::Base *MemoryManager::allocData(std::size_t size) } // try to free up space, otherwise allocate - if (m_d->allocCount[pos] > (m_d->availableItems[pos] >> 1) && m_d->totalAlloc > (m_d->totalItems >> 1) && !m_d->aggressiveGC) { + if (!didGCRun && m_d->allocCount[pos] > (m_d->availableItems[pos] >> 1) && m_d->totalAlloc > (m_d->totalItems >> 1) && !m_d->aggressiveGC) { runGC(); header = m_d->nonFullChunks[pos]; if (header) { @@ -405,7 +434,7 @@ void MemoryManager::sweep(bool lastSweep) for (int i = 0; i < m_d->heapChunks.size(); ++i) { Data::ChunkHeader *header = reinterpret_cast<Data::ChunkHeader *>(m_d->heapChunks[i].base()); - chunkIsEmpty[i] = sweepChunk(header, &itemsInUse[header->itemSize >> 4], m_d->engine); + chunkIsEmpty[i] = sweepChunk(header, &itemsInUse[header->itemSize >> 4], m_d->engine, &m_d->unmanagedHeapSize); } QVector<PageAllocation>::iterator chunkIter = m_d->heapChunks.begin(); @@ -545,6 +574,11 @@ size_t MemoryManager::getLargeItemsMem() const return total; } +void MemoryManager::growUnmanagedHeapSizeUsage(size_t delta) +{ + m_d->unmanagedHeapSize += delta; +} + MemoryManager::~MemoryManager() { delete m_persistentValues; diff --git a/src/qml/memory/qv4mm_p.h b/src/qml/memory/qv4mm_p.h index 6d6ce1bad7..c01866ff11 100644 --- a/src/qml/memory/qv4mm_p.h +++ b/src/qml/memory/qv4mm_p.h @@ -83,10 +83,10 @@ public: { return (size + 15) & ~0xf; } template<typename ManagedType> - inline typename ManagedType::Data *allocManaged(std::size_t size) + inline typename ManagedType::Data *allocManaged(std::size_t size, std::size_t unmanagedSize = 0) { size = align(size); - Heap::Base *o = allocData(size); + Heap::Base *o = allocData(size, unmanagedSize); o->setVtable(ManagedType::staticVTable()); return static_cast<typename ManagedType::Data *>(o); } @@ -109,6 +109,15 @@ public: return t->d(); } + template <typename ManagedType, typename Arg1> + typename ManagedType::Data *allocWithStringData(std::size_t unmanagedSize, Arg1 arg1) + { + Scope scope(engine()); + Scoped<ManagedType> t(scope, allocManaged<ManagedType>(sizeof(typename ManagedType::Data), unmanagedSize)); + (void)new (t->d()) typename ManagedType::Data(this, arg1); + return t->d(); + } + template <typename ManagedType, typename Arg1, typename Arg2> typename ManagedType::Data *alloc(Arg1 arg1, Arg2 arg2) { @@ -157,10 +166,12 @@ public: size_t getAllocatedMem() const; size_t getLargeItemsMem() const; + void growUnmanagedHeapSizeUsage(size_t delta); // called when a JS object grows itself. Specifically: Heap::String::append + protected: /// expects size to be aligned // TODO: try to inline - Heap::Base *allocData(std::size_t size); + Heap::Base *allocData(std::size_t size, std::size_t unmanagedSize); #ifdef DETAILED_MM_STATS void willAllocate(std::size_t size); diff --git a/src/qml/qml/ftw/qbitfield_p.h b/src/qml/qml/ftw/qbitfield_p.h index 0b7d507b11..e3b6b0e498 100644 --- a/src/qml/qml/ftw/qbitfield_p.h +++ b/src/qml/qml/ftw/qbitfield_p.h @@ -129,15 +129,16 @@ QBitField QBitField::united(const QBitField &o) rv.bits = max; rv.ownData = new quint32[length + 1]; *(rv.ownData) = 1; - rv.data = rv.ownData + 1; + quint32 *rvdata; + rv.data = rvdata = rv.ownData + 1; if (bits > o.bits) { - ::memcpy((quint32 *)rv.data, data, length * sizeof(quint32)); + ::memcpy(rvdata, data, length * sizeof(quint32)); for (quint32 ii = 0; ii < (o.bits + quint32(31)) / 32; ++ii) - ((quint32 *)rv.data)[ii] |= o.data[ii]; + (rvdata)[ii] |= o.data[ii]; } else { - ::memcpy((quint32 *)rv.data, o.data, length * sizeof(quint32)); + ::memcpy(rvdata, o.data, length * sizeof(quint32)); for (quint32 ii = 0; ii < (bits + quint32(31)) / 32; ++ii) - ((quint32 *)rv.data)[ii] |= data[ii]; + (rvdata)[ii] |= data[ii]; } return rv; } diff --git a/src/qml/qml/ftw/qhashedstring_p.h b/src/qml/qml/ftw/qhashedstring_p.h index 6ae2e17267..d38fd668f3 100644 --- a/src/qml/qml/ftw/qhashedstring_p.h +++ b/src/qml/qml/ftw/qhashedstring_p.h @@ -252,14 +252,14 @@ public: inline bool equals(const QHashedStringRef &string) const { return length == string.length() && hash == string.hash() && - (isQString()?QHashedString::compare(string.constData(), (QChar *)utf16Data(), length): + (isQString()?QHashedString::compare(string.constData(), (const QChar *)utf16Data(), length): QHashedString::compare(string.constData(), cStrData(), length)); } inline bool equals(const QHashedCStringRef &string) const { return length == string.length() && hash == string.hash() && - (isQString()?QHashedString::compare((QChar *)utf16Data(), string.constData(), length): + (isQString()?QHashedString::compare((const QChar *)utf16Data(), string.constData(), length): QHashedString::compare(string.constData(), cStrData(), length)); } }; diff --git a/src/qml/qml/qqml.h b/src/qml/qml/qqml.h index d6fd7b96f6..23cb69e2f1 100644 --- a/src/qml/qml/qqml.h +++ b/src/qml/qml/qqml.h @@ -502,17 +502,13 @@ namespace QtQml { } #endif -#if defined(Q_CC_CLANG) && !defined(Q_CC_INTEL) -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wheader-hygiene" -#endif +QT_WARNING_PUSH +QT_WARNING_DISABLE_CLANG("-Wheader-hygiene") // This is necessary to allow for QtQuick1 and QtQuick2 scenes in a single application. using namespace QtQml; -#if defined(Q_CC_CLANG) && !defined(Q_CC_INTEL) -#pragma clang diagnostic pop -#endif +QT_WARNING_POP //The C++ version of protected namespaces in qmldir Q_QML_EXPORT bool qmlProtectModule(const char* uri, int majVersion); diff --git a/src/qml/qml/qqmlabstracturlinterceptor.cpp b/src/qml/qml/qqmlabstracturlinterceptor.cpp index e64b33b181..cb57bc2146 100644 --- a/src/qml/qml/qqmlabstracturlinterceptor.cpp +++ b/src/qml/qml/qqmlabstracturlinterceptor.cpp @@ -58,7 +58,7 @@ To implement support for a custom networked scheme, see setNetworkAccessManagerFactory. */ -/* +/*! \enum QQmlAbstractUrlInterceptor::DataType Specifies where URL interception is taking place. diff --git a/src/qml/qml/qqmlbinding.cpp b/src/qml/qml/qqmlbinding.cpp index f17009569f..3613c17242 100644 --- a/src/qml/qml/qqmlbinding.cpp +++ b/src/qml/qml/qqmlbinding.cpp @@ -44,6 +44,7 @@ #include <private/qqmlcontextwrapper_p.h> #include <private/qqmlbuiltinfunctions_p.h> #include <private/qqmlvmemetaobject_p.h> +#include <private/qqmlvaluetypewrapper_p.h> #include <QVariant> #include <QtCore/qdebug.h> @@ -253,6 +254,11 @@ bool QQmlBinding::write(const QQmlPropertyData &core, QUICK_STORE(QString, result.toQStringNoThrow()) break; default: + if (const QV4::QQmlValueTypeWrapper *vtw = result.as<const QV4::QQmlValueTypeWrapper>()) { + if (vtw->d()->valueType->typeId == core.propType) { + return vtw->write(m_target.data(), core.coreIndex); + } + } break; } } @@ -327,7 +333,7 @@ bool QQmlBinding::write(const QQmlPropertyData &core, const char *propertyType = 0; if (value.userType() == QMetaType::QObjectStar) { - if (QObject *o = *(QObject **)value.constData()) { + if (QObject *o = *(QObject *const *)value.constData()) { valueType = o->metaObject()->className(); QQmlMetaObject propertyMetaObject = QQmlPropertyPrivate::rawMetaObjectForType(QQmlEnginePrivate::get(engine), type); diff --git a/src/qml/qml/qqmlcontext.cpp b/src/qml/qml/qqmlcontext.cpp index 56326df979..b056731e96 100644 --- a/src/qml/qml/qqmlcontext.cpp +++ b/src/qml/qml/qqmlcontext.cpp @@ -782,7 +782,7 @@ QString QQmlContextData::findObjectId(const QObject *obj) const if (publicContext) { QQmlContextPrivate *p = QQmlContextPrivate::get(publicContext); for (int ii = 0; ii < p->propertyValues.count(); ++ii) - if (p->propertyValues.at(ii) == QVariant::fromValue((QObject *)obj)) + if (p->propertyValues.at(ii) == QVariant::fromValue(const_cast<QObject *>(obj))) return properties.findId(ii); } diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp index 70c682dedd..9c5e48ae32 100644 --- a/src/qml/qml/qqmlengine.cpp +++ b/src/qml/qml/qqmlengine.cpp @@ -258,6 +258,18 @@ void QQmlEnginePrivate::activateDesignerMode() on producing the image without blocking the main thread. */ +/*! + \fn QQmlImageProviderBase::imageType() const + + Implement this method to return the image type supported by this image provider. +*/ + +/*! + \fn QQmlImageProviderBase::flags() const + + Implement this to return the properties of this image provider. +*/ + /*! \internal */ QQmlImageProviderBase::QQmlImageProviderBase() { @@ -1355,6 +1367,9 @@ QQmlEngine::ObjectOwnership QQmlEngine::objectOwnership(QObject *object) return ddata->indestructible?CppOwnership:JavaScriptOwnership; } +/*! + \reimp +*/ bool QQmlEngine::event(QEvent *e) { Q_D(QQmlEngine); @@ -1496,16 +1511,28 @@ QQmlDataExtended::~QQmlDataExtended() void QQmlData::NotifyList::layout(QQmlNotifierEndpoint *endpoint) { - if (endpoint->next) - layout(endpoint->next); + // Add a temporary sentinel at beginning of list. This will be overwritten + // when the end point is inserted into the notifies further down. + endpoint->prev = 0; - int index = endpoint->sourceSignal; - index = qMin(index, 0xFFFF - 1); + while (endpoint->next) { + Q_ASSERT(reinterpret_cast<QQmlNotifierEndpoint *>(endpoint->next->prev) == endpoint); + endpoint = endpoint->next; + } + + while (endpoint) { + QQmlNotifierEndpoint *ep = (QQmlNotifierEndpoint *) endpoint->prev; - endpoint->next = notifies[index]; - if (endpoint->next) endpoint->next->prev = &endpoint->next; - endpoint->prev = ¬ifies[index]; - notifies[index] = endpoint; + int index = endpoint->sourceSignal; + index = qMin(index, 0xFFFF - 1); + + endpoint->next = notifies[index]; + if (endpoint->next) endpoint->next->prev = &endpoint->next; + endpoint->prev = ¬ifies[index]; + notifies[index] = endpoint; + + endpoint = ep; + } } void QQmlData::NotifyList::layout() @@ -2182,7 +2209,7 @@ QObject *QQmlEnginePrivate::toQObject(const QVariant &v, bool *ok) const int t = v.userType(); if (t == QMetaType::QObjectStar || m_compositeTypes.contains(t)) { if (ok) *ok = true; - return *(QObject **)(v.constData()); + return *(QObject *const *)(v.constData()); } else { return QQmlMetaType::toQObject(v, ok); } diff --git a/src/qml/qml/qqmlextensionplugin.cpp b/src/qml/qml/qqmlextensionplugin.cpp index 7b560268ba..d86fbc5999 100644 --- a/src/qml/qml/qqmlextensionplugin.cpp +++ b/src/qml/qml/qqmlextensionplugin.cpp @@ -44,71 +44,7 @@ QT_BEGIN_NAMESPACE \ingroup plugins - QQmlExtensionPlugin is a plugin interface that makes it possible to - create QML extensions that can be loaded dynamically into QML applications. - These extensions allow custom QML types to be made available to the QML engine. - - To write a QML extension plugin: - - \list - \li Subclass QQmlExtensionPlugin, implement registerTypes() method to register types - using qmlRegisterType(), and export the class using the Q_PLUGIN_METADATA() macro - \li Write an appropriate project file for the plugin - \li Create a \l{Module Definition qmldir Files}{qmldir file} to describe the plugin - \endlist - - QML extension plugins can be used to provide either application-specific or - library-like plugins. Library plugins should limit themselves to registering types, - as any manipulation of the engine's root context may cause conflicts - or other issues in the library user's code. - - - \section1 An Example - - Suppose there is a new \c TimeModel C++ class that should be made available - as a new QML element. It provides the current time through \c hour and \c minute - properties, like this: - - \snippet qmlextensionplugins/plugin.cpp 0 - \dots - - To make this class available as a QML type, create a plugin that registers - this type with a specific \l {QML Modules}{module} using qmlRegisterType(). For this example the plugin - module will be named \c TimeExample (as defined in the project - file further below). - - \snippet qmlextensionplugins/plugin.cpp plugin - - This registers the \c TimeModel class with the 1.0 version of this - plugin library, as a QML type called \c Time. The Q_ASSERT statement - ensures the module is imported correctly by any QML components that use this plugin. - - The project file defines the project as a plugin library and specifies - it should be built into the \c imports/TimeExample directory: - - \code - TEMPLATE = lib - CONFIG += qt plugin - QT += qml - - DESTDIR = imports/TimeExample - TARGET = qmlqtimeexampleplugin - ... - \endcode - - Finally, a \l{Module Definition qmldir Files}{qmldir file} is required in the \c imports/TimeExample directory - that describes the plugin. This directory includes a \c Clock.qml file that - should be bundled with the plugin, so it needs to be specified in the \c qmldir - file: - - \quotefile qmlextensionplugins/imports/TimeExample/qmldir - - Once the project is built and installed, the new \c Time element can be - used by any QML component that imports the \c TimeExample module: - - \snippet qmlextensionplugins/plugins.qml 0 - - The full source code is available in the \l {qmlextensionplugins}{plugins example}. + \include qqmlextensionplugin.qdocinc The \l {Writing QML Extensions with C++} tutorial also contains a chapter on creating QML plugins. diff --git a/src/qml/qml/qqmlfileselector.cpp b/src/qml/qml/qqmlfileselector.cpp index 3ee7bb3040..8597e8a5c7 100644 --- a/src/qml/qml/qqmlfileselector.cpp +++ b/src/qml/qml/qqmlfileselector.cpp @@ -102,6 +102,9 @@ QQmlFileSelector::QQmlFileSelector(QQmlEngine* engine, QObject* parent) d->engine->setUrlInterceptor(d->myInstance.data()); } +/*! + Destroys the QQmlFileSelector object. +*/ QQmlFileSelector::~QQmlFileSelector() { Q_D(QQmlFileSelector); diff --git a/src/qml/qml/qqmlimport.cpp b/src/qml/qml/qqmlimport.cpp index cf509a96ec..b17bb0455d 100644 --- a/src/qml/qml/qqmlimport.cpp +++ b/src/qml/qml/qqmlimport.cpp @@ -1653,7 +1653,7 @@ QString QQmlImportDatabase::resolvePlugin(QQmlTypeLoader *typeLoader, \row \li Unix/Linux \li \c .so \row \li AIX \li \c .a \row \li HP-UX \li \c .sl, \c .so (HP-UXi) - \row \li Mac OS X \li \c .dylib, \c .bundle, \c .so + \row \li OS X \li \c .dylib, \c .bundle, \c .so \endtable Version number on unix are ignored. diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp index 41629801ea..fbb21f4562 100644 --- a/src/qml/qml/qqmlmetatype.cpp +++ b/src/qml/qml/qqmlmetatype.cpp @@ -225,6 +225,9 @@ void QQmlType::SingletonInstanceInfo::init(QQmlEngine *e) v4->pushGlobalContext(); QObject *o = qobjectCallback(e, e); setQObjectApi(e, o); + if (!o) { + qFatal("qmlRegisterSingletonType(): \"%s\" is not available because the callback function returns a null pointer.", qPrintable(typeName)); + } // if this object can use a property cache, create it now QQmlData::ensurePropertyCache(e, o); v4->popContext(); @@ -1510,7 +1513,7 @@ QObject *QQmlMetaType::toQObject(const QVariant &v, bool *ok) if (ok) *ok = true; - return *(QObject **)v.constData(); + return *(QObject *const *)v.constData(); } bool QQmlMetaType::isQObject(int userType) diff --git a/src/qml/qml/qqmlnotifier.cpp b/src/qml/qml/qqmlnotifier.cpp index 4ce5be4d1a..ea3f7a1530 100644 --- a/src/qml/qml/qqmlnotifier.cpp +++ b/src/qml/qml/qqmlnotifier.cpp @@ -51,30 +51,52 @@ static Callback QQmlNotifier_callbacks[] = { QQmlVMEMetaObjectEndpoint_callback }; +namespace { + struct NotifyListTraversalData { + NotifyListTraversalData(QQmlNotifierEndpoint *ep = 0) + : originalSenderPtr(0) + , disconnectWatch(0) + , endpoint(ep) + {} + + qintptr originalSenderPtr; + qintptr *disconnectWatch; + QQmlNotifierEndpoint *endpoint; + }; +} + void QQmlNotifier::emitNotify(QQmlNotifierEndpoint *endpoint, void **a) { - qintptr originalSenderPtr; - qintptr *disconnectWatch; - - if (!endpoint->isNotifying()) { - originalSenderPtr = endpoint->senderPtr; - disconnectWatch = &originalSenderPtr; - endpoint->senderPtr = qintptr(disconnectWatch) | 0x1; - } else { - disconnectWatch = (qintptr *)(endpoint->senderPtr & ~0x1); + QVarLengthArray<NotifyListTraversalData> stack; + while (endpoint) { + stack.append(NotifyListTraversalData(endpoint)); + endpoint = endpoint->next; } - if (endpoint->next) - emitNotify(endpoint->next, a); + int i = 0; + for (; i < stack.size(); ++i) { + NotifyListTraversalData &data = stack[i]; + + if (!data.endpoint->isNotifying()) { + data.originalSenderPtr = data.endpoint->senderPtr; + data.disconnectWatch = &data.originalSenderPtr; + data.endpoint->senderPtr = qintptr(data.disconnectWatch) | 0x1; + } else { + data.disconnectWatch = (qintptr *)(data.endpoint->senderPtr & ~0x1); + } + } - if (*disconnectWatch) { + while (--i >= 0) { + const NotifyListTraversalData &data = stack.at(i); + if (*data.disconnectWatch) { - Q_ASSERT(QQmlNotifier_callbacks[endpoint->callback]); - QQmlNotifier_callbacks[endpoint->callback](endpoint, a); + Q_ASSERT(QQmlNotifier_callbacks[data.endpoint->callback]); + QQmlNotifier_callbacks[data.endpoint->callback](data.endpoint, a); - if (disconnectWatch == &originalSenderPtr && originalSenderPtr) { - // End of notifying, restore values - endpoint->senderPtr = originalSenderPtr; + if (data.disconnectWatch == &data.originalSenderPtr && data.originalSenderPtr) { + // End of notifying, restore values + data.endpoint->senderPtr = data.originalSenderPtr; + } } } } diff --git a/src/qml/qml/qqmlnotifier_p.h b/src/qml/qml/qqmlnotifier_p.h index bd2c0e6506..90902c089d 100644 --- a/src/qml/qml/qqmlnotifier_p.h +++ b/src/qml/qml/qqmlnotifier_p.h @@ -60,6 +60,8 @@ private: class QQmlEngine; class QQmlNotifierEndpoint { + QQmlNotifierEndpoint *next; + QQmlNotifierEndpoint **prev; public: // QQmlNotifierEndpoint can only invoke one of a set of pre-defined callbacks. // To add another callback, extend this enum and add the callback to the top @@ -103,9 +105,6 @@ private: // The index is in the range returned by QObjectPrivate::signalIndex(). // This is different from QMetaMethod::methodIndex(). signed int sourceSignal:28; - - QQmlNotifierEndpoint *next; - QQmlNotifierEndpoint **prev; }; QQmlNotifier::QQmlNotifier() @@ -137,7 +136,7 @@ void QQmlNotifier::notify() } QQmlNotifierEndpoint::QQmlNotifierEndpoint(Callback callback) -: senderPtr(0), callback(callback), sourceSignal(-1), next(0), prev(0) +: next(0), prev(0), senderPtr(0), callback(callback), sourceSignal(-1) { } diff --git a/src/qml/qml/qqmlproperty.cpp b/src/qml/qml/qqmlproperty.cpp index 414bf8fe0f..c1120b4542 100644 --- a/src/qml/qml/qqmlproperty.cpp +++ b/src/qml/qml/qqmlproperty.cpp @@ -1240,12 +1240,12 @@ bool QQmlPropertyPrivate::write(QObject *object, QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, argv); } else if (variantType == propertyType) { - void *a[] = { (void *)value.constData(), 0, &status, &flags }; + void *a[] = { const_cast<void *>(value.constData()), 0, &status, &flags }; QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, a); } else if (qMetaTypeId<QVariant>() == propertyType) { - void *a[] = { (void *)&value, 0, &status, &flags }; + void *a[] = { const_cast<QVariant *>(&value), 0, &status, &flags }; QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, a); } else if (property.isQObject()) { @@ -1255,7 +1255,7 @@ bool QQmlPropertyPrivate::write(QObject *object, if (valMo.isNull()) return false; - QObject *o = *(QObject **)value.constData(); + QObject *o = *(QObject *const *)value.constData(); QQmlMetaObject propMo = rawMetaObjectForType(enginePriv, propertyType); if (o) valMo = o; @@ -1401,7 +1401,7 @@ bool QQmlPropertyPrivate::write(QObject *object, } if (ok) { - void *a[] = { (void *)v.constData(), 0, &status, &flags}; + void *a[] = { const_cast<void *>(v.constData()), 0, &status, &flags}; QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, a); } else { return false; @@ -1411,7 +1411,6 @@ bool QQmlPropertyPrivate::write(QObject *object, return true; } - QQmlMetaObject QQmlPropertyPrivate::rawMetaObjectForType(QQmlEnginePrivate *engine, int userType) { QMetaType metaType(userType); diff --git a/src/qml/qml/qqmlpropertycache.cpp b/src/qml/qml/qqmlpropertycache.cpp index 294f3ccdf9..cd8eb0d3e2 100644 --- a/src/qml/qml/qqmlpropertycache.cpp +++ b/src/qml/qml/qqmlpropertycache.cpp @@ -271,7 +271,7 @@ QQmlPropertyCache::~QQmlPropertyCache() stringCache.clear(); if (_parent) _parent->release(); - if (_ownMetaObject) free((void *)_metaObject); + if (_ownMetaObject) free(const_cast<QMetaObject *>(_metaObject)); _metaObject = 0; _parent = 0; engine = 0; diff --git a/src/qml/qml/qqmlvaluetype.cpp b/src/qml/qml/qqmlvaluetype.cpp index 7ebfcd64b7..6a71a07e9b 100644 --- a/src/qml/qml/qqmlvaluetype.cpp +++ b/src/qml/qml/qqmlvaluetype.cpp @@ -202,7 +202,7 @@ QQmlValueType::~QQmlValueType() QObjectPrivate *op = QObjectPrivate::get(this); Q_ASSERT(op->metaObject == this); op->metaObject = 0; - ::free((void*)_metaObject); + ::free(const_cast<QMetaObject *>(_metaObject)); metaType.destroy(gadgetPtr); } diff --git a/src/qml/qml/qqmlvmemetaobject.cpp b/src/qml/qml/qqmlvmemetaobject.cpp index 08b1e09d76..9f02c905fc 100644 --- a/src/qml/qml/qqmlvmemetaobject.cpp +++ b/src/qml/qml/qqmlvmemetaobject.cpp @@ -732,7 +732,7 @@ int QQmlVMEMetaObject::metaCall(QMetaObject::Call c, int _id, void **a) int listIndex = data[id].asInt(); const List *list = &listProperties.at(listIndex); *reinterpret_cast<QQmlListProperty<QObject> *>(a[0]) = - QQmlListProperty<QObject>(object, (void *)list, + QQmlListProperty<QObject>(object, const_cast<List *>(list), list_append, list_count, list_at, list_clear); } @@ -1048,7 +1048,7 @@ void QQmlVMEMetaObject::writeProperty(int id, const QVariant &value) } else { bool needActivate = false; if (value.userType() == QMetaType::QObjectStar) { - QObject *o = *(QObject **)value.data(); + QObject *o = *(QObject *const *)value.data(); needActivate = (data[id].dataType() != QMetaType::QObjectStar || data[id].asQObject() != o); data[id].setValue(o, this, id); } else { diff --git a/src/qml/qml/qqmlvmemetaobject_p.h b/src/qml/qml/qqmlvmemetaobject_p.h index 44809a26f0..a320163f23 100644 --- a/src/qml/qml/qqmlvmemetaobject_p.h +++ b/src/qml/qml/qqmlvmemetaobject_p.h @@ -119,7 +119,7 @@ struct QQmlVMEMetaData }; PropertyData *propertyData() const { - return (PropertyData *)(((const char *)this) + sizeof(QQmlVMEMetaData)); + return (PropertyData *)(((char *)const_cast<QQmlVMEMetaData *>(this)) + sizeof(QQmlVMEMetaData)); } AliasData *aliasData() const { diff --git a/src/qml/types/qqmlinstantiator.cpp b/src/qml/types/qqmlinstantiator.cpp index 7626ba5a05..735463a058 100644 --- a/src/qml/types/qqmlinstantiator.cpp +++ b/src/qml/types/qqmlinstantiator.cpp @@ -321,7 +321,7 @@ int QQmlInstantiator::count() const Note that an extra variable, index, will be available inside instances of the delegate. This variable refers to the index of the instance inside the Instantiator, - and can be used to obtain the object through the itemAt method of the Instantiator. + and can be used to obtain the object through the objectAt method of the Instantiator. If this property is changed, all instances using the old delegate will be destroyed and new instances will be created using the new delegate. diff --git a/src/qml/util/qqmllistaccessor.cpp b/src/qml/util/qqmllistaccessor.cpp index 55b745ab6d..bebab80d28 100644 --- a/src/qml/util/qqmllistaccessor.cpp +++ b/src/qml/util/qqmllistaccessor.cpp @@ -96,7 +96,7 @@ int QQmlListAccessor::count() const case VariantList: return qvariant_cast<QVariantList>(d).count(); case ListProperty: - return ((QQmlListReference *)d.constData())->count(); + return ((const QQmlListReference *)d.constData())->count(); case Instance: return 1; case Integer: @@ -116,7 +116,7 @@ QVariant QQmlListAccessor::at(int idx) const case VariantList: return qvariant_cast<QVariantList>(d).at(idx); case ListProperty: - return QVariant::fromValue(((QQmlListReference *)d.constData())->at(idx)); + return QVariant::fromValue(((const QQmlListReference *)d.constData())->at(idx)); case Instance: return d; case Integer: diff --git a/src/quick/doc/qtquick.qdocconf b/src/quick/doc/qtquick.qdocconf index afe1b9708f..7f43dc2c31 100644 --- a/src/quick/doc/qtquick.qdocconf +++ b/src/quick/doc/qtquick.qdocconf @@ -67,7 +67,8 @@ excludedirs += ../../imports/models \ examples.fileextensions += "*.qm" -manifestmeta.thumbnail.names += "QtQuick/Threaded ListModel Example" +manifestmeta.thumbnail.names += "QtQuick/Threaded ListModel Example" \ + "QtQuick/QML Dynamic View Ordering Tutorial*" navigation.landingpage = "Qt Quick" navigation.cppclassespage = "Qt Quick C++ Classes" diff --git a/src/quick/doc/src/concepts/modelviewsdata/modelview.qdoc b/src/quick/doc/src/concepts/modelviewsdata/modelview.qdoc index 4e894e5a33..e03b3a9bf8 100644 --- a/src/quick/doc/src/concepts/modelviewsdata/modelview.qdoc +++ b/src/quick/doc/src/concepts/modelviewsdata/modelview.qdoc @@ -187,7 +187,7 @@ To visualize data, bind the view's \c model property to a model and the QML provides several types of data models among the built-in set of QML types. In addition, models can be created with Qt C++ and then made - available to the \l{QQmlEngine}{QMLEngine} for use by + available to \l{QQmlEngine} for use by QML components. For information about creating these models, visit the \l{Using C++ Models with Qt Quick Views} and \l{qtqml-typesystem-topic.html#qml-object-types} diff --git a/src/quick/items/context2d/qquickcanvasitem.cpp b/src/quick/items/context2d/qquickcanvasitem.cpp index 8fa290b953..9932747dd3 100644 --- a/src/quick/items/context2d/qquickcanvasitem.cpp +++ b/src/quick/items/context2d/qquickcanvasitem.cpp @@ -57,7 +57,11 @@ class QQuickCanvasNode : public QSGSimpleTextureNode public: QQuickCanvasNode() { qsgnode_set_description(this, QStringLiteral("canvasnode")); - setOwnsTexture(true); + setOwnsTexture(false); + } + + ~QQuickCanvasNode() { + delete texture(); } }; diff --git a/src/quick/items/context2d/qquickcontext2dcommandbuffer.cpp b/src/quick/items/context2d/qquickcontext2dcommandbuffer.cpp index 782d03f9f9..4a2c137aa1 100644 --- a/src/quick/items/context2d/qquickcontext2dcommandbuffer.cpp +++ b/src/quick/items/context2d/qquickcontext2dcommandbuffer.cpp @@ -92,7 +92,7 @@ namespace { { } - void paint(QPainter *p) const { p->fillRect(m_rect, m_brush); } + void paint(QPainter *p) const Q_DECL_OVERRIDE { p->fillRect(m_rect, m_brush); } QRectF boundingRect() const Q_DECL_OVERRIDE { return m_rect; } private: @@ -109,7 +109,7 @@ namespace { { } - void paint(QPainter *p) const { p->fillPath(m_path, m_brush); } + void paint(QPainter *p) const Q_DECL_OVERRIDE { p->fillPath(m_path, m_brush); } QRectF boundingRect() const Q_DECL_OVERRIDE { return m_path.boundingRect(); } private: @@ -126,7 +126,7 @@ namespace { { } - void paint(QPainter *p) const { p->strokePath(m_path, m_pen); } + void paint(QPainter *p) const Q_DECL_OVERRIDE { p->strokePath(m_path, m_pen); } QRectF boundingRect() const Q_DECL_OVERRIDE { @@ -148,7 +148,7 @@ namespace { { } - void paint(QPainter *p) const { p->drawImage(m_offset, m_image); } + void paint(QPainter *p) const Q_DECL_OVERRIDE { p->drawImage(m_offset, m_image); } QRectF boundingRect() const Q_DECL_OVERRIDE { return QRectF(m_image.rect()).translated(m_offset); } diff --git a/src/quick/items/qquickdrag.cpp b/src/quick/items/qquickdrag.cpp index 4d46485718..2612b855bd 100644 --- a/src/quick/items/qquickdrag.cpp +++ b/src/quick/items/qquickdrag.cpp @@ -75,7 +75,7 @@ public: } void itemGeometryChanged(QQuickItem *, const QRectF &, const QRectF &) Q_DECL_OVERRIDE; - void itemParentChanged(QQuickItem *, QQuickItem *parent); + void itemParentChanged(QQuickItem *, QQuickItem *parent) Q_DECL_OVERRIDE; void updatePosition(); void restartDrag(); void deliverEnterEvent(); diff --git a/src/quick/items/qquickevents.cpp b/src/quick/items/qquickevents.cpp index 3ce4a8cb49..1380452718 100644 --- a/src/quick/items/qquickevents.cpp +++ b/src/quick/items/qquickevents.cpp @@ -323,7 +323,7 @@ Item { \qmlproperty point QtQuick::WheelEvent::pixelDelta This property holds the delta in screen pixels and is available in plataforms that - have high-resolution trackpads, such as Mac OS X. + have high-resolution trackpads, such as OS X. The x and y cordinate of this property holds the delta in horizontal and vertical orientation. The value should be used directly to scroll content on screen. diff --git a/src/quick/items/qquickflickable.cpp b/src/quick/items/qquickflickable.cpp index fc4a3efb8e..ea4398bc71 100644 --- a/src/quick/items/qquickflickable.cpp +++ b/src/quick/items/qquickflickable.cpp @@ -1004,7 +1004,8 @@ void QQuickFlickablePrivate::maybeBeginDrag(qint64 currentTimestamp, const QPoin } void QQuickFlickablePrivate::drag(qint64 currentTimestamp, QEvent::Type eventType, const QPointF &localPos, - const QVector2D &deltas, bool overThreshold, bool momentum, const QVector2D &velocity) + const QVector2D &deltas, bool overThreshold, bool momentum, + bool velocitySensitiveOverBounds, const QVector2D &velocity) { Q_Q(QQuickFlickable); bool rejectY = false; @@ -1061,9 +1062,13 @@ void QQuickFlickablePrivate::drag(qint64 currentTimestamp, QEvent::Type eventTyp } return; } - qreal overshoot = (newY - minY) * vData.velocity / QML_FLICK_DEFAULTMAXVELOCITY / QML_FLICK_OVERSHOOTFRICTION; - overshoot = QML_FLICK_OVERSHOOT * devicePixelRatio() * EaseOvershoot(overshoot / QML_FLICK_OVERSHOOT / devicePixelRatio()); - newY = minY + overshoot; + if (velocitySensitiveOverBounds) { + qreal overshoot = (newY - minY) * vData.velocity / QML_FLICK_DEFAULTMAXVELOCITY / QML_FLICK_OVERSHOOTFRICTION; + overshoot = QML_FLICK_OVERSHOOT * devicePixelRatio() * EaseOvershoot(overshoot / QML_FLICK_OVERSHOOT / devicePixelRatio()); + newY = minY + overshoot; + } else { + newY = minY + (newY - minY) / 2; + } } else if (newY < maxY && maxY - minY <= 0) { // Overshoot beyond the bottom. But don't wait for momentum phase to end before returning to bounds. if (momentum && vData.atEnd) { @@ -1073,9 +1078,13 @@ void QQuickFlickablePrivate::drag(qint64 currentTimestamp, QEvent::Type eventTyp } return; } - qreal overshoot = (newY - maxY) * vData.velocity / QML_FLICK_DEFAULTMAXVELOCITY / QML_FLICK_OVERSHOOTFRICTION; - overshoot = QML_FLICK_OVERSHOOT * devicePixelRatio() * EaseOvershoot(overshoot / QML_FLICK_OVERSHOOT / devicePixelRatio()); - newY = maxY - overshoot; + if (velocitySensitiveOverBounds) { + qreal overshoot = (newY - maxY) * vData.velocity / QML_FLICK_DEFAULTMAXVELOCITY / QML_FLICK_OVERSHOOTFRICTION; + overshoot = QML_FLICK_OVERSHOOT * devicePixelRatio() * EaseOvershoot(overshoot / QML_FLICK_OVERSHOOT / devicePixelRatio()); + newY = maxY - overshoot; + } else { + newY = maxY + (newY - maxY) / 2; + } } } if (!rejectY && stealMouse && dy != 0.0 && dy != vData.previousDragDelta) { @@ -1126,9 +1135,13 @@ void QQuickFlickablePrivate::drag(qint64 currentTimestamp, QEvent::Type eventTyp } return; } - qreal overshoot = (newX - minX) * hData.velocity / QML_FLICK_DEFAULTMAXVELOCITY / QML_FLICK_OVERSHOOTFRICTION; - overshoot = QML_FLICK_OVERSHOOT * devicePixelRatio() * EaseOvershoot(overshoot / QML_FLICK_OVERSHOOT / devicePixelRatio()); - newX = minX + overshoot; + if (velocitySensitiveOverBounds) { + qreal overshoot = (newX - minX) * hData.velocity / QML_FLICK_DEFAULTMAXVELOCITY / QML_FLICK_OVERSHOOTFRICTION; + overshoot = QML_FLICK_OVERSHOOT * devicePixelRatio() * EaseOvershoot(overshoot / QML_FLICK_OVERSHOOT / devicePixelRatio()); + newX = minX + overshoot; + } else { + newX = minX + (newX - minX) / 2; + } } else if (newX < maxX && maxX - minX <= 0) { // Overshoot beyond the right. But don't wait for momentum phase to end before returning to bounds. if (momentum && hData.atEnd) { @@ -1138,9 +1151,13 @@ void QQuickFlickablePrivate::drag(qint64 currentTimestamp, QEvent::Type eventTyp } return; } - qreal overshoot = (newX - maxX) * hData.velocity / QML_FLICK_DEFAULTMAXVELOCITY / QML_FLICK_OVERSHOOTFRICTION; - overshoot = QML_FLICK_OVERSHOOT * devicePixelRatio() * EaseOvershoot(overshoot / QML_FLICK_OVERSHOOT / devicePixelRatio()); - newX = maxX - overshoot; + if (velocitySensitiveOverBounds) { + qreal overshoot = (newX - maxX) * hData.velocity / QML_FLICK_DEFAULTMAXVELOCITY / QML_FLICK_OVERSHOOTFRICTION; + overshoot = QML_FLICK_OVERSHOOT * devicePixelRatio() * EaseOvershoot(overshoot / QML_FLICK_OVERSHOOT / devicePixelRatio()); + newX = maxX - overshoot; + } else { + newX = maxX + (newX - maxX) / 2; + } } } @@ -1210,7 +1227,7 @@ void QQuickFlickablePrivate::handleMouseMoveEvent(QMouseEvent *event) if (q->xflick()) overThreshold |= QQuickWindowPrivate::dragOverThreshold(deltas.x(), Qt::XAxis, event); - drag(currentTimestamp, event->type(), event->localPos(), deltas, overThreshold, false, velocity); + drag(currentTimestamp, event->type(), event->localPos(), deltas, overThreshold, false, false, velocity); } void QQuickFlickablePrivate::handleMouseReleaseEvent(QMouseEvent *event) @@ -1433,7 +1450,7 @@ void QQuickFlickable::wheelEvent(QWheelEvent *event) QVector2D velocity(xDelta / elapsed, yDelta / elapsed); d->lastPosTime = currentTimestamp; d->accumulatedWheelPixelDelta += QVector2D(event->pixelDelta()); - d->drag(currentTimestamp, event->type(), event->posF(), d->accumulatedWheelPixelDelta, true, !d->scrollingPhase, velocity); + d->drag(currentTimestamp, event->type(), event->posF(), d->accumulatedWheelPixelDelta, true, !d->scrollingPhase, true, velocity); event->accept(); } diff --git a/src/quick/items/qquickflickable_p_p.h b/src/quick/items/qquickflickable_p_p.h index d7148ca57a..65bb3e802d 100644 --- a/src/quick/items/qquickflickable_p_p.h +++ b/src/quick/items/qquickflickable_p_p.h @@ -250,7 +250,8 @@ public: void maybeBeginDrag(qint64 currentTimestamp, const QPointF &pressPosn); void drag(qint64 currentTimestamp, QEvent::Type eventType, const QPointF &localPos, - const QVector2D &deltas, bool overThreshold, bool momentum, const QVector2D &velocity); + const QVector2D &deltas, bool overThreshold, bool momentum, + bool velocitySensitiveOverBounds, const QVector2D &velocity); qint64 computeCurrentTime(QInputEvent *event); qreal devicePixelRatio(); diff --git a/src/quick/items/qquickframebufferobject.cpp b/src/quick/items/qquickframebufferobject.cpp index 18e786fea4..74abd8cf9f 100644 --- a/src/quick/items/qquickframebufferobject.cpp +++ b/src/quick/items/qquickframebufferobject.cpp @@ -329,11 +329,17 @@ QSGNode *QQuickFramebufferObject::updatePaintNode(QSGNode *node, UpdatePaintNode return n; } +/*! + \reimp +*/ bool QQuickFramebufferObject::isTextureProvider() const { return true; } +/*! + \reimp +*/ QSGTextureProvider *QQuickFramebufferObject::textureProvider() const { Q_D(const QQuickFramebufferObject); @@ -347,6 +353,9 @@ QSGTextureProvider *QQuickFramebufferObject::textureProvider() const return d->node; } +/*! + \reimp +*/ void QQuickFramebufferObject::releaseResources() { // When release resources is called on the GUI thread, we only need to diff --git a/src/quick/items/qquickgridview.cpp b/src/quick/items/qquickgridview.cpp index ff928a599f..3ac9c6eb1c 100644 --- a/src/quick/items/qquickgridview.cpp +++ b/src/quick/items/qquickgridview.cpp @@ -60,19 +60,19 @@ public: { } - qreal position() const { + qreal position() const Q_DECL_OVERRIDE { return rowPos(); } - qreal endPosition() const { + qreal endPosition() const Q_DECL_OVERRIDE { return endRowPos(); } - qreal size() const { + qreal size() const Q_DECL_OVERRIDE { return view->flow() == QQuickGridView::FlowLeftToRight ? view->cellHeight() : view->cellWidth(); } - qreal sectionSize() const { + qreal sectionSize() const Q_DECL_OVERRIDE { return 0.0; } diff --git a/src/quick/items/qquickimage_p.h b/src/quick/items/qquickimage_p.h index a780f9a626..421360bd35 100644 --- a/src/quick/items/qquickimage_p.h +++ b/src/quick/items/qquickimage_p.h @@ -88,7 +88,7 @@ public: bool mipmap() const; void setMipmap(bool use); - virtual void emitAutoTransformBaseChanged() { emit autoTransformChanged(); } + virtual void emitAutoTransformBaseChanged() Q_DECL_OVERRIDE { emit autoTransformChanged(); } Q_SIGNALS: void fillModeChanged(); diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp index 22290d4fc1..32c3e651dd 100644 --- a/src/quick/items/qquickitem.cpp +++ b/src/quick/items/qquickitem.cpp @@ -4321,7 +4321,6 @@ void QQuickItem::mapToItem(QQmlV4Function *args) const /*! \qmlmethod QtQuick::Item::forceActiveFocus() - \overload Forces active focus on the item. @@ -4334,6 +4333,18 @@ void QQuickItem::mapToItem(QQmlV4Function *args) const \sa activeFocus */ +/*! + Forces active focus on the item. + + This method sets focus on the item and ensures that all ancestor + FocusScope objects in the object hierarchy are also given \l focus. + + The reason for the focus change will be \l [CPP] Qt::OtherFocusReason. Use + the overloaded method to specify the focus reason to enable better + handling of the focus change. + + \sa activeFocus +*/ void QQuickItem::forceActiveFocus() { forceActiveFocus(Qt::OtherFocusReason); @@ -4341,7 +4352,19 @@ void QQuickItem::forceActiveFocus() /*! \qmlmethod QtQuick::Item::forceActiveFocus(Qt::FocusReason reason) + \overload + + Forces active focus on the item with the given \a reason. + + This method sets focus on the item and ensures that all ancestor + FocusScope objects in the object hierarchy are also given \l focus. + \since 5.1 + + \sa activeFocus, Qt::FocusReason +*/ +/*! + \overload Forces active focus on the item with the given \a reason. This method sets focus on the item and ensures that all ancestor diff --git a/src/quick/items/qquickitemview_p_p.h b/src/quick/items/qquickitemview_p_p.h index f535963fdb..0931db4e56 100644 --- a/src/quick/items/qquickitemview_p_p.h +++ b/src/quick/items/qquickitemview_p_p.h @@ -180,7 +180,7 @@ public: void regenerate(bool orientationChanged=false); void layout(); - virtual void animationFinished(QAbstractAnimationJob *); + virtual void animationFinished(QAbstractAnimationJob *) Q_DECL_OVERRIDE; void refill(); void refill(qreal from, qreal to); void mirrorChange() Q_DECL_OVERRIDE; diff --git a/src/quick/items/qquicklistview.cpp b/src/quick/items/qquicklistview.cpp index b08a8cfffe..a1d765d6ec 100644 --- a/src/quick/items/qquicklistview.cpp +++ b/src/quick/items/qquicklistview.cpp @@ -255,7 +255,7 @@ public: static_cast<QQuickListViewAttached*>(attached)->m_sectionItem = s; } - qreal position() const { + qreal position() const Q_DECL_OVERRIDE { if (section()) { if (view->orientation() == QQuickListView::Vertical) return (view->verticalLayoutDirection() == QQuickItemView::BottomToTop ? -section()->height()-section()->y() : section()->y()); @@ -271,7 +271,7 @@ public: else return (view->effectiveLayoutDirection() == Qt::RightToLeft ? -itemWidth()-itemX() : itemX()); } - qreal size() const { + qreal size() const Q_DECL_OVERRIDE { if (section()) return (view->orientation() == QQuickListView::Vertical ? itemHeight()+section()->height() : itemWidth()+section()->width()); else @@ -280,12 +280,12 @@ public: qreal itemSize() const { return (view->orientation() == QQuickListView::Vertical ? itemHeight() : itemWidth()); } - qreal sectionSize() const { + qreal sectionSize() const Q_DECL_OVERRIDE { if (section()) return (view->orientation() == QQuickListView::Vertical ? section()->height() : section()->width()); return 0.0; } - qreal endPosition() const { + qreal endPosition() const Q_DECL_OVERRIDE { if (view->orientation() == QQuickListView::Vertical) { return (view->verticalLayoutDirection() == QQuickItemView::BottomToTop ? -itemY() diff --git a/src/quick/items/qquickpainteditem.cpp b/src/quick/items/qquickpainteditem.cpp index b3e4906c41..8d93c577ab 100644 --- a/src/quick/items/qquickpainteditem.cpp +++ b/src/quick/items/qquickpainteditem.cpp @@ -549,6 +549,9 @@ QSGNode *QQuickPaintedItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeDat return node; } +/*! + \reimp +*/ void QQuickPaintedItem::releaseResources() { Q_D(QQuickPaintedItem); @@ -567,11 +570,17 @@ void QQuickPaintedItem::invalidateSceneGraph() d->node = 0; // Managed by the scene graph, just clear the pointer } +/*! + \reimp +*/ bool QQuickPaintedItem::isTextureProvider() const { return true; } +/*! + \reimp +*/ QSGTextureProvider *QQuickPaintedItem::textureProvider() const { Q_D(const QQuickPaintedItem); diff --git a/src/quick/items/qquickrendercontrol.cpp b/src/quick/items/qquickrendercontrol.cpp index e81edecde9..cc4cec443a 100644 --- a/src/quick/items/qquickrendercontrol.cpp +++ b/src/quick/items/qquickrendercontrol.cpp @@ -140,6 +140,10 @@ void QQuickRenderControlPrivate::cleanup() sg = 0; } +/*! + Constructs a QQuickRenderControl object, with parent + object \a parent. +*/ QQuickRenderControl::QQuickRenderControl(QObject *parent) : QObject(*(new QQuickRenderControlPrivate), parent) { diff --git a/src/quick/items/qquicktext.cpp b/src/quick/items/qquicktext.cpp index a91e6b47c2..924c455872 100644 --- a/src/quick/items/qquicktext.cpp +++ b/src/quick/items/qquicktext.cpp @@ -100,6 +100,7 @@ QQuickTextPrivate::ExtraData::ExtraData() , minimumPointSize(12) , nbActiveDownloads(0) , maximumLineCount(INT_MAX) + , lineHeightValid(false) , lineHeightMode(QQuickText::ProportionalHeight) , fontSizeMode(QQuickText::FixedSize) { @@ -421,7 +422,7 @@ void QQuickTextPrivate::updateLayout() } textHasChanged = false; } - } else { + } else if (extra.isAllocated() && extra->lineHeightValid) { ensureDoc(); QTextBlockFormat::LineHeightTypes type; type = lineHeightMode() == QQuickText::FixedHeight ? QTextBlockFormat::FixedHeight : QTextBlockFormat::ProportionalHeight; @@ -2480,6 +2481,7 @@ void QQuickText::setLineHeight(qreal lineHeight) if ((d->lineHeight() == lineHeight) || (lineHeight < 0.0)) return; + d->extra.value().lineHeightValid = true; d->extra.value().lineHeight = lineHeight; d->implicitHeightValid = false; d->updateLayout(); @@ -2511,6 +2513,7 @@ void QQuickText::setLineHeightMode(LineHeightMode mode) return; d->implicitHeightValid = false; + d->extra.value().lineHeightValid = true; d->extra.value().lineHeightMode = mode; d->updateLayout(); diff --git a/src/quick/items/qquicktext_p_p.h b/src/quick/items/qquicktext_p_p.h index f0469fc8ea..f43df691b5 100644 --- a/src/quick/items/qquicktext_p_p.h +++ b/src/quick/items/qquicktext_p_p.h @@ -104,6 +104,7 @@ public: int minimumPointSize; int nbActiveDownloads; int maximumLineCount; + bool lineHeightValid : 1; QQuickText::LineHeightMode lineHeightMode; QQuickText::FontSizeMode fontSizeMode; QList<QQuickStyledTextImgTag*> imgTags; diff --git a/src/quick/items/qquicktextcontrol.cpp b/src/quick/items/qquicktextcontrol.cpp index 19cdc388f1..7bc5fab677 100644 --- a/src/quick/items/qquicktextcontrol.cpp +++ b/src/quick/items/qquicktextcontrol.cpp @@ -225,7 +225,7 @@ bool QQuickTextControlPrivate::cursorMoveKeyEvent(QKeyEvent *e) return false; } -// Except for pageup and pagedown, Mac OS X has very different behavior, we don't do it all, but +// Except for pageup and pagedown, OS X has very different behavior, we don't do it all, but // here's the breakdown: // Shift still works as an anchor, but only one of the other keys can be down Ctrl (Command), // Alt (Option), or Meta (Control). diff --git a/src/quick/items/qquicktextedit.cpp b/src/quick/items/qquicktextedit.cpp index cf7e91ffec..dc4e301a36 100644 --- a/src/quick/items/qquicktextedit.cpp +++ b/src/quick/items/qquicktextedit.cpp @@ -1961,13 +1961,6 @@ QSGNode *QQuickTextEdit::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData * engine.addTextObject(QPointF(0, 0), format, QQuickTextNodeEngine::Unselected, d->document, pos, textFrame->frameFormat().position()); nodeStart = pos; - } else if (qobject_cast<QTextTable*>(textFrame)) { // To keep things simple, map text tables as one text node - QTextFrame::iterator it = textFrame->begin(); - nodeOffset = d->document->documentLayout()->frameBoundingRect(textFrame).topLeft(); - updateNodeTransform(node, nodeOffset); - while (!it.atEnd()) - engine.addTextBlock(d->document, (it++).currentBlock(), -nodeOffset, d->color, QColor(), selectionStart(), selectionEnd() - 1); - nodeStart = textFrame->firstPosition(); } else { // Having nodes spanning across frame boundaries will break the current bookkeeping mechanism. We need to prevent that. QList<int> frameBoundaries; diff --git a/src/quick/items/qquicktextinput.cpp b/src/quick/items/qquicktextinput.cpp index 31549451ab..c29acf3c83 100644 --- a/src/quick/items/qquicktextinput.cpp +++ b/src/quick/items/qquicktextinput.cpp @@ -78,7 +78,7 @@ DEFINE_BOOL_CONFIG_OPTION(qmlDisableDistanceField, QML_DISABLE_DISTANCEFIELD) and setting \l echoMode to an appropriate value enables TextInput to be used for a password input field. - On Mac OS X, the Up/Down key bindings for Home/End are explicitly disabled. + On OS X, the Up/Down key bindings for Home/End are explicitly disabled. If you want such bindings (on any platform), you will need to construct them in QML. \sa TextEdit, Text diff --git a/src/quick/items/qquicktextnodeengine.cpp b/src/quick/items/qquicktextnodeengine.cpp index 204b135b8c..2b7f94d8bf 100644 --- a/src/quick/items/qquicktextnodeengine.cpp +++ b/src/quick/items/qquicktextnodeengine.cpp @@ -596,7 +596,6 @@ void QQuickTextNodeEngine::addGlyphsInRange(int rangeStart, int rangeLength, for (int j=0; j<glyphRuns.size(); ++j) { const QGlyphRun &glyphRun = glyphRuns.at(j); addSelectedGlyphs(glyphRun); - addUnselectedGlyphs(glyphRun); } } @@ -762,11 +761,10 @@ void QQuickTextNodeEngine::addToSceneGraph(QQuickTextNode *parentNode, parentNode->addRectangleNode(rect, color); } - // Add all unselected text first + // Add all text with unselected color first for (int i = 0; i < nodes.size(); ++i) { const BinaryTreeNode *node = nodes.at(i); - if (node->selectionState == Unselected) - parentNode->addGlyphs(node->position, node->glyphRun, node->color, style, styleColor, 0); + parentNode->addGlyphs(node->position, node->glyphRun, node->color, style, styleColor, 0); } for (int i = 0; i < imageNodes.size(); ++i) { @@ -823,14 +821,14 @@ void QQuickTextNodeEngine::addToSceneGraph(QQuickTextNode *parentNode, for (int i = 0; i < node->ranges.size(); ++i) { const QPair<int, int> &range = node->ranges.at(i); - int rangeLength = range.second - range.first + 1; + int rangeLength = range.second - range.first; if (previousNode != 0) { for (int j = 0; j < previousNode->ranges.size(); ++j) { const QPair<int, int> &otherRange = previousNode->ranges.at(j); - if (range.first <= otherRange.second && range.second >= otherRange.first) { + if (range.first < otherRange.second && range.second > otherRange.first) { int start = qMax(range.first, otherRange.first); int end = qMin(range.second, otherRange.second); - rangeLength -= end - start + 1; + rangeLength -= end - start; if (rangeLength == 0) break; } @@ -841,10 +839,10 @@ void QQuickTextNodeEngine::addToSceneGraph(QQuickTextNode *parentNode, for (int j = 0; j < nextNode->ranges.size(); ++j) { const QPair<int, int> &otherRange = nextNode->ranges.at(j); - if (range.first <= otherRange.second && range.second >= otherRange.first) { + if (range.first < otherRange.second && range.second > otherRange.first) { int start = qMax(range.first, otherRange.first); int end = qMin(range.second, otherRange.second); - rangeLength -= end - start + 1; + rangeLength -= end - start; if (rangeLength == 0) break; } diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp index 501b1073a7..99dbf1d83e 100644 --- a/src/quick/items/qquickwindow.cpp +++ b/src/quick/items/qquickwindow.cpp @@ -112,7 +112,7 @@ public: } protected: - void timerEvent(QTimerEvent *) + void timerEvent(QTimerEvent *) Q_DECL_OVERRIDE { killTimer(m_timer); m_timer = 0; @@ -1110,7 +1110,6 @@ QQuickWindow::~QQuickWindow() { Q_D(QQuickWindow); - d->animationController->deleteLater(); if (d->renderControl) { QQuickRenderControlPrivate::get(d->renderControl)->windowDestroyed(); } else if (d->windowManager) { @@ -3524,7 +3523,7 @@ QQmlIncubationController *QQuickWindow::incubationController() const slot function needs to finish before execution continues, you must make sure that the connection is direct (see Qt::ConnectionType). - \warning Make very sure that a signal handler for afterRendering() leaves the GL + \warning Make very sure that a signal handler for sceneGraphAboutToStop() leaves the GL context in the same state as it was when the signal handler was entered. Failing to do so can result in the scene not rendering properly. diff --git a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp index 6d0ed4ce9f..8632ea0b52 100644 --- a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp +++ b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp @@ -1523,6 +1523,7 @@ void Renderer::prepareOpaqueBatches() if (gni->clipList() == gnj->clipList() && gni->geometry()->drawingMode() == gnj->geometry()->drawingMode() + && (gni->geometry()->drawingMode() != GL_LINES || gni->geometry()->lineWidth() == gnj->geometry()->lineWidth()) && gni->geometry()->attributes() == gnj->geometry()->attributes() && gni->inheritedOpacity() == gnj->inheritedOpacity() && gni->activeMaterial()->type() == gnj->activeMaterial()->type() @@ -1621,6 +1622,7 @@ void Renderer::prepareAlphaBatches() if (gni->clipList() == gnj->clipList() && gni->geometry()->drawingMode() == gnj->geometry()->drawingMode() + && (gni->geometry()->drawingMode() != GL_LINES || gni->geometry()->lineWidth() == gnj->geometry()->lineWidth()) && gni->geometry()->attributes() == gnj->geometry()->attributes() && gni->inheritedOpacity() == gnj->inheritedOpacity() && gni->activeMaterial()->type() == gnj->activeMaterial()->type() @@ -2283,6 +2285,7 @@ void Renderer::renderMergedBatch(const Batch *batch) m_currentMaterial = material; QSGGeometry* g = gn->geometry(); + updateLineWidth(g); char const *const *attrNames = program->attributeNames(); for (int i=0; i<batch->drawSets.size(); ++i) { const DrawSet &draw = batch->drawSets.at(i); @@ -2413,24 +2416,7 @@ void Renderer::renderUnmergedBatch(const Batch *batch) offset += a.tupleSize * size_of_type(a.type); } - if (g->drawingMode() == GL_LINE_STRIP || g->drawingMode() == GL_LINE_LOOP || g->drawingMode() == GL_LINES) - glLineWidth(g->lineWidth()); -#if !defined(QT_OPENGL_ES_2) - else if (!QOpenGLContext::currentContext()->isOpenGLES() && g->drawingMode() == GL_POINTS) { - QOpenGLFunctions_1_0 *gl1funcs = 0; - QOpenGLFunctions_3_2_Core *gl3funcs = 0; - if (QOpenGLContext::currentContext()->format().profile() == QSurfaceFormat::CoreProfile) - gl3funcs = QOpenGLContext::currentContext()->versionFunctions<QOpenGLFunctions_3_2_Core>(); - else - gl1funcs = QOpenGLContext::currentContext()->versionFunctions<QOpenGLFunctions_1_0>(); - Q_ASSERT(gl1funcs || gl3funcs); - if (gl1funcs) - gl1funcs->glPointSize(g->lineWidth()); - else - gl3funcs->glPointSize(g->lineWidth()); - } -#endif - + updateLineWidth(g); if (g->indexCount()) glDrawElements(g->drawingMode(), g->indexCount(), g->indexType(), iOffset); else @@ -2446,6 +2432,27 @@ void Renderer::renderUnmergedBatch(const Batch *batch) } } +void Renderer::updateLineWidth(QSGGeometry *g) +{ + if (g->drawingMode() == GL_LINE_STRIP || g->drawingMode() == GL_LINE_LOOP || g->drawingMode() == GL_LINES) + glLineWidth(g->lineWidth()); +#if !defined(QT_OPENGL_ES_2) + else if (!QOpenGLContext::currentContext()->isOpenGLES() && g->drawingMode() == GL_POINTS) { + QOpenGLFunctions_1_0 *gl1funcs = 0; + QOpenGLFunctions_3_2_Core *gl3funcs = 0; + if (QOpenGLContext::currentContext()->format().profile() == QSurfaceFormat::CoreProfile) + gl3funcs = QOpenGLContext::currentContext()->versionFunctions<QOpenGLFunctions_3_2_Core>(); + else + gl1funcs = QOpenGLContext::currentContext()->versionFunctions<QOpenGLFunctions_1_0>(); + Q_ASSERT(gl1funcs || gl3funcs); + if (gl1funcs) + gl1funcs->glPointSize(g->lineWidth()); + else + gl3funcs->glPointSize(g->lineWidth()); + } +#endif +} + void Renderer::renderBatches() { if (Q_UNLIKELY(debug_render())) { diff --git a/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h b/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h index c7b5f73688..d19fa0e17d 100644 --- a/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h +++ b/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h @@ -603,6 +603,7 @@ private: void nodeWasRemoved(Node *node); void nodeWasAdded(QSGNode *node, Node *shadowParent); BatchRootInfo *batchRootInfo(Node *node); + void updateLineWidth(QSGGeometry *g); inline Batch *newBatch(); void invalidateAndRecycleBatch(Batch *b); diff --git a/src/quick/scenegraph/coreapi/qsggeometry.cpp b/src/quick/scenegraph/coreapi/qsggeometry.cpp index 3f54e13c52..1fd37be84a 100644 --- a/src/quick/scenegraph/coreapi/qsggeometry.cpp +++ b/src/quick/scenegraph/coreapi/qsggeometry.cpp @@ -522,7 +522,8 @@ void QSGGeometry::setDrawingMode(GLenum mode) /*! Gets the current line or point width or to be used for this geometry. This property only applies to line width when the drawingMode is \c GL_LINES, \c GL_LINE_STRIP, or - \c GL_LINE_LOOP, and only applies to point size when the drawingMode is \c GL_POINTS. + \c GL_LINE_LOOP. For desktop OpenGL, it also applies to point size when the drawingMode + is \c GL_POINTS. The default value is \c 1.0 @@ -536,7 +537,12 @@ float QSGGeometry::lineWidth() const /*! Sets the line or point width to be used for this geometry to \a width. This property only applies to line width when the drawingMode is \c GL_LINES, \c GL_LINE_STRIP, or - \c GL_LINE_LOOP, and only applies to point size when the drawingMode is \c GL_POINTS. + \c GL_LINE_LOOP. For Desktop OpenGL, it also applies to point size when the drawingMode + is \c GL_POINTS. + + \note How line width and point size are treated is implementation dependent: The application + should not rely on these, but rather create triangles or similar to draw areas. On OpenGL ES, + line width support is limited and point size is unsupported. \sa lineWidth(), drawingMode() */ diff --git a/src/quick/scenegraph/coreapi/qsgnode.cpp b/src/quick/scenegraph/coreapi/qsgnode.cpp index 71f4f62db9..51f3976ed9 100644 --- a/src/quick/scenegraph/coreapi/qsgnode.cpp +++ b/src/quick/scenegraph/coreapi/qsgnode.cpp @@ -806,7 +806,7 @@ void QSGBasicGeometryNode::setGeometry(QSGGeometry *geometry) the vertices and their structure, to be drawn. The Material defines how the shape is filled. - The following is a code snipped illustrating how to create a red + The following is a code snippet illustrating how to create a red line using a QSGGeometryNode: \code QSGGeometry *geometry = new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), 2); diff --git a/src/quick/scenegraph/qsgrenderloop.cpp b/src/quick/scenegraph/qsgrenderloop.cpp index 6c7fb89b6f..3059b750f2 100644 --- a/src/quick/scenegraph/qsgrenderloop.cpp +++ b/src/quick/scenegraph/qsgrenderloop.cpp @@ -34,6 +34,7 @@ #include "qsgrenderloop_p.h" #include "qsgthreadedrenderloop_p.h" #include "qsgwindowsrenderloop_p.h" +#include <private/qquickanimatorcontroller_p.h> #include <QtCore/QCoreApplication> #include <QtCore/QTime> @@ -321,6 +322,8 @@ void QSGGuiThreadRenderLoop::windowDestroyed(QQuickWindow *window) } else if (gl && window == gl->surface() && current) { gl->doneCurrent(); } + + delete d->animationController; } void QSGGuiThreadRenderLoop::renderWindow(QQuickWindow *window) diff --git a/src/quick/scenegraph/qsgthreadedrenderloop.cpp b/src/quick/scenegraph/qsgthreadedrenderloop.cpp index 9a7407b421..4b78fefa99 100644 --- a/src/quick/scenegraph/qsgthreadedrenderloop.cpp +++ b/src/quick/scenegraph/qsgthreadedrenderloop.cpp @@ -477,11 +477,12 @@ void QSGRenderThread::invalidateOpenGL(QQuickWindow *window, bool inDestructor, qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "- cleanup without an OpenGL context"; } + QQuickWindowPrivate *dd = QQuickWindowPrivate::get(window); + QQuickShaderEffectMaterial::cleanupMaterialCache(); // The canvas nodes must be cleaned up regardless if we are in the destructor.. if (wipeSG) { - QQuickWindowPrivate *dd = QQuickWindowPrivate::get(window); dd->cleanupNodesOnShutdown(); } else { qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "- persistent SG, avoiding cleanup"; @@ -493,6 +494,8 @@ void QSGRenderThread::invalidateOpenGL(QQuickWindow *window, bool inDestructor, sgrc->invalidate(); QCoreApplication::processEvents(); QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete); + if (inDestructor) + delete dd->animationController; if (current) gl->doneCurrent(); qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "- invalidating scene graph"; diff --git a/src/quick/scenegraph/qsgwindowsrenderloop.cpp b/src/quick/scenegraph/qsgwindowsrenderloop.cpp index c571e60018..7fd9651618 100644 --- a/src/quick/scenegraph/qsgwindowsrenderloop.cpp +++ b/src/quick/scenegraph/qsgwindowsrenderloop.cpp @@ -32,7 +32,6 @@ ****************************************************************************/ #include "qsgwindowsrenderloop_p.h" - #include <QtCore/QCoreApplication> #include <QtCore/QLibraryInfo> #include <QtCore/QThread> @@ -47,8 +46,8 @@ #include <QtQuick/QQuickWindow> #include <private/qquickprofiler_p.h> - #include <private/qquickshadereffectnode_p.h> +#include <private/qquickanimatorcontroller_p.h> QT_BEGIN_NAMESPACE @@ -219,6 +218,7 @@ void QSGWindowsRenderLoop::windowDestroyed(QQuickWindow *window) hide(window); QQuickWindowPrivate *d = QQuickWindowPrivate::get(window); + bool current = false; QScopedPointer<QOffscreenSurface> offscreenSurface; if (m_gl) { @@ -245,6 +245,8 @@ void QSGWindowsRenderLoop::windowDestroyed(QQuickWindow *window) } else if (m_gl && current) { m_gl->doneCurrent(); } + + delete d->animationController; } bool QSGWindowsRenderLoop::anyoneShowing() const diff --git a/src/quick/scenegraph/util/qsgsimpletexturenode.cpp b/src/quick/scenegraph/util/qsgsimpletexturenode.cpp index 8d38e83029..d9f3c44374 100644 --- a/src/quick/scenegraph/util/qsgsimpletexturenode.cpp +++ b/src/quick/scenegraph/util/qsgsimpletexturenode.cpp @@ -223,9 +223,11 @@ QRectF QSGSimpleTextureNode::sourceRect() const void QSGSimpleTextureNode::setTexture(QSGTexture *texture) { Q_ASSERT(texture); + Q_D(QSGSimpleTextureNode); + if (d->ownsTexture) + delete m_material.texture(); m_material.setTexture(texture); m_opaque_material.setTexture(texture); - Q_D(QSGSimpleTextureNode); qsgsimpletexturenode_update(&m_geometry, texture, m_rect, d->sourceRect, d->texCoordMode); DirtyState dirty = DirtyMaterial; diff --git a/src/quick/util/qquickanimatorjob.cpp b/src/quick/util/qquickanimatorjob.cpp index 016f41d436..0182f8abfb 100644 --- a/src/quick/util/qquickanimatorjob.cpp +++ b/src/quick/util/qquickanimatorjob.cpp @@ -135,7 +135,7 @@ void QQuickAnimatorProxyJob::updateState(QAbstractAnimationJob::State newState, void QQuickAnimatorProxyJob::debugAnimation(QDebug d) const { - d << "QuickAnimatorProxyJob("<< hex << (void *) this << dec + d << "QuickAnimatorProxyJob("<< hex << (const void *) this << dec << "state:" << state() << "duration:" << duration() << "proxying: (" << job() << ')'; } @@ -224,7 +224,7 @@ QQuickAnimatorJob::QQuickAnimatorJob() void QQuickAnimatorJob::debugAnimation(QDebug d) const { - d << "QuickAnimatorJob(" << hex << (void *) this << dec + d << "QuickAnimatorJob(" << hex << (const void *) this << dec << ") state:" << state() << "duration:" << duration() << "target:" << m_target << "value:" << m_value; } diff --git a/src/quick/util/qquickanimatorjob_p.h b/src/quick/util/qquickanimatorjob_p.h index 34c106e89b..ca70aecb8e 100644 --- a/src/quick/util/qquickanimatorjob_p.h +++ b/src/quick/util/qquickanimatorjob_p.h @@ -63,7 +63,7 @@ public: QQuickAnimatorProxyJob(QAbstractAnimationJob *job, QObject *item); ~QQuickAnimatorProxyJob(); - int duration() const { return m_duration; } + int duration() const Q_DECL_OVERRIDE { return m_duration; } QAbstractAnimationJob *job() const { return m_job; } @@ -72,8 +72,8 @@ public: void markJobManagedByController() { m_jobManagedByController = true; } protected: - void updateCurrentTime(int); - void updateState(QAbstractAnimationJob::State newState, QAbstractAnimationJob::State oldState); + void updateCurrentTime(int) Q_DECL_OVERRIDE; + void updateState(QAbstractAnimationJob::State newState, QAbstractAnimationJob::State oldState) Q_DECL_OVERRIDE; void debugAnimation(QDebug d) const Q_DECL_OVERRIDE; public Q_SLOTS: @@ -116,7 +116,7 @@ public: qreal to() const { return m_to; } void setDuration(int duration) { m_duration = duration; } - int duration() const { return m_duration; } + int duration() const Q_DECL_OVERRIDE { return m_duration; } QEasingCurve easingCurve() const { return m_easing; } void setEasingCurve(const QEasingCurve &curve) { m_easing = curve; } diff --git a/src/quick/util/qquickprofiler_p.h b/src/quick/util/qquickprofiler_p.h index 2eec9bf877..6b6e7fa062 100644 --- a/src/quick/util/qquickprofiler_p.h +++ b/src/quick/util/qquickprofiler_p.h @@ -259,7 +259,7 @@ public: } template<SceneGraphFrameType FrameType, bool Record> - static void reportSceneGraphFrame(quint64 payload = -1) + static void reportSceneGraphFrame(quint64 payload = ~0) { qint64 *timings = s_instance->m_sceneGraphData.timings<FrameType>(); int &offset = s_instance->m_sceneGraphData.offset<FrameType>(); @@ -275,7 +275,7 @@ public: } template<SceneGraphFrameType FrameType, bool Record, SceneGraphFrameType SwitchTo> - static void reportSceneGraphFrame(quint64 payload = -1) + static void reportSceneGraphFrame(quint64 payload = ~0) { reportSceneGraphFrame<FrameType, Record>(payload); s_instance->m_sceneGraphData.offset<SwitchTo>() = 0; diff --git a/src/quick/util/qquickstyledtext.cpp b/src/quick/util/qquickstyledtext.cpp index 6b1768e9ef..c411207121 100644 --- a/src/quick/util/qquickstyledtext.cpp +++ b/src/quick/util/qquickstyledtext.cpp @@ -542,6 +542,12 @@ void QQuickStyledTextPrivate::parseEntity(const QChar *&ch, const QString &textI textOut += QChar(38); else if (entity == QLatin1String("quot")) textOut += QChar(34); + else if (entity == QLatin1String("nbsp")) + textOut += QChar(QChar::Nbsp); + return; + } else if (*ch == QLatin1Char(' ')) { + QStringRef entity(&textIn, entityStart - 1, entityLength + 1); + textOut += entity + *ch; return; } ++entityLength; diff --git a/src/quickwidgets/qquickwidget_p.h b/src/quickwidgets/qquickwidget_p.h index 9249fa138b..fa8bb3beb7 100644 --- a/src/quickwidgets/qquickwidget_p.h +++ b/src/quickwidgets/qquickwidget_p.h @@ -70,7 +70,7 @@ public: ~QQuickWidgetPrivate(); void execute(); - void itemGeometryChanged(QQuickItem *item, const QRectF &newGeometry, const QRectF &oldGeometry); + void itemGeometryChanged(QQuickItem *item, const QRectF &newGeometry, const QRectF &oldGeometry) Q_DECL_OVERRIDE; void initResize(); void updateSize(); void updatePosition(); @@ -82,7 +82,7 @@ public: void destroyContext(); void handleContextCreationFailure(const QSurfaceFormat &format, bool isEs); - QObject *focusObject(); + QObject *focusObject() Q_DECL_OVERRIDE; GLuint textureId() const Q_DECL_OVERRIDE; QImage grabFramebuffer() Q_DECL_OVERRIDE; |