aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@digia.com>2014-06-03 15:28:51 +0200
committerSimon Hausmann <simon.hausmann@digia.com>2014-06-04 17:02:55 +0200
commit11a11d1280b1634628b9c4a92a0fc420ee8a3a81 (patch)
treeb48d9608ef3f08123cdeea605068342131b32b44
parent52e07d564b65ed6ce26955a676c7692ad67686c1 (diff)
parentfea26bb2941c3f24c4a5f3ad5efc1b85e0123ff3 (diff)
Merge remote-tracking branch 'origin/stable' into dev
The merge conflict is about the removal of "d1" from the register set on ARM, but that was already done in dev in commit ddb33ee9ba9e1344caa9be5dbf4b534c3ede692e The change in src/quick/scenegraph/coreapi/qsgrenderer.cpp with commit 2414f1675eab163b22dcc4e8ded80ed04d06369b was reverted to what it was before, per Laszlo's advice. Conflicts: src/qml/jit/qv4isel_masm.cpp Change-Id: I7bce546c5cdee01e37853a476d82279d4e72948b
-rw-r--r--examples/quick/demos/photoviewer/main.qml18
-rw-r--r--examples/quick/demos/samegame/samegame.pro2
-rw-r--r--src/imports/localstorage/plugin.cpp2
-rw-r--r--src/particles/qquickitemparticle.cpp1
-rw-r--r--src/qml/compiler/qqmltypecompiler.cpp21
-rw-r--r--src/qml/compiler/qv4compileddata_p.h54
-rw-r--r--src/qml/qml/qqmlimport.cpp18
-rw-r--r--src/qml/qml/qqmlobjectcreator.cpp2
-rw-r--r--src/qml/qml/qqmlscriptstring.cpp4
-rw-r--r--src/qml/qml/v8/qqmlbuiltinfunctions.cpp5
-rw-r--r--src/qml/types/qqmllistmodel.cpp44
-rw-r--r--src/qml/types/qqmllistmodel_p.h3
-rw-r--r--src/qml/types/qquickworkerscript.cpp54
-rw-r--r--src/quick/items/context2d/qquickcontext2d.cpp20
-rw-r--r--src/quick/items/context2d/qquickcontext2d_p.h2
-rw-r--r--src/quick/items/context2d/qquickcontext2dcommandbuffer.cpp3
-rw-r--r--src/quick/items/qquickaccessibleattached.cpp157
-rw-r--r--src/quick/items/qquickclipnode.cpp2
-rw-r--r--src/quick/items/qquickmousearea.cpp2
-rw-r--r--src/quick/items/qquickmultipointtoucharea.cpp2
-rw-r--r--src/quick/items/qquickrendercontrol.cpp23
-rw-r--r--src/quick/items/qquickrendercontrol_p.h1
-rw-r--r--src/quick/items/qquickshadereffect.cpp10
-rw-r--r--src/quick/items/qquickwindow.h2
-rw-r--r--src/quick/scenegraph/qsgcontext.cpp3
-rw-r--r--src/quick/scenegraph/qsgdefaultglyphnode_p.cpp1
-rw-r--r--src/quick/util/qquickanimationcontroller.cpp2
-rw-r--r--src/quick/util/qquickpixmapcache.cpp2
-rw-r--r--src/quickwidgets/qquickwidget.cpp61
-rw-r--r--src/quickwidgets/qquickwidget_p.h1
-rw-r--r--tests/auto/qml/debugger/debugger.pro4
-rw-r--r--tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp234
-rw-r--r--tests/auto/qml/qqmllanguage/data/idPropertyMismatch.qml5
-rw-r--r--tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp88
-rw-r--r--tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp129
-rw-r--r--tests/auto/qmltest/textinput/tst_textinput.qml45
-rw-r--r--tests/auto/quick/qquicktext/data/horizontalAlignment_RightToLeft.qml2
-rw-r--r--tests/auto/quick/qquicktext/tst_qquicktext.cpp7
-rw-r--r--tools/tools.pro2
39 files changed, 711 insertions, 327 deletions
diff --git a/examples/quick/demos/photoviewer/main.qml b/examples/quick/demos/photoviewer/main.qml
index f443b70762..cbafb0112a 100644
--- a/examples/quick/demos/photoviewer/main.qml
+++ b/examples/quick/demos/photoviewer/main.qml
@@ -49,6 +49,15 @@ ApplicationWindow {
visible: true
+ Rectangle {
+ focus: true
+
+ Keys.onBackPressed: {
+ event.accepted = true
+ backButton.clicked()
+ }
+ }
+
property real downloadProgress: 0
property bool imageLoading: false
property bool editMode: false
@@ -99,7 +108,14 @@ ApplicationWindow {
ListView { anchors.fill: parent; model: albumVisualModel.parts.browser; interactive: false }
- Button { id: backButton; label: qsTr("Back"); rotation: 3; x: parent.width - backButton.width - 6; y: -backButton.height - 8 }
+ Button {
+ id: backButton
+ label: qsTr("Back")
+ rotation: 3
+ x: parent.width - backButton.width - 6
+ y: -backButton.height - 8
+ visible: Qt.platform.os !== "android"
+ }
Rectangle { id: photosShade; color: 'black'; width: parent.width; height: parent.height; opacity: 0; visible: opacity != 0.0 }
diff --git a/examples/quick/demos/samegame/samegame.pro b/examples/quick/demos/samegame/samegame.pro
index 59cacd3c8b..b9b316871c 100644
--- a/examples/quick/demos/samegame/samegame.pro
+++ b/examples/quick/demos/samegame/samegame.pro
@@ -6,3 +6,5 @@ RESOURCES += samegame.qrc
target.path = $$[QT_INSTALL_EXAMPLES]/quick/demos/samegame
INSTALLS += target
+
+QTPLUGIN += qsqlite
diff --git a/src/imports/localstorage/plugin.cpp b/src/imports/localstorage/plugin.cpp
index 7a7649c6f1..d5dbeeb4c2 100644
--- a/src/imports/localstorage/plugin.cpp
+++ b/src/imports/localstorage/plugin.cpp
@@ -694,7 +694,6 @@ void QQuickLocalStorage::openDatabaseSync(QQmlV4Function *args)
V4THROW_SQL2(SQLEXCEPTION_VERSION_ERR, QQmlEngine::tr("SQL: database version mismatch"));
} else {
created = !QFile::exists(basename+QLatin1String(".sqlite"));
- database = QSqlDatabase::addDatabase(QLatin1String("QSQLITE"), dbid);
if (created) {
ini.setValue(QLatin1String("Name"), dbname);
if (dbcreationCallback)
@@ -710,6 +709,7 @@ void QQuickLocalStorage::openDatabaseSync(QQmlV4Function *args)
}
version = ini.value(QLatin1String("Version")).toString();
}
+ database = QSqlDatabase::addDatabase(QLatin1String("QSQLITE"), dbid);
database.setDatabaseName(basename+QLatin1String(".sqlite"));
}
if (!database.isOpen())
diff --git a/src/particles/qquickitemparticle.cpp b/src/particles/qquickitemparticle.cpp
index 0fe0b2ae0b..1f357df20d 100644
--- a/src/particles/qquickitemparticle.cpp
+++ b/src/particles/qquickitemparticle.cpp
@@ -163,6 +163,7 @@ void QQuickItemParticle::tick(int time)
m_deletables.clear();
foreach (QQuickParticleData* d, m_loadables){
+ Q_ASSERT(d);
if (m_stasis.contains(d->delegate))
qWarning() << "Current model particles prefers overwrite:false";
//remove old item from the particle that is dying to make room for this one
diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp
index 45fdab3fd1..3aad050dff 100644
--- a/src/qml/compiler/qqmltypecompiler.cpp
+++ b/src/qml/compiler/qqmltypecompiler.cpp
@@ -1746,10 +1746,21 @@ QString QQmlPropertyValidator::bindingAsString(int objectIndex, const QV4::Compi
typedef QVarLengthArray<const QV4::CompiledData::Binding *, 8> GroupPropertyVector;
-static bool compareNameIndices(const QV4::CompiledData::Binding *binding, quint32 name)
+struct BindingFinder
{
- return binding->propertyNameIndex < name;
-}
+ bool operator()(quint32 name, const QV4::CompiledData::Binding *binding) const
+ {
+ return name < binding->propertyNameIndex;
+ }
+ bool operator()(const QV4::CompiledData::Binding *binding, quint32 name) const
+ {
+ return binding->propertyNameIndex < name;
+ }
+ bool operator()(const QV4::CompiledData::Binding *lhs, const QV4::CompiledData::Binding *rhs) const
+ {
+ return lhs->propertyNameIndex < rhs->propertyNameIndex;
+ }
+};
bool QQmlPropertyValidator::validateObject(int objectIndex, const QV4::CompiledData::Binding *instantiatingBinding, bool populatingValueTypeGroupProperty)
{
@@ -1797,7 +1808,7 @@ bool QQmlPropertyValidator::validateObject(int objectIndex, const QV4::CompiledD
return false;
}
- GroupPropertyVector::const_iterator pos = std::lower_bound(groupProperties.constBegin(), groupProperties.constEnd(), binding->propertyNameIndex, compareNameIndices);
+ GroupPropertyVector::const_iterator pos = std::lower_bound(groupProperties.constBegin(), groupProperties.constEnd(), binding->propertyNameIndex, BindingFinder());
groupProperties.insert(pos, binding);
}
@@ -1910,7 +1921,7 @@ bool QQmlPropertyValidator::validateObject(int objectIndex, const QV4::CompiledD
}
if (pd) {
- GroupPropertyVector::const_iterator assignedGroupProperty = std::lower_bound(groupProperties.constBegin(), groupProperties.constEnd(), binding->propertyNameIndex, compareNameIndices);
+ GroupPropertyVector::const_iterator assignedGroupProperty = std::lower_bound(groupProperties.constBegin(), groupProperties.constEnd(), binding->propertyNameIndex, BindingFinder());
const bool assigningToGroupProperty = assignedGroupProperty != groupProperties.constEnd() && !(binding->propertyNameIndex < (*assignedGroupProperty)->propertyNameIndex);
if (!pd->isWritable()
diff --git a/src/qml/compiler/qv4compileddata_p.h b/src/qml/compiler/qv4compileddata_p.h
index 6ee23690a6..5fb94af140 100644
--- a/src/qml/compiler/qv4compileddata_p.h
+++ b/src/qml/compiler/qv4compileddata_p.h
@@ -69,6 +69,10 @@ struct Function;
struct Lookup;
struct RegExp;
+#if defined(Q_CC_MSVC) || defined(Q_CC_GNU)
+#pragma pack(push, 1)
+#endif
+
struct Location
{
qint32 line;
@@ -82,29 +86,6 @@ struct Location
}
};
-struct TypeReference
-{
- TypeReference(const Location &loc)
- : location(loc)
- , needsCreation(false)
- , errorWhenNotFound(false)
- {}
- Location location; // first use
- bool needsCreation : 1; // whether the type needs to be creatable or not
- bool errorWhenNotFound: 1;
-};
-
-// map from name index to location of first use
-struct TypeReferenceMap : QHash<int, TypeReference>
-{
- TypeReference &add(int nameIndex, const Location &loc) {
- Iterator it = find(nameIndex);
- if (it != end())
- return *it;
- return *insert(nameIndex, loc);
- }
-};
-
struct RegExp
{
enum Flags {
@@ -553,6 +534,33 @@ struct QmlUnit
}
};
+#if defined(Q_CC_MSVC) || defined(Q_CC_GNU)
+#pragma pack(pop)
+#endif
+
+struct TypeReference
+{
+ TypeReference(const Location &loc)
+ : location(loc)
+ , needsCreation(false)
+ , errorWhenNotFound(false)
+ {}
+ Location location; // first use
+ bool needsCreation : 1; // whether the type needs to be creatable or not
+ bool errorWhenNotFound: 1;
+};
+
+// map from name index to location of first use
+struct TypeReferenceMap : QHash<int, TypeReference>
+{
+ TypeReference &add(int nameIndex, const Location &loc) {
+ Iterator it = find(nameIndex);
+ if (it != end())
+ return *it;
+ return *insert(nameIndex, loc);
+ }
+};
+
// This is how this hooks into the existing structures:
//VM::Function
diff --git a/src/qml/qml/qqmlimport.cpp b/src/qml/qml/qqmlimport.cpp
index c0b21a943f..bde61dca9d 100644
--- a/src/qml/qml/qqmlimport.cpp
+++ b/src/qml/qml/qqmlimport.cpp
@@ -672,6 +672,8 @@ bool QQmlImportNamespace::Import::resolveType(QQmlTypeLoader *typeLoader,
exists = QQmlFile::bundleFileExists(qmlUrl, typeLoader->engine());
} else {
exists = !typeLoader->absoluteFilePath(QQmlFile::urlToLocalFileOrQrc(qmlUrl)).isEmpty();
+ if (!exists)
+ exists = QQmlMetaType::findCachedCompilationUnit(QUrl(qmlUrl));
}
if (exists) {
@@ -1849,17 +1851,21 @@ bool QQmlImportDatabase::registerPluginTypes(QObject *instance, const QString &b
// This is an 'identified' module
if (typeNamespace != uri) {
// The namespace for type registrations must match the URI for locating the module
- QQmlError error;
- error.setDescription(tr("Module namespace '%1' does not match import URI '%2'").arg(typeNamespace).arg(uri));
- errors->prepend(error);
+ if (errors) {
+ QQmlError error;
+ error.setDescription(tr("Module namespace '%1' does not match import URI '%2'").arg(typeNamespace).arg(uri));
+ errors->prepend(error);
+ }
return false;
}
if (QQmlMetaType::namespaceContainsRegistrations(typeNamespace)) {
// Other modules have already installed to this namespace
- QQmlError error;
- error.setDescription(tr("Namespace '%1' has already been used for type registration").arg(typeNamespace));
- errors->prepend(error);
+ if (errors) {
+ QQmlError error;
+ error.setDescription(tr("Namespace '%1' has already been used for type registration").arg(typeNamespace));
+ errors->prepend(error);
+ }
return false;
} else {
QQmlMetaType::protectNamespace(typeNamespace);
diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp
index efdf4d86da..65e302d3d9 100644
--- a/src/qml/qml/qqmlobjectcreator.cpp
+++ b/src/qml/qml/qqmlobjectcreator.cpp
@@ -651,7 +651,7 @@ void QQmlObjectCreator::setupBindings(const QBitArray &bindingsToSkip)
QString id = stringAt(_compiledObject->idIndex);
if (!id.isEmpty()) {
QQmlPropertyData *idProperty = _propertyCache->property(QStringLiteral("id"), _qobject, context);
- if (idProperty && idProperty->isWritable()) {
+ if (idProperty && idProperty->isWritable() && idProperty->propType == QMetaType::QString) {
QV4::CompiledData::Binding idBinding;
idBinding.propertyNameIndex = 0; // Not used
idBinding.flags = 0;
diff --git a/src/qml/qml/qqmlscriptstring.cpp b/src/qml/qml/qqmlscriptstring.cpp
index fd710df52f..af9d8ec265 100644
--- a/src/qml/qml/qqmlscriptstring.cpp
+++ b/src/qml/qml/qqmlscriptstring.cpp
@@ -126,7 +126,9 @@ Returns whether the QQmlScriptString is empty.
*/
bool QQmlScriptString::isEmpty() const
{
- return d->script.isEmpty();
+ if (!d->script.isEmpty())
+ return false;
+ return d->bindingId == -1;
}
/*!
diff --git a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
index d0d6839bdc..a7db7d214e 100644
--- a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
+++ b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
@@ -980,12 +980,13 @@ ReturnedValue QtObject::method_createQmlObject(CallContext *ctx)
QQmlEngine *engine = v8engine->engine();
QQmlContextData *context = v8engine->callingContext();
+ Q_ASSERT(context);
QQmlContext *effectiveContext = 0;
if (context->isPragmaLibraryContext)
effectiveContext = engine->rootContext();
else
effectiveContext = context->asQQmlContext();
- Q_ASSERT(context && effectiveContext);
+ Q_ASSERT(effectiveContext);
QString qml = ctx->callData->args[0].toQStringNoThrow();
if (qml.isEmpty())
@@ -1086,10 +1087,10 @@ ReturnedValue QtObject::method_createComponent(CallContext *ctx)
QQmlEngine *engine = v8engine->engine();
QQmlContextData *context = v8engine->callingContext();
+ Q_ASSERT(context);
QQmlContextData *effectiveContext = context;
if (context->isPragmaLibraryContext)
effectiveContext = 0;
- Q_ASSERT(context);
QString arg = ctx->callData->args[0].toQStringNoThrow();
if (arg.isEmpty())
diff --git a/src/qml/types/qqmllistmodel.cpp b/src/qml/types/qqmllistmodel.cpp
index 1b074efd56..a0148715ce 100644
--- a/src/qml/types/qqmllistmodel.cpp
+++ b/src/qml/types/qqmllistmodel.cpp
@@ -1694,13 +1694,20 @@ void QQmlListModel::emitItemsChanged(int index, int count, const QVector<int> &r
}
}
+void QQmlListModel::emitItemsAboutToBeRemoved(int index, int count)
+{
+ if (count <= 0 || !m_mainThread)
+ return;
+
+ beginRemoveRows(QModelIndex(), index, index + count - 1);
+}
+
void QQmlListModel::emitItemsRemoved(int index, int count)
{
if (count <= 0)
return;
if (m_mainThread) {
- beginRemoveRows(QModelIndex(), index, index + count - 1);
endRemoveRows();
emit countChanged();
} else {
@@ -1711,13 +1718,20 @@ void QQmlListModel::emitItemsRemoved(int index, int count)
}
}
+void QQmlListModel::emitItemsAboutToBeInserted(int index, int count)
+{
+ if (count <= 0 || !m_mainThread)
+ return;
+
+ beginInsertRows(QModelIndex(), index, index + count - 1);
+}
+
void QQmlListModel::emitItemsInserted(int index, int count)
{
if (count <= 0)
return;
if (m_mainThread) {
- beginInsertRows(QModelIndex(), index, index + count - 1);
endInsertRows();
emit countChanged();
} else {
@@ -1726,13 +1740,20 @@ void QQmlListModel::emitItemsInserted(int index, int count)
}
}
+void QQmlListModel::emitItemsAboutToBeMoved(int from, int to, int n)
+{
+ if (n <= 0 || !m_mainThread)
+ return;
+
+ beginMoveRows(QModelIndex(), from, from + n - 1, QModelIndex(), to > from ? to + n : to);
+}
+
void QQmlListModel::emitItemsMoved(int from, int to, int n)
{
if (n <= 0)
return;
if (m_mainThread) {
- beginMoveRows(QModelIndex(), from, from + n - 1, QModelIndex(), to > from ? to + n : to);
endMoveRows();
} else {
int uid = m_dynamicRoles ? getUid() : m_listModel->getUid();
@@ -1872,6 +1893,8 @@ void QQmlListModel::clear()
{
int cleared = count();
+ emitItemsAboutToBeRemoved(0, cleared);
+
if (m_dynamicRoles) {
for (int i=0 ; i < m_modelObjects.count() ; ++i)
delete m_modelObjects[i];
@@ -1904,6 +1927,8 @@ void QQmlListModel::remove(QQmlV4Function *args)
return;
}
+ emitItemsAboutToBeRemoved(index, removeCount);
+
if (m_dynamicRoles) {
for (int i=0 ; i < removeCount ; ++i)
delete m_modelObjects[index+i];
@@ -1952,6 +1977,7 @@ void QQmlListModel::insert(QQmlV4Function *args)
QV4::ScopedObject argObject(scope);
int objectArrayLength = objectArray->getLength();
+ emitItemsAboutToBeInserted(index, objectArrayLength);
for (int i=0 ; i < objectArrayLength ; ++i) {
argObject = objectArray->getIndexed(i);
@@ -1963,6 +1989,8 @@ void QQmlListModel::insert(QQmlV4Function *args)
}
emitItemsInserted(index, objectArrayLength);
} else if (argObject) {
+ emitItemsAboutToBeInserted(index, 1);
+
if (m_dynamicRoles) {
m_modelObjects.insert(index, DynamicRoleModelNode::create(args->engine()->variantMapFromJS(argObject), this));
} else {
@@ -2001,6 +2029,8 @@ void QQmlListModel::move(int from, int to, int n)
return;
}
+ emitItemsAboutToBeMoved(from, to, n);
+
if (m_dynamicRoles) {
int realFrom = from;
@@ -2056,6 +2086,8 @@ void QQmlListModel::append(QQmlV4Function *args)
int objectArrayLength = objectArray->getLength();
int index = count();
+ emitItemsAboutToBeInserted(index, objectArrayLength);
+
for (int i=0 ; i < objectArrayLength ; ++i) {
argObject = objectArray->getIndexed(i);
@@ -2072,9 +2104,12 @@ void QQmlListModel::append(QQmlV4Function *args)
if (m_dynamicRoles) {
index = m_modelObjects.count();
+ emitItemsAboutToBeInserted(index, 1);
m_modelObjects.append(DynamicRoleModelNode::create(args->engine()->variantMapFromJS(argObject), this));
} else {
- index = m_listModel->append(argObject, args->engine());
+ index = m_listModel->elementCount();
+ emitItemsAboutToBeInserted(index, 1);
+ m_listModel->append(argObject, args->engine());
}
emitItemsInserted(index, 1);
@@ -2169,6 +2204,7 @@ void QQmlListModel::set(int index, const QQmlV4Handle &handle)
if (index == count()) {
+ emitItemsAboutToBeInserted(index, 1);
if (m_dynamicRoles) {
m_modelObjects.append(DynamicRoleModelNode::create(engine()->variantMapFromJS(object), this));
diff --git a/src/qml/types/qqmllistmodel_p.h b/src/qml/types/qqmllistmodel_p.h
index 59cfce81e5..8c12173425 100644
--- a/src/qml/types/qqmllistmodel_p.h
+++ b/src/qml/types/qqmllistmodel_p.h
@@ -144,8 +144,11 @@ private:
static QQmlListModel *createWithOwner(QQmlListModel *newOwner);
void emitItemsChanged(int index, int count, const QVector<int> &roles);
+ void emitItemsAboutToBeRemoved(int index, int count);
void emitItemsRemoved(int index, int count);
+ void emitItemsAboutToBeInserted(int index, int count);
void emitItemsInserted(int index, int count);
+ void emitItemsAboutToBeMoved(int from, int to, int n);
void emitItemsMoved(int from, int to, int n);
};
diff --git a/src/qml/types/qquickworkerscript.cpp b/src/qml/types/qquickworkerscript.cpp
index 507e94fb7e..80c4112930 100644
--- a/src/qml/types/qquickworkerscript.cpp
+++ b/src/qml/types/qquickworkerscript.cpp
@@ -382,36 +382,44 @@ void QQuickWorkerScriptEnginePrivate::processLoad(int id, const QUrl &url)
QString fileName = QQmlFile::urlToLocalFileOrQrc(url);
- QFile f(fileName);
- if (f.open(QIODevice::ReadOnly)) {
- QByteArray data = f.readAll();
- QString sourceCode = QString::fromUtf8(data);
- QmlIR::Document::removeScriptPragmas(sourceCode);
+ QV4::ExecutionEngine *v4 = QV8Engine::getV4(workerEngine);
+ QV4::Scope scope(v4);
+ QScopedPointer<QV4::Script> program;
- WorkerScript *script = workers.value(id);
- if (!script)
- return;
- script->source = url;
+ WorkerScript *script = workers.value(id);
+ if (!script)
+ return;
+ script->source = url;
- QV4::ExecutionEngine *v4 = QV8Engine::getV4(workerEngine);
- QV4::Scope scope(v4);
+ QV4::Scoped<QV4::Object> activation(scope, getWorker(script));
+ if (!activation)
+ return;
- QV4::Scoped<QV4::Object> activation(scope, getWorker(script));
- if (!activation)
+ if (const QQmlPrivate::CachedQmlUnit *cachedUnit = QQmlMetaType::findCachedCompilationUnit(url)) {
+ QV4::CompiledData::CompilationUnit *jsUnit = cachedUnit->createCompilationUnit();
+ program.reset(new QV4::Script(v4, activation, jsUnit));
+ } else {
+ QFile f(fileName);
+ if (!f.open(QIODevice::ReadOnly)) {
+ qWarning().nospace() << "WorkerScript: Cannot find source file " << url.toString();
return;
+ }
+
+ QByteArray data = f.readAll();
+ QString sourceCode = QString::fromUtf8(data);
+ QmlIR::Document::removeScriptPragmas(sourceCode);
- QV4::Script program(v4, activation, sourceCode, url.toString());
+ program.reset(new QV4::Script(v4, activation, sourceCode, url.toString()));
+ program->parse();
+ }
+
+ if (!v4->hasException)
+ program->run();
+ if (v4->hasException) {
QV4::ExecutionContext *ctx = v4->currentContext();
- program.parse();
- if (!v4->hasException)
- program.run();
- if (v4->hasException) {
- QQmlError error = QV4::ExecutionEngine::catchExceptionAsQmlError(ctx);
- reportScriptException(script, error);
- }
- } else {
- qWarning().nospace() << "WorkerScript: Cannot find source file " << url.toString();
+ QQmlError error = QV4::ExecutionEngine::catchExceptionAsQmlError(ctx);
+ reportScriptException(script, error);
}
}
diff --git a/src/quick/items/context2d/qquickcontext2d.cpp b/src/quick/items/context2d/qquickcontext2d.cpp
index 29e83e8247..a7d5f7d65f 100644
--- a/src/quick/items/context2d/qquickcontext2d.cpp
+++ b/src/quick/items/context2d/qquickcontext2d.cpp
@@ -3177,11 +3177,6 @@ QV4::ReturnedValue QQuickJSContext2DPixelData::getIndexed(QV4::Managed *m, uint
QV4::ExecutionEngine *v4 = m->engine();
QV4::Scope scope(v4);
QV4::Scoped<QQuickJSContext2DPixelData> r(scope, m->as<QQuickJSContext2DPixelData>());
- if (!m) {
- if (hasProperty)
- *hasProperty = false;
- return m->engine()->currentContext()->throwTypeError();
- }
if (r && index < static_cast<quint32>(r->image.width() * r->image.height() * 4)) {
if (hasProperty)
@@ -3610,10 +3605,12 @@ void QQuickContext2D::clip()
QPainterPath clipPath = m_path;
clipPath.closeSubpath();
- if (!state.clipPath.isEmpty())
+ if (state.clip) {
state.clipPath = clipPath.intersected(state.clipPath);
- else
+ } else {
+ state.clip = true;
state.clipPath = clipPath;
+ }
buffer()->clip(state.clipPath);
}
@@ -4282,9 +4279,8 @@ void QQuickContext2D::popState()
if (newState.miterLimit != state.miterLimit)
buffer()->setMiterLimit(newState.miterLimit);
- if (newState.clipPath != state.clipPath) {
+ if (newState.clip && (!state.clip || newState.clipPath != state.clipPath))
buffer()->clip(newState.clipPath);
- }
if (newState.shadowBlur != state.shadowBlur)
buffer()->setShadowBlur(newState.shadowBlur);
@@ -4312,12 +4308,6 @@ void QQuickContext2D::reset()
m_path = QPainterPath();
- QPainterPath defaultClipPath;
-
- QRect r(0, 0, m_canvas->canvasSize().width(), m_canvas->canvasSize().height());
- r = r.united(m_canvas->canvasWindow().toRect());
- defaultClipPath.addRect(r);
- newState.clipPath = defaultClipPath;
newState.clipPath.setFillRule(Qt::WindingFill);
m_stateStack.clear();
diff --git a/src/quick/items/context2d/qquickcontext2d_p.h b/src/quick/items/context2d/qquickcontext2d_p.h
index ab851d302f..bd1a83ce08 100644
--- a/src/quick/items/context2d/qquickcontext2d_p.h
+++ b/src/quick/items/context2d/qquickcontext2d_p.h
@@ -123,6 +123,7 @@ public:
, strokePatternRepeatX(false)
, strokePatternRepeatY(false)
, invertibleCTM(true)
+ , clip(false)
, fillRule(Qt::WindingFill)
, globalAlpha(1.0)
, lineWidth(1)
@@ -150,6 +151,7 @@ public:
bool strokePatternRepeatX:1;
bool strokePatternRepeatY:1;
bool invertibleCTM:1;
+ bool clip:1;
Qt::FillRule fillRule;
qreal globalAlpha;
qreal lineWidth;
diff --git a/src/quick/items/context2d/qquickcontext2dcommandbuffer.cpp b/src/quick/items/context2d/qquickcontext2dcommandbuffer.cpp
index 5697c25ff0..cb09c9d4ff 100644
--- a/src/quick/items/context2d/qquickcontext2dcommandbuffer.cpp
+++ b/src/quick/items/context2d/qquickcontext2dcommandbuffer.cpp
@@ -215,7 +215,8 @@ void QQuickContext2DCommandBuffer::setPainterState(QPainter* p, const QQuickCont
if (state.globalCompositeOperation != p->compositionMode())
p->setCompositionMode(state.globalCompositeOperation);
- p->setClipPath(state.clipPath);
+ if (state.clip)
+ p->setClipPath(state.clipPath);
}
static void qt_drawImage(QPainter *p, QQuickContext2D::State& state, QImage image, const QRectF& sr, const QRectF& dr, bool shadow = false)
diff --git a/src/quick/items/qquickaccessibleattached.cpp b/src/quick/items/qquickaccessibleattached.cpp
index b5cc6ea3ef..16f684ce77 100644
--- a/src/quick/items/qquickaccessibleattached.cpp
+++ b/src/quick/items/qquickaccessibleattached.cpp
@@ -56,16 +56,39 @@ QT_BEGIN_NAMESPACE
\ingroup qtquick-visual-utility
\ingroup accessibility
- This class is part of \l {Accessibility for Qt Quick Applications}.
+ This class is part of the \l {Accessibility for Qt Quick Applications}.
Items the user interacts with or that give information to the user
- need to expose their information in a semantic way.
+ need to expose their information to the accessibility framework.
Then assistive tools can make use of that information to enable
users to interact with the application in various ways.
-
This enables Qt Quick applications to be used with screen-readers for example.
- The most important properties to set are \l name and \l role.
+ The most important properties are \l name, \l description and \l role.
+
+ Example implementation of a simple button:
+ \qml
+ Rectangle {
+ id: myButton
+ Text {
+ id: label
+ text: "next"
+ }
+ Accessible.role: Accessible.Button
+ Accessible.name: label.text
+ Accessible.description: "shows the next page"
+ function accessiblePressAction() {
+ // do a button click
+ }
+ }
+ \endqml
+ The \l role is set to \c Button to indicate the type of control.
+ \l Accessible.name is the most important information and bound to the text on the button.
+ The name is a short and consise description of the control and should reflect the visual label.
+ In this case it is not clear what the button does with the name only, so \l description contains
+ an explanation.
+ There is also a function \c accessiblePressAction() which can be invoked by assistive tools to trigger
+ the button. This function needs to have the same effect as tapping or clicking the button would have.
\sa Accessibility
*/
@@ -94,25 +117,7 @@ QT_BEGIN_NAMESPACE
This flags sets the semantic type of the widget.
A button for example would have "Button" as type.
- The value must be one of \l QAccessible::Role .
- Example:
- \qml
- Item {
- id: myButton
-
- Text {
- id: label
- // ...
- }
-
- Accessible.name: label.text
- Accessible.role: Accessible.Button
-
- function accessiblePressAction() {
- //...
- }
- }
- \endqml
+ The value must be one of \l QAccessible::Role.
Some roles have special semantics.
In order to implement check boxes for example a "checked" property is expected.
@@ -120,74 +125,116 @@ QT_BEGIN_NAMESPACE
\table
\header
\li \b {Role}
- \li \b {Expected property}
- \li
-
+ \li \b {Properties and functions}
+ \li \b {Explanation}
\row
- \li Button
- \li function accessiblePressAction
- \li Called when the button receives a press action. The implementation should visually simulate a button click and perform the button action.
+ \li All interactive elements
+ \li \l focusable and \l focused
+ \li All elements that the user can interact with should have focusable set to \c true and
+ set \l focus to \c true when they have the focus. This is important even for applications
+ that run on touch-only devices since screen readers often implement a virtual focus that
+ can be moved from item to item.
\row
- \li CheckBox, Radiobutton
- \li checked
+ \li Button, CheckBox, RadioButton
+ \li \c accessiblePressAction()
+ \li A button should have a function with the name \c accessiblePressAction.
+ This function may be called by an assistive tool such as a screen-reader.
+ The implementation needs to behave the same as a mouse click or tap on the button.
+ \row
+ \li CheckBox, RadioButton
+ \li \l checkable, \l checked
\li The check state of the check box. Updated on Press, Check and Uncheck actions.
\row
\li Slider, SpinBox, Dial, ScrollBar
- \li value, minimumValue, maximumValue, stepSize
- \li value will be updated on increase and decrase actions, in accordance with the other properties
-
+ \li \c value, \c minimumValue, \c maximumValue, \c stepSize
+ \li These properties reflect the state and possible values for the elements.
+ \row
+ \li Slider, SpinBox, Dial, ScrollBar
+ \li \c accessibleIncreaseAction(), \c accessibleDecreaseAction()
+ \li Actions to increase and decrease the value of the element.
\endtable
*/
-/*! \qmlproperty bool focusable
+/*! \qmlproperty bool QtQuick::Accessible::focusable
\brief This property holds whether this item is focusable.
- By default, this property is false except for items where the role is one of
- CheckBox, RadioButton, Button, MenuItem, PageTab, EditableText, SpinBox, ComboBox,
- Terminal or ScrollBar.
+ By default, this property is \c false except for items where the role is one of
+ \c CheckBox, \c RadioButton, \c Button, \c MenuItem, \c PageTab, \c EditableText, \c SpinBox, \c ComboBox,
+ \c Terminal or \c ScrollBar.
+ \sa focused
*/
-/*! \qmlproperty bool focused
+/*! \qmlproperty bool QtQuick::Accessible::focused
\brief This property holds whether this item currently has the active focus.
- By default, this property is false, but it will return true for items that
- have \l QQuickItem::hasActiveFocus() returning true.
+ By default, this property is \c false, but it will return \c true for items that
+ have \l QQuickItem::hasActiveFocus() returning \c true.
+ \sa focusable
*/
-/*! \qmlproperty bool checkable
+/*! \qmlproperty bool QtQuick::Accessible::checkable
\brief This property holds whether this item is checkable (like a check box or some buttons).
+
+ By default this property is \c false.
+ \sa checked
*/
-/*! \qmlproperty bool checked
+/*! \qmlproperty bool QtQuick::Accessible::checked
\brief This property holds whether this item is currently checked.
+
+ By default this property is \c false.
+ \sa checkable
*/
-/*! \qmlproperty bool editable
+/*! \qmlproperty bool QtQuick::Accessible::editable
\brief This property holds whether this item has editable text.
+
+ By default this property is \c false.
*/
-/*! \qmlproperty bool multiLine
+/*! \qmlproperty bool QtQuick::Accessible::multiLine
\brief This property holds whether this item has multiple text lines.
+
+ By default this property is \c false.
*/
-/*! \qmlproperty bool readOnly
- \brief This property holds whether this item while being of type \l QAccessible::EditableText
- is set to read-only.
+/*! \qmlproperty bool QtQuick::Accessible::readOnly
+ \brief This property indicates that a text field is read only.
+
+ It is relevant when the role is \l QAccessible::EditableText and set to be read-only.
+ By default this property is \c false.
*/
-/*! \qmlproperty bool selected
+/*! \qmlproperty bool QtQuick::Accessible::selected
\brief This property holds whether this item is selected.
+
+ By default this property is \c false.
+ \sa selectable
*/
-/*! \qmlproperty bool selectable
+/*! \qmlproperty bool QtQuick::Accessible::selectable
\brief This property holds whether this item can be selected.
+
+ By default this property is \c false.
+ \sa selected
*/
-/*! \qmlproperty bool pressed
+/*! \qmlproperty bool QtQuick::Accessible::pressed
\brief This property holds whether this item is pressed (for example a button during a mouse click).
+
+ By default this property is \c false.
*/
-/*! \qmlproperty bool checkStateMixed
+/*! \qmlproperty bool QtQuick::Accessible::checkStateMixed
\brief This property holds whether this item is in the partially checked state.
+
+ By default this property is \c false.
+ \sa checked, checkable
*/
-/*! \qmlproperty bool defaultButton
+/*! \qmlproperty bool QtQuick::Accessible::defaultButton
\brief This property holds whether this item is the default button of a dialog.
+
+ By default this property is \c false.
*/
-/*! \qmlproperty bool passwordEdit
+/*! \qmlproperty bool QtQuick::Accessible::passwordEdit
\brief This property holds whether this item is a password text edit.
+
+ By default this property is \c false.
*/
-/*! \qmlproperty bool selectableText
+/*! \qmlproperty bool QtQuick::Accessible::selectableText
\brief This property holds whether this item contains selectable text.
+
+ By default this property is \c false.
*/
QQuickAccessibleAttached::QQuickAccessibleAttached(QObject *parent)
diff --git a/src/quick/items/qquickclipnode.cpp b/src/quick/items/qquickclipnode.cpp
index 3974073b55..78c29ea4a7 100644
--- a/src/quick/items/qquickclipnode.cpp
+++ b/src/quick/items/qquickclipnode.cpp
@@ -114,8 +114,8 @@ void QQuickDefaultClipNode::updateGeometry()
}
}
- markDirty(DirtyGeometry);
}
+ markDirty(DirtyGeometry);
setClipRect(m_rect);
}
diff --git a/src/quick/items/qquickmousearea.cpp b/src/quick/items/qquickmousearea.cpp
index 01d1305260..f2f90935a3 100644
--- a/src/quick/items/qquickmousearea.cpp
+++ b/src/quick/items/qquickmousearea.cpp
@@ -900,7 +900,7 @@ bool QQuickMouseArea::sendMouseEvent(QMouseEvent *event)
default:
break;
}
- grabber = c->mouseGrabberItem();
+ grabber = c ? c->mouseGrabberItem() : 0;
if (grabber && stealThisEvent && !grabber->keepMouseGrab() && grabber != this)
grabMouse();
diff --git a/src/quick/items/qquickmultipointtoucharea.cpp b/src/quick/items/qquickmultipointtoucharea.cpp
index c20559454e..ee31c018af 100644
--- a/src/quick/items/qquickmultipointtoucharea.cpp
+++ b/src/quick/items/qquickmultipointtoucharea.cpp
@@ -844,7 +844,7 @@ bool QQuickMultiPointTouchArea::sendMouseEvent(QMouseEvent *event)
default:
break;
}
- grabber = c->mouseGrabberItem();
+ grabber = c ? c->mouseGrabberItem() : 0;
if (grabber && stealThisEvent && !grabber->keepMouseGrab() && grabber != this)
grabMouse();
diff --git a/src/quick/items/qquickrendercontrol.cpp b/src/quick/items/qquickrendercontrol.cpp
index 55736c33c3..b8d572114a 100644
--- a/src/quick/items/qquickrendercontrol.cpp
+++ b/src/quick/items/qquickrendercontrol.cpp
@@ -120,13 +120,13 @@ void QQuickRenderControl::initialize(QOpenGLContext *gl)
// surface belonging to window. In fact window may not have a native
// window/surface at all.
- QQuickWindowPrivate::get(d->window)->context->initialize(gl);
+ d->rc->initialize(gl);
}
void QQuickRenderControl::invalidate()
{
Q_D(QQuickRenderControl);
- QQuickWindowPrivate::get(d->window)->context->invalidate();
+ d->rc->invalidate();
}
/*!
@@ -242,6 +242,10 @@ void QQuickRenderControl::setWindow(QQuickWindow *window)
d->window = window;
}
+/*!
+ Returns the offscreen window.
+ */
+
QQuickWindow *QQuickRenderControl::window() const
{
Q_D(const QQuickRenderControl);
@@ -249,6 +253,21 @@ QQuickWindow *QQuickRenderControl::window() const
}
/*!
+ Create an offscreen QQuickWindow for this render control,
+ unless the render control already has a window().
+
+ Returns the offscreen window if one is created, otherwise returns null.
+ The caller takes ownership of the window, and is responsible for deleting it.
+ */
+QQuickWindow *QQuickRenderControl::createOffscreenWindow()
+{
+ Q_D(QQuickRenderControl);
+ if (!d->window)
+ return new QQuickWindow(this);
+ return 0;
+}
+
+/*!
\fn QWindow *QQuickRenderControl::renderWindow(QPoint *offset)
Reimplemented in subclasses to return the real window this render control
diff --git a/src/quick/items/qquickrendercontrol_p.h b/src/quick/items/qquickrendercontrol_p.h
index e7b7759afa..cc30e37724 100644
--- a/src/quick/items/qquickrendercontrol_p.h
+++ b/src/quick/items/qquickrendercontrol_p.h
@@ -63,6 +63,7 @@ public:
~QQuickRenderControl();
QQuickWindow *window() const;
+ QQuickWindow *createOffscreenWindow();
virtual QWindow *renderWindow(QPoint *offset) { Q_UNUSED(offset); return 0; }
static QWindow *renderWindowFor(QQuickWindow *win, QPoint *offset = 0);
diff --git a/src/quick/items/qquickshadereffect.cpp b/src/quick/items/qquickshadereffect.cpp
index e57b7abddc..8bcd2e64db 100644
--- a/src/quick/items/qquickshadereffect.cpp
+++ b/src/quick/items/qquickshadereffect.cpp
@@ -97,7 +97,8 @@ namespace {
// Returns -1 if not found, returns index to first character after the name if found.
int qt_search_for_variable(const char *s, int length, int index, VariableQualifier &decl,
int &typeIndex, int &typeLength,
- int &nameIndex, int &nameLength)
+ int &nameIndex, int &nameLength,
+ QQuickShaderEffectCommon::Key::ShaderType shaderType)
{
enum Identifier {
QualifierIdentifier, // Base state
@@ -124,6 +125,7 @@ namespace {
int idLength = index - idIndex;
const int attrLen = sizeof("attribute") - 1;
+ const int inLen = sizeof("in") - 1;
const int uniLen = sizeof("uniform") - 1;
const int loLen = sizeof("lowp") - 1;
const int medLen = sizeof("mediump") - 1;
@@ -134,6 +136,10 @@ namespace {
if (idLength == attrLen && qstrncmp("attribute", s + idIndex, attrLen) == 0) {
decl = AttributeQualifier;
expected = PrecisionIdentifier;
+ } else if (shaderType == QQuickShaderEffectCommon::Key::VertexShader
+ && idLength == inLen && qstrncmp("in", s + idIndex, inLen) == 0) {
+ decl = AttributeQualifier;
+ expected = PrecisionIdentifier;
} else if (idLength == uniLen && qstrncmp("uniform", s + idIndex, uniLen) == 0) {
decl = UniformQualifier;
expected = PrecisionIdentifier;
@@ -287,7 +293,7 @@ void QQuickShaderEffectCommon::lookThroughShaderCode(QQuickItem *item, Key::Shad
const char *s = code.constData();
VariableQualifier decl = AttributeQualifier;
while ((index = qt_search_for_variable(s, code.size(), index, decl, typeIndex, typeLength,
- nameIndex, nameLength)) != -1)
+ nameIndex, nameLength, shaderType)) != -1)
{
if (decl == AttributeQualifier) {
if (shaderType == Key::VertexShader)
diff --git a/src/quick/items/qquickwindow.h b/src/quick/items/qquickwindow.h
index 1a4adb0785..c95ec5b46d 100644
--- a/src/quick/items/qquickwindow.h
+++ b/src/quick/items/qquickwindow.h
@@ -199,7 +199,7 @@ private Q_SLOTS:
private:
friend class QQuickItem;
friend class QQuickWidget;
- friend class QQuickWidgetPrivate;
+ friend class QQuickRenderControl;
friend class QQuickAnimatorController;
explicit QQuickWindow(QQuickRenderControl*);
Q_DISABLE_COPY(QQuickWindow)
diff --git a/src/quick/scenegraph/qsgcontext.cpp b/src/quick/scenegraph/qsgcontext.cpp
index 99b52a65cb..6a69ea02db 100644
--- a/src/quick/scenegraph/qsgcontext.cpp
+++ b/src/quick/scenegraph/qsgcontext.cpp
@@ -416,6 +416,7 @@ QSGRenderContext *QSGRenderContext::from(QOpenGLContext *context)
void QSGRenderContext::registerFontengineForCleanup(QFontEngine *engine)
{
+ engine->ref.ref();
m_fontEnginesToClean << engine;
}
@@ -495,6 +496,8 @@ void QSGRenderContext::invalidate()
for (QSet<QFontEngine *>::const_iterator it = m_fontEnginesToClean.constBegin(),
end = m_fontEnginesToClean.constEnd(); it != end; ++it) {
(*it)->clearGlyphCache(m_gl);
+ if (!(*it)->ref.deref())
+ delete *it;
}
m_fontEnginesToClean.clear();
diff --git a/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp b/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp
index a69cbc54ea..c3234be158 100644
--- a/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp
+++ b/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp
@@ -352,6 +352,7 @@ QSGTextMaskMaterial::QSGTextMaskMaterial(const QRawFont &font, QFontEngine::Glyp
QSGTextMaskMaterial::~QSGTextMaskMaterial()
{
+ delete m_texture;
}
void QSGTextMaskMaterial::init(QFontEngine::GlyphFormat glyphFormat)
diff --git a/src/quick/util/qquickanimationcontroller.cpp b/src/quick/util/qquickanimationcontroller.cpp
index 0214dde597..6a9308da3e 100644
--- a/src/quick/util/qquickanimationcontroller.cpp
+++ b/src/quick/util/qquickanimationcontroller.cpp
@@ -142,7 +142,7 @@ void QQuickAnimationController::setProgress(qreal progress)
}
/*!
- \qmlproperty real QtQuick::AnimationController::animation
+ \qmlproperty Animation QtQuick::AnimationController::animation
\default
This property holds the animation to be controlled by the AnimationController.
diff --git a/src/quick/util/qquickpixmapcache.cpp b/src/quick/util/qquickpixmapcache.cpp
index b90ca47fd1..0a5b26281a 100644
--- a/src/quick/util/qquickpixmapcache.cpp
+++ b/src/quick/util/qquickpixmapcache.cpp
@@ -810,7 +810,7 @@ void QQuickPixmapStore::unreferencePixmap(QQuickPixmapData *data)
if (!m_lastUnreferencedPixmap)
m_lastUnreferencedPixmap = data;
- shrinkCache(-1); // Shrink the cache incase it has become larger than cache_limit
+ shrinkCache(-1); // Shrink the cache in case it has become larger than cache_limit
if (m_timerId == -1 && m_unreferencedPixmaps && !m_destroying)
m_timerId = startTimer(CACHE_EXPIRE_TIME * 1000);
diff --git a/src/quickwidgets/qquickwidget.cpp b/src/quickwidgets/qquickwidget.cpp
index 53176faaa6..a8a33c07c8 100644
--- a/src/quickwidgets/qquickwidget.cpp
+++ b/src/quickwidgets/qquickwidget.cpp
@@ -86,7 +86,7 @@ void QQuickWidgetPrivate::init(QQmlEngine* e)
Q_Q(QQuickWidget);
renderControl = new QQuickWidgetRenderControl(q);
- offscreenWindow = new QQuickWindow(renderControl);
+ offscreenWindow = renderControl->createOffscreenWindow();
offscreenWindow->setTitle(QString::fromLatin1("Offscreen"));
// Do not call create() on offscreenWindow.
createOffscreenSurface();
@@ -107,15 +107,33 @@ void QQuickWidgetPrivate::init(QQmlEngine* e)
if (QQmlDebugService::isDebuggingEnabled())
QQmlInspectorService::instance()->addView(q);
+#ifndef QT_NO_DRAGANDDROP
+ q->setAcceptDrops(true);
+#endif
+
QWidget::connect(offscreenWindow, SIGNAL(sceneGraphInitialized()), q, SLOT(createFramebufferObject()));
QWidget::connect(offscreenWindow, SIGNAL(sceneGraphInvalidated()), q, SLOT(destroyFramebufferObject()));
QObject::connect(renderControl, SIGNAL(renderRequested()), q, SLOT(triggerUpdate()));
QObject::connect(renderControl, SIGNAL(sceneChanged()), q, SLOT(triggerUpdate()));
}
-void QQuickWidgetPrivate::handleWindowChange()
+void QQuickWidgetPrivate::stopRenderControl()
{
+ if (!context) // this is not an error, could be called before creating the context, or multiple times
+ return;
+
+ bool success = context->makeCurrent(offscreenSurface);
+ if (!success) {
+ qWarning("QQuickWidget::stopRenderControl could not make context current");
+ return;
+ }
+
renderControl->stop();
+}
+
+void QQuickWidgetPrivate::handleWindowChange()
+{
+ stopRenderControl();
destroyContext();
}
@@ -139,10 +157,17 @@ QQuickWidgetPrivate::~QQuickWidgetPrivate()
{
if (QQmlDebugService::isDebuggingEnabled())
QQmlInspectorService::instance()->removeView(q_func());
- delete offscreenSurface;
+
+ stopRenderControl();
+
+ // context and offscreenSurface are current at this stage, if the context was created.
+ Q_ASSERT(!context || (QOpenGLContext::currentContext() == context && context->surface() == offscreenSurface));
delete offscreenWindow;
delete renderControl;
delete fbo;
+
+ delete offscreenSurface;
+ destroyContext();
}
void QQuickWidgetPrivate::createOffscreenSurface()
@@ -624,9 +649,6 @@ void QQuickWidgetPrivate::createContext()
void QQuickWidgetPrivate::destroyContext()
{
- if (!context)
- return;
- renderControl->invalidate();
delete context;
context = 0;
}
@@ -635,8 +657,6 @@ void QQuickWidget::createFramebufferObject()
{
Q_D(QQuickWidget);
- if (d->fbo)
- delete d->fbo;
QOpenGLContext *context = d->offscreenWindow->openglContext();
if (!context) {
@@ -650,6 +670,8 @@ void QQuickWidget::createFramebufferObject()
}
context->makeCurrent(d->offscreenSurface);
+
+ delete d->fbo;
d->fbo = new QOpenGLFramebufferObject(size() * window()->devicePixelRatio());
d->fbo->setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
d->offscreenWindow->setRenderTarget(d->fbo);
@@ -902,17 +924,7 @@ void QQuickWidget::showEvent(QShowEvent *)
void QQuickWidget::hideEvent(QHideEvent *)
{
Q_D(QQuickWidget);
-
- if (!d->context) {
- qWarning("QQuickWidget::hideEvent with no context");
- return;
- }
- bool success = d->context->makeCurrent(d->offscreenSurface);
- if (!success) {
- qWarning("QQuickWidget::hideEvent could not make context current");
- return;
- }
- d->renderControl->stop();
+ d->stopRenderControl();
}
/*! \reimp */
@@ -960,13 +972,22 @@ void QQuickWidget::focusOutEvent(QFocusEvent * event)
d->offscreenWindow->focusOutEvent(event);
}
-
/*! \reimp */
bool QQuickWidget::event(QEvent *e)
{
Q_D(QQuickWidget);
switch (e->type()) {
+#ifndef QT_NO_DRAGANDDROP
+ case QEvent::Drop:
+ case QEvent::DragEnter:
+ case QEvent::DragMove:
+ case QEvent::DragLeave:
+ // Drag/drop events only have local pos, so no need to map,
+ // but QQuickWindow::event() does not return true
+ d->offscreenWindow->event(e);
+ return e->isAccepted();
+#endif
case QEvent::TouchBegin:
case QEvent::TouchEnd:
case QEvent::TouchUpdate:
diff --git a/src/quickwidgets/qquickwidget_p.h b/src/quickwidgets/qquickwidget_p.h
index 5cf2bfbf1d..8efe32b3ce 100644
--- a/src/quickwidgets/qquickwidget_p.h
+++ b/src/quickwidgets/qquickwidget_p.h
@@ -93,6 +93,7 @@ public:
void init(QQmlEngine* e = 0);
void handleWindowChange();
+ void stopRenderControl();
QSize rootObjectSize() const;
diff --git a/tests/auto/qml/debugger/debugger.pro b/tests/auto/qml/debugger/debugger.pro
index 4c4342a6a5..303e78db75 100644
--- a/tests/auto/qml/debugger/debugger.pro
+++ b/tests/auto/qml/debugger/debugger.pro
@@ -6,11 +6,7 @@ PUBLICTESTS += \
qqmlinspector \
qqmlprofilerservice \
qpacketprotocol \
-# qv4profilerservice \
-# qdebugmessageservice \
qqmlenginedebuginspectorintegrationtest \
- qqmlinspector \
- qqmlprofilerservice \
qqmlenginecontrol
PRIVATETESTS += \
diff --git a/tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp b/tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp
index a918e23a05..5fd985f6d5 100644
--- a/tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp
+++ b/tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp
@@ -136,7 +136,9 @@ public:
{
}
- QList<QQmlProfilerData> traceMessages;
+ QList<QQmlProfilerData> synchronousMessages;
+ QList<QQmlProfilerData> asynchronousMessages;
+ QList<QQmlProfilerData> pixmapMessages;
void setTraceState(bool enabled) {
QByteArray message;
@@ -171,6 +173,7 @@ private:
QQmlProfilerClient *m_client;
void connect(bool block, const QString &testFile);
+ void checkTraceReceived();
private slots:
void cleanup();
@@ -305,7 +308,17 @@ void QQmlProfilerClient::messageReceived(const QByteArray &message)
break;
}
QVERIFY(stream.atEnd());
- traceMessages.append(data);
+ if (data.messageType == QQmlProfilerClient::PixmapCacheEvent)
+ pixmapMessages.append(data);
+ else if (data.messageType == QQmlProfilerClient::SceneGraphFrame ||
+ (data.messageType == QQmlProfilerClient::Event &&
+ (data.detailType == QQmlProfilerClient::FramePaint ||
+ data.detailType == QQmlProfilerClient::AnimationFrame ||
+ data.detailType == QQmlProfilerClient::Mouse ||
+ data.detailType == QQmlProfilerClient::Key)))
+ asynchronousMessages.append(data);
+ else
+ synchronousMessages.append(data);
}
void tst_QQmlProfilerService::connect(bool block, const QString &testFile)
@@ -331,9 +344,44 @@ void tst_QQmlProfilerService::connect(bool block, const QString &testFile)
m_connection->connectToHost(QLatin1String("127.0.0.1"), port);
}
+void tst_QQmlProfilerService::checkTraceReceived()
+{
+ QVERIFY2(QQmlDebugTest::waitForSignal(m_client, SIGNAL(complete())), "No trace received in time.");
+ QVERIFY(m_client->synchronousMessages.count());
+
+ // must start with "StartTrace"
+ QCOMPARE(m_client->synchronousMessages.first().messageType, (int)QQmlProfilerClient::Event);
+ QCOMPARE(m_client->synchronousMessages.first().detailType, (int)QQmlProfilerClient::StartTrace);
+
+ // must end with "EndTrace"
+ QCOMPARE(m_client->synchronousMessages.last().messageType, (int)QQmlProfilerClient::Event);
+ QCOMPARE(m_client->synchronousMessages.last().detailType, (int)QQmlProfilerClient::EndTrace);
+}
+
void tst_QQmlProfilerService::cleanup()
{
if (QTest::currentTestFailed()) {
+ qDebug() << "Synchronous Messages:" << m_client->synchronousMessages.count();
+ int i = 0;
+ foreach (const QQmlProfilerData &data, m_client->synchronousMessages) {
+ qDebug() << i++ << data.time << data.messageType << data.detailType << data.detailData
+ << data.line << data.column;
+ }
+ qDebug() << " ";
+ qDebug() << "Asynchronous Messages:" << m_client->asynchronousMessages.count();
+ i = 0;
+ foreach (const QQmlProfilerData &data, m_client->asynchronousMessages) {
+ qDebug() << i++ << data.time << data.messageType << data.detailType << data.detailData
+ << data.framerate << data.animationcount << data.line << data.column;
+ }
+ qDebug() << " ";
+ qDebug() << "Pixmap Cache Messages:" << m_client->pixmapMessages.count();
+ i = 0;
+ foreach (const QQmlProfilerData &data, m_client->pixmapMessages) {
+ qDebug() << i++ << data.time << data.messageType << data.detailType << data.detailData
+ << data.line << data.column;
+ }
+ qDebug() << " ";
qDebug() << "Process State:" << (m_process ? m_process->state() : QLatin1String("null"));
qDebug() << "Application Output:" << (m_process ? m_process->output() : QLatin1String("null"));
qDebug() << "Connection State:" << (m_connection ? m_connection->stateString() : QLatin1String("null"));
@@ -355,16 +403,7 @@ void tst_QQmlProfilerService::blockingConnectWithTraceEnabled()
m_client->setTraceState(true);
m_client->setTraceState(false);
- QVERIFY2(QQmlDebugTest::waitForSignal(m_client, SIGNAL(complete())), "No trace received in time.");
-
- QVERIFY(m_client->traceMessages.count());
- // must start with "StartTrace"
- QCOMPARE(m_client->traceMessages.first().messageType, (int)QQmlProfilerClient::Event);
- QCOMPARE(m_client->traceMessages.first().detailType, (int)QQmlProfilerClient::StartTrace);
-
- // must end with "EndTrace"
- QCOMPARE(m_client->traceMessages.last().messageType, (int)QQmlProfilerClient::Event);
- QCOMPARE(m_client->traceMessages.last().detailType, (int)QQmlProfilerClient::EndTrace);
+ checkTraceReceived();
}
void tst_QQmlProfilerService::blockingConnectWithTraceDisabled()
@@ -376,17 +415,7 @@ void tst_QQmlProfilerService::blockingConnectWithTraceDisabled()
m_client->setTraceState(false);
m_client->setTraceState(true);
m_client->setTraceState(false);
- QVERIFY2(QQmlDebugTest::waitForSignal(m_client, SIGNAL(complete())), "No trace received in time.");
-
- QVERIFY(m_client->traceMessages.count());
-
- // must start with "StartTrace"
- QCOMPARE(m_client->traceMessages.first().messageType, (int)QQmlProfilerClient::Event);
- QCOMPARE(m_client->traceMessages.first().detailType, (int)QQmlProfilerClient::StartTrace);
-
- // must end with "EndTrace"
- QCOMPARE(m_client->traceMessages.last().messageType, (int)QQmlProfilerClient::Event);
- QCOMPARE(m_client->traceMessages.last().detailType, (int)QQmlProfilerClient::EndTrace);
+ checkTraceReceived();
}
void tst_QQmlProfilerService::nonBlockingConnect()
@@ -397,16 +426,7 @@ void tst_QQmlProfilerService::nonBlockingConnect()
m_client->setTraceState(true);
m_client->setTraceState(false);
- QVERIFY2(QQmlDebugTest::waitForSignal(m_client, SIGNAL(complete())), "No trace received in time.");
- QVERIFY(m_client->traceMessages.count());
-
- // must start with "StartTrace"
- QCOMPARE(m_client->traceMessages.first().messageType, (int)QQmlProfilerClient::Event);
- QCOMPARE(m_client->traceMessages.first().detailType, (int)QQmlProfilerClient::StartTrace);
-
- // must end with "EndTrace"
- QCOMPARE(m_client->traceMessages.last().messageType, (int)QQmlProfilerClient::Event);
- QCOMPARE(m_client->traceMessages.last().detailType, (int)QQmlProfilerClient::EndTrace);
+ checkTraceReceived();
}
void tst_QQmlProfilerService::pixmapCacheData()
@@ -424,35 +444,27 @@ void tst_QQmlProfilerService::pixmapCacheData()
m_client->setTraceState(false);
- QVERIFY2(QQmlDebugTest::waitForSignal(m_client, SIGNAL(complete())), "No trace received in time.");
- QVERIFY2(m_client->traceMessages.count() >= 20,
- QString::number(m_client->traceMessages.count()).toUtf8().constData());
-
- // must start with "StartTrace"
- QCOMPARE(m_client->traceMessages.first().messageType, (int)QQmlProfilerClient::Event);
- QCOMPARE(m_client->traceMessages.first().detailType, (int)QQmlProfilerClient::StartTrace);
+ checkTraceReceived();
+ QVERIFY2(m_client->pixmapMessages.count() >= 4,
+ QString::number(m_client->pixmapMessages.count()).toUtf8().constData());
// image starting to load
- QCOMPARE(m_client->traceMessages[16].messageType, (int)QQmlProfilerClient::PixmapCacheEvent);
- QCOMPARE(m_client->traceMessages[16].detailType, (int)QQmlProfilerClient::PixmapLoadingStarted);
+ QCOMPARE(m_client->pixmapMessages[0].messageType, (int)QQmlProfilerClient::PixmapCacheEvent);
+ QCOMPARE(m_client->pixmapMessages[0].detailType, (int)QQmlProfilerClient::PixmapLoadingStarted);
// image size
- QCOMPARE(m_client->traceMessages[17].messageType, (int)QQmlProfilerClient::PixmapCacheEvent);
- QCOMPARE(m_client->traceMessages[17].detailType, (int)QQmlProfilerClient::PixmapSizeKnown);
- QCOMPARE(m_client->traceMessages[17].line, 2); // width
- QCOMPARE(m_client->traceMessages[17].column, 2); // height
+ QCOMPARE(m_client->pixmapMessages[1].messageType, (int)QQmlProfilerClient::PixmapCacheEvent);
+ QCOMPARE(m_client->pixmapMessages[1].detailType, (int)QQmlProfilerClient::PixmapSizeKnown);
+ QCOMPARE(m_client->pixmapMessages[1].line, 2); // width
+ QCOMPARE(m_client->pixmapMessages[1].column, 2); // height
// image loaded
- QCOMPARE(m_client->traceMessages[18].messageType, (int)QQmlProfilerClient::PixmapCacheEvent);
- QCOMPARE(m_client->traceMessages[18].detailType, (int)QQmlProfilerClient::PixmapLoadingFinished);
+ QCOMPARE(m_client->pixmapMessages[2].messageType, (int)QQmlProfilerClient::PixmapCacheEvent);
+ QCOMPARE(m_client->pixmapMessages[2].detailType, (int)QQmlProfilerClient::PixmapLoadingFinished);
// cache size
- QCOMPARE(m_client->traceMessages[19].messageType, (int)QQmlProfilerClient::PixmapCacheEvent);
- QCOMPARE(m_client->traceMessages[19].detailType, (int)QQmlProfilerClient::PixmapCacheCountChanged);
-
- // must end with "EndTrace"
- QCOMPARE(m_client->traceMessages.last().messageType, (int)QQmlProfilerClient::Event);
- QCOMPARE(m_client->traceMessages.last().detailType, (int)QQmlProfilerClient::EndTrace);
+ QCOMPARE(m_client->pixmapMessages[3].messageType, (int)QQmlProfilerClient::PixmapCacheEvent);
+ QCOMPARE(m_client->pixmapMessages[3].detailType, (int)QQmlProfilerClient::PixmapCacheCountChanged);
}
@@ -468,8 +480,7 @@ void tst_QQmlProfilerService::scenegraphData()
QVERIFY(QQmlDebugTest::waitForSignal(m_process, SIGNAL(readyReadStandardOutput())));
m_client->setTraceState(false);
- QVERIFY2(QQmlDebugTest::waitForSignal(m_client, SIGNAL(complete())), "No trace received in time.");
- QVERIFY(m_client->traceMessages.count());
+ checkTraceReceived();
// check that at least one frame was rendered
// there should be a SGPolishAndSync + SGRendererFrame + SGRenderLoopFrame sequence
@@ -477,7 +488,7 @@ void tst_QQmlProfilerService::scenegraphData()
//
// since the rendering happens in a different thread, there could be other unrelated events interleaved
int loopcheck = 0;
- foreach (const QQmlProfilerData &msg, m_client->traceMessages) {
+ foreach (const QQmlProfilerData &msg, m_client->asynchronousMessages) {
if (msg.messageType == QQmlProfilerClient::SceneGraphFrame) {
if (loopcheck == 0 && msg.detailType == QQmlProfilerClient::SceneGraphContextFrame)
loopcheck = 1;
@@ -498,17 +509,7 @@ void tst_QQmlProfilerService::profileOnExit()
m_client->setTraceState(true);
- QVERIFY2(QQmlDebugTest::waitForSignal(m_client, SIGNAL(complete())), "No trace received in time.");
- QVERIFY2(m_client->traceMessages.count() >= 2,
- QString::number(m_client->traceMessages.count()).toUtf8().constData());
-
- // must start with "StartTrace"
- QCOMPARE(m_client->traceMessages.first().messageType, (int)QQmlProfilerClient::Event);
- QCOMPARE(m_client->traceMessages.first().detailType, (int)QQmlProfilerClient::StartTrace);
-
- // must end with "EndTrace"
- QCOMPARE(m_client->traceMessages.last().messageType, (int)QQmlProfilerClient::Event);
- QCOMPARE(m_client->traceMessages.last().detailType, (int)QQmlProfilerClient::EndTrace);
+ checkTraceReceived();
}
void tst_QQmlProfilerService::controlFromJS()
@@ -518,17 +519,7 @@ void tst_QQmlProfilerService::controlFromJS()
QTRY_COMPARE(m_client->state(), QQmlDebugClient::Enabled);
m_client->setTraceState(false);
- QVERIFY2(QQmlDebugTest::waitForSignal(m_client, SIGNAL(complete())), "No trace received in time.");
- QVERIFY2(m_client->traceMessages.count() >= 2,
- QString::number(m_client->traceMessages.count()).toUtf8().constData());
-
- // must start with "StartTrace"
- QCOMPARE(m_client->traceMessages.first().messageType, (int)QQmlProfilerClient::Event);
- QCOMPARE(m_client->traceMessages.first().detailType, (int)QQmlProfilerClient::StartTrace);
-
- // must end with "EndTrace"
- QCOMPARE(m_client->traceMessages.last().messageType, (int)QQmlProfilerClient::Event);
- QCOMPARE(m_client->traceMessages.last().detailType, (int)QQmlProfilerClient::EndTrace);
+ checkTraceReceived();
}
void tst_QQmlProfilerService::signalSourceLocation()
@@ -541,32 +532,24 @@ void tst_QQmlProfilerService::signalSourceLocation()
while (!(m_process->output().contains(QLatin1String("500"))))
QVERIFY(QQmlDebugTest::waitForSignal(m_process, SIGNAL(readyReadStandardOutput())));
m_client->setTraceState(false);
- QVERIFY2(QQmlDebugTest::waitForSignal(m_client, SIGNAL(complete())), "No trace received in time.");
-
- QVERIFY2(m_client->traceMessages.count() >= 20,
- QString::number(m_client->traceMessages.count()).toUtf8().constData());
-
- // must start with "StartTrace"
- QCOMPARE(m_client->traceMessages.first().messageType, (int)QQmlProfilerClient::Event);
- QCOMPARE(m_client->traceMessages.first().detailType, (int)QQmlProfilerClient::StartTrace);
-
- QCOMPARE(m_client->traceMessages[14].messageType, (int)QQmlProfilerClient::RangeLocation);
- QCOMPARE(m_client->traceMessages[14].detailType, (int)QQmlProfilerClient::HandlingSignal);
- QVERIFY2(m_client->traceMessages[14].detailData.endsWith("signalSourceLocation.qml"),
- m_client->traceMessages[14].detailData.toUtf8().constData());
- QCOMPARE(m_client->traceMessages[14].line, 8);
- QCOMPARE(m_client->traceMessages[14].column, 28);
-
- QCOMPARE(m_client->traceMessages[19].messageType, (int)QQmlProfilerClient::RangeLocation);
- QCOMPARE(m_client->traceMessages[19].detailType, (int)QQmlProfilerClient::HandlingSignal);
- QVERIFY2(m_client->traceMessages[19].detailData.endsWith("signalSourceLocation.qml"),
- m_client->traceMessages[19].detailData.toUtf8().constData());
- QCOMPARE(m_client->traceMessages[19].line, 7);
- QCOMPARE(m_client->traceMessages[19].column, 21);
-
- // must end with "EndTrace"
- QCOMPARE(m_client->traceMessages.last().messageType, (int)QQmlProfilerClient::Event);
- QCOMPARE(m_client->traceMessages.last().detailType, (int)QQmlProfilerClient::EndTrace);
+ checkTraceReceived();
+
+ QVERIFY2(m_client->synchronousMessages.count() >= 20,
+ QString::number(m_client->synchronousMessages.count()).toUtf8().constData());
+
+ QCOMPARE(m_client->synchronousMessages[14].messageType, (int)QQmlProfilerClient::RangeLocation);
+ QCOMPARE(m_client->synchronousMessages[14].detailType, (int)QQmlProfilerClient::HandlingSignal);
+ QVERIFY2(m_client->synchronousMessages[14].detailData.endsWith("signalSourceLocation.qml"),
+ m_client->synchronousMessages[14].detailData.toUtf8().constData());
+ QCOMPARE(m_client->synchronousMessages[14].line, 8);
+ QCOMPARE(m_client->synchronousMessages[14].column, 28);
+
+ QCOMPARE(m_client->synchronousMessages[19].messageType, (int)QQmlProfilerClient::RangeLocation);
+ QCOMPARE(m_client->synchronousMessages[19].detailType, (int)QQmlProfilerClient::HandlingSignal);
+ QVERIFY2(m_client->synchronousMessages[19].detailData.endsWith("signalSourceLocation.qml"),
+ m_client->synchronousMessages[19].detailData.toUtf8().constData());
+ QCOMPARE(m_client->synchronousMessages[19].line, 7);
+ QCOMPARE(m_client->synchronousMessages[19].column, 21);
}
void tst_QQmlProfilerService::javascript()
@@ -579,35 +562,28 @@ void tst_QQmlProfilerService::javascript()
while (!(m_process->output().contains(QLatin1String("done"))))
QVERIFY(QQmlDebugTest::waitForSignal(m_process, SIGNAL(readyReadStandardOutput())));
m_client->setTraceState(false);
- QVERIFY2(QQmlDebugTest::waitForSignal(m_client, SIGNAL(complete())), "No trace received in time.");
+ checkTraceReceived();
- QVERIFY2(m_client->traceMessages.count() >= 36,
- QString::number(m_client->traceMessages.count()).toUtf8().constData());
- // must start with "StartTrace"
- QCOMPARE(m_client->traceMessages.first().messageType, (int)QQmlProfilerClient::Event);
- QCOMPARE(m_client->traceMessages.first().detailType, (int)QQmlProfilerClient::StartTrace);
-
- QCOMPARE(m_client->traceMessages[32].messageType, (int)QQmlProfilerClient::RangeStart);
- QCOMPARE(m_client->traceMessages[32].detailType, (int)QQmlProfilerClient::Javascript);
+ QVERIFY2(m_client->synchronousMessages.count() >= 36,
+ QString::number(m_client->synchronousMessages.count()).toUtf8().constData());
- QCOMPARE(m_client->traceMessages[33].messageType, (int)QQmlProfilerClient::RangeLocation);
- QCOMPARE(m_client->traceMessages[33].detailType, (int)QQmlProfilerClient::Javascript);
- QVERIFY2(m_client->traceMessages[33].detailData.endsWith("javascript.qml"),
- m_client->traceMessages[33].detailData.toUtf8().constData());
- QCOMPARE(m_client->traceMessages[33].line, 4);
- QCOMPARE(m_client->traceMessages[33].column, 5);
+ QCOMPARE(m_client->synchronousMessages[32].messageType, (int)QQmlProfilerClient::RangeStart);
+ QCOMPARE(m_client->synchronousMessages[32].detailType, (int)QQmlProfilerClient::Javascript);
- QCOMPARE(m_client->traceMessages[34].messageType, (int)QQmlProfilerClient::RangeData);
- QCOMPARE(m_client->traceMessages[34].detailType, (int)QQmlProfilerClient::Javascript);
- QVERIFY2(m_client->traceMessages[34].detailData == "something",
- m_client->traceMessages[34].detailData.toUtf8().constData());
+ QCOMPARE(m_client->synchronousMessages[33].messageType, (int)QQmlProfilerClient::RangeLocation);
+ QCOMPARE(m_client->synchronousMessages[33].detailType, (int)QQmlProfilerClient::Javascript);
+ QVERIFY2(m_client->synchronousMessages[33].detailData.endsWith("javascript.qml"),
+ m_client->synchronousMessages[33].detailData.toUtf8().constData());
+ QCOMPARE(m_client->synchronousMessages[33].line, 4);
+ QCOMPARE(m_client->synchronousMessages[33].column, 5);
- QCOMPARE(m_client->traceMessages[35].messageType, (int)QQmlProfilerClient::RangeEnd);
- QCOMPARE(m_client->traceMessages[35].detailType, (int)QQmlProfilerClient::Javascript);
+ QCOMPARE(m_client->synchronousMessages[34].messageType, (int)QQmlProfilerClient::RangeData);
+ QCOMPARE(m_client->synchronousMessages[34].detailType, (int)QQmlProfilerClient::Javascript);
+ QVERIFY2(m_client->synchronousMessages[34].detailData == "something",
+ m_client->synchronousMessages[34].detailData.toUtf8().constData());
- // must end with "EndTrace"
- QCOMPARE(m_client->traceMessages.last().messageType, (int)QQmlProfilerClient::Event);
- QCOMPARE(m_client->traceMessages.last().detailType, (int)QQmlProfilerClient::EndTrace);
+ QCOMPARE(m_client->synchronousMessages[35].messageType, (int)QQmlProfilerClient::RangeEnd);
+ QCOMPARE(m_client->synchronousMessages[35].detailType, (int)QQmlProfilerClient::Javascript);
}
QTEST_MAIN(tst_QQmlProfilerService)
diff --git a/tests/auto/qml/qqmllanguage/data/idPropertyMismatch.qml b/tests/auto/qml/qqmllanguage/data/idPropertyMismatch.qml
new file mode 100644
index 0000000000..8c4fd65786
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/idPropertyMismatch.qml
@@ -0,0 +1,5 @@
+import QtQml 2.0
+QtObject {
+ property int id;
+ id: "root"
+}
diff --git a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
index be417df325..e77c15b79a 100644
--- a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
+++ b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
@@ -146,6 +146,7 @@ private slots:
void onCompleted();
void onDestruction();
void scriptString();
+ void scriptStringWithoutSourceCode();
void defaultPropertyListOrder();
void declaredPropertyValues();
void dontDoubleCallClassBegin();
@@ -1200,21 +1201,32 @@ void tst_qqmllanguage::inlineQmlComponents()
// Tests that types that have an id property have it set
void tst_qqmllanguage::idProperty()
{
- QQmlComponent component(&engine, testFileUrl("idProperty.qml"));
- VERIFY_ERRORS(0);
- MyContainer *object = qobject_cast<MyContainer *>(component.create());
- QVERIFY(object != 0);
- QCOMPARE(object->getChildren()->count(), 2);
- MyTypeObject *child =
- qobject_cast<MyTypeObject *>(object->getChildren()->at(0));
- QVERIFY(child != 0);
- QCOMPARE(child->id(), QString("myObjectId"));
- QCOMPARE(object->property("object"), QVariant::fromValue((QObject *)child));
+ {
+ QQmlComponent component(&engine, testFileUrl("idProperty.qml"));
+ VERIFY_ERRORS(0);
+ MyContainer *object = qobject_cast<MyContainer *>(component.create());
+ QVERIFY(object != 0);
+ QCOMPARE(object->getChildren()->count(), 2);
+ MyTypeObject *child =
+ qobject_cast<MyTypeObject *>(object->getChildren()->at(0));
+ QVERIFY(child != 0);
+ QCOMPARE(child->id(), QString("myObjectId"));
+ QCOMPARE(object->property("object"), QVariant::fromValue((QObject *)child));
- child =
- qobject_cast<MyTypeObject *>(object->getChildren()->at(1));
- QVERIFY(child != 0);
- QCOMPARE(child->id(), QString("name.with.dots"));
+ child =
+ qobject_cast<MyTypeObject *>(object->getChildren()->at(1));
+ QVERIFY(child != 0);
+ QCOMPARE(child->id(), QString("name.with.dots"));
+ }
+ {
+ QQmlComponent component(&engine, testFileUrl("idPropertyMismatch.qml"));
+ VERIFY_ERRORS(0);
+ QScopedPointer<QObject> root(component.create());
+ QVERIFY(!root.isNull());
+ QQmlContext *ctx = qmlContext(root.data());
+ QVERIFY(ctx);
+ QCOMPARE(ctx->nameForObject(root.data()), QString("root"));
+ }
}
// Tests automatic connection to notify signals if "onBlahChanged" syntax is used
@@ -1932,6 +1944,54 @@ void tst_qqmllanguage::scriptString()
}
}
+void tst_qqmllanguage::scriptStringWithoutSourceCode()
+{
+ QUrl url = testFileUrl("scriptString7.qml");
+ {
+ QQmlEnginePrivate *eng = QQmlEnginePrivate::get(&engine);
+ QQmlTypeData *td = eng->typeLoader.getType(url);
+ Q_ASSERT(td);
+
+ QV4::CompiledData::QmlUnit *qmlUnit = td->compiledData()->qmlUnit;
+ Q_ASSERT(qmlUnit);
+ const QV4::CompiledData::Object *rootObject = qmlUnit->objectAt(qmlUnit->indexOfRootObject);
+ QCOMPARE(qmlUnit->header.stringAt(rootObject->inheritedTypeNameIndex), QString("MyTypeObject"));
+ quint32 i;
+ for (i = 0; i < rootObject->nBindings; ++i) {
+ const QV4::CompiledData::Binding *binding = rootObject->bindingTable() + i;
+ if (qmlUnit->header.stringAt(binding->propertyNameIndex) != QString("scriptProperty"))
+ continue;
+ QCOMPARE(binding->valueAsScriptString(&qmlUnit->header), QString("intProperty"));
+ const_cast<QV4::CompiledData::Binding*>(binding)->stringIndex = 0; // empty string index
+ QVERIFY(binding->valueAsScriptString(&qmlUnit->header).isEmpty());
+ break;
+ }
+ QVERIFY(i < rootObject->nBindings);
+ }
+ QQmlComponent component(&engine, url);
+ VERIFY_ERRORS(0);
+
+ MyTypeObject *object = qobject_cast<MyTypeObject*>(component.create());
+ QVERIFY(object != 0);
+ QQmlScriptString ss = object->scriptProperty();
+ QVERIFY(!ss.isEmpty());
+ QCOMPARE(ss.stringLiteral(), QString());
+ bool ok;
+ QCOMPARE(ss.numberLiteral(&ok), qreal(0.));
+ QCOMPARE(ok, false);
+
+ const QQmlScriptStringPrivate *scriptPrivate = QQmlScriptStringPrivate::get(ss);
+ QVERIFY(scriptPrivate != 0);
+ QVERIFY(scriptPrivate->script.isEmpty());
+ QCOMPARE(scriptPrivate->scope, qobject_cast<QObject*>(object));
+ QCOMPARE(scriptPrivate->context, qmlContext(object));
+
+ {
+ QQmlExpression expr(ss, /*context*/0, object);
+ QCOMPARE(expr.evaluate().toInt(), int(100));
+ }
+}
+
// Check that default property assignments are correctly spliced into explicit
// property assignments
void tst_qqmllanguage::defaultPropertyListOrder()
diff --git a/tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp b/tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp
index 22404aa862..ede80b355a 100644
--- a/tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp
+++ b/tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp
@@ -132,6 +132,7 @@ private slots:
void empty_element_warning_data();
void datetime();
void datetime_data();
+ void about_to_be_signals();
};
bool tst_qqmllistmodel::compareVariantList(const QVariantList &testList, QVariant object)
@@ -1306,6 +1307,134 @@ void tst_qqmllistmodel::datetime()
QVERIFY(expected == dtResult);
}
+class RowTester : public QObject
+{
+ Q_OBJECT
+public:
+ RowTester(QAbstractItemModel *model) : QObject(model), model(model)
+ {
+ reset();
+ connect(model, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)), this, SLOT(rowsAboutToBeInserted()));
+ connect(model, SIGNAL(rowsInserted(QModelIndex,int,int)), this, SLOT(rowsInserted()));
+ connect(model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)), this, SLOT(rowsAboutToBeRemoved()));
+ connect(model, SIGNAL(rowsRemoved(QModelIndex,int,int)), this, SLOT(rowsRemoved()));
+ connect(model, SIGNAL(rowsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)), this, SLOT(rowsAboutToBeMoved()));
+ connect(model, SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int)), this, SLOT(rowsMoved()));
+ }
+
+ void reset()
+ {
+ rowsAboutToBeInsertedCalls = 0;
+ rowsAboutToBeInsertedCount = 0;
+ rowsInsertedCalls = 0;
+ rowsInsertedCount = 0;
+ rowsAboutToBeRemovedCalls = 0;
+ rowsAboutToBeRemovedCount = 0;
+ rowsRemovedCalls = 0;
+ rowsRemovedCount = 0;
+ rowsAboutToBeMovedCalls = 0;
+ rowsAboutToBeMovedData.clear();
+ rowsMovedCalls = 0;
+ rowsMovedData.clear();
+ }
+
+ int rowsAboutToBeInsertedCalls;
+ int rowsAboutToBeInsertedCount;
+ int rowsInsertedCalls;
+ int rowsInsertedCount;
+ int rowsAboutToBeRemovedCalls;
+ int rowsAboutToBeRemovedCount;
+ int rowsRemovedCalls;
+ int rowsRemovedCount;
+ int rowsAboutToBeMovedCalls;
+ QVariantList rowsAboutToBeMovedData;
+ int rowsMovedCalls;
+ QVariantList rowsMovedData;
+
+private slots:
+ void rowsAboutToBeInserted()
+ {
+ rowsAboutToBeInsertedCalls++;
+ rowsAboutToBeInsertedCount = model->rowCount();
+ }
+
+ void rowsInserted()
+ {
+ rowsInsertedCalls++;
+ rowsInsertedCount = model->rowCount();
+ }
+
+ void rowsAboutToBeRemoved()
+ {
+ rowsAboutToBeRemovedCalls++;
+ rowsAboutToBeRemovedCount = model->rowCount();
+ }
+
+ void rowsRemoved()
+ {
+ rowsRemovedCalls++;
+ rowsRemovedCount = model->rowCount();
+ }
+
+ void rowsAboutToBeMoved()
+ {
+ rowsAboutToBeMovedCalls++;
+ for (int i = 0; i < model->rowCount(); ++i)
+ rowsAboutToBeMovedData += model->data(model->index(i, 0), 0);
+ }
+
+ void rowsMoved()
+ {
+ rowsMovedCalls++;
+ for (int i = 0; i < model->rowCount(); ++i)
+ rowsMovedData += model->data(model->index(i, 0), 0);
+ }
+
+private:
+ QAbstractItemModel *model;
+};
+
+void tst_qqmllistmodel::about_to_be_signals()
+{
+ QQmlEngine engine;
+ QQmlListModel model;
+ QQmlEngine::setContextForObject(&model,engine.rootContext());
+
+ RowTester tester(&model);
+
+ QQmlExpression e1(engine.rootContext(), &model, "{append({'test':0})}");
+ e1.evaluate();
+
+ QCOMPARE(tester.rowsAboutToBeInsertedCalls, 1);
+ QCOMPARE(tester.rowsAboutToBeInsertedCount, 0);
+ QCOMPARE(tester.rowsInsertedCalls, 1);
+ QCOMPARE(tester.rowsInsertedCount, 1);
+
+ QQmlExpression e2(engine.rootContext(), &model, "{append({'test':1})}");
+ e2.evaluate();
+
+ QCOMPARE(tester.rowsAboutToBeInsertedCalls, 2);
+ QCOMPARE(tester.rowsAboutToBeInsertedCount, 1);
+ QCOMPARE(tester.rowsInsertedCalls, 2);
+ QCOMPARE(tester.rowsInsertedCount, 2);
+
+ QQmlExpression e3(engine.rootContext(), &model, "{move(0, 1, 1)}");
+ e3.evaluate();
+
+ QCOMPARE(tester.rowsAboutToBeMovedCalls, 1);
+ QCOMPARE(tester.rowsAboutToBeMovedData, QVariantList() << 0.0 << 1.0);
+ QCOMPARE(tester.rowsMovedCalls, 1);
+ QCOMPARE(tester.rowsMovedData, QVariantList() << 1.0 << 0.0);
+
+ QQmlExpression e4(engine.rootContext(), &model, "{remove(0, 2)}");
+ e4.evaluate();
+
+ QCOMPARE(tester.rowsAboutToBeRemovedCalls, 1);
+ QCOMPARE(tester.rowsAboutToBeRemovedCount, 2);
+ QCOMPARE(tester.rowsRemovedCalls, 1);
+ QCOMPARE(tester.rowsRemovedCount, 0);
+}
+
QTEST_MAIN(tst_qqmllistmodel)
#include "tst_qqmllistmodel.moc"
diff --git a/tests/auto/qmltest/textinput/tst_textinput.qml b/tests/auto/qmltest/textinput/tst_textinput.qml
index c359d53200..9a00ac8a60 100644
--- a/tests/auto/qmltest/textinput/tst_textinput.qml
+++ b/tests/auto/qmltest/textinput/tst_textinput.qml
@@ -75,6 +75,13 @@ Item {
TextInput {
id: txtfunctions
+ text: "The quick brown fox"
+ height: 20
+ width: 50
+ }
+
+ TextInput {
+ id: txtclipboard
text: "The quick brown fox jumped over the lazy dog"
height: 20
width: 50
@@ -143,31 +150,51 @@ Item {
compare(txtentry.text, "hello world")
}
- function test_functions() {
+ function test_select_insert() {
compare(txtfunctions.getText(4,9), "quick")
txtfunctions.select(4,9);
compare(txtfunctions.selectedText, "quick")
+ txtfunctions.insert(4, "very ")
+ compare(txtfunctions.text, "The very quick brown fox")
txtfunctions.deselect();
compare(txtfunctions.selectedText, "")
- txtfunctions.select(4,9);
- txtfunctions.cut();
- compare(txtfunctions.text, "The brown fox jumped over the lazy dog")
txtfunctions.text = "Qt";
txtfunctions.insert(txtfunctions.text.length, " ")
compare(txtfunctions.text, "Qt ");
- txtfunctions.cursorPosition = txtfunctions.text.length;
- txtfunctions.paste();
+ txtfunctions.insert(txtfunctions.text.length, "quick")
compare(txtfunctions.text, "Qt quick");
txtfunctions.cursorPosition = txtfunctions.text.length;
txtfunctions.selectWord();
compare(txtfunctions.selectedText, "quick")
- txtfunctions.copy();
txtfunctions.selectAll();
compare(txtfunctions.selectedText, "Qt quick")
txtfunctions.deselect();
compare(txtfunctions.selectedText, "")
- txtfunctions.paste();
- compare(txtfunctions.text, "Qt quickquick");
+ }
+
+ function test_clipboard() {
+ if (typeof(txtclipboard.copy) !== "function"
+ || typeof(txtclipboard.paste) !== "function"
+ || typeof(txtclipboard.cut) !== "function") {
+ skip("Clipboard is not supported on this platform.")
+ }
+ txtclipboard.select(4,10);
+ txtclipboard.cut();
+ compare(txtclipboard.text, "The brown fox jumped over the lazy dog")
+ txtclipboard.select(30,35)
+ txtclipboard.paste();
+ compare(txtclipboard.text, "The brown fox jumped over the quick dog")
+ txtclipboard.text = "Qt ";
+ txtclipboard.cursorPosition = txtclipboard.text.length;
+ txtclipboard.paste();
+ compare(txtclipboard.text, "Qt quick ");
+ txtclipboard.cursorPosition = txtclipboard.text.length-1;
+ txtclipboard.selectWord();
+ compare(txtclipboard.selectedText, "quick")
+ txtclipboard.copy();
+ txtclipboard.cursorPosition = txtclipboard.text.length;
+ txtclipboard.paste();
+ compare(txtclipboard.text, "Qt quick quick");
}
function test_intvalidators_data() {
diff --git a/tests/auto/quick/qquicktext/data/horizontalAlignment_RightToLeft.qml b/tests/auto/quick/qquicktext/data/horizontalAlignment_RightToLeft.qml
index 5ba4d35684..876d325d5a 100644
--- a/tests/auto/quick/qquicktext/data/horizontalAlignment_RightToLeft.qml
+++ b/tests/auto/quick/qquicktext/data/horizontalAlignment_RightToLeft.qml
@@ -9,7 +9,7 @@ Rectangle {
Rectangle {
anchors.centerIn: parent
- width: 180
+ width: parent.width
height: 20
color: "green"
diff --git a/tests/auto/quick/qquicktext/tst_qquicktext.cpp b/tests/auto/quick/qquicktext/tst_qquicktext.cpp
index 9ca7cafe3d..6167577b60 100644
--- a/tests/auto/quick/qquicktext/tst_qquicktext.cpp
+++ b/tests/auto/quick/qquicktext/tst_qquicktext.cpp
@@ -732,10 +732,15 @@ void tst_qquicktext::horizontalAlignment()
void tst_qquicktext::horizontalAlignment_RightToLeft()
{
+#if defined(Q_OS_BLACKBERRY)
+ QQuickWindow dummy; // On BlackBerry first window is always full screen,
+ dummy.showFullScreen(); // so make test window a second window.
+#endif
+
QQuickView *window = createView(testFile("horizontalAlignment_RightToLeft.qml"));
QQuickText *text = window->rootObject()->findChild<QQuickText*>("text");
QVERIFY(text != 0);
- window->show();
+ window->showNormal();
QQuickTextPrivate *textPrivate = QQuickTextPrivate::get(text);
QVERIFY(textPrivate != 0);
diff --git a/tools/tools.pro b/tools/tools.pro
index a1b48789b8..fffa4df5c0 100644
--- a/tools/tools.pro
+++ b/tools/tools.pro
@@ -12,7 +12,7 @@ qmlimportscanner.CONFIG = host_build
qmlprofiler \
qmlbundle
qtHaveModule(quick) {
- SUBDIRS += qmlscene qmlplugindump
+ !static: SUBDIRS += qmlscene qmlplugindump
qtHaveModule(widgets): SUBDIRS += qmleasing
}
qtHaveModule(qmltest): SUBDIRS += qmltestrunner