aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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