From 223499039bfdda2ad14727f79fdfb7a07680379f Mon Sep 17 00:00:00 2001 From: Rmys Date: Sun, 23 Feb 2025 16:44:42 +0300 Subject: [PATCH] qt5-5.15.16 --- .../qt5/qt5-declarative/files/qt_kde.patch | 996 +----------------- desktop/toolkit/qt5/qt5-declarative/pspec.xml | 2 +- .../toolkit/qt5/qt5-tools/files/qt_kde.patch | 69 -- 3 files changed, 58 insertions(+), 1009 deletions(-) diff --git a/desktop/toolkit/qt5/qt5-declarative/files/qt_kde.patch b/desktop/toolkit/qt5/qt5-declarative/files/qt_kde.patch index 03308af354..17d6f5cd11 100644 --- a/desktop/toolkit/qt5/qt5-declarative/files/qt_kde.patch +++ b/desktop/toolkit/qt5/qt5-declarative/files/qt_kde.patch @@ -1,74 +1,32 @@ -diff --git a/src/qml/animations/qcontinuinganimationgroupjob.cpp b/src/qml/animations/qcontinuinganimationgroupjob.cpp -index 88c0e9e60e..61a9dc36f8 100644 ---- a/src/qml/animations/qcontinuinganimationgroupjob.cpp -+++ b/src/qml/animations/qcontinuinganimationgroupjob.cpp -@@ -82,9 +82,9 @@ void QContinuingAnimationGroupJob::updateState(QAbstractAnimationJob::State newS - return; - } - for (QAbstractAnimationJob *animation = firstChild(); animation; animation = animation->nextSibling()) { -- resetUncontrolledAnimationFinishTime(animation); -+ RETURN_IF_DELETED(resetUncontrolledAnimationFinishTime(animation)); - animation->setDirection(m_direction); -- animation->start(); -+ RETURN_IF_DELETED(animation->start()); - } - break; +diff --git a/src/3rdparty/masm/wtf/OSAllocatorPosix.cpp b/src/3rdparty/masm/wtf/OSAllocatorPosix.cpp +index b5c5f6a2b0..1a3d3cdf97 100644 +--- a/src/3rdparty/masm/wtf/OSAllocatorPosix.cpp ++++ b/src/3rdparty/masm/wtf/OSAllocatorPosix.cpp +@@ -112,10 +112,7 @@ void* OSAllocator::reserveUncommitted(size_t bytes, Usage usage, bool writable, + if (result == MAP_FAILED) + CRASH(); + +- while (madvise(result, bytes, MADV_DONTNEED)) { +- if (errno != EAGAIN) +- CRASH(); +- } ++ while (madvise(result, bytes, MADV_DONTNEED) == -1 && errno == EAGAIN) { } + + if (fd != -1) + close(fd); +@@ -248,8 +245,10 @@ void OSAllocator::decommit(void* address, size_t bytes) + mmap(address, bytes, PROT_NONE, MAP_FIXED | MAP_LAZY | MAP_PRIVATE | MAP_ANON, -1, 0); + #elif OS(LINUX) + while (madvise(address, bytes, MADV_DONTNEED)) { +- if (errno != EAGAIN) +- CRASH(); ++ if (errno != EAGAIN) { ++ memset(address, 0, bytes); // We rely on madvise to zero-out the memory ++ break; ++ } } -diff --git a/src/qml/animations/qparallelanimationgroupjob.cpp b/src/qml/animations/qparallelanimationgroupjob.cpp -index 420a934ba2..a828d0e234 100644 ---- a/src/qml/animations/qparallelanimationgroupjob.cpp -+++ b/src/qml/animations/qparallelanimationgroupjob.cpp -@@ -144,10 +144,10 @@ void QParallelAnimationGroupJob::updateState(QAbstractAnimationJob::State newSta - animation->stop(); - m_previousLoop = m_direction == Forward ? 0 : m_loopCount - 1; - } -- resetUncontrolledAnimationFinishTime(animation); -+ RETURN_IF_DELETED(resetUncontrolledAnimationFinishTime(animation)); - animation->setDirection(m_direction); - if (shouldAnimationStart(animation, oldState == Stopped)) -- animation->start(); -+ RETURN_IF_DELETED(animation->start()); - } - break; - } -diff --git a/src/qml/common/qqmljsmemorypool_p.h b/src/qml/common/qqmljsmemorypool_p.h -index 0cf7ea84e6..1b81a87a2c 100644 ---- a/src/qml/common/qqmljsmemorypool_p.h -+++ b/src/qml/common/qqmljsmemorypool_p.h -@@ -87,7 +87,7 @@ public: - inline void *allocate(size_t size) - { - size = (size + 7) & ~size_t(7); -- if (Q_LIKELY(_ptr && (_ptr + size < _end))) { -+ if (Q_LIKELY(_ptr && size < size_t(_end - _ptr))) { - void *addr = _ptr; - _ptr += size; - return addr; -diff --git a/src/qml/jit/qv4baselinejit.cpp b/src/qml/jit/qv4baselinejit.cpp -index 45150cfffd..5ad53faf95 100644 ---- a/src/qml/jit/qv4baselinejit.cpp -+++ b/src/qml/jit/qv4baselinejit.cpp -@@ -540,6 +540,8 @@ void BaselineJIT::generate_ThrowException() - as->passEngineAsArg(0); - BASELINEJIT_GENERATE_RUNTIME_CALL(ThrowException, CallResultDestination::Ignore); - as->gotoCatchException(); -+ -+ // LOAD_ACC(); <- not needed here since it would be unreachable. - } - - void BaselineJIT::generate_GetException() { as->getException(); } -@@ -547,9 +549,11 @@ void BaselineJIT::generate_SetException() { as->setException(); } - - void BaselineJIT::generate_CreateCallContext() - { -+ STORE_ACC(); - as->prepareCallWithArgCount(1); - as->passCppFrameAsArg(0); - BASELINEJIT_GENERATE_RUNTIME_CALL(PushCallContext, CallResultDestination::Ignore); -+ LOAD_ACC(); - } - - void BaselineJIT::generate_PushCatchContext(int index, int name) { as->pushCatchContext(index, name); } + if (mprotect(address, bytes, PROT_NONE)) + CRASH(); diff --git a/src/qml/jsruntime/qv4function.cpp b/src/qml/jsruntime/qv4function.cpp index cf8a53cf9f..223e64271e 100644 --- a/src/qml/jsruntime/qv4function.cpp @@ -82,79 +40,19 @@ index cf8a53cf9f..223e64271e 100644 parameterNames.append(dup); parameterNames[duplicate] = QString(0xfffe) + QString::number(duplicate) + dup; -diff --git a/src/qml/qml/ftw/qrecyclepool_p.h b/src/qml/qml/ftw/qrecyclepool_p.h -index 39f4f88512..c963e1878e 100644 ---- a/src/qml/qml/ftw/qrecyclepool_p.h -+++ b/src/qml/qml/ftw/qrecyclepool_p.h -@@ -130,8 +130,7 @@ template - T *QRecyclePool::New() - { - T *rv = d->allocate(); -- new (rv) T; -- return rv; -+ return new (rv) T; - } - - template -@@ -139,8 +138,7 @@ template - T *QRecyclePool::New(const T1 &a) - { - T *rv = d->allocate(); -- new (rv) T(a); -- return rv; -+ return new (rv) T(a); - } - - template -@@ -148,8 +146,7 @@ template - T *QRecyclePool::New(T1 &a) - { - T *rv = d->allocate(); -- new (rv) T(a); -- return rv; -+ return new (rv) T(a); - } - - template diff --git a/src/qml/qml/qqmldata_p.h b/src/qml/qml/qqmldata_p.h -index ee31cb38d9..187339169b 100644 +index c44fb8608e..69dac27c9a 100644 --- a/src/qml/qml/qqmldata_p.h +++ b/src/qml/qml/qqmldata_p.h -@@ -176,24 +176,24 @@ public: - }; - - struct NotifyList { -- quint64 connectionMask; -- -- quint16 maximumTodoIndex; -- quint16 notifiesSize; -- -- QQmlNotifierEndpoint *todo; -- QQmlNotifierEndpoint**notifies; -+ QAtomicInteger connectionMask; -+ QQmlNotifierEndpoint *todo = nullptr; -+ QQmlNotifierEndpoint**notifies = nullptr; -+ quint16 maximumTodoIndex = 0; -+ quint16 notifiesSize = 0; - void layout(); +@@ -185,7 +185,7 @@ public: private: void layout(QQmlNotifierEndpoint*); }; -- NotifyList *notifyList; -+ QAtomicPointer notifyList; +- QAtomicPointer notifyList; ++ QAtomicPointer notifyList = nullptr; -- inline QQmlNotifierEndpoint *notify(int index); -+ inline QQmlNotifierEndpoint *notify(int index) const; + inline QQmlNotifierEndpoint *notify(int index) const; void addNotify(int index, QQmlNotifierEndpoint *); - int endpointCount(int index); - bool signalHasEndpoint(int index) const; -- void disconnectNotifiers(); -+ -+ enum class DeleteNotifyList { Yes, No }; -+ void disconnectNotifiers(DeleteNotifyList doDelete); - - // The context that created the C++ object - QQmlContextData *context = nullptr; @@ -201,12 +201,12 @@ public: QQmlContextData *outerContext = nullptr; QQmlContextDataRef ownContext; @@ -191,7 +89,7 @@ index ee31cb38d9..187339169b 100644 QQmlPropertyCache *propertyCache; - QQmlGuardImpl *guards; -+ QQmlGuardImpl *guards = nullptr; ++ QQmlGuardImpl *guards = 0; static QQmlData *get(const QObject *object, bool create = false) { QObjectPrivate *priv = QObjectPrivate::get(const_cast(object)); @@ -204,83 +102,11 @@ index ee31cb38d9..187339169b 100644 Q_NEVER_INLINE static QQmlData *createQQmlData(QObjectPrivate *priv); Q_NEVER_INLINE static QQmlPropertyCache *createPropertyCache(QJSEngine *engine, QObject *object); -@@ -342,23 +342,31 @@ bool QQmlData::wasDeleted(const QObject *object) - return ddata && ddata->isQueuedForDeletion; - } - --QQmlNotifierEndpoint *QQmlData::notify(int index) -+inline bool isIndexInConnectionMask(quint64 connectionMask, int index) -+{ -+ return connectionMask & (1ULL << quint64(index % 64)); -+} -+ -+QQmlNotifierEndpoint *QQmlData::notify(int index) const - { -+ // Can only happen on "home" thread. We apply relaxed semantics when loading the atomics. -+ - Q_ASSERT(index <= 0xFFFF); - -- if (!notifyList || !(notifyList->connectionMask & (1ULL << quint64(index % 64)))) { -+ NotifyList *list = notifyList.loadRelaxed(); -+ if (!list || !isIndexInConnectionMask(list->connectionMask.loadRelaxed(), index)) - return nullptr; -- } else if (index < notifyList->notifiesSize) { -- return notifyList->notifies[index]; -- } else if (index <= notifyList->maximumTodoIndex) { -- notifyList->layout(); -- } - -- if (index < notifyList->notifiesSize) { -- return notifyList->notifies[index]; -- } else { -- return nullptr; -+ if (index < list->notifiesSize) -+ return list->notifies[index]; -+ -+ if (index <= list->maximumTodoIndex) { -+ list->layout(); -+ if (index < list->notifiesSize) -+ return list->notifies[index]; - } -+ -+ return nullptr; - } - - /* -@@ -367,7 +375,19 @@ QQmlNotifierEndpoint *QQmlData::notify(int index) - */ - inline bool QQmlData::signalHasEndpoint(int index) const - { -- return notifyList && (notifyList->connectionMask & (1ULL << quint64(index % 64))); -+ // This can be called from any thread. -+ // We still use relaxed semantics. If we're on a thread different from the "home" thread -+ // of the QQmlData, two interesting things might happen: -+ // -+ // 1. The list might go away while we hold it. In that case we are dealing with an object whose -+ // QObject dtor is being executed concurrently. This is UB already without the notify lists. -+ // Therefore, we don't need to consider it. -+ // 2. The connectionMask may be amended or zeroed while we are looking at it. In that case -+ // we "misreport" the endpoint. Since ordering of events across threads is inherently -+ // nondeterministic, either result is correct in that case. We can accept it. -+ -+ NotifyList *list = notifyList.loadRelaxed(); -+ return list && isIndexInConnectionMask(list->connectionMask.loadRelaxed(), index); - } - - bool QQmlData::hasBindingBit(int coreIndex) const diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp -index 852a673ebd..5f3367e4d2 100644 +index 2325c4c1e0..069e369319 100644 --- a/src/qml/qml/qqmlengine.cpp +++ b/src/qml/qml/qqmlengine.cpp -@@ -718,18 +718,15 @@ void QQmlPrivate::qdeclarativeelement_destructor(QObject *o) - // Disconnect the notifiers now - during object destruction this would be too late, since - // the disconnect call wouldn't be able to call disconnectNotify(), as it isn't possible to - // get the metaobject anymore. -- d->disconnectNotifiers(); -+ d->disconnectNotifiers(QQmlData::DeleteNotifyList::No); - } - } - +@@ -725,11 +725,8 @@ void QQmlPrivate::qdeclarativeelement_destructor(QObject *o) QQmlData::QQmlData() : ownedByQml1(false), ownMemory(true), indestructible(true), explicitIndestructibleSet(false), hasTaintedV4Object(false), isQueuedForDeletion(false), rootObjectInCreation(false), @@ -294,19 +120,7 @@ index 852a673ebd..5f3367e4d2 100644 { memset(bindingBitsValue, 0, sizeof(bindingBitsValue)); init(); -@@ -789,7 +786,10 @@ void QQmlData::signalEmitted(QAbstractDeclarativeData *, QObject *object, int in - // QQmlEngine to emit signals from a different thread. These signals are then automatically - // marshalled back onto the QObject's thread and handled by QML from there. This is tested - // by the qqmlecmascript::threadSignal() autotest. -- if (!ddata->notifyList) -+ -+ // Relaxed semantics here. If we're on a different thread we might schedule a useless event, -+ // but that should be rare. -+ if (!ddata->notifyList.loadRelaxed()) - return; - - auto objectThreadData = QObjectPrivate::get(object)->threadData.loadRelaxed(); -@@ -1588,17 +1588,22 @@ void qmlExecuteDeferred(QObject *object) +@@ -1591,17 +1588,22 @@ void qmlExecuteDeferred(QObject *object) { QQmlData *data = QQmlData::get(object); @@ -337,115 +151,6 @@ index 852a673ebd..5f3367e4d2 100644 } QQmlContext *qmlContext(const QObject *obj) -@@ -1835,49 +1840,73 @@ void QQmlData::releaseDeferredData() - - void QQmlData::addNotify(int index, QQmlNotifierEndpoint *endpoint) - { -- if (!notifyList) { -- notifyList = (NotifyList *)malloc(sizeof(NotifyList)); -- notifyList->connectionMask = 0; -- notifyList->maximumTodoIndex = 0; -- notifyList->notifiesSize = 0; -- notifyList->todo = nullptr; -- notifyList->notifies = nullptr; -+ // Can only happen on "home" thread. We apply relaxed semantics when loading the atomics. -+ -+ NotifyList *list = notifyList.loadRelaxed(); -+ -+ if (!list) { -+ list = new NotifyList; -+ // We don't really care when this change takes effect on other threads. The notifyList can -+ // only become non-null once in the life time of a QQmlData. It becomes null again when the -+ // underlying QObject is deleted. At that point any interaction with the QQmlData is UB -+ // anyway. So, for all intents and purposese, the list becomes non-null once and then stays -+ // non-null "forever". We can apply relaxed semantics. -+ notifyList.storeRelaxed(list); - } - - Q_ASSERT(!endpoint->isConnected()); - - index = qMin(index, 0xFFFF - 1); -- notifyList->connectionMask |= (1ULL << quint64(index % 64)); - -- if (index < notifyList->notifiesSize) { -+ // Likewise, we don't really care _when_ the change in the connectionMask is propagated to other -+ // threads. Cross-thread event ordering is inherently nondeterministic. Therefore, when querying -+ // the conenctionMask in the presence of concurrent modification, any result is correct. -+ list->connectionMask.storeRelaxed( -+ list->connectionMask.loadRelaxed() | (1ULL << quint64(index % 64))); - -- endpoint->next = notifyList->notifies[index]; -+ if (index < list->notifiesSize) { -+ endpoint->next = list->notifies[index]; - if (endpoint->next) endpoint->next->prev = &endpoint->next; -- endpoint->prev = ¬ifyList->notifies[index]; -- notifyList->notifies[index] = endpoint; -- -+ endpoint->prev = &list->notifies[index]; -+ list->notifies[index] = endpoint; - } else { -- notifyList->maximumTodoIndex = qMax(int(notifyList->maximumTodoIndex), index); -+ list->maximumTodoIndex = qMax(int(list->maximumTodoIndex), index); - -- endpoint->next = notifyList->todo; -+ endpoint->next = list->todo; - if (endpoint->next) endpoint->next->prev = &endpoint->next; -- endpoint->prev = ¬ifyList->todo; -- notifyList->todo = endpoint; -+ endpoint->prev = &list->todo; -+ list->todo = endpoint; - } - } - --void QQmlData::disconnectNotifiers() -+void QQmlData::disconnectNotifiers(QQmlData::DeleteNotifyList doDelete) - { -- if (notifyList) { -- while (notifyList->todo) -- notifyList->todo->disconnect(); -- for (int ii = 0; ii < notifyList->notifiesSize; ++ii) { -- while (QQmlNotifierEndpoint *ep = notifyList->notifies[ii]) -+ // Can only happen on "home" thread. We apply relaxed semantics when loading the atomics. -+ if (NotifyList *list = notifyList.loadRelaxed()) { -+ while (QQmlNotifierEndpoint *todo = list->todo) -+ todo->disconnect(); -+ for (int ii = 0; ii < list->notifiesSize; ++ii) { -+ while (QQmlNotifierEndpoint *ep = list->notifies[ii]) - ep->disconnect(); - } -- free(notifyList->notifies); -- free(notifyList); -- notifyList = nullptr; -+ free(list->notifies); -+ -+ if (doDelete == DeleteNotifyList::Yes) { -+ // We can only get here from QQmlData::destroyed(), and that can only come from the -+ // the QObject dtor. If you're still sending signals at that point you have UB already -+ // without any threads. Therefore, it's enough to apply relaxed semantics. -+ notifyList.storeRelaxed(nullptr); -+ delete list; -+ } else { -+ // We can use relaxed semantics here. The worst thing that can happen is that some -+ // signal is falsely reported as connected. Signal connectedness across threads -+ // is not quite deterministic anyway. -+ list->connectionMask.storeRelaxed(0); -+ list->maximumTodoIndex = 0; -+ list->notifiesSize = 0; -+ list->notifies = nullptr; -+ -+ } - } - } - -@@ -1961,7 +1990,7 @@ void QQmlData::destroyed(QObject *object) - guard->objectDestroyed(object); - } - -- disconnectNotifiers(); -+ disconnectNotifiers(DeleteNotifyList::Yes); - - if (extendedData) - delete extendedData; diff --git a/src/qml/qml/qqmlimport.cpp b/src/qml/qml/qqmlimport.cpp index e7263d1850..289f11d006 100644 --- a/src/qml/qml/qqmlimport.cpp @@ -466,28 +171,11 @@ index e7263d1850..289f11d006 100644 } /*! -diff --git a/src/qml/qml/qqmltypewrapper.cpp b/src/qml/qml/qqmltypewrapper.cpp -index 175de8b936..a6ba4b8cb3 100644 ---- a/src/qml/qml/qqmltypewrapper.cpp -+++ b/src/qml/qml/qqmltypewrapper.cpp -@@ -419,8 +419,10 @@ ReturnedValue QQmlTypeWrapper::virtualInstanceOf(const Object *typeObject, const - return Encode(false); - - QQmlRefPointer td = qenginepriv->typeLoader.getType(typeWrapper->d()->type().sourceUrl()); -- ExecutableCompilationUnit *cu = td->compilationUnit(); -- myQmlType = qenginepriv->metaObjectForType(cu->metaTypeId); -+ if (ExecutableCompilationUnit *cu = td->compilationUnit()) -+ myQmlType = qenginepriv->metaObjectForType(cu->metaTypeId); -+ else -+ return Encode(false); // It seems myQmlType has some errors, so we could not compile it. - } else { - myQmlType = qenginepriv->metaObjectForType(myTypeId); - } diff --git a/src/qml/qml/qqmlvmemetaobject.cpp b/src/qml/qml/qqmlvmemetaobject.cpp -index 1e0e4e419f..a0532d1794 100644 +index 4fd2092fd3..0d59d197dc 100644 --- a/src/qml/qml/qqmlvmemetaobject.cpp +++ b/src/qml/qml/qqmlvmemetaobject.cpp -@@ -251,7 +251,7 @@ void QQmlVMEMetaObjectEndpoint::tryConnect() +@@ -254,7 +254,7 @@ void QQmlVMEMetaObjectEndpoint::tryConnect() if (!pd) return; @@ -496,21 +184,8 @@ index 1e0e4e419f..a0532d1794 100644 connect(target, pd->notifyIndex(), ctxt->engine); } -diff --git a/src/qml/types/qqmlconnections.cpp b/src/qml/types/qqmlconnections.cpp -index 4a4e6ce12c..a5889b7396 100644 ---- a/src/qml/types/qqmlconnections.cpp -+++ b/src/qml/types/qqmlconnections.cpp -@@ -341,7 +341,7 @@ void QQmlConnections::connectSignalsToMethods() - && propName.at(2).isUpper()) { - qmlWarning(this) << tr("Detected function \"%1\" in Connections element. " - "This is probably intended to be a signal handler but no " -- "signal of the target matches the name.").arg(propName); -+ "signal of the \"%2\" target matches the name.").arg(propName).arg(target->metaObject()->className()); - } - } - } diff --git a/src/qmlmodels/qqmldelegatemodel.cpp b/src/qmlmodels/qqmldelegatemodel.cpp -index 4fcff70de6..5b7e767ae2 100644 +index 3b57edfc5d..5b7e767ae2 100644 --- a/src/qmlmodels/qqmldelegatemodel.cpp +++ b/src/qmlmodels/qqmldelegatemodel.cpp @@ -389,6 +389,12 @@ void QQmlDelegateModelPrivate::connectToAbstractItemModel() @@ -539,27 +214,7 @@ index 4fcff70de6..5b7e767ae2 100644 QObject::disconnect(aim, SIGNAL(dataChanged(QModelIndex,QModelIndex,QVector)), q, SLOT(_q_dataChanged(QModelIndex,QModelIndex,QVector))); QObject::disconnect(aim, SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int)), -@@ -1871,10 +1883,15 @@ void QQmlDelegateModelPrivate::emitChanges() - for (int i = 1; i < m_groupCount; ++i) - QQmlDelegateModelGroupPrivate::get(m_groups[i])->emitModelUpdated(reset); - -- auto cacheCopy = m_cache; // deliberate; emitChanges may alter m_cache -- for (QQmlDelegateModelItem *cacheItem : qAsConst(cacheCopy)) { -- if (cacheItem->attached) -- cacheItem->attached->emitChanges(); -+ // emitChanges may alter m_cache and delete items -+ QVarLengthArray> attachedObjects; -+ attachedObjects.reserve(m_cache.length()); -+ for (const QQmlDelegateModelItem *cacheItem : qAsConst(m_cache)) -+ attachedObjects.append(cacheItem->attached); -+ -+ for (const QPointer &attached : qAsConst(attachedObjects)) { -+ if (attached && attached->m_cacheItem) -+ attached->emitChanges(); - } - } - -@@ -1974,6 +1991,38 @@ void QQmlDelegateModel::_q_rowsMoved( +@@ -1979,6 +1991,38 @@ void QQmlDelegateModel::_q_rowsMoved( } } @@ -598,34 +253,6 @@ index 4fcff70de6..5b7e767ae2 100644 void QQmlDelegateModel::_q_dataChanged(const QModelIndex &begin, const QModelIndex &end, const QVector &roles) { Q_D(QQmlDelegateModel); -@@ -2663,20 +2712,24 @@ void QQmlDelegateModelAttached::emitChanges() - m_previousGroups = m_cacheItem->groups; - - int indexChanges = 0; -- for (int i = 1; i < m_cacheItem->metaType->groupCount; ++i) { -+ const int groupCount = m_cacheItem->metaType->groupCount; -+ for (int i = 1; i < groupCount; ++i) { - if (m_previousIndex[i] != m_currentIndex[i]) { - m_previousIndex[i] = m_currentIndex[i]; - indexChanges |= (1 << i); - } - } - -+ // Don't access m_cacheItem anymore once we've started sending signals. -+ // We don't own it and someone might delete it. -+ - int notifierId = 0; - const QMetaObject *meta = metaObject(); -- for (int i = 1; i < m_cacheItem->metaType->groupCount; ++i, ++notifierId) { -+ for (int i = 1; i < groupCount; ++i, ++notifierId) { - if (groupChanges & (1 << i)) - QMetaObject::activate(this, meta, notifierId, nullptr); - } -- for (int i = 1; i < m_cacheItem->metaType->groupCount; ++i, ++notifierId) { -+ for (int i = 1; i < groupCount; ++i, ++notifierId) { - if (indexChanges & (1 << i)) - QMetaObject::activate(this, meta, notifierId, nullptr); - } diff --git a/src/qmlmodels/qqmldelegatemodel_p.h b/src/qmlmodels/qqmldelegatemodel_p.h index 8aab4badca..d140bfbaaf 100644 --- a/src/qmlmodels/qqmldelegatemodel_p.h @@ -641,7 +268,7 @@ index 8aab4badca..d140bfbaaf 100644 void _q_rowsRemoved(const QModelIndex &,int,int); void _q_rowsMoved(const QModelIndex &, int, int, const QModelIndex &, int); diff --git a/src/quick/accessible/qaccessiblequickitem.cpp b/src/quick/accessible/qaccessiblequickitem.cpp -index ae1954ae8d..99e6eff7c3 100644 +index 36b65f906c..99e6eff7c3 100644 --- a/src/quick/accessible/qaccessiblequickitem.cpp +++ b/src/quick/accessible/qaccessiblequickitem.cpp @@ -46,6 +46,7 @@ @@ -717,15 +344,6 @@ index ae1954ae8d..99e6eff7c3 100644 return state; } -@@ -217,7 +230,7 @@ QAccessible::Role QAccessibleQuickItem::role() const - - QAccessible::Role role = QAccessible::NoRole; - if (item()) -- role = QQuickItemPrivate::get(item())->accessibleRole(); -+ role = QQuickItemPrivate::get(item())->effectiveAccessibleRole(); - if (role == QAccessible::NoRole) { - if (qobject_cast(const_cast(item()))) - role = QAccessible::StaticText; diff --git a/src/quick/accessible/qaccessiblequickview_p.h b/src/quick/accessible/qaccessiblequickview_p.h index 39ffcaf39c..8baa01330c 100644 --- a/src/quick/accessible/qaccessiblequickview_p.h @@ -769,61 +387,11 @@ index 8321fcfeed..383078b3b9 100644 drag->setMimeData(mimeData); if (pixmapLoader.isReady()) { -diff --git a/src/quick/items/qquickflickable.cpp b/src/quick/items/qquickflickable.cpp -index ea357d819d..2634b68248 100644 ---- a/src/quick/items/qquickflickable.cpp -+++ b/src/quick/items/qquickflickable.cpp -@@ -2120,11 +2120,9 @@ void QQuickFlickable::setContentWidth(qreal w) - d->contentItem->setWidth(w); - d->hData.markExtentsDirty(); - // Make sure that we're entirely in view. -- if ((!d->pressed && !d->hData.moving && !d->vData.moving) || d->hData.dragging) { -- d->hData.contentPositionChangedExternallyDuringDrag = d->hData.dragging; -+ if (!d->pressed && !d->hData.moving && !d->vData.moving) { - d->fixupMode = QQuickFlickablePrivate::Immediate; - d->fixupX(); -- d->hData.contentPositionChangedExternallyDuringDrag = false; - } else if (!d->pressed && d->hData.fixingUp) { - d->fixupMode = QQuickFlickablePrivate::ExtentChanged; - d->fixupX(); -@@ -2151,11 +2149,9 @@ void QQuickFlickable::setContentHeight(qreal h) - d->contentItem->setHeight(h); - d->vData.markExtentsDirty(); - // Make sure that we're entirely in view. -- if ((!d->pressed && !d->hData.moving && !d->vData.moving) || d->vData.dragging) { -- d->vData.contentPositionChangedExternallyDuringDrag = d->vData.dragging; -+ if (!d->pressed && !d->hData.moving && !d->vData.moving) { - d->fixupMode = QQuickFlickablePrivate::Immediate; - d->fixupY(); -- d->vData.contentPositionChangedExternallyDuringDrag = false; - } else if (!d->pressed && d->vData.fixingUp) { - d->fixupMode = QQuickFlickablePrivate::ExtentChanged; - d->fixupY(); -diff --git a/src/quick/items/qquickflickable_p_p.h b/src/quick/items/qquickflickable_p_p.h -index d5d838eaea..aef15e150a 100644 ---- a/src/quick/items/qquickflickable_p_p.h -+++ b/src/quick/items/qquickflickable_p_p.h -@@ -120,6 +120,7 @@ public: - dragStartOffset = 0; - fixingUp = false; - inOvershoot = false; -+ contentPositionChangedExternallyDuringDrag = false; - } - - void markExtentsDirty() { diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp -index 33da9762d3..9e8b289376 100644 +index c655b4c327..8b139cb539 100644 --- a/src/quick/items/qquickitem.cpp +++ b/src/quick/items/qquickitem.cpp -@@ -59,6 +59,7 @@ - #include - #include - #include -+#include - - #include - #include -@@ -2326,6 +2327,7 @@ QQuickItem::QQuickItem(QQuickItemPrivate &dd, QQuickItem *parent) +@@ -2328,6 +2328,7 @@ QQuickItem::QQuickItem(QQuickItemPrivate &dd, QQuickItem *parent) QQuickItem::~QQuickItem() { Q_D(QQuickItem); @@ -831,36 +399,7 @@ index 33da9762d3..9e8b289376 100644 if (d->windowRefCount > 1) d->windowRefCount = 1; // Make sure window is set to null in next call to derefWindow(). -@@ -2398,7 +2400,7 @@ bool QQuickItemPrivate::canAcceptTabFocus(QQuickItem *item) - return true; - - #if QT_CONFIG(accessibility) -- QAccessible::Role role = QQuickItemPrivate::get(item)->accessibleRole(); -+ QAccessible::Role role = QQuickItemPrivate::get(item)->effectiveAccessibleRole(); - if (role == QAccessible::EditableText || role == QAccessible::Table || role == QAccessible::List) { - return true; - } else if (role == QAccessible::ComboBox || role == QAccessible::SpinBox) { -@@ -2526,6 +2528,7 @@ QQuickItem* QQuickItemPrivate::nextPrevItemInTabFocusChain(QQuickItem *item, boo - QQuickItem *current = item; - qCDebug(DBG_FOCUS) << "QQuickItemPrivate::nextPrevItemInTabFocusChain: startItem:" << startItem; - qCDebug(DBG_FOCUS) << "QQuickItemPrivate::nextPrevItemInTabFocusChain: firstFromItem:" << firstFromItem; -+ QDuplicateTracker cycleDetector; - do { - qCDebug(DBG_FOCUS) << "QQuickItemPrivate::nextPrevItemInTabFocusChain: current:" << current; - qCDebug(DBG_FOCUS) << "QQuickItemPrivate::nextPrevItemInTabFocusChain: from:" << from; -@@ -2592,7 +2595,10 @@ QQuickItem* QQuickItemPrivate::nextPrevItemInTabFocusChain(QQuickItem *item, boo - // traversed all of the chain (by compare the [current] item with [startItem]) - // Since the [startItem] might be promoted to its parent if it is invisible, - // we still have to check [current] item with original start item -- if ((current == startItem || current == originalStartItem) && from == firstFromItem) { -+ // We might also run into a cycle before we reach firstFromItem again -+ // but note that we have to ignore current if we are meant to skip it -+ if (((current == startItem || current == originalStartItem) && from == firstFromItem) || -+ (!skip && cycleDetector.hasSeen(current))) { - // wrapped around, avoid endless loops - if (item == contentItem) { - qCDebug(DBG_FOCUS) << "QQuickItemPrivate::nextPrevItemInTabFocusChain: looped, return contentItem"; -@@ -2689,9 +2695,8 @@ void QQuickItem::setParentItem(QQuickItem *parentItem) +@@ -2695,9 +2696,8 @@ void QQuickItem::setParentItem(QQuickItem *parentItem) const bool wasVisible = isVisible(); op->removeChild(this); @@ -871,7 +410,7 @@ index 33da9762d3..9e8b289376 100644 } else if (d->window) { QQuickWindowPrivate::get(d->window)->parentlessItems.remove(this); } -@@ -2768,8 +2773,9 @@ void QQuickItem::setParentItem(QQuickItem *parentItem) +@@ -2774,8 +2774,9 @@ void QQuickItem::setParentItem(QQuickItem *parentItem) d->itemChange(ItemParentHasChanged, d->parentItem); @@ -883,7 +422,7 @@ index 33da9762d3..9e8b289376 100644 emit d->parentItem->visibleChildrenChanged(); } -@@ -2965,7 +2971,8 @@ void QQuickItemPrivate::removeChild(QQuickItem *child) +@@ -2971,7 +2972,8 @@ void QQuickItemPrivate::removeChild(QQuickItem *child) itemChange(QQuickItem::ItemChildRemovedChange, child); @@ -893,7 +432,7 @@ index 33da9762d3..9e8b289376 100644 } void QQuickItemPrivate::refWindow(QQuickWindow *c) -@@ -3194,6 +3201,7 @@ QQuickItemPrivate::QQuickItemPrivate() +@@ -3200,6 +3202,7 @@ QQuickItemPrivate::QQuickItemPrivate() , touchEnabled(false) #endif , hasCursorHandler(false) @@ -901,7 +440,7 @@ index 33da9762d3..9e8b289376 100644 , dirtyAttributes(0) , nextDirtyItem(nullptr) , prevDirtyItem(nullptr) -@@ -5120,6 +5128,13 @@ void QQuickItem::componentComplete() +@@ -5126,6 +5129,13 @@ void QQuickItem::componentComplete() d->addToDirtyList(); QQuickWindowPrivate::get(d->window)->dirtyItem(this); } @@ -915,7 +454,7 @@ index 33da9762d3..9e8b289376 100644 } QQuickStateGroup *QQuickItemPrivate::_states() -@@ -6106,9 +6121,11 @@ bool QQuickItemPrivate::setEffectiveVisibleRecur(bool newEffectiveVisible) +@@ -6112,9 +6122,11 @@ bool QQuickItemPrivate::setEffectiveVisibleRecur(bool newEffectiveVisible) QAccessible::updateAccessibility(&ev); } #endif @@ -930,7 +469,7 @@ index 33da9762d3..9e8b289376 100644 return true; // effective visibility DID change } -@@ -6157,6 +6174,15 @@ void QQuickItemPrivate::setEffectiveEnableRecur(QQuickItem *scope, bool newEffec +@@ -6163,6 +6175,15 @@ void QQuickItemPrivate::setEffectiveEnableRecur(QQuickItem *scope, bool newEffec } itemChange(QQuickItem::ItemEnabledHasChanged, effectiveEnable); @@ -946,33 +485,8 @@ index 33da9762d3..9e8b289376 100644 emit q->enabledChanged(); } -@@ -8974,13 +9000,20 @@ QQuickItemPrivate::ExtraData::ExtraData() - - - #if QT_CONFIG(accessibility) --QAccessible::Role QQuickItemPrivate::accessibleRole() const -+QAccessible::Role QQuickItemPrivate::effectiveAccessibleRole() const - { - Q_Q(const QQuickItem); -- QQuickAccessibleAttached *accessibleAttached = qobject_cast(qmlAttachedPropertiesObject(q, false)); -- if (accessibleAttached) -- return accessibleAttached->role(); -+ auto *attached = qmlAttachedPropertiesObject(q, false); -+ auto role = QAccessible::NoRole; -+ if (auto *accessibleAttached = qobject_cast(attached)) -+ role = accessibleAttached->role(); -+ if (role == QAccessible::NoRole) -+ role = accessibleRole(); -+ return role; -+} - -+QAccessible::Role QQuickItemPrivate::accessibleRole() const -+{ - return QAccessible::NoRole; - } - #endif diff --git a/src/quick/items/qquickitem_p.h b/src/quick/items/qquickitem_p.h -index 841d91bb40..6f329bd119 100644 +index d48b551064..6f329bd119 100644 --- a/src/quick/items/qquickitem_p.h +++ b/src/quick/items/qquickitem_p.h @@ -472,6 +472,7 @@ public: @@ -983,17 +497,6 @@ index 841d91bb40..6f329bd119 100644 enum DirtyType { TransformOrigin = 0x00000001, -@@ -574,7 +575,10 @@ public: - virtual void implicitHeightChanged(); - - #if QT_CONFIG(accessibility) -+ QAccessible::Role effectiveAccessibleRole() const; -+private: - virtual QAccessible::Role accessibleRole() const; -+public: - #endif - - void setImplicitAntialiasing(bool antialiasing); diff --git a/src/quick/items/qquickmousearea_p_p.h b/src/quick/items/qquickmousearea_p_p.h index fba383e268..0d63618622 100644 --- a/src/quick/items/qquickmousearea_p_p.h @@ -1014,27 +517,6 @@ index fba383e268..0d63618622 100644 QPointF startScene; QPointF targetStartPos; QPointF lastPos; -diff --git a/src/quick/util/qquickstategroup.cpp b/src/quick/util/qquickstategroup.cpp -index 7cb3138618..f732b1eb4a 100644 ---- a/src/quick/util/qquickstategroup.cpp -+++ b/src/quick/util/qquickstategroup.cpp -@@ -381,8 +381,14 @@ bool QQuickStateGroupPrivate::updateAutoState() - const auto potentialWhenBinding = QQmlPropertyPrivate::binding(whenProp); - // if there is a binding, the value in when might not be up-to-date at this point - // so we manually reevaluate the binding -- if (auto abstractBinding = dynamic_cast(potentialWhenBinding)) -- whenValue = abstractBinding->evaluate().toBool(); -+ if (auto abstractBinding = dynamic_cast(potentialWhenBinding)) { -+ QVariant evalResult = abstractBinding->evaluate(); -+ if (evalResult.userType() == qMetaTypeId()) -+ whenValue = evalResult.value().toBool(); -+ else -+ whenValue = evalResult.toBool(); -+ } -+ - if (whenValue) { - if (stateChangeDebug()) - qWarning() << "Setting auto state due to expression"; diff --git a/src/quickwidgets/qaccessiblequickwidget.cpp b/src/quickwidgets/qaccessiblequickwidget.cpp new file mode 100644 index 0000000000..8a1c901880 @@ -1530,62 +1012,6 @@ index 2438e577ae..85d156b8a3 100644 + qaccessiblequickwidgetfactory.cpp load(qt_module) -diff --git a/tests/auto/qml/qqmldelegatemodel/data/deleteRace.qml b/tests/auto/qml/qqmldelegatemodel/data/deleteRace.qml -new file mode 100644 -index 0000000000..23874970e7 ---- /dev/null -+++ b/tests/auto/qml/qqmldelegatemodel/data/deleteRace.qml -@@ -0,0 +1,50 @@ -+import QtQuick 2.15 -+import QtQml.Models 2.15 -+ -+Item { -+ DelegateModel { -+ id: delegateModel -+ model: ListModel { -+ id: sourceModel -+ -+ ListElement { title: "foo" } -+ ListElement { title: "bar" } -+ -+ function clear() { -+ if (count > 0) -+ remove(0, count); -+ } -+ } -+ -+ groups: [ -+ DelegateModelGroup { name: "selectedItems" } -+ ] -+ -+ delegate: Text { -+ height: DelegateModel.inSelectedItems ? implicitHeight * 2 : implicitHeight -+ Component.onCompleted: { -+ if (index === 0) -+ DelegateModel.inSelectedItems = true; -+ } -+ } -+ -+ Component.onCompleted: { -+ items.create(0) -+ items.create(1) -+ } -+ } -+ -+ ListView { -+ anchors.fill: parent -+ model: delegateModel -+ } -+ -+ Timer { -+ running: true -+ interval: 10 -+ onTriggered: sourceModel.clear() -+ } -+ -+ property int count: delegateModel.items.count -+} -+ diff --git a/tests/auto/qml/qqmldelegatemodel/data/redrawUponColumnChange.qml b/tests/auto/qml/qqmldelegatemodel/data/redrawUponColumnChange.qml new file mode 100644 index 0000000000..206133bb39 @@ -1604,7 +1030,7 @@ index 0000000000..206133bb39 + } +} diff --git a/tests/auto/qml/qqmldelegatemodel/tst_qqmldelegatemodel.cpp b/tests/auto/qml/qqmldelegatemodel/tst_qqmldelegatemodel.cpp -index 35f1e2c94d..f473cff75f 100644 +index f0afdb16ca..e5daf2d28b 100644 --- a/tests/auto/qml/qqmldelegatemodel/tst_qqmldelegatemodel.cpp +++ b/tests/auto/qml/qqmldelegatemodel/tst_qqmldelegatemodel.cpp @@ -27,6 +27,8 @@ @@ -1616,17 +1042,17 @@ index 35f1e2c94d..f473cff75f 100644 #include #include #include -@@ -47,6 +49,8 @@ private slots: - void filterOnGroup_removeWhenCompleted(); +@@ -48,6 +50,8 @@ private slots: void qtbug_86017(); void contextAccessedByHandler(); + void deleteRace(); + void redrawUponColumnChange(); + void deleteRace(); }; class AbstractItemModel : public QAbstractItemModel -@@ -186,6 +190,41 @@ void tst_QQmlDelegateModel::contextAccessedByHandler() - QVERIFY(root->property("works").toBool()); +@@ -187,6 +191,41 @@ void tst_QQmlDelegateModel::deleteRace() + QTRY_COMPARE(o->property("count").toInt(), 0); } +void tst_QQmlDelegateModel::redrawUponColumnChange() @@ -1683,283 +1109,6 @@ index 9c865b3f73..1f788f7a7f 100644 } Q_DECLARE_METATYPE(QQmlImports::ImportVersion) -diff --git a/tests/auto/qml/qqmllanguage/data/Broken.qml b/tests/auto/qml/qqmllanguage/data/Broken.qml -new file mode 100644 -index 0000000000..e24d9112a8 ---- /dev/null -+++ b/tests/auto/qml/qqmllanguage/data/Broken.qml -@@ -0,0 +1,5 @@ -+import QtQml 2.15 -+ -+QtObject { -+ notThere: 5 -+} -diff --git a/tests/auto/qml/qqmllanguage/data/asBroken.qml b/tests/auto/qml/qqmllanguage/data/asBroken.qml -new file mode 100644 -index 0000000000..bd88d14c76 ---- /dev/null -+++ b/tests/auto/qml/qqmllanguage/data/asBroken.qml -@@ -0,0 +1,6 @@ -+import QtQml 2.15 -+ -+QtObject { -+ id: self -+ property var selfAsBroken: self as Broken -+} -diff --git a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp -index ac6634290a..d16d117d65 100644 ---- a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp -+++ b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp -@@ -337,6 +337,7 @@ private slots: - void bareInlineComponent(); - - void hangOnWarning(); -+ void objectAsBroken(); - - void ambiguousContainingType(); - void staticConstexprMembers(); -@@ -5951,6 +5952,21 @@ void tst_qqmllanguage::badGroupedProperty() - .arg(url.toString())); - } - -+void tst_qqmllanguage::objectAsBroken() -+{ -+ QQmlEngine engine; -+ QQmlComponent c(&engine, testFileUrl("asBroken.qml")); -+ QVERIFY2(c.isReady(), qPrintable(c.errorString())); -+ QScopedPointer o(c.create()); -+ QVERIFY(!o.isNull()); -+ QVariant selfAsBroken = o->property("selfAsBroken"); -+ QVERIFY(selfAsBroken.isValid()); -+ // QCOMPARE(selfAsBroken.metaType(), QMetaType::fromType()); -+ -+ QQmlComponent b(&engine, testFileUrl("Broken.qml")); -+ QVERIFY(b.isError()); -+} -+ - QTEST_MAIN(tst_qqmllanguage) - - #include "tst_qqmllanguage.moc" -diff --git a/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp b/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp -index d092cd0170..62f7c67dd4 100644 ---- a/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp -+++ b/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp -@@ -2642,7 +2642,12 @@ void tst_qquickflickable::setContentPositionWhileDragging() // QTBUG-104966 - } else if (newExtent >= 0) { - // ...or reduce the content size be be less than current (contentX, contentY) position - // This forces the content item to move. -- expectedContentPos = moveDelta; -+ // contentY: 150 -+ // 320 - 150 = 170 pixels down to bottom -+ // Now reduce contentHeight to 200 -+ // since we are at the bottom, and the flickable is 100 pixels tall, contentY must land -+ // at newExtent - 100. -+ - if (isHorizontal) { - flickable->setContentWidth(newExtent); - } else { -@@ -2652,6 +2657,7 @@ void tst_qquickflickable::setContentPositionWhileDragging() // QTBUG-104966 - // We therefore cannot scroll/flick it further down. Drag it up towards the top instead - // (by moving mouse down). - pos += moveDelta; -+ expectedContentPos = unitDelta * (newExtent - (isHorizontal ? flickable->width() : flickable->height())); - } - - QTest::mouseMove(window.data(), pos); -diff --git a/tests/auto/quick/qquickgridview/data/qtbug86255.qml b/tests/auto/quick/qquickgridview/data/qtbug86255.qml -new file mode 100644 -index 0000000000..20688b1967 ---- /dev/null -+++ b/tests/auto/quick/qquickgridview/data/qtbug86255.qml -@@ -0,0 +1,55 @@ -+import QtQuick 2.15 -+ -+Item { -+ width: 240 -+ height: 320 -+ -+ GridView { -+ id: grid -+ objectName: "view" -+ anchors.fill: parent -+ cellWidth: 64 -+ cellHeight: 64 -+ model: ListModel { -+ id: listModel -+ -+ Component.onCompleted: reload() -+ -+ function reload() { -+ clear(); -+ for (let i = 0; i < 1000; i++) { -+ let magic = Math.random(); -+ append( { magic } ); -+ } -+ } -+ } -+ clip: true -+ delegate: Item { -+ id: d -+ property string val: magic -+ Loader { -+ property alias value: d.val -+ asynchronous: true -+ sourceComponent: cmp -+ } -+ } -+ } -+ -+ Timer { -+ running: true -+ interval: 1000 -+ onTriggered: listModel.reload() -+ } -+ Timer { -+ running: true -+ interval: 500 -+ onTriggered: grid.flick(0, -4000) -+ } -+ -+ Component { -+ id: cmp -+ Text { -+ text: value -+ } -+ } -+} -diff --git a/tests/auto/quick/qquickgridview/tst_qquickgridview.cpp b/tests/auto/quick/qquickgridview/tst_qquickgridview.cpp -index 94ec4f44d5..7d0d9fa7a7 100644 ---- a/tests/auto/quick/qquickgridview/tst_qquickgridview.cpp -+++ b/tests/auto/quick/qquickgridview/tst_qquickgridview.cpp -@@ -213,6 +213,7 @@ private slots: - void QTBUG_45640(); - void QTBUG_49218(); - void QTBUG_48870_fastModelUpdates(); -+ void QTBUG_86255(); - - void keyNavigationEnabled(); - void resizeDynamicCellWidthRtL(); -@@ -6814,6 +6815,18 @@ void tst_QQuickGridView::resizeDynamicCellWidthRtL() - QTRY_COMPARE(gridview->contentX(), 0.f); - } - -+void tst_QQuickGridView::QTBUG_86255() -+{ -+ QScopedPointer window(createView()); -+ window->setSource(testFileUrl("qtbug86255.qml")); -+ window->show(); -+ QVERIFY(QTest::qWaitForWindowExposed(window.data())); -+ QQuickGridView *view = findItem(window->rootObject(), "view"); -+ QVERIFY(view != nullptr); -+ QTRY_COMPARE(view->isFlicking(), true); -+ QTRY_COMPARE(view->isFlicking(), false); -+} -+ - void tst_QQuickGridView::releaseItems() - { - QScopedPointer view(createView()); -diff --git a/tests/auto/quick/qquickitem2/data/activeFocusOnTab_infiniteLoop3.qml b/tests/auto/quick/qquickitem2/data/activeFocusOnTab_infiniteLoop3.qml -new file mode 100644 -index 0000000000..889e480f3b ---- /dev/null -+++ b/tests/auto/quick/qquickitem2/data/activeFocusOnTab_infiniteLoop3.qml -@@ -0,0 +1,13 @@ -+import QtQuick 2.6 -+ -+Item { -+ visible: true -+ Item { -+ visible: false -+ Item { -+ objectName: "hiddenChild" -+ activeFocusOnTab: true -+ focus: true -+ } -+ } -+} -diff --git a/tests/auto/quick/qquickitem2/tst_qquickitem.cpp b/tests/auto/quick/qquickitem2/tst_qquickitem.cpp -index c8f251dbe1..c8ef36ee68 100644 ---- a/tests/auto/quick/qquickitem2/tst_qquickitem.cpp -+++ b/tests/auto/quick/qquickitem2/tst_qquickitem.cpp -@@ -67,6 +67,7 @@ private slots: - void activeFocusOnTab10(); - void activeFocusOnTab_infiniteLoop_data(); - void activeFocusOnTab_infiniteLoop(); -+ void activeFocusOnTab_infiniteLoopControls(); - - void nextItemInFocusChain(); - void nextItemInFocusChain2(); -@@ -1057,6 +1058,17 @@ void tst_QQuickItem::activeFocusOnTab_infiniteLoop() - QCOMPARE(item, window->rootObject()); - } - -+ -+void tst_QQuickItem::activeFocusOnTab_infiniteLoopControls() -+{ -+ auto source = testFileUrl("activeFocusOnTab_infiniteLoop3.qml"); -+ QScopedPointerwindow(new QQuickView()); -+ window->setSource(source); -+ window->show(); -+ QVERIFY(window->errors().isEmpty()); -+ QTest::keyClick(window.get(), Qt::Key_Tab); // should not hang -+} -+ - void tst_QQuickItem::nextItemInFocusChain() - { - if (!qt_tab_all_widgets()) -diff --git a/tests/auto/quick/qquickstates/data/jsValueWhen.qml b/tests/auto/quick/qquickstates/data/jsValueWhen.qml -new file mode 100644 -index 0000000000..6d5eb1600c ---- /dev/null -+++ b/tests/auto/quick/qquickstates/data/jsValueWhen.qml -@@ -0,0 +1,18 @@ -+import QtQuick 2.15 -+ -+Item { -+ id: root -+ property var prop: null -+ property bool works: false -+ states: [ -+ State { -+ name: "mystate" -+ when: root.prop -+ PropertyChanges { -+ target: root -+ works: "works" -+ } -+ } -+ ] -+ Component.onCompleted: root.prop = new Object -+} -diff --git a/tests/auto/quick/qquickstates/tst_qquickstates.cpp b/tests/auto/quick/qquickstates/tst_qquickstates.cpp -index aa55b42935..26e86672b0 100644 ---- a/tests/auto/quick/qquickstates/tst_qquickstates.cpp -+++ b/tests/auto/quick/qquickstates/tst_qquickstates.cpp -@@ -188,6 +188,7 @@ private slots: - void revertListMemoryLeak(); - void duplicateStateName(); - void trivialWhen(); -+ void jsValueWhen(); - void noStateOsciallation(); - void parentChangeCorrectReversal(); - void revertNullObjectBinding(); -@@ -1734,6 +1735,16 @@ void tst_qquickstates::trivialWhen() - QVERIFY(c.create()); - } - -+void tst_qquickstates::jsValueWhen() -+{ -+ QQmlEngine engine; -+ -+ QQmlComponent c(&engine, testFileUrl("jsValueWhen.qml")); -+ QScopedPointer root(c.create()); -+ QVERIFY(root); -+ QVERIFY(root->property("works").toBool()); -+} -+ - void tst_qquickstates::noStateOsciallation() - { - QQmlEngine engine; diff --git a/tests/manual/quickcontrols2/swipedelegate/CloseOnCompletedWorks.qml b/tests/manual/quickcontrols2/swipedelegate/CloseOnCompletedWorks.qml new file mode 100644 index 0000000000..38dfde41c3 @@ -2040,34 +1189,3 @@ index 0000000000..38dfde41c3 + } + } +} -diff --git a/tools/qml/main.cpp b/tools/qml/main.cpp -index beeec88f07..2cb7653d65 100644 ---- a/tools/qml/main.cpp -+++ b/tools/qml/main.cpp -@@ -446,8 +446,8 @@ int main(int argc, char *argv[]) - QCommandLineParser parser; - parser.setSingleDashWordOptionMode(QCommandLineParser::ParseAsLongOptions); - parser.setOptionsAfterPositionalArgumentsMode(QCommandLineParser::ParseAsPositionalArguments); -- const QCommandLineOption helpOption = parser.addHelpOption(); -- const QCommandLineOption versionOption = parser.addVersionOption(); -+ parser.addHelpOption(); -+ parser.addVersionOption(); - #ifdef QT_GUI_LIB - QCommandLineOption apptypeOption(QStringList() << QStringLiteral("a") << QStringLiteral("apptype"), - QCoreApplication::translate("main", "Select which application class to use. Default is gui."), -@@ -522,14 +522,7 @@ int main(int argc, char *argv[]) - parser.addPositionalArgument("args", - QCoreApplication::translate("main", "Arguments after '--' are ignored, but passed through to the application.arguments variable in QML."), "[-- args...]"); - -- if (!parser.parse(QCoreApplication::arguments())) { -- qWarning() << parser.errorText(); -- exit(1); -- } -- if (parser.isSet(versionOption)) -- parser.showVersion(); -- if (parser.isSet(helpOption)) -- parser.showHelp(); -+ parser.process(*app); - if (parser.isSet(listConfOption)) - listConfFiles(); - if (applicationType == QmlApplicationTypeUnknown) { diff --git a/desktop/toolkit/qt5/qt5-declarative/pspec.xml b/desktop/toolkit/qt5/qt5-declarative/pspec.xml index 8ec69e873a..33aab1ee74 100755 --- a/desktop/toolkit/qt5/qt5-declarative/pspec.xml +++ b/desktop/toolkit/qt5/qt5-declarative/pspec.xml @@ -22,7 +22,7 @@ qt5-sql-sqlite - + qt_kde.patch diff --git a/desktop/toolkit/qt5/qt5-tools/files/qt_kde.patch b/desktop/toolkit/qt5/qt5-tools/files/qt_kde.patch index 4d19d3dcca..4b1ffc11ed 100644 --- a/desktop/toolkit/qt5/qt5-tools/files/qt_kde.patch +++ b/desktop/toolkit/qt5/qt5-tools/files/qt_kde.patch @@ -35,75 +35,6 @@ index bb22000c8..415347a00 100644 QTPLUGIN.platforms = qminimal QTPLUGIN.sqldrivers = qsqlite -diff --git a/src/linguist/Qt5LinguistToolsMacros.cmake b/src/linguist/Qt5LinguistToolsMacros.cmake -index 6a45e57be..0ccf59f3c 100644 ---- a/src/linguist/Qt5LinguistToolsMacros.cmake -+++ b/src/linguist/Qt5LinguistToolsMacros.cmake -@@ -68,6 +68,7 @@ function(QT5_CREATE_TRANSLATION _qm_files) - if(NOT EXISTS "${stamp_file_dir}") - file(MAKE_DIRECTORY "${stamp_file_dir}") - endif() -+ set(stamp_files "") - foreach(_ts_file ${_my_tsfiles}) - get_filename_component(_ts_name ${_ts_file} NAME) - if(_my_sources) -@@ -95,7 +96,14 @@ function(QT5_CREATE_TRANSLATION _qm_files) - - file(WRITE ${_ts_lst_file} "${_lst_file_srcs}") - endif() -- set(stamp_file "${stamp_file_dir}/${_ts_name}.stamp") -+ file(RELATIVE_PATH _ts_relative_path ${CMAKE_CURRENT_SOURCE_DIR} ${_ts_file}) -+ string(REPLACE "../" "__/" _ts_relative_path "${_ts_relative_path}") -+ set(stamp_file "${stamp_file_dir}/${_ts_relative_path}.stamp") -+ list(APPEND stamp_files ${stamp_file}) -+ get_filename_component(full_stamp_file_dir "${stamp_file}" DIRECTORY) -+ if(NOT EXISTS "${full_stamp_file_dir}") -+ file(MAKE_DIRECTORY "${full_stamp_file_dir}") -+ endif() - add_custom_command(OUTPUT ${stamp_file} - COMMAND ${Qt5_LUPDATE_EXECUTABLE} - ARGS ${_lupdate_options} "@${_ts_lst_file}" -ts ${_ts_file} -@@ -103,7 +111,7 @@ function(QT5_CREATE_TRANSLATION _qm_files) - DEPENDS ${_dependencies} - VERBATIM) - endforeach() -- qt5_add_translation(${_qm_files} __QT_INTERNAL_DEPEND_ON_TIMESTAMP_FILE ${_my_tsfiles}) -+ qt5_add_translation(${_qm_files} ${_my_tsfiles} __QT_INTERNAL_TIMESTAMP_FILES ${stamp_files}) - set(${_qm_files} ${${_qm_files}} PARENT_SCOPE) - endfunction() - -@@ -120,17 +128,17 @@ endif() - - - function(QT5_ADD_TRANSLATION _qm_files) -- set(options __QT_INTERNAL_DEPEND_ON_TIMESTAMP_FILE) -+ set(options) - set(oneValueArgs) -- set(multiValueArgs OPTIONS) -+ set(multiValueArgs OPTIONS __QT_INTERNAL_TIMESTAMP_FILES) - - cmake_parse_arguments(_LRELEASE "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) - set(_lrelease_files ${_LRELEASE_UNPARSED_ARGUMENTS}) - -+ set(idx 0) - foreach(_current_FILE ${_lrelease_files}) - get_filename_component(_abs_FILE ${_current_FILE} ABSOLUTE) - get_filename_component(qm ${_abs_FILE} NAME) -- set(ts_stamp_file "${CMAKE_CURRENT_BINARY_DIR}/.lupdate/${qm}.stamp") - # everything before the last dot has to be considered the file name (including other dots) - string(REGEX REPLACE "\\.[^.]*$" "" FILE_NAME ${qm}) - get_source_file_property(output_location ${_abs_FILE} OUTPUT_LOCATION) -@@ -141,7 +149,9 @@ function(QT5_ADD_TRANSLATION _qm_files) - set(qm "${CMAKE_CURRENT_BINARY_DIR}/${FILE_NAME}.qm") - endif() - -- if(_LRELEASE___QT_INTERNAL_DEPEND_ON_TIMESTAMP_FILE) -+ if(_LRELEASE___QT_INTERNAL_TIMESTAMP_FILES) -+ list(GET _LRELEASE___QT_INTERNAL_TIMESTAMP_FILES ${idx} ts_stamp_file) -+ math(EXPR idx "${idx} + 1") - set(qm_dep "${ts_stamp_file}") - else() - set(qm_dep "${_abs_FILE}") diff --git a/src/qdoc/clangcodeparser.cpp b/src/qdoc/clangcodeparser.cpp index 539a603da..a41b99cec 100644 --- a/src/qdoc/clangcodeparser.cpp