From 70c3f2cdc7b795a6faffbb5e7b552e6feb00c654 Mon Sep 17 00:00:00 2001 From: Albert Astals Cid Date: Thu, 17 Jun 2021 16:32:28 +0200 Subject: [PATCH 01/21] Remove unused QPointer Change-Id: I009fa6bbd8599dc3bb2e810176fe20e70ed50851 Reviewed-by: Shawn Rutledge (cherry picked from commit ac03b4b8ee9cc8d4522e0c8cf1018ff086f80c1b) --- src/quick/items/qquickmousearea_p_p.h | 2 -- 1 file changed, 2 deletions(-) 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 +++ b/src/quick/items/qquickmousearea_p_p.h @@ -61,7 +61,6 @@ QT_BEGIN_NAMESPACE class QQuickMouseEvent; class QQuickMouseArea; -class QQuickPointerMask; class QQuickMouseAreaPrivate : public QQuickItemPrivate { Q_DECLARE_PUBLIC(QQuickMouseArea) @@ -100,7 +99,6 @@ public: #if QT_CONFIG(quick_draganddrop) QQuickDrag *drag; #endif - QPointer mask; QPointF startScene; QPointF targetStartPos; QPointF lastPos; -- 2.49.0 From cd192119255ac8a1b451aad04a82c58b294d5cbf Mon Sep 17 00:00:00 2001 From: Aleix Pol Date: Thu, 23 Sep 2021 03:43:04 +0200 Subject: [PATCH 02/21] QQmlDelegateModel: Refresh the view when a column is added at 0 It can happen that a model reports n>0 rows but columns=0 (See QConcatenateTablesProxyModel). In those cases we would render glitchy items until the elements are marked as dirty. Change-Id: I615c9cacbb1b6f9dee3898b03476605e5ac39d0a Reviewed-by: Ulf Hermann (cherry picked from commit ec9251efb918f37971aeefa1f687d137d037ff12) Reviewed-by: Qt Cherry-pick Bot Signed-off-by: Aleix Pol --- src/qmlmodels/qqmldelegatemodel.cpp | 44 +++++++++++++++++++ src/qmlmodels/qqmldelegatemodel_p.h | 3 ++ .../data/redrawUponColumnChange.qml | 11 +++++ .../tst_qqmldelegatemodel.cpp | 27 ++++++++++++ 4 files changed, 85 insertions(+) create mode 100644 tests/auto/qml/qqmldelegatemodel/data/redrawUponColumnChange.qml diff --git a/src/qmlmodels/qqmldelegatemodel.cpp b/src/qmlmodels/qqmldelegatemodel.cpp index 3b57edfc5d..5b7e767ae2 100644 --- a/src/qmlmodels/qqmldelegatemodel.cpp +++ b/src/qmlmodels/qqmldelegatemodel.cpp @@ -389,6 +389,12 @@ void QQmlDelegateModelPrivate::connectToAbstractItemModel() q, QQmlDelegateModel, SLOT(_q_rowsRemoved(QModelIndex,int,int))); qmlobject_connect(aim, QAbstractItemModel, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)), q, QQmlDelegateModel, SLOT(_q_rowsAboutToBeRemoved(QModelIndex,int,int))); + qmlobject_connect(aim, QAbstractItemModel, SIGNAL(columnsInserted(QModelIndex,int,int)), + q, QQmlDelegateModel, SLOT(_q_columnsInserted(QModelIndex,int,int))); + qmlobject_connect(aim, QAbstractItemModel, SIGNAL(columnsRemoved(QModelIndex,int,int)), + q, QQmlDelegateModel, SLOT(_q_columnsRemoved(QModelIndex,int,int))); + qmlobject_connect(aim, QAbstractItemModel, SIGNAL(columnsMoved(QModelIndex,int,int,QModelIndex,int)), + q, QQmlDelegateModel, SLOT(_q_columnsMoved(QModelIndex,int,int,QModelIndex,int))); qmlobject_connect(aim, QAbstractItemModel, SIGNAL(dataChanged(QModelIndex,QModelIndex,QVector)), q, QQmlDelegateModel, SLOT(_q_dataChanged(QModelIndex,QModelIndex,QVector))); qmlobject_connect(aim, QAbstractItemModel, SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int)), @@ -413,6 +419,12 @@ void QQmlDelegateModelPrivate::disconnectFromAbstractItemModel() q, SLOT(_q_rowsAboutToBeRemoved(QModelIndex,int,int))); QObject::disconnect(aim, SIGNAL(rowsRemoved(QModelIndex,int,int)), q, SLOT(_q_rowsRemoved(QModelIndex,int,int))); + QObject::disconnect(aim, SIGNAL(columnsInserted(QModelIndex,int,int)), q, + SLOT(_q_columnsInserted(QModelIndex,int,int))); + QObject::disconnect(aim, SIGNAL(columnsRemoved(QModelIndex,int,int)), q, + SLOT(_q_columnsRemoved(QModelIndex,int,int))); + QObject::disconnect(aim, SIGNAL(columnsMoved(QModelIndex,int,int,QModelIndex,int)), q, + SLOT(_q_columnsMoved(QModelIndex,int,int,QModelIndex,int))); 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)), @@ -1979,6 +1991,38 @@ void QQmlDelegateModel::_q_rowsMoved( } } +void QQmlDelegateModel::_q_columnsInserted(const QModelIndex &parent, int begin, int end) +{ + Q_D(QQmlDelegateModel); + Q_UNUSED(end); + if (parent == d->m_adaptorModel.rootIndex && begin == 0) { + // mark all items as changed + _q_itemsChanged(0, d->m_count, QVector()); + } +} + +void QQmlDelegateModel::_q_columnsRemoved(const QModelIndex &parent, int begin, int end) +{ + Q_D(QQmlDelegateModel); + Q_UNUSED(end); + if (parent == d->m_adaptorModel.rootIndex && begin == 0) { + // mark all items as changed + _q_itemsChanged(0, d->m_count, QVector()); + } +} + +void QQmlDelegateModel::_q_columnsMoved(const QModelIndex &parent, int start, int end, + const QModelIndex &destination, int column) +{ + Q_D(QQmlDelegateModel); + Q_UNUSED(end); + if ((parent == d->m_adaptorModel.rootIndex && start == 0) + || (destination == d->m_adaptorModel.rootIndex && column == 0)) { + // mark all items as changed + _q_itemsChanged(0, d->m_count, QVector()); + } +} + void QQmlDelegateModel::_q_dataChanged(const QModelIndex &begin, const QModelIndex &end, const QVector &roles) { Q_D(QQmlDelegateModel); diff --git a/src/qmlmodels/qqmldelegatemodel_p.h b/src/qmlmodels/qqmldelegatemodel_p.h index 8aab4badca..d140bfbaaf 100644 --- a/src/qmlmodels/qqmldelegatemodel_p.h +++ b/src/qmlmodels/qqmldelegatemodel_p.h @@ -152,6 +152,9 @@ private Q_SLOTS: void _q_itemsMoved(int from, int to, int count); void _q_modelReset(); void _q_rowsInserted(const QModelIndex &,int,int); + void _q_columnsInserted(const QModelIndex &, int, int); + void _q_columnsRemoved(const QModelIndex &, int, int); + void _q_columnsMoved(const QModelIndex &, int, int, const QModelIndex &, int); void _q_rowsAboutToBeRemoved(const QModelIndex &parent, int begin, int end); void _q_rowsRemoved(const QModelIndex &,int,int); void _q_rowsMoved(const QModelIndex &, int, int, const QModelIndex &, int); 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 --- /dev/null +++ b/tests/auto/qml/qqmldelegatemodel/data/redrawUponColumnChange.qml @@ -0,0 +1,11 @@ +import QtQuick 2.8 + +ListView { + id: root + width: 200 + height: 200 + + delegate: Text { + text: display + } +} diff --git a/tests/auto/qml/qqmldelegatemodel/tst_qqmldelegatemodel.cpp b/tests/auto/qml/qqmldelegatemodel/tst_qqmldelegatemodel.cpp index f0afdb16ca..e128d77c52 100644 --- a/tests/auto/qml/qqmldelegatemodel/tst_qqmldelegatemodel.cpp +++ b/tests/auto/qml/qqmldelegatemodel/tst_qqmldelegatemodel.cpp @@ -27,6 +27,8 @@ ****************************************************************************/ #include +#include +#include #include #include #include @@ -48,6 +50,7 @@ private slots: void qtbug_86017(); void contextAccessedByHandler(); void deleteRace(); + void redrawUponColumnChange(); }; class AbstractItemModel : public QAbstractItemModel @@ -187,6 +190,30 @@ void tst_QQmlDelegateModel::deleteRace() QTRY_COMPARE(o->property("count").toInt(), 0); } +void tst_QQmlDelegateModel::redrawUponColumnChange() +{ + QStandardItemModel m1; + m1.appendRow({ + new QStandardItem("Banana"), + new QStandardItem("Coconut"), + }); + + QQuickView view(testFileUrl("redrawUponColumnChange.qml")); + QCOMPARE(view.status(), QQuickView::Ready); + view.show(); + QQuickItem *root = view.rootObject(); + root->setProperty("model", QVariant::fromValue(&m1)); + + QObject *item = root->property("currentItem").value(); + QVERIFY(item); + QCOMPARE(item->property("text").toString(), "Banana"); + + QVERIFY(root); + m1.removeColumn(0); + + QCOMPARE(item->property("text").toString(), "Coconut"); +} + QTEST_MAIN(tst_QQmlDelegateModel) #include "tst_qqmldelegatemodel.moc" -- 2.49.0 From 608d9a277e1d3e6a84b711e6828a8f50ce26d7ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Arve=20S=C3=A6ther?= Date: Thu, 3 Sep 2020 10:51:01 +0200 Subject: [PATCH 03/21] Fix TapHandler so that it actually registers a tap This bug caused all quick examples that used the shared\LauncherList.qml to be broken. In QtGui, QSinglePointEvent will construct itself with a point id of 0 if there is a valid point, and with a point id of -1 if the point is invalid (the default constructor does the latter). However, QQuickSinglePointHandler::wantsPointerEvent() did not agree with that, because it assumed that a point id of 0 meant uninitialized/invalid point. The fix is to change QQuickSinglePointHandler::wantsPointerEvent() and QQuickHandlerPoint so that it assumes that the id -1 is now an invalid point, (instead of 0) Change-Id: I8c9683dfe06ebb77c5342a26f08174b67e7cbd90 Reviewed-by: Shawn Rutledge (cherry picked from commit 8d3a91016506fd0afedb0be535f7c34a4ca762f6) --- src/quick/handlers/qquickhandlerpoint.cpp | 4 ++-- src/quick/handlers/qquicksinglepointhandler.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/quick/handlers/qquickhandlerpoint.cpp b/src/quick/handlers/qquickhandlerpoint.cpp index 7103206470..02141b9a9e 100644 --- a/src/quick/handlers/qquickhandlerpoint.cpp +++ b/src/quick/handlers/qquickhandlerpoint.cpp @@ -82,7 +82,7 @@ void QQuickHandlerPoint::localize(QQuickItem *item) void QQuickHandlerPoint::reset() { - m_id = 0; + m_id = -1; m_uniqueId = QPointingDeviceUniqueId(); m_position = QPointF(); m_scenePosition = QPointF(); @@ -165,7 +165,7 @@ void QQuickHandlerPoint::reset(const QVector &points) pressureSum += point.pressure(); ellipseDiameterSum += point.ellipseDiameters(); } - m_id = 0; + m_id = -1; m_uniqueId = QPointingDeviceUniqueId(); // all points are required to be from the same event, so pressed buttons and modifiers should be the same m_pressedButtons = points.first().pressedButtons(); diff --git a/src/quick/handlers/qquicksinglepointhandler.cpp b/src/quick/handlers/qquicksinglepointhandler.cpp index d785d8c0ca..a508de455d 100644 --- a/src/quick/handlers/qquicksinglepointhandler.cpp +++ b/src/quick/handlers/qquicksinglepointhandler.cpp @@ -75,7 +75,7 @@ bool QQuickSinglePointHandler::wantsPointerEvent(QQuickPointerEvent *event) if (!QQuickPointerDeviceHandler::wantsPointerEvent(event)) return false; - if (d->pointInfo.id()) { + if (d->pointInfo.id() != -1) { // We already know which one we want, so check whether it's there. // It's expected to be an update or a release. // If we no longer want it, cancel the grab. @@ -125,7 +125,7 @@ bool QQuickSinglePointHandler::wantsPointerEvent(QQuickPointerEvent *event) chosen->setAccepted(); } } - return d->pointInfo.id(); + return d->pointInfo.id() != -1; } void QQuickSinglePointHandler::handlePointerEventImpl(QQuickPointerEvent *event) -- 2.49.0 From f5dd04cc3e358f7e8430b60e78ba90b6386b1cba Mon Sep 17 00:00:00 2001 From: Albert Astals Cid Date: Tue, 16 Nov 2021 22:43:37 +0100 Subject: [PATCH 04/21] Revert "Fix TapHandler so that it actually registers a tap" This reverts commit 36e8ccd434f948e4f11a8f9d59139ec072e41ff5. It's causing regresions --- src/quick/handlers/qquickhandlerpoint.cpp | 4 ++-- src/quick/handlers/qquicksinglepointhandler.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/quick/handlers/qquickhandlerpoint.cpp b/src/quick/handlers/qquickhandlerpoint.cpp index 02141b9a9e..7103206470 100644 --- a/src/quick/handlers/qquickhandlerpoint.cpp +++ b/src/quick/handlers/qquickhandlerpoint.cpp @@ -82,7 +82,7 @@ void QQuickHandlerPoint::localize(QQuickItem *item) void QQuickHandlerPoint::reset() { - m_id = -1; + m_id = 0; m_uniqueId = QPointingDeviceUniqueId(); m_position = QPointF(); m_scenePosition = QPointF(); @@ -165,7 +165,7 @@ void QQuickHandlerPoint::reset(const QVector &points) pressureSum += point.pressure(); ellipseDiameterSum += point.ellipseDiameters(); } - m_id = -1; + m_id = 0; m_uniqueId = QPointingDeviceUniqueId(); // all points are required to be from the same event, so pressed buttons and modifiers should be the same m_pressedButtons = points.first().pressedButtons(); diff --git a/src/quick/handlers/qquicksinglepointhandler.cpp b/src/quick/handlers/qquicksinglepointhandler.cpp index a508de455d..d785d8c0ca 100644 --- a/src/quick/handlers/qquicksinglepointhandler.cpp +++ b/src/quick/handlers/qquicksinglepointhandler.cpp @@ -75,7 +75,7 @@ bool QQuickSinglePointHandler::wantsPointerEvent(QQuickPointerEvent *event) if (!QQuickPointerDeviceHandler::wantsPointerEvent(event)) return false; - if (d->pointInfo.id() != -1) { + if (d->pointInfo.id()) { // We already know which one we want, so check whether it's there. // It's expected to be an update or a release. // If we no longer want it, cancel the grab. @@ -125,7 +125,7 @@ bool QQuickSinglePointHandler::wantsPointerEvent(QQuickPointerEvent *event) chosen->setAccepted(); } } - return d->pointInfo.id() != -1; + return d->pointInfo.id(); } void QQuickSinglePointHandler::handlePointerEventImpl(QQuickPointerEvent *event) -- 2.49.0 From 34752ab840ef2dc3bce327fe39c356f4b909f22a Mon Sep 17 00:00:00 2001 From: Vlad Zahorodnii Date: Sat, 29 Jan 2022 21:59:33 +0200 Subject: [PATCH 05/21] Make sure QQuickWidget and its offscreen window's screens are always in sync By default, the offscreen window is placed on the primary screen. However, if the parent widget argument is passed to the QQuickWidget's constructor, then QQuickWidget's and the offscreen window's screens can be different and that can create rendering issues, e.g. blurry text if the primary screen and QQuickWidget's screen have different scale factors. Change-Id: I10c62b5635664f943b11828773f14017f198a770 Reviewed-by: David Edmundson Reviewed-by: Laszlo Agocs (cherry picked from commit a2a2734bffa1459639b31fb3f4f83873ba44ab5c) --- src/quickwidgets/qquickwidget.cpp | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/src/quickwidgets/qquickwidget.cpp b/src/quickwidgets/qquickwidget.cpp index cf021d9a7c..c791f209cf 100644 --- a/src/quickwidgets/qquickwidget.cpp +++ b/src/quickwidgets/qquickwidget.cpp @@ -106,6 +106,7 @@ void QQuickWidgetPrivate::init(QQmlEngine* e) renderControl = new QQuickWidgetRenderControl(q); offscreenWindow = new QQuickWindow(*new QQuickOffcreenWindowPrivate(),renderControl); + offscreenWindow->setScreen(q->screen()); offscreenWindow->setTitle(QString::fromLatin1("Offscreen")); offscreenWindow->setObjectName(QString::fromLatin1("QQuickOffScreenWindow")); // Do not call create() on offscreenWindow. @@ -901,9 +902,7 @@ void QQuickWidgetPrivate::createContext() context = new QOpenGLContext; context->setFormat(offscreenWindow->requestedFormat()); - const QWindow *win = q->window()->windowHandle(); - if (win && win->screen()) - context->setScreen(win->screen()); + context->setScreen(q->screen()); QOpenGLContext *shareContext = qt_gl_global_share_context(); if (!shareContext) shareContext = QWidgetPrivate::get(q->window())->shareContext(); @@ -1527,19 +1526,16 @@ bool QQuickWidget::event(QEvent *e) d->handleWindowChange(); break; - case QEvent::ScreenChangeInternal: - if (QWindow *window = this->window()->windowHandle()) { - QScreen *newScreen = window->screen(); - - if (d->offscreenWindow) - d->offscreenWindow->setScreen(newScreen); - if (d->offscreenSurface) - d->offscreenSurface->setScreen(newScreen); + case QEvent::ScreenChangeInternal: { + QScreen *newScreen = screen(); + if (d->offscreenWindow) + d->offscreenWindow->setScreen(newScreen); + if (d->offscreenSurface) + d->offscreenSurface->setScreen(newScreen); #if QT_CONFIG(opengl) - if (d->context) - d->context->setScreen(newScreen); + if (d->context) + d->context->setScreen(newScreen); #endif - } if (d->useSoftwareRenderer #if QT_CONFIG(opengl) @@ -1552,7 +1548,7 @@ bool QQuickWidget::event(QEvent *e) d->render(true); } break; - + } case QEvent::Show: case QEvent::Move: d->updatePosition(); -- 2.49.0 From f2659326a01cd58ebd04b7590e486eb7d2830b28 Mon Sep 17 00:00:00 2001 From: Fushan Wen Date: Tue, 1 Nov 2022 22:35:24 +0800 Subject: [PATCH 06/21] Don't convert QByteArray in `startDrag` QMimeData::setData expects the provided data to contain the correctly encoded QByteArray, so if the variant contains a QByteArray, then take it as is to avoid data loss. If the variant is not already a byte array, then we ideally would make sure that the mime type (i.e. the key of the map) and the QVariant's type are compatible (image/png with a QImage works; text/plain with a QImage does not). This changes behavior and needs to be a follow-up commit. Fixes: QTBUG-71922 Change-Id: I9b9f10fd332e1f9568f6835a69a1c359457f823c Reviewed-by: Volker Hilsheimer (cherry picked from commit 062f9bf57657b54dc708015ec5fed3c89e5cc3ca) Reviewed-by: Qt Cherry-pick Bot (cherry picked from commit 22de23c4bb9ac5e2c545e9de3149a7d4f8edd5ee) --- src/quick/items/qquickdrag.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/quick/items/qquickdrag.cpp b/src/quick/items/qquickdrag.cpp index 8321fcfeed..3b50370355 100644 --- a/src/quick/items/qquickdrag.cpp +++ b/src/quick/items/qquickdrag.cpp @@ -481,7 +481,9 @@ void QQuickDragAttached::setKeys(const QStringList &keys) \qmlattachedproperty stringlist QtQuick::Drag::mimeData \since 5.2 - This property holds a map of mimeData that is used during startDrag. + This property holds a map from mime type to data that is used during startDrag. + The mime data needs to be a \c string, or an \c ArrayBuffer with the data encoded + according to the mime type. */ QVariantMap QQuickDragAttached::mimeData() const @@ -766,8 +768,12 @@ Qt::DropAction QQuickDragAttachedPrivate::startDrag(Qt::DropActions supportedAct QDrag *drag = new QDrag(source ? source : q); QMimeData *mimeData = new QMimeData(); - for (auto it = externalMimeData.cbegin(), end = externalMimeData.cend(); it != end; ++it) - mimeData->setData(it.key(), it.value().toString().toUtf8()); + for (auto it = externalMimeData.cbegin(), end = externalMimeData.cend(); it != end; ++it) { + if (it.value().typeId() == QMetaType::QByteArray) + mimeData->setData(it.key(), it.value().toByteArray()); + else + mimeData->setData(it.key(), it.value().toString().toUtf8()); + } drag->setMimeData(mimeData); if (pixmapLoader.isReady()) { -- 2.49.0 From 771b2ebea68e8f4c33a9d440c20d3dd1157670f6 Mon Sep 17 00:00:00 2001 From: Hannah von Reth Date: Sat, 5 Nov 2022 18:48:41 +0100 Subject: [PATCH 07/21] Fix build after 95290f66b806a307b8da1f72f8fc2c69801933d0 --- src/quick/items/qquickdrag.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/quick/items/qquickdrag.cpp b/src/quick/items/qquickdrag.cpp index 3b50370355..383078b3b9 100644 --- a/src/quick/items/qquickdrag.cpp +++ b/src/quick/items/qquickdrag.cpp @@ -769,7 +769,7 @@ Qt::DropAction QQuickDragAttachedPrivate::startDrag(Qt::DropActions supportedAct QMimeData *mimeData = new QMimeData(); for (auto it = externalMimeData.cbegin(), end = externalMimeData.cend(); it != end; ++it) { - if (it.value().typeId() == QMetaType::QByteArray) + if (static_cast(it.value().type()) == QMetaType::QByteArray) mimeData->setData(it.key(), it.value().toByteArray()); else mimeData->setData(it.key(), it.value().toString().toUtf8()); -- 2.49.0 From 295c5e9912edf5976f2035b22baa5f37af40c7c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Fri, 7 May 2021 10:07:50 +0200 Subject: [PATCH 08/21] Implement accessibility for QQuickWidget MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The accessibility tree for the Qt Quick content should be rooted at the QQuickWidget, and not at the offscreen QQuickWindow. For this to be the case, several things must happen: - QQuickWindow must not report the child interfaces - QQuickWidget must report the child interfaces - The child interfaces must report the QQuickWidget as the parent Create accessibility interfaces for QQuickWidget and and QQuickWigetOffscreenWindow (which now gets a proper subclass), where the QQuickWidget interface reports the child interfaces and the QQuickWigetOffscreenWindow reports no children Change the code in QAccessibleQuickItem to use the true (visible) window, where needed. Fixes: QTBUG-67290 Change-Id: I387d0ef711138d248a8dd16eefc9839499b35eeb Reviewed-by: Jan Arve Sæther Reviewed-by: Volker Hilsheimer (cherry picked from commit 41926e08d73ea6c4bbfc87a1dd52d2cdbc435c27) --- src/quick/accessible/qaccessiblequickitem.cpp | 29 +++-- src/quick/accessible/qaccessiblequickview_p.h | 2 +- src/quickwidgets/qaccessiblequickwidget.cpp | 110 ++++++++++++++++++ src/quickwidgets/qaccessiblequickwidget.h | 84 +++++++++++++ .../qaccessiblequickwidgetfactory.cpp | 60 ++++++++++ .../qaccessiblequickwidgetfactory_p.h | 66 +++++++++++ src/quickwidgets/qquickwidget.cpp | 18 ++- src/quickwidgets/qquickwidget_p.h | 8 ++ src/quickwidgets/quickwidgets.pro | 8 +- 9 files changed, 368 insertions(+), 17 deletions(-) create mode 100644 src/quickwidgets/qaccessiblequickwidget.cpp create mode 100644 src/quickwidgets/qaccessiblequickwidget.h create mode 100644 src/quickwidgets/qaccessiblequickwidgetfactory.cpp create mode 100644 src/quickwidgets/qaccessiblequickwidgetfactory_p.h diff --git a/src/quick/accessible/qaccessiblequickitem.cpp b/src/quick/accessible/qaccessiblequickitem.cpp index 36b65f906c..4d9e307a48 100644 --- a/src/quick/accessible/qaccessiblequickitem.cpp +++ b/src/quick/accessible/qaccessiblequickitem.cpp @@ -46,6 +46,7 @@ #include "QtQuick/private/qquicktextinput_p.h" #include "QtQuick/private/qquickaccessibleattached_p.h" #include "QtQuick/qquicktextdocument.h" +#include "QtQuick/qquickrendercontrol.h" QT_BEGIN_NAMESPACE #if QT_CONFIG(accessibility) @@ -57,7 +58,19 @@ QAccessibleQuickItem::QAccessibleQuickItem(QQuickItem *item) QWindow *QAccessibleQuickItem::window() const { - return item()->window(); + QQuickWindow *window = item()->window(); + + // For QQuickWidget the above window will be the offscreen QQuickWindow, + // which is not a part of the accessibility tree. Detect this case and + // return the window for the QQuickWidget instead. + if (window && !window->handle()) { + if (QQuickRenderControl *renderControl = QQuickWindowPrivate::get(window)->renderControl) { + if (QWindow *renderWindow = renderControl->renderWindow(nullptr)) + return renderWindow; + } + } + + return window; } int QAccessibleQuickItem::childCount() const @@ -113,19 +126,15 @@ QAccessibleInterface *QAccessibleQuickItem::childAt(int x, int y) const QAccessibleInterface *QAccessibleQuickItem::parent() const { QQuickItem *parent = item()->parentItem(); - QQuickWindow *window = item()->window(); - QQuickItem *ci = window ? window->contentItem() : nullptr; + QQuickWindow *itemWindow = item()->window(); + QQuickItem *ci = itemWindow ? itemWindow->contentItem() : nullptr; while (parent && !QQuickItemPrivate::get(parent)->isAccessible && parent != ci) parent = parent->parentItem(); if (parent) { if (parent == ci) { - // Jump out to the scene widget if the parent is the root item. - // There are two root items, QQuickWindow::rootItem and - // QQuickView::declarativeRoot. The former is the true root item, - // but is not a part of the accessibility tree. Check if we hit - // it here and return an interface for the scene instead. - return QAccessible::queryAccessibleInterface(window); + // Jump out to the window if the parent is the root item + return QAccessible::queryAccessibleInterface(window()); } else { while (parent && !parent->d_func()->isAccessible) parent = parent->parentItem(); @@ -193,7 +202,7 @@ QAccessible::State QAccessibleQuickItem::state() const QRect viewRect_ = viewRect(); QRect itemRect = rect(); - if (viewRect_.isNull() || itemRect.isNull() || !item()->window() || !item()->window()->isVisible() ||!item()->isVisible() || qFuzzyIsNull(item()->opacity())) + if (viewRect_.isNull() || itemRect.isNull() || !window() || !window()->isVisible() ||!item()->isVisible() || qFuzzyIsNull(item()->opacity())) state.invisible = true; if (!viewRect_.intersects(itemRect)) state.offscreen = true; 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 +++ b/src/quick/accessible/qaccessiblequickview_p.h @@ -58,7 +58,7 @@ QT_BEGIN_NAMESPACE #if QT_CONFIG(accessibility) -class QAccessibleQuickWindow : public QAccessibleObject +class Q_QUICK_EXPORT QAccessibleQuickWindow : public QAccessibleObject { public: QAccessibleQuickWindow(QQuickWindow *object); diff --git a/src/quickwidgets/qaccessiblequickwidget.cpp b/src/quickwidgets/qaccessiblequickwidget.cpp new file mode 100644 index 0000000000..6f04d6693f --- /dev/null +++ b/src/quickwidgets/qaccessiblequickwidget.cpp @@ -0,0 +1,110 @@ +/**************************************************************************** +** +** Copyright (C) 2021 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQuick module 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$ +** +****************************************************************************/ + +#include "qaccessiblequickwidget.h" + +#include "qquickwidget_p.h" + +QT_BEGIN_NAMESPACE + +#if QT_CONFIG(accessibility) + +QAccessibleQuickWidget::QAccessibleQuickWidget(QQuickWidget* widget) +: QAccessibleWidget(widget) +, m_accessibleWindow(QQuickWidgetPrivate::get(widget)->offscreenWindow) +{ + // NOTE: m_accessibleWindow is a QAccessibleQuickWindow, and not a + // QAccessibleQuickWidgetOffscreenWindow (defined below). This means + // it will return the Quick item child interfaces, which is what's needed here + // (unlike QAccessibleQuickWidgetOffscreenWindow, which will report 0 children). +} + +QAccessibleInterface *QAccessibleQuickWidget::child(int index) const +{ + return m_accessibleWindow.child(index); +} + +int QAccessibleQuickWidget::childCount() const +{ + return m_accessibleWindow.childCount(); +} + +int QAccessibleQuickWidget::indexOfChild(const QAccessibleInterface *iface) const +{ + return m_accessibleWindow.indexOfChild(iface); +} + +QAccessibleInterface *QAccessibleQuickWidget::childAt(int x, int y) const +{ + return m_accessibleWindow.childAt(x, y); +} + +QAccessibleQuickWidgetOffscreenWindow::QAccessibleQuickWidgetOffscreenWindow(QQuickWindow *window) +:QAccessibleQuickWindow(window) +{ + +} + +QAccessibleInterface *QAccessibleQuickWidgetOffscreenWindow::child(int index) const +{ + Q_UNUSED(index); + return nullptr; +} + +int QAccessibleQuickWidgetOffscreenWindow::childCount() const +{ + return 0; +} + +int QAccessibleQuickWidgetOffscreenWindow::indexOfChild(const QAccessibleInterface *iface) const +{ + Q_UNUSED(iface); + return -1; +} + +QAccessibleInterface *QAccessibleQuickWidgetOffscreenWindow::QAccessibleQuickWidgetOffscreenWindow::childAt(int x, int y) const +{ + Q_UNUSED(x); + Q_UNUSED(y); + return nullptr; +} + +#endif // accessibility + +QT_END_NAMESPACE diff --git a/src/quickwidgets/qaccessiblequickwidget.h b/src/quickwidgets/qaccessiblequickwidget.h new file mode 100644 index 0000000000..1f52c78c46 --- /dev/null +++ b/src/quickwidgets/qaccessiblequickwidget.h @@ -0,0 +1,84 @@ +/**************************************************************************** +** +** Copyright (C) 2021 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQuick module 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 QACCESSIBLEQUICKWIDGET_H +#define QACCESSIBLEQUICKWIDGET_H + +#include "qquickwidget.h" +#include + +#include + +QT_BEGIN_NAMESPACE + +#if QT_CONFIG(accessibility) + +// These classes implement the QQuickWiget accessibility switcharoo, +// where the child items of the QQuickWidgetOffscreenWindow are reported +// as child accessible interfaces of the QAccessibleQuickWidget. +class QAccessibleQuickWidget: public QAccessibleWidget +{ +public: + QAccessibleQuickWidget(QQuickWidget* widget); + + QAccessibleInterface *child(int index) const override; + int childCount() const override; + int indexOfChild(const QAccessibleInterface *iface) const override; + QAccessibleInterface *childAt(int x, int y) const override; + +private: + QAccessibleQuickWindow m_accessibleWindow; + Q_DISABLE_COPY(QAccessibleQuickWidget) +}; + +class QAccessibleQuickWidgetOffscreenWindow: public QAccessibleQuickWindow +{ +public: + QAccessibleQuickWidgetOffscreenWindow(QQuickWindow *window); + QAccessibleInterface *child(int index) const override; + int childCount() const override; + int indexOfChild(const QAccessibleInterface *iface) const override; + QAccessibleInterface *childAt(int x, int y) const override; +}; + +#endif // accessibility + +QT_END_NAMESPACE + +#endif diff --git a/src/quickwidgets/qaccessiblequickwidgetfactory.cpp b/src/quickwidgets/qaccessiblequickwidgetfactory.cpp new file mode 100644 index 0000000000..3756d0c27c --- /dev/null +++ b/src/quickwidgets/qaccessiblequickwidgetfactory.cpp @@ -0,0 +1,60 @@ +/**************************************************************************** +** +** Copyright (C) 2021 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQuick module 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$ +** +****************************************************************************/ + +#include "qaccessiblequickwidgetfactory_p.h" +#include "qaccessiblequickwidget.h" + +QT_BEGIN_NAMESPACE + +#if QT_CONFIG(accessibility) + +QAccessibleInterface *qAccessibleQuickWidgetFactory(const QString &classname, QObject *object) +{ + if (classname == QLatin1String("QQuickWidget")) { + return new QAccessibleQuickWidget(qobject_cast(object)); + } else if (classname == QLatin1String("QQuickWidgetOffscreenWindow")) { + return new QAccessibleQuickWidgetOffscreenWindow(qobject_cast(object)); + } + return 0; +} + +#endif // accessibility + +QT_END_NAMESPACE + diff --git a/src/quickwidgets/qaccessiblequickwidgetfactory_p.h b/src/quickwidgets/qaccessiblequickwidgetfactory_p.h new file mode 100644 index 0000000000..8c63b09f81 --- /dev/null +++ b/src/quickwidgets/qaccessiblequickwidgetfactory_p.h @@ -0,0 +1,66 @@ +/**************************************************************************** +** +** Copyright (C) 2021 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQuick module 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$ +** +****************************************************************************/ + +#include + +#ifndef QACCESSIBLEQUICKWIDGETFACTORY_H +#define QACCESSIBLEQUICKWIDGETFACTORY_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. +// + +QT_BEGIN_NAMESPACE + +#if QT_CONFIG(accessibility) + +QAccessibleInterface *qAccessibleQuickWidgetFactory(const QString &classname, QObject *object); + +#endif + +QT_END_NAMESPACE + +#endif diff --git a/src/quickwidgets/qquickwidget.cpp b/src/quickwidgets/qquickwidget.cpp index c791f209cf..b0117683f7 100644 --- a/src/quickwidgets/qquickwidget.cpp +++ b/src/quickwidgets/qquickwidget.cpp @@ -39,6 +39,7 @@ #include "qquickwidget.h" #include "qquickwidget_p.h" +#include "qaccessiblequickwidgetfactory_p.h" #include "private/qquickwindow_p.h" #include "private/qquickitem_p.h" @@ -75,9 +76,16 @@ QT_BEGIN_NAMESPACE +QQuickWidgetOffscreenWindow::QQuickWidgetOffscreenWindow(QQuickWindowPrivate &dd, QQuickRenderControl *control) +:QQuickWindow(dd, control) +{ + setTitle(QString::fromLatin1("Offscreen")); + setObjectName(QString::fromLatin1("QQuickOffScreenWindow")); +} + // override setVisble to prevent accidental offscreen window being created // by base class. -class QQuickOffcreenWindowPrivate: public QQuickWindowPrivate { +class QQuickWidgetOffscreenWindowPrivate: public QQuickWindowPrivate { public: void setVisible(bool visible) override { Q_Q(QWindow); @@ -105,10 +113,8 @@ void QQuickWidgetPrivate::init(QQmlEngine* e) Q_Q(QQuickWidget); renderControl = new QQuickWidgetRenderControl(q); - offscreenWindow = new QQuickWindow(*new QQuickOffcreenWindowPrivate(),renderControl); + offscreenWindow = new QQuickWidgetOffscreenWindow(*new QQuickWidgetOffscreenWindowPrivate(), renderControl); offscreenWindow->setScreen(q->screen()); - offscreenWindow->setTitle(QString::fromLatin1("Offscreen")); - offscreenWindow->setObjectName(QString::fromLatin1("QQuickOffScreenWindow")); // Do not call create() on offscreenWindow. // Check if the Software Adaptation is being used @@ -139,6 +145,10 @@ void QQuickWidgetPrivate::init(QQmlEngine* e) QWidget::connect(offscreenWindow, &QQuickWindow::focusObjectChanged, q, &QQuickWidget::propagateFocusObjectChanged); QObject::connect(renderControl, SIGNAL(renderRequested()), q, SLOT(triggerUpdate())); QObject::connect(renderControl, SIGNAL(sceneChanged()), q, SLOT(triggerUpdate())); + +#if QT_CONFIG(accessibility) + QAccessible::installFactory(&qAccessibleQuickWidgetFactory); +#endif } void QQuickWidgetPrivate::ensureEngine() const diff --git a/src/quickwidgets/qquickwidget_p.h b/src/quickwidgets/qquickwidget_p.h index 881f7f9220..1a946bcc71 100644 --- a/src/quickwidgets/qquickwidget_p.h +++ b/src/quickwidgets/qquickwidget_p.h @@ -148,6 +148,14 @@ public: bool forceFullUpdate; }; +class QQuickWidgetOffscreenWindow: public QQuickWindow +{ + Q_OBJECT + +public: + QQuickWidgetOffscreenWindow(QQuickWindowPrivate &dd, QQuickRenderControl *control); +}; + QT_END_NAMESPACE #endif // QQuickWidget_P_H diff --git a/src/quickwidgets/quickwidgets.pro b/src/quickwidgets/quickwidgets.pro index 2438e577ae..f46deb54ac 100644 --- a/src/quickwidgets/quickwidgets.pro +++ b/src/quickwidgets/quickwidgets.pro @@ -7,9 +7,13 @@ DEFINES += QT_NO_URL_CAST_FROM_STRING QT_NO_INTEGER_EVENT_COORDINATES QT_NO_FO HEADERS += \ qquickwidget.h \ qquickwidget_p.h \ - qtquickwidgetsglobal.h + qtquickwidgetsglobal.h \ + qaccessiblequickwidget.h \ + qaccessiblequickwidgetfactory_p.h SOURCES += \ - qquickwidget.cpp + qquickwidget.cpp \ + qaccessiblequickwidget.cpp \ + qaccessiblequickwidgetfactory.cpp load(qt_module) -- 2.49.0 From 646152bc85f1586a2e958d5279a90213e4a7d658 Mon Sep 17 00:00:00 2001 From: Fushan Wen Date: Sat, 5 Nov 2022 01:44:30 +0800 Subject: [PATCH 09/21] Send ObjectShow event for visible components after initialized MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently ObjectShow event is only sent when the visible property changes from false to true, but for items with the notification accessible role, a screen reader like Orca needs to receive an ObjectShow event to read the notification, so also send the event after a component is initialized. See also: https://gitlab.gnome.org/GNOME/orca/-/merge_requests/134 Pick-to: 6.4 Change-Id: I626594b65ffe4d0582dcee9f489df0c2c63e53b7 Reviewed-by: Jan Arve Sæther (cherry picked from commit 9a4f2d23ecec2c7ff19f83cff28df6b97e3fda98) --- src/quick/items/qquickitem.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp index c655b4c327..1e9d3a5cb7 100644 --- a/src/quick/items/qquickitem.cpp +++ b/src/quick/items/qquickitem.cpp @@ -5126,6 +5126,13 @@ void QQuickItem::componentComplete() d->addToDirtyList(); QQuickWindowPrivate::get(d->window)->dirtyItem(this); } + +#if QT_CONFIG(accessibility) + if (d->isAccessible && d->effectiveVisible) { + QAccessibleEvent ev(this, QAccessible::ObjectShow); + QAccessible::updateAccessibility(&ev); + } +#endif } QQuickStateGroup *QQuickItemPrivate::_states() -- 2.49.0 From fa676c3d3a33ef8fe989aa0b69b447a5ded72139 Mon Sep 17 00:00:00 2001 From: Volker Hilsheimer Date: Wed, 9 Nov 2022 15:34:11 +0100 Subject: [PATCH 10/21] QQuickItem: avoid emitting signals during destruction If a QQuickItem is in the QQuickItem destructor, then it is both unsafe and unnecessary to emit property change notifications. Connected code can no longer rely on the state of the emitting object - if it was originally a subclass of QQuickItem, then those subclass destructors will already have run. And the QQuickItem destructor will also have partially run, leaving the object in an undefined state. Add a flag that we set to true at the top of ~QQuickItem, and don't emit visibleChildrenChanged, parentChanged, visibleChanged, and childrenChanged for items that are partially destroyed already. [ChangeLog][Qt Quick][QQuickItem] QQuickItem no longer emits change notifications for the parent, children, visible, and visibleChildren properties while it is being destroyed. Task-number: QTBUG-107850 Change-Id: I36ea98842c89ad89fcc1c4a328d138f66f2a0446 Reviewed-by: Shawn Rutledge Reviewed-by: Mitch Curtis (cherry picked from commit 74873324bdf3399753f9fcaf7461c0e00df628b1) --- src/quick/items/qquickitem.cpp | 21 +++++++++++++-------- src/quick/items/qquickitem_p.h | 1 + 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp index 1e9d3a5cb7..2627494bdd 100644 --- a/src/quick/items/qquickitem.cpp +++ b/src/quick/items/qquickitem.cpp @@ -2328,6 +2328,7 @@ QQuickItem::QQuickItem(QQuickItemPrivate &dd, QQuickItem *parent) QQuickItem::~QQuickItem() { Q_D(QQuickItem); + d->inDestructor = true; if (d->windowRefCount > 1) d->windowRefCount = 1; // Make sure window is set to null in next call to derefWindow(). @@ -2695,9 +2696,8 @@ void QQuickItem::setParentItem(QQuickItem *parentItem) const bool wasVisible = isVisible(); op->removeChild(this); - if (wasVisible) { + if (wasVisible && !op->inDestructor) emit oldParentItem->visibleChildrenChanged(); - } } else if (d->window) { QQuickWindowPrivate::get(d->window)->parentlessItems.remove(this); } @@ -2774,8 +2774,9 @@ void QQuickItem::setParentItem(QQuickItem *parentItem) d->itemChange(ItemParentHasChanged, d->parentItem); - emit parentChanged(d->parentItem); - if (isVisible() && d->parentItem) + if (!d->inDestructor) + emit parentChanged(d->parentItem); + if (isVisible() && d->parentItem && !QQuickItemPrivate::get(d->parentItem)->inDestructor) emit d->parentItem->visibleChildrenChanged(); } @@ -2971,7 +2972,8 @@ void QQuickItemPrivate::removeChild(QQuickItem *child) itemChange(QQuickItem::ItemChildRemovedChange, child); - emit q->childrenChanged(); + if (!inDestructor) + emit q->childrenChanged(); } void QQuickItemPrivate::refWindow(QQuickWindow *c) @@ -3200,6 +3202,7 @@ QQuickItemPrivate::QQuickItemPrivate() , touchEnabled(false) #endif , hasCursorHandler(false) + , inDestructor(false) , dirtyAttributes(0) , nextDirtyItem(nullptr) , prevDirtyItem(nullptr) @@ -6119,9 +6122,11 @@ bool QQuickItemPrivate::setEffectiveVisibleRecur(bool newEffectiveVisible) QAccessible::updateAccessibility(&ev); } #endif - emit q->visibleChanged(); - if (childVisibilityChanged) - emit q->visibleChildrenChanged(); + if (!inDestructor) { + emit q->visibleChanged(); + if (childVisibilityChanged) + emit q->visibleChildrenChanged(); + } return true; // effective visibility DID change } diff --git a/src/quick/items/qquickitem_p.h b/src/quick/items/qquickitem_p.h index d48b551064..6f329bd119 100644 --- a/src/quick/items/qquickitem_p.h +++ b/src/quick/items/qquickitem_p.h @@ -472,6 +472,7 @@ public: bool replayingPressEvent:1; bool touchEnabled:1; bool hasCursorHandler:1; + quint32 inDestructor:1; // has entered ~QQuickItem enum DirtyType { TransformOrigin = 0x00000001, -- 2.49.0 From 54a95a6307e0276bdd3e463108501dfb3c4826c1 Mon Sep 17 00:00:00 2001 From: Harald Sitter Date: Mon, 28 Nov 2022 14:59:33 +0100 Subject: [PATCH 11/21] a11y: track item enabled state MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit disabled items are neither enabled nor focusable Change-Id: I4f286c7b85605d5ad6fa787d1f5cfcce1297d268 Reviewed-by: Volker Hilsheimer Reviewed-by: Jan Arve Sæther (cherry picked from commit 20fd2902a6d7bdb4a3306005d2718ca5a8fef96d) --- src/quick/accessible/qaccessiblequickitem.cpp | 4 ++++ src/quick/items/qquickitem.cpp | 9 +++++++++ 2 files changed, 13 insertions(+) diff --git a/src/quick/accessible/qaccessiblequickitem.cpp b/src/quick/accessible/qaccessiblequickitem.cpp index 4d9e307a48..99e6eff7c3 100644 --- a/src/quick/accessible/qaccessiblequickitem.cpp +++ b/src/quick/accessible/qaccessiblequickitem.cpp @@ -215,6 +215,10 @@ QAccessible::State QAccessibleQuickItem::state() const if (role() == QAccessible::EditableText) if (auto ti = qobject_cast(item())) state.passwordEdit = ti->echoMode() != QQuickTextInput::Normal; + if (!item()->isEnabled()) { + state.focusable = false; + state.disabled = true; + } return state; } diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp index 2627494bdd..8b139cb539 100644 --- a/src/quick/items/qquickitem.cpp +++ b/src/quick/items/qquickitem.cpp @@ -6175,6 +6175,15 @@ void QQuickItemPrivate::setEffectiveEnableRecur(QQuickItem *scope, bool newEffec } itemChange(QQuickItem::ItemEnabledHasChanged, effectiveEnable); +#if QT_CONFIG(accessibility) + if (isAccessible) { + QAccessible::State changedState; + changedState.disabled = true; + changedState.focusable = true; + QAccessibleStateChangeEvent ev(q, changedState); + QAccessible::updateAccessibility(&ev); + } +#endif emit q->enabledChanged(); } -- 2.49.0 From 37b588026cd2e9b6ab3d4fc374be8583432bbcc9 Mon Sep 17 00:00:00 2001 From: Fabian Kosmale Date: Tue, 1 Jun 2021 16:40:44 +0200 Subject: [PATCH 12/21] Make QaccessibleQuickWidget private API Its base class is private API, so it should be private API, too. Change-Id: Ic80f841fee19ed0305c60ad5f8e9349a05f09e5e Reviewed-by: Alexandru Croitor Reviewed-by: Ulf Hermann Reviewed-by: Qt CI Bot (cherry picked from commit a4fa74d3e7581cb5c6bb82223ee17257f66fa41d) --- src/quickwidgets/qaccessiblequickwidget.cpp | 2 +- ...ssiblequickwidget.h => qaccessiblequickwidget_p.h} | 11 +++++++++++ src/quickwidgets/qaccessiblequickwidgetfactory.cpp | 2 +- src/quickwidgets/quickwidgets.pro | 2 +- 4 files changed, 14 insertions(+), 3 deletions(-) rename src/quickwidgets/{qaccessiblequickwidget.h => qaccessiblequickwidget_p.h} (92%) diff --git a/src/quickwidgets/qaccessiblequickwidget.cpp b/src/quickwidgets/qaccessiblequickwidget.cpp index 6f04d6693f..8a1c901880 100644 --- a/src/quickwidgets/qaccessiblequickwidget.cpp +++ b/src/quickwidgets/qaccessiblequickwidget.cpp @@ -37,7 +37,7 @@ ** ****************************************************************************/ -#include "qaccessiblequickwidget.h" +#include "qaccessiblequickwidget_p.h" #include "qquickwidget_p.h" diff --git a/src/quickwidgets/qaccessiblequickwidget.h b/src/quickwidgets/qaccessiblequickwidget_p.h similarity index 92% rename from src/quickwidgets/qaccessiblequickwidget.h rename to src/quickwidgets/qaccessiblequickwidget_p.h index 1f52c78c46..7c2ab930e0 100644 --- a/src/quickwidgets/qaccessiblequickwidget.h +++ b/src/quickwidgets/qaccessiblequickwidget_p.h @@ -40,6 +40,17 @@ #ifndef QACCESSIBLEQUICKWIDGET_H #define QACCESSIBLEQUICKWIDGET_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 "qquickwidget.h" #include diff --git a/src/quickwidgets/qaccessiblequickwidgetfactory.cpp b/src/quickwidgets/qaccessiblequickwidgetfactory.cpp index 3756d0c27c..7ba88a1769 100644 --- a/src/quickwidgets/qaccessiblequickwidgetfactory.cpp +++ b/src/quickwidgets/qaccessiblequickwidgetfactory.cpp @@ -38,7 +38,7 @@ ****************************************************************************/ #include "qaccessiblequickwidgetfactory_p.h" -#include "qaccessiblequickwidget.h" +#include "qaccessiblequickwidget_p.h" QT_BEGIN_NAMESPACE diff --git a/src/quickwidgets/quickwidgets.pro b/src/quickwidgets/quickwidgets.pro index f46deb54ac..85d156b8a3 100644 --- a/src/quickwidgets/quickwidgets.pro +++ b/src/quickwidgets/quickwidgets.pro @@ -8,7 +8,7 @@ HEADERS += \ qquickwidget.h \ qquickwidget_p.h \ qtquickwidgetsglobal.h \ - qaccessiblequickwidget.h \ + qaccessiblequickwidget_p.h \ qaccessiblequickwidgetfactory_p.h SOURCES += \ -- 2.49.0 From b1fbbbcb6b0168946170a450ca01b09169b89e66 Mon Sep 17 00:00:00 2001 From: Jaeyoon Jung Date: Fri, 19 Feb 2021 08:11:57 +0900 Subject: [PATCH 13/21] QQmlImportDatabase: Make sure the newly added import path be first If it already exists in the import list, move it to the first place. This is as per the description of QQmlEngine::addImportPath: | The newly added path will be first in the importPathList(). Change-Id: I782d355c46ada2a46cff72e63326208f39028e01 Reviewed-by: Ulf Hermann (cherry picked from commit 3e413803c698d21f398daf0450c8f501204eb167) --- src/qml/qml/qqmlimport.cpp | 9 ++++++--- tests/auto/qml/qqmlimport/tst_qqmlimport.cpp | 5 +++++ 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/qml/qml/qqmlimport.cpp b/src/qml/qml/qqmlimport.cpp index e7263d1850..289f11d006 100644 --- a/src/qml/qml/qqmlimport.cpp +++ b/src/qml/qml/qqmlimport.cpp @@ -2119,9 +2119,12 @@ void QQmlImportDatabase::addImportPath(const QString& path) cPath.replace(Backslash, Slash); } - if (!cPath.isEmpty() - && !fileImportPath.contains(cPath)) - fileImportPath.prepend(cPath); + if (!cPath.isEmpty()) { + if (fileImportPath.contains(cPath)) + fileImportPath.move(fileImportPath.indexOf(cPath), 0); + else + fileImportPath.prepend(cPath); + } } /*! diff --git a/tests/auto/qml/qqmlimport/tst_qqmlimport.cpp b/tests/auto/qml/qqmlimport/tst_qqmlimport.cpp index 9c865b3f73..1f788f7a7f 100644 --- a/tests/auto/qml/qqmlimport/tst_qqmlimport.cpp +++ b/tests/auto/qml/qqmlimport/tst_qqmlimport.cpp @@ -154,6 +154,11 @@ void tst_QQmlImport::importPathOrder() engine.addImportPath(QT_QMLTEST_DATADIR); expectedImportPaths.prepend(QT_QMLTEST_DATADIR); QCOMPARE(expectedImportPaths, engine.importPathList()); + + // Add qml2Imports again to make it the first of the list + engine.addImportPath(qml2Imports); + expectedImportPaths.move(expectedImportPaths.indexOf(qml2Imports), 0); + QCOMPARE(expectedImportPaths, engine.importPathList()); } Q_DECLARE_METATYPE(QQmlImports::ImportVersion) -- 2.49.0 From cfae55e0beaf6636233f55940c50f82d1d5a4b96 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Wed, 29 Mar 2023 16:36:03 +0200 Subject: [PATCH 14/21] Models: Avoid crashes when deleting cache items Pick-to: 6.5 6.2 5.15 Fixes: QTBUG-91425 Change-Id: I58cf9ee29922f83fc6621f771b80ed557b31f106 Reviewed-by: Shawn Rutledge Reviewed-by: Fabian Kosmale (cherry picked from commit 0cfdecba54e4f40468c4c9a8a6668cc1bc0eff65) * asturmlechner 2023-04-08: Resolve conflict with dev branch commit c2d490a2385ea6f389340a296acaac0fa198c8b9 (qAsConst to std::as_const) --- .../qml/qqmldelegatemodel/tst_qqmldelegatemodel.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/tests/auto/qml/qqmldelegatemodel/tst_qqmldelegatemodel.cpp b/tests/auto/qml/qqmldelegatemodel/tst_qqmldelegatemodel.cpp index e128d77c52..e5daf2d28b 100644 --- a/tests/auto/qml/qqmldelegatemodel/tst_qqmldelegatemodel.cpp +++ b/tests/auto/qml/qqmldelegatemodel/tst_qqmldelegatemodel.cpp @@ -51,6 +51,7 @@ private slots: void contextAccessedByHandler(); void deleteRace(); void redrawUponColumnChange(); + void deleteRace(); }; class AbstractItemModel : public QAbstractItemModel @@ -214,6 +215,17 @@ void tst_QQmlDelegateModel::redrawUponColumnChange() QCOMPARE(item->property("text").toString(), "Coconut"); } +void tst_QQmlDelegateModel::deleteRace() +{ + QQmlEngine engine; + QQmlComponent c(&engine, testFileUrl("deleteRace.qml")); + QVERIFY2(c.isReady(), qPrintable(c.errorString())); + QScopedPointer o(c.create()); + QVERIFY(!o.isNull()); + QTRY_COMPARE(o->property("count").toInt(), 2); + QTRY_COMPARE(o->property("count").toInt(), 0); +} + QTEST_MAIN(tst_QQmlDelegateModel) #include "tst_qqmldelegatemodel.moc" -- 2.49.0 From f13592522e51087059442c254d22b582c7baa776 Mon Sep 17 00:00:00 2001 From: Maximilian Goldstein Date: Wed, 9 Jun 2021 15:02:45 +0200 Subject: [PATCH 15/21] qv4function: Fix crash due to reference being invalidated Function::updateInternalClass creates a reference to a QStringList that is appended to before being used. This is unsafe and can leads to a segfault if the append() causes a reallocation. Fixes: QTBUG-94360 Pick-to: 5.15 6.1 6.2 Change-Id: Iac49e8d816cf440ca2b70e133c88314eb8df6b91 Reviewed-by: Fabian Kosmale Reviewed-by: Andrei Golubev (cherry picked from commit 7fa28f98824a94396106eadfc028b329985a0cfc) --- src/qml/jsruntime/qv4function.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qml/jsruntime/qv4function.cpp b/src/qml/jsruntime/qv4function.cpp index cf8a53cf9f..223e64271e 100644 --- a/src/qml/jsruntime/qv4function.cpp +++ b/src/qml/jsruntime/qv4function.cpp @@ -136,7 +136,7 @@ void Function::updateInternalClass(ExecutionEngine *engine, const QList Date: Tue, 29 Mar 2022 10:44:04 +0200 Subject: [PATCH 16/21] Quick Animations: Fix crash SwipeDelegate causes the running animation job to be deleted when calling swipe.close in swipe.completed. Employ the RETURN_IF_DELETED check in more places to avoid crashes. Fixes: QTBUG-100560 Task-number: QTBUG-103223 Pick-to: 6.3 6.2 5.15 Change-Id: I276eeaa9aed1bdb36449b322a24641fa02c4d5e4 Reviewed-by: Ulf Hermann (cherry picked from commit 0238af0bd48b831d72126f2228d5913eccf67bae) * asturmlechner 2023-04-09: Resolve conflict with dev branch commit 4938984f9a779192264757a06e6ca555fc8f5e91 --- .../swipedelegate/CloseOnCompletedWorks.qml | 74 +++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 tests/manual/quickcontrols2/swipedelegate/CloseOnCompletedWorks.qml diff --git a/tests/manual/quickcontrols2/swipedelegate/CloseOnCompletedWorks.qml b/tests/manual/quickcontrols2/swipedelegate/CloseOnCompletedWorks.qml new file mode 100644 index 0000000000..38dfde41c3 --- /dev/null +++ b/tests/manual/quickcontrols2/swipedelegate/CloseOnCompletedWorks.qml @@ -0,0 +1,74 @@ +/**************************************************************************** +** +** Copyright (C) 2022 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:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2 +import QtQuick.Controls 2 +ApplicationWindow { + visible: true + width: 640 + height: 480 + + ListView { + anchors.fill: parent + model: 2 + + delegate: SwipeDelegate { + text: "Swipe me left (should not crash)" + + swipe.right: Label { + text: "Release (should not crash)" + } + + swipe.onCompleted: { + swipe.close() + } + } + } +} -- 2.49.0 From 3329a68014f64332636ac96e2c352e99d2caaadd Mon Sep 17 00:00:00 2001 From: Joni Poikelin Date: Thu, 3 Sep 2020 14:22:26 +0300 Subject: [PATCH 17/21] Prevent crash when destroying asynchronous Loader Fixes: QTBUG-86255 Pick-to: 5.15 Change-Id: I30488b64d910a1409a43e2e98ee7ab084aec33d2 Reviewed-by: Ulf Hermann (cherry picked from commit 149c1dd07b54ee0c027d94a49d52160dc4f4e2ac) * asturmlechner 2023-01-06: Resolve conflict with dev branch commits d51c007ecc8aa6256cb95cf3992e5ac34a70fa3f and b2a4a61e8cb0839ba293783ac03c72f35c7b1307 --- src/qml/qml/qqmlvmemetaobject.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qml/qml/qqmlvmemetaobject.cpp b/src/qml/qml/qqmlvmemetaobject.cpp index 4fd2092fd3..0d59d197dc 100644 --- a/src/qml/qml/qqmlvmemetaobject.cpp +++ b/src/qml/qml/qqmlvmemetaobject.cpp @@ -254,7 +254,7 @@ void QQmlVMEMetaObjectEndpoint::tryConnect() if (!pd) return; - if (pd->notifyIndex() != -1) + if (pd->notifyIndex() != -1 && ctxt->engine) connect(target, pd->notifyIndex(), ctxt->engine); } -- 2.49.0 From abdead2f5daef5aabe72882cb8005495dd93855b Mon Sep 17 00:00:00 2001 From: Volker Hilsheimer Date: Fri, 18 Nov 2022 14:20:20 +0100 Subject: [PATCH 18/21] QQuickItem: Fix effective visibility for items without parent Items are visible if they are children of a visible parent, and not explicitly hidden. The effectiveVisible member stores the state and is updated when conditions that impact the item visibility changes. The old code returned true for items outside a visual hierarchy, which broke signal emission when items were removed from a parent, e.g. because the parent got destroyed. With this change, items removed from a visual hierarchy will emit the visibleChanged signal. Note: QQuickItem initializes the effectiveVisible member to true, even if the item was created without parent item. Visual items are required to be added to a visual hierarchy via setParentItem. For this reason, newly created items never emit visibleChanged when they are added to a parent. Adjust the QQuickItem::visible test - it creates an item hierarchy without window. Such items are never visible, so add a window and parent the test item hierarchy to the window's content item. This fixes the expected failures in the tests. It does introduce an incompatibility with QGraphicsView and QGraphicsItem, which continue to return true from QGraphicsItem::isVisible for items that are not in an item hierarchy. [ChangeLog][Qt Quick][QQuickItem] The visible property of Items without a parent now always returns false, and the visibleChanged signal gets emitted when the parent item of a visible item becomes null. Fixes: QTBUG-108213 Change-Id: If4b2947cefd1407853f0f29e6c3fdbd49fc9af65 Reviewed-by: Fabian Kosmale Reviewed-by: Shawn Rutledge (cherry picked from commit d1b9a4cacfb966cf0a37983d8f8044f3aedf5de3) CCBUG: 467909 CCBUG: 396359 --- src/quick/items/qquickitem.cpp | 6 ++---- tests/auto/quick/qquickitem/tst_qquickitem.cpp | 2 ++ 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp index 8b139cb539..a5e91b2b61 100644 --- a/src/quick/items/qquickitem.cpp +++ b/src/quick/items/qquickitem.cpp @@ -6082,10 +6082,8 @@ void QQuickItem::setEnabled(bool e) bool QQuickItemPrivate::calcEffectiveVisible() const { - // XXX todo - Should the effective visible of an element with no parent just be the current - // effective visible? This would prevent pointless re-processing in the case of an element - // moving to/from a no-parent situation, but it is different from what graphics view does. - return explicitVisible && (!parentItem || QQuickItemPrivate::get(parentItem)->effectiveVisible); + // An item is visible if it is a child of a visible parent, and not explicitly hidden. + return explicitVisible && parentItem && QQuickItemPrivate::get(parentItem)->effectiveVisible; } bool QQuickItemPrivate::setEffectiveVisibleRecur(bool newEffectiveVisible) diff --git a/tests/auto/quick/qquickitem/tst_qquickitem.cpp b/tests/auto/quick/qquickitem/tst_qquickitem.cpp index 42348d8dd1..34eefd85e6 100644 --- a/tests/auto/quick/qquickitem/tst_qquickitem.cpp +++ b/tests/auto/quick/qquickitem/tst_qquickitem.cpp @@ -989,7 +989,9 @@ void tst_qquickitem::setParentItem() void tst_qquickitem::visible() { + QQuickWindow window; QQuickItem *root = new QQuickItem; + root->setParentItem(window.contentItem()); QQuickItem *child1 = new QQuickItem; child1->setParentItem(root); -- 2.49.0 From 584e70bc485eb3aff7fe845c441efce24e410820 Mon Sep 17 00:00:00 2001 From: Fushan Wen Date: Fri, 21 Apr 2023 23:38:04 +0800 Subject: [PATCH 19/21] Revert "QQuickItem: Fix effective visibility for items without parent" This breaks applications that use QQmlPropertyList to store QQuickItem and don't set a parentItem for them. Ref: https://github.com/musescore/MuseScore/issues/17276 This reverts commit 45c22a0221937682f4496801a495458a00f76d3a. --- src/quick/items/qquickitem.cpp | 6 ++++-- tests/auto/quick/qquickitem/tst_qquickitem.cpp | 2 -- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp index a5e91b2b61..8b139cb539 100644 --- a/src/quick/items/qquickitem.cpp +++ b/src/quick/items/qquickitem.cpp @@ -6082,8 +6082,10 @@ void QQuickItem::setEnabled(bool e) bool QQuickItemPrivate::calcEffectiveVisible() const { - // An item is visible if it is a child of a visible parent, and not explicitly hidden. - return explicitVisible && parentItem && QQuickItemPrivate::get(parentItem)->effectiveVisible; + // XXX todo - Should the effective visible of an element with no parent just be the current + // effective visible? This would prevent pointless re-processing in the case of an element + // moving to/from a no-parent situation, but it is different from what graphics view does. + return explicitVisible && (!parentItem || QQuickItemPrivate::get(parentItem)->effectiveVisible); } bool QQuickItemPrivate::setEffectiveVisibleRecur(bool newEffectiveVisible) diff --git a/tests/auto/quick/qquickitem/tst_qquickitem.cpp b/tests/auto/quick/qquickitem/tst_qquickitem.cpp index 34eefd85e6..42348d8dd1 100644 --- a/tests/auto/quick/qquickitem/tst_qquickitem.cpp +++ b/tests/auto/quick/qquickitem/tst_qquickitem.cpp @@ -989,9 +989,7 @@ void tst_qquickitem::setParentItem() void tst_qquickitem::visible() { - QQuickWindow window; QQuickItem *root = new QQuickItem; - root->setParentItem(window.contentItem()); QQuickItem *child1 = new QQuickItem; child1->setParentItem(root); -- 2.49.0 From ca6a197c9589c2c9a90f7a02fd7644c9b2f3eb00 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Wed, 8 Feb 2023 12:14:21 +0100 Subject: [PATCH 20/21] QML: Fortify qmlExecuteDeferred some more I don't know how to trigger this, but a recent crash report from the CI shows that we can get there without a valid engine. Pick-to: 6.5 Change-Id: I9f17894da82b8e7eab88181c96dfa8eaf7795523 Reviewed-by: Fabian Kosmale (cherry picked from commit f69b6f0940b178b46ecbaa5f0b4956ac44e8379e) --- src/qml/qml/qqmlengine.cpp | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp index 4337a7f454..5ae937e22f 100644 --- a/src/qml/qml/qqmlengine.cpp +++ b/src/qml/qml/qqmlengine.cpp @@ -1583,17 +1583,22 @@ void qmlExecuteDeferred(QObject *object) { QQmlData *data = QQmlData::get(object); - if (data && !data->deferredData.isEmpty() && !data->wasDeleted(object)) { - QQmlEnginePrivate *ep = QQmlEnginePrivate::get(data->context->engine); + if (!data + || !data->context + || !data->context->engine + || data->deferredData.isEmpty() + || data->wasDeleted(object)) { + return; + } - QQmlComponentPrivate::DeferredState state; - QQmlComponentPrivate::beginDeferred(ep, object, &state); + QQmlEnginePrivate *ep = QQmlEnginePrivate::get(data->context->engine); + QQmlComponentPrivate::DeferredState state; + QQmlComponentPrivate::beginDeferred(ep, object, &state); - // Release the reference for the deferral action (we still have one from construction) - data->releaseDeferredData(); + // Release the reference for the deferral action (we still have one from construction) + data->releaseDeferredData(); - QQmlComponentPrivate::completeDeferred(ep, &state); - } + QQmlComponentPrivate::completeDeferred(ep, &state); } QQmlContext *qmlContext(const QObject *obj) -- 2.49.0 From 11ea94fc8ea95d0ba95745a021a1b139283b8b36 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Mon, 10 Jul 2023 07:43:28 +0200 Subject: [PATCH 21/21] QtQml: Clean up QQmlData ctor MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Initialize the "dummy" member even though we never use it. Static analyzers complain about it and we may appreciate it having a defined value in the future. Also, initialize other members inline where possible. Coverity-Id: 415867 Change-Id: Ie428eb3294d6363afe9d7ab2d2bed6e52df0b304 Reviewed-by: Olivier De Cannière Reviewed-by: Fabian Kosmale (cherry picked from commit 10985a568db8cfb4140140967f7d247627ec4350) * asturmlechner 2023-08-12: Resolve conflicts with dev branch commits 10985a568db8cfb4140140967f7d247627ec4350 and e5246cafffb93f69a49c133210390c253fcb71f2 and d3b3fef5a878d7fd53de6a9f9fff196a273930e3 --- src/qml/qml/qqmldata_p.h | 20 ++++++++++---------- src/qml/qml/qqmlengine.cpp | 7 ++----- 2 files changed, 12 insertions(+), 15 deletions(-) diff --git a/src/qml/qml/qqmldata_p.h b/src/qml/qml/qqmldata_p.h index c44fb8608e..69dac27c9a 100644 --- a/src/qml/qml/qqmldata_p.h +++ b/src/qml/qml/qqmldata_p.h @@ -185,7 +185,7 @@ public: private: void layout(QQmlNotifierEndpoint*); }; - QAtomicPointer notifyList; + QAtomicPointer notifyList = nullptr; inline QQmlNotifierEndpoint *notify(int index) const; void addNotify(int index, QQmlNotifierEndpoint *); @@ -201,12 +201,12 @@ public: QQmlContextData *outerContext = nullptr; QQmlContextDataRef ownContext; - QQmlAbstractBinding *bindings; - QQmlBoundSignal *signalHandlers; + QQmlAbstractBinding *bindings = nullptr; + QQmlBoundSignal *signalHandlers = nullptr; // Linked list for QQmlContext::contextObjects - QQmlData *nextContextObject; - QQmlData**prevContextObject; + QQmlData *nextContextObject = nullptr; + QQmlData**prevContextObject = nullptr; inline bool hasBindingBit(int) const; inline void setBindingBit(QObject *obj, int); @@ -216,10 +216,10 @@ public: inline void setPendingBindingBit(QObject *obj, int); inline void clearPendingBindingBit(int); - quint16 lineNumber; - quint16 columnNumber; + quint16 lineNumber = 0; + quint16 columnNumber = 0; - quint32 jsEngineId; // id of the engine that created the jsWrapper + quint32 jsEngineId = 0; // id of the engine that created the jsWrapper struct DeferredData { DeferredData(); @@ -240,7 +240,7 @@ public: QQmlPropertyCache *propertyCache; - QQmlGuardImpl *guards; + QQmlGuardImpl *guards = 0; static QQmlData *get(const QObject *object, bool create = false) { QObjectPrivate *priv = QObjectPrivate::get(const_cast(object)); @@ -289,7 +289,7 @@ public: private: // For attachedProperties - mutable QQmlDataExtended *extendedData; + mutable QQmlDataExtended *extendedData = nullptr; Q_NEVER_INLINE static QQmlData *createQQmlData(QObjectPrivate *priv); Q_NEVER_INLINE static QQmlPropertyCache *createPropertyCache(QJSEngine *engine, QObject *object); diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp index 5ae937e22f..afb117d36e 100644 --- a/src/qml/qml/qqmlengine.cpp +++ b/src/qml/qml/qqmlengine.cpp @@ -719,11 +719,8 @@ void QQmlPrivate::qdeclarativeelement_destructor(QObject *o) QQmlData::QQmlData() : ownedByQml1(false), ownMemory(true), indestructible(true), explicitIndestructibleSet(false), hasTaintedV4Object(false), isQueuedForDeletion(false), rootObjectInCreation(false), - hasInterceptorMetaObject(false), hasVMEMetaObject(false), parentFrozen(false), - bindingBitsArraySize(InlineBindingArraySize), notifyList(nullptr), - bindings(nullptr), signalHandlers(nullptr), nextContextObject(nullptr), prevContextObject(nullptr), - lineNumber(0), columnNumber(0), jsEngineId(0), - propertyCache(nullptr), guards(nullptr), extendedData(nullptr) + hasInterceptorMetaObject(false), hasVMEMetaObject(false), parentFrozen(false), dummy(0), + bindingBitsArraySize(InlineBindingArraySize), propertyCache(nullptr) { memset(bindingBitsValue, 0, sizeof(bindingBitsValue)); init(); -- 2.49.0