aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLiang Qi <liang.qi@qt.io>2018-01-19 10:49:56 +0100
committerLiang Qi <liang.qi@qt.io>2018-01-24 09:34:11 +0100
commit2570b801c74832a3c83a8b56ad0f76812969e190 (patch)
treec4bd64d8e6b15b507f51f550ba13a0c062528d65 /src
parent1b96186d1418adcba85fdbfd794da2d2f6ea122d (diff)
parent706a6647db695cdeb854ef1bf956ded56b498f78 (diff)
Merge remote-tracking branch 'origin/5.9' into 5.10
Conflicts: .qmake.conf src/qml/compiler/qv4codegen.cpp src/qml/compiler/qv4compileddata_p.h src/qml/debugger/qqmlprofiler_p.h src/qml/jsruntime/qv4engine.cpp src/qml/memory/qv4mm.cpp src/qml/qml/qqmlcomponent.cpp src/qml/qml/qqmlobjectcreator.cpp src/qml/qml/qqmlobjectcreator_p.h src/qml/types/qqmldelegatemodel.cpp src/quick/items/qquickitem_p.h src/quick/items/qquickwindow.cpp tests/auto/quick/touchmouse/BLACKLIST tests/benchmarks/qml/holistic/tst_holistic.cpp Change-Id: I520f349ab4b048dd337d9647113564fc257865c2
Diffstat (limited to 'src')
-rw-r--r--src/3rdparty/masm/assembler/ARM64Assembler.h7
-rw-r--r--src/3rdparty/masm/wtf/MathExtras.h5
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp21
-rw-r--r--src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.cpp32
-rw-r--r--src/qml/compiler/qqmlirbuilder.cpp11
-rw-r--r--src/qml/compiler/qqmlirbuilder_p.h7
-rw-r--r--src/qml/compiler/qqmltypecompiler.cpp11
-rw-r--r--src/qml/compiler/qv4codegen.cpp4
-rw-r--r--src/qml/compiler/qv4codegen_p.h8
-rw-r--r--src/qml/compiler/qv4compileddata.cpp3
-rw-r--r--src/qml/compiler/qv4compileddata_p.h22
-rw-r--r--src/qml/compiler/qv4compiler.cpp2
-rw-r--r--src/qml/compiler/qv4isel_moth.cpp6
-rw-r--r--src/qml/compiler/qv4jsir.cpp10
-rw-r--r--src/qml/compiler/qv4jsir_p.h11
-rw-r--r--src/qml/debugger/qqmlprofiler_p.h14
-rw-r--r--src/qml/doc/src/includes/qqmlcomponent.qdoc58
-rw-r--r--src/qml/doc/src/qmllanguageref/syntax/objectattributes.qdoc39
-rw-r--r--src/qml/jit/qv4isel_masm.cpp6
-rw-r--r--src/qml/jsruntime/qv4engine.cpp6
-rw-r--r--src/qml/jsruntime/qv4enginebase_p.h2
-rw-r--r--src/qml/jsruntime/qv4function_p.h1
-rw-r--r--src/qml/jsruntime/qv4functionobject.cpp2
-rw-r--r--src/qml/jsruntime/qv4global_p.h4
-rw-r--r--src/qml/jsruntime/qv4qmlcontext_p.h2
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper.cpp6
-rw-r--r--src/qml/jsruntime/qv4script.cpp14
-rw-r--r--src/qml/jsruntime/qv4script_p.h6
-rw-r--r--src/qml/memory/qv4mm.cpp151
-rw-r--r--src/qml/memory/qv4mm_p.h25
-rw-r--r--src/qml/qml/qqmlcomponent.cpp35
-rw-r--r--src/qml/qml/qqmlcontext.cpp4
-rw-r--r--src/qml/qml/qqmldata_p.h31
-rw-r--r--src/qml/qml/qqmlengine.cpp60
-rw-r--r--src/qml/qml/qqmlincubator.cpp19
-rw-r--r--src/qml/qml/qqmlincubator_p.h3
-rw-r--r--src/qml/qml/qqmlobjectcreator.cpp27
-rw-r--r--src/qml/qml/qqmlobjectcreator_p.h12
-rw-r--r--src/qml/qml/qqmlproperty.cpp150
-rw-r--r--src/qml/qml/qqmlproperty_p.h2
-rw-r--r--src/qml/qml/qqmltypeloader.cpp80
-rw-r--r--src/qml/qml/qqmltypeloader_p.h2
-rw-r--r--src/qml/qml/qqmlvme.cpp12
-rw-r--r--src/qml/qml/qqmlvme_p.h1
-rw-r--r--src/qml/types/qqmldelegatemodel.cpp12
-rw-r--r--src/quick/items/qquickanimatedimage.cpp114
-rw-r--r--src/quick/items/qquickanimatedimage_p_p.h21
-rw-r--r--src/quick/items/qquickflickable.cpp14
-rw-r--r--src/quick/items/qquickflickable_p_p.h4
-rw-r--r--src/quick/items/qquickframebufferobject.cpp1
-rw-r--r--src/quick/items/qquickgridview.cpp14
-rw-r--r--src/quick/items/qquickitem.cpp35
-rw-r--r--src/quick/items/qquickitem_p.h3
-rw-r--r--src/quick/items/qquickitemsmodule.cpp6
-rw-r--r--src/quick/items/qquickitemview.cpp76
-rw-r--r--src/quick/items/qquickitemviewtransition_p.h18
-rw-r--r--src/quick/items/qquicklistview.cpp3
-rw-r--r--src/quick/items/qquickloader.cpp2
-rw-r--r--src/quick/items/qquickrepeater.cpp5
-rw-r--r--src/quick/items/qquickwindow.cpp50
-rw-r--r--src/quick/items/qquickwindow.h6
-rw-r--r--src/quick/items/qquickwindowmodule.cpp2
-rw-r--r--src/quick/scenegraph/adaptations/software/qsgabstractsoftwarerenderer.cpp10
-rw-r--r--src/quick/scenegraph/adaptations/software/qsgabstractsoftwarerenderer_p.h4
-rw-r--r--src/quick/scenegraph/adaptations/software/qsgsoftwarepixmaprenderer.cpp2
-rw-r--r--src/quick/scenegraph/adaptations/software/qsgsoftwarerenderer.cpp3
-rw-r--r--src/quick/util/qquickpropertychanges.cpp33
-rw-r--r--src/quick/util/qquickshortcut.cpp3
-rw-r--r--src/quick/util/qquickstate.cpp5
-rw-r--r--src/quick/util/qquickstate_p.h4
-rw-r--r--src/quick/util/qquicktransition.cpp29
-rw-r--r--src/quick/util/qquicktransition_p.h15
-rw-r--r--src/quickwidgets/qquickwidget.cpp53
73 files changed, 882 insertions, 599 deletions
diff --git a/src/3rdparty/masm/assembler/ARM64Assembler.h b/src/3rdparty/masm/assembler/ARM64Assembler.h
index 7390997af1..008f03bccf 100644
--- a/src/3rdparty/masm/assembler/ARM64Assembler.h
+++ b/src/3rdparty/masm/assembler/ARM64Assembler.h
@@ -3032,6 +3032,13 @@ public:
linuxPageFlush(current, current + page);
linuxPageFlush(current, end);
+#elif OS(QNX)
+#if !ENABLE(ASSEMBLER_WX_EXCLUSIVE)
+ msync(code, size, MS_INVALIDATE_ICACHE);
+#else
+ UNUSED_PARAM(code);
+ UNUSED_PARAM(size);
+#endif
#else
#error "The cacheFlush support is missing on this platform."
#endif
diff --git a/src/3rdparty/masm/wtf/MathExtras.h b/src/3rdparty/masm/wtf/MathExtras.h
index 3740d54beb..a529ba7b37 100644
--- a/src/3rdparty/masm/wtf/MathExtras.h
+++ b/src/3rdparty/masm/wtf/MathExtras.h
@@ -147,11 +147,6 @@ inline long lroundf(float num) { return static_cast<long>(roundf(num)); }
#endif
-#if COMPILER(GCC) && OS(QNX) && _CPPLIB_VER < 640
-// The stdlib on QNX < 6.6 doesn't contain long abs(long). See PR #104666.
-inline long long abs(long num) { return labs(num); }
-#endif
-
#if COMPILER(MSVC) && COMPILER(MSVC12_OR_LOWER)
// MSVC's math.h does not currently supply log2 or log2f.
inline double log2(double num)
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp b/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp
index d2cf7dc57f..d2934ba034 100644
--- a/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp
+++ b/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp
@@ -209,19 +209,32 @@ QVariant QQmlEngineDebugServiceImpl::valueContents(QVariant value) const
}
if (QQmlValueTypeFactory::isValueType(userType)) {
+ switch (userType) {
+ case QMetaType::QRect:
+ case QMetaType::QRectF:
+ case QMetaType::QPoint:
+ case QMetaType::QPointF:
+ case QMetaType::QSize:
+ case QMetaType::QSizeF:
+ case QMetaType::QFont:
+ // Don't call the toString() method on those. The stream operators are better.
+ return value;
+ default:
+ break;
+ }
+
const QMetaObject *mo = QQmlValueTypeFactory::metaObjectForMetaType(userType);
if (mo) {
- int toStringIndex = mo->indexOfMethod("toString");
+ int toStringIndex = mo->indexOfMethod("toString()");
if (toStringIndex != -1) {
QMetaMethod mm = mo->method(toStringIndex);
- QMetaType info(userType);
QString s;
- if (info.flags() & QMetaType::IsGadget
- && mm.invokeOnGadget(value.data(), Q_RETURN_ARG(QString, s)))
+ if (mm.invokeOnGadget(value.data(), Q_RETURN_ARG(QString, s)))
return s;
}
}
+ // We expect all QML value types to either have a toString() method or stream operators
return value;
}
diff --git a/src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.cpp b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.cpp
index 4176ede40e..affd2a417e 100644
--- a/src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.cpp
+++ b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.cpp
@@ -296,10 +296,11 @@ void QQmlProfilerServiceImpl::stopProfiling(QJSEngine *engine)
for (QMultiHash<QJSEngine *, QQmlAbstractProfilerAdapter *>::iterator i(m_engineProfilers.begin());
i != m_engineProfilers.end(); ++i) {
if (i.value()->isRunning()) {
+ m_startTimes.insert(-1, i.value());
if (engine == 0 || i.key() == engine) {
- m_startTimes.insert(-1, i.value());
stopping << i.value();
} else {
+ reporting << i.value();
stillRunning = true;
}
}
@@ -368,25 +369,32 @@ void QQmlProfilerServiceImpl::sendMessages()
}
}
+ bool stillRunning = false;
+ for (const QQmlAbstractProfilerAdapter *profiler : qAsConst(m_engineProfilers)) {
+ if (profiler->isRunning()) {
+ stillRunning = true;
+ break;
+ }
+ }
+
if (m_waitingForStop) {
- //indicate completion
+ // EndTrace can be sent multiple times, as it's engine specific.
messages << traceEnd.data();
- QQmlDebugPacket ds;
- ds << (qint64)-1 << (int)Complete;
- messages << ds.data();
- m_waitingForStop = false;
+ if (!stillRunning) {
+ // Complete is only sent once, when no engines are running anymore.
+ QQmlDebugPacket ds;
+ ds << (qint64)-1 << (int)Complete;
+ messages << ds.data();
+ m_waitingForStop = false;
+ }
}
emit messagesToClient(name(), messages);
// Restart flushing if any profilers are still running
- for (const QQmlAbstractProfilerAdapter *profiler : qAsConst(m_engineProfilers)) {
- if (profiler->isRunning()) {
- emit startFlushTimer();
- break;
- }
- }
+ if (stillRunning)
+ emit startFlushTimer();
}
void QQmlProfilerServiceImpl::stateAboutToBeChanged(QQmlDebugService::State newState)
diff --git a/src/qml/compiler/qqmlirbuilder.cpp b/src/qml/compiler/qqmlirbuilder.cpp
index 57121e5460..184925f167 100644
--- a/src/qml/compiler/qqmlirbuilder.cpp
+++ b/src/qml/compiler/qqmlirbuilder.cpp
@@ -1647,8 +1647,10 @@ char *QmlUnitGenerator::writeBindings(char *bindingPtr, const Object *o, Binding
return bindingPtr;
}
-JSCodeGen::JSCodeGen(const QString &fileName, const QString &sourceCode, QV4::IR::Module *jsModule, QQmlJS::Engine *jsEngine,
- QQmlJS::AST::UiProgram *qmlRoot, QQmlTypeNameCache *imports, const QV4::Compiler::StringTableGenerator *stringPool)
+JSCodeGen::JSCodeGen(const QString &fileName, const QString &finalUrl, const QString &sourceCode,
+ QV4::IR::Module *jsModule, QQmlJS::Engine *jsEngine,
+ QQmlJS::AST::UiProgram *qmlRoot, QQmlTypeNameCache *imports,
+ const QV4::Compiler::StringTableGenerator *stringPool, const QSet<QString> &globalNames)
: QQmlJS::Codegen(/*strict mode*/false)
, sourceCode(sourceCode)
, jsEngine(jsEngine)
@@ -1660,9 +1662,11 @@ JSCodeGen::JSCodeGen(const QString &fileName, const QString &sourceCode, QV4::IR
, _scopeObject(0)
, _qmlContextTemp(-1)
, _importedScriptsTemp(-1)
+ , m_globalNames(globalNames)
{
_module = jsModule;
_module->setFileName(fileName);
+ _module->setFinalUrl(finalUrl);
_fileNameIsUrl = true;
}
@@ -2138,6 +2142,9 @@ QV4::IR::Expr *JSCodeGen::fallbackNameLookup(const QString &name, int line, int
}
}
+ if (m_globalNames.contains(name))
+ return _block->GLOBALNAME(name, line, col, /*forceLookup =*/ true);
+
#else
Q_UNUSED(name)
#endif // V4_BOOTSTRAP
diff --git a/src/qml/compiler/qqmlirbuilder_p.h b/src/qml/compiler/qqmlirbuilder_p.h
index a5b4815745..f4d5901f92 100644
--- a/src/qml/compiler/qqmlirbuilder_p.h
+++ b/src/qml/compiler/qqmlirbuilder_p.h
@@ -608,9 +608,9 @@ struct Q_QML_EXPORT PropertyResolver
struct Q_QML_PRIVATE_EXPORT JSCodeGen : public QQmlJS::Codegen
{
- JSCodeGen(const QString &fileName, const QString &sourceCode, QV4::IR::Module *jsModule,
- QQmlJS::Engine *jsEngine, QQmlJS::AST::UiProgram *qmlRoot, QQmlTypeNameCache *imports,
- const QV4::Compiler::StringTableGenerator *stringPool);
+ JSCodeGen(const QString &fileName, const QString &finalUrl, const QString &sourceCode,
+ QV4::IR::Module *jsModule, QQmlJS::Engine *jsEngine, QQmlJS::AST::UiProgram *qmlRoot,
+ QQmlTypeNameCache *imports, const QV4::Compiler::StringTableGenerator *stringPool, const QSet<QString> &globalNames);
struct IdMapping
{
@@ -645,6 +645,7 @@ private:
QQmlPropertyCache *_scopeObject;
int _qmlContextTemp;
int _importedScriptsTemp;
+ QSet<QString> m_globalNames;
};
struct Q_QML_PRIVATE_EXPORT IRLoader {
diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp
index 46f0c46b99..c502d410f1 100644
--- a/src/qml/compiler/qqmltypecompiler.cpp
+++ b/src/qml/compiler/qqmltypecompiler.cpp
@@ -140,7 +140,10 @@ QV4::CompiledData::CompilationUnit *QQmlTypeCompiler::compile()
sss.scan();
}
- QmlIR::JSCodeGen v4CodeGenerator(typeData->finalUrlString(), document->code, &document->jsModule, &document->jsParserEngine, document->program, typeNameCache, &document->jsGenerator.stringTable);
+ QmlIR::JSCodeGen v4CodeGenerator(typeData->urlString(), typeData->finalUrlString(),
+ document->code, &document->jsModule,
+ &document->jsParserEngine, document->program,
+ typeNameCache, &document->jsGenerator.stringTable, engine->v8engine()->illegalNames());
QQmlJSCodeGenerator jsCodeGen(this, &v4CodeGenerator);
if (!jsCodeGen.generateCodeForComponents())
return nullptr;
@@ -1100,7 +1103,11 @@ QQmlComponentAndAliasResolver::AliasResolutionResult QQmlComponentAndAliasResolv
alias->flags |= QV4::CompiledData::Alias::AliasPointsToPointerObject;
} else {
QQmlPropertyCache *targetCache = propertyCaches.at(targetObjectIndex);
- Q_ASSERT(targetCache);
+ if (!targetCache) {
+ *error = QQmlCompileError(alias->referenceLocation, tr("Invalid alias target location: %1").arg(property.toString()));
+ break;
+ }
+
QmlIR::PropertyResolver resolver(targetCache);
QQmlPropertyData *targetProperty = resolver.property(property.toString());
diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp
index 5b7a7f9050..06f7cce2c7 100644
--- a/src/qml/compiler/qv4codegen.cpp
+++ b/src/qml/compiler/qv4codegen.cpp
@@ -501,6 +501,7 @@ Codegen::Codegen(bool strict)
}
void Codegen::generateFromProgram(const QString &fileName,
+ const QString &finalUrl,
const QString &sourceCode,
Program *node,
QV4::IR::Module *module,
@@ -513,6 +514,7 @@ void Codegen::generateFromProgram(const QString &fileName,
_variableEnvironment = 0;
_module->setFileName(fileName);
+ _module->setFinalUrl(finalUrl);
ScanFunctions scan(this, sourceCode, mode);
scan(node);
@@ -523,12 +525,14 @@ void Codegen::generateFromProgram(const QString &fileName,
}
void Codegen::generateFromFunctionExpression(const QString &fileName,
+ const QString &finalUrl,
const QString &sourceCode,
AST::FunctionExpression *ast,
QV4::IR::Module *module)
{
_module = module;
_module->setFileName(fileName);
+ _module->setFinalUrl(finalUrl);
_variableEnvironment = 0;
ScanFunctions scan(this, sourceCode, GlobalCode);
diff --git a/src/qml/compiler/qv4codegen_p.h b/src/qml/compiler/qv4codegen_p.h
index 31e9cc0f46..f1066b88c5 100644
--- a/src/qml/compiler/qv4codegen_p.h
+++ b/src/qml/compiler/qv4codegen_p.h
@@ -86,15 +86,17 @@ public:
};
void generateFromProgram(const QString &fileName,
+ const QString &finalUrl,
const QString &sourceCode,
AST::Program *ast,
QV4::IR::Module *module,
CompilationMode mode = GlobalCode,
const QStringList &inheritedLocals = QStringList());
void generateFromFunctionExpression(const QString &fileName,
- const QString &sourceCode,
- AST::FunctionExpression *ast,
- QV4::IR::Module *module);
+ const QString &finalUrl,
+ const QString &sourceCode,
+ AST::FunctionExpression *ast,
+ QV4::IR::Module *module);
protected:
enum Format { ex, cx, nx };
diff --git a/src/qml/compiler/qv4compileddata.cpp b/src/qml/compiler/qv4compileddata.cpp
index 292f5cde45..cacc3752ee 100644
--- a/src/qml/compiler/qv4compileddata.cpp
+++ b/src/qml/compiler/qv4compileddata.cpp
@@ -500,6 +500,7 @@ Unit *CompilationUnit::createUnitData(QmlIR::Document *irDocument)
if (jsUnit->sourceFileIndex == quint32(0) || jsUnit->stringAt(jsUnit->sourceFileIndex) != irDocument->jsModule.fileName) {
ensureWritableUnit();
jsUnit->sourceFileIndex = stringTable.registerString(irDocument->jsModule.fileName);
+ jsUnit->finalUrlIndex = stringTable.registerString(irDocument->jsModule.finalUrl);
}
// Collect signals that have had a change in signature (from onClicked to onClicked(mouse) for example)
@@ -744,7 +745,7 @@ static QByteArray ownLibraryChecksum()
// the cache files may end up being re-used. To avoid that we also add the checksum of
// the QtQml library.
Dl_info libInfo;
- if (dladdr(reinterpret_cast<const void *>(&ownLibraryChecksum), &libInfo) != 0) {
+ if (dladdr(reinterpret_cast<void *>(&ownLibraryChecksum), &libInfo) != 0) {
QFile library(QFile::decodeName(libInfo.dli_fname));
if (library.open(QIODevice::ReadOnly)) {
QCryptographicHash hash(QCryptographicHash::Md5);
diff --git a/src/qml/compiler/qv4compileddata_p.h b/src/qml/compiler/qv4compileddata_p.h
index adf6c21cc3..dc18a78681 100644
--- a/src/qml/compiler/qv4compileddata_p.h
+++ b/src/qml/compiler/qv4compileddata_p.h
@@ -72,7 +72,7 @@
QT_BEGIN_NAMESPACE
// Bump this whenever the compiler data structures change in an incompatible way.
-#define QV4_DATA_STRUCTURE_VERSION 0x13
+#define QV4_DATA_STRUCTURE_VERSION 0x14
class QIODevice;
class QQmlPropertyCache;
@@ -704,6 +704,7 @@ struct Unit
quint32_le offsetToJSClassTable;
qint32_le indexOfRootFunction;
quint32_le sourceFileIndex;
+ quint32_le finalUrlIndex;
/* QML specific fields */
quint32_le nImports;
@@ -711,6 +712,8 @@ struct Unit
quint32_le nObjects;
quint32_le offsetToObjects;
+ quint32_le padding;
+
const Import *importAt(int idx) const {
return reinterpret_cast<const Import*>((reinterpret_cast<const char *>(this)) + offsetToImports + idx * sizeof(Import));
}
@@ -775,7 +778,7 @@ struct Unit
}
};
-static_assert(sizeof(Unit) == 144, "Unit structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
+static_assert(sizeof(Unit) == 152, "Unit structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
struct TypeReference
{
@@ -885,14 +888,29 @@ struct Q_QML_PRIVATE_EXPORT CompilationUnit : public CompilationUnitBase, public
ExecutionEngine *engine;
QQmlEnginePrivate *qmlEngine; // only used in QML environment for composite types, not in plain QJSEngine case.
+ // url() and fileName() shall be used to load the actual QML/JS code or to show errors or
+ // warnings about that code. They include any potential URL interceptions and thus represent the
+ // "physical" location of the code.
+ //
+ // finalUrl() and finalUrlString() shall be used to resolve further URLs referred to in the code
+ // They are _not_ intercepted and thus represent the "logical" name for the code.
+
QString fileName() const { return data->stringAt(data->sourceFileIndex); }
+ QString finalUrlString() const { return data->stringAt(data->finalUrlIndex); }
QUrl url() const { if (m_url.isNull) m_url = QUrl(fileName()); return m_url; }
+ QUrl finalUrl() const
+ {
+ if (m_finalUrl.isNull)
+ m_finalUrl = QUrl(finalUrlString());
+ return m_finalUrl;
+ }
QV4::Lookup *runtimeLookups;
QV4::Value *runtimeRegularExpressions;
QV4::InternalClass **runtimeClasses;
QVector<QV4::Function *> runtimeFunctions;
mutable QQmlNullableValue<QUrl> m_url;
+ mutable QQmlNullableValue<QUrl> m_finalUrl;
// QML specific fields
QQmlPropertyCacheVector propertyCaches;
diff --git a/src/qml/compiler/qv4compiler.cpp b/src/qml/compiler/qv4compiler.cpp
index f02ee728c9..fc03320a20 100644
--- a/src/qml/compiler/qv4compiler.cpp
+++ b/src/qml/compiler/qv4compiler.cpp
@@ -212,6 +212,7 @@ int QV4::Compiler::JSUnitGenerator::registerJSClass(int count, IR::ExprList *arg
QV4::CompiledData::Unit *QV4::Compiler::JSUnitGenerator::generateUnit(GeneratorOption option)
{
registerString(irModule->fileName);
+ registerString(irModule->finalUrl);
for (QV4::IR::Function *f : qAsConst(irModule->functions)) {
registerString(*f->name);
for (int i = 0; i < f->formals.size(); ++i)
@@ -429,6 +430,7 @@ QV4::CompiledData::Unit QV4::Compiler::JSUnitGenerator::generateHeader(QV4::Comp
}
unit.indexOfRootFunction = -1;
unit.sourceFileIndex = getStringId(irModule->fileName);
+ unit.finalUrlIndex = getStringId(irModule->finalUrl);
unit.sourceTimeStamp = irModule->sourceTimeStamp.isValid() ? irModule->sourceTimeStamp.toMSecsSinceEpoch() : 0;
unit.nImports = 0;
unit.offsetToImports = 0;
diff --git a/src/qml/compiler/qv4isel_moth.cpp b/src/qml/compiler/qv4isel_moth.cpp
index 82f5225f28..c29ffa10c2 100644
--- a/src/qml/compiler/qv4isel_moth.cpp
+++ b/src/qml/compiler/qv4isel_moth.cpp
@@ -386,7 +386,7 @@ void InstructionSelection::constructActivationProperty(IR::Name *func,
IR::ExprList *args,
IR::Expr *target)
{
- if (useFastLookups && func->global) {
+ if ((useFastLookups || func->forceLookup) && func->global) {
Instruction::ConstructGlobalLookup call;
call.index = registerGlobalGetterLookup(*func->id);
prepareCallArgs(args, call.argc);
@@ -491,7 +491,7 @@ void InstructionSelection::loadRegexp(IR::RegExp *sourceRegexp, IR::Expr *target
void InstructionSelection::getActivationProperty(const IR::Name *name, IR::Expr *target)
{
- if (useFastLookups && name->global) {
+ if ((useFastLookups || name->forceLookup) && name->global) {
Instruction::GetGlobalLookup load;
load.index = registerGlobalGetterLookup(*name->id);
load.result = getResultParam(target);
@@ -1015,7 +1015,7 @@ void InstructionSelection::visitRet(IR::Ret *s)
void InstructionSelection::callBuiltinInvalid(IR::Name *func, IR::ExprList *args, IR::Expr *result)
{
- if (useFastLookups && func->global) {
+ if ((useFastLookups || func->forceLookup) && func->global) {
Instruction::CallGlobalLookup call;
call.index = registerGlobalGetterLookup(*func->id);
prepareCallArgs(args, call.argc);
diff --git a/src/qml/compiler/qv4jsir.cpp b/src/qml/compiler/qv4jsir.cpp
index 0b0ed391fb..a4038f827a 100644
--- a/src/qml/compiler/qv4jsir.cpp
+++ b/src/qml/compiler/qv4jsir.cpp
@@ -243,11 +243,12 @@ private:
}
};
-void Name::initGlobal(const QString *id, quint32 line, quint32 column)
+void Name::initGlobal(const QString *id, quint32 line, quint32 column, bool forceLookup)
{
this->id = id;
this->builtin = builtin_invalid;
this->global = true;
+ this->forceLookup = forceLookup;
this->qmlSingleton = false;
this->freeOfSideEffects = false;
this->line = line;
@@ -259,6 +260,7 @@ void Name::init(const QString *id, quint32 line, quint32 column)
this->id = id;
this->builtin = builtin_invalid;
this->global = false;
+ this->forceLookup = false;
this->qmlSingleton = false;
this->freeOfSideEffects = false;
this->line = line;
@@ -270,6 +272,7 @@ void Name::init(Builtin builtin, quint32 line, quint32 column)
this->id = 0;
this->builtin = builtin;
this->global = false;
+ this->forceLookup = false;
this->qmlSingleton = false;
this->freeOfSideEffects = false;
this->line = line;
@@ -351,6 +354,11 @@ void Module::setFileName(const QString &name)
fileName = name;
}
+void Module::setFinalUrl(const QString &url)
+{
+ finalUrl = url;
+}
+
Function::Function(Module *module, Function *outer, const QString &name)
: module(module)
, pool(&module->pool)
diff --git a/src/qml/compiler/qv4jsir_p.h b/src/qml/compiler/qv4jsir_p.h
index fb65eb4d8c..8c314a9635 100644
--- a/src/qml/compiler/qv4jsir_p.h
+++ b/src/qml/compiler/qv4jsir_p.h
@@ -480,6 +480,7 @@ struct Name: Expr {
const QString *id;
Builtin builtin;
bool global : 1;
+ bool forceLookup : 1;
bool qmlSingleton : 1;
bool freeOfSideEffects : 1;
quint32 line;
@@ -487,7 +488,7 @@ struct Name: Expr {
Name(): Expr(NameExpr) {}
- void initGlobal(const QString *id, quint32 line, quint32 column);
+ void initGlobal(const QString *id, quint32 line, quint32 column, bool forceLookup = false);
void init(const QString *id, quint32 line, quint32 column);
void init(Builtin builtin, quint32 line, quint32 column);
@@ -952,6 +953,7 @@ struct Q_QML_PRIVATE_EXPORT Module {
QVector<Function *> functions;
Function *rootFunction;
QString fileName;
+ QString finalUrl;
QDateTime sourceTimeStamp;
bool isQmlModule; // implies rootFunction is always 0
uint unitFlags; // flags merged into CompiledData::Unit::flags
@@ -977,6 +979,7 @@ struct Q_QML_PRIVATE_EXPORT Module {
~Module();
void setFileName(const QString &name);
+ void setFinalUrl(const QString &url);
};
struct BasicBlock {
@@ -1139,7 +1142,7 @@ public:
Name *NAME(const QString &id, quint32 line, quint32 column);
Name *NAME(Name::Builtin builtin, quint32 line, quint32 column);
- Name *GLOBALNAME(const QString &id, quint32 line, quint32 column);
+ Name *GLOBALNAME(const QString &id, quint32 line, quint32 column, bool forceLookup = false);
Closure *CLOSURE(int functionInModule);
@@ -1607,11 +1610,11 @@ inline Name *BasicBlock::NAME(const QString &id, quint32 line, quint32 column)
return e;
}
-inline Name *BasicBlock::GLOBALNAME(const QString &id, quint32 line, quint32 column)
+inline Name *BasicBlock::GLOBALNAME(const QString &id, quint32 line, quint32 column, bool forceLookup)
{
Q_ASSERT(!isRemoved());
Name *e = function->New<Name>();
- e->initGlobal(function->newString(id), line, column);
+ e->initGlobal(function->newString(id), line, column, forceLookup);
return e;
}
diff --git a/src/qml/debugger/qqmlprofiler_p.h b/src/qml/debugger/qqmlprofiler_p.h
index 6dc9859295..f03657508e 100644
--- a/src/qml/debugger/qqmlprofiler_p.h
+++ b/src/qml/debugger/qqmlprofiler_p.h
@@ -234,9 +234,10 @@ public:
{
// Use the QV4::Function as ID, as that is common among different instances of the same
// component. QQmlBinding is per instance.
- // Add 1 to the ID, to make it different from the IDs the V4 profiler produces. The +1 makes
- // the pointer point into the middle of the QV4::Function. Thus it still points to valid
- // memory but we cannot accidentally create a duplicate key from another object.
+ // Add 1 to the ID, to make it different from the IDs the V4 and signal handling profilers
+ // produce. The +1 makes the pointer point into the middle of the QV4::Function. Thus it
+ // still points to valid memory but we cannot accidentally create a duplicate key from
+ // another object.
// If there is no function, use a static but valid address: The profiler itself.
quintptr locationId = function ? id(function) + 1 : id(this);
m_data.append(QQmlProfilerData(m_timer.nsecsElapsed(),
@@ -268,7 +269,12 @@ public:
void startHandlingSignal(QQmlBoundSignalExpression *expression)
{
- quintptr locationId(id(expression));
+ // Use the QV4::Function as ID, as that is common among different instances of the same
+ // component. QQmlBoundSignalExpression is per instance.
+ // Add 2 to the ID, to make it different from the IDs the V4 and binding profilers produce.
+ // The +2 makes the pointer point into the middle of the QV4::Function. Thus it still points
+ // to valid memory but we cannot accidentally create a duplicate key from another object.
+ quintptr locationId(id(expression->function()) + 2);
m_data.append(QQmlProfilerData(m_timer.nsecsElapsed(),
(1 << RangeStart | 1 << RangeLocation), HandlingSignal,
locationId));
diff --git a/src/qml/doc/src/includes/qqmlcomponent.qdoc b/src/qml/doc/src/includes/qqmlcomponent.qdoc
new file mode 100644
index 0000000000..0eb60ed743
--- /dev/null
+++ b/src/qml/doc/src/includes/qqmlcomponent.qdoc
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//! [url-note]
+Ensure that the URL provided is full and correct, in particular, use
+\l QUrl::fromLocalFile() when loading a file from the local filesystem.
+
+Relative paths will be resolved against the engine's
+\l {QQmlEngine::baseUrl}{baseUrl()}, which is the current working directory
+unless specified.
+//! [url-note]
diff --git a/src/qml/doc/src/qmllanguageref/syntax/objectattributes.qdoc b/src/qml/doc/src/qmllanguageref/syntax/objectattributes.qdoc
index 207fb53ca0..31650db7c0 100644
--- a/src/qml/doc/src/qmllanguageref/syntax/objectattributes.qdoc
+++ b/src/qml/doc/src/qmllanguageref/syntax/objectattributes.qdoc
@@ -449,13 +449,38 @@ right-hand-side of the property declaration must be a valid alias reference:
[default] property alias <name>: <alias reference>
\endcode
-Unlike an ordinary property, an alias can only refer to an object, or the
-property of an object, that is within the scope of the \l{QML Object Types}
-{type} within which the alias is declared. It cannot contain arbitrary
-JavaScript expressions and it cannot refer to objects declared outside of
-the scope of its type. Also note the \e {alias reference} is not optional,
-unlike the optional default value for an ordinary property; the alias reference
-must be provided when the alias is first declared.
+Unlike an ordinary property, an alias has the following restrictions:
+
+\list
+\li It can only refer to an object, or the
+ property of an object, that is within the scope of the \l{QML Object Types}
+ {type} within which the alias is declared.
+\li It cannot contain arbitrary
+ JavaScript expressions
+\li It cannot refer to objects declared outside of
+ the scope of its type.
+\li The \e {alias reference} is not optional,
+ unlike the optional default value for an ordinary property; the alias reference
+ must be provided when the alias is first declared.
+\li It cannot refer to grouped properties; the following code will not work:
+ \code
+ property alias color: rectangle.border.color
+
+ Rectangle {
+ id: rectangle
+ }
+ \endcode
+
+ However, aliases to \l {QML Basic Types}{value type} properties do work:
+ \code
+ property alias rectX: object.rectProperty.x
+
+ Item {
+ id: object
+ property rect rectProperty
+ }
+ \endcode
+\endlist
For example, below is a \c Button type with a \c buttonText aliased property
which is connected to the \c text object of the \l Text child:
diff --git a/src/qml/jit/qv4isel_masm.cpp b/src/qml/jit/qv4isel_masm.cpp
index 7784eb364e..a35b12d51e 100644
--- a/src/qml/jit/qv4isel_masm.cpp
+++ b/src/qml/jit/qv4isel_masm.cpp
@@ -168,7 +168,7 @@ void InstructionSelection<JITAssembler>::callBuiltinInvalid(IR::Name *func, IR::
{
prepareCallData(args, 0);
- if (useFastLookups && func->global) {
+ if ((useFastLookups || func->forceLookup) && func->global) {
uint index = registerGlobalGetterLookup(*func->id);
generateRuntimeCall(_as, result, callGlobalLookup,
JITTargetPlatform::EngineRegister,
@@ -520,7 +520,7 @@ void InstructionSelection<JITAssembler>::loadRegexp(IR::RegExp *sourceRegexp, IR
template <typename JITAssembler>
void InstructionSelection<JITAssembler>::getActivationProperty(const IR::Name *name, IR::Expr *target)
{
- if (useFastLookups && name->global) {
+ if ((useFastLookups || name->forceLookup) && name->global) {
uint index = registerGlobalGetterLookup(*name->id);
generateLookupCall(target, index, offsetof(QV4::Lookup, globalGetter), JITTargetPlatform::EngineRegister, JITAssembler::Void);
return;
@@ -1136,7 +1136,7 @@ void InstructionSelection<JITAssembler>::constructActivationProperty(IR::Name *f
Q_ASSERT(func != 0);
prepareCallData(args, 0);
- if (useFastLookups && func->global) {
+ if ((useFastLookups || func->forceLookup) && func->global) {
uint index = registerGlobalGetterLookup(*func->id);
generateRuntimeCall(_as, result, constructGlobalLookup,
JITTargetPlatform::EngineRegister,
diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp
index 7b298a302c..f19f134c53 100644
--- a/src/qml/jsruntime/qv4engine.cpp
+++ b/src/qml/jsruntime/qv4engine.cpp
@@ -219,6 +219,7 @@ ExecutionEngine::ExecutionEngine(EvalISelFactory *factory)
internalClasses[Class_SimpleArrayData] = internalClasses[EngineBase::Class_Empty]->changeVTable(QV4::SimpleArrayData::staticVTable());
internalClasses[Class_SparseArrayData] = internalClasses[EngineBase::Class_Empty]->changeVTable(QV4::SparseArrayData::staticVTable());
internalClasses[Class_ExecutionContext] = internalClasses[EngineBase::Class_Empty]->changeVTable(QV4::ExecutionContext::staticVTable());
+ internalClasses[EngineBase::Class_QmlContext] = internalClasses[EngineBase::Class_ExecutionContext]->changeVTable(QV4::QmlContext::staticVTable());
internalClasses[Class_SimpleCallContext] = internalClasses[EngineBase::Class_Empty]->changeVTable(QV4::CallContext::staticVTable());
jsStrings[String_Empty] = newIdentifier(QString());
@@ -261,6 +262,7 @@ ExecutionEngine::ExecutionEngine(EvalISelFactory *factory)
InternalClass *ic = internalClasses[Class_Empty]->changeVTable(QV4::Object::staticVTable());
jsObjects[ObjectProto] = memoryManager->allocObject<ObjectPrototype>(ic);
internalClasses[Class_Object] = ic->changePrototype(objectPrototype()->d());
+ internalClasses[EngineBase::Class_QmlContextWrapper] = internalClasses[Class_Object]->changeVTable(QV4::QQmlContextWrapper::staticVTable());
ic = newInternalClass(ArrayPrototype::staticVTable(), objectPrototype());
Q_ASSERT(ic->prototype);
@@ -912,14 +914,14 @@ QUrl ExecutionEngine::resolvedUrl(const QString &file)
while (c) {
SimpleCallContext *callCtx = c->asSimpleCallContext();
if (callCtx && callCtx->d()->v4Function) {
- base.setUrl(callCtx->d()->v4Function->sourceFile());
+ base = callCtx->d()->v4Function->finalUrl();
break;
}
c = parentContext(c);
}
if (base.isEmpty() && globalCode)
- base.setUrl(globalCode->sourceFile());
+ base = globalCode->finalUrl();
if (base.isEmpty())
return src;
diff --git a/src/qml/jsruntime/qv4enginebase_p.h b/src/qml/jsruntime/qv4enginebase_p.h
index 88f9dfd85c..8258d644ff 100644
--- a/src/qml/jsruntime/qv4enginebase_p.h
+++ b/src/qml/jsruntime/qv4enginebase_p.h
@@ -106,6 +106,8 @@ struct EngineBase {
Class_ErrorObject,
Class_ErrorObjectWithMessage,
Class_ErrorProto,
+ Class_QmlContextWrapper,
+ Class_QmlContext,
NClasses
};
InternalClass *internalClasses[NClasses];
diff --git a/src/qml/jsruntime/qv4function_p.h b/src/qml/jsruntime/qv4function_p.h
index b11c8af94a..8b2d14a0cf 100644
--- a/src/qml/jsruntime/qv4function_p.h
+++ b/src/qml/jsruntime/qv4function_p.h
@@ -83,6 +83,7 @@ struct Q_QML_EXPORT Function {
return compilationUnit->runtimeStrings[compiledFunction->nameIndex];
}
inline QString sourceFile() const { return compilationUnit->fileName(); }
+ inline QUrl finalUrl() const { return compilationUnit->finalUrl(); }
inline bool usesArgumentsObject() const { return compiledFunction->flags & CompiledData::Function::UsesArgumentsObject; }
inline bool isStrict() const { return compiledFunction->flags & CompiledData::Function::IsStrict; }
diff --git a/src/qml/jsruntime/qv4functionobject.cpp b/src/qml/jsruntime/qv4functionobject.cpp
index 45fdde98f7..2375aae92b 100644
--- a/src/qml/jsruntime/qv4functionobject.cpp
+++ b/src/qml/jsruntime/qv4functionobject.cpp
@@ -222,7 +222,7 @@ void FunctionCtor::construct(const Managed *that, Scope &scope, CallData *callDa
IR::Module module(scope.engine->debugger() != 0);
QQmlJS::RuntimeCodegen cg(scope.engine, f->strictMode());
- cg.generateFromFunctionExpression(QString(), function, fe, &module);
+ cg.generateFromFunctionExpression(QString(), QString(), function, fe, &module);
Compiler::JSUnitGenerator jsGenerator(&module);
QScopedPointer<EvalInstructionSelection> isel(scope.engine->iselFactory->create(QQmlEnginePrivate::get(scope.engine), scope.engine->executableAllocator, &module, &jsGenerator));
diff --git a/src/qml/jsruntime/qv4global_p.h b/src/qml/jsruntime/qv4global_p.h
index 8769519a59..5cddf2eaa6 100644
--- a/src/qml/jsruntime/qv4global_p.h
+++ b/src/qml/jsruntime/qv4global_p.h
@@ -95,7 +95,7 @@ inline double trunc(double d) { return d > 0 ? floor(d) : ceil(d); }
&& (defined(Q_OS_WIN) || defined(Q_OS_LINUX) || defined(Q_OS_QNX) || defined(Q_OS_FREEBSD))
# define V4_ENABLE_JIT
#elif defined(Q_PROCESSOR_X86_64) && (QT_POINTER_SIZE == 8) \
- && (defined(Q_OS_WIN) || defined(Q_OS_LINUX) || defined(Q_OS_MAC) || defined(Q_OS_FREEBSD))
+ && (defined(Q_OS_WIN) || defined(Q_OS_LINUX) || defined(Q_OS_QNX) || defined(Q_OS_MAC) || defined(Q_OS_FREEBSD))
# define V4_ENABLE_JIT
#elif defined(Q_PROCESSOR_ARM_32) && (QT_POINTER_SIZE == 4)
# if defined(thumb2) || defined(__thumb2__) || ((defined(__thumb) || defined(__thumb__)) && __TARGET_ARCH_THUMB-0 == 4)
@@ -104,7 +104,7 @@ inline double trunc(double d) { return d > 0 ? floor(d) : ceil(d); }
# define V4_ENABLE_JIT
# endif
#elif defined(Q_PROCESSOR_ARM_64) && (QT_POINTER_SIZE == 8)
-# if defined(Q_OS_LINUX)
+# if defined(Q_OS_LINUX) || defined(Q_OS_QNX)
# define V4_ENABLE_JIT
# endif
#elif defined(Q_PROCESSOR_MIPS_32) && defined(Q_OS_LINUX)
diff --git a/src/qml/jsruntime/qv4qmlcontext_p.h b/src/qml/jsruntime/qv4qmlcontext_p.h
index 48c9ee2c36..65bf4c60ce 100644
--- a/src/qml/jsruntime/qv4qmlcontext_p.h
+++ b/src/qml/jsruntime/qv4qmlcontext_p.h
@@ -91,6 +91,7 @@ struct Q_QML_EXPORT QQmlContextWrapper : Object
{
V4_OBJECT2(QQmlContextWrapper, Object)
V4_NEEDS_DESTROY
+ V4_INTERNALCLASS(QmlContextWrapper)
inline QObject *getScopeObject() const { return d()->scopeObject; }
inline QQmlContextData *getContext() const { return *d()->context; }
@@ -104,6 +105,7 @@ struct Q_QML_EXPORT QQmlContextWrapper : Object
struct Q_QML_EXPORT QmlContext : public ExecutionContext
{
V4_MANAGED(QmlContext, ExecutionContext)
+ V4_INTERNALCLASS(QmlContext)
static Heap::QmlContext *createWorkerContext(QV4::ExecutionContext *parent, const QUrl &source, Value *sendFunction);
static Heap::QmlContext *create(QV4::ExecutionContext *parent, QQmlContextData *context, QObject *scopeObject);
diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp
index fb3aa47d1b..51a957acc9 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper.cpp
+++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp
@@ -714,6 +714,10 @@ bool QObjectWrapper::put(Managed *m, String *name, const Value &value)
PropertyAttributes QObjectWrapper::query(const Managed *m, String *name)
{
const QObjectWrapper *that = static_cast<const QObjectWrapper*>(m);
+ const QObject *thatObject = that->d()->object();
+ if (QQmlData::wasDeleted(thatObject))
+ return QV4::Object::query(m, name);
+
ExecutionEngine *engine = that->engine();
QQmlContextData *qmlContext = engine->callingQmlContext();
QQmlPropertyData local;
@@ -2083,10 +2087,10 @@ ReturnedValue QMetaObjectWrapper::callOverloadedConstructor(QV4::ExecutionEngine
for (int i = 0; i < numberOfConstructors; i++) {
const QQmlPropertyData & attempt = d()->constructors[i];
+ QQmlMetaObject::ArgTypeStorage storage;
int methodArgumentCount = 0;
int *methodArgTypes = 0;
if (attempt.hasArguments()) {
- QQmlMetaObject::ArgTypeStorage storage;
int *args = object.constructorParameterTypes(attempt.coreIndex(), &storage, 0);
if (!args) // Must be an unknown argument
continue;
diff --git a/src/qml/jsruntime/qv4script.cpp b/src/qml/jsruntime/qv4script.cpp
index 62145f36cc..9d1d5e2589 100644
--- a/src/qml/jsruntime/qv4script.cpp
+++ b/src/qml/jsruntime/qv4script.cpp
@@ -127,7 +127,8 @@ void Script::parse()
}
RuntimeCodegen cg(v4, strictMode);
- cg.generateFromProgram(sourceFile, sourceCode, program, &module, QQmlJS::Codegen::EvalCode, inheritedLocals);
+ cg.generateFromProgram(sourceFile, sourceFile, sourceCode, program, &module,
+ QQmlJS::Codegen::EvalCode, inheritedLocals);
if (v4->hasException)
return;
@@ -186,7 +187,10 @@ Function *Script::function()
return vmFunction;
}
-QQmlRefPointer<QV4::CompiledData::CompilationUnit> Script::precompile(IR::Module *module, Compiler::JSUnitGenerator *unitGenerator, ExecutionEngine *engine, const QUrl &url, const QString &source, QList<QQmlError> *reportedErrors, QQmlJS::Directives *directivesCollector)
+QQmlRefPointer<QV4::CompiledData::CompilationUnit> Script::precompile(
+ IR::Module *module, Compiler::JSUnitGenerator *unitGenerator, ExecutionEngine *engine,
+ const QString &fileName, const QString &finalUrl, const QString &source,
+ QList<QQmlError> *reportedErrors, QQmlJS::Directives *directivesCollector)
{
using namespace QQmlJS;
using namespace QQmlJS::AST;
@@ -205,12 +209,12 @@ QQmlRefPointer<QV4::CompiledData::CompilationUnit> Script::precompile(IR::Module
const auto diagnosticMessages = parser.diagnosticMessages();
for (const QQmlJS::DiagnosticMessage &m : diagnosticMessages) {
if (m.isWarning()) {
- qWarning("%s:%d : %s", qPrintable(url.toString()), m.loc.startLine, qPrintable(m.message));
+ qWarning("%s:%d : %s", qPrintable(fileName), m.loc.startLine, qPrintable(m.message));
continue;
}
QQmlError error;
- error.setUrl(url);
+ error.setUrl(QUrl(fileName));
error.setDescription(m.message);
error.setLine(m.loc.startLine);
error.setColumn(m.loc.startColumn);
@@ -231,7 +235,7 @@ QQmlRefPointer<QV4::CompiledData::CompilationUnit> Script::precompile(IR::Module
}
QQmlJS::Codegen cg(/*strict mode*/false);
- cg.generateFromProgram(url.toString(), source, program, module, QQmlJS::Codegen::EvalCode);
+ cg.generateFromProgram(fileName, finalUrl, source, program, module, QQmlJS::Codegen::EvalCode);
errors = cg.qmlErrors();
if (!errors.isEmpty()) {
if (reportedErrors)
diff --git a/src/qml/jsruntime/qv4script_p.h b/src/qml/jsruntime/qv4script_p.h
index 4ebe2dd609..55a349b5fc 100644
--- a/src/qml/jsruntime/qv4script_p.h
+++ b/src/qml/jsruntime/qv4script_p.h
@@ -139,8 +139,10 @@ struct Q_QML_EXPORT Script {
Function *function();
- static QQmlRefPointer<CompiledData::CompilationUnit> precompile(IR::Module *module, Compiler::JSUnitGenerator *unitGenerator, ExecutionEngine *engine, const QUrl &url, const QString &source,
- QList<QQmlError> *reportedErrors = 0, QQmlJS::Directives *directivesCollector = 0);
+ static QQmlRefPointer<CompiledData::CompilationUnit> precompile(
+ IR::Module *module, Compiler::JSUnitGenerator *unitGenerator, ExecutionEngine *engine,
+ const QString &fileName, const QString &finalUrl, const QString &source,
+ QList<QQmlError> *reportedErrors = 0, QQmlJS::Directives *directivesCollector = 0);
static ReturnedValue evaluate(ExecutionEngine *engine, const QString &script, QmlContext *qmlContext);
};
diff --git a/src/qml/memory/qv4mm.cpp b/src/qml/memory/qv4mm.cpp
index 8821d3c921..27b3c756c5 100644
--- a/src/qml/memory/qv4mm.cpp
+++ b/src/qml/memory/qv4mm.cpp
@@ -44,6 +44,7 @@
#include "qv4qobjectwrapper_p.h"
#include <QtCore/qalgorithms.h>
#include <QtCore/private/qnumeric_p.h>
+#include <QtCore/qloggingcategory.h>
#include <qqmlengine.h>
#include "PageReservation.h"
#include "PageAllocation.h"
@@ -91,6 +92,11 @@
#define MIN_UNMANAGED_HEAPSIZE_GC_LIMIT std::size_t(128 * 1024)
+Q_LOGGING_CATEGORY(lcGcStats, "qt.qml.gc.statistics")
+Q_DECLARE_LOGGING_CATEGORY(lcGcStats)
+Q_LOGGING_CATEGORY(lcGcAllocatorStats, "qt.qml.gc.allocatorStats")
+Q_DECLARE_LOGGING_CATEGORY(lcGcAllocatorStats)
+
using namespace WTF;
QT_BEGIN_NAMESPACE
@@ -607,9 +613,9 @@ template struct StackAllocator<Heap::CallContext>;
HeapItem *BlockAllocator::allocate(size_t size, bool forceAllocation) {
Q_ASSERT((size % Chunk::SlotSize) == 0);
size_t slotsRequired = size >> Chunk::SlotSizeShift;
-#if MM_DEBUG
- ++allocations[bin];
-#endif
+
+ if (allocationStats)
+ ++allocationStats[binForSlots(slotsRequired)];
HeapItem **last;
@@ -751,37 +757,6 @@ void BlockAllocator::collectGrayItems(MarkStack *markStack)
}
-#if MM_DEBUG
-void BlockAllocator::stats() {
- DEBUG << "MM stats:";
- QString s;
- for (int i = 0; i < 10; ++i) {
- uint c = 0;
- HeapItem *item = freeBins[i];
- while (item) {
- ++c;
- item = item->freeData.next;
- }
- s += QString::number(c) + QLatin1String(", ");
- }
- HeapItem *item = freeBins[NumBins - 1];
- uint c = 0;
- while (item) {
- ++c;
- item = item->freeData.next;
- }
- s += QLatin1String("..., ") + QString::number(c);
- DEBUG << "bins:" << s;
- QString a;
- for (int i = 0; i < 10; ++i)
- a += QString::number(allocations[i]) + QLatin1String(", ");
- a += QLatin1String("..., ") + QString::number(allocations[NumBins - 1]);
- DEBUG << "allocs:" << a;
- memset(allocations, 0, sizeof(allocations));
-}
-#endif
-
-
HeapItem *HugeItemAllocator::allocate(size_t size) {
Chunk *c = chunkAllocator->allocate(size);
chunks.push_back(HugeChunk{c, size});
@@ -858,11 +833,15 @@ MemoryManager::MemoryManager(ExecutionEngine *engine)
, m_weakValues(new PersistentValueStorage(engine))
, unmanagedHeapSizeGCLimit(MIN_UNMANAGED_HEAPSIZE_GC_LIMIT)
, aggressiveGC(!qEnvironmentVariableIsEmpty("QV4_MM_AGGRESSIVE_GC"))
- , gcStats(!qEnvironmentVariableIsEmpty(QV4_MM_STATS))
+ , gcStats(lcGcStats().isDebugEnabled())
+ , gcCollectorStats(lcGcAllocatorStats().isDebugEnabled())
{
#ifdef V4_USE_VALGRIND
VALGRIND_CREATE_MEMPOOL(this, 0, true);
#endif
+ memset(statistics.allocations, 0, sizeof(statistics.allocations));
+ if (gcStats)
+ blockAllocator.allocationStats = statistics.allocations;
}
#ifdef MM_STATS
@@ -922,9 +901,6 @@ Heap::Base *MemoryManager::allocData(std::size_t size)
runGC();
didRunGC = true;
}
-#ifdef DETAILED_MM_STATS
- willAllocate(size);
-#endif // DETAILED_MM_STATS
Q_ASSERT(size >= Chunk::SlotSize);
Q_ASSERT(size % Chunk::SlotSize == 0);
@@ -1125,9 +1101,10 @@ bool MemoryManager::shouldRunGC() const
size_t dumpBins(BlockAllocator *b, bool printOutput = true)
{
+ const QLoggingCategory &stats = lcGcAllocatorStats();
size_t totalSlotMem = 0;
if (printOutput)
- qDebug() << "Slot map:";
+ qDebug(stats) << "Slot map:";
for (uint i = 0; i < BlockAllocator::NumBins; ++i) {
uint nEntries = 0;
HeapItem *h = b->freeBins[i];
@@ -1137,7 +1114,7 @@ size_t dumpBins(BlockAllocator *b, bool printOutput = true)
h = h->freeData.next;
}
if (printOutput)
- qDebug() << " number of entries in slot" << i << ":" << nEntries;
+ qDebug(stats) << " number of entries in slot" << i << ":" << nEntries;
}
SDUMP() << " large slot map";
HeapItem *h = b->freeBins[BlockAllocator::NumBins - 1];
@@ -1147,7 +1124,7 @@ size_t dumpBins(BlockAllocator *b, bool printOutput = true)
}
if (printOutput)
- qDebug() << " total mem in bins" << totalSlotMem*Chunk::SlotSize;
+ qDebug(stats) << " total mem in bins" << totalSlotMem*Chunk::SlotSize;
return totalSlotMem*Chunk::SlotSize;
}
@@ -1161,27 +1138,32 @@ void MemoryManager::runGC()
QScopedValueRollback<bool> gcBlocker(gcBlocked, true);
// qDebug() << "runGC";
- if (!gcStats) {
-// uint oldUsed = allocator.usedMem();
+ if (gcStats) {
+ statistics.maxReservedMem = qMax(statistics.maxReservedMem, getAllocatedMem());
+ statistics.maxAllocatedMem = qMax(statistics.maxAllocatedMem, getUsedMem() + getLargeItemsMem());
+ }
+
+ if (!gcCollectorStats) {
mark();
sweep();
-// DEBUG << "RUN GC: allocated:" << allocator.allocatedMem() << "used before" << oldUsed << "used now" << allocator.usedMem();
} else {
bool triggeredByUnmanagedHeap = (unmanagedHeapSize > unmanagedHeapSizeGCLimit);
size_t oldUnmanagedSize = unmanagedHeapSize;
+
const size_t totalMem = getAllocatedMem();
const size_t usedBefore = getUsedMem();
const size_t largeItemsBefore = getLargeItemsMem();
- qDebug() << "========== GC ==========";
+ const QLoggingCategory &stats = lcGcAllocatorStats();
+ qDebug(stats) << "========== GC ==========";
#ifdef MM_STATS
- qDebug() << " Triggered by alloc request of" << lastAllocRequestedSlots << "slots.";
- qDebug() << " Allocations since last GC" << allocationCount;
+ qDebug(stats) << " Triggered by alloc request of" << lastAllocRequestedSlots << "slots.";
+ qDebug(stats) << " Allocations since last GC" << allocationCount;
allocationCount = 0;
#endif
size_t oldChunks = blockAllocator.chunks.size();
- qDebug() << "Allocated" << totalMem << "bytes in" << oldChunks << "chunks";
- qDebug() << "Fragmented memory before GC" << (totalMem - usedBefore);
+ qDebug(stats) << "Allocated" << totalMem << "bytes in" << oldChunks << "chunks";
+ qDebug(stats) << "Fragmented memory before GC" << (totalMem - usedBefore);
dumpBins(&blockAllocator);
#ifdef MM_STATS
@@ -1199,15 +1181,15 @@ void MemoryManager::runGC()
qint64 sweepTime = t.nsecsElapsed()/1000;
if (triggeredByUnmanagedHeap) {
- qDebug() << "triggered by unmanaged heap:";
- qDebug() << " old unmanaged heap size:" << oldUnmanagedSize;
- qDebug() << " new unmanaged heap:" << unmanagedHeapSize;
- qDebug() << " unmanaged heap limit:" << unmanagedHeapSizeGCLimit;
+ qDebug(stats) << "triggered by unmanaged heap:";
+ qDebug(stats) << " old unmanaged heap size:" << oldUnmanagedSize;
+ qDebug(stats) << " new unmanaged heap:" << unmanagedHeapSize;
+ qDebug(stats) << " unmanaged heap limit:" << unmanagedHeapSizeGCLimit;
}
size_t memInBins = dumpBins(&blockAllocator);
- qDebug() << "Marked object in" << markTime << "us.";
- qDebug() << " " << markStackSize << "objects marked";
- qDebug() << "Sweeped object in" << sweepTime << "us.";
+ qDebug(stats) << "Marked object in" << markTime << "us.";
+ qDebug(stats) << " " << markStackSize << "objects marked";
+ qDebug(stats) << "Sweeped object in" << sweepTime << "us.";
// sort our object types by number of freed instances
MMStatsHash freedObjectStats;
@@ -1222,26 +1204,29 @@ void MemoryManager::runGC()
return a.second > b.second && strcmp(a.first, b.first) < 0;
});
- qDebug() << "Used memory before GC:" << usedBefore;
- qDebug() << "Used memory after GC:" << usedAfter;
- qDebug() << "Freed up bytes :" << (usedBefore - usedAfter);
- qDebug() << "Freed up chunks :" << (oldChunks - blockAllocator.chunks.size());
+ qDebug(stats) << "Used memory before GC:" << usedBefore;
+ qDebug(stats) << "Used memory after GC:" << usedAfter;
+ qDebug(stats) << "Freed up bytes :" << (usedBefore - usedAfter);
+ qDebug(stats) << "Freed up chunks :" << (oldChunks - blockAllocator.chunks.size());
size_t lost = blockAllocator.allocatedMem() - memInBins - usedAfter;
if (lost)
- qDebug() << "!!!!!!!!!!!!!!!!!!!!! LOST MEM:" << lost << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!";
+ qDebug(stats) << "!!!!!!!!!!!!!!!!!!!!! LOST MEM:" << lost << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!";
if (largeItemsBefore || largeItemsAfter) {
- qDebug() << "Large item memory before GC:" << largeItemsBefore;
- qDebug() << "Large item memory after GC:" << largeItemsAfter;
- qDebug() << "Large item memory freed up:" << (largeItemsBefore - largeItemsAfter);
+ qDebug(stats) << "Large item memory before GC:" << largeItemsBefore;
+ qDebug(stats) << "Large item memory after GC:" << largeItemsAfter;
+ qDebug(stats) << "Large item memory freed up:" << (largeItemsBefore - largeItemsAfter);
}
for (auto it = freedObjectsSorted.cbegin(); it != freedObjectsSorted.cend(); ++it) {
- qDebug().noquote() << QString::fromLatin1("Freed JS type: %1 (%2 instances)").arg(QString::fromLatin1(it->first), QString::number(it->second));
+ qDebug(stats).noquote() << QString::fromLatin1("Freed JS type: %1 (%2 instances)").arg(QString::fromLatin1(it->first), QString::number(it->second));
}
- qDebug() << "======== End GC ========";
+ qDebug(stats) << "======== End GC ========";
}
+ if (gcStats)
+ statistics.maxUsedMem = qMax(statistics.maxUsedMem, getUsedMem() + getLargeItemsMem());
+
if (aggressiveGC) {
// ensure we don't 'loose' any memory
Q_ASSERT(blockAllocator.allocatedMem() == getUsedMem() + dumpBins(&blockAllocator, false));
@@ -1273,6 +1258,8 @@ MemoryManager::~MemoryManager()
{
delete m_persistentValues;
+ dumpStats();
+
sweep(/*lastSweep*/true);
blockAllocator.freeAll();
hugeItemAllocator.freeAll();
@@ -1288,30 +1275,20 @@ MemoryManager::~MemoryManager()
void MemoryManager::dumpStats() const
{
-#ifdef DETAILED_MM_STATS
- std::cerr << "=================" << std::endl;
- std::cerr << "Allocation stats:" << std::endl;
- std::cerr << "Requests for each chunk size:" << std::endl;
- for (int i = 0; i < allocSizeCounters.size(); ++i) {
- if (unsigned count = allocSizeCounters[i]) {
- std::cerr << "\t" << (i << 4) << " bytes chunks: " << count << std::endl;
- }
- }
-#endif // DETAILED_MM_STATS
-}
+ if (!gcStats)
+ return;
-#ifdef DETAILED_MM_STATS
-void MemoryManager::willAllocate(std::size_t size)
-{
- unsigned alignedSize = (size + 15) >> 4;
- QVector<unsigned> &counters = allocSizeCounters;
- if ((unsigned) counters.size() < alignedSize + 1)
- counters.resize(alignedSize + 1);
- counters[alignedSize]++;
+ const QLoggingCategory &stats = lcGcStats();
+ qDebug(stats) << "Qml GC memory allocation statistics:";
+ qDebug(stats) << "Total memory allocated:" << statistics.maxReservedMem;
+ qDebug(stats) << "Max memory used before a GC run:" << statistics.maxAllocatedMem;
+ qDebug(stats) << "Max memory used after a GC run:" << statistics.maxUsedMem;
+ qDebug(stats) << "Requests for different item sizes:";
+ for (int i = 1; i < BlockAllocator::NumBins - 1; ++i)
+ qDebug(stats) << " <" << (i << Chunk::SlotSizeShift) << " bytes: " << statistics.allocations[i];
+ qDebug(stats) << " >=" << ((BlockAllocator::NumBins - 1) << Chunk::SlotSizeShift) << " bytes: " << statistics.allocations[BlockAllocator::NumBins - 1];
}
-#endif // DETAILED_MM_STATS
-
void MemoryManager::collectFromJSStack(MarkStack *markStack) const
{
Value *v = engine->jsStackBase;
diff --git a/src/qml/memory/qv4mm_p.h b/src/qml/memory/qv4mm_p.h
index e16a0ca544..fb21481d5b 100644
--- a/src/qml/memory/qv4mm_p.h
+++ b/src/qml/memory/qv4mm_p.h
@@ -58,8 +58,6 @@
#include <private/qv4mmdefs_p.h>
#include <QVector>
-//#define DETAILED_MM_STATS
-
#define QV4_MM_MAXBLOCK_SHIFT "QV4_MM_MAXBLOCK_SHIFT"
#define QV4_MM_MAX_CHUNK_SIZE "QV4_MM_MAX_CHUNK_SIZE"
#define QV4_MM_STATS "QV4_MM_STATS"
@@ -122,9 +120,6 @@ struct BlockAllocator {
: chunkAllocator(chunkAllocator), engine(engine)
{
memset(freeBins, 0, sizeof(freeBins));
-#if MM_DEBUG
- memset(allocations, 0, sizeof(allocations));
-#endif
}
enum { NumBins = 8 };
@@ -133,10 +128,6 @@ struct BlockAllocator {
return nSlots >= NumBins ? NumBins - 1 : nSlots;
}
-#if MM_DEBUG
- void stats();
-#endif
-
HeapItem *allocate(size_t size, bool forceAllocation = false);
size_t totalSlots() const {
@@ -166,9 +157,7 @@ struct BlockAllocator {
ChunkAllocator *chunkAllocator;
ExecutionEngine *engine;
std::vector<Chunk *> chunks;
-#if MM_DEBUG
- uint allocations[NumBins];
-#endif
+ uint *allocationStats = nullptr;
};
struct HugeItemAllocator {
@@ -453,10 +442,6 @@ protected:
Heap::Base *allocData(std::size_t size);
Heap::Object *allocObjectWithMemberData(const QV4::VTable *vtable, uint nMembers);
-#ifdef DETAILED_MM_STATS
- void willAllocate(std::size_t size);
-#endif // DETAILED_MM_STATS
-
private:
void collectFromJSStack(MarkStack *markStack) const;
void mark();
@@ -481,6 +466,14 @@ public:
bool gcBlocked = false;
bool aggressiveGC = false;
bool gcStats = false;
+ bool gcCollectorStats = false;
+
+ struct {
+ size_t maxReservedMem = 0;
+ size_t maxAllocatedMem = 0;
+ size_t maxUsedMem = 0;
+ uint allocations[BlockAllocator::NumBins];
+ } statistics;
};
}
diff --git a/src/qml/qml/qqmlcomponent.cpp b/src/qml/qml/qqmlcomponent.cpp
index 8ec8669c60..e895f1df1b 100644
--- a/src/qml/qml/qqmlcomponent.cpp
+++ b/src/qml/qml/qqmlcomponent.cpp
@@ -496,8 +496,7 @@ QQmlComponent::QQmlComponent(QQmlEngine *engine, QObject *parent)
Create a QQmlComponent from the given \a url and give it the
specified \a parent and \a engine.
- Ensure that the URL provided is full and correct, in particular, use
- \l QUrl::fromLocalFile() when loading a file from the local filesystem.
+ \include qqmlcomponent.qdoc url-note
\sa loadUrl()
*/
@@ -511,8 +510,7 @@ QQmlComponent::QQmlComponent(QQmlEngine *engine, const QUrl &url, QObject *paren
specified \a parent and \a engine. If \a mode is \l Asynchronous,
the component will be loaded and compiled asynchronously.
- Ensure that the URL provided is full and correct, in particular, use
- \l QUrl::fromLocalFile() when loading a file from the local filesystem.
+ \include qqmlcomponent.qdoc url-note
\sa loadUrl()
*/
@@ -548,7 +546,7 @@ QQmlComponent::QQmlComponent(QQmlEngine *engine, const QString &fileName,
: QQmlComponent(engine, parent)
{
Q_D(QQmlComponent);
- const QUrl url = QDir::isAbsolutePath(fileName) ? QUrl::fromLocalFile(fileName) : d->engine->baseUrl().resolved(QUrl(fileName));
+ const QUrl url = QDir::isAbsolutePath(fileName) ? QUrl::fromLocalFile(fileName) : QUrl(fileName);
d->loadUrl(url, mode);
}
@@ -561,7 +559,7 @@ QQmlComponent::QQmlComponent(QQmlEngine *engine, QV4::CompiledData::CompilationU
Q_D(QQmlComponent);
d->compilationUnit = compilationUnit;
d->start = start;
- d->url = compilationUnit->url();
+ d->url = compilationUnit->finalUrl();
d->progress = 1.0;
}
@@ -608,8 +606,7 @@ QQmlContext *QQmlComponent::creationContext() const
/*!
Load the QQmlComponent from the provided \a url.
- Ensure that the URL provided is full and correct, in particular, use
- \l QUrl::fromLocalFile() when loading a file from the local filesystem.
+ \include qqmlcomponent.qdoc url-note
*/
void QQmlComponent::loadUrl(const QUrl &url)
{
@@ -621,8 +618,7 @@ void QQmlComponent::loadUrl(const QUrl &url)
Load the QQmlComponent from the provided \a url.
If \a mode is \l Asynchronous, the component will be loaded and compiled asynchronously.
- Ensure that the URL provided is full and correct, in particular, use
- \l QUrl::fromLocalFile() when loading a file from the local filesystem.
+ \include qqmlcomponent.qdoc url-note
*/
void QQmlComponent::loadUrl(const QUrl &url, QQmlComponent::CompilationMode mode)
{
@@ -635,11 +631,21 @@ void QQmlComponentPrivate::loadUrl(const QUrl &newUrl, QQmlComponent::Compilatio
Q_Q(QQmlComponent);
clear();
- if ((newUrl.isRelative() && !newUrl.isEmpty())
- || newUrl.scheme() == QLatin1String("file")) // Workaround QTBUG-11929
- url = engine->baseUrl().resolved(newUrl);
- else
+ if (newUrl.isRelative()) {
+ // The new URL is a relative URL like QUrl("main.qml").
+ url = engine->baseUrl().resolved(QUrl(newUrl.toString()));
+ } else if (engine->baseUrl().isLocalFile() && newUrl.isLocalFile() && !QDir::isAbsolutePath(newUrl.toLocalFile())) {
+ // The new URL is a file on disk but it's a relative path; e.g.:
+ // QUrl::fromLocalFile("main.qml") or QUrl("file:main.qml")
+ // We need to remove the scheme so that it becomes a relative URL with a relative path:
+ QUrl fixedUrl(newUrl);
+ fixedUrl.setScheme(QString());
+ // Then, turn it into an absolute URL with an absolute path by resolving it against the engine's baseUrl().
+ // This is a compatibility hack for QTBUG-58837.
+ url = engine->baseUrl().resolved(fixedUrl);
+ } else {
url = newUrl;
+ }
if (newUrl.isEmpty()) {
QQmlError error;
@@ -1073,7 +1079,6 @@ void QQmlComponentPrivate::incubateObject(
QQmlComponentPrivate *componentPriv = QQmlComponentPrivate::get(component);
incubatorPriv->compilationUnit = componentPriv->compilationUnit;
- incubatorPriv->compilationUnit->addref();
incubatorPriv->enginePriv = enginePriv;
incubatorPriv->creator.reset(new QQmlObjectCreator(context, componentPriv->compilationUnit, componentPriv->creationContext));
incubatorPriv->subComponentToCreate = componentPriv->start;
diff --git a/src/qml/qml/qqmlcontext.cpp b/src/qml/qml/qqmlcontext.cpp
index 37cb328b36..59e2c83a63 100644
--- a/src/qml/qml/qqmlcontext.cpp
+++ b/src/qml/qml/qqmlcontext.cpp
@@ -845,14 +845,14 @@ QV4::IdentifierHash<int> &QQmlContextData::detachedPropertyNames()
QUrl QQmlContextData::url() const
{
if (typeCompilationUnit)
- return typeCompilationUnit->url();
+ return typeCompilationUnit->finalUrl();
return baseUrl;
}
QString QQmlContextData::urlString() const
{
if (typeCompilationUnit)
- return typeCompilationUnit->fileName();
+ return typeCompilationUnit->finalUrlString();
return baseUrlString;
}
diff --git a/src/qml/qml/qqmldata_p.h b/src/qml/qml/qqmldata_p.h
index 63994a392d..5794e6f0c5 100644
--- a/src/qml/qml/qqmldata_p.h
+++ b/src/qml/qml/qqmldata_p.h
@@ -156,18 +156,21 @@ public:
quint32 hasInterceptorMetaObject:1;
quint32 hasVMEMetaObject:1;
quint32 parentFrozen:1;
- quint32 dummy:22;
+ quint32 dummy:6;
// When bindingBitsSize < sizeof(ptr), we store the binding bit flags inside
// bindingBitsValue. When we need more than sizeof(ptr) bits, we allocated
// sufficient space and use bindingBits to point to it.
- int bindingBitsSize;
+ quint32 bindingBitsArraySize : 16;
typedef quintptr BindingBitsType;
+ enum {
+ BitsPerType = sizeof(BindingBitsType) * 8,
+ InlineBindingArraySize = 2
+ };
union {
BindingBitsType *bindingBits;
- BindingBitsType bindingBitsValue;
+ BindingBitsType bindingBitsValue[InlineBindingArraySize];
};
- enum { MaxInlineBits = sizeof(BindingBitsType) * 8 };
struct NotifyList {
quint64 connectionMask;
@@ -259,7 +262,7 @@ public:
bool hasExtendedData() const { return extendedData != 0; }
QHash<int, QObject *> *attachedProperties() const;
- static inline bool wasDeleted(QObject *);
+ static inline bool wasDeleted(const QObject *);
static void markAsDeleted(QObject *);
static void setQueuedForDeletion(QObject *);
@@ -275,6 +278,9 @@ public:
return createPropertyCache(engine, object);
}
+ Q_ALWAYS_INLINE static uint offsetForBit(int bit) { return static_cast<uint>(bit) / BitsPerType; }
+ Q_ALWAYS_INLINE static BindingBitsType bitFlagForBit(int bit) { return BindingBitsType(1) << (static_cast<uint>(bit) & (BitsPerType - 1)); }
+
private:
// For attachedProperties
mutable QQmlDataExtended *extendedData;
@@ -286,26 +292,25 @@ private:
Q_ALWAYS_INLINE bool hasBitSet(int bit) const
{
- if (bindingBitsSize <= bit)
+ uint offset = offsetForBit(bit);
+ if (bindingBitsArraySize <= offset)
return false;
- if (bindingBitsSize == MaxInlineBits)
- return bindingBitsValue & (BindingBitsType(1) << bit);
- else
- return bindingBits[bit / MaxInlineBits] & (BindingBitsType(1) << (bit % MaxInlineBits));
+ const BindingBitsType *bits = (bindingBitsArraySize == InlineBindingArraySize) ? bindingBitsValue : bindingBits;
+ return bits[offset] & bitFlagForBit(bit);
}
};
-bool QQmlData::wasDeleted(QObject *object)
+bool QQmlData::wasDeleted(const QObject *object)
{
if (!object)
return true;
- QObjectPrivate *priv = QObjectPrivate::get(object);
+ const QObjectPrivate *priv = QObjectPrivate::get(object);
if (!priv || priv->wasDeleted)
return true;
- QQmlData *ddata = QQmlData::get(object);
+ const QQmlData *ddata = QQmlData::get(object);
return ddata && ddata->isQueuedForDeletion;
}
diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp
index 20f9b6439d..d53c94e901 100644
--- a/src/qml/qml/qqmlengine.cpp
+++ b/src/qml/qml/qqmlengine.cpp
@@ -110,7 +110,10 @@ Q_DECLARE_METATYPE(QQmlProperty)
QT_BEGIN_NAMESPACE
typedef QQmlData::BindingBitsType BindingBitsType;
-enum { MaxInlineBits = QQmlData::MaxInlineBits };
+enum {
+ BitsPerType = QQmlData::BitsPerType,
+ InlineBindingArraySize = QQmlData::InlineBindingArraySize
+};
void qmlRegisterBaseTypes(const char *uri, int versionMajor, int versionMinor)
{
@@ -747,11 +750,12 @@ QQmlData::QQmlData()
: ownedByQml1(false), ownMemory(true), indestructible(true), explicitIndestructibleSet(false),
hasTaintedV4Object(false), isQueuedForDeletion(false), rootObjectInCreation(false),
hasInterceptorMetaObject(false), hasVMEMetaObject(false), parentFrozen(false),
- bindingBitsSize(MaxInlineBits), bindingBitsValue(0), notifyList(0),
+ bindingBitsArraySize(InlineBindingArraySize), notifyList(0),
bindings(0), signalHandlers(0), nextContextObject(0), prevContextObject(0),
lineNumber(0), columnNumber(0), jsEngineId(0), compilationUnit(0),
propertyCache(0), guards(0), extendedData(0)
{
+ memset(bindingBitsValue, 0, sizeof(bindingBitsValue));
init();
}
@@ -1825,7 +1829,7 @@ void QQmlData::destroyed(QObject *object)
signalHandler = next;
}
- if (bindingBitsSize > MaxInlineBits)
+ if (bindingBitsArraySize > InlineBindingArraySize)
free(bindingBits);
if (propertyCache)
@@ -1874,47 +1878,35 @@ void QQmlData::parentChanged(QObject *object, QObject *parent)
static void QQmlData_setBit(QQmlData *data, QObject *obj, int bit)
{
- if (Q_UNLIKELY(data->bindingBitsSize <= bit)) {
+ uint offset = QQmlData::offsetForBit(bit);
+ BindingBitsType *bits = (data->bindingBitsArraySize == InlineBindingArraySize) ? data->bindingBitsValue : data->bindingBits;
+ if (Q_UNLIKELY(data->bindingBitsArraySize <= offset)) {
int props = QQmlMetaObject(obj).propertyCount();
Q_ASSERT(bit < 2 * props);
- int arraySize = (2 * props + MaxInlineBits - 1) / MaxInlineBits;
- Q_ASSERT(arraySize > 1);
-
- // special handling for 32 here is to make sure we wipe the first byte
- // when going from bindingBitsValue to bindingBits, and preserve the old
- // set bits so we can restore them after the allocation
- int oldArraySize = data->bindingBitsSize > MaxInlineBits ? data->bindingBitsSize / MaxInlineBits : 0;
- quintptr oldValue = data->bindingBitsSize == MaxInlineBits ? data->bindingBitsValue : 0;
-
- data->bindingBits = static_cast<BindingBitsType *>(realloc((data->bindingBitsSize == MaxInlineBits) ? 0 : data->bindingBits,
- arraySize * sizeof(BindingBitsType)));
-
- memset(data->bindingBits + oldArraySize,
- 0x00,
- sizeof(BindingBitsType) * (arraySize - oldArraySize));
+ uint arraySize = (2 * static_cast<uint>(props) + BitsPerType - 1) / BitsPerType;
+ Q_ASSERT(arraySize > InlineBindingArraySize && arraySize > data->bindingBitsArraySize);
- data->bindingBitsSize = arraySize * MaxInlineBits;
+ BindingBitsType *newBits = static_cast<BindingBitsType *>(malloc(arraySize*sizeof(BindingBitsType)));
+ memcpy(newBits, bits, data->bindingBitsArraySize * sizeof(BindingBitsType));
+ memset(newBits + data->bindingBitsArraySize, 0, sizeof(BindingBitsType) * (arraySize - data->bindingBitsArraySize));
- // reinstate bindingBitsValue after we dropped it
- if (oldValue) {
- memcpy(data->bindingBits, &oldValue, sizeof(oldValue));
- }
+ if (data->bindingBitsArraySize > InlineBindingArraySize)
+ free(bits);
+ data->bindingBits = newBits;
+ bits = newBits;
+ data->bindingBitsArraySize = arraySize;
}
-
- if (data->bindingBitsSize == MaxInlineBits)
- data->bindingBitsValue |= BindingBitsType(1) << bit;
- else
- data->bindingBits[bit / MaxInlineBits] |= (BindingBitsType(1) << (bit % MaxInlineBits));
+ Q_ASSERT(offset < data->bindingBitsArraySize);
+ bits[offset] |= QQmlData::bitFlagForBit(bit);
}
static void QQmlData_clearBit(QQmlData *data, int bit)
{
- if (data->bindingBitsSize > bit) {
- if (data->bindingBitsSize == MaxInlineBits)
- data->bindingBitsValue &= ~(BindingBitsType(1) << (bit % MaxInlineBits));
- else
- data->bindingBits[bit / MaxInlineBits] &= ~(BindingBitsType(1) << (bit % MaxInlineBits));
+ uint offset = QQmlData::offsetForBit(bit);
+ if (data->bindingBitsArraySize > offset) {
+ BindingBitsType *bits = (data->bindingBitsArraySize == InlineBindingArraySize) ? data->bindingBitsValue : data->bindingBits;
+ bits[offset] &= ~QQmlData::bitFlagForBit(bit);
}
}
diff --git a/src/qml/qml/qqmlincubator.cpp b/src/qml/qml/qqmlincubator.cpp
index 6d0e4b915a..9855c27375 100644
--- a/src/qml/qml/qqmlincubator.cpp
+++ b/src/qml/qml/qqmlincubator.cpp
@@ -272,7 +272,7 @@ void QQmlIncubatorPrivate::incubate(QQmlInstantiationInterrupt &i)
if (!compilationUnit)
return;
- QML_MEMORY_SCOPE_URL(compilationUnit->url());
+ QML_MEMORY_SCOPE_URL(compilationUnit->finalUrl());
QExplicitlySharedDataPointer<QQmlIncubatorPrivate> protectThis(this);
@@ -377,23 +377,6 @@ finishIncubate:
}
}
-void QQmlIncubatorPrivate::cancel(QObject *object, QQmlContext *context)
-{
- if (!context)
- context = qmlContext(object);
- if (!context)
- return;
-
- QQmlContextData *data = QQmlContextData::get(context);
- QQmlIncubatorPrivate *p = data->incubator;
- if (!p)
- return;
-
- p->vmeGuard.unguard(object);
- if (!p->creator.isNull())
- p->creator->cancel(object);
-}
-
/*!
Incubate objects for \a msecs, or until there are no more objects to incubate.
*/
diff --git a/src/qml/qml/qqmlincubator_p.h b/src/qml/qml/qqmlincubator_p.h
index 758e0a29f6..676ba1a29a 100644
--- a/src/qml/qml/qqmlincubator_p.h
+++ b/src/qml/qml/qqmlincubator_p.h
@@ -102,9 +102,6 @@ public:
void forceCompletion(QQmlInstantiationInterrupt &i);
void incubate(QQmlInstantiationInterrupt &i);
-
- // used by Qt Quick Controls 2
- Q_QML_PRIVATE_EXPORT static void cancel(QObject *object, QQmlContext *context = 0);
};
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp
index 7761eb4677..7caab2a5d3 100644
--- a/src/qml/qml/qqmlobjectcreator.cpp
+++ b/src/qml/qml/qqmlobjectcreator.cpp
@@ -445,7 +445,7 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const
QString string = binding->valueAsString(qmlUnit);
// Encoded dir-separators defeat QUrl processing - decode them first
string.replace(QLatin1String("%2f"), QLatin1String("/"), Qt::CaseInsensitive);
- QUrl value = string.isEmpty() ? QUrl() : compilationUnit->url().resolved(QUrl(string));
+ QUrl value = string.isEmpty() ? QUrl() : compilationUnit->finalUrl().resolved(QUrl(string));
// Apply URL interceptor
if (engine->urlInterceptor())
value = engine->urlInterceptor()->intercept(value, QQmlAbstractUrlInterceptor::UrlString);
@@ -643,7 +643,8 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const
} else if (property->propType() == qMetaTypeId<QList<QUrl> >()) {
Q_ASSERT(binding->type == QV4::CompiledData::Binding::Type_String);
QString urlString = binding->valueAsString(qmlUnit);
- QUrl u = urlString.isEmpty() ? QUrl() : compilationUnit->url().resolved(QUrl(urlString));
+ QUrl u = urlString.isEmpty() ? QUrl()
+ : compilationUnit->finalUrl().resolved(QUrl(urlString));
QList<QUrl> value;
value.append(u);
property->writeProperty(_qobject, &value, propertyWriteFlags);
@@ -1103,12 +1104,9 @@ void QQmlObjectCreator::registerObjectWithContextById(const QV4::CompiledData::O
context->setIdProperty(object->id, instance);
}
-QV4::QmlContext *QQmlObjectCreator::currentQmlContext()
+void QQmlObjectCreator::createQmlContext()
{
- if (!_qmlContext->isManaged())
- _qmlContext->setM(QV4::QmlContext::create(v4->rootContext(), context, _scopeObject));
-
- return _qmlContext;
+ _qmlContext->setM(QV4::QmlContext::create(v4->rootContext(), context, _scopeObject));
}
QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isContextObject)
@@ -1349,21 +1347,6 @@ QQmlContextData *QQmlObjectCreator::finalize(QQmlInstantiationInterrupt &interru
return sharedState->rootContext;
}
-void QQmlObjectCreator::cancel(QObject *object)
-{
- int last = sharedState->allCreatedObjects.count() - 1;
- int i = last;
- while (i >= 0) {
- if (sharedState->allCreatedObjects.at(i) == object) {
- if (i < last)
- qSwap(sharedState->allCreatedObjects[i], sharedState->allCreatedObjects[last]);
- sharedState->allCreatedObjects.pop();
- break;
- }
- --i;
- }
-}
-
void QQmlObjectCreator::clear()
{
if (phase == Done || phase == Finalizing || phase == Startup)
diff --git a/src/qml/qml/qqmlobjectcreator_p.h b/src/qml/qml/qqmlobjectcreator_p.h
index 593d89e5d5..f4c03af5b7 100644
--- a/src/qml/qml/qqmlobjectcreator_p.h
+++ b/src/qml/qml/qqmlobjectcreator_p.h
@@ -92,7 +92,6 @@ public:
bool populateDeferredProperties(QObject *instance, QQmlData::DeferredData *deferredData);
bool populateDeferredBinding(const QQmlProperty &qmlProperty, QQmlData::DeferredData *deferredData, const QV4::CompiledData::Binding *binding);
QQmlContextData *finalize(QQmlInstantiationInterrupt &interrupt);
- void cancel(QObject *object);
void clear();
QQmlComponentAttached **componentAttachment() const { return &sharedState->componentAttached; }
@@ -124,7 +123,8 @@ private:
void registerObjectWithContextById(const QV4::CompiledData::Object *object, QObject *instance) const;
- QV4::QmlContext *currentQmlContext();
+ inline QV4::QmlContext *currentQmlContext();
+ Q_NEVER_INLINE void createQmlContext();
enum Phase {
Startup,
@@ -174,6 +174,14 @@ private:
QRecursionWatcher<QQmlObjectCreatorSharedState, &QQmlObjectCreatorSharedState::recursionNode> watcher;
};
+QV4::QmlContext *QQmlObjectCreator::currentQmlContext()
+{
+ if (!_qmlContext->isManaged())
+ _qmlContext->setM(QV4::QmlContext::create(v4->rootContext(), context, _scopeObject));
+
+ return _qmlContext;
+}
+
QT_END_NAMESPACE
#endif // QQMLOBJECTCREATOR_P_H
diff --git a/src/qml/qml/qqmlproperty.cpp b/src/qml/qml/qqmlproperty.cpp
index 9a138dcf80..50d9f13049 100644
--- a/src/qml/qml/qqmlproperty.cpp
+++ b/src/qml/qml/qqmlproperty.cpp
@@ -223,6 +223,22 @@ QQmlProperty::QQmlProperty(QObject *obj, const QString &name, QQmlEngine *engine
if (!isValid()) { d->object = 0; d->context = 0; d->engine = 0; }
}
+QQmlProperty QQmlPropertyPrivate::create(QObject *target, const QString &propertyName, QQmlContextData *context)
+{
+ QQmlProperty result;
+ auto d = new QQmlPropertyPrivate;
+ result.d = d;
+ d->context = context;
+ d->engine = context ? context->engine : nullptr;
+ d->initProperty(target, propertyName);
+ if (!result.isValid()) {
+ d->object = nullptr;
+ d->context = nullptr;
+ d->engine = nullptr;
+ }
+ return result;
+}
+
QQmlPropertyPrivate::QQmlPropertyPrivate()
: context(0), engine(0), object(0), isNameCached(false)
{
@@ -241,89 +257,93 @@ void QQmlPropertyPrivate::initProperty(QObject *obj, const QString &name)
QQmlTypeNameCache *typeNameCache = context?context->imports:0;
- const auto path = name.splitRef(QLatin1Char('.'));
- if (path.isEmpty()) return;
-
QObject *currentObject = obj;
-
- // Everything up to the last property must be an "object type" property
- for (int ii = 0; ii < path.count() - 1; ++ii) {
- const QStringRef &pathName = path.at(ii);
-
- if (typeNameCache) {
- QQmlTypeNameCache::Result r = typeNameCache->query(pathName);
- if (r.isValid()) {
- if (r.type.isValid()) {
- QQmlEnginePrivate *enginePrivate = QQmlEnginePrivate::get(engine);
- QQmlAttachedPropertiesFunc func = r.type.attachedPropertiesFunction(enginePrivate);
- if (!func) return; // Not an attachable type
-
- currentObject = qmlAttachedPropertiesObjectById(r.type.attachedPropertiesId(enginePrivate), currentObject);
- if (!currentObject) return; // Something is broken with the attachable type
- } else if (r.importNamespace) {
- if ((ii + 1) == path.count()) return; // No type following the namespace
-
- ++ii; r = typeNameCache->query(path.at(ii), r.importNamespace);
- if (!r.type.isValid()) return; // Invalid type in namespace
-
- QQmlEnginePrivate *enginePrivate = QQmlEnginePrivate::get(engine);
- QQmlAttachedPropertiesFunc func = r.type.attachedPropertiesFunction(enginePrivate);
- if (!func) return; // Not an attachable type
-
- currentObject = qmlAttachedPropertiesObjectById(r.type.attachedPropertiesId(enginePrivate), currentObject);
- if (!currentObject) return; // Something is broken with the attachable type
-
- } else if (r.scriptIndex != -1) {
- return; // Not a type
- } else {
- Q_ASSERT(!"Unreachable");
+ QVector<QStringRef> path;
+ QStringRef terminal(&name);
+
+ if (name.contains(QLatin1Char('.'))) {
+ path = name.splitRef(QLatin1Char('.'));
+ if (path.isEmpty()) return;
+
+ // Everything up to the last property must be an "object type" property
+ for (int ii = 0; ii < path.count() - 1; ++ii) {
+ const QStringRef &pathName = path.at(ii);
+
+ if (typeNameCache) {
+ QQmlTypeNameCache::Result r = typeNameCache->query(pathName);
+ if (r.isValid()) {
+ if (r.type.isValid()) {
+ QQmlEnginePrivate *enginePrivate = QQmlEnginePrivate::get(engine);
+ QQmlAttachedPropertiesFunc func = r.type.attachedPropertiesFunction(enginePrivate);
+ if (!func) return; // Not an attachable type
+
+ currentObject = qmlAttachedPropertiesObjectById(r.type.attachedPropertiesId(enginePrivate), currentObject);
+ if (!currentObject) return; // Something is broken with the attachable type
+ } else if (r.importNamespace) {
+ if ((ii + 1) == path.count()) return; // No type following the namespace
+
+ ++ii; r = typeNameCache->query(path.at(ii), r.importNamespace);
+ if (!r.type.isValid()) return; // Invalid type in namespace
+
+ QQmlEnginePrivate *enginePrivate = QQmlEnginePrivate::get(engine);
+ QQmlAttachedPropertiesFunc func = r.type.attachedPropertiesFunction(enginePrivate);
+ if (!func) return; // Not an attachable type
+
+ currentObject = qmlAttachedPropertiesObjectById(r.type.attachedPropertiesId(enginePrivate), currentObject);
+ if (!currentObject) return; // Something is broken with the attachable type
+
+ } else if (r.scriptIndex != -1) {
+ return; // Not a type
+ } else {
+ Q_ASSERT(!"Unreachable");
+ }
+ continue;
}
- continue;
+
}
- }
+ QQmlPropertyData local;
+ QQmlPropertyData *property =
+ QQmlPropertyCache::property(engine, currentObject, pathName, context, local);
- QQmlPropertyData local;
- QQmlPropertyData *property =
- QQmlPropertyCache::property(engine, currentObject, pathName, context, local);
+ if (!property) return; // Not a property
+ if (property->isFunction())
+ return; // Not an object property
- if (!property) return; // Not a property
- if (property->isFunction())
- return; // Not an object property
+ if (ii == (path.count() - 2) && QQmlValueTypeFactory::isValueType(property->propType())) {
+ // We're now at a value type property
+ const QMetaObject *valueTypeMetaObject = QQmlValueTypeFactory::metaObjectForMetaType(property->propType());
+ if (!valueTypeMetaObject) return; // Not a value type
- if (ii == (path.count() - 2) && QQmlValueTypeFactory::isValueType(property->propType())) {
- // We're now at a value type property
- const QMetaObject *valueTypeMetaObject = QQmlValueTypeFactory::metaObjectForMetaType(property->propType());
- if (!valueTypeMetaObject) return; // Not a value type
+ int idx = valueTypeMetaObject->indexOfProperty(path.last().toUtf8().constData());
+ if (idx == -1) return; // Value type property does not exist
- int idx = valueTypeMetaObject->indexOfProperty(path.last().toUtf8().constData());
- if (idx == -1) return; // Value type property does not exist
+ QMetaProperty vtProp = valueTypeMetaObject->property(idx);
- QMetaProperty vtProp = valueTypeMetaObject->property(idx);
+ Q_ASSERT(vtProp.userType() <= 0x0000FFFF);
+ Q_ASSERT(idx <= 0x0000FFFF);
- Q_ASSERT(vtProp.userType() <= 0x0000FFFF);
- Q_ASSERT(idx <= 0x0000FFFF);
+ object = currentObject;
+ core = *property;
+ valueTypeData.setFlags(QQmlPropertyData::flagsForProperty(vtProp));
+ valueTypeData.setPropType(vtProp.userType());
+ valueTypeData.setCoreIndex(idx);
- object = currentObject;
- core = *property;
- valueTypeData.setFlags(QQmlPropertyData::flagsForProperty(vtProp));
- valueTypeData.setPropType(vtProp.userType());
- valueTypeData.setCoreIndex(idx);
+ return;
+ } else {
+ if (!property->isQObject())
+ return; // Not an object property
- return;
- } else {
- if (!property->isQObject())
- return; // Not an object property
+ property->readProperty(currentObject, &currentObject);
+ if (!currentObject) return; // No value
- property->readProperty(currentObject, &currentObject);
- if (!currentObject) return; // No value
+ }
}
+ terminal = path.last();
}
- const QStringRef &terminal = path.last();
-
if (terminal.count() >= 3 &&
terminal.at(0) == QLatin1Char('o') &&
terminal.at(1) == QLatin1Char('n') &&
diff --git a/src/qml/qml/qqmlproperty_p.h b/src/qml/qml/qqmlproperty_p.h
index 53062a2f13..7a66d8113c 100644
--- a/src/qml/qml/qqmlproperty_p.h
+++ b/src/qml/qml/qqmlproperty_p.h
@@ -144,6 +144,8 @@ public:
static void flushSignal(const QObject *sender, int signal_index);
static QVariant resolvedUrlSequence(const QVariant &value, QQmlContextData *context);
+ static QQmlProperty create(QObject *target, const QString &propertyName, QQmlContextData *context);
+
};
Q_DECLARE_OPERATORS_FOR_FLAGS(QQmlPropertyPrivate::BindingFlags)
diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp
index a4db62eebf..4b6e69e617 100644
--- a/src/qml/qml/qqmltypeloader.cpp
+++ b/src/qml/qml/qqmltypeloader.cpp
@@ -356,8 +356,10 @@ qreal QQmlDataBlob::progress() const
}
/*!
-Returns the blob url passed to the constructor. If a network redirect
-happens while fetching the data, this url remains the same.
+Returns the physical url of the data. Initially this is the same as
+finalUrl(), but if a network redirect happens while fetching the data, this url
+is updated to reflect the new location. Also, if a URL interceptor is set, it
+will work on this URL and leave finalUrl() alone.
\sa finalUrl()
*/
@@ -366,16 +368,25 @@ QUrl QQmlDataBlob::url() const
return m_url;
}
+QString QQmlDataBlob::urlString() const
+{
+ if (m_urlString.isEmpty())
+ m_urlString = m_url.toString();
+
+ return m_urlString;
+}
+
/*!
-Returns the final url of the data. Initially this is the same as
-url(), but if a network redirect happens while fetching the data, this url
-is updated to reflect the new location.
+Returns the logical URL to be used for resolving further URLs referred to in
+the code.
-May only be called from the load thread, or after the blob isCompleteOrError().
+This is the blob url passed to the constructor. If a network redirect
+happens while fetching the data, this url remains the same.
+
+\sa url()
*/
QUrl QQmlDataBlob::finalUrl() const
{
- Q_ASSERT(isCompleteOrError() || (m_typeLoader && m_typeLoader->m_thread->isThisThread()));
return m_finalUrl;
}
@@ -384,7 +395,6 @@ Returns the finalUrl() as a string.
*/
QString QQmlDataBlob::finalUrlString() const
{
- Q_ASSERT(isCompleteOrError() || (m_typeLoader && m_typeLoader->m_thread->isThisThread()));
if (m_finalUrlString.isEmpty())
m_finalUrlString = m_finalUrl.toString();
@@ -433,7 +443,7 @@ void QQmlDataBlob::setError(const QList<QQmlError> &errors)
m_data.setStatus(Error);
if (dumpErrors()) {
- qWarning().nospace() << "Errors for " << m_finalUrl.toString();
+ qWarning().nospace() << "Errors for " << urlString();
for (int ii = 0; ii < errors.count(); ++ii)
qWarning().nospace() << " " << qPrintable(errors.at(ii).toString());
}
@@ -472,7 +482,7 @@ void QQmlDataBlob::setError(const QString &description)
{
QQmlError e;
e.setDescription(description);
- e.setUrl(finalUrl());
+ e.setUrl(url());
setError(e);
}
@@ -537,7 +547,7 @@ void QQmlDataBlob::networkError(QNetworkReply::NetworkError networkError)
Q_UNUSED(networkError);
QQmlError error;
- error.setUrl(m_finalUrl);
+ error.setUrl(m_url);
const char *errorString = 0;
switch (networkError) {
@@ -654,7 +664,7 @@ void QQmlDataBlob::tryDone()
addref();
#ifdef DATABLOB_DEBUG
- qWarning("QQmlDataBlob::done() %s", qPrintable(url().toString()));
+ qWarning("QQmlDataBlob::done() %s", qPrintable(urlString()));
#endif
done();
@@ -893,7 +903,7 @@ void QQmlTypeLoaderThread::callCompletedMain(QQmlDataBlob *b)
{
QML_MEMORY_SCOPE_URL(b->url());
#ifdef DATABLOB_DEBUG
- qWarning("QQmlTypeLoaderThread: %s completed() callback", qPrintable(b->url().toString()));
+ qWarning("QQmlTypeLoaderThread: %s completed() callback", qPrintable(b->urlString()));
#endif
b->completed();
b->release();
@@ -903,7 +913,7 @@ void QQmlTypeLoaderThread::callDownloadProgressChangedMain(QQmlDataBlob *b, qrea
{
#ifdef DATABLOB_DEBUG
qWarning("QQmlTypeLoaderThread: %s downloadProgressChanged(%f) callback",
- qPrintable(b->url().toString()), p);
+ qPrintable(b->urlString()), p);
#endif
b->downloadProgressChanged(p);
b->release();
@@ -1037,7 +1047,7 @@ template<typename Loader>
void QQmlTypeLoader::doLoad(const Loader &loader, QQmlDataBlob *blob, Mode mode)
{
#ifdef DATABLOB_DEBUG
- qWarning("QQmlTypeLoader::doLoad(%s): %s thread", qPrintable(blob->m_url.toString()),
+ qWarning("QQmlTypeLoader::doLoad(%s): %s thread", qPrintable(blob->urlString()),
m_thread->isThisThread()?"Compile":"Engine");
#endif
blob->startLoading();
@@ -1159,7 +1169,7 @@ void QQmlTypeLoader::loadThread(QQmlDataBlob *blob)
}
#ifdef DATABLOB_DEBUG
- qWarning("QQmlDataBlob: requested %s", qPrintable(blob->url().toString()));
+ qWarning("QQmlDataBlob: requested %s", qPrintable(blob->urlString()));
#endif // DATABLOB_DEBUG
#endif // qml_network
}
@@ -1185,14 +1195,15 @@ void QQmlTypeLoader::networkReplyFinished(QNetworkReply *reply)
QVariant redirect = reply->attribute(QNetworkRequest::RedirectionTargetAttribute);
if (redirect.isValid()) {
QUrl url = reply->url().resolved(redirect.toUrl());
- blob->m_finalUrl = url;
+ blob->m_url = url;
+ blob->m_urlString.clear();
QNetworkReply *reply = m_thread->networkAccessManager()->get(QNetworkRequest(url));
QObject *nrp = m_thread->networkReplyProxy();
QObject::connect(reply, SIGNAL(finished()), nrp, SLOT(finished()));
m_networkReplies.insert(reply, blob);
#ifdef DATABLOB_DEBUG
- qWarning("QQmlDataBlob: redirected to %s", qPrintable(blob->m_finalUrl.toString()));
+ qWarning("QQmlDataBlob: redirected to %s", qPrintable(blob->urlString()));
#endif
return;
}
@@ -1348,7 +1359,7 @@ bool QQmlTypeLoader::Blob::fetchQmldir(const QUrl &url, const QV4::CompiledData:
bool QQmlTypeLoader::Blob::updateQmldir(QQmlQmldirData *data, const QV4::CompiledData::Import *import, QList<QQmlError> *errors)
{
- QString qmldirIdentifier = data->url().toString();
+ QString qmldirIdentifier = data->urlString();
QString qmldirUrl = qmldirIdentifier.left(qmldirIdentifier.lastIndexOf(QLatin1Char('/')) + 1);
typeLoader()->setQmldirContent(qmldirIdentifier, data->content());
@@ -2104,7 +2115,7 @@ bool QQmlTypeData::tryLoadFromDiskCache()
{
QString error;
if (!unit->loadFromDisk(url(), m_backupSourceCode.sourceTimeStamp(), v4->iselFactory.data(), &error)) {
- qCDebug(DBG_DISK_CACHE) << "Error loading" << url().toString() << "from disk cache:" << error;
+ qCDebug(DBG_DISK_CACHE) << "Error loading" << urlString() << "from disk cache:" << error;
return false;
}
}
@@ -2224,10 +2235,10 @@ void QQmlTypeData::done()
if (script.script->isError()) {
QList<QQmlError> errors = script.script->errors();
QQmlError error;
- error.setUrl(finalUrl());
+ error.setUrl(url());
error.setLine(script.location.line);
error.setColumn(script.location.column);
- error.setDescription(QQmlTypeLoader::tr("Script %1 unavailable").arg(script.script->url().toString()));
+ error.setDescription(QQmlTypeLoader::tr("Script %1 unavailable").arg(script.script->urlString()));
errors.prepend(error);
setError(errors);
return;
@@ -2244,7 +2255,7 @@ void QQmlTypeData::done()
QList<QQmlError> errors = type.typeData->errors();
QQmlError error;
- error.setUrl(finalUrl());
+ error.setUrl(url());
error.setLine(type.location.line);
error.setColumn(type.location.column);
error.setDescription(QQmlTypeLoader::tr("Type %1 unavailable").arg(typeName));
@@ -2263,7 +2274,7 @@ void QQmlTypeData::done()
QList<QQmlError> errors = type.typeData->errors();
QQmlError error;
- error.setUrl(finalUrl());
+ error.setUrl(url());
error.setLine(type.location.line);
error.setColumn(type.location.column);
error.setDescription(QQmlTypeLoader::tr("Type %1 unavailable").arg(typeName));
@@ -2293,7 +2304,7 @@ void QQmlTypeData::done()
// verify if any dependencies changed if we're using a cache
if (m_document.isNull() && !m_compiledData->verifyChecksum(dependencyHasher)) {
- qCDebug(DBG_DISK_CACHE) << "Checksum mismatch for cached version of" << m_compiledData->url().toString();
+ qCDebug(DBG_DISK_CACHE) << "Checksum mismatch for cached version of" << m_compiledData->fileName();
if (!loadFromSource())
return;
m_backupSourceCode = SourceCodeData();
@@ -2458,7 +2469,7 @@ bool QQmlTypeData::loadFromSource()
errors.reserve(compiler.errors.count());
for (const QQmlJS::DiagnosticMessage &msg : qAsConst(compiler.errors)) {
QQmlError e;
- e.setUrl(finalUrl());
+ e.setUrl(url());
e.setLine(msg.loc.startLine);
e.setColumn(msg.loc.startColumn);
e.setDescription(msg.message);
@@ -2475,7 +2486,8 @@ void QQmlTypeData::restoreIR(QQmlRefPointer<QV4::CompiledData::CompilationUnit>
m_document.reset(new QmlIR::Document(isDebugging()));
QmlIR::IRLoader loader(unit->data, m_document.data());
loader.load();
- m_document->jsModule.setFileName(finalUrlString());
+ m_document->jsModule.setFileName(urlString());
+ m_document->jsModule.setFinalUrl(finalUrlString());
m_document->javaScriptCompilationUnit = unit;
continueLoadFromIR();
}
@@ -2598,7 +2610,7 @@ void QQmlTypeData::compile(const QQmlRefPointer<QQmlTypeNameCache> &typeNameCach
// ignore error, keep using the in-memory compilation unit.
}
} else {
- qCDebug(DBG_DISK_CACHE) << "Error saving cached version of" << m_compiledData->url().toString() << "to disk:" << errorString;
+ qCDebug(DBG_DISK_CACHE) << "Error saving cached version of" << m_compiledData->fileName() << "to disk:" << errorString;
}
}
}
@@ -2973,7 +2985,7 @@ void QQmlScriptBlob::dataReceived(const SourceCodeData &data)
initializeFromCompilationUnit(unit);
return;
} else {
- qCDebug(DBG_DISK_CACHE()) << "Error loading" << url().toString() << "from disk cache:" << error;
+ qCDebug(DBG_DISK_CACHE()) << "Error loading" << urlString() << "from disk cache:" << error;
}
}
@@ -2991,7 +3003,9 @@ void QQmlScriptBlob::dataReceived(const SourceCodeData &data)
QmlIR::ScriptDirectivesCollector collector(&irUnit.jsParserEngine, &irUnit.jsGenerator);
QList<QQmlError> errors;
- QQmlRefPointer<QV4::CompiledData::CompilationUnit> unit = QV4::Script::precompile(&irUnit.jsModule, &irUnit.jsGenerator, v4, finalUrl(), source, &errors, &collector);
+ QQmlRefPointer<QV4::CompiledData::CompilationUnit> unit = QV4::Script::precompile(
+ &irUnit.jsModule, &irUnit.jsGenerator, v4, urlString(), finalUrlString(),
+ source, &errors, &collector);
// No need to addref on unit, it's initial refcount is 1
source.clear();
if (!errors.isEmpty()) {
@@ -3015,7 +3029,7 @@ void QQmlScriptBlob::dataReceived(const SourceCodeData &data)
if (!disableDiskCache() || forceDiskCache()) {
QString errorString;
if (!unit->saveToDisk(url(), &errorString)) {
- qCDebug(DBG_DISK_CACHE()) << "Error saving cached version of" << unit->url().toString() << "to disk:" << errorString;
+ qCDebug(DBG_DISK_CACHE()) << "Error saving cached version of" << unit->fileName() << "to disk:" << errorString;
}
}
@@ -3039,10 +3053,10 @@ void QQmlScriptBlob::done()
if (script.script->isError()) {
QList<QQmlError> errors = script.script->errors();
QQmlError error;
- error.setUrl(finalUrl());
+ error.setUrl(url());
error.setLine(script.location.line);
error.setColumn(script.location.column);
- error.setDescription(QQmlTypeLoader::tr("Script %1 unavailable").arg(script.script->url().toString()));
+ error.setDescription(QQmlTypeLoader::tr("Script %1 unavailable").arg(script.script->urlString()));
errors.prepend(error);
setError(errors);
return;
diff --git a/src/qml/qml/qqmltypeloader_p.h b/src/qml/qml/qqmltypeloader_p.h
index 22ac61968f..ab32bac7b2 100644
--- a/src/qml/qml/qqmltypeloader_p.h
+++ b/src/qml/qml/qqmltypeloader_p.h
@@ -129,6 +129,7 @@ public:
qreal progress() const;
QUrl url() const;
+ QString urlString() const;
QUrl finalUrl() const;
QString finalUrlString() const;
@@ -207,6 +208,7 @@ private:
QUrl m_url;
QUrl m_finalUrl;
+ mutable QString m_urlString;
mutable QString m_finalUrlString;
// List of QQmlDataBlob's that are waiting for me to complete.
diff --git a/src/qml/qml/qqmlvme.cpp b/src/qml/qml/qqmlvme.cpp
index c60f4edc80..72d4ab7e8f 100644
--- a/src/qml/qml/qqmlvme.cpp
+++ b/src/qml/qml/qqmlvme.cpp
@@ -120,18 +120,6 @@ void QQmlVMEGuard::guard(QQmlObjectCreator *creator)
m_contexts[0] = creator->parentContextData();
}
-void QQmlVMEGuard::unguard(QObject *object)
-{
- for (int ii = 0; ii < m_objectCount; ++ii) {
- if (m_objects[ii] == object) {
- if (ii < m_objectCount - 1)
- ::memmove((void *) m_objects[ii], (void *) m_objects[ii + 1], sizeof(QPointer<QObject> *));
- delete m_objects[--m_objectCount];
- break;
- }
- }
-}
-
void QQmlVMEGuard::clear()
{
delete [] m_objects;
diff --git a/src/qml/qml/qqmlvme_p.h b/src/qml/qml/qqmlvme_p.h
index 9585b5b6df..99d63380ad 100644
--- a/src/qml/qml/qqmlvme_p.h
+++ b/src/qml/qml/qqmlvme_p.h
@@ -131,7 +131,6 @@ public:
~QQmlVMEGuard();
void guard(QQmlObjectCreator *);
- void unguard(QObject *);
void clear();
bool isOK() const;
diff --git a/src/qml/types/qqmldelegatemodel.cpp b/src/qml/types/qqmldelegatemodel.cpp
index dc41a16e3b..7a34bab2f5 100644
--- a/src/qml/types/qqmldelegatemodel.cpp
+++ b/src/qml/types/qqmldelegatemodel.cpp
@@ -864,7 +864,7 @@ void QQmlDelegateModelPrivate::releaseIncubator(QQDMIncubationTask *incubationTa
void QQmlDelegateModelPrivate::removeCacheItem(QQmlDelegateModelItem *cacheItem)
{
- int cidx = m_cache.indexOf(cacheItem);
+ int cidx = m_cache.lastIndexOf(cacheItem);
if (cidx >= 0) {
m_compositor.clearFlags(Compositor::Cache, cidx, 1, Compositor::CacheFlag);
m_cache.removeAt(cidx);
@@ -1021,11 +1021,11 @@ QObject *QQmlDelegateModelPrivate::object(Compositor::Group group, int index, QQ
/*
If asynchronous is true or the component is being loaded asynchronously due
- to an ancestor being loaded asynchronously, item() may return 0. In this
- case createdItem() will be emitted when the item is available. The item
- at this stage does not have any references, so item() must be called again
- to ensure a reference is held. Any call to item() which returns a valid item
- must be matched by a call to release() in order to destroy the item.
+ to an ancestor being loaded asynchronously, object() may return 0. In this
+ case createdItem() will be emitted when the object is available. The object
+ at this stage does not have any references, so object() must be called again
+ to ensure a reference is held. Any call to object() which returns a valid object
+ must be matched by a call to release() in order to destroy the object.
*/
QObject *QQmlDelegateModel::object(int index, QQmlIncubator::IncubationMode incubationMode)
{
diff --git a/src/quick/items/qquickanimatedimage.cpp b/src/quick/items/qquickanimatedimage.cpp
index 5bc5b0faff..2f76671b1a 100644
--- a/src/quick/items/qquickanimatedimage.cpp
+++ b/src/quick/items/qquickanimatedimage.cpp
@@ -54,26 +54,26 @@ QT_BEGIN_NAMESPACE
QQuickPixmap* QQuickAnimatedImagePrivate::infoForCurrentFrame(QQmlEngine *engine)
{
- if (!_movie)
+ if (!movie)
return 0;
- int current = _movie->currentFrameNumber();
+ int current = movie->currentFrameNumber();
if (!frameMap.contains(current)) {
QUrl requestedUrl;
QQuickPixmap *pixmap = 0;
- if (engine && !_movie->fileName().isEmpty()) {
+ if (engine && !movie->fileName().isEmpty()) {
requestedUrl.setUrl(QString::fromUtf8("quickanimatedimage://%1#%2")
- .arg(_movie->fileName())
+ .arg(movie->fileName())
.arg(current));
}
if (!requestedUrl.isEmpty()) {
if (QQuickPixmap::isCached(requestedUrl, QSize(), QQuickImageProviderOptions()))
pixmap = new QQuickPixmap(engine, requestedUrl);
else
- pixmap = new QQuickPixmap(requestedUrl, _movie->currentImage());
+ pixmap = new QQuickPixmap(requestedUrl, movie->currentImage());
} else {
pixmap = new QQuickPixmap;
- pixmap->setImage(_movie->currentImage());
+ pixmap->setImage(movie->currentImage());
}
frameMap.insert(current, pixmap);
}
@@ -138,7 +138,7 @@ QQuickPixmap* QQuickAnimatedImagePrivate::infoForCurrentFrame(QQmlEngine *engine
QQuickAnimatedImage::QQuickAnimatedImage(QQuickItem *parent)
: QQuickImage(*(new QQuickAnimatedImagePrivate), parent)
{
- QObject::connect(this, &QQuickImageBase::cacheChanged, this, &QQuickAnimatedImage::onCacheChanged);
+ connect(this, &QQuickImageBase::cacheChanged, this, &QQuickAnimatedImage::onCacheChanged);
}
QQuickAnimatedImage::~QQuickAnimatedImage()
@@ -148,7 +148,7 @@ QQuickAnimatedImage::~QQuickAnimatedImage()
if (d->reply)
d->reply->deleteLater();
#endif
- delete d->_movie;
+ delete d->movie;
qDeleteAll(d->frameMap);
d->frameMap.clear();
}
@@ -164,9 +164,9 @@ QQuickAnimatedImage::~QQuickAnimatedImage()
bool QQuickAnimatedImage::isPaused() const
{
Q_D(const QQuickAnimatedImage);
- if (!d->_movie)
+ if (!d->movie)
return d->paused;
- return d->_movie->state()==QMovie::Paused;
+ return d->movie->state()==QMovie::Paused;
}
void QQuickAnimatedImage::setPaused(bool pause)
@@ -174,11 +174,11 @@ void QQuickAnimatedImage::setPaused(bool pause)
Q_D(QQuickAnimatedImage);
if (pause == d->paused)
return;
- if (!d->_movie) {
+ if (!d->movie) {
d->paused = pause;
emit pausedChanged();
} else {
- d->_movie->setPaused(pause);
+ d->movie->setPaused(pause);
}
}
@@ -203,9 +203,9 @@ void QQuickAnimatedImage::setPaused(bool pause)
bool QQuickAnimatedImage::isPlaying() const
{
Q_D(const QQuickAnimatedImage);
- if (!d->_movie)
+ if (!d->movie)
return d->playing;
- return d->_movie->state()!=QMovie::NotRunning;
+ return d->movie->state()!=QMovie::NotRunning;
}
void QQuickAnimatedImage::setPlaying(bool play)
@@ -213,15 +213,15 @@ void QQuickAnimatedImage::setPlaying(bool play)
Q_D(QQuickAnimatedImage);
if (play == d->playing)
return;
- if (!d->_movie) {
+ if (!d->movie) {
d->playing = play;
emit playingChanged();
return;
}
if (play)
- d->_movie->start();
+ d->movie->start();
else
- d->_movie->stop();
+ d->movie->stop();
}
/*!
@@ -237,27 +237,27 @@ void QQuickAnimatedImage::setPlaying(bool play)
int QQuickAnimatedImage::currentFrame() const
{
Q_D(const QQuickAnimatedImage);
- if (!d->_movie)
- return d->preset_currentframe;
- return d->_movie->currentFrameNumber();
+ if (!d->movie)
+ return d->presetCurrentFrame;
+ return d->movie->currentFrameNumber();
}
void QQuickAnimatedImage::setCurrentFrame(int frame)
{
Q_D(QQuickAnimatedImage);
- if (!d->_movie) {
- d->preset_currentframe = frame;
+ if (!d->movie) {
+ d->presetCurrentFrame = frame;
return;
}
- d->_movie->jumpToFrame(frame);
+ d->movie->jumpToFrame(frame);
}
int QQuickAnimatedImage::frameCount() const
{
Q_D(const QQuickAnimatedImage);
- if (!d->_movie)
+ if (!d->movie)
return 0;
- return d->_movie->frameCount();
+ return d->movie->frameCount();
}
void QQuickAnimatedImage::setSource(const QUrl &url)
@@ -278,10 +278,7 @@ void QQuickAnimatedImage::setSource(const QUrl &url)
d->frameMap.clear();
d->oldPlaying = isPlaying();
- if (d->_movie) {
- d->setMovie(nullptr);
- }
-
+ d->setMovie(nullptr);
d->url = url;
emit sourceChanged(d->url);
@@ -335,10 +332,8 @@ void QQuickAnimatedImage::load()
req.setAttribute(QNetworkRequest::HttpPipeliningAllowedAttribute, true);
d->reply = qmlEngine(this)->networkAccessManager()->get(req);
- QObject::connect(d->reply, SIGNAL(finished()),
- this, SLOT(movieRequestFinished()));
- QObject::connect(d->reply, SIGNAL(downloadProgress(qint64,qint64)),
- this, SLOT(requestProgress(qint64,qint64)));
+ connect(d->reply, &QNetworkReply::finished, this, &QQuickAnimatedImage::movieRequestFinished);
+ connect(d->reply, SIGNAL(downloadProgress(qint64,qint64)), this, SLOT(requestProgress(qint64,qint64)));
#endif
}
}
@@ -369,7 +364,7 @@ void QQuickAnimatedImage::movieRequestFinished()
}
#endif
- if (!d->_movie || !d->_movie->isValid()) {
+ if (!d->movie || !d->movie->isValid()) {
qmlWarning(this) << "Error Reading Animated Image File " << d->url.toString();
d->setMovie(nullptr);
d->setImage(QImage());
@@ -390,12 +385,10 @@ void QQuickAnimatedImage::movieRequestFinished()
return;
}
- connect(d->_movie, SIGNAL(stateChanged(QMovie::MovieState)),
- this, SLOT(playingStatusChanged()));
- connect(d->_movie, SIGNAL(frameChanged(int)),
- this, SLOT(movieUpdate()));
+ connect(d->movie, &QMovie::stateChanged, this, &QQuickAnimatedImage::playingStatusChanged);
+ connect(d->movie, &QMovie::frameChanged, this, &QQuickAnimatedImage::movieUpdate);
if (d->cache)
- d->_movie->setCacheMode(QMovie::CacheAll);
+ d->movie->setCacheMode(QMovie::CacheAll);
d->status = Ready;
emit statusChanged(d->status);
@@ -406,22 +399,21 @@ void QQuickAnimatedImage::movieRequestFinished()
}
bool pausedAtStart = d->paused;
- if (d->playing) {
- d->_movie->start();
- }
+ if (d->playing)
+ d->movie->start();
if (pausedAtStart)
- d->_movie->setPaused(true);
+ d->movie->setPaused(true);
if (d->paused || !d->playing) {
- d->_movie->jumpToFrame(d->preset_currentframe);
- d->preset_currentframe = 0;
+ d->movie->jumpToFrame(d->presetCurrentFrame);
+ d->presetCurrentFrame = 0;
}
d->setPixmap(*d->infoForCurrentFrame(qmlEngine(this)));
if (isPlaying() != d->oldPlaying)
emit playingChanged();
- if (d->_movie)
- d->currentSourceSize = d->_movie->currentPixmap().size();
+ if (d->movie)
+ d->currentSourceSize = d->movie->currentPixmap().size();
else
d->currentSourceSize = QSize(0, 0);
@@ -440,7 +432,7 @@ void QQuickAnimatedImage::movieUpdate()
d->frameMap.clear();
}
- if (d->_movie) {
+ if (d->movie) {
d->setPixmap(*d->infoForCurrentFrame(qmlEngine(this)));
emit frameChanged();
}
@@ -450,12 +442,12 @@ void QQuickAnimatedImage::playingStatusChanged()
{
Q_D(QQuickAnimatedImage);
- if ((d->_movie->state() != QMovie::NotRunning) != d->playing) {
- d->playing = (d->_movie->state() != QMovie::NotRunning);
+ if ((d->movie->state() != QMovie::NotRunning) != d->playing) {
+ d->playing = (d->movie->state() != QMovie::NotRunning);
emit playingChanged();
}
- if ((d->_movie->state() == QMovie::Paused) != d->paused) {
- d->paused = (d->_movie->state() == QMovie::Paused);
+ if ((d->movie->state() == QMovie::Paused) != d->paused) {
+ d->paused = (d->movie->state() == QMovie::Paused);
emit pausedChanged();
}
}
@@ -466,13 +458,11 @@ void QQuickAnimatedImage::onCacheChanged()
if (!cache()) {
qDeleteAll(d->frameMap);
d->frameMap.clear();
- if (d->_movie) {
- d->_movie->setCacheMode(QMovie::CacheNone);
- }
+ if (d->movie)
+ d->movie->setCacheMode(QMovie::CacheNone);
} else {
- if (d->_movie) {
- d->_movie->setCacheMode(QMovie::CacheAll);
- }
+ if (d->movie)
+ d->movie->setCacheMode(QMovie::CacheAll);
}
}
@@ -488,13 +478,15 @@ void QQuickAnimatedImage::componentComplete()
load();
}
-void QQuickAnimatedImagePrivate::setMovie(QMovie *movie)
+void QQuickAnimatedImagePrivate::setMovie(QMovie *m)
{
+ if (movie == m)
+ return;
Q_Q(QQuickAnimatedImage);
const int oldFrameCount = q->frameCount();
- delete _movie;
- _movie = movie;
+ delete movie;
+ movie = m;
if (oldFrameCount != q->frameCount())
emit q->frameCountChanged();
diff --git a/src/quick/items/qquickanimatedimage_p_p.h b/src/quick/items/qquickanimatedimage_p_p.h
index 68c4f2d359..e172962ee4 100644
--- a/src/quick/items/qquickanimatedimage_p_p.h
+++ b/src/quick/items/qquickanimatedimage_p_p.h
@@ -70,28 +70,29 @@ class QQuickAnimatedImagePrivate : public QQuickImagePrivate
public:
QQuickAnimatedImagePrivate()
- : playing(true), paused(false), preset_currentframe(0), _movie(0), oldPlaying(false)
+ : playing(true), paused(false), oldPlaying(false), padding(0)
+ , presetCurrentFrame(0) , currentSourceSize(0, 0), movie(nullptr)
#if QT_CONFIG(qml_network)
- , reply(0), redirectCount(0)
+ , reply(nullptr), redirectCount(0)
#endif
- , currentSourceSize(0, 0)
{
}
QQuickPixmap *infoForCurrentFrame(QQmlEngine *engine);
+ void setMovie(QMovie *movie);
- bool playing;
- bool paused;
- int preset_currentframe;
- QMovie *_movie;
- bool oldPlaying;
+ bool playing : 1;
+ bool paused : 1;
+ bool oldPlaying : 1;
+ unsigned padding: 29;
+ int presetCurrentFrame;
+ QSize currentSourceSize;
+ QMovie *movie;
#if QT_CONFIG(qml_network)
QNetworkReply *reply;
int redirectCount;
#endif
QMap<int, QQuickPixmap *> frameMap;
- QSize currentSourceSize;
- void setMovie(QMovie *movie);
};
QT_END_NAMESPACE
diff --git a/src/quick/items/qquickflickable.cpp b/src/quick/items/qquickflickable.cpp
index ae5bdc3083..2ad65058b3 100644
--- a/src/quick/items/qquickflickable.cpp
+++ b/src/quick/items/qquickflickable.cpp
@@ -1435,17 +1435,23 @@ void QQuickFlickable::wheelEvent(QWheelEvent *event)
case Qt::ScrollUpdate:
if (d->scrollingPhase)
d->pressed = true;
-#ifdef Q_OS_OSX
+#ifdef Q_OS_MACOS
+ // TODO eliminate this timer when ScrollMomentum has been added
d->movementEndingTimer.start(MovementEndingTimerInterval, this);
#endif
break;
case Qt::ScrollEnd:
+ // TODO most of this should be done at transition to ScrollMomentum phase,
+ // then do what the movementEndingTimer triggers at transition to ScrollEnd phase
d->pressed = false;
d->scrollingPhase = false;
d->draggingEnding();
event->accept();
returnToBounds();
d->lastPosTime = -1;
+#ifdef Q_OS_MACOS
+ d->movementEndingTimer.start(MovementEndingTimerInterval, this);
+#endif
return;
}
@@ -2670,13 +2676,15 @@ void QQuickFlickable::movementEnding(bool hMovementEnding, bool vMovementEnding)
if (hMovementEnding && d->hData.moving
&& (!d->pressed && !d->stealMouse)) {
d->hData.moving = false;
- d->hMoved = false;
+ if (!d->scrollingPhase)
+ d->hMoved = false;
emit movingHorizontallyChanged();
}
if (vMovementEnding && d->vData.moving
&& (!d->pressed && !d->stealMouse)) {
d->vData.moving = false;
- d->vMoved = false;
+ if (!d->scrollingPhase)
+ d->vMoved = false;
emit movingVerticallyChanged();
}
if (wasMoving && !isMoving()) {
diff --git a/src/quick/items/qquickflickable_p_p.h b/src/quick/items/qquickflickable_p_p.h
index 8609a15fcd..bdffeb2101 100644
--- a/src/quick/items/qquickflickable_p_p.h
+++ b/src/quick/items/qquickflickable_p_p.h
@@ -106,9 +106,10 @@ public:
, continuousFlickVelocity(0), velocityTime(), vTime(0)
, smoothVelocity(fp), atEnd(false), atBeginning(true)
, transitionToSet(false)
- , fixingUp(false), inOvershoot(false), moving(false), flicking(false)
+ , fixingUp(false), inOvershoot(false), inRebound(false), moving(false), flicking(false)
, dragging(false), extentsChanged(false)
, explicitValue(false), minExtentDirty(true), maxExtentDirty(true)
+ , unused(0)
{}
~AxisData();
@@ -168,6 +169,7 @@ public:
bool explicitValue : 1;
mutable bool minExtentDirty : 1;
mutable bool maxExtentDirty : 1;
+ uint unused : 19;
};
bool flickX(qreal velocity);
diff --git a/src/quick/items/qquickframebufferobject.cpp b/src/quick/items/qquickframebufferobject.cpp
index 042ee21aec..20ba067a6b 100644
--- a/src/quick/items/qquickframebufferobject.cpp
+++ b/src/quick/items/qquickframebufferobject.cpp
@@ -313,6 +313,7 @@ QSGNode *QQuickFramebufferObject::updatePaintNode(QSGNode *node, UpdatePaintNode
desiredFboSize *= n->devicePixelRatio;
if (n->fbo && ((d->followsItemSize && n->fbo->size() != desiredFboSize) || n->invalidatePending)) {
+ delete n->texture();
delete n->fbo;
n->fbo = 0;
delete n->msDisplayFbo;
diff --git a/src/quick/items/qquickgridview.cpp b/src/quick/items/qquickgridview.cpp
index c56cfd3005..2be64362b2 100644
--- a/src/quick/items/qquickgridview.cpp
+++ b/src/quick/items/qquickgridview.cpp
@@ -537,13 +537,12 @@ bool QQuickGridViewPrivate::addVisibleItems(qreal fillFrom, qreal fillTo, qreal
if (visibleItems.count()) {
FxGridItemSG *firstItem = static_cast<FxGridItemSG*>(visibleItems.constFirst());
rowPos = firstItem->rowPos();
- colNum = qFloor((firstItem->colPos()+colSize()/2) / colSize());
- if (--colNum < 0) {
- colNum = columns - 1;
- rowPos -= rowSize();
- }
- } else {
- colNum = qFloor((colPos+colSize()/2) / colSize());
+ colPos = firstItem->colPos();
+ }
+ colNum = qFloor((colPos+colSize()/2) / colSize());
+ if (--colNum < 0) {
+ colNum = columns - 1;
+ rowPos -= rowSize();
}
// Prepend
@@ -895,7 +894,6 @@ void QQuickGridViewPrivate::initializeCurrentItem()
void QQuickGridViewPrivate::fixupPosition()
{
- moveReason = Other;
if (flow == QQuickGridView::FlowLeftToRight)
fixupY();
else
diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp
index 6b123d1dfe..dac37e284b 100644
--- a/src/quick/items/qquickitem.cpp
+++ b/src/quick/items/qquickitem.cpp
@@ -87,6 +87,7 @@ QT_BEGIN_NAMESPACE
Q_DECLARE_LOGGING_CATEGORY(DBG_MOUSE_TARGET)
Q_DECLARE_LOGGING_CATEGORY(DBG_HOVER_TRACE)
+Q_DECLARE_LOGGING_CATEGORY(lcTransient)
void debugFocusTree(QQuickItem *item, QQuickItem *scope = 0, int depth = 1)
{
@@ -970,7 +971,7 @@ bool QQuickKeysAttached::isConnected(const char *signalName) const
Keys.onEscapePressed: {
console.log("escapeItem is handling escape");
- event.accepted = true;
+ // event.accepted is set to true by default for the specific key handlers
}
}
@@ -3264,11 +3265,13 @@ void QQuickItemPrivate::data_append(QQmlListProperty<QObject> *prop, QObject *o)
}
if (thisWindow) {
- if (itemWindow)
+ if (itemWindow) {
+ qCDebug(lcTransient) << thisWindow << "is transient for" << itemWindow;
thisWindow->setTransientParent(itemWindow);
- else
+ } else {
QObject::connect(item, SIGNAL(windowChanged(QQuickWindow*)),
thisWindow, SLOT(setTransientParent_helper(QQuickWindow*)));
+ }
}
o->setParent(that);
}
@@ -3667,8 +3670,9 @@ QQmlListProperty<QObject> QQuickItemPrivate::data()
\qmlproperty real QtQuick::Item::childrenRect.y
\qmlproperty real QtQuick::Item::childrenRect.width
\qmlproperty real QtQuick::Item::childrenRect.height
+ \readonly
- This property holds the collective position and size of the item's
+ This read-only property holds the collective position and size of the item's
children.
This property is useful if you need to access the collective geometry
@@ -5806,19 +5810,24 @@ bool QQuickItem::isVisible() const
return d->effectiveVisible;
}
-void QQuickItem::setVisible(bool v)
+void QQuickItemPrivate::setVisible(bool visible)
{
- Q_D(QQuickItem);
- if (v == d->explicitVisible)
+ if (visible == explicitVisible)
return;
- d->explicitVisible = v;
- if (!v)
- d->dirty(QQuickItemPrivate::Visible);
+ explicitVisible = visible;
+ if (!visible)
+ dirty(QQuickItemPrivate::Visible);
- const bool childVisibilityChanged = d->setEffectiveVisibleRecur(d->calcEffectiveVisible());
- if (childVisibilityChanged && d->parentItem)
- emit d->parentItem->visibleChildrenChanged(); // signal the parent, not this!
+ const bool childVisibilityChanged = setEffectiveVisibleRecur(calcEffectiveVisible());
+ if (childVisibilityChanged && parentItem)
+ emit parentItem->visibleChildrenChanged(); // signal the parent, not this!
+}
+
+void QQuickItem::setVisible(bool v)
+{
+ Q_D(QQuickItem);
+ d->setVisible(v);
}
/*!
diff --git a/src/quick/items/qquickitem_p.h b/src/quick/items/qquickitem_p.h
index 2f0c316602..285e86048c 100644
--- a/src/quick/items/qquickitem_p.h
+++ b/src/quick/items/qquickitem_p.h
@@ -311,7 +311,6 @@ public:
static void transform_clear(QQmlListProperty<QQuickTransform> *list);
void _q_resourceObjectDeleted(QObject *);
- void _q_windowChanged(QQuickWindow *w);
quint64 _q_createJSWrapper(QV4::ExecutionEngine *engine);
enum ChangeType {
@@ -574,6 +573,8 @@ public:
virtual bool handlePointerEvent(QQuickPointerEvent *, bool avoidExclusiveGrabber = false);
+ virtual void setVisible(bool visible);
+
bool isTransparentForPositioner() const;
void setTransparentForPositioner(bool trans);
diff --git a/src/quick/items/qquickitemsmodule.cpp b/src/quick/items/qquickitemsmodule.cpp
index fcf6e49135..b89ee764c3 100644
--- a/src/quick/items/qquickitemsmodule.cpp
+++ b/src/quick/items/qquickitemsmodule.cpp
@@ -111,6 +111,10 @@
#include <private/qqmlmetatype_p.h>
#include <QtQuick/private/qquickaccessibleattached_p.h>
+QT_BEGIN_NAMESPACE
+Q_DECLARE_LOGGING_CATEGORY(lcTransient)
+QT_END_NAMESPACE
+
static QQmlPrivate::AutoParentResult qquickitem_autoParent(QObject *obj, QObject *parent)
{
// When setting a parent (especially during dynamic object creation) in QML,
@@ -125,6 +129,7 @@ static QQmlPrivate::AutoParentResult qquickitem_autoParent(QObject *obj, QObject
QQuickWindow *win = qmlobject_cast<QQuickWindow *>(obj);
if (win) {
// A Window inside an Item should be transient for that item's window
+ qCDebug(lcTransient) << win << "is transient for" << parentItem->window();
win->setTransientParent(parentItem->window());
return QQmlPrivate::Parented;
}
@@ -134,6 +139,7 @@ static QQmlPrivate::AutoParentResult qquickitem_autoParent(QObject *obj, QObject
QQuickWindow *win = qmlobject_cast<QQuickWindow *>(obj);
if (win) {
// A Window inside a Window should be transient for it
+ qCDebug(lcTransient) << win << "is transient for" << parentWindow;
win->setTransientParent(parentWindow);
return QQmlPrivate::Parented;
} else {
diff --git a/src/quick/items/qquickitemview.cpp b/src/quick/items/qquickitemview.cpp
index 10f6c63170..856070634c 100644
--- a/src/quick/items/qquickitemview.cpp
+++ b/src/quick/items/qquickitemview.cpp
@@ -1751,6 +1751,7 @@ void QQuickItemViewPrivate::updateCurrent(int modelIndex)
void QQuickItemViewPrivate::clear()
{
currentChanges.reset();
+ bufferedChanges.reset();
timeline.clear();
releaseVisibleItems();
@@ -1808,51 +1809,56 @@ void QQuickItemViewPrivate::refill(qreal from, qreal to)
if (!isValid() || !q->isComponentComplete())
return;
- bufferPause.stop();
- currentChanges.reset();
+ do {
+ bufferPause.stop();
+ if (currentChanges.hasPendingChanges() || bufferedChanges.hasPendingChanges()) {
+ currentChanges.reset();
+ bufferedChanges.reset();
+ releaseVisibleItems();
+ }
- int prevCount = itemCount;
- itemCount = model->count();
- qreal bufferFrom = from - buffer;
- qreal bufferTo = to + buffer;
- qreal fillFrom = from;
- qreal fillTo = to;
-
- bool added = addVisibleItems(fillFrom, fillTo, bufferFrom, bufferTo, false);
- bool removed = removeNonVisibleItems(bufferFrom, bufferTo);
-
- if (requestedIndex == -1 && buffer && bufferMode != NoBuffer) {
- if (added) {
- // We've already created a new delegate this frame.
- // Just schedule a buffer refill.
- bufferPause.start();
- } else {
- if (bufferMode & BufferAfter)
- fillTo = bufferTo;
- if (bufferMode & BufferBefore)
- fillFrom = bufferFrom;
- added |= addVisibleItems(fillFrom, fillTo, bufferFrom, bufferTo, true);
+ int prevCount = itemCount;
+ itemCount = model->count();
+ qreal bufferFrom = from - buffer;
+ qreal bufferTo = to + buffer;
+ qreal fillFrom = from;
+ qreal fillTo = to;
+
+ bool added = addVisibleItems(fillFrom, fillTo, bufferFrom, bufferTo, false);
+ bool removed = removeNonVisibleItems(bufferFrom, bufferTo);
+
+ if (requestedIndex == -1 && buffer && bufferMode != NoBuffer) {
+ if (added) {
+ // We've already created a new delegate this frame.
+ // Just schedule a buffer refill.
+ bufferPause.start();
+ } else {
+ if (bufferMode & BufferAfter)
+ fillTo = bufferTo;
+ if (bufferMode & BufferBefore)
+ fillFrom = bufferFrom;
+ added |= addVisibleItems(fillFrom, fillTo, bufferFrom, bufferTo, true);
+ }
}
- }
- if (added || removed) {
- markExtentsDirty();
- updateBeginningEnd();
- visibleItemsChanged();
- updateHeader();
- updateFooter();
- updateViewport();
- }
+ if (added || removed) {
+ markExtentsDirty();
+ updateBeginningEnd();
+ visibleItemsChanged();
+ updateHeader();
+ updateFooter();
+ updateViewport();
+ }
- if (prevCount != itemCount)
- emit q->countChanged();
+ if (prevCount != itemCount)
+ emit q->countChanged();
+ } while (currentChanges.hasPendingChanges() || bufferedChanges.hasPendingChanges());
}
void QQuickItemViewPrivate::regenerate(bool orientationChanged)
{
Q_Q(QQuickItemView);
if (q->isComponentComplete()) {
- currentChanges.reset();
if (orientationChanged) {
delete header;
header = 0;
diff --git a/src/quick/items/qquickitemviewtransition_p.h b/src/quick/items/qquickitemviewtransition_p.h
index 3d2f5361b1..29a62f7f10 100644
--- a/src/quick/items/qquickitemviewtransition_p.h
+++ b/src/quick/items/qquickitemviewtransition_p.h
@@ -58,6 +58,8 @@ QT_REQUIRE_CONFIG(quick_viewtransitions);
#include <QtCore/qobject.h>
#include <QtCore/qpoint.h>
#include <QtQml/qqml.h>
+#include <private/qqmlguard_p.h>
+#include <private/qquicktransition_p.h>
QT_BEGIN_NAMESPACE
@@ -115,14 +117,14 @@ public:
QList<QObject *> moveTransitionTargets;
QList<QObject *> removeTransitionTargets;
- QQuickTransition *populateTransition;
- QQuickTransition *addTransition;
- QQuickTransition *addDisplacedTransition;
- QQuickTransition *moveTransition;
- QQuickTransition *moveDisplacedTransition;
- QQuickTransition *removeTransition;
- QQuickTransition *removeDisplacedTransition;
- QQuickTransition *displacedTransition;
+ QQmlGuard<QQuickTransition> populateTransition;
+ QQmlGuard<QQuickTransition> addTransition;
+ QQmlGuard<QQuickTransition> addDisplacedTransition;
+ QQmlGuard<QQuickTransition> moveTransition;
+ QQmlGuard<QQuickTransition> moveDisplacedTransition;
+ QQmlGuard<QQuickTransition> removeTransition;
+ QQmlGuard<QQuickTransition> removeDisplacedTransition;
+ QQmlGuard<QQuickTransition> displacedTransition;
private:
friend class QQuickItemViewTransitionJob;
diff --git a/src/quick/items/qquicklistview.cpp b/src/quick/items/qquicklistview.cpp
index 11eaf393ea..54dfbafaa2 100644
--- a/src/quick/items/qquicklistview.cpp
+++ b/src/quick/items/qquicklistview.cpp
@@ -1468,9 +1468,6 @@ void QQuickListViewPrivate::itemGeometryChanged(QQuickItem *item, QQuickGeometry
void QQuickListViewPrivate::fixupPosition()
{
- if ((haveHighlightRange && highlightRange == QQuickListView::StrictlyEnforceRange)
- || snapMode != QQuickListView::NoSnap)
- moveReason = Other;
if (orient == QQuickListView::Vertical)
fixupY();
else
diff --git a/src/quick/items/qquickloader.cpp b/src/quick/items/qquickloader.cpp
index 27b8d32707..d5601292b7 100644
--- a/src/quick/items/qquickloader.cpp
+++ b/src/quick/items/qquickloader.cpp
@@ -48,6 +48,8 @@
QT_BEGIN_NAMESPACE
+Q_DECLARE_LOGGING_CATEGORY(lcTransient)
+
static const QQuickItemPrivate::ChangeTypes watchedChanges
= QQuickItemPrivate::Geometry | QQuickItemPrivate::ImplicitWidth | QQuickItemPrivate::ImplicitHeight;
diff --git a/src/quick/items/qquickrepeater.cpp b/src/quick/items/qquickrepeater.cpp
index 658a7de3d4..ba9460bf76 100644
--- a/src/quick/items/qquickrepeater.cpp
+++ b/src/quick/items/qquickrepeater.cpp
@@ -374,9 +374,12 @@ void QQuickRepeater::clear()
if (complete)
emit itemRemoved(i, item);
d->model->release(item);
- item->setParentItem(0);
}
}
+ for (QQuickItem *item : qAsConst(d->deletables)) {
+ if (item)
+ item->setParentItem(0);
+ }
}
d->deletables.clear();
d->itemCount = 0;
diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp
index a056575f41..8b8469f801 100644
--- a/src/quick/items/qquickwindow.cpp
+++ b/src/quick/items/qquickwindow.cpp
@@ -78,6 +78,9 @@
# include <private/qopenglvertexarrayobject_p.h>
# include <private/qsgdefaultrendercontext_p.h>
#endif
+#ifndef QT_NO_DEBUG_STREAM
+#include <private/qdebug_p.h>
+#endif
QT_BEGIN_NAMESPACE
@@ -88,6 +91,7 @@ Q_LOGGING_CATEGORY(DBG_MOUSE_TARGET, "qt.quick.mouse.target")
Q_LOGGING_CATEGORY(DBG_HOVER_TRACE, "qt.quick.hover.trace")
Q_LOGGING_CATEGORY(DBG_FOCUS, "qt.quick.focus")
Q_LOGGING_CATEGORY(DBG_DIRTY, "qt.quick.dirty")
+Q_LOGGING_CATEGORY(lcTransient, "qt.quick.window.transient")
extern Q_GUI_EXPORT QImage qt_gl_read_framebuffer(const QSize &size, bool alpha_format, bool include_alpha);
@@ -576,13 +580,21 @@ void QQuickWindowPrivate::init(QQuickWindow *c, QQuickRenderControl *control)
QObject::connect(q, SIGNAL(focusObjectChanged(QObject*)), q, SIGNAL(activeFocusItemChanged()));
QObject::connect(q, SIGNAL(screenChanged(QScreen*)), q, SLOT(handleScreenChanged(QScreen*)));
-
+ QObject::connect(qApp, SIGNAL(applicationStateChanged(Qt::ApplicationState)),
+ q, SLOT(handleApplicationStateChanged(Qt::ApplicationState)));
QObject::connect(q, SIGNAL(frameSwapped()), q, SLOT(runJobsAfterSwap()), Qt::DirectConnection);
if (QQmlInspectorService *service = QQmlDebugConnector::service<QQmlInspectorService>())
service->addWindow(q);
}
+void QQuickWindow::handleApplicationStateChanged(Qt::ApplicationState state)
+{
+ Q_D(QQuickWindow);
+ if (state != Qt::ApplicationActive && d->contentItem)
+ d->contentItem->windowDeactivateEvent();
+}
+
/*!
\property QQuickWindow::data
\internal
@@ -2953,8 +2965,10 @@ void QQuickWindowPrivate::data_append(QQmlListProperty<QObject> *property, QObje
if (!o)
return;
QQuickWindow *that = static_cast<QQuickWindow *>(property->object);
- if (QQuickWindow *window = qmlobject_cast<QQuickWindow *>(o))
+ if (QQuickWindow *window = qmlobject_cast<QQuickWindow *>(o)) {
+ qCDebug(lcTransient) << window << "is transient for" << that;
window->setTransientParent(that);
+ }
QQmlListProperty<QObject> itemProperty = QQuickItemPrivate::get(that->contentItem())->data();
itemProperty.append(&itemProperty, o);
}
@@ -3485,6 +3499,7 @@ void QQuickWindow::cleanupSceneGraph()
void QQuickWindow::setTransientParent_helper(QQuickWindow *window)
{
+ qCDebug(lcTransient) << this << "is transient for" << window;
setTransientParent(window);
disconnect(sender(), SIGNAL(windowChanged(QQuickWindow*)),
this, SLOT(setTransientParent_helper(QQuickWindow*)));
@@ -4927,6 +4942,37 @@ void QQuickWindow::setTextRenderType(QQuickWindow::TextRenderType renderType)
QQuickWindowPrivate::textRenderType = renderType;
}
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug debug, const QQuickWindow *win)
+{
+ QDebugStateSaver saver(debug);
+ debug.nospace();
+ if (!win) {
+ debug << "QQuickWindow(0)";
+ return debug;
+ }
+
+ debug << win->metaObject()->className() << '(' << static_cast<const void *>(win);
+ if (win->isActive())
+ debug << " active";
+ if (win->isExposed())
+ debug << " exposed";
+ debug << ", visibility=" << win->visibility() << ", flags=" << win->flags();
+ if (!win->title().isEmpty())
+ debug << ", title=" << win->title();
+ if (!win->objectName().isEmpty())
+ debug << ", name=" << win->objectName();
+ if (win->parent())
+ debug << ", parent=" << static_cast<const void *>(win->parent());
+ if (win->transientParent())
+ debug << ", transientParent=" << static_cast<const void *>(win->transientParent());
+ debug << ", geometry=";
+ QtDebugUtils::formatQRect(debug, win->geometry());
+ debug << ')';
+ return debug;
+}
+#endif
+
#include "moc_qquickwindow.cpp"
QT_END_NAMESPACE
diff --git a/src/quick/items/qquickwindow.h b/src/quick/items/qquickwindow.h
index 022c4738f2..5ec5a0f95f 100644
--- a/src/quick/items/qquickwindow.h
+++ b/src/quick/items/qquickwindow.h
@@ -232,7 +232,7 @@ private Q_SLOTS:
void handleScreenChanged(QScreen *screen);
void setTransientParent_helper(QQuickWindow *window);
void runJobsAfterSwap();
-
+ void handleApplicationStateChanged(Qt::ApplicationState state);
private:
friend class QQuickItem;
friend class QQuickWidget;
@@ -241,6 +241,10 @@ private:
Q_DISABLE_COPY(QQuickWindow)
};
+#ifndef QT_NO_DEBUG_STREAM
+QDebug Q_QUICK_EXPORT operator<<(QDebug debug, const QQuickWindow *item);
+#endif
+
QT_END_NAMESPACE
Q_DECLARE_METATYPE(QQuickWindow *)
diff --git a/src/quick/items/qquickwindowmodule.cpp b/src/quick/items/qquickwindowmodule.cpp
index 45e3f0004d..6165ce1ba1 100644
--- a/src/quick/items/qquickwindowmodule.cpp
+++ b/src/quick/items/qquickwindowmodule.cpp
@@ -52,6 +52,8 @@
QT_BEGIN_NAMESPACE
+Q_DECLARE_LOGGING_CATEGORY(lcTransient)
+
class QQuickWindowQmlImplPrivate : public QQuickWindowPrivate
{
public:
diff --git a/src/quick/scenegraph/adaptations/software/qsgabstractsoftwarerenderer.cpp b/src/quick/scenegraph/adaptations/software/qsgabstractsoftwarerenderer.cpp
index 30088846a6..4cec84646e 100644
--- a/src/quick/scenegraph/adaptations/software/qsgabstractsoftwarerenderer.cpp
+++ b/src/quick/scenegraph/adaptations/software/qsgabstractsoftwarerenderer.cpp
@@ -233,11 +233,11 @@ void QSGAbstractSoftwareRenderer::setBackgroundColor(const QColor &color)
renderableNode(m_background)->markMaterialDirty();
}
-void QSGAbstractSoftwareRenderer::setBackgroundSize(const QSize &size)
+void QSGAbstractSoftwareRenderer::setBackgroundRect(const QRect &rect)
{
- if (m_background->rect().size().toSize() == size)
+ if (m_background->rect().toRect() == rect)
return;
- m_background->setRect(0.0f, 0.0f, size.width(), size.height());
+ m_background->setRect(rect);
renderableNode(m_background)->markGeometryDirty();
// Invalidate the whole scene when the background is resized
markDirty();
@@ -248,9 +248,9 @@ QColor QSGAbstractSoftwareRenderer::backgroundColor()
return m_background->color();
}
-QSize QSGAbstractSoftwareRenderer::backgroundSize()
+QRect QSGAbstractSoftwareRenderer::backgroundRect()
{
- return m_background->rect().size().toSize();
+ return m_background->rect().toRect();
}
void QSGAbstractSoftwareRenderer::nodeAdded(QSGNode *node)
diff --git a/src/quick/scenegraph/adaptations/software/qsgabstractsoftwarerenderer_p.h b/src/quick/scenegraph/adaptations/software/qsgabstractsoftwarerenderer_p.h
index f20c2cf977..f6594d931a 100644
--- a/src/quick/scenegraph/adaptations/software/qsgabstractsoftwarerenderer_p.h
+++ b/src/quick/scenegraph/adaptations/software/qsgabstractsoftwarerenderer_p.h
@@ -83,9 +83,9 @@ protected:
QRegion optimizeRenderList();
void setBackgroundColor(const QColor &color);
- void setBackgroundSize(const QSize &size);
+ void setBackgroundRect(const QRect &rect);
QColor backgroundColor();
- QSize backgroundSize();
+ QRect backgroundRect();
// only known after calling optimizeRenderList()
bool isOpaque() const { return m_isOpaque; }
diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwarepixmaprenderer.cpp b/src/quick/scenegraph/adaptations/software/qsgsoftwarepixmaprenderer.cpp
index 186fd92fb7..303f98c801 100644
--- a/src/quick/scenegraph/adaptations/software/qsgsoftwarepixmaprenderer.cpp
+++ b/src/quick/scenegraph/adaptations/software/qsgsoftwarepixmaprenderer.cpp
@@ -79,7 +79,7 @@ void QSGSoftwarePixmapRenderer::render(QPaintDevice *target)
QElapsedTimer renderTimer;
// Setup background item
- setBackgroundSize(QSize(target->width(), target->height()));
+ setBackgroundRect(m_projectionRect);
setBackgroundColor(clearColor());
renderTimer.start();
diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderer.cpp b/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderer.cpp
index 85d04fe136..d403884b4e 100644
--- a/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderer.cpp
+++ b/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderer.cpp
@@ -112,7 +112,8 @@ void QSGSoftwareRenderer::render()
QElapsedTimer renderTimer;
setBackgroundColor(clearColor());
- setBackgroundSize(QSize(m_paintDevice->width() / m_paintDevice->devicePixelRatio(),
+ setBackgroundRect(QRect(0, 0,
+ m_paintDevice->width() / m_paintDevice->devicePixelRatio(),
m_paintDevice->height() / m_paintDevice->devicePixelRatio()));
// Build Renderlist
diff --git a/src/quick/util/qquickpropertychanges.cpp b/src/quick/util/qquickpropertychanges.cpp
index 61380b3ea0..aecb7115ea 100644
--- a/src/quick/util/qquickpropertychanges.cpp
+++ b/src/quick/util/qquickpropertychanges.cpp
@@ -281,15 +281,19 @@ void QQuickPropertyChangesPrivate::decodeBinding(const QString &propertyPrefix,
return;
}
- QQmlProperty prop = property(propertyName); //### better way to check for signal property?
-
- if (prop.type() & QQmlProperty::SignalProperty) {
- QQuickReplaceSignalHandler *handler = new QQuickReplaceSignalHandler;
- handler->property = prop;
- handler->expression.take(new QQmlBoundSignalExpression(object, QQmlPropertyPrivate::get(prop)->signalIndex(),
- QQmlContextData::get(qmlContext(q)), object, compilationUnit->runtimeFunctions.at(binding->value.compiledScriptIndex)));
- signalReplacements << handler;
- return;
+ if (propertyName.count() >= 3 &&
+ propertyName.at(0) == QLatin1Char('o') &&
+ propertyName.at(1) == QLatin1Char('n') &&
+ propertyName.at(2).isUpper()) {
+ QQmlProperty prop = property(propertyName);
+ if (prop.isSignalProperty()) {
+ QQuickReplaceSignalHandler *handler = new QQuickReplaceSignalHandler;
+ handler->property = prop;
+ handler->expression.take(new QQmlBoundSignalExpression(object, QQmlPropertyPrivate::get(prop)->signalIndex(),
+ QQmlContextData::get(qmlContext(q)), object, compilationUnit->runtimeFunctions.at(binding->value.compiledScriptIndex)));
+ signalReplacements << handler;
+ return;
+ }
}
if (binding->type == QV4::CompiledData::Binding::Type_Script) {
@@ -395,7 +399,10 @@ QQmlProperty
QQuickPropertyChangesPrivate::property(const QString &property)
{
Q_Q(QQuickPropertyChanges);
- QQmlProperty prop(object, property, qmlContext(q));
+ QQmlContextData *context = nullptr;
+ if (QQmlData *ddata = QQmlData::get(q))
+ context = ddata->outerContext;
+ QQmlProperty prop = QQmlPropertyPrivate::create(object, property, context);
if (!prop.isValid()) {
qmlWarning(q) << QQuickPropertyChanges::tr("Cannot assign to non-existent property \"%1\"").arg(property);
return QQmlProperty();
@@ -415,9 +422,10 @@ QQuickPropertyChanges::ActionList QQuickPropertyChanges::actions()
ActionList list;
for (int ii = 0; ii < d->properties.count(); ++ii) {
+ QQmlProperty prop = d->property(d->properties.at(ii).first);
- QQuickStateAction a(d->object, d->properties.at(ii).first,
- qmlContext(this), d->properties.at(ii).second);
+ QQuickStateAction a(d->object, prop, d->properties.at(ii).first,
+ d->properties.at(ii).second);
if (a.property.isValid()) {
a.restore = restoreEntryValues();
@@ -426,7 +434,6 @@ QQuickPropertyChanges::ActionList QQuickPropertyChanges::actions()
}
for (int ii = 0; ii < d->signalReplacements.count(); ++ii) {
-
QQuickReplaceSignalHandler *handler = d->signalReplacements.at(ii);
if (handler->property.isValid()) {
diff --git a/src/quick/util/qquickshortcut.cpp b/src/quick/util/qquickshortcut.cpp
index 58f7fc8439..78dc855326 100644
--- a/src/quick/util/qquickshortcut.cpp
+++ b/src/quick/util/qquickshortcut.cpp
@@ -122,7 +122,8 @@ Q_QUICK_PRIVATE_EXPORT ContextMatcher qt_quick_shortcut_context_matcher()
Q_QUICK_PRIVATE_EXPORT void qt_quick_set_shortcut_context_matcher(ContextMatcher matcher)
{
- *ctxMatcher() = matcher;
+ if (!ctxMatcher.isDestroyed())
+ *ctxMatcher() = matcher;
}
QT_BEGIN_NAMESPACE
diff --git a/src/quick/util/qquickstate.cpp b/src/quick/util/qquickstate.cpp
index 0a49d41491..ca8b7bbc2b 100644
--- a/src/quick/util/qquickstate.cpp
+++ b/src/quick/util/qquickstate.cpp
@@ -68,10 +68,9 @@ QQuickStateAction::QQuickStateAction(QObject *target, const QString &propertyNam
fromValue = property.read();
}
-QQuickStateAction::QQuickStateAction(QObject *target, const QString &propertyName,
- QQmlContext *context, const QVariant &value)
+QQuickStateAction::QQuickStateAction(QObject *target, const QQmlProperty &property, const QString &propertyName, const QVariant &value)
: restore(true), actionDone(false), reverseEvent(false), deletableToBinding(false),
- property(target, propertyName, context), toValue(value),
+ property(property), toValue(value),
fromBinding(0), event(0),
specifiedObject(target), specifiedProperty(propertyName)
{
diff --git a/src/quick/util/qquickstate_p.h b/src/quick/util/qquickstate_p.h
index 7d22ca9f8c..3826daf283 100644
--- a/src/quick/util/qquickstate_p.h
+++ b/src/quick/util/qquickstate_p.h
@@ -69,8 +69,8 @@ class Q_QUICK_PRIVATE_EXPORT QQuickStateAction
public:
QQuickStateAction();
QQuickStateAction(QObject *, const QString &, const QVariant &);
- QQuickStateAction(QObject *, const QString &,
- QQmlContext *, const QVariant &);
+ QQuickStateAction(QObject *, const QQmlProperty &property, const QString &,
+ const QVariant &);
bool restore:1;
bool actionDone:1;
diff --git a/src/quick/util/qquicktransition.cpp b/src/quick/util/qquicktransition.cpp
index 29690a4857..6ae89c4ed4 100644
--- a/src/quick/util/qquicktransition.cpp
+++ b/src/quick/util/qquicktransition.cpp
@@ -109,7 +109,7 @@ protected:
void updateState(QAbstractAnimationJob::State newState, QAbstractAnimationJob::State oldState) override;
};
-class QQuickTransitionPrivate : public QObjectPrivate, QAnimationJobChangeListener
+class QQuickTransitionPrivate : public QObjectPrivate
{
Q_DECLARE_PUBLIC(QQuickTransition)
public:
@@ -120,11 +120,8 @@ public:
{
}
- void removeStateChangeListener(QAbstractAnimationJob *anim)
- {
- if (anim)
- anim->removeAnimationChangeListener(this, QAbstractAnimationJob::StateChange);
- }
+ static QQuickTransitionPrivate *get(QQuickTransition *q) { return q->d_func(); }
+ void animationStateChanged(QAbstractAnimationJob::State newState);
QString fromState;
QString toState;
@@ -134,7 +131,6 @@ public:
bool reversible;
bool enabled;
protected:
- void animationStateChanged(QAbstractAnimationJob *, QAbstractAnimationJob::State, QAbstractAnimationJob::State) override;
static void append_animation(QQmlListProperty<QQuickAbstractAnimation> *list, QQuickAbstractAnimation *a);
static int animation_count(QQmlListProperty<QQuickAbstractAnimation> *list);
@@ -171,7 +167,16 @@ void QQuickTransitionPrivate::clear_animations(QQmlListProperty<QQuickAbstractAn
}
}
-void QQuickTransitionPrivate::animationStateChanged(QAbstractAnimationJob *, QAbstractAnimationJob::State newState, QAbstractAnimationJob::State)
+void QQuickTransitionInstance::animationStateChanged(QAbstractAnimationJob *, QAbstractAnimationJob::State newState, QAbstractAnimationJob::State)
+{
+ if (!m_transition)
+ return;
+
+ QQuickTransitionPrivate *transition = QQuickTransitionPrivate::get(m_transition);
+ transition->animationStateChanged(newState);
+}
+
+void QQuickTransitionPrivate::animationStateChanged(QAbstractAnimationJob::State newState)
{
Q_Q(QQuickTransition);
@@ -197,15 +202,16 @@ void ParallelAnimationWrapper::updateState(QAbstractAnimationJob::State newState
}
}
-QQuickTransitionInstance::QQuickTransitionInstance(QQuickTransitionPrivate *transition, QAbstractAnimationJob *anim)
+QQuickTransitionInstance::QQuickTransitionInstance(QQuickTransition *transition, QAbstractAnimationJob *anim)
: m_transition(transition)
, m_anim(anim)
{
+ anim->addAnimationChangeListener(this, QAbstractAnimationJob::StateChange);
}
QQuickTransitionInstance::~QQuickTransitionInstance()
{
- m_transition->removeStateChangeListener(m_anim);
+ removeStateChangeListener();
delete m_anim;
}
@@ -270,8 +276,7 @@ QQuickTransitionInstance *QQuickTransition::prepare(QQuickStateOperation::Action
group->setDirection(d->reversed ? QAbstractAnimationJob::Backward : QAbstractAnimationJob::Forward);
- group->addAnimationChangeListener(d, QAbstractAnimationJob::StateChange);
- QQuickTransitionInstance *wrapper = new QQuickTransitionInstance(d, group);
+ QQuickTransitionInstance *wrapper = new QQuickTransitionInstance(this, group);
return wrapper;
}
diff --git a/src/quick/util/qquicktransition_p.h b/src/quick/util/qquicktransition_p.h
index d6f365f99e..6d2e41fc9d 100644
--- a/src/quick/util/qquicktransition_p.h
+++ b/src/quick/util/qquicktransition_p.h
@@ -53,6 +53,7 @@
#include "qquickstate_p.h"
#include <private/qabstractanimationjob_p.h>
+#include <private/qqmlguard_p.h>
#include <qqml.h>
#include <QtCore/qobject.h>
@@ -64,10 +65,10 @@ class QQuickTransitionPrivate;
class QQuickTransitionManager;
class QQuickTransition;
-class QQuickTransitionInstance
+class QQuickTransitionInstance : QAnimationJobChangeListener
{
public:
- QQuickTransitionInstance(QQuickTransitionPrivate *transition, QAbstractAnimationJob *anim);
+ QQuickTransitionInstance(QQuickTransition *transition, QAbstractAnimationJob *anim);
~QQuickTransitionInstance();
void start();
@@ -75,8 +76,16 @@ public:
bool isRunning() const;
+protected:
+ void animationStateChanged(QAbstractAnimationJob *, QAbstractAnimationJob::State, QAbstractAnimationJob::State) override;
+
+ void removeStateChangeListener()
+ {
+ m_anim->removeAnimationChangeListener(this, QAbstractAnimationJob::StateChange);
+ }
+
private:
- QQuickTransitionPrivate *m_transition;
+ QQmlGuard<QQuickTransition> m_transition;
QAbstractAnimationJob *m_anim;
friend class QQuickTransition;
};
diff --git a/src/quickwidgets/qquickwidget.cpp b/src/quickwidgets/qquickwidget.cpp
index a64fabcfc2..94f00f7d36 100644
--- a/src/quickwidgets/qquickwidget.cpp
+++ b/src/quickwidgets/qquickwidget.cpp
@@ -935,7 +935,7 @@ void QQuickWidget::createFramebufferObject()
}
QOpenGLContext *shareWindowContext = QWidgetPrivate::get(window())->shareContext();
- if (shareWindowContext && context->shareContext() != shareWindowContext) {
+ if (shareWindowContext && context->shareContext() != shareWindowContext && !qGuiApp->testAttribute(Qt::AA_ShareOpenGLContexts)) {
context->setShareContext(shareWindowContext);
context->setScreen(shareWindowContext->screen());
if (!context->create())
@@ -1247,11 +1247,11 @@ void QQuickWidget::mouseMoveEvent(QMouseEvent *e)
Q_QUICK_INPUT_PROFILE(QQuickProfiler::Mouse, QQuickProfiler::InputMouseMove, e->localPos().x(),
e->localPos().y());
- // Use the constructor taking localPos and screenPos. That puts localPos into the
- // event's localPos and windowPos, and screenPos into the event's screenPos. This way
- // the windowPos in e is ignored and is replaced by localPos. This is necessary
- // because QQuickWindow thinks of itself as a top-level window always.
- QMouseEvent mappedEvent(e->type(), e->localPos(), e->windowPos(), e->screenPos(),
+ // Put localPos into the event's localPos and windowPos, and screenPos into the
+ // event's screenPos. This way the windowPos in e is ignored and is replaced by
+ // localPos. This is necessary because QQuickWindow thinks of itself as a
+ // top-level window always.
+ QMouseEvent mappedEvent(e->type(), e->localPos(), e->localPos(), e->screenPos(),
e->button(), e->buttons(), e->modifiers(), e->source());
QCoreApplication::sendEvent(d->offscreenWindow, &mappedEvent);
e->setAccepted(mappedEvent.isAccepted());
@@ -1266,11 +1266,11 @@ void QQuickWidget::mouseDoubleClickEvent(QMouseEvent *e)
// As the second mouse press is suppressed in widget windows we emulate it here for QML.
// See QTBUG-25831
- QMouseEvent pressEvent(QEvent::MouseButtonPress, e->localPos(), e->windowPos(), e->screenPos(),
+ QMouseEvent pressEvent(QEvent::MouseButtonPress, e->localPos(), e->localPos(), e->screenPos(),
e->button(), e->buttons(), e->modifiers(), e->source());
QCoreApplication::sendEvent(d->offscreenWindow, &pressEvent);
e->setAccepted(pressEvent.isAccepted());
- QMouseEvent mappedEvent(e->type(), e->localPos(), e->windowPos(), e->screenPos(),
+ QMouseEvent mappedEvent(e->type(), e->localPos(), e->localPos(), e->screenPos(),
e->button(), e->buttons(), e->modifiers(), e->source());
QCoreApplication::sendEvent(d->offscreenWindow, &mappedEvent);
}
@@ -1331,7 +1331,7 @@ void QQuickWidget::mousePressEvent(QMouseEvent *e)
Q_QUICK_INPUT_PROFILE(QQuickProfiler::Mouse, QQuickProfiler::InputMousePress, e->button(),
e->buttons());
- QMouseEvent mappedEvent(e->type(), e->localPos(), e->windowPos(), e->screenPos(),
+ QMouseEvent mappedEvent(e->type(), e->localPos(), e->localPos(), e->screenPos(),
e->button(), e->buttons(), e->modifiers(), e->source());
QCoreApplication::sendEvent(d->offscreenWindow, &mappedEvent);
e->setAccepted(mappedEvent.isAccepted());
@@ -1344,7 +1344,7 @@ void QQuickWidget::mouseReleaseEvent(QMouseEvent *e)
Q_QUICK_INPUT_PROFILE(QQuickProfiler::Mouse, QQuickProfiler::InputMouseRelease, e->button(),
e->buttons());
- QMouseEvent mappedEvent(e->type(), e->localPos(), e->windowPos(), e->screenPos(),
+ QMouseEvent mappedEvent(e->type(), e->localPos(), e->localPos(), e->screenPos(),
e->button(), e->buttons(), e->modifiers(), e->source());
QCoreApplication::sendEvent(d->offscreenWindow, &mappedEvent);
e->setAccepted(mappedEvent.isAccepted());
@@ -1395,6 +1395,28 @@ static Qt::WindowState resolveWindowState(Qt::WindowStates states)
return Qt::WindowNoState;
}
+static void remapInputMethodQueryEvent(QObject *object, QInputMethodQueryEvent *e)
+{
+ auto item = qobject_cast<QQuickItem *>(object);
+ if (!item)
+ return;
+
+ // Remap all QRectF values.
+ for (auto query : {Qt::ImCursorRectangle, Qt::ImAnchorRectangle, Qt::ImInputItemClipRectangle}) {
+ if (e->queries() & query) {
+ auto value = e->value(query);
+ if (value.canConvert<QRectF>())
+ e->setValue(query, item->mapRectToScene(value.toRectF()));
+ }
+ }
+ // Remap all QPointF values.
+ if (e->queries() & Qt::ImCursorPosition) {
+ auto value = e->value(Qt::ImCursorPosition);
+ if (value.canConvert<QPointF>())
+ e->setValue(Qt::ImCursorPosition, item->mapToScene(value.toPointF()));
+ }
+}
+
/*! \reimp */
bool QQuickWidget::event(QEvent *e)
{
@@ -1411,8 +1433,17 @@ bool QQuickWidget::event(QEvent *e)
return QCoreApplication::sendEvent(d->offscreenWindow, e);
case QEvent::InputMethod:
- case QEvent::InputMethodQuery:
return QCoreApplication::sendEvent(d->offscreenWindow->focusObject(), e);
+ case QEvent::InputMethodQuery:
+ {
+ bool eventResult = QCoreApplication::sendEvent(d->offscreenWindow->focusObject(), e);
+ // The result in focusObject are based on offscreenWindow. But
+ // the inputMethodTransform won't get updated because the focus
+ // is on QQuickWidget. We need to remap the value based on the
+ // widget.
+ remapInputMethodQueryEvent(d->offscreenWindow->focusObject(), static_cast<QInputMethodQueryEvent *>(e));
+ return eventResult;
+ }
case QEvent::WindowChangeInternal:
d->handleWindowChange();