aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--examples/quick/scenegraph/d3d11underqml/d3d11squircle.cpp1
-rw-r--r--src/imports/folderlistmodel/qquickfolderlistmodel.cpp10
-rw-r--r--src/imports/folderlistmodel/qquickfolderlistmodel.h3
-rw-r--r--src/qml/Qt5QmlConfigExtras.cmake.in10
-rw-r--r--src/qml/doc/src/external-resources.qdoc4
-rw-r--r--src/qml/doc/src/javascript/hostenvironment.qdoc2
-rw-r--r--src/qml/jsruntime/qv4engine.cpp2
-rw-r--r--src/qml/jsruntime/qv4resolvedtypereference_p.h36
-rw-r--r--src/qml/qml/qqmlapplicationengine.cpp2
-rw-r--r--src/qml/qml/qqmlapplicationengine_p.h2
-rw-r--r--src/qml/qml/qqmltypedata.cpp9
-rw-r--r--src/qmldebug/qqmldebugconnection.cpp3
-rw-r--r--src/qmlmodels/qqmldelegatemodel.cpp18
-rw-r--r--src/qmlmodels/qqmldelegatemodel_p_p.h1
-rw-r--r--src/qmlmodels/qqmltableinstancemodel.cpp13
-rw-r--r--src/qmlmodels/qqmltableinstancemodel_p.h7
-rw-r--r--src/qmltest/qmldir2
-rw-r--r--src/qmltest/qmltest.pro14
-rw-r--r--src/qmltest/quicktest.cpp53
-rw-r--r--src/qmltest/quicktest_p.h113
-rw-r--r--src/qmltyperegistrar/qmltyperegistrar.cpp47
-rw-r--r--src/qmltyperegistrar/qmltypes.prf12
-rw-r--r--src/qmltyperegistrar/qmltypesclassdescription.cpp2
-rw-r--r--src/qmltyperegistrar/qmltypesclassdescription.h1
-rw-r--r--src/qmltyperegistrar/qmltypescreator.cpp2
-rw-r--r--src/quick/items/context2d/qquickcontext2d.cpp5
-rw-r--r--src/quick/items/qquickevents.cpp2
-rw-r--r--src/quick/items/qquickflickable.cpp3
-rw-r--r--src/quick/items/qquickitem.cpp11
-rw-r--r--src/quick/items/qquickmousearea.cpp6
-rw-r--r--src/quick/items/qquickmultipointtoucharea.cpp4
-rw-r--r--src/quick/items/qquickpincharea.cpp8
-rw-r--r--src/quick/items/qquickscreen_p.h2
-rw-r--r--src/quick/items/qquicktableview.cpp19
-rw-r--r--src/quick/items/qquickwindow.cpp3
-rw-r--r--src/quick/scenegraph/qsgdefaultrendercontext.cpp2
-rw-r--r--src/quick/util/qquickanimation.cpp20
-rw-r--r--src/quickwidgets/qquickwidget.cpp33
-rw-r--r--tests/auto/qml/qml.pro3
-rw-r--r--tests/auto/qml/qmlformat/data/FrontInline.formatted.qml3
-rw-r--r--tests/auto/qml/qmlformat/data/FrontInline.qml2
-rw-r--r--tests/auto/qml/qmlformat/data/IfBlocks.formatted.qml63
-rw-r--r--tests/auto/qml/qmlformat/data/IfBlocks.qml66
-rw-r--r--tests/auto/qml/qmlformat/tst_qmlformat.cpp59
-rw-r--r--tests/auto/qml/qmltyperegistrar/foreign/foreign.cpp43
-rw-r--r--tests/auto/qml/qmltyperegistrar/foreign/foreign.h52
-rw-r--r--tests/auto/qml/qmltyperegistrar/foreign/foreign.pro10
-rw-r--r--tests/auto/qml/qmltyperegistrar/hppheader.hpp64
-rw-r--r--tests/auto/qml/qmltyperegistrar/noextheader64
-rw-r--r--tests/auto/qml/qmltyperegistrar/qmltyperegistrar.pro4
-rw-r--r--tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.cpp61
-rw-r--r--tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.h56
-rw-r--r--tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.pro20
-rw-r--r--tests/auto/qml/qqmllanguage/data/arrayToContainer.qml2
-rw-r--r--tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp25
-rw-r--r--tests/auto/quick/qquickanimations/data/signalorder.qml27
-rw-r--r--tests/auto/quick/qquickanimations/qquickanimations.pro1
-rw-r--r--tests/auto/quick/qquickanimations/tst_qquickanimations.cpp52
-rw-r--r--tests/auto/quick/qquickcanvasitem/BLACKLIST10
-rw-r--r--tests/auto/quick/qquickcanvasitem/data/CanvasTestCase.qml5
-rw-r--r--tests/auto/quick/qquickcanvasitem/data/tst_arcto.qml8
-rw-r--r--tests/auto/quick/qquickcanvasitem/data/tst_canvas.qml25
-rw-r--r--tests/auto/quick/qquickcanvasitem/qquickcanvasitem.pro2
-rw-r--r--tests/auto/quick/qquickcanvasitem/tst_qquickcanvasitem.cpp2
-rw-r--r--tests/auto/quick/qquicklayouts/data/tst_rowlayout.qml6
-rw-r--r--tests/auto/quick/qquickmousearea/data/settingHiddenInPressUngrabs.qml36
-rw-r--r--tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp38
-rw-r--r--tests/auto/quickwidgets/qquickwidget/data/resizeOverlay.qml15
-rw-r--r--tests/auto/quickwidgets/qquickwidget/tst_qquickwidget.cpp70
-rw-r--r--tools/qmlformat/commentastvisitor.cpp12
-rw-r--r--tools/qmlformat/commentastvisitor.h5
-rw-r--r--tools/qmlformat/dumpastvisitor.cpp40
-rw-r--r--tools/qmlformat/main.cpp35
-rw-r--r--tools/qmllint/findunqualified.cpp41
-rw-r--r--tools/qmllint/findunqualified.h3
-rw-r--r--tools/qmllint/main.cpp24
76 files changed, 1329 insertions, 212 deletions
diff --git a/examples/quick/scenegraph/d3d11underqml/d3d11squircle.cpp b/examples/quick/scenegraph/d3d11underqml/d3d11squircle.cpp
index f05bf2f843..5737e419b0 100644
--- a/examples/quick/scenegraph/d3d11underqml/d3d11squircle.cpp
+++ b/examples/quick/scenegraph/d3d11underqml/d3d11squircle.cpp
@@ -49,6 +49,7 @@
****************************************************************************/
#include "d3d11squircle.h"
+#include <QtCore/QFile>
#include <QtCore/QRunnable>
#include <QtQuick/QQuickWindow>
diff --git a/src/imports/folderlistmodel/qquickfolderlistmodel.cpp b/src/imports/folderlistmodel/qquickfolderlistmodel.cpp
index 26c6d4032f..44f0a49d76 100644
--- a/src/imports/folderlistmodel/qquickfolderlistmodel.cpp
+++ b/src/imports/folderlistmodel/qquickfolderlistmodel.cpp
@@ -255,7 +255,8 @@ QString QQuickFolderListModelPrivate::resolvePath(const QUrl &path)
\list
\li \c fileName
\li \c filePath
- \li \c fileURL (since Qt 5.2)
+ \li \c fileURL (since Qt 5.2; deprecated since Qt 5.15)
+ \li \c fileUrl (since Qt 5.15)
\li \c fileBaseName
\li \c fileSuffix
\li \c fileSize
@@ -334,7 +335,8 @@ QQuickFolderListModel::QQuickFolderListModel(QObject *parent)
d->roleNames[FileLastModifiedRole] = "fileModified";
d->roleNames[FileLastReadRole] = "fileAccessed";
d->roleNames[FileIsDirRole] = "fileIsDir";
- d->roleNames[FileUrlRole] = "fileURL";
+ d->roleNames[FileUrlRole] = "fileUrl";
+ d->roleNames[FileURLRole] = "fileURL";
d->init();
}
@@ -377,6 +379,7 @@ QVariant QQuickFolderListModel::data(const QModelIndex &index, int role) const
rv = d->data.at(index.row()).isDir();
break;
case FileUrlRole:
+ case FileURLRole:
rv = QUrl::fromLocalFile(d->data.at(index.row()).filePath());
break;
default:
@@ -886,7 +889,8 @@ void QQuickFolderListModel::setSortCaseSensitive(bool on)
\list
\li \c fileName
\li \c filePath
- \li \c fileURL (since Qt 5.2)
+ \li \c fileURL (since Qt 5.2; deprecated since Qt 5.15)
+ \li \c fileUrl (since Qt 5.15)
\li \c fileBaseName
\li \c fileSuffix
\li \c fileSize
diff --git a/src/imports/folderlistmodel/qquickfolderlistmodel.h b/src/imports/folderlistmodel/qquickfolderlistmodel.h
index d7429efeda..e21a8d8f37 100644
--- a/src/imports/folderlistmodel/qquickfolderlistmodel.h
+++ b/src/imports/folderlistmodel/qquickfolderlistmodel.h
@@ -95,7 +95,8 @@ public:
FileLastModifiedRole = Qt::UserRole + 6,
FileLastReadRole = Qt::UserRole +7,
FileIsDirRole = Qt::UserRole + 8,
- FileUrlRole = Qt::UserRole + 9
+ FileUrlRole = Qt::UserRole + 9,
+ FileURLRole = Qt::UserRole + 10
};
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
diff --git a/src/qml/Qt5QmlConfigExtras.cmake.in b/src/qml/Qt5QmlConfigExtras.cmake.in
index 9ddb9885cd..4242143bca 100644
--- a/src/qml/Qt5QmlConfigExtras.cmake.in
+++ b/src/qml/Qt5QmlConfigExtras.cmake.in
@@ -1,5 +1,7 @@
-file(GLOB _qt5qml_other_plugins "${CMAKE_CURRENT_LIST_DIR}/Qt5Qml_*Factory.cmake")
+if(QT5_STRICT_PLUGIN_GLOB OR Qt5Qml_STRICT_PLUGIN_GLOB)
+ file(GLOB _qt5qml_other_plugins "${CMAKE_CURRENT_LIST_DIR}/Qt5Qml_*Factory.cmake")
-foreach(_other_plugin ${_qt5qml_other_plugins})
- include(${_other_plugin} OPTIONAL)
-endforeach()
+ foreach(_other_plugin ${_qt5qml_other_plugins})
+ include(${_other_plugin} OPTIONAL)
+ endforeach()
+endif()
diff --git a/src/qml/doc/src/external-resources.qdoc b/src/qml/doc/src/external-resources.qdoc
index 17ac7693bc..c11174db43 100644
--- a/src/qml/doc/src/external-resources.qdoc
+++ b/src/qml/doc/src/external-resources.qdoc
@@ -76,3 +76,7 @@
\externalpage https://fontawesome.com/
\title Font Awesome
*/
+/*!
+ \externalpage https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Nullish_coalescing_operator
+ \title Nullish Coalescing
+*/
diff --git a/src/qml/doc/src/javascript/hostenvironment.qdoc b/src/qml/doc/src/javascript/hostenvironment.qdoc
index c22c392b80..bc75f843fb 100644
--- a/src/qml/doc/src/javascript/hostenvironment.qdoc
+++ b/src/qml/doc/src/javascript/hostenvironment.qdoc
@@ -42,6 +42,8 @@ Like a browser or server-side JavaScript environment, the QML runtime implements
all of the built-in types and functions defined by the standard, such as Object, Array, and Math.
The QML runtime implements the 7th edition of the standard.
+Since Qt 5.15 \l{Nullish Coalescing} is also implemented in the QML runtime.
+
The standard ECMAScript built-ins are not explicitly documented in the QML documentation. For more
information on their use, please refer to the ECMA-262 7th edition standard or one of the many online
JavaScript reference and tutorial sites, such as the \l{W3Schools JavaScript Reference} (JavaScript Objects
diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp
index 55884aa42c..51e63f3608 100644
--- a/src/qml/jsruntime/qv4engine.cpp
+++ b/src/qml/jsruntime/qv4engine.cpp
@@ -1562,7 +1562,7 @@ static QVariant toVariant(QV4::ExecutionEngine *e, const QV4::Value &value, int
retn = QVariant(typeHint, temp);
QMetaType::destroy(typeHint, temp);
auto retnAsIterable = retn.value<QtMetaTypePrivate::QSequentialIterableImpl>();
- if (retnAsIterable._iteratorCapabilities & QtMetaTypePrivate::ContainerIsAppendable) {
+ if (retnAsIterable.containerCapabilities() & QtMetaTypePrivate::ContainerIsAppendable) {
auto const length = a->getLength();
QV4::ScopedValue arrayValue(scope);
for (qint64 i = 0; i < length; ++i) {
diff --git a/src/qml/jsruntime/qv4resolvedtypereference_p.h b/src/qml/jsruntime/qv4resolvedtypereference_p.h
index 88b77cf2a8..7e8bedad62 100644
--- a/src/qml/jsruntime/qv4resolvedtypereference_p.h
+++ b/src/qml/jsruntime/qv4resolvedtypereference_p.h
@@ -67,6 +67,11 @@ class ResolvedTypeReference
Q_DISABLE_COPY_MOVE(ResolvedTypeReference)
public:
ResolvedTypeReference() = default;
+ ~ResolvedTypeReference()
+ {
+ if (m_stronglyReferencesCompilationUnit && m_compilationUnit)
+ m_compilationUnit->release();
+ }
QQmlRefPointer<QQmlPropertyCache> propertyCache() const;
QQmlRefPointer<QQmlPropertyCache> createPropertyCache(QQmlEngine *);
@@ -80,7 +85,33 @@ public:
QQmlRefPointer<QV4::ExecutableCompilationUnit> compilationUnit() { return m_compilationUnit; }
void setCompilationUnit(QQmlRefPointer<QV4::ExecutableCompilationUnit> unit)
{
- m_compilationUnit = std::move(unit);
+ if (m_compilationUnit == unit.data())
+ return;
+ if (m_stronglyReferencesCompilationUnit) {
+ if (m_compilationUnit)
+ m_compilationUnit->release();
+ m_compilationUnit = unit.take();
+ } else {
+ m_compilationUnit = unit.data();
+ }
+ }
+
+ bool referencesCompilationUnit() const { return m_stronglyReferencesCompilationUnit; }
+ void setReferencesCompilationUnit(bool doReference)
+ {
+ if (doReference == m_stronglyReferencesCompilationUnit)
+ return;
+ m_stronglyReferencesCompilationUnit = doReference;
+ if (!m_compilationUnit)
+ return;
+ if (doReference) {
+ m_compilationUnit->addref();
+ } else if (m_compilationUnit->count() == 1) {
+ m_compilationUnit->release();
+ m_compilationUnit = nullptr;
+ } else {
+ m_compilationUnit->release();
+ }
}
QQmlRefPointer<QQmlPropertyCache> typePropertyCache() const { return m_typePropertyCache; }
@@ -98,12 +129,13 @@ public:
private:
QQmlType m_type;
QQmlRefPointer<QQmlPropertyCache> m_typePropertyCache;
- QQmlRefPointer<QV4::ExecutableCompilationUnit> m_compilationUnit;
+ QV4::ExecutableCompilationUnit *m_compilationUnit = nullptr;
QTypeRevision m_version = QTypeRevision::zero();
// Types such as QQmlPropertyMap can add properties dynamically at run-time and
// therefore cannot have a property cache installed when instantiated.
bool m_isFullyDynamicType = false;
+ bool m_stronglyReferencesCompilationUnit = true;
};
} // namespace QV4
diff --git a/src/qml/qml/qqmlapplicationengine.cpp b/src/qml/qml/qqmlapplicationengine.cpp
index 6fe8dc5227..a2976b59c3 100644
--- a/src/qml/qml/qqmlapplicationengine.cpp
+++ b/src/qml/qml/qqmlapplicationengine.cpp
@@ -107,8 +107,6 @@ void QQmlApplicationEnginePrivate::_q_loadTranslations()
activeTranslator.reset();
}
q->retranslate();
-#else
- Q_UNUSED(rootFile)
#endif
}
diff --git a/src/qml/qml/qqmlapplicationengine_p.h b/src/qml/qml/qqmlapplicationengine_p.h
index 70232b3d52..4568f7cfbb 100644
--- a/src/qml/qml/qqmlapplicationengine_p.h
+++ b/src/qml/qml/qqmlapplicationengine_p.h
@@ -76,8 +76,10 @@ public:
QVariantMap initialProperties;
QStringList extraFileSelectors;
QString translationsDirectory;
+#if QT_CONFIG(translation)
QScopedPointer<QTranslator> activeTranslator;
bool isInitialized = false;
+#endif
};
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmltypedata.cpp b/src/qml/qml/qqmltypedata.cpp
index b264528daa..fea0062242 100644
--- a/src/qml/qml/qqmltypedata.cpp
+++ b/src/qml/qml/qqmltypedata.cpp
@@ -300,7 +300,14 @@ void QQmlTypeData::setCompileUnit(const Container &container)
auto const root = container->objectAt(i);
for (auto it = root->inlineComponentsBegin(); it != root->inlineComponentsEnd(); ++it) {
auto *typeRef = m_compiledData->resolvedType(it->nameIndex);
- typeRef->setCompilationUnit(m_compiledData); // share compilation unit
+
+ // We don't want the type reference to keep a strong reference to the compilation unit
+ // here. The compilation unit owns the type reference, and having a strong reference
+ // would prevent the compilation unit from ever getting deleted. We can still be sure
+ // that the compilation unit outlives the type reference, due to ownership.
+ typeRef->setReferencesCompilationUnit(false);
+
+ typeRef->setCompilationUnit(m_compiledData); // share compilation unit
}
}
}
diff --git a/src/qmldebug/qqmldebugconnection.cpp b/src/qmldebug/qqmldebugconnection.cpp
index 9d495ce6e4..81b69d1216 100644
--- a/src/qmldebug/qqmldebugconnection.cpp
+++ b/src/qmldebug/qqmldebugconnection.cpp
@@ -416,8 +416,7 @@ public:
{
connect(parent, &QLocalSocket::stateChanged,
this, &LocalSocketSignalTranslator::onStateChanged);
- connect(parent, static_cast<void(QLocalSocket::*)(QLocalSocket::LocalSocketError)>(
- &QLocalSocket::errorOccurred), this, &LocalSocketSignalTranslator::onError);
+ connect(parent, &QLocalSocket::errorOccurred, this, &LocalSocketSignalTranslator::onError);
}
void onError(QLocalSocket::LocalSocketError error)
diff --git a/src/qmlmodels/qqmldelegatemodel.cpp b/src/qmlmodels/qqmldelegatemodel.cpp
index 646ac5e9f9..c94493dee8 100644
--- a/src/qmlmodels/qqmldelegatemodel.cpp
+++ b/src/qmlmodels/qqmldelegatemodel.cpp
@@ -926,17 +926,11 @@ void PropertyUpdater::doUpdate()
auto mo = sender->metaObject();
auto signalIndex = QObject::senderSignalIndex();
++updateCount;
- // start at 0 instead of propertyOffset to handle properties from parent hierarchy
- for (auto i = 0; i < mo->propertyCount() + mo->propertyOffset(); ++i) {
- auto property = mo->property(i);
- if (property.notifySignal().methodIndex() == signalIndex) {
- // we synchronize between required properties and model rolenames by name
- // that's why the QQmlProperty and the metaobject property must have the same name
- QQmlProperty qmlProp(parent(), QString::fromLatin1(property.name()));
- qmlProp.write(property.read(QObject::sender()));
- return;
- }
- }
+ auto property = mo->property(changeSignalIndexToPropertyIndex[signalIndex]);
+ // we synchronize between required properties and model rolenames by name
+ // that's why the QQmlProperty and the metaobject property must have the same name
+ QQmlProperty qmlProp(parent(), QString::fromLatin1(property.name()));
+ qmlProp.write(property.read(QObject::sender()));
}
void PropertyUpdater::breakBinding()
@@ -1014,8 +1008,10 @@ void QQDMIncubationTask::initializeRequiredProperties(QQmlDelegateModelItem *mod
QMetaMethod changeSignal = prop.notifySignal();
static QMetaMethod updateSlot = PropertyUpdater::staticMetaObject.method(
PropertyUpdater::staticMetaObject.indexOfSlot("doUpdate()"));
+
QMetaObject::Connection conn = QObject::connect(itemOrProxy, changeSignal,
updater, updateSlot);
+ updater->changeSignalIndexToPropertyIndex[changeSignal.methodIndex()] = i;
auto propIdx = object->metaObject()->indexOfProperty(propName.toUtf8());
QMetaMethod writeToPropSignal
= object->metaObject()->property(propIdx).notifySignal();
diff --git a/src/qmlmodels/qqmldelegatemodel_p_p.h b/src/qmlmodels/qqmldelegatemodel_p_p.h
index 20fb47f021..491e8025b8 100644
--- a/src/qmlmodels/qqmldelegatemodel_p_p.h
+++ b/src/qmlmodels/qqmldelegatemodel_p_p.h
@@ -475,6 +475,7 @@ class PropertyUpdater : public QObject
public:
PropertyUpdater(QObject *parent);
QHash<int, QMetaObject::Connection> senderToConnection;
+ QHash<int, int> changeSignalIndexToPropertyIndex;
int updateCount = 0;
public Q_SLOTS:
void doUpdate();
diff --git a/src/qmlmodels/qqmltableinstancemodel.cpp b/src/qmlmodels/qqmltableinstancemodel.cpp
index 4152cbe3ea..332a5447b1 100644
--- a/src/qmlmodels/qqmltableinstancemodel.cpp
+++ b/src/qmlmodels/qqmltableinstancemodel.cpp
@@ -232,14 +232,17 @@ QQmlInstanceModel::ReleaseFlags QQmlTableInstanceModel::release(QObject *object,
}
// The item is not reused or referenced by anyone, so just delete it
- destroyModelItem(modelItem);
+ destroyModelItem(modelItem, Deferred);
return QQmlInstanceModel::Destroyed;
}
-void QQmlTableInstanceModel::destroyModelItem(QQmlDelegateModelItem *modelItem)
+void QQmlTableInstanceModel::destroyModelItem(QQmlDelegateModelItem *modelItem, DestructionMode mode)
{
emit destroyingItem(modelItem->object);
- modelItem->destroyObject();
+ if (mode == Deferred)
+ modelItem->destroyObject();
+ else
+ delete modelItem->object;
delete modelItem;
}
@@ -284,7 +287,9 @@ void QQmlTableInstanceModel::cancel(int index)
void QQmlTableInstanceModel::drainReusableItemsPool(int maxPoolTime)
{
- m_reusableItemsPool.drain(maxPoolTime, [=](QQmlDelegateModelItem *modelItem){ destroyModelItem(modelItem); });
+ m_reusableItemsPool.drain(maxPoolTime, [this](QQmlDelegateModelItem *modelItem) {
+ destroyModelItem(modelItem, Immediate);
+ });
}
void QQmlTableInstanceModel::reuseItem(QQmlDelegateModelItem *item, int newModelIndex)
diff --git a/src/qmlmodels/qqmltableinstancemodel_p.h b/src/qmlmodels/qqmltableinstancemodel_p.h
index 57b9b26e43..defe513ef9 100644
--- a/src/qmlmodels/qqmltableinstancemodel_p.h
+++ b/src/qmlmodels/qqmltableinstancemodel_p.h
@@ -124,6 +124,11 @@ public:
int indexOf(QObject *, QObject *) const override { Q_UNREACHABLE(); return 0; }
private:
+ enum DestructionMode {
+ Deferred,
+ Immediate
+ };
+
QQmlComponent *resolveDelegate(int index);
QQmlAdaptorModel m_adaptorModel;
@@ -141,7 +146,7 @@ private:
void deleteIncubationTaskLater(QQmlIncubator *incubationTask);
void deleteAllFinishedIncubationTasks();
QQmlDelegateModelItem *resolveModelItem(int index);
- void destroyModelItem(QQmlDelegateModelItem *modelItem);
+ void destroyModelItem(QQmlDelegateModelItem *modelItem, DestructionMode mode);
void dataChangedCallback(const QModelIndex &begin, const QModelIndex &end, const QVector<int> &roles);
diff --git a/src/qmltest/qmldir b/src/qmltest/qmldir
new file mode 100644
index 0000000000..5e9d5e2c95
--- /dev/null
+++ b/src/qmltest/qmldir
@@ -0,0 +1,2 @@
+module Qt.test.qtestroot
+typeinfo plugins.qmltypes
diff --git a/src/qmltest/qmltest.pro b/src/qmltest/qmltest.pro
index 6864203ba4..c2e8068fc6 100644
--- a/src/qmltest/qmltest.pro
+++ b/src/qmltest/qmltest.pro
@@ -22,6 +22,7 @@ SOURCES += \
HEADERS += \
$$PWD/quicktestglobal.h \
$$PWD/quicktest.h \
+ $$PWD/quicktest_p.h \
$$PWD/quicktestresult_p.h \
$$PWD/qtestoptions_p.h
@@ -29,4 +30,15 @@ qtConfig(qml-debug): DEFINES += QT_QML_DEBUG_NO_WARNING
load(qt_module)
-CONFIG += metatypes install_metatypes
+QMLTYPES_FILENAME = plugins.qmltypes
+QMLTYPES_INSTALL_DIR = $$[QT_INSTALL_QML]/Qt/test/qtestroot
+QML_IMPORT_NAME = Qt.test.qtestroot
+QML_IMPORT_VERSION = 1.0
+CONFIG += qmltypes install_qmltypes install_metatypes
+
+# Install qmldir
+qmldir.files = $$PWD/qmldir
+qmldir.path = $$QMLTYPES_INSTALL_DIR
+
+prefix_build: INSTALLS += qmldir
+else: COPIES += qmldir
diff --git a/src/qmltest/quicktest.cpp b/src/qmltest/quicktest.cpp
index b2f54d978f..63e51fa4ba 100644
--- a/src/qmltest/quicktest.cpp
+++ b/src/qmltest/quicktest.cpp
@@ -37,7 +37,7 @@
**
****************************************************************************/
-#include "quicktest.h"
+#include "quicktest_p.h"
#include "quicktestresult_p.h"
#include <QtTest/qtestsystem.h>
#include "qtestoptions_p.h"
@@ -133,53 +133,6 @@ bool QQuickTest::qWaitForItemPolished(const QQuickItem *item, int timeout)
return QTest::qWaitFor([&]() { return !QQuickItemPrivate::get(item)->polishScheduled; }, timeout);
}
-class QTestRootObject : public QObject
-{
- Q_OBJECT
- Q_PROPERTY(bool windowShown READ windowShown NOTIFY windowShownChanged)
- Q_PROPERTY(bool hasTestCase READ hasTestCase WRITE setHasTestCase NOTIFY hasTestCaseChanged)
- Q_PROPERTY(QObject *defined READ defined)
-public:
- QTestRootObject(QObject *parent = nullptr)
- : QObject(parent), hasQuit(false), m_windowShown(false), m_hasTestCase(false) {
- m_defined = new QQmlPropertyMap(this);
-#if defined(QT_OPENGL_ES_2_ANGLE)
- m_defined->insert(QLatin1String("QT_OPENGL_ES_2_ANGLE"), QVariant(true));
-#endif
- }
-
- static QTestRootObject *instance() {
- static QPointer<QTestRootObject> object = new QTestRootObject;
- if (!object) {
- // QTestRootObject was deleted when previous test ended, create a new one
- object = new QTestRootObject;
- }
- return object;
- }
-
- bool hasQuit:1;
- bool hasTestCase() const { return m_hasTestCase; }
- void setHasTestCase(bool value) { m_hasTestCase = value; emit hasTestCaseChanged(); }
-
- bool windowShown() const { return m_windowShown; }
- void setWindowShown(bool value) { m_windowShown = value; emit windowShownChanged(); }
- QQmlPropertyMap *defined() const { return m_defined; }
-
- void init() { setWindowShown(false); setHasTestCase(false); hasQuit = false; }
-
-Q_SIGNALS:
- void windowShownChanged();
- void hasTestCaseChanged();
-
-private Q_SLOTS:
- void quit() { hasQuit = true; }
-
-private:
- bool m_windowShown : 1;
- bool m_hasTestCase :1;
- QQmlPropertyMap *m_defined;
-};
-
static QObject *testRootObject(QQmlEngine *engine, QJSEngine *jsEngine)
{
Q_UNUSED(engine);
@@ -556,7 +509,7 @@ int quick_test_main_with_setup(int argc, char **argv, const char *name, const ch
qputenv("QT_QTESTLIB_RUNNING", "1");
- // Register the test object
+ // Register the custom factory function
qmlRegisterSingletonType<QTestRootObject>("Qt.test.qtestroot", 1, 0, "QTestRootObject", testRootObject);
QSet<QString> commandLineTestFunctions(QTest::testFunctions.cbegin(), QTest::testFunctions.cend());
@@ -688,5 +641,3 @@ int quick_test_main_with_setup(int argc, char **argv, const char *name, const ch
}
QT_END_NAMESPACE
-
-#include "quicktest.moc"
diff --git a/src/qmltest/quicktest_p.h b/src/qmltest/quicktest_p.h
new file mode 100644
index 0000000000..50fc3be050
--- /dev/null
+++ b/src/qmltest/quicktest_p.h
@@ -0,0 +1,113 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QUICKTEST_P_H
+#define QUICKTEST_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtQuickTest/quicktest.h>
+
+#include <QtQml/qqmlpropertymap.h>
+#include <QtQml/qqml.h>
+
+QT_BEGIN_NAMESPACE
+
+class QTestRootObject : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(bool windowShown READ windowShown NOTIFY windowShownChanged)
+ Q_PROPERTY(bool hasTestCase READ hasTestCase WRITE setHasTestCase NOTIFY hasTestCaseChanged)
+ Q_PROPERTY(QObject *defined READ defined)
+ QML_SINGLETON
+ QML_ELEMENT
+
+public:
+ QTestRootObject(QObject *parent = nullptr)
+ : QObject(parent), hasQuit(false), m_windowShown(false), m_hasTestCase(false) {
+ m_defined = new QQmlPropertyMap(this);
+#if defined(QT_OPENGL_ES_2_ANGLE)
+ m_defined->insert(QLatin1String("QT_OPENGL_ES_2_ANGLE"), QVariant(true));
+#endif
+ }
+
+ static QTestRootObject *instance() {
+ static QPointer<QTestRootObject> object = new QTestRootObject;
+ if (!object) {
+ // QTestRootObject was deleted when previous test ended, create a new one
+ object = new QTestRootObject;
+ }
+ return object;
+ }
+
+ bool hasQuit:1;
+ bool hasTestCase() const { return m_hasTestCase; }
+ void setHasTestCase(bool value) { m_hasTestCase = value; emit hasTestCaseChanged(); }
+
+ bool windowShown() const { return m_windowShown; }
+ void setWindowShown(bool value) { m_windowShown = value; emit windowShownChanged(); }
+ QQmlPropertyMap *defined() const { return m_defined; }
+
+ void init() { setWindowShown(false); setHasTestCase(false); hasQuit = false; }
+
+Q_SIGNALS:
+ void windowShownChanged();
+ void hasTestCaseChanged();
+
+private Q_SLOTS:
+ void quit() { hasQuit = true; }
+
+private:
+ bool m_windowShown : 1;
+ bool m_hasTestCase :1;
+ QQmlPropertyMap *m_defined;
+};
+
+QT_END_NAMESPACE
+
+#endif // QUICKTEST_P_H
diff --git a/src/qmltyperegistrar/qmltyperegistrar.cpp b/src/qmltyperegistrar/qmltyperegistrar.cpp
index 33f1ebbbd5..e6b0ee8cd9 100644
--- a/src/qmltyperegistrar/qmltyperegistrar.cpp
+++ b/src/qmltyperegistrar/qmltyperegistrar.cpp
@@ -331,25 +331,37 @@ int main(int argc, char **argv)
}
}
+ const bool privateIncludes = parser.isSet(privateIncludesOption);
+ auto resolvedInclude = [&](const QString &include) {
+ return (privateIncludes && include.endsWith(QLatin1String("_p.h")))
+ ? QLatin1String("private/") + include
+ : include;
+ };
+
auto processMetaObject = [&](const QJsonObject &metaObject) {
+ const QString include = resolvedInclude(metaObject[QLatin1String("inputFile")].toString());
const QJsonArray classes = metaObject[QLatin1String("classes")].toArray();
for (const auto &cls : classes) {
QJsonObject classDef = cls.toObject();
+ classDef.insert(QLatin1String("inputFile"), include);
+
switch (qmlTypeRegistrationMode(classDef)) {
case NamespaceRegistration:
case GadgetRegistration:
case ObjectRegistration: {
- const QString include = metaObject[QLatin1String("inputFile")].toString();
- const bool declaredInHeader = include.endsWith(QLatin1String(".h"));
- if (declaredInHeader) {
- includes.append(include);
- classDef.insert(QLatin1String("registerable"), true);
- } else {
- fprintf(stderr, "Cannot generate QML type registration for class %s "
- "because it is not declared in a header.",
+ if (!include.endsWith(QLatin1String(".h"))
+ && !include.endsWith(QLatin1String(".hpp"))
+ && !include.endsWith(QLatin1String(".hxx"))
+ && include.contains(QLatin1Char('.'))) {
+ fprintf(stderr,
+ "Class %s is declared in %s, which appears not to be a header.\n"
+ "The compilation of its registration to QML may fail.\n",
qPrintable(classDef.value(QLatin1String("qualifiedClassName"))
- .toString()));
+ .toString()),
+ qPrintable(include));
}
+ includes.append(include);
+ classDef.insert(QLatin1String("registerable"), true);
types.append(classDef);
break;
@@ -395,13 +407,8 @@ int main(int argc, char **argv)
const auto newEnd = std::unique(includes.begin(), includes.end());
includes.erase(newEnd, includes.end());
- const bool privateIncludes = parser.isSet(privateIncludesOption);
- for (const QString &include : qAsConst(includes)) {
- if (privateIncludes && include.endsWith(QLatin1String("_p.h")))
- fprintf(output, "\n#include <private/%s>", qPrintable(include));
- else
- fprintf(output, "\n#include <%s>", qPrintable(include));
- }
+ for (const QString &include : qAsConst(includes))
+ fprintf(output, "\n#include <%s>", qPrintable(include));
fprintf(output, "\n\n");
@@ -463,9 +470,13 @@ int main(int argc, char **argv)
continue;
}
+ const QString include = metaObject[QLatin1String("inputFile")].toString();
const QJsonArray classes = metaObject[QLatin1String("classes")].toArray();
- for (const auto &cls : classes)
- foreignTypes.append(cls.toObject());
+ for (const auto &cls : classes) {
+ QJsonObject classDef = cls.toObject();
+ classDef.insert(QLatin1String("inputFile"), include);
+ foreignTypes.append(classDef);
+ }
}
}
}
diff --git a/src/qmltyperegistrar/qmltypes.prf b/src/qmltyperegistrar/qmltypes.prf
index fbb00dbe2d..0d5a6ded24 100644
--- a/src/qmltyperegistrar/qmltypes.prf
+++ b/src/qmltyperegistrar/qmltypes.prf
@@ -31,7 +31,7 @@ isEmpty(QML_IMPORT_MINOR_VERSION) {
isEmpty(QMLTYPES_FILENAME) {
plugin: QMLTYPES_FILENAME = plugins.qmltypes
- else: QMLTYPES_FILENAME = $${TEMPLATE}.qmltypes
+ else: QMLTYPES_FILENAME = $${TARGET}.qmltypes
}
qt_module_deps = $$replace(QT, -private$, '')
@@ -40,25 +40,25 @@ qt_module_deps = $$resolve_depends(qt_module_deps, "QT.", ".depends" ".run_depen
qt_module_deps = $$replace(qt_module_deps, _private$, '')
qt_module_deps = $$unique(qt_module_deps)
-foreign_types =
for(dep, qt_module_deps) {
METATYPES_FILENAME = $$lower($$eval(QT.$${dep}.module))_metatypes.json
INSTALLED_METATYPES = $$[QT_INSTALL_LIBS]/metatypes/$$METATYPES_FILENAME
isEmpty(MODULE_BASE_OUTDIR) {
- foreign_types += $$INSTALLED_METATYPES
+ QML_FOREIGN_METATYPES += $$INSTALLED_METATYPES
} else {
MODULE_BASE_METATYPES = $$MODULE_BASE_OUTDIR/lib/metatypes/$$METATYPES_FILENAME
- exists($$MODULE_BASE_METATYPES): foreign_types += $$MODULE_BASE_METATYPES
- else: foreign_types += $$INSTALLED_METATYPES
+ exists($$MODULE_BASE_METATYPES): QML_FOREIGN_METATYPES += $$MODULE_BASE_METATYPES
+ else: QML_FOREIGN_METATYPES += $$INSTALLED_METATYPES
}
}
+
QML_TYPEREGISTRAR_FLAGS = \
--generate-qmltypes=$$QMLTYPES_FILENAME \
--import-name=$$QML_IMPORT_NAME \
--major-version=$$QML_IMPORT_MAJOR_VERSION \
--minor-version=$$QML_IMPORT_MINOR_VERSION \
- --foreign-types=$$join(foreign_types, ',')
+ --foreign-types=$$join(QML_FOREIGN_METATYPES, ',')
DEPENDENCIESFILE = $$_PRO_FILE_PWD_/dependencies.json
exists($$DEPENDENCIESFILE): QML_TYPEREGISTRAR_FLAGS += --dependencies=$$DEPENDENCIESFILE
diff --git a/src/qmltyperegistrar/qmltypesclassdescription.cpp b/src/qmltyperegistrar/qmltypesclassdescription.cpp
index e21abd97bc..778d057240 100644
--- a/src/qmltyperegistrar/qmltypesclassdescription.cpp
+++ b/src/qmltyperegistrar/qmltypesclassdescription.cpp
@@ -63,6 +63,8 @@ void QmlTypesClassDescription::collect(const QJsonObject *classDef,
const QVector<QJsonObject> &foreign,
CollectMode mode, QTypeRevision defaultRevision)
{
+ if (file.isEmpty() && classDef->value(QLatin1String("registerable")).toBool())
+ file = classDef->value(QLatin1String("inputFile")).toString();
const auto classInfos = classDef->value(QLatin1String("classInfos")).toArray();
for (const QJsonValue &classInfo : classInfos) {
const QJsonObject obj = classInfo.toObject();
diff --git a/src/qmltyperegistrar/qmltypesclassdescription.h b/src/qmltyperegistrar/qmltypesclassdescription.h
index e4ae37a84e..abe68d42ed 100644
--- a/src/qmltyperegistrar/qmltypesclassdescription.h
+++ b/src/qmltyperegistrar/qmltypesclassdescription.h
@@ -38,6 +38,7 @@
struct QmlTypesClassDescription
{
const QJsonObject *resolvedClass = nullptr;
+ QString file;
QString elementName;
QString defaultProp;
QString superClass;
diff --git a/src/qmltyperegistrar/qmltypescreator.cpp b/src/qmltyperegistrar/qmltypescreator.cpp
index 3569bbe253..d1378d809d 100644
--- a/src/qmltyperegistrar/qmltypescreator.cpp
+++ b/src/qmltyperegistrar/qmltypescreator.cpp
@@ -46,6 +46,8 @@ static QString enquote(const QString &string)
void QmlTypesCreator::writeClassProperties(const QmlTypesClassDescription &collector)
{
+ if (!collector.file.isEmpty())
+ m_qml.writeScriptBinding(QLatin1String("file"), enquote(collector.file));
m_qml.writeScriptBinding(
QLatin1String("name"),
enquote(collector.resolvedClass->value(
diff --git a/src/quick/items/context2d/qquickcontext2d.cpp b/src/quick/items/context2d/qquickcontext2d.cpp
index 8361be7277..12a4ce32df 100644
--- a/src/quick/items/context2d/qquickcontext2d.cpp
+++ b/src/quick/items/context2d/qquickcontext2d.cpp
@@ -986,10 +986,11 @@ static QV4::ReturnedValue qt_create_image_data(qreal w, qreal h, QV4::ExecutionE
pixelData->setPrototypeOf(p);
if (image.isNull()) {
- *pixelData->d()->image = QImage(w, h, QImage::Format_ARGB32);
+ *pixelData->d()->image = QImage(qRound(w), qRound(h), QImage::Format_ARGB32);
pixelData->d()->image->fill(0x00000000);
} else {
- Q_ASSERT(image.width()== qRound(w * image.devicePixelRatioF()) && image.height() == qRound(h * image.devicePixelRatioF()));
+ // After qtbase 88e56d0932a3615231adf40d5ae033e742d72c33, the image size can be off by one.
+ Q_ASSERT(qAbs(image.width() - qRound(w * image.devicePixelRatioF())) <= 1 && qAbs(image.height() - qRound(h * image.devicePixelRatioF())) <= 1);
*pixelData->d()->image = image.format() == QImage::Format_ARGB32 ? image : image.convertToFormat(QImage::Format_ARGB32);
}
diff --git a/src/quick/items/qquickevents.cpp b/src/quick/items/qquickevents.cpp
index 9469a9a06c..22b8877b9f 100644
--- a/src/quick/items/qquickevents.cpp
+++ b/src/quick/items/qquickevents.cpp
@@ -2171,7 +2171,7 @@ QTouchEvent *QQuickPointerTouchEvent::touchEventForItem(QQuickItem *item, bool i
tpCopy.setPos(item->mapFromScene(tpCopy.scenePos()));
tpCopy.setLastPos(item->mapFromScene(tpCopy.lastScenePos()));
tpCopy.setStartPos(item->mapFromScene(tpCopy.startScenePos()));
- tpCopy.setRect(item->mapRectFromScene(tpCopy.sceneRect()));
+ tpCopy.setEllipseDiameters(tpCopy.ellipseDiameters());
tpCopy.setVelocity(transformMatrix.mapVector(tpCopy.velocity()).toVector2D());
touchPoints << tpCopy;
}
diff --git a/src/quick/items/qquickflickable.cpp b/src/quick/items/qquickflickable.cpp
index c7f641cf1f..c91a5ef92b 100644
--- a/src/quick/items/qquickflickable.cpp
+++ b/src/quick/items/qquickflickable.cpp
@@ -1897,6 +1897,9 @@ void QQuickFlickable::cancelFlick()
void QQuickFlickablePrivate::data_append(QQmlListProperty<QObject> *prop, QObject *o)
{
+ if (!prop || !prop->data)
+ return;
+
if (QQuickItem *i = qmlobject_cast<QQuickItem *>(o)) {
i->setParentItem(static_cast<QQuickFlickablePrivate*>(prop->data)->contentItem);
} else if (QQuickPointerHandler *pointerHandler = qmlobject_cast<QQuickPointerHandler *>(o)) {
diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp
index a1f8fd35d8..cb1d3e224e 100644
--- a/src/quick/items/qquickitem.cpp
+++ b/src/quick/items/qquickitem.cpp
@@ -3977,6 +3977,9 @@ void QQuickItem::focusOutEvent(QFocusEvent * /*event*/)
press events for an item. The event information is provided by the
\a event parameter.
+ In order to receive mouse press events, \l acceptedMouseButtons() must
+ return the relevant mouse button.
+
\input item.qdocinc accepting-events
*/
void QQuickItem::mousePressEvent(QMouseEvent *event)
@@ -3989,6 +3992,10 @@ void QQuickItem::mousePressEvent(QMouseEvent *event)
move events for an item. The event information is provided by the
\a event parameter.
+ In order to receive mouse movement events, the preceding mouse press event
+ must be accepted (by overriding \l mousePressEvent(), for example) and
+ \l acceptedMouseButtons() must return the relevant mouse button.
+
\input item.qdocinc accepting-events
*/
void QQuickItem::mouseMoveEvent(QMouseEvent *event)
@@ -4001,6 +4008,10 @@ void QQuickItem::mouseMoveEvent(QMouseEvent *event)
release events for an item. The event information is provided by the
\a event parameter.
+ In order to receive mouse release events, the preceding mouse press event
+ must be accepted (by overriding \l mousePressEvent(), for example) and
+ \l acceptedMouseButtons() must return the relevant mouse button.
+
\input item.qdocinc accepting-events
*/
void QQuickItem::mouseReleaseEvent(QMouseEvent *event)
diff --git a/src/quick/items/qquickmousearea.cpp b/src/quick/items/qquickmousearea.cpp
index fd2458494c..f54858e4eb 100644
--- a/src/quick/items/qquickmousearea.cpp
+++ b/src/quick/items/qquickmousearea.cpp
@@ -1063,6 +1063,12 @@ void QQuickMouseArea::itemChange(ItemChange change, const ItemChangeData &value)
}
setHovered(!d->hovered);
}
+ if (d->pressed && (!isVisible())) {
+ // This happens when the mouse area sets itself disabled or hidden
+ // inside the press handler. In that case we should not keep the internal
+ // state as pressed, since we never became the mouse grabber.
+ ungrabMouse();
+ }
break;
default:
break;
diff --git a/src/quick/items/qquickmultipointtoucharea.cpp b/src/quick/items/qquickmultipointtoucharea.cpp
index a854d97f7e..383718c979 100644
--- a/src/quick/items/qquickmultipointtoucharea.cpp
+++ b/src/quick/items/qquickmultipointtoucharea.cpp
@@ -789,7 +789,9 @@ void QQuickMultiPointTouchArea::updateTouchPoint(QQuickTouchPoint *dtp, const QT
dtp->setPressure(p->pressure());
dtp->setRotation(p->rotation());
dtp->setVelocity(p->velocity());
- dtp->setArea(p->rect());
+ QRectF area(QPointF(), p->ellipseDiameters());
+ area.moveCenter(p->pos());
+ dtp->setArea(area);
dtp->setStartX(p->startPos().x());
dtp->setStartY(p->startPos().y());
dtp->setPreviousX(p->lastPos().x());
diff --git a/src/quick/items/qquickpincharea.cpp b/src/quick/items/qquickpincharea.cpp
index f963bdf74f..0692a1da42 100644
--- a/src/quick/items/qquickpincharea.cpp
+++ b/src/quick/items/qquickpincharea.cpp
@@ -194,7 +194,7 @@ QQuickPinchAreaPrivate::~QQuickPinchAreaPrivate()
*/
/*!
- \qmlsignal QtQuick::PinchArea::pinchStarted()
+ \qmlsignal QtQuick::PinchArea::pinchStarted(PinchEvent pinch)
This signal is emitted when the pinch area detects that a pinch gesture has
started: two touch points (fingers) have been detected, and they have moved
@@ -213,7 +213,7 @@ QQuickPinchAreaPrivate::~QQuickPinchAreaPrivate()
*/
/*!
- \qmlsignal QtQuick::PinchArea::pinchUpdated()
+ \qmlsignal QtQuick::PinchArea::pinchUpdated(PinchEvent pinch)
This signal is emitted when the pinch area detects that a pinch gesture has changed.
@@ -225,7 +225,7 @@ QQuickPinchAreaPrivate::~QQuickPinchAreaPrivate()
*/
/*!
- \qmlsignal QtQuick::PinchArea::pinchFinished()
+ \qmlsignal QtQuick::PinchArea::pinchFinished(PinchEvent pinch)
This signal is emitted when the pinch area detects that a pinch gesture has finished.
@@ -235,7 +235,7 @@ QQuickPinchAreaPrivate::~QQuickPinchAreaPrivate()
*/
/*!
- \qmlsignal QtQuick::PinchArea::smartZoom()
+ \qmlsignal QtQuick::PinchArea::smartZoom(PinchEvent pinch)
\since 5.5
This signal is emitted when the pinch area detects the smart zoom gesture.
diff --git a/src/quick/items/qquickscreen_p.h b/src/quick/items/qquickscreen_p.h
index dc1c820309..eade79e683 100644
--- a/src/quick/items/qquickscreen_p.h
+++ b/src/quick/items/qquickscreen_p.h
@@ -78,9 +78,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickScreenInfo : public QObject
Q_PROPERTY(qreal logicalPixelDensity READ logicalPixelDensity NOTIFY logicalPixelDensityChanged)
Q_PROPERTY(qreal pixelDensity READ pixelDensity NOTIFY pixelDensityChanged)
Q_PROPERTY(qreal devicePixelRatio READ devicePixelRatio NOTIFY devicePixelRatioChanged)
- // TODO Qt 6 Rename primaryOrientation to orientation
Q_PROPERTY(Qt::ScreenOrientation primaryOrientation READ primaryOrientation NOTIFY primaryOrientationChanged)
- // TODO Qt 6 Remove this orientation -> incomplete device orientation -> better use OrientationSensor
Q_PROPERTY(Qt::ScreenOrientation orientation READ orientation NOTIFY orientationChanged)
Q_PROPERTY(int virtualX READ virtualX NOTIFY virtualXChanged REVISION(2, 3))
diff --git a/src/quick/items/qquicktableview.cpp b/src/quick/items/qquicktableview.cpp
index 3548d20706..5adfd20bf0 100644
--- a/src/quick/items/qquicktableview.cpp
+++ b/src/quick/items/qquicktableview.cpp
@@ -1,4 +1,4 @@
-/****************************************************************************
+/****************************************************************************
**
** Copyright (C) 2018 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
@@ -193,8 +193,10 @@
\qmlproperty int QtQuick::TableView::rows
\readonly
- This property holds the number of rows in the table. This is
- equal to the number of rows in the model.
+ This property holds the number of rows in the table.
+
+ \note \a rows is usually equal to the number of rows in the model, but can
+ temporarily differ until all pending model changes have been processed.
This property is read only.
*/
@@ -203,9 +205,12 @@
\qmlproperty int QtQuick::TableView::columns
\readonly
- This property holds the number of columns in the table. This is
- equal to the number of columns in the model. If the model is
- a list, columns will be \c 1.
+ This property holds the number of rows in the table.
+
+ \note \a columns is usually equal to the number of columns in the model, but
+ can temporarily differ until all pending model changes have been processed.
+
+ If the model is a list, columns will be \c 1.
This property is read only.
*/
@@ -549,6 +554,8 @@ QQuickTableViewPrivate::~QQuickTableViewPrivate()
QString QQuickTableViewPrivate::tableLayoutToString() const
{
+ if (loadedItems.isEmpty())
+ return QLatin1String("table is empty!");
return QString(QLatin1String("table cells: (%1,%2) -> (%3,%4), item count: %5, table rect: %6,%7 x %8,%9"))
.arg(leftColumn()).arg(topRow())
.arg(rightColumn()).arg(bottomRow())
diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp
index acf6fd68c8..4874af44ed 100644
--- a/src/quick/items/qquickwindow.cpp
+++ b/src/quick/items/qquickwindow.cpp
@@ -976,8 +976,7 @@ void QQuickWindowPrivate::translateTouchEvent(QTouchEvent *touchEvent)
QList<QTouchEvent::TouchPoint> touchPoints = touchEvent->touchPoints();
for (int i = 0; i < touchPoints.count(); ++i) {
QTouchEvent::TouchPoint &touchPoint = touchPoints[i];
-
- touchPoint.setSceneRect(touchPoint.rect());
+ touchPoint.setScenePos(touchPoint.pos());
touchPoint.setStartScenePos(touchPoint.startPos());
touchPoint.setLastScenePos(touchPoint.lastPos());
}
diff --git a/src/quick/scenegraph/qsgdefaultrendercontext.cpp b/src/quick/scenegraph/qsgdefaultrendercontext.cpp
index 14314b2c94..ed2f8c313f 100644
--- a/src/quick/scenegraph/qsgdefaultrendercontext.cpp
+++ b/src/quick/scenegraph/qsgdefaultrendercontext.cpp
@@ -242,8 +242,6 @@ void QSGDefaultRenderContext::beginNextRhiFrame(QSGRenderer *renderer, QRhiRende
RenderPassCallback mainPassRecordingEnd,
void *callbackUserData)
{
- Q_ASSERT(!m_currentFrameCommandBuffer);
-
renderer->setRenderTarget(rt);
renderer->setRenderPassDescriptor(rp);
renderer->setCommandBuffer(cb);
diff --git a/src/quick/util/qquickanimation.cpp b/src/quick/util/qquickanimation.cpp
index 90c725a67f..e5e25d141b 100644
--- a/src/quick/util/qquickanimation.cpp
+++ b/src/quick/util/qquickanimation.cpp
@@ -176,11 +176,8 @@ void QQuickAbstractAnimationPrivate::commence()
animationInstance = new QQuickAnimatorProxyJob(animationInstance, q);
animationInstance->addAnimationChangeListener(this, QAbstractAnimationJob::Completion);
}
+ emit q->started();
animationInstance->start();
- if (animationInstance->isStopped()) {
- running = false;
- emit q->stopped();
- }
}
}
@@ -287,10 +284,8 @@ void QQuickAbstractAnimation::setRunning(bool r)
d->animationInstance->setLoopCount(d->animationInstance->currentLoop() + d->loopCount);
supressStart = true; //we want the animation to continue, rather than restart
}
- if (!supressStart) {
+ if (!supressStart)
d->commence();
- emit started();
- }
} else {
if (d->paused) {
d->paused = false; //reset paused state to false when stopped
@@ -308,7 +303,16 @@ void QQuickAbstractAnimation::setRunning(bool r)
}
}
- emit runningChanged(d->running);
+
+ if (r == d->running) {
+ // This might happen if we start an animation with 0 duration: This will result in that
+ // commence() will emit started(), and then when it starts it will call setCurrentTime(0),
+ // (which is both start and end time of the animation), so it will also end up calling
+ // setRunning(false) (recursively) and stop the animation.
+ // Therefore, the state of d->running will in that case be different than r if we are back in
+ // the root stack frame of the recursive calls to setRunning()
+ emit runningChanged(d->running);
+ }
}
/*!
diff --git a/src/quickwidgets/qquickwidget.cpp b/src/quickwidgets/qquickwidget.cpp
index db7ae22767..59d4a89fbf 100644
--- a/src/quickwidgets/qquickwidget.cpp
+++ b/src/quickwidgets/qquickwidget.cpp
@@ -109,6 +109,7 @@ void QQuickWidgetPrivate::init(QQmlEngine* e)
renderControl = new QQuickWidgetRenderControl(q);
offscreenWindow = new QQuickWindow(*new QQuickOffcreenWindowPrivate(),renderControl);
offscreenWindow->setTitle(QString::fromLatin1("Offscreen"));
+ offscreenWindow->setObjectName(QString::fromLatin1("QQuickOffScreenWindow"));
// Do not call create() on offscreenWindow.
// Check if the Software Adaptation is being used
@@ -804,15 +805,29 @@ void QQuickWidgetPrivate::updateSize()
q->updateGeometry();
}
} else if (resizeMode == QQuickWidget::SizeRootObjectToView) {
- bool needToUpdateWidth = !qFuzzyCompare(q->width(), root->width());
- bool needToUpdateHeight = !qFuzzyCompare(q->height(), root->height());
-
- if (needToUpdateWidth && needToUpdateHeight)
- root->setSize(QSizeF(q->width(), q->height()));
- else if (needToUpdateWidth)
- root->setWidth(q->width());
- else if (needToUpdateHeight)
- root->setHeight(q->height());
+ const bool needToUpdateWidth = !qFuzzyCompare(q->width(), root->width());
+ const bool needToUpdateHeight = !qFuzzyCompare(q->height(), root->height());
+
+ if (needToUpdateWidth && needToUpdateHeight) {
+ // Make sure that we have realistic sizing behavior by following
+ // what on-screen windows would do and resize everything, not just
+ // the root item. We do this because other types may be relying on
+ // us to behave correctly.
+ const QSizeF newSize(q->width(), q->height());
+ offscreenWindow->resize(newSize.toSize());
+ offscreenWindow->contentItem()->setSize(newSize);
+ root->setSize(newSize);
+ } else if (needToUpdateWidth) {
+ const int newWidth = q->width();
+ offscreenWindow->setWidth(newWidth);
+ offscreenWindow->contentItem()->setWidth(newWidth);
+ root->setWidth(newWidth);
+ } else if (needToUpdateHeight) {
+ const int newHeight = q->height();
+ offscreenWindow->setHeight(newHeight);
+ offscreenWindow->contentItem()->setHeight(newHeight);
+ root->setHeight(newHeight);
+ }
}
}
diff --git a/tests/auto/qml/qml.pro b/tests/auto/qml/qml.pro
index 418d3d4cb5..bc90d6df03 100644
--- a/tests/auto/qml/qml.pro
+++ b/tests/auto/qml/qml.pro
@@ -104,3 +104,6 @@ qtConfig(private_tests): \
qtNomakeTools( \
qmlplugindump \
)
+
+!cross_compile: \
+ SUBDIRS += qmltyperegistrar
diff --git a/tests/auto/qml/qmlformat/data/FrontInline.formatted.qml b/tests/auto/qml/qmlformat/data/FrontInline.formatted.qml
new file mode 100644
index 0000000000..620fbf4120
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/FrontInline.formatted.qml
@@ -0,0 +1,3 @@
+// This comment should be directly above Item after formatting
+Item {
+}
diff --git a/tests/auto/qml/qmlformat/data/FrontInline.qml b/tests/auto/qml/qmlformat/data/FrontInline.qml
new file mode 100644
index 0000000000..c63265481c
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/FrontInline.qml
@@ -0,0 +1,2 @@
+Item { // This comment should be directly above Item after formatting
+}
diff --git a/tests/auto/qml/qmlformat/data/IfBlocks.formatted.qml b/tests/auto/qml/qmlformat/data/IfBlocks.formatted.qml
new file mode 100644
index 0000000000..b8e77ec23a
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/IfBlocks.formatted.qml
@@ -0,0 +1,63 @@
+Item {
+
+ function test() {
+ //// The following if blocks should NOT HAVE braces
+ // Single branch, no braces
+ if (true)
+ console.log("foo");
+
+ // Single branch, no braces
+ if (true)
+ console.log("foo");
+
+ // Multiple branches, No braces
+ if (true)
+ console.log("foo");
+ else if (false)
+ console.log("bar");
+ else
+ console.log("baz");
+ // Multiple branches, all braces
+ if (true)
+ console.log("foo");
+ else if (false)
+ console.log("bar");
+ else
+ console.log("baz");
+
+ //// The following if blocks should HAVE braces
+ // Single branch, braces
+ if (true) {
+ console.log("foo");
+ console.log("bar");
+ }
+ // Multiple branches, some braces
+ if (true) {
+ console.log("foo");
+ console.log("foo2");
+ } else if (false) {
+ console.log("bar");
+ } else {
+ console.log("baz");
+ }
+ // Multiple branches, some braces
+ if (true) {
+ console.log("foo");
+ } else if (false) {
+ console.log("bar");
+ console.log("bar2");
+ } else {
+ console.log("baz");
+ }
+ // Multiple branches, some braces
+ if (true) {
+ console.log("foo");
+ } else if (false) {
+ console.log("bar");
+ } else {
+ console.log("baz");
+ console.log("baz2");
+ }
+ }
+
+}
diff --git a/tests/auto/qml/qmlformat/data/IfBlocks.qml b/tests/auto/qml/qmlformat/data/IfBlocks.qml
new file mode 100644
index 0000000000..505988b238
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/IfBlocks.qml
@@ -0,0 +1,66 @@
+Item {
+ function test() {
+ //// The following if blocks should NOT HAVE braces
+ // Single branch, no braces
+ if (true)
+ console.log("foo");
+
+ // Single branch, no braces
+ if (true) {
+ console.log("foo");
+ }
+
+
+ // Multiple branches, No braces
+ if (true)
+ console.log("foo");
+ else if (false)
+ console.log("bar");
+ else
+ console.log("baz");
+
+ // Multiple branches, all braces
+ if (true) {
+ console.log("foo");
+ } else if (false) {
+ console.log("bar");
+ } else {
+ console.log("baz");
+ }
+
+ //// The following if blocks should HAVE braces
+ // Single branch, braces
+ if (true) {
+ console.log("foo");
+ console.log("bar");
+ }
+
+ // Multiple branches, some braces
+ if (true) {
+ console.log("foo");
+ console.log("foo2");
+ } else if (false)
+ console.log("bar");
+ else
+ console.log("baz");
+
+ // Multiple branches, some braces
+ if (true)
+ console.log("foo");
+ else if (false) {
+ console.log("bar");
+ console.log("bar2");
+ } else
+ console.log("baz");
+
+ // Multiple branches, some braces
+ if (true)
+ console.log("foo");
+ else if (false)
+ console.log("bar");
+ else {
+ console.log("baz");
+ console.log("baz2");
+ }
+ }
+}
diff --git a/tests/auto/qml/qmlformat/tst_qmlformat.cpp b/tests/auto/qml/qmlformat/tst_qmlformat.cpp
index 21d5ae46a9..997a5cc753 100644
--- a/tests/auto/qml/qmlformat/tst_qmlformat.cpp
+++ b/tests/auto/qml/qmlformat/tst_qmlformat.cpp
@@ -27,8 +27,11 @@
****************************************************************************/
#include <QtTest/QtTest>
+#include <QDir>
+#include <QFile>
#include <QProcess>
#include <QString>
+#include <QTemporaryDir>
#include <util.h>
@@ -43,6 +46,9 @@ private Q_SLOTS:
void testFormatNoSort();
void testAnnotations();
void testAnnotationsNoSort();
+ void testLineEndings();
+ void testFrontInline();
+ void testIfBlocks();
void testReadOnlyProps();
void testStatesAndTransitions();
@@ -55,7 +61,7 @@ private Q_SLOTS:
private:
QString readTestFile(const QString &path);
- QString runQmlformat(const QString &fileToFormat, bool sortImports, bool shouldSucceed);
+ QString runQmlformat(const QString &fileToFormat, bool sortImports, bool shouldSucceed, const QString &newlineFormat = "native");
QString m_qmlformatPath;
QStringList m_excludedDirs;
@@ -113,6 +119,7 @@ void TestQmlformat::initTestCase()
m_invalidFiles << "tests/auto/qml/qqmlecmascript/data/numberParsing_error.1.qml";
m_invalidFiles << "tests/auto/qml/qqmlecmascript/data/numberParsing_error.2.qml";
m_invalidFiles << "tests/auto/qml/qqmlecmascript/data/incrDecrSemicolon_error1.qml";
+ m_invalidFiles << "tests/auto/qml/qqmlecmascript/data/incrDecrSemicolon_error1.qml";
m_invalidFiles << "tests/auto/qml/debugger/qqmlpreview/data/broken.qml";
m_invalidFiles << "tests/auto/qml/qqmllanguage/data/fuzzed.2.qml";
m_invalidFiles << "tests/auto/qml/qqmllanguage/data/fuzzed.3.qml";
@@ -197,6 +204,16 @@ void TestQmlformat::testAnnotationsNoSort()
QCOMPARE(runQmlformat(testFile("Annotations.qml"), false, true), readTestFile("Annotations.formatted.nosort.qml"));
}
+void TestQmlformat::testFrontInline()
+{
+ QCOMPARE(runQmlformat(testFile("FrontInline.qml"), false, true), readTestFile("FrontInline.formatted.qml"));
+}
+
+void TestQmlformat::testIfBlocks()
+{
+ QCOMPARE(runQmlformat(testFile("IfBlocks.qml"), false, true), readTestFile("IfBlocks.formatted.qml"));
+}
+
void TestQmlformat::testReadOnlyProps()
{
QCOMPARE(runQmlformat(testFile("readOnlyProps.qml"), false, true), readTestFile("readOnlyProps.formatted.qml"));
@@ -212,6 +229,23 @@ void TestQmlformat::testLargeBindings()
QCOMPARE(runQmlformat(testFile("largeBindings.qml"), false, true), readTestFile("largeBindings.formatted.qml"));
}
+void TestQmlformat::testLineEndings()
+{
+ // macos
+ const QString macosContents = runQmlformat(testFile("Example1.formatted.qml"), false, true, "macos");
+ QVERIFY(!macosContents.contains("\n"));
+ QVERIFY(macosContents.contains("\r"));
+
+ // windows
+ const QString windowsContents = runQmlformat(testFile("Example1.formatted.qml"), false, true, "windows");
+ QVERIFY(windowsContents.contains("\r\n"));
+
+ // unix
+ const QString unixContents = runQmlformat(testFile("Example1.formatted.qml"), false, true, "unix");
+ QVERIFY(unixContents.contains("\n"));
+ QVERIFY(!unixContents.contains("\r"));
+}
+
#if !defined(QTEST_CROSS_COMPILED) // sources not available when cross compiled
void TestQmlformat::testExample_data()
{
@@ -240,15 +274,22 @@ void TestQmlformat::testExample()
}
#endif
-QString TestQmlformat::runQmlformat(const QString &fileToFormat, bool sortImports, bool shouldSucceed)
+QString TestQmlformat::runQmlformat(const QString &fileToFormat, bool sortImports, bool shouldSucceed, const QString &newlineFormat)
{
+ // Copy test file to temporary location
+ QTemporaryDir tempDir;
+ const QString tempFile = tempDir.path() + QDir::separator() + "to_format.qml";
+ QFile::copy(fileToFormat, tempFile);
+
QStringList args;
- args << fileToFormat;
+ args << "-i";
+ args << tempFile;
if (!sortImports)
args << "-n";
- QString output;
+ args << "-l" << newlineFormat;
+
auto verify = [&]() {
QProcess process;
process.start(m_qmlformatPath, args);
@@ -256,13 +297,15 @@ QString TestQmlformat::runQmlformat(const QString &fileToFormat, bool sortImport
QCOMPARE(process.exitStatus(), QProcess::NormalExit);
if (shouldSucceed)
QCOMPARE(process.exitCode(), 0);
- else
- QVERIFY(process.exitCode() != 0);
- output = process.readAllStandardOutput();
};
verify();
- return output;
+ QFile temp(tempFile);
+
+ temp.open(QIODevice::ReadOnly);
+ QString formatted = QString::fromUtf8(temp.readAll());
+
+ return formatted;
}
QTEST_MAIN(TestQmlformat)
diff --git a/tests/auto/qml/qmltyperegistrar/foreign/foreign.cpp b/tests/auto/qml/qmltyperegistrar/foreign/foreign.cpp
new file mode 100644
index 0000000000..db080a5cad
--- /dev/null
+++ b/tests/auto/qml/qmltyperegistrar/foreign/foreign.cpp
@@ -0,0 +1,43 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "foreign.h"
+
+int Foreign::things() const
+{
+ return m_things;
+}
+
+void Foreign::setThings(int things)
+{
+ if (m_things == things)
+ return;
+
+ m_things = things;
+ emit thingsChanged(m_things);
+}
diff --git a/tests/auto/qml/qmltyperegistrar/foreign/foreign.h b/tests/auto/qml/qmltyperegistrar/foreign/foreign.h
new file mode 100644
index 0000000000..d5e5a060b4
--- /dev/null
+++ b/tests/auto/qml/qmltyperegistrar/foreign/foreign.h
@@ -0,0 +1,52 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef FOREIGN_H
+#define FOREIGN_H
+
+#include <QtCore/qobject.h>
+
+class Foreign : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(int things READ things WRITE setThings NOTIFY thingsChanged)
+
+public:
+ int things() const;
+
+public slots:
+ void setThings(int things);
+
+signals:
+ void thingsChanged(int things);
+
+private:
+ int m_things = 0;
+};
+
+#endif // FOREIGN_H
diff --git a/tests/auto/qml/qmltyperegistrar/foreign/foreign.pro b/tests/auto/qml/qmltyperegistrar/foreign/foreign.pro
new file mode 100644
index 0000000000..87521eac43
--- /dev/null
+++ b/tests/auto/qml/qmltyperegistrar/foreign/foreign.pro
@@ -0,0 +1,10 @@
+TEMPLATE = lib
+QT = core
+
+macos:CONFIG -= app_bundle
+CONFIG -= debug_and_release_target
+
+SOURCES = foreign.cpp
+HEADERS = foreign.h
+
+CONFIG += metatypes static
diff --git a/tests/auto/qml/qmltyperegistrar/hppheader.hpp b/tests/auto/qml/qmltyperegistrar/hppheader.hpp
new file mode 100644
index 0000000000..f5fc881b77
--- /dev/null
+++ b/tests/auto/qml/qmltyperegistrar/hppheader.hpp
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef HPPHEADER_HPP
+#define HPPHEADER_HPP
+
+#include <QtCore/qobject.h>
+#include <QtQml/qqml.h>
+
+class HppClass : public QObject
+{
+ Q_OBJECT
+ QML_ELEMENT
+ Q_PROPERTY(int eieiei READ eieiei WRITE setEieiei NOTIFY eieieiChanged)
+
+public:
+ int eieiei() const
+ {
+ return m_eieiei;
+ }
+
+public slots:
+ void setEieiei(int eieiei)
+ {
+ if (m_eieiei == eieiei)
+ return;
+
+ m_eieiei = eieiei;
+ emit eieieiChanged(m_eieiei);
+ }
+
+signals:
+ void eieieiChanged(int eieiei);
+
+private:
+ int m_eieiei;
+};
+
+#endif // HPPHEADER_HPP
diff --git a/tests/auto/qml/qmltyperegistrar/noextheader b/tests/auto/qml/qmltyperegistrar/noextheader
new file mode 100644
index 0000000000..3b6cb6d72c
--- /dev/null
+++ b/tests/auto/qml/qmltyperegistrar/noextheader
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef NOEXTHEADER
+#define NOEXTHEADER
+
+#include <QtCore/qobject.h>
+#include <QtQml/qqml.h>
+
+class Noext : public QObject
+{
+ Q_OBJECT
+ QML_ELEMENT
+ Q_PROPERTY(int gagaga READ gagaga WRITE setGagaga NOTIFY gagagaChanged)
+
+public:
+ int gagaga() const
+ {
+ return m_gagaga;
+ }
+
+public slots:
+ void setGagaga(int gagaga)
+ {
+ if (m_gagaga == gagaga)
+ return;
+
+ m_gagaga = gagaga;
+ emit gagagaChanged(m_gagaga);
+ }
+
+signals:
+ void gagagaChanged(int gagaga);
+
+private:
+ int m_gagaga;
+};
+
+#endif // NOEXTHEADER
diff --git a/tests/auto/qml/qmltyperegistrar/qmltyperegistrar.pro b/tests/auto/qml/qmltyperegistrar/qmltyperegistrar.pro
new file mode 100644
index 0000000000..738d099123
--- /dev/null
+++ b/tests/auto/qml/qmltyperegistrar/qmltyperegistrar.pro
@@ -0,0 +1,4 @@
+TEMPLATE = subdirs
+SUBDIRS = foreign tst_qmltyperegistrar.pro
+
+tst_qmltyperegistrar_pro.depends = foreign
diff --git a/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.cpp b/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.cpp
new file mode 100644
index 0000000000..8bdee2f937
--- /dev/null
+++ b/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.cpp
@@ -0,0 +1,61 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "tst_qmltyperegistrar.h"
+#include <QtTest/qtest.h>
+#include <QtCore/qcoreapplication.h>
+#include <QtCore/qfile.h>
+
+void tst_qmltyperegistrar::initTestCase()
+{
+ QFile file(QCoreApplication::applicationDirPath() + "/tst_qmltyperegistrar.qmltypes");
+ QVERIFY(file.open(QIODevice::ReadOnly));
+ qmltypesData = file.readAll();
+ QVERIFY(file.atEnd());
+ QCOMPARE(file.error(), QFile::NoError);
+}
+
+void tst_qmltyperegistrar::qmltypesHasForeign()
+{
+ QVERIFY(qmltypesData.contains("things"));
+}
+
+void tst_qmltyperegistrar::qmltypesHasHppClassAndNoext()
+{
+ QVERIFY(qmltypesData.contains("HppClass"));
+ QVERIFY(qmltypesData.contains("Noext"));
+}
+
+void tst_qmltyperegistrar::qmltypesHasFileNames()
+{
+ QVERIFY(qmltypesData.contains("file: \"hppheader.hpp\""));
+ QVERIFY(qmltypesData.contains("file: \"noextheader\""));
+ QVERIFY(qmltypesData.contains("file: \"tst_qmltyperegistrar.h\""));
+}
+
+QTEST_MAIN(tst_qmltyperegistrar)
diff --git a/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.h b/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.h
new file mode 100644
index 0000000000..37d49efa40
--- /dev/null
+++ b/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.h
@@ -0,0 +1,56 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef TST_QMLTYPEREGISTRAR_H
+#define TST_QMLTYPEREGISTRAR_H
+
+#include "foreign.h"
+
+#include <QtQml/qqml.h>
+
+class Local : public Foreign
+{
+ Q_OBJECT
+ QML_ELEMENT
+};
+
+class tst_qmltyperegistrar : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void initTestCase();
+ void qmltypesHasForeign();
+ void qmltypesHasHppClassAndNoext();
+ void qmltypesHasFileNames();
+
+private:
+ QByteArray qmltypesData;
+};
+
+#endif // TST_QMLTYPEREGISTRAR_H
diff --git a/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.pro b/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.pro
new file mode 100644
index 0000000000..fe21b122c2
--- /dev/null
+++ b/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.pro
@@ -0,0 +1,20 @@
+TEMPLATE = app
+
+QT = core qml testlib
+CONFIG += testcase qmltypes
+CONFIG -= debug_and_release_target
+macos:CONFIG -= app_bundle
+
+SOURCES += tst_qmltyperegistrar.cpp
+HEADERS += \
+ hppheader.hpp \
+ noextheader \
+ tst_qmltyperegistrar.h
+
+QMLTYPES_FILENAME = tst_qmltyperegistrar.qmltypes
+QML_FOREIGN_METATYPES += foreign/foreign_metatypes.json
+QML_IMPORT_NAME = QmlTypeRegistrarTest
+QML_IMPORT_VERSION = 1.0
+
+INCLUDEPATH += foreign
+LIBS += -Lforeign -lforeign
diff --git a/tests/auto/qml/qqmllanguage/data/arrayToContainer.qml b/tests/auto/qml/qqmllanguage/data/arrayToContainer.qml
index ee400eb41f..d8e278a7a1 100644
--- a/tests/auto/qml/qqmllanguage/data/arrayToContainer.qml
+++ b/tests/auto/qml/qqmllanguage/data/arrayToContainer.qml
@@ -3,5 +3,7 @@ import qt.test 1.0
TestItem {
property var vector
+ property var myset
positions: vector
+ barrays: myset
}
diff --git a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
index f2fa301565..8bee4ef260 100644
--- a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
+++ b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
@@ -2464,20 +2464,31 @@ void tst_qqmllanguage::scriptStringJs()
QVERIFY(!object->scriptProperty().booleanLiteral(&ok) && !ok);
}
+struct FreeUnitData
+{
+ static void cleanup(const QV4::CompiledData::Unit *readOnlyQmlUnit)
+ {
+ if (readOnlyQmlUnit && !(readOnlyQmlUnit->flags & QV4::CompiledData::Unit::StaticData))
+ free(const_cast<QV4::CompiledData::Unit *>(readOnlyQmlUnit));
+ }
+};
+
void tst_qqmllanguage::scriptStringWithoutSourceCode()
{
QUrl url = testFileUrl("scriptString7.qml");
+ QScopedPointer<const QV4::CompiledData::Unit, FreeUnitData> readOnlyQmlUnit;
{
QQmlEnginePrivate *eng = QQmlEnginePrivate::get(&engine);
QQmlRefPointer<QQmlTypeData> td = eng->typeLoader.getType(url);
Q_ASSERT(td);
- const QV4::CompiledData::Unit *readOnlyQmlUnit = td->compilationUnit()->unitData();
+ QQmlRefPointer<QV4::ExecutableCompilationUnit> compilationUnit = td->compilationUnit();
+ readOnlyQmlUnit.reset(compilationUnit->unitData());
Q_ASSERT(readOnlyQmlUnit);
QV4::CompiledData::Unit *qmlUnit = reinterpret_cast<QV4::CompiledData::Unit *>(malloc(readOnlyQmlUnit->unitSize));
- memcpy(qmlUnit, readOnlyQmlUnit, readOnlyQmlUnit->unitSize);
+ memcpy(qmlUnit, readOnlyQmlUnit.data(), readOnlyQmlUnit->unitSize);
+
qmlUnit->flags &= ~QV4::CompiledData::Unit::StaticData;
- QQmlRefPointer<QV4::ExecutableCompilationUnit> compilationUnit = td->compilationUnit();
compilationUnit->setUnitData(qmlUnit);
const QV4::CompiledData::Object *rootObject = compilationUnit->objectAt(/*root object*/0);
@@ -5773,25 +5784,31 @@ class TestItem : public QObject
{
Q_OBJECT
Q_PROPERTY( QVector<QPointF> positions MEMBER m_points )
+ Q_PROPERTY( QSet<QByteArray> barrays MEMBER m_barrays )
public:
TestItem() = default;
QVector< QPointF > m_points;
+ QSet<QByteArray> m_barrays;
};
Q_DECLARE_METATYPE(QVector<QPointF>);
+Q_DECLARE_METATYPE(QSet<QByteArray>);
void tst_qqmllanguage::arrayToContainer()
{
QQmlEngine engine;
qmlRegisterType<TestItem>("qt.test", 1, 0, "TestItem");
QVector<QPointF> points { QPointF (2.0, 3.0) };
+ QSet<QByteArray> barrays { QByteArray("hello"), QByteArray("world") };
engine.rootContext()->setContextProperty("test", QVariant::fromValue(points));
QQmlComponent component(&engine, testFileUrl("arrayToContainer.qml"));
VERIFY_ERRORS(0);
- QScopedPointer<TestItem> root(qobject_cast<TestItem *>(component.createWithInitialProperties( {{"vector", QVariant::fromValue(points)}} )));
+ QScopedPointer<TestItem> root(qobject_cast<TestItem *>(component.createWithInitialProperties( {{"vector", QVariant::fromValue(points)}, {"myset", QVariant::fromValue(barrays)} } )));
QVERIFY(root);
QCOMPARE(root->m_points.at(0), QPointF (2.0, 3.0) );
+ QVERIFY(root->m_barrays.contains("hello"));
+ QVERIFY(root->m_barrays.contains("world"));
}
class EnumTester : public QObject
diff --git a/tests/auto/quick/qquickanimations/data/signalorder.qml b/tests/auto/quick/qquickanimations/data/signalorder.qml
new file mode 100644
index 0000000000..35029b0c84
--- /dev/null
+++ b/tests/auto/quick/qquickanimations/data/signalorder.qml
@@ -0,0 +1,27 @@
+import QtQuick 2.12
+
+
+Item {
+ id: wrapper
+ width: 400; height: 400
+
+ Rectangle {
+ id: greenRect
+ width: 50; height: 50
+ color: "red"
+
+ ColorAnimation on color {
+ id: colorAnimation
+ objectName: "ColorAnimation"
+ to: "green"
+ duration: 10
+ running: false
+ }
+
+ ParallelAnimation {
+ id: parallelAnimation
+ objectName: "ParallelAnimation"
+ running: false
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickanimations/qquickanimations.pro b/tests/auto/quick/qquickanimations/qquickanimations.pro
index 94f694181d..6998c023db 100644
--- a/tests/auto/quick/qquickanimations/qquickanimations.pro
+++ b/tests/auto/quick/qquickanimations/qquickanimations.pro
@@ -64,6 +64,7 @@ OTHER_FILES += \
data/scriptActionCrash.qml \
data/sequentialAnimationNullChildBug.qml \
data/signals.qml \
+ data/signalorder.qml \
data/transitionAssignmentBug.qml \
data/valuesource.qml \
data/valuesource2.qml
diff --git a/tests/auto/quick/qquickanimations/tst_qquickanimations.cpp b/tests/auto/quick/qquickanimations/tst_qquickanimations.cpp
index 55957fa71a..e62d49ed6b 100644
--- a/tests/auto/quick/qquickanimations/tst_qquickanimations.cpp
+++ b/tests/auto/quick/qquickanimations/tst_qquickanimations.cpp
@@ -89,6 +89,8 @@ private slots:
void easingProperties();
void rotation();
void startStopSignals();
+ void signalOrder_data();
+ void signalOrder();
void runningTrueBug();
void nonTransitionBug();
void registrationBug();
@@ -1323,6 +1325,56 @@ void tst_qquickanimations::startStopSignals()
QVERIFY(timer.elapsed() >= 200);
}
+void tst_qquickanimations::signalOrder_data()
+{
+ QTest::addColumn<QByteArray>("animationType");
+ QTest::addColumn<int>("duration");
+
+ QTest::addRow("ColorAnimation, duration = 10") << QByteArray("ColorAnimation") << 10;
+ QTest::addRow("ColorAnimation, duration = 0") << QByteArray("ColorAnimation") << 0;
+ QTest::addRow("ParallelAnimation, duration = 0") << QByteArray("ParallelAnimation") << 0;
+}
+
+void tst_qquickanimations::signalOrder()
+{
+ QFETCH(QByteArray, animationType);
+ QFETCH(int, duration);
+
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFileUrl("signalorder.qml"));
+ QScopedPointer<QObject> obj(c.create());
+ auto *root = qobject_cast<QQuickItem *>(obj.data());
+ QVERIFY(root);
+ QQuickAbstractAnimation *animation = root->findChild<QQuickAbstractAnimation*>(animationType);
+
+ const QVector<void (QQuickAbstractAnimation::*)()> signalsToConnect = {
+ &QQuickAbstractAnimation::started,
+ &QQuickAbstractAnimation::stopped,
+ &QQuickAbstractAnimation::finished
+ };
+ const QVector<const char*> expectedSignalOrder = {
+ "started",
+ "stopped",
+ "finished"
+ };
+
+ QVector<const char*> actualSignalOrder;
+
+ for (int i = 0; i < signalsToConnect.size(); ++i) {
+ const char *str = expectedSignalOrder.at(i);
+ connect(animation, signalsToConnect.at(i) , [str, &actualSignalOrder] () {
+ actualSignalOrder.append(str);
+ });
+ }
+ QSignalSpy finishedSpy(animation, SIGNAL(finished()));
+ if (QQuickColorAnimation *colorAnimation = qobject_cast<QQuickColorAnimation*>(animation))
+ colorAnimation->setDuration(duration);
+
+ animation->start();
+ QTRY_VERIFY(finishedSpy.count());
+ QCOMPARE(actualSignalOrder, expectedSignalOrder);
+}
+
void tst_qquickanimations::runningTrueBug()
{
//ensure we start correctly when "running: true" is explicitly set
diff --git a/tests/auto/quick/qquickcanvasitem/BLACKLIST b/tests/auto/quick/qquickcanvasitem/BLACKLIST
index 21580b6730..a4b25475a4 100644
--- a/tests/auto/quick/qquickcanvasitem/BLACKLIST
+++ b/tests/auto/quick/qquickcanvasitem/BLACKLIST
@@ -3,12 +3,18 @@ macos
[canvas::test_paint]
macos
[canvas::test_save]
+windows
macos
[canvas::test_implicitlySizedParent]
-macos ci
+*
+# QTBUG-41043
[canvas::test_toDataURL]
-macos
+*
[fillRect::test_fillRect]
macos
[imagedata::test_rounding]
macos ci
+[ContextFontValidation::test_pixelSize]
+opensuse-leap
+[ContextFontValidation::test_valid]
+opensuse-leap
diff --git a/tests/auto/quick/qquickcanvasitem/data/CanvasTestCase.qml b/tests/auto/quick/qquickcanvasitem/data/CanvasTestCase.qml
index b0fb7fcf8c..5e02ca10d0 100644
--- a/tests/auto/quick/qquickcanvasitem/data/CanvasTestCase.qml
+++ b/tests/auto/quick/qquickcanvasitem/data/CanvasTestCase.qml
@@ -7,6 +7,7 @@ TestCase {
when:windowShown
width:100
height:100
+ visible: true
property Component component:CanvasComponent{}
function cleanupTestCase() {
wait(100) //wait for a short while to make sure no leaked textures
@@ -19,8 +20,8 @@ TestCase {
// { tag:"image cooperative", properties:{width:100, height:100, renderTarget:Canvas.Image, renderStrategy:Canvas.Cooperative}},
{ tag:"image immediate", properties:{width:100, height:100, renderTarget:Canvas.Image, renderStrategy:Canvas.Immediate}},
// { tag:"fbo cooperative", properties:{width:100, height:100, renderTarget:Canvas.FramebufferObject, renderStrategy:Canvas.Cooperative}},
- { tag:"fbo immediate", properties:{width:100, height:100, renderTarget:Canvas.FramebufferObject, renderStrategy:Canvas.Immediate}},
- { tag:"fbo threaded", properties:{width:100, height:100, renderTarget:Canvas.FramebufferObject, renderStrategy:Canvas.Threaded}}
+ { tag:"fbo immediate", properties:{width:100, height:100, renderTarget:Canvas.FramebufferObject, renderStrategy:Canvas.Immediate}}
+// { tag:"fbo threaded", properties:{width:100, height:100, renderTarget:Canvas.FramebufferObject, renderStrategy:Canvas.Threaded}} // QTBUG-82675
];
return [];
}
diff --git a/tests/auto/quick/qquickcanvasitem/data/tst_arcto.qml b/tests/auto/quick/qquickcanvasitem/data/tst_arcto.qml
index d9017150a4..ef1b7a7b2a 100644
--- a/tests/auto/quick/qquickcanvasitem/data/tst_arcto.qml
+++ b/tests/auto/quick/qquickcanvasitem/data/tst_arcto.qml
@@ -357,7 +357,7 @@ CanvasTestCase {
ctx.fillStyle = '#0f0';
ctx.beginPath();
ctx.moveTo(0, 50);
- ctx.translate(100, 0);
+ ctx.translate(50, 0);
ctx.arcTo(50, 50, 50, 0, 50);
ctx.lineTo(-100, 0);
ctx.fill();
@@ -367,11 +367,11 @@ CanvasTestCase {
comparePixel(ctx, 99,0, 0,255,0,255);
comparePixel(ctx, 0,25, 0,255,0,255);
comparePixel(ctx, 50,25, 0,255,0,255);
- comparePixel(ctx, 99,25, 0,255,0,255);
+ comparePixel(ctx, 99,25, 255,0,0,255);
comparePixel(ctx, 0,49, 0,255,0,255);
comparePixel(ctx, 50,49, 0,255,0,255);
- comparePixel(ctx, 99,49, 0,255,0,255);
- }
+ comparePixel(ctx, 99,49, 255,0,0,255);
+ }
function test_zero(row) {
var canvas = createCanvasObject(row);
var ctx = canvas.getContext('2d');
diff --git a/tests/auto/quick/qquickcanvasitem/data/tst_canvas.qml b/tests/auto/quick/qquickcanvasitem/data/tst_canvas.qml
index 8238d87313..d74df3daa7 100644
--- a/tests/auto/quick/qquickcanvasitem/data/tst_canvas.qml
+++ b/tests/auto/quick/qquickcanvasitem/data/tst_canvas.qml
@@ -129,12 +129,12 @@ CanvasTestCase {
tryCompare(c, "availableChangedCount", 1);
c.requestPaint();
- verify(c.save("c.png"));
- c.loadImage("c.png");
- wait(200);
- verify(c.isImageLoaded("c.png"));
- verify(!c.isImageLoading("c.png"));
- verify(!c.isImageError("c.png"));
+ var imagePath = applicationDirPath + "/c.png";
+ verify(c.save(imagePath));
+ c.loadImage(imagePath);
+ tryVerify(function() { return c.isImageLoaded(imagePath) })
+ verify(!c.isImageLoading(imagePath));
+ verify(!c.isImageError(imagePath));
c.destroy();
}
@@ -187,28 +187,28 @@ CanvasTestCase {
tryCompare(c, "availableChangedCount", 1);
//scene graph could be available immediately
//in this case, we force waiting a short while until the init paint finished
- tryCompare(c, "paintedCount", 1);
+ tryCompare(c, "paintedCount", 0);
ctx.fillRect(0, 0, c.width, c.height);
c.toDataURL();
- tryCompare(c, "paintedCount", 2);
+ tryCompare(c, "paintedCount", 1);
tryCompare(c, "paintCount", 1);
// implicit repaint when visible and resized
testCase.visible = true;
c.width += 1;
c.height += 1;
tryCompare(c, "paintCount", 2);
- tryCompare(c, "paintedCount", 2);
+ tryCompare(c, "paintedCount", 1);
// allow explicit repaint even when hidden
testCase.visible = false;
c.requestPaint();
tryCompare(c, "paintCount", 3);
- tryCompare(c, "paintedCount", 2);
+ tryCompare(c, "paintedCount", 1);
// no implicit repaint when resized but hidden
c.width += 1;
c.height += 1;
waitForRendering(c);
compare(c.paintCount, 3);
- tryCompare(c, "paintedCount", 2);
+ tryCompare(c, "paintedCount", 1);
c.destroy();
}
function test_loadImage(row) {
@@ -221,8 +221,7 @@ CanvasTestCase {
verify(!c.isImageLoaded("red.png"));
c.loadImage("red.png");
- wait(200);
- verify(c.isImageLoaded("red.png"));
+ tryVerify(function() { return c.isImageLoaded("red.png") });
verify(!c.isImageLoading("red.png"));
verify(!c.isImageError("red.png"));
diff --git a/tests/auto/quick/qquickcanvasitem/qquickcanvasitem.pro b/tests/auto/quick/qquickcanvasitem/qquickcanvasitem.pro
index 70e5a05f8d..90c7962382 100644
--- a/tests/auto/quick/qquickcanvasitem/qquickcanvasitem.pro
+++ b/tests/auto/quick/qquickcanvasitem/qquickcanvasitem.pro
@@ -55,5 +55,3 @@ OTHER_FILES += \
data/yellow75.png \
data/tst_invalidContext.qml
-
-CONFIG += insignificant_test # QTBUG-41043
diff --git a/tests/auto/quick/qquickcanvasitem/tst_qquickcanvasitem.cpp b/tests/auto/quick/qquickcanvasitem/tst_qquickcanvasitem.cpp
index dad8df0682..4a83bd6c0d 100644
--- a/tests/auto/quick/qquickcanvasitem/tst_qquickcanvasitem.cpp
+++ b/tests/auto/quick/qquickcanvasitem/tst_qquickcanvasitem.cpp
@@ -46,6 +46,8 @@ public slots:
false
#endif
));
+ engine->rootContext()->setContextProperty("applicationDirPath",
+ QCoreApplication::applicationDirPath());
}
};
diff --git a/tests/auto/quick/qquicklayouts/data/tst_rowlayout.qml b/tests/auto/quick/qquicklayouts/data/tst_rowlayout.qml
index 0732884c97..f61e2e0f48 100644
--- a/tests/auto/quick/qquicklayouts/data/tst_rowlayout.qml
+++ b/tests/auto/quick/qquicklayouts/data/tst_rowlayout.qml
@@ -118,10 +118,10 @@ Item {
function test_warnAboutLayoutItemsWithAnchors()
{
- var fullPath = Qt.resolvedUrl("tst_rowlayout.qml")
+ var regex = new RegExp("QML Item: Detected anchors on an item that is managed by a layout. "
+ + "This is undefined behavior; use Layout.alignment instead.")
for (var i = 0; i < 7; ++i) {
- ignoreWarning(fullPath + ":" + (75 + 5*i) +":17: QML Item: Detected anchors on an item that is managed by a layout. "
- + "This is undefined behavior; use Layout.alignment instead.")
+ ignoreWarning(regex)
}
var layout = itemsWithAnchorsLayout_Component.createObject(container)
waitForRendering(layout)
diff --git a/tests/auto/quick/qquickmousearea/data/settingHiddenInPressUngrabs.qml b/tests/auto/quick/qquickmousearea/data/settingHiddenInPressUngrabs.qml
new file mode 100644
index 0000000000..4532dabfd8
--- /dev/null
+++ b/tests/auto/quick/qquickmousearea/data/settingHiddenInPressUngrabs.qml
@@ -0,0 +1,36 @@
+import QtQuick 2.11
+import QtQuick.Window 2.11
+
+Window {
+ id: window
+ visible: true
+ width: 200
+ height: 200
+
+ MouseArea {
+ objectName: "cat"
+ anchors.fill: parent
+ onPressed: visible = false
+ width: parent.width / 2
+ height: parent.height
+ Rectangle {
+ width: 10
+ height: 10
+ color: "blue"
+ }
+ }
+ MouseArea {
+ objectName: "mouse"
+ x: parent.width / 2
+ width: parent.width / 2
+ height: parent.height
+ onPressed: {
+ enabled = false
+ }
+ Rectangle {
+ width: 10
+ height: 10
+ color: "blue"
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp b/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp
index 3503e8a9fd..5879fc6897 100644
--- a/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp
+++ b/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp
@@ -158,6 +158,7 @@ private slots:
void pressOneAndTapAnother();
void mask();
void nestedEventDelivery();
+ void settingHiddenInPressUngrabs();
private:
int startDragDistance() const {
@@ -2346,6 +2347,43 @@ void tst_QQuickMouseArea::nestedEventDelivery() // QTBUG-70898
QTest::mouseClick(window.data(), Qt::LeftButton, Qt::NoModifier, QPoint(50,150));
}
+void tst_QQuickMouseArea::settingHiddenInPressUngrabs()
+{
+ // When an item sets itself hidden, while handling pressed, it doesn't receive the grab.
+ // But that in turn means it doesn't see any release events, so we need to make sure it
+ // receives an ungrab event.
+
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFileUrl("settingHiddenInPressUngrabs.qml"));
+ QScopedPointer<QQuickWindow> window(qmlobject_cast<QQuickWindow *>(c.create()));
+ QVERIFY(window.data());
+ window->show();
+ window->requestActivate();
+ QVERIFY(QTest::qWaitForWindowExposed(window.data()));
+
+ QQuickMouseArea *catArea = window->findChild<QQuickMouseArea*>("cat");
+ QVERIFY(catArea != nullptr);
+ auto pointOnCatArea = catArea->mapToScene(QPointF(5.0, 5.0)).toPoint();
+ QTest::mouseClick(window.data(), Qt::LeftButton, Qt::NoModifier, pointOnCatArea);
+
+ QCoreApplication::processEvents();
+ // The click hides the cat area
+ QTRY_VERIFY(!catArea->isVisible());
+ // The cat area is not stuck in pressed state.
+ QVERIFY(!catArea->pressed());
+
+ QQuickMouseArea *mouseArea = window->findChild<QQuickMouseArea*>("mouse");
+ QVERIFY(mouseArea != nullptr);
+ auto pointOnMouseArea = mouseArea->mapToScene(QPointF(5.0, 5.0)).toPoint();
+ QTest::mouseClick(window.data(), Qt::LeftButton, Qt::NoModifier, pointOnMouseArea);
+
+ QCoreApplication::processEvents();
+ // The click disables the mouse area
+ QTRY_VERIFY(!mouseArea->isEnabled());
+ // The mouse area is not stuck in pressed state.
+ QVERIFY(!mouseArea->pressed());
+}
+
QTEST_MAIN(tst_QQuickMouseArea)
#include "tst_qquickmousearea.moc"
diff --git a/tests/auto/quickwidgets/qquickwidget/data/resizeOverlay.qml b/tests/auto/quickwidgets/qquickwidget/data/resizeOverlay.qml
new file mode 100644
index 0000000000..5547856941
--- /dev/null
+++ b/tests/auto/quickwidgets/qquickwidget/data/resizeOverlay.qml
@@ -0,0 +1,15 @@
+import QtQuick 2.15
+
+import Test 1.0
+
+Item {
+ id: root
+
+ property alias overlay: overlay
+
+ Overlay {
+ id: overlay
+ // Parent it to the contentItem of the underlying QQuickWindow.
+ parent: root.parent
+ }
+}
diff --git a/tests/auto/quickwidgets/qquickwidget/tst_qquickwidget.cpp b/tests/auto/quickwidgets/qquickwidget/tst_qquickwidget.cpp
index 691dfd1bc6..12c51caa75 100644
--- a/tests/auto/quickwidgets/qquickwidget/tst_qquickwidget.cpp
+++ b/tests/auto/quickwidgets/qquickwidget/tst_qquickwidget.cpp
@@ -33,6 +33,7 @@
#include <QtQml/qqmlcontext.h>
#include <QtQuick/qquickview.h>
#include <QtQuick/qquickitem.h>
+#include <QtQuick/private/qquickitem_p.h>
#include "../../shared/util.h"
#include <QtGui/QWindow>
#include <QtGui/QScreen>
@@ -142,6 +143,7 @@ private slots:
void synthMouseFromTouch_data();
void synthMouseFromTouch();
void tabKey();
+ void resizeOverlay();
private:
QTouchDevice *device = QTest::createTouchDevice();
@@ -662,6 +664,74 @@ void tst_qquickwidget::tabKey()
QVERIFY(middleItem->property("activeFocus").toBool());
}
+class Overlay : public QQuickItem, public QQuickItemChangeListener
+{
+ Q_OBJECT
+
+public:
+ Overlay() = default;
+
+ ~Overlay()
+ {
+ QQuickItemPrivate::get(parentItem())->removeItemChangeListener(this, QQuickItemPrivate::Geometry);
+ }
+
+ // componentCompleted() is too early to add the listener, as parentItem()
+ // is still null by that stage, so we use this function instead.
+ void startListening()
+ {
+ QQuickItemPrivate::get(parentItem())->addItemChangeListener(this, QQuickItemPrivate::Geometry);
+ }
+
+private:
+ virtual void itemGeometryChanged(QQuickItem *, QQuickGeometryChange, const QRectF &/*oldGeometry*/) override
+ {
+ auto window = QQuickItemPrivate::get(this)->window;
+ if (!window)
+ return;
+
+ setSize(window->size());
+ }
+};
+
+// Test that an item that resizes itself based on the window size can use a
+// Geometry item change listener to respond to changes in size. This is a
+// simplified test to mimic a use case involving Overlay from Qt Quick Controls 2.
+void tst_qquickwidget::resizeOverlay()
+{
+ QWidget widget;
+ auto contentVerticalLayout = new QVBoxLayout(&widget);
+ contentVerticalLayout->setMargin(0);
+
+ qmlRegisterType<Overlay>("Test", 1, 0, "Overlay");
+
+ auto quickWidget = new QQuickWidget(testFileUrl("resizeOverlay.qml"), &widget);
+ QCOMPARE(quickWidget->status(), QQuickWidget::Ready);
+ quickWidget->setResizeMode(QQuickWidget::SizeRootObjectToView);
+ contentVerticalLayout->addWidget(quickWidget);
+
+ auto rootItem = qobject_cast<QQuickItem*>(quickWidget->rootObject());
+ QVERIFY(rootItem);
+
+ auto overlay = rootItem->property("overlay").value<Overlay*>();
+ QVERIFY(overlay);
+ QVERIFY(overlay->parentItem());
+ overlay->startListening();
+
+ widget.resize(200, 200);
+ widget.show();
+ QCOMPARE(rootItem->width(), 200);
+ QCOMPARE(rootItem->height(), 200);
+ QCOMPARE(overlay->width(), rootItem->width());
+ QCOMPARE(overlay->height(), rootItem->height());
+
+ widget.resize(300, 300);
+ QCOMPARE(rootItem->width(), 300);
+ QCOMPARE(rootItem->height(), 300);
+ QCOMPARE(overlay->width(), rootItem->width());
+ QCOMPARE(overlay->height(), rootItem->height());
+}
+
QTEST_MAIN(tst_qquickwidget)
#include "tst_qquickwidget.moc"
diff --git a/tools/qmlformat/commentastvisitor.cpp b/tools/qmlformat/commentastvisitor.cpp
index 4dd241ff93..9383fa29aa 100644
--- a/tools/qmlformat/commentastvisitor.cpp
+++ b/tools/qmlformat/commentastvisitor.cpp
@@ -126,6 +126,14 @@ Comment CommentAstVisitor::findComment(SourceLocation first, SourceLocation last
return Comment(m_engine, Comment::Location::Front, comments);
}
+ if (locations & Comment::Location::Front_Inline) {
+ quint32 searchAt = first.startLine;
+
+ const auto comments = findCommentsInLine(searchAt);
+ if (!comments.isEmpty())
+ return Comment(m_engine, Comment::Location::Front_Inline, comments);
+ }
+
if (locations & Comment::Location::Back_Inline) {
quint32 searchAt = last.startLine;
@@ -198,13 +206,13 @@ void CommentAstVisitor::endVisit(StatementList *node)
bool CommentAstVisitor::visit(UiObjectBinding *node)
{
- attachComment(node, Comment::Front | Comment::Back);
+ attachComment(node, Comment::Front | Comment::Front_Inline | Comment::Back);
return true;
}
bool CommentAstVisitor::visit(UiObjectDefinition *node)
{
- attachComment(node, Comment::Front | Comment::Back);
+ attachComment(node, Comment::Front | Comment::Front_Inline | Comment::Back);
return true;
}
diff --git a/tools/qmlformat/commentastvisitor.h b/tools/qmlformat/commentastvisitor.h
index d3de0a9b9d..21c7eb6416 100644
--- a/tools/qmlformat/commentastvisitor.h
+++ b/tools/qmlformat/commentastvisitor.h
@@ -45,10 +45,11 @@ struct Comment
enum Location : int
{
Front = 1,
- Back = Front << 1,
+ Front_Inline = Front << 1,
+ Back = Front_Inline << 1,
Back_Inline = Back << 1,
DefaultLocations = Front | Back_Inline,
- AllLocations = Front | Back | Back_Inline
+ AllLocations = Front | Back | Front_Inline | Back_Inline
} m_location = Front;
Comment() = default;
diff --git a/tools/qmlformat/dumpastvisitor.cpp b/tools/qmlformat/dumpastvisitor.cpp
index 75712975cc..e0feff4e51 100644
--- a/tools/qmlformat/dumpastvisitor.cpp
+++ b/tools/qmlformat/dumpastvisitor.cpp
@@ -626,7 +626,7 @@ QString DumpAstVisitor::parseStatement(Statement *statement, bool blockHasNext,
case Node::Kind_IfStatement: {
auto *ifStatement = cast<IfStatement *>(statement);
- m_blockNeededBraces = false;
+ m_blockNeededBraces = !blockAllowBraceless;
QString ifFalse = parseStatement(ifStatement->ko, false, true);
QString ifTrue = parseStatement(ifStatement->ok, !ifFalse.isEmpty(), true);
@@ -641,8 +641,36 @@ QString DumpAstVisitor::parseStatement(Statement *statement, bool blockHasNext,
ifTrue = parseStatement(ifStatement->ok, !ifFalse.isEmpty(), false);
}
+ if (ifStatement->ok->kind != Node::Kind_Block)
+ ifTrue += ";";
+
+ if (ifStatement->ko && ifStatement->ko->kind != Node::Kind_Block && ifStatement->ko->kind != Node::Kind_IfStatement)
+ ifFalse += ";";
+
QString result = "if (" + parseExpression(ifStatement->expression) + ")";
+ if (m_blockNeededBraces) {
+ if (ifStatement->ok->kind != Node::Kind_Block) {
+ QString result = "{\n";
+ m_indentLevel++;
+ result += formatLine(ifTrue);
+ m_indentLevel--;
+ result += formatLine("} ", false);
+ ifTrue = result;
+ ifTrueBlock = true;
+ }
+
+ if (ifStatement->ko && ifStatement->ko->kind != Node::Kind_Block && ifStatement->ko->kind != Node::Kind_IfStatement) {
+ QString result = "{\n";
+ m_indentLevel++;
+ result += formatLine(ifFalse);
+ m_indentLevel--;
+ result += formatLine("} ", false);
+ ifFalse = result;
+ ifFalseBlock = true;
+ }
+ }
+
if (ifTrueBlock) {
result += " " + ifTrue;
} else {
@@ -724,8 +752,6 @@ QString DumpAstVisitor::parseStatement(Statement *statement, bool blockHasNext,
else
result += ";";
-
-
return result;
}
case Node::Kind_WhileStatement: {
@@ -825,7 +851,7 @@ QString DumpAstVisitor::parseStatementList(StatementList *list)
result += getOrphanedComments(list);
for (auto *item = list; item != nullptr; item = item->next) {
- QString statement = parseStatement(item->statement->statementCast());
+ QString statement = parseStatement(item->statement->statementCast(), false, true);
if (statement.isEmpty())
continue;
@@ -843,8 +869,8 @@ QString DumpAstVisitor::parseStatementList(StatementList *list)
}
bool DumpAstVisitor::visit(UiPublicMember *node) {
- addLine(getComment(node, Comment::Location::Front));
+ QString commentFront = getComment(node, Comment::Location::Front);
QString commentBackInline = getComment(node, Comment::Location::Back_Inline);
switch (node->type)
@@ -859,6 +885,7 @@ bool DumpAstVisitor::visit(UiPublicMember *node) {
scope().m_firstSignal = false;
}
+ addLine(commentFront);
addLine("signal "+node->name.toString()+"("+parseUiParameterList(node->parameters) + ")"
+ commentBackInline);
break;
@@ -897,6 +924,7 @@ bool DumpAstVisitor::visit(UiPublicMember *node) {
if (has_type_modifier)
member_type = node->typeModifier + "<" + member_type + ">";
+ addLine(commentFront);
if (is_readonly && statement.isEmpty()
&& scope().m_bindings.contains(node->name.toString())) {
m_result += formatLine(prefix + "property " + member_type + " ", false);
@@ -1003,6 +1031,7 @@ bool DumpAstVisitor::visit(UiObjectDefinition *node) {
}
addLine(getComment(node, Comment::Location::Front));
+ addLine(getComment(node, Comment::Location::Front_Inline));
addLine(parseUiQualifiedId(node->qualifiedTypeNameId) + " {");
m_indentLevel++;
@@ -1198,6 +1227,7 @@ bool DumpAstVisitor::visit(UiObjectBinding *node) {
} else {
addNewLine();
addLine(getComment(node, Comment::Location::Front));
+ addLine(getComment(node, Comment::Location::Front_Inline));
addLine(result + " {");
}
diff --git a/tools/qmlformat/main.cpp b/tools/qmlformat/main.cpp
index da58ffd5d0..3e71110cf9 100644
--- a/tools/qmlformat/main.cpp
+++ b/tools/qmlformat/main.cpp
@@ -43,7 +43,7 @@
#include "dumpastvisitor.h"
#include "restructureastvisitor.h"
-bool parseFile(const QString& filename, bool inplace, bool verbose, bool sortImports, bool force)
+bool parseFile(const QString& filename, bool inplace, bool verbose, bool sortImports, bool force, const QString& newline)
{
QFile file(filename);
@@ -128,11 +128,27 @@ bool parseFile(const QString& filename, bool inplace, bool verbose, bool sortImp
}
}
+
+ const bool native = newline == "native";
+
+ if (!native) {
+ if (newline == "macos") {
+ dumpCode = dumpCode.replace("\n","\r");
+ } else if (newline == "windows") {
+ dumpCode = dumpCode.replace("\n", "\r\n");
+ } else if (newline == "unix") {
+ // Nothing needs to be done for unix line-endings
+ } else {
+ qWarning().noquote() << "Unknown line ending type" << newline;
+ return false;
+ }
+ }
+
if (inplace) {
if (verbose)
qWarning().noquote() << "Writing to file" << filename;
- if (!file.open(QIODevice::Text | QIODevice::WriteOnly))
+ if (!file.open(native ? QIODevice::WriteOnly | QIODevice::Text : QIODevice::WriteOnly))
{
qWarning().noquote() << "Failed to open" << filename << "for writing";
return false;
@@ -141,7 +157,9 @@ bool parseFile(const QString& filename, bool inplace, bool verbose, bool sortImp
file.write(dumpCode.toUtf8());
file.close();
} else {
- QTextStream(stdout) << dumpCode;
+ QFile out;
+ out.open(stdout, QIODevice::WriteOnly);
+ out.write(dumpCode.toUtf8());
}
return true;
@@ -172,6 +190,10 @@ int main(int argc, char *argv[])
parser.addOption(QCommandLineOption({"f", "force"},
QStringLiteral("Continue even if an error has occurred.")));
+ parser.addOption(QCommandLineOption({"l", "newline"},
+ QStringLiteral("Override the new line format to use (native macos unix windows)."),
+ "newline", "native"));
+
parser.addPositionalArgument("filenames", "files to be processed by qmlformat");
parser.process(app);
@@ -181,8 +203,13 @@ int main(int argc, char *argv[])
if (positionalArguments.isEmpty())
parser.showHelp(-1);
+ if (!parser.isSet("inplace") && parser.value("newline") != "native") {
+ qWarning() << "Error: The -l option can only be used with -i";
+ return -1;
+ }
+
for (const QString& file: parser.positionalArguments()) {
- if (!parseFile(file, parser.isSet("inplace"), parser.isSet("verbose"), !parser.isSet("no-sort"), parser.isSet("force")))
+ if (!parseFile(file, parser.isSet("inplace"), parser.isSet("verbose"), !parser.isSet("no-sort"), parser.isSet("force"), parser.value("newline")))
success = false;
}
#endif
diff --git a/tools/qmllint/findunqualified.cpp b/tools/qmllint/findunqualified.cpp
index baae3a3ce7..604cf49122 100644
--- a/tools/qmllint/findunqualified.cpp
+++ b/tools/qmllint/findunqualified.cpp
@@ -183,8 +183,6 @@ QStringList completeImportPaths(const QString &uri, const QString &basePath, QTy
}
static const QLatin1String SlashQmldir = QLatin1String("/qmldir");
-static const QLatin1String SlashAppDotQmltypes = QLatin1String("/app.qmltypes");
-static const QLatin1String SlashLibDotQmltypes = QLatin1String("/lib.qmltypes");
static const QLatin1String SlashPluginsDotQmltypes = QLatin1String("/plugins.qmltypes");
void FindUnqualifiedIDVisitor::readQmltypes(const QString &filename,
@@ -287,16 +285,29 @@ void FindUnqualifiedIDVisitor::importHelper(const QString &module, const QString
break;
}
- Import result;
- if (QFile::exists(qmltypesPath + SlashAppDotQmltypes))
- readQmltypes(qmltypesPath + SlashAppDotQmltypes, result);
- else if (QFile::exists(qmltypesPath + SlashLibDotQmltypes))
- readQmltypes(qmltypesPath + SlashLibDotQmltypes, result);
- else
+ if (!m_qmltypeFiles.isEmpty())
continue;
+
+ Import result;
+
+ QDirIterator it { qmltypesPath, QStringList() << QLatin1String("*.qmltypes"), QDir::Files };
+
+ while (it.hasNext())
+ readQmltypes(it.next(), result);
+
processImport(prefix, result);
}
}
+
+ if (!m_qmltypeFiles.isEmpty())
+ {
+ Import result;
+
+ for (const auto &qmltypeFile : m_qmltypeFiles)
+ readQmltypes(qmltypeFile, result);
+
+ processImport("", result);
+ }
}
ScopeTree::Ptr FindUnqualifiedIDVisitor::localFile2ScopeTree(const QString &filePath)
@@ -433,6 +444,17 @@ bool FindUnqualifiedIDVisitor::visit(QQmlJS::AST::UiProgram *)
m_colorOut.writeUncolored(reader.errorMessage());
}
}
+
+ if (!m_qmltypeFiles.isEmpty())
+ {
+ for (const auto &qmltypeFile : m_qmltypeFiles) {
+ auto reader = createQmltypesReaderForFile(qmltypeFile);
+ auto succ = reader(&objects, &dependencies);
+ if (!succ)
+ m_colorOut.writeUncolored(reader.errorMessage());
+ }
+ }
+
// add builtins
for (auto objectIt = objects.begin(); objectIt != objects.end(); ++objectIt) {
auto val = objectIt.value();
@@ -644,10 +666,11 @@ bool FindUnqualifiedIDVisitor::visit(QQmlJS::AST::IdentifierExpression *idexp)
return true;
}
-FindUnqualifiedIDVisitor::FindUnqualifiedIDVisitor(QStringList qmltypeDirs, QString code,
+FindUnqualifiedIDVisitor::FindUnqualifiedIDVisitor(QStringList qmltypeDirs, QStringList qmltypeFiles, QString code,
QString fileName, bool silent)
: m_rootScope(ScopeTree::create(ScopeType::JSFunctionScope, "global")),
m_qmltypeDirs(std::move(qmltypeDirs)),
+ m_qmltypeFiles(std::move(qmltypeFiles)),
m_code(std::move(code)),
m_rootId(QLatin1String("<id>")),
m_filePath(std::move(fileName)),
diff --git a/tools/qmllint/findunqualified.h b/tools/qmllint/findunqualified.h
index 1c1751fafb..1782012424 100644
--- a/tools/qmllint/findunqualified.h
+++ b/tools/qmllint/findunqualified.h
@@ -52,7 +52,7 @@ class FindUnqualifiedIDVisitor : public QQmlJS::AST::Visitor
{
Q_DISABLE_COPY_MOVE(FindUnqualifiedIDVisitor)
public:
- explicit FindUnqualifiedIDVisitor(QStringList qmltypeDirs, QString code,
+ explicit FindUnqualifiedIDVisitor(QStringList qmltypeDirs, QStringList qmltypeFiles, QString code,
QString fileName, bool silent);
~FindUnqualifiedIDVisitor() override = default;
bool check();
@@ -69,6 +69,7 @@ private:
QHash<QString, ScopeTree::ConstPtr> m_types;
QHash<QString, ScopeTree::ConstPtr> m_exportedName2Scope;
QStringList m_qmltypeDirs;
+ QStringList m_qmltypeFiles;
QString m_code;
QHash<QString, ScopeTree::ConstPtr> m_qmlid2scope;
QString m_rootId;
diff --git a/tools/qmllint/main.cpp b/tools/qmllint/main.cpp
index fa601986b2..05519fc8d8 100644
--- a/tools/qmllint/main.cpp
+++ b/tools/qmllint/main.cpp
@@ -48,7 +48,7 @@
#endif
static bool lint_file(const QString &filename, const bool silent, const bool warnUnqualied,
- const QStringList &qmltypeDirs)
+ const QStringList &qmltypeDirs, const QStringList &qmltypeFiles)
{
QFile file(filename);
if (!file.open(QFile::ReadOnly)) {
@@ -84,7 +84,7 @@ static bool lint_file(const QString &filename, const bool silent, const bool war
if (success && !isJavaScript && warnUnqualied) {
auto root = parser.rootNode();
- FindUnqualifiedIDVisitor v { qmltypeDirs, code, filename, silent };
+ FindUnqualifiedIDVisitor v { qmltypeDirs, qmltypeFiles, code, filename, silent };
root->accept(&v);
success = v.check();
}
@@ -118,6 +118,13 @@ int main(int argv, char *argc[])
QLatin1String("directory"));
parser.addOption(qmltypesDirsOption);
+ QCommandLineOption qmltypesFilesOption(
+ QStringList() << "i"
+ << "qmltypes",
+ QLatin1String("Include the specified qmltypes files"),
+ QLatin1String("qmltypes"));
+ parser.addOption(qmltypesFilesOption);
+
parser.addPositionalArgument(QLatin1String("files"),
QLatin1String("list of qml or js files to verify"));
@@ -134,15 +141,20 @@ int main(int argv, char *argc[])
QStringList qmltypeDirs = parser.isSet(qmltypesDirsOption)
? parser.values(qmltypesDirsOption)
# ifndef QT_BOOTSTRAPPED
- : QStringList { QLibraryInfo::location(QLibraryInfo::Qml2ImportsPath),
- QLatin1String(".") };
+ : QStringList { QLibraryInfo::location(QLibraryInfo::Qml2ImportsPath) };
# else
- : QStringList { QLatin1String(".") };
+ : QStringList {};
# endif
+
+ if (!parser.isSet(qmltypesFilesOption))
+ qmltypeDirs << ".";
+
+ QStringList qmltypeFiles = parser.isSet(qmltypesFilesOption) ? parser.values(qmltypesFilesOption) : QStringList {};
#else
bool silent = false;
bool warnUnqualified = false;
QStringList qmltypeDirs {};
+ QStringList qmltypeFiles {};
#endif
bool success = true;
#if QT_CONFIG(commandlineparser)
@@ -151,7 +163,7 @@ int main(int argv, char *argc[])
const auto arguments = app.arguments();
for (const QString &filename : arguments)
#endif
- success &= lint_file(filename, silent, warnUnqualified, qmltypeDirs);
+ success &= lint_file(filename, silent, warnUnqualified, qmltypeDirs, qmltypeFiles);
return success ? 0 : -1;
}