aboutsummaryrefslogtreecommitdiffstats
path: root/src/quick
diff options
context:
space:
mode:
Diffstat (limited to 'src/quick')
-rw-r--r--src/quick/accessible/qaccessiblequickitem.cpp24
-rw-r--r--src/quick/accessible/qaccessiblequickview.cpp6
-rw-r--r--src/quick/designer/qqmldesignermetaobject.cpp6
-rw-r--r--src/quick/designer/qquickdesignersupportitems.cpp2
-rw-r--r--src/quick/doc/images/pointerHandlers/dragReleaseMenu.webpbin0 -> 86252 bytes
-rw-r--r--src/quick/doc/images/pointerHandlers/tapHandlerButtonReleaseWithinBounds.webpbin0 -> 53154 bytes
-rw-r--r--src/quick/doc/images/pointerHandlers/tapHandlerButtonWithinBounds.webpbin0 -> 27426 bytes
-rw-r--r--src/quick/doc/images/pointerHandlers/tapHandlerOverlappingButtons.webpbin0 -> 51008 bytes
-rw-r--r--src/quick/doc/snippets/pointerHandlers/dragReleaseMenu.qml72
-rw-r--r--src/quick/doc/snippets/pointerHandlers/pointHandler.qml5
-rw-r--r--src/quick/doc/snippets/pointerHandlers/pointHandlerAcceptedButtons.qml21
-rw-r--r--src/quick/doc/snippets/pointerHandlers/pointHandlerAcceptedModifiers.qml36
-rw-r--r--src/quick/doc/snippets/pointerHandlers/pointHandlerCanvasDrawing.qml54
-rw-r--r--src/quick/doc/snippets/pointerHandlers/pointHandlerMargin.qml36
-rw-r--r--src/quick/doc/snippets/pointerHandlers/tapHandlerButtonReleaseWithinBounds.qml51
-rw-r--r--src/quick/doc/snippets/pointerHandlers/tapHandlerButtonWithinBounds.qml51
-rw-r--r--src/quick/doc/snippets/pointerHandlers/tapHandlerOverlappingButtons.qml51
-rw-r--r--src/quick/doc/snippets/qml/item/itemGrab.qml39
-rw-r--r--src/quick/doc/snippets/qml/itemGrab.qml50
-rw-r--r--src/quick/doc/src/concepts/inputhandlers/qtquickhandlers-index.qdoc3
-rw-r--r--src/quick/doc/src/concepts/visualcanvas/scenegraph.qdoc6
-rw-r--r--src/quick/doc/src/cppextensionpoints.qdoc19
-rw-r--r--src/quick/doc/src/guidelines/qtquick-bestpractices.qdoc27
-rw-r--r--src/quick/doc/src/guidelines/qtquick-tool-qmllint.qdoc4
-rw-r--r--src/quick/doc/src/qmltypereference.qdoc4
-rw-r--r--src/quick/handlers/qquickdraghandler.cpp2
-rw-r--r--src/quick/handlers/qquickhandlerpoint.cpp39
-rw-r--r--src/quick/handlers/qquickhandlerpoint_p.h1
-rw-r--r--src/quick/handlers/qquickhoverhandler.cpp73
-rw-r--r--src/quick/handlers/qquickhoverhandler_p.h4
-rw-r--r--src/quick/handlers/qquickmultipointhandler.cpp12
-rw-r--r--src/quick/handlers/qquickpinchhandler.cpp21
-rw-r--r--src/quick/handlers/qquickpointerdevicehandler.cpp4
-rw-r--r--src/quick/handlers/qquickpointerdevicehandler_p.h7
-rw-r--r--src/quick/handlers/qquickpointerhandler.cpp10
-rw-r--r--src/quick/handlers/qquickpointerhandler_p_p.h4
-rw-r--r--src/quick/handlers/qquickpointhandler.cpp126
-rw-r--r--src/quick/handlers/qquicksinglepointhandler.cpp2
-rw-r--r--src/quick/handlers/qquicktaphandler.cpp132
-rw-r--r--src/quick/handlers/qquickwheelhandler.cpp2
-rw-r--r--src/quick/items/context2d/qquickcanvasitem.cpp4
-rw-r--r--src/quick/items/context2d/qquickcontext2d.cpp2
-rw-r--r--src/quick/items/context2d/qquickcontext2dcommandbuffer_p.h2
-rw-r--r--src/quick/items/context2d/qquickcontext2dtexture.cpp6
-rw-r--r--src/quick/items/qquickaccessibleattached.cpp34
-rw-r--r--src/quick/items/qquickcolorgroup.cpp4
-rw-r--r--src/quick/items/qquickdrag.cpp12
-rw-r--r--src/quick/items/qquickdrag_p.h3
-rw-r--r--src/quick/items/qquickdroparea.cpp2
-rw-r--r--src/quick/items/qquickflickable.cpp66
-rw-r--r--src/quick/items/qquickflickable_p_p.h34
-rw-r--r--src/quick/items/qquickflipable.cpp54
-rw-r--r--src/quick/items/qquickgridview.cpp48
-rw-r--r--src/quick/items/qquickimagebase.cpp4
-rw-r--r--src/quick/items/qquickitem.cpp199
-rw-r--r--src/quick/items/qquickitem_p.h7
-rw-r--r--src/quick/items/qquickitemanimation.cpp16
-rw-r--r--src/quick/items/qquickitemgrabresult.cpp14
-rw-r--r--src/quick/items/qquickitemsmodule.cpp134
-rw-r--r--src/quick/items/qquickitemview.cpp61
-rw-r--r--src/quick/items/qquicklistview.cpp113
-rw-r--r--src/quick/items/qquickloader.cpp2
-rw-r--r--src/quick/items/qquickmousearea.cpp74
-rw-r--r--src/quick/items/qquickmousearea_p_p.h1
-rw-r--r--src/quick/items/qquickmultipointtoucharea.cpp24
-rw-r--r--src/quick/items/qquickmultipointtoucharea_p.h2
-rw-r--r--src/quick/items/qquickpainteditem.cpp2
-rw-r--r--src/quick/items/qquickpalette.cpp10
-rw-r--r--src/quick/items/qquickpathview.cpp44
-rw-r--r--src/quick/items/qquickpincharea.cpp30
-rw-r--r--src/quick/items/qquickpositioners.cpp4
-rw-r--r--src/quick/items/qquickrectangle.cpp9
-rw-r--r--src/quick/items/qquickrendercontrol.cpp6
-rw-r--r--src/quick/items/qquickrendertarget.cpp2
-rw-r--r--src/quick/items/qquickrepeater.cpp20
-rw-r--r--src/quick/items/qquickshadereffect.cpp22
-rw-r--r--src/quick/items/qquickshadereffectmesh.cpp2
-rw-r--r--src/quick/items/qquickspriteengine.cpp47
-rw-r--r--src/quick/items/qquickspriteengine_p.h8
-rw-r--r--src/quick/items/qquickspritesequence.cpp2
-rw-r--r--src/quick/items/qquickstateoperations.cpp2
-rw-r--r--src/quick/items/qquicktableview.cpp238
-rw-r--r--src/quick/items/qquicktableview_p.h6
-rw-r--r--src/quick/items/qquicktableview_p_p.h21
-rw-r--r--src/quick/items/qquicktext.cpp98
-rw-r--r--src/quick/items/qquicktext_p_p.h2
-rw-r--r--src/quick/items/qquicktextcontrol.cpp11
-rw-r--r--src/quick/items/qquicktextdocument.cpp2
-rw-r--r--src/quick/items/qquicktextedit.cpp34
-rw-r--r--src/quick/items/qquicktextedit_p.h1
-rw-r--r--src/quick/items/qquicktextedit_p_p.h8
-rw-r--r--src/quick/items/qquicktextinput.cpp148
-rw-r--r--src/quick/items/qquicktextinput_p_p.h10
-rw-r--r--src/quick/items/qquicktextnode.cpp2
-rw-r--r--src/quick/items/qquicktextnodeengine.cpp11
-rw-r--r--src/quick/items/qquicktreeview.cpp33
-rw-r--r--src/quick/items/qquicktreeview_p.h6
-rw-r--r--src/quick/items/qquickwindow.cpp46
-rw-r--r--src/quick/scenegraph/adaptations/software/qsgsoftwarecontext.cpp12
-rw-r--r--src/quick/scenegraph/adaptations/software/qsgsoftwareinternalrectanglenode.cpp14
-rw-r--r--src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenodeupdater.cpp4
-rw-r--r--src/quick/scenegraph/adaptations/software/qsgsoftwarethreadedrenderloop.cpp2
-rw-r--r--src/quick/scenegraph/compressedtexture/qsgcompressedatlastexture_p.h2
-rw-r--r--src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp28
-rw-r--r--src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h2
-rw-r--r--src/quick/scenegraph/coreapi/qsggeometry.cpp31
-rw-r--r--src/quick/scenegraph/coreapi/qsggeometry.h1
-rw-r--r--src/quick/scenegraph/coreapi/qsgmaterialshader.cpp4
-rw-r--r--src/quick/scenegraph/coreapi/qsgrhivisualizer.cpp4
-rw-r--r--src/quick/scenegraph/coreapi/qsgtexture.cpp4
-rw-r--r--src/quick/scenegraph/qsgadaptationlayer.cpp14
-rw-r--r--src/quick/scenegraph/qsgadaptationlayer_p.h2
-rw-r--r--src/quick/scenegraph/qsgcontextplugin.cpp4
-rw-r--r--src/quick/scenegraph/qsgdefaultglyphnode_p.cpp4
-rw-r--r--src/quick/scenegraph/qsgdefaultrendercontext.cpp15
-rw-r--r--src/quick/scenegraph/qsgdefaultrendercontext_p.h5
-rw-r--r--src/quick/scenegraph/qsgdistancefieldglyphnode.cpp14
-rw-r--r--src/quick/scenegraph/qsgrenderloop.cpp2
-rw-r--r--src/quick/scenegraph/qsgrhidistancefieldglyphcache.cpp27
-rw-r--r--src/quick/scenegraph/qsgrhidistancefieldglyphcache_p.h3
-rw-r--r--src/quick/scenegraph/qsgrhishadereffectnode.cpp70
-rw-r--r--src/quick/scenegraph/qsgrhishadereffectnode_p.h2
-rw-r--r--src/quick/scenegraph/qsgrhisupport.cpp2
-rw-r--r--src/quick/scenegraph/qsgrhitextureglyphcache.cpp25
-rw-r--r--src/quick/scenegraph/qsgrhitextureglyphcache_p.h1
-rw-r--r--src/quick/scenegraph/qsgthreadedrenderloop.cpp3
-rw-r--r--src/quick/util/qquickanimation.cpp50
-rw-r--r--src/quick/util/qquickanimatorcontroller.cpp14
-rw-r--r--src/quick/util/qquickanimatorjob.cpp5
-rw-r--r--src/quick/util/qquickapplication.cpp6
-rw-r--r--src/quick/util/qquickdeliveryagent.cpp280
-rw-r--r--src/quick/util/qquickdeliveryagent_p_p.h2
-rw-r--r--src/quick/util/qquickframeanimation.cpp5
-rw-r--r--src/quick/util/qquickglobal.cpp6
-rw-r--r--src/quick/util/qquickimageprovider.cpp2
-rw-r--r--src/quick/util/qquickpath.cpp52
-rw-r--r--src/quick/util/qquickpixmapcache.cpp21
-rw-r--r--src/quick/util/qquickpropertychanges.cpp12
-rw-r--r--src/quick/util/qquickshortcut.cpp4
-rw-r--r--src/quick/util/qquickshortcut_p.h3
-rw-r--r--src/quick/util/qquicksmoothedanimation.cpp2
-rw-r--r--src/quick/util/qquickstate.cpp24
-rw-r--r--src/quick/util/qquickstate_p_p.h2
-rw-r--r--src/quick/util/qquickstategroup.cpp41
-rw-r--r--src/quick/util/qquickstyledtext.cpp107
-rw-r--r--src/quick/util/qquicksvgparser.cpp2
-rw-r--r--src/quick/util/qquicktimeline.cpp4
-rw-r--r--src/quick/util/qquicktransition.cpp8
-rw-r--r--src/quick/util/qquicktransitionmanager.cpp31
149 files changed, 2658 insertions, 1141 deletions
diff --git a/src/quick/accessible/qaccessiblequickitem.cpp b/src/quick/accessible/qaccessiblequickitem.cpp
index e891b5c132..c47a94e3aa 100644
--- a/src/quick/accessible/qaccessiblequickitem.cpp
+++ b/src/quick/accessible/qaccessiblequickitem.cpp
@@ -46,7 +46,7 @@ public:
QString anchor() const override
{
const QVector<QQuickTextPrivate::LinkDesc> links = QQuickTextPrivate::get(textItem())->getLinks();
- if (linkIndex < links.count())
+ if (linkIndex < links.size())
return links.at(linkIndex).m_anchor;
return QString();
}
@@ -54,7 +54,7 @@ public:
QString anchorTarget() const override
{
const QVector<QQuickTextPrivate::LinkDesc> links = QQuickTextPrivate::get(textItem())->getLinks();
- if (linkIndex < links.count())
+ if (linkIndex < links.size())
return links.at(linkIndex).m_anchorTarget;
return QString();
}
@@ -62,7 +62,7 @@ public:
int startIndex() const override
{
const QVector<QQuickTextPrivate::LinkDesc> links = QQuickTextPrivate::get(textItem())->getLinks();
- if (linkIndex < links.count())
+ if (linkIndex < links.size())
return links.at(linkIndex).m_startIndex;
return -1;
}
@@ -70,7 +70,7 @@ public:
int endIndex() const override
{
const QVector<QQuickTextPrivate::LinkDesc> links = QQuickTextPrivate::get(textItem())->getLinks();
- if (linkIndex < links.count())
+ if (linkIndex < links.size())
return links.at(linkIndex).m_endIndex;
return -1;
}
@@ -113,7 +113,7 @@ QWindow *QAccessibleHyperlink::window() const
QRect QAccessibleHyperlink::rect() const
{
const QVector<QQuickTextPrivate::LinkDesc> links = QQuickTextPrivate::get(textItem())->getLinks();
- if (linkIndex < links.count()) {
+ if (linkIndex < links.size()) {
const QPoint tl = itemScreenRect(textItem()).topLeft();
return links.at(linkIndex).rect.translated(tl);
}
@@ -232,9 +232,9 @@ int QAccessibleQuickItem::childCount() const
// see comment in QAccessibleQuickItem::child() as to why we do this
int cc = 0;
if (QQuickText *textItem = qobject_cast<QQuickText*>(item())) {
- cc = QQuickTextPrivate::get(textItem)->getLinks().count();
+ cc = QQuickTextPrivate::get(textItem)->getLinks().size();
}
- cc += childItems().count();
+ cc += childItems().size();
return cc;
}
@@ -271,7 +271,7 @@ QAccessibleInterface *QAccessibleQuickItem::childAt(int x, int y) const
// special case for text interfaces
if (QQuickText *textItem = qobject_cast<QQuickText*>(item())) {
- const auto hyperLinkChildCount = QQuickTextPrivate::get(textItem)->getLinks().count();
+ const auto hyperLinkChildCount = QQuickTextPrivate::get(textItem)->getLinks().size();
for (auto i = 0; i < hyperLinkChildCount; i++) {
QAccessibleInterface *iface = child(i);
if (iface->rect().contains(x,y)) {
@@ -282,7 +282,7 @@ QAccessibleInterface *QAccessibleQuickItem::childAt(int x, int y) const
// general item hit test
const QList<QQuickItem*> kids = accessibleUnignoredChildren(item(), true);
- for (int i = kids.count() - 1; i >= 0; --i) {
+ for (int i = kids.size() - 1; i >= 0; --i) {
QAccessibleInterface *childIface = QAccessible::queryAccessibleInterface(kids.at(i));
if (QAccessibleInterface *childChild = childIface->childAt(x, y))
return childChild;
@@ -344,7 +344,7 @@ QAccessibleInterface *QAccessibleQuickItem::child(int index) const
if (QQuickText *textItem = qobject_cast<QQuickText*>(item())) {
- const int hyperLinkChildCount = QQuickTextPrivate::get(textItem)->getLinks().count();
+ const int hyperLinkChildCount = QQuickTextPrivate::get(textItem)->getLinks().size();
if (index < hyperLinkChildCount) {
auto it = m_childToId.constFind(index);
if (it != m_childToId.constEnd())
@@ -359,7 +359,7 @@ QAccessibleInterface *QAccessibleQuickItem::child(int index) const
}
QList<QQuickItem *> children = childItems();
- if (index < children.count()) {
+ if (index < children.size()) {
QQuickItem *child = children.at(index);
return QAccessible::queryAccessibleInterface(child);
}
@@ -370,7 +370,7 @@ int QAccessibleQuickItem::indexOfChild(const QAccessibleInterface *iface) const
{
int hyperLinkChildCount = 0;
if (QQuickText *textItem = qobject_cast<QQuickText*>(item())) {
- hyperLinkChildCount = QQuickTextPrivate::get(textItem)->getLinks().count();
+ hyperLinkChildCount = QQuickTextPrivate::get(textItem)->getLinks().size();
if (QAccessibleHyperlinkInterface *hyperLinkIface = const_cast<QAccessibleInterface *>(iface)->hyperlinkInterface()) {
// ### assumes that there is only one subclass implementing QAccessibleHyperlinkInterface
// Alternatively, we could simply iterate with child() and do a linear search for it
diff --git a/src/quick/accessible/qaccessiblequickview.cpp b/src/quick/accessible/qaccessiblequickview.cpp
index 3f327619c8..5cd93b9613 100644
--- a/src/quick/accessible/qaccessiblequickview.cpp
+++ b/src/quick/accessible/qaccessiblequickview.cpp
@@ -28,7 +28,7 @@ QList<QQuickItem *> QAccessibleQuickWindow::rootItems() const
int QAccessibleQuickWindow::childCount() const
{
- return rootItems().count();
+ return rootItems().size();
}
QAccessibleInterface *QAccessibleQuickWindow::parent() const
@@ -40,7 +40,7 @@ QAccessibleInterface *QAccessibleQuickWindow::parent() const
QAccessibleInterface *QAccessibleQuickWindow::child(int index) const
{
const QList<QQuickItem*> &kids = rootItems();
- if (index >= 0 && index < kids.count())
+ if (index >= 0 && index < kids.size())
return QAccessible::queryAccessibleInterface(kids.at(index));
return nullptr;
}
@@ -109,7 +109,7 @@ int QAccessibleQuickWindow::indexOfChild(const QAccessibleInterface *iface) cons
int i = -1;
if (iface) {
const QList<QQuickItem *> &roots = rootItems();
- i = roots.count() - 1;
+ i = roots.size() - 1;
while (i >= 0) {
if (iface->object() == roots.at(i))
break;
diff --git a/src/quick/designer/qqmldesignermetaobject.cpp b/src/quick/designer/qqmldesignermetaobject.cpp
index 4bd221481b..e368f5f443 100644
--- a/src/quick/designer/qqmldesignermetaobject.cpp
+++ b/src/quick/designer/qqmldesignermetaobject.cpp
@@ -17,7 +17,7 @@ static void (*notifyPropertyChangeCallBack)(QObject*, const QQuickDesignerSuppor
struct MetaPropertyData {
inline QPair<QVariant, bool> &getDataRef(int idx) {
- while (m_data.count() <= idx)
+ while (m_data.size() <= idx)
m_data << QPair<QVariant, bool>(QVariant(), false);
return m_data[idx];
}
@@ -32,12 +32,12 @@ struct MetaPropertyData {
}
inline bool hasData(int idx) const {
- if (idx >= m_data.count())
+ if (idx >= m_data.size())
return false;
return m_data[idx].second;
}
- inline int count() { return m_data.count(); }
+ inline int count() { return m_data.size(); }
QVector<QPair<QVariant, bool> > m_data;
};
diff --git a/src/quick/designer/qquickdesignersupportitems.cpp b/src/quick/designer/qquickdesignersupportitems.cpp
index 2ee8984ea1..5887ff951f 100644
--- a/src/quick/designer/qquickdesignersupportitems.cpp
+++ b/src/quick/designer/qquickdesignersupportitems.cpp
@@ -118,7 +118,7 @@ void QQuickDesignerSupportItems::tweakObjects(QObject *object)
{
QObjectList objectList;
allSubObjects(object, objectList);
- for (QObject* childObject : qAsConst(objectList)) {
+ for (QObject* childObject : std::as_const(objectList)) {
stopAnimation(childObject);
makeLoaderSynchronous(childObject);
if (fixResourcePathsForObjectCallBack)
diff --git a/src/quick/doc/images/pointerHandlers/dragReleaseMenu.webp b/src/quick/doc/images/pointerHandlers/dragReleaseMenu.webp
new file mode 100644
index 0000000000..16aaca4d86
--- /dev/null
+++ b/src/quick/doc/images/pointerHandlers/dragReleaseMenu.webp
Binary files differ
diff --git a/src/quick/doc/images/pointerHandlers/tapHandlerButtonReleaseWithinBounds.webp b/src/quick/doc/images/pointerHandlers/tapHandlerButtonReleaseWithinBounds.webp
new file mode 100644
index 0000000000..3edab7d7a1
--- /dev/null
+++ b/src/quick/doc/images/pointerHandlers/tapHandlerButtonReleaseWithinBounds.webp
Binary files differ
diff --git a/src/quick/doc/images/pointerHandlers/tapHandlerButtonWithinBounds.webp b/src/quick/doc/images/pointerHandlers/tapHandlerButtonWithinBounds.webp
new file mode 100644
index 0000000000..05cb2f2276
--- /dev/null
+++ b/src/quick/doc/images/pointerHandlers/tapHandlerButtonWithinBounds.webp
Binary files differ
diff --git a/src/quick/doc/images/pointerHandlers/tapHandlerOverlappingButtons.webp b/src/quick/doc/images/pointerHandlers/tapHandlerOverlappingButtons.webp
new file mode 100644
index 0000000000..0455097159
--- /dev/null
+++ b/src/quick/doc/images/pointerHandlers/tapHandlerOverlappingButtons.webp
Binary files differ
diff --git a/src/quick/doc/snippets/pointerHandlers/dragReleaseMenu.qml b/src/quick/doc/snippets/pointerHandlers/dragReleaseMenu.qml
new file mode 100644
index 0000000000..e6d2266408
--- /dev/null
+++ b/src/quick/doc/snippets/pointerHandlers/dragReleaseMenu.qml
@@ -0,0 +1,72 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+//![0]
+import QtQuick
+
+Rectangle {
+ id: rect
+ width: 140; height: 100
+
+ //![1]
+ TapHandler {
+ id: menuPopupHandler
+ gesturePolicy: TapHandler.DragWithinBounds
+ onPressedChanged:
+ if (pressed) {
+ menu.x = point.position.x - menu.width / 2
+ menu.y = point.position.y - menu.height / 2
+ } else {
+ feedback.text = menu.highlightedMenuItem
+ selectFlash.start()
+ }
+ onCanceled: feedback.text = "canceled"
+ }
+ //![1]
+
+ Column {
+ id: menu
+ visible: menuPopupHandler.pressed
+ opacity: Math.min(1, menuPopupHandler.timeHeld)
+ property string highlightedMenuItem: ""
+ Repeater {
+ model: [ "top", "middle", "bottom" ]
+ delegate: Rectangle {
+ property bool highlighted: menuPopupHandler.pressed &&
+ contains(mapFromItem(rect, menuPopupHandler.point.position))
+ onHighlightedChanged: {
+ if (highlighted)
+ menu.highlightedMenuItem = menuItemText.text
+ else if (menu.highlightedMenuItem === menuItemText.text)
+ menu.highlightedMenuItem = ""
+ }
+ width: 100
+ height: 20
+ color: highlighted ? "lightsteelblue" : "aliceblue"
+ Text {
+ id: menuItemText
+ anchors.centerIn: parent
+ text: modelData
+ }
+ }
+ }
+ }
+
+ Text {
+ id: feedback
+ y: 6; anchors.horizontalCenter: parent.horizontalCenter
+ textFormat: Text.MarkdownText
+ text: "hold for context menu"
+
+ SequentialAnimation on font.weight {
+ id: selectFlash
+ running: false
+ loops: 3
+ PropertyAction { value: Font.Black }
+ PauseAnimation { duration: 100 }
+ PropertyAction { value: Font.Normal }
+ PauseAnimation { duration: 100 }
+ }
+ }
+}
+//![0]
diff --git a/src/quick/doc/snippets/pointerHandlers/pointHandler.qml b/src/quick/doc/snippets/pointerHandlers/pointHandler.qml
index f5fe29566e..d363150ab5 100644
--- a/src/quick/doc/snippets/pointerHandlers/pointHandler.qml
+++ b/src/quick/doc/snippets/pointerHandlers/pointHandler.qml
@@ -1,8 +1,7 @@
// Copyright (C) 2017 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
//![0]
-import QtQuick 2.12
-import QtQuick.Window 2.2
+import QtQuick
Window {
width: 480
@@ -14,6 +13,7 @@ Window {
z: 10000
anchors.fill: parent
+ //![1]
PointHandler {
id: handler
acceptedDevices: PointerDevice.TouchScreen | PointerDevice.TouchPad
@@ -26,6 +26,7 @@ Window {
width: 20; height: width; radius: width / 2
}
}
+ //![1]
}
}
//![0]
diff --git a/src/quick/doc/snippets/pointerHandlers/pointHandlerAcceptedButtons.qml b/src/quick/doc/snippets/pointerHandlers/pointHandlerAcceptedButtons.qml
new file mode 100644
index 0000000000..3eab8b319b
--- /dev/null
+++ b/src/quick/doc/snippets/pointerHandlers/pointHandlerAcceptedButtons.qml
@@ -0,0 +1,21 @@
+// Copyright (C) 2023 Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+//![0]
+import QtQuick
+
+Item {
+ width: 480; height: 320
+
+ Rectangle {
+ color: handler.active ? "tomato" : "wheat"
+ x: handler.point.position.x - width / 2
+ y: handler.point.position.y - height / 2
+ width: 20; height: width; radius: width / 2
+ }
+
+ PointHandler {
+ id: handler
+ acceptedButtons: Qt.MiddleButton | Qt.RightButton
+ }
+}
+//![0]
diff --git a/src/quick/doc/snippets/pointerHandlers/pointHandlerAcceptedModifiers.qml b/src/quick/doc/snippets/pointerHandlers/pointHandlerAcceptedModifiers.qml
new file mode 100644
index 0000000000..9e3cb6f465
--- /dev/null
+++ b/src/quick/doc/snippets/pointerHandlers/pointHandlerAcceptedModifiers.qml
@@ -0,0 +1,36 @@
+// Copyright (C) 2023 Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+//![0]
+import QtQuick
+
+Item {
+ id: feedbackPane
+ width: 480; height: 320
+
+ PointHandler {
+ id: control
+ acceptedModifiers: Qt.ControlModifier
+ cursorShape: Qt.PointingHandCursor
+ target: Rectangle {
+ parent: feedbackPane
+ color: control.active ? "indianred" : "khaki"
+ x: control.point.position.x - width / 2
+ y: control.point.position.y - height / 2
+ width: 20; height: width; radius: width / 2
+ }
+ }
+
+ PointHandler {
+ id: shift
+ acceptedModifiers: Qt.ShiftModifier | Qt.MetaModifier
+ cursorShape: Qt.CrossCursor
+ target: Rectangle {
+ parent: feedbackPane
+ color: shift.active ? "darkslateblue" : "lightseagreen"
+ x: shift.point.position.x - width / 2
+ y: shift.point.position.y - height / 2
+ width: 30; height: width; radius: width / 2
+ }
+ }
+}
+//![0]
diff --git a/src/quick/doc/snippets/pointerHandlers/pointHandlerCanvasDrawing.qml b/src/quick/doc/snippets/pointerHandlers/pointHandlerCanvasDrawing.qml
new file mode 100644
index 0000000000..d04bd4f149
--- /dev/null
+++ b/src/quick/doc/snippets/pointerHandlers/pointHandlerCanvasDrawing.qml
@@ -0,0 +1,54 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+//![0]
+import QtQuick
+
+Canvas {
+ id: canvas
+ width: 800
+ height: 600
+ antialiasing: true
+ renderTarget: Canvas.FramebufferObject
+ property var points: []
+ onPaint: {
+ if (points.length < 2)
+ return
+ var ctx = canvas.getContext('2d');
+ ctx.save()
+ ctx.strokeStyle = stylusHandler.active ? "blue" : "white"
+ ctx.lineCap = "round"
+ ctx.beginPath()
+ ctx.moveTo(points[0].x, points[0].y)
+ for (var i = 1; i < points.length; i++)
+ ctx.lineTo(points[i].x, points[i].y)
+ ctx.lineWidth = 3
+ ctx.stroke()
+ points = points.slice(points.length - 2, 1)
+ ctx.restore()
+ }
+
+ PointHandler {
+ id: stylusHandler
+ acceptedPointerTypes: PointerDevice.Pen
+ onPointChanged: {
+ canvas.points.push(point.position)
+ canvas.requestPaint()
+ }
+ }
+
+ PointHandler {
+ id: eraserHandler
+ acceptedPointerTypes: PointerDevice.Eraser
+ onPointChanged: {
+ canvas.points.push(point.position)
+ canvas.requestPaint()
+ }
+ }
+
+ Rectangle {
+ width: 10; height: 10
+ color: stylusHandler.active ? "green" : eraserHandler.active ? "red" : "beige"
+ }
+}
+//![0]
diff --git a/src/quick/doc/snippets/pointerHandlers/pointHandlerMargin.qml b/src/quick/doc/snippets/pointerHandlers/pointHandlerMargin.qml
new file mode 100644
index 0000000000..1b66531dbf
--- /dev/null
+++ b/src/quick/doc/snippets/pointerHandlers/pointHandlerMargin.qml
@@ -0,0 +1,36 @@
+// Copyright (C) 2023 Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+//![0]
+import QtQuick
+
+Item {
+ width: 480; height: 320
+
+ Rectangle {
+ anchors.fill: handlingContainer
+ anchors.margins: -handler.margin
+ color: "beige"
+ }
+
+ Rectangle {
+ id: handlingContainer
+ width: 200; height: 200
+ anchors.centerIn: parent
+ border.color: "green"
+ color: handler.active ? "lightsteelblue" : "khaki"
+
+ Text {
+ text: "X"
+ x: handler.point.position.x - width / 2
+ y: handler.point.position.y - height / 2
+ visible: handler.active
+ }
+
+ PointHandler {
+ id: handler
+ margin: 30
+ }
+ }
+
+}
+//![0]
diff --git a/src/quick/doc/snippets/pointerHandlers/tapHandlerButtonReleaseWithinBounds.qml b/src/quick/doc/snippets/pointerHandlers/tapHandlerButtonReleaseWithinBounds.qml
new file mode 100644
index 0000000000..3e8634a605
--- /dev/null
+++ b/src/quick/doc/snippets/pointerHandlers/tapHandlerButtonReleaseWithinBounds.qml
@@ -0,0 +1,51 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+//![0]
+import QtQuick
+
+Item {
+ width: 120; height: 80
+
+ component Button : Rectangle {
+ id: button
+ signal clicked
+ property alias text: buttonLabel.text
+
+ width: 80
+ height: 40
+ radius: 3
+ property color dark: Qt.darker(palette.button, 1.3)
+ gradient: Gradient {
+ GradientStop { position: 0.0; color: tapHandler.pressed ? dark : palette.button }
+ GradientStop { position: 1.0; color: dark }
+ }
+
+ SequentialAnimation on border.width {
+ id: tapFlash
+ running: false
+ loops: 3
+ PropertyAction { value: 2 }
+ PauseAnimation { duration: 100 }
+ PropertyAction { value: 0 }
+ PauseAnimation { duration: 100 }
+ }
+
+ //![1]
+ TapHandler {
+ id: tapHandler
+ gesturePolicy: TapHandler.ReleaseWithinBounds
+ onTapped: tapFlash.start()
+ }
+ //![1]
+
+ Text {
+ id: buttonLabel
+ text: "Click Me"
+ color: palette.buttonText
+ anchors.centerIn: parent
+ }
+ }
+
+ Button { x: 10; y: 10 }
+}
+//![0]
diff --git a/src/quick/doc/snippets/pointerHandlers/tapHandlerButtonWithinBounds.qml b/src/quick/doc/snippets/pointerHandlers/tapHandlerButtonWithinBounds.qml
new file mode 100644
index 0000000000..4563b44014
--- /dev/null
+++ b/src/quick/doc/snippets/pointerHandlers/tapHandlerButtonWithinBounds.qml
@@ -0,0 +1,51 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+//![0]
+import QtQuick
+
+Item {
+ width: 120; height: 80
+
+ component Button : Rectangle {
+ id: button
+ signal clicked
+ property alias text: buttonLabel.text
+
+ width: 80
+ height: 40
+ radius: 3
+ property color dark: Qt.darker(palette.button, 1.3)
+ gradient: Gradient {
+ GradientStop { position: 0.0; color: tapHandler.pressed ? dark : palette.button }
+ GradientStop { position: 1.0; color: dark }
+ }
+
+ SequentialAnimation on border.width {
+ id: tapFlash
+ running: false
+ loops: 3
+ PropertyAction { value: 2 }
+ PauseAnimation { duration: 100 }
+ PropertyAction { value: 0 }
+ PauseAnimation { duration: 100 }
+ }
+
+ //![1]
+ TapHandler {
+ id: tapHandler
+ gesturePolicy: TapHandler.WithinBounds
+ onTapped: tapFlash.start()
+ }
+ //![1]
+
+ Text {
+ id: buttonLabel
+ text: "Click Me"
+ color: palette.buttonText
+ anchors.centerIn: parent
+ }
+ }
+
+ Button { x: 10; y: 10 }
+}
+//![0]
diff --git a/src/quick/doc/snippets/pointerHandlers/tapHandlerOverlappingButtons.qml b/src/quick/doc/snippets/pointerHandlers/tapHandlerOverlappingButtons.qml
new file mode 100644
index 0000000000..917c863e53
--- /dev/null
+++ b/src/quick/doc/snippets/pointerHandlers/tapHandlerOverlappingButtons.qml
@@ -0,0 +1,51 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+//![0]
+import QtQuick
+
+Item {
+ width: 120; height: 80
+
+ component Button : Rectangle {
+ signal clicked
+ property alias text: buttonLabel.text
+
+ width: 80
+ height: 40
+ radius: 3
+ property color dark: Qt.darker(palette.button, 1.3)
+ gradient: Gradient {
+ GradientStop { position: 0.0; color: tapHandler.pressed ? dark : palette.button }
+ GradientStop { position: 1.0; color: dark }
+ }
+
+ SequentialAnimation on border.width {
+ id: tapFlash
+ running: false
+ loops: 3
+ PropertyAction { value: 2 }
+ PauseAnimation { duration: 100 }
+ PropertyAction { value: 0 }
+ PauseAnimation { duration: 100 }
+ }
+
+ //![1]
+ TapHandler {
+ id: tapHandler
+ gesturePolicy: TapHandler.DragThreshold // the default
+ onTapped: tapFlash.start()
+ }
+ //![1]
+
+ Text {
+ id: buttonLabel
+ text: "Click Me"
+ color: palette.buttonText
+ anchors.centerIn: parent
+ }
+ }
+
+ Button { x: 10; y: 10 }
+ Button { x: 30; y: 30 }
+}
+//![0]
diff --git a/src/quick/doc/snippets/qml/item/itemGrab.qml b/src/quick/doc/snippets/qml/item/itemGrab.qml
new file mode 100644
index 0000000000..ef4430175a
--- /dev/null
+++ b/src/quick/doc/snippets/qml/item/itemGrab.qml
@@ -0,0 +1,39 @@
+// Copyright (C) 2014 Jolla Ltd, author: <gunnar.sletta@jollamobile.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+import QtQuick 2.4
+
+Item {
+ width: 320
+ height: 480
+
+//! [grab-to-file]
+Rectangle {
+ id: sourceRectangle
+ width: 100
+ height: 100
+ gradient: Gradient {
+ GradientStop { position: 0; color: "steelblue" }
+ GradientStop { position: 1; color: "black" }
+ }
+
+ Component.onCompleted: {
+ sourceRectangle.grabToImage(function(result) {
+ result.saveToFile("something.png")
+ })
+ }
+}
+//! [grab-to-file]
+
+//! [grab-to-image]
+Image {
+ id: image
+}
+
+Component.onCompleted: {
+ sourceRectangle.grabToImage(function(result) {
+ image.source = result.url
+ }, Qt.size(50, 50))
+}
+//! [grab-to-image]
+}
diff --git a/src/quick/doc/snippets/qml/itemGrab.qml b/src/quick/doc/snippets/qml/itemGrab.qml
deleted file mode 100644
index dd02661894..0000000000
--- a/src/quick/doc/snippets/qml/itemGrab.qml
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright (C) 2014 Jolla Ltd, author: <gunnar.sletta@jollamobile.com>
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
-
-import QtQuick 2.4
-
-Item {
- width: 320
- height: 480
-
-//! [grab-source]
-Rectangle {
- id: source
- width: 100
- height: 100
- gradient: Gradient {
- GradientStop { position: 0; color: "steelblue" }
- GradientStop { position: 1; color: "black" }
- }
-}
-//! [grab-source]
-
-//! [grab-image-target]
-Image {
- id: image
-}
-//! [grab-image-target]
- Timer {
- repeat: false
- running: true
- interval: 1000
- onTriggered: {
-//! [grab-to-file]
-
- // ...
- source.grabToImage(function(result) {
- result.saveToFile("something.png");
- });
-//! [grab-to-file]
-
-//! [grab-to-cache]
-
- // ...
- source.grabToImage(function(result) {
- image.source = result.url;
- },
- Qt.size(50, 50));
-//! [grab-to-cache]
- }
- }
-}
diff --git a/src/quick/doc/src/concepts/inputhandlers/qtquickhandlers-index.qdoc b/src/quick/doc/src/concepts/inputhandlers/qtquickhandlers-index.qdoc
index 182773b0f5..1157364df8 100644
--- a/src/quick/doc/src/concepts/inputhandlers/qtquickhandlers-index.qdoc
+++ b/src/quick/doc/src/concepts/inputhandlers/qtquickhandlers-index.qdoc
@@ -70,7 +70,8 @@
PointHandler) can work only with passive grabs; others require exclusive
grabs; and others can "lurk" with passive grabs until they detect that a
gesture is being performed, and then make the transition from passive to
- exclusive grab.
+ exclusive grab. TapHandler's grabbing behavior is
+ \l {TapHandler::gesturePolicy}{configurable}.
When a grab transition is requested, \l PointerHandler::grabPermissions,
\l QQuickItem::keepMouseGrab() and \l QQuickItem::keepTouchGrab() control
diff --git a/src/quick/doc/src/concepts/visualcanvas/scenegraph.qdoc b/src/quick/doc/src/concepts/visualcanvas/scenegraph.qdoc
index 505e7b570a..8163cf0dd6 100644
--- a/src/quick/doc/src/concepts/visualcanvas/scenegraph.qdoc
+++ b/src/quick/doc/src/concepts/visualcanvas/scenegraph.qdoc
@@ -1171,8 +1171,10 @@ with multiple windows.
\row
\li \c QSG_RHI_DEBUG_LAYER
\li \c 1
- \li Where applicable (Vulkan, Direct3D), enables the graphics API implementation's debug
- and/or validation layers, if available.
+ \li Where applicable (Vulkan, Direct3D), enables the graphics API implementation's
+ debug or validation layers, if available, either on the graphics device or the instance
+ object. For Metal on \macos, set the environment variable
+ \c{METAL_DEVICE_WRAPPER_TYPE=1} instead.
\row
\li \c QSG_RHI_PREFER_SOFTWARE_RENDERER
diff --git a/src/quick/doc/src/cppextensionpoints.qdoc b/src/quick/doc/src/cppextensionpoints.qdoc
index 148df0dce8..9a62f8f715 100644
--- a/src/quick/doc/src/cppextensionpoints.qdoc
+++ b/src/quick/doc/src/cppextensionpoints.qdoc
@@ -30,17 +30,16 @@ for more details.
\target scene-graph-related-classes
\section1 Scene Graph-Related Classes
-Qt Quick 2 makes use of a dedicated scene graph based on OpenGL ES 2.0 or OpenGL 2.0
-for its rendering. Using a scene graph for graphics rather than the traditional imperative
-painting systems (QPainter and similar), means the scene to be rendered can be retained
-between frames and the complete set of primitives to render is known before rendering
-starts. This opens up for a number of optimizations, such as batching the OpenGL draw calls
-to minimize state changes or discarding obscured primitives.
-
+Qt Quick 2 makes use of a dedicated scene graph based on graphics APIs such as
+OpenGL ES, OpenGL, Vulkan, Metal, or Direct 3D for its rendering. Using a scene
+graph for graphics rather than the traditional imperative painting systems
+(QPainter and similar), means the scene to be rendered can be retained between
+frames and the complete set of primitives to render is known before rendering
+starts. This opens up for a number of optimizations, such as batching the
+OpenGL draw calls to minimize state changes or discarding obscured primitives.
The \l {Qt Quick C++ Classes}{Qt Quick C++ API} provides various classes to
-enable custom nodes to be created in C++.
-
-See the \l {Qt Quick Scene Graph} documentation for details.
+enable custom nodes to be created in C++. See the \l {Qt Quick Scene Graph}
+documentation for details.
\target pixmap-and-threaded-image-support
\section1 Pixmap and Threaded Image Support
diff --git a/src/quick/doc/src/guidelines/qtquick-bestpractices.qdoc b/src/quick/doc/src/guidelines/qtquick-bestpractices.qdoc
index e3c64a85a1..bce8a2e11c 100644
--- a/src/quick/doc/src/guidelines/qtquick-bestpractices.qdoc
+++ b/src/quick/doc/src/guidelines/qtquick-bestpractices.qdoc
@@ -28,11 +28,16 @@ options that align with the latest UI design trends. If these UI controls do not
satisfy your application's needs, only then it is recommended to create a
custom control.
+You can use the controls when you design UIs in Qt Design Studio. In addition,
+it provides timeline-based animations, visual effects, layouts, and a
+live-preview for prototyping applications.
\section2 Related Information
\list
\li \l{Qt Quick Controls}
+\li \l{Customizing Qt Quick Controls}
\li \l{Qt Quick}
+\li \l{Qt Design Studio Manual}
\endlist
\omit
@@ -93,7 +98,7 @@ All QML files listed under \c {QML_FILES} will automatically get compiled \l {Ah
\li \l{The Qt Resource System}
\endlist
-\section1 Separate UI from Logic
+\section1 Separate UI from Business Logic
One of the key goals that most application developers want to achieve is to
create a maintainable application. One of the ways to achieve this goal is
@@ -109,8 +114,8 @@ reasons why an application's UI should be written in QML:
\li JavaScript can easily be used in QML to respond to events.
\endlist
-Being a strongly typed language, C++ is best suited for an application's logic.
-Typically, such code performs tasks such as complex calculations
+Being a strongly typed language, C++ is best suited for an application's
+business logic. Typically, such code performs tasks such as complex calculations
or data processing, which are faster in C++ than QML.
Qt offers various approaches to integrate QML and C++ code in an application.
@@ -154,6 +159,22 @@ see \l {Choosing the Correct Integration Method Between C++ and QML}.
\li \l{Qt Quick Controls - Chat Tutorial}{Chat application tutorial}
\endlist
+\section1 Using Qt Design Studio
+
+Qt Design Studio uses UI files that have the filename extension \e {.ui.qml}
+to separate the visual parts of the UI from the UI logic you implement in
+\e {.qml} files. You should edit UI files only in the \uicontrol {2D} view in
+Qt Design Studio. If you use some other tool to add code that Qt Design Studio
+does not support, it displays error messages. Fix the errors to enable visual
+editing of the UI files again. Typically, you should move the unsupported code
+to a \e {.qml} file.
+
+\section2 Related Information
+
+\list
+ \li \l{Qt Design Studio: UI Files}
+\endlist
+
\section1 Using Qt Quick Layouts
Qt offers Qt Quick Layouts to arrange Qt Quick items visually in a layout.
diff --git a/src/quick/doc/src/guidelines/qtquick-tool-qmllint.qdoc b/src/quick/doc/src/guidelines/qtquick-tool-qmllint.qdoc
index 6ca5f4f47b..0a9d6dbc58 100644
--- a/src/quick/doc/src/guidelines/qtquick-tool-qmllint.qdoc
+++ b/src/quick/doc/src/guidelines/qtquick-tool-qmllint.qdoc
@@ -129,9 +129,9 @@ that take precedence over the warning levels in settings.
\section2 Scripting
-qmllint can output JSON via the \c{--json} option which will return valid JSON
+qmllint can write or output JSON via the \c{--json <file>} option which will return valid JSON
with warning messages, file and line location of warnings, and their severity
-level.
+level. Use the special filename '-' to write to stdout instead of a file.
This can be used to more easily integrate qmllint in your pre-commit hooks or
CI testing.
diff --git a/src/quick/doc/src/qmltypereference.qdoc b/src/quick/doc/src/qmltypereference.qdoc
index 2ad40fc315..c856a42b8a 100644
--- a/src/quick/doc/src/qmltypereference.qdoc
+++ b/src/quick/doc/src/qmltypereference.qdoc
@@ -56,10 +56,10 @@ available when you import \c QtQuick.
*/
/*!
+ \keyword colorvaluetypedocs
\qmlvaluetype color
\ingroup qtquickvaluetypes
\brief an ARGB color value.
- \target colorvaluetypedocs
The \c color type refers to an ARGB color value. It can be specified in a number of ways:
@@ -835,7 +835,7 @@ console.log(c + " " + d); // false true
\qmlvaluetype matrix4x4
\ingroup qtquickvaluetypes
- \brief A matrix4x4 type is a 4-row and 4-column matrix
+ \brief A matrix4x4 type is a 4-row and 4-column matrix.
A \c matrix4x4 type has sixteen values, each accessible via the properties
\c m11 through \c m44 in QML (in row/column order). Values of this type
diff --git a/src/quick/handlers/qquickdraghandler.cpp b/src/quick/handlers/qquickdraghandler.cpp
index f90dd305d9..c31eb13d98 100644
--- a/src/quick/handlers/qquickdraghandler.cpp
+++ b/src/quick/handlers/qquickdraghandler.cpp
@@ -186,7 +186,7 @@ void QQuickDragHandler::handlePointerEventImpl(QPointerEvent *event)
QVector<QEventPoint> chosenPoints;
if (event->isBeginEvent())
- m_pressedInsideTarget = target() && currentPoints().count() > 0;
+ m_pressedInsideTarget = target() && currentPoints().size() > 0;
for (const QQuickHandlerPoint &p : currentPoints()) {
if (!allOverThreshold)
diff --git a/src/quick/handlers/qquickhandlerpoint.cpp b/src/quick/handlers/qquickhandlerpoint.cpp
index 2028c5c8ec..75848c2882 100644
--- a/src/quick/handlers/qquickhandlerpoint.cpp
+++ b/src/quick/handlers/qquickhandlerpoint.cpp
@@ -8,7 +8,7 @@ QT_BEGIN_NAMESPACE
Q_DECLARE_LOGGING_CATEGORY(lcTouchTarget)
/*!
- \qmltype HandlerPoint
+ \qmltype handlerPoint
\instantiates QQuickHandlerPoint
\inqmlmodule QtQuick
\brief An event point.
@@ -30,7 +30,7 @@ Q_DECLARE_LOGGING_CATEGORY(lcTouchTarget)
and reused for subsequent event deliveries. Continuous bindings to its
properties are not possible, and an individual handler cannot rely on it
outside the period when that point is part of an active gesture which that
- handler is handling. HandlerPoint is a Q_GADGET that the handler owns.
+ handler is handling. handlerPoint is a Q_GADGET that the handler owns.
This allows you to make lifetime bindings to its properties.
\sa SinglePointHandler::point, MultiPointHandler::centroid
@@ -105,7 +105,7 @@ void QQuickHandlerPoint::reset(const QVector<QQuickHandlerPoint> &points)
qWarning("reset: no points");
return;
}
- if (points.count() == 1) {
+ if (points.size() == 1) {
*this = points.first(); // copy all values
return;
}
@@ -144,7 +144,7 @@ void QQuickHandlerPoint::reset(const QVector<QQuickHandlerPoint> &points)
/*!
\readonly
- \qmlproperty int QtQuick::HandlerPoint::id
+ \qmlproperty int QtQuick::handlerPoint::id
\brief The ID number of the point
During a touch gesture, from the time that the first finger is pressed
@@ -162,7 +162,7 @@ void QQuickHandlerPoint::reset(const QVector<QQuickHandlerPoint> &points)
/*!
\readonly
- \qmlproperty pointingDeviceUniqueId QtQuick::HandlerPoint::uniqueId
+ \qmlproperty pointingDeviceUniqueId QtQuick::handlerPoint::uniqueId
\brief The unique ID of the point, if any
This is normally empty, because touchscreens cannot uniquely identify fingers.
@@ -184,7 +184,7 @@ void QQuickHandlerPoint::reset(const QVector<QQuickHandlerPoint> &points)
/*!
\readonly
- \qmlproperty QPointF QtQuick::HandlerPoint::position
+ \qmlproperty QPointF QtQuick::handlerPoint::position
\brief The position within the \c parent Item
This is the position of the event point relative to the bounds of
@@ -193,7 +193,7 @@ void QQuickHandlerPoint::reset(const QVector<QQuickHandlerPoint> &points)
/*!
\readonly
- \qmlproperty QPointF QtQuick::HandlerPoint::scenePosition
+ \qmlproperty QPointF QtQuick::handlerPoint::scenePosition
\brief The position within the scene
This is the position of the event point relative to the bounds of the Qt
@@ -202,7 +202,7 @@ void QQuickHandlerPoint::reset(const QVector<QQuickHandlerPoint> &points)
/*!
\readonly
- \qmlproperty QPointF QtQuick::HandlerPoint::pressPosition
+ \qmlproperty QPointF QtQuick::handlerPoint::pressPosition
\brief The pressed position within the \c parent Item
This is the position at which this point was pressed, relative to the
@@ -211,7 +211,7 @@ void QQuickHandlerPoint::reset(const QVector<QQuickHandlerPoint> &points)
/*!
\readonly
- \qmlproperty QPointF QtQuick::HandlerPoint::scenePressPosition
+ \qmlproperty QPointF QtQuick::handlerPoint::scenePressPosition
\brief The pressed position within the scene
This is the position at which this point was pressed, in the coordinate
@@ -220,7 +220,7 @@ void QQuickHandlerPoint::reset(const QVector<QQuickHandlerPoint> &points)
/*!
\readonly
- \qmlproperty QPointF QtQuick::HandlerPoint::sceneGrabPosition
+ \qmlproperty QPointF QtQuick::handlerPoint::sceneGrabPosition
\brief The grabbed position within the scene
If this point has been grabbed by a Pointer Handler or an Item, it means
@@ -231,7 +231,7 @@ void QQuickHandlerPoint::reset(const QVector<QQuickHandlerPoint> &points)
/*!
\readonly
- \qmlproperty enumeration QtQuick::HandlerPoint::pressedButtons
+ \qmlproperty enumeration QtQuick::handlerPoint::pressedButtons
\brief Which mouse or stylus buttons are currently pressed
\sa MouseArea::pressedButtons
@@ -239,7 +239,7 @@ void QQuickHandlerPoint::reset(const QVector<QQuickHandlerPoint> &points)
/*!
\readonly
- \qmlproperty enumeration QtQuick::HandlerPoint::modifiers
+ \qmlproperty enumeration QtQuick::handlerPoint::modifiers
\brief Which modifier keys are currently pressed
This property holds the keyboard modifiers that were pressed at the time
@@ -248,7 +248,7 @@ void QQuickHandlerPoint::reset(const QVector<QQuickHandlerPoint> &points)
/*!
\readonly
- \qmlproperty QVector2D QtQuick::HandlerPoint::velocity
+ \qmlproperty QVector2D QtQuick::handlerPoint::velocity
\brief A vector representing the average speed and direction of movement
This is a velocity vector pointing in the direction of movement, in logical
@@ -261,7 +261,7 @@ void QQuickHandlerPoint::reset(const QVector<QQuickHandlerPoint> &points)
/*!
\readonly
- \qmlproperty qreal QtQuick::HandlerPoint::rotation
+ \qmlproperty qreal QtQuick::handlerPoint::rotation
This property holds the rotation angle of the stylus on a graphics tablet
or the contact patch of a touchpoint on a touchscreen.
@@ -272,7 +272,7 @@ void QQuickHandlerPoint::reset(const QVector<QQuickHandlerPoint> &points)
/*!
\readonly
- \qmlproperty qreal QtQuick::HandlerPoint::pressure
+ \qmlproperty qreal QtQuick::handlerPoint::pressure
This property tells how hard the user is pressing the stylus on a graphics
tablet or the finger against a touchscreen, in the range from \c 0 (no
@@ -285,7 +285,7 @@ void QQuickHandlerPoint::reset(const QVector<QQuickHandlerPoint> &points)
/*!
\readonly
- \qmlproperty size QtQuick::HandlerPoint::ellipseDiameters
+ \qmlproperty size QtQuick::handlerPoint::ellipseDiameters
This property holds the diameters of the contact patch, if the event
comes from a touchpoint and the device provides this information.
@@ -309,6 +309,13 @@ void QQuickHandlerPoint::reset(const QVector<QQuickHandlerPoint> &points)
\sa QtQuick::TouchPoint::ellipseDiameters, QEventPoint::ellipseDiameters
*/
+/*!
+ \readonly
+ \qmlproperty PointerDevice QtQuick::handlerPoint::device
+
+ This property holds the device that the point (and its event) came from.
+*/
+
QT_END_NAMESPACE
#include "moc_qquickhandlerpoint_p.cpp"
diff --git a/src/quick/handlers/qquickhandlerpoint_p.h b/src/quick/handlers/qquickhandlerpoint_p.h
index 79a05765c8..7a01aedca1 100644
--- a/src/quick/handlers/qquickhandlerpoint_p.h
+++ b/src/quick/handlers/qquickhandlerpoint_p.h
@@ -38,6 +38,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickHandlerPoint {
Q_PROPERTY(qreal pressure READ pressure)
Q_PROPERTY(QSizeF ellipseDiameters READ ellipseDiameters)
Q_PROPERTY(QPointingDevice *device READ device)
+ QML_ANONYMOUS
public:
QQuickHandlerPoint();
diff --git a/src/quick/handlers/qquickhoverhandler.cpp b/src/quick/handlers/qquickhoverhandler.cpp
index 59a2775c7b..ea7613550f 100644
--- a/src/quick/handlers/qquickhoverhandler.cpp
+++ b/src/quick/handlers/qquickhoverhandler.cpp
@@ -34,17 +34,64 @@ Q_LOGGING_CATEGORY(lcHoverHandler, "qt.quick.handler.hover")
\sa MouseArea, PointHandler
*/
+class QQuickHoverHandlerPrivate : public QQuickSinglePointHandlerPrivate
+{
+ Q_DECLARE_PUBLIC(QQuickHoverHandler)
+
+public:
+ void onEnabledChanged() override;
+ void onParentChanged(QQuickItem *oldParent, QQuickItem *newParent) override;
+
+ void updateHasHoverInChild(QQuickItem *item, bool hasHover);
+};
+
+void QQuickHoverHandlerPrivate::onEnabledChanged()
+{
+ Q_Q(QQuickHoverHandler);
+
+ if (auto parent = q->parentItem())
+ updateHasHoverInChild(parent, enabled);
+ if (!enabled)
+ q->setHovered(false);
+
+ QQuickSinglePointHandlerPrivate::onEnabledChanged();
+}
+
+void QQuickHoverHandlerPrivate::onParentChanged(QQuickItem *oldParent, QQuickItem *newParent)
+{
+ if (oldParent)
+ updateHasHoverInChild(oldParent, false);
+ if (newParent)
+ updateHasHoverInChild(newParent, true);
+
+ QQuickSinglePointHandlerPrivate::onParentChanged(oldParent, newParent);
+}
+
+void QQuickHoverHandlerPrivate::updateHasHoverInChild(QQuickItem *item, bool hasHover)
+{
+ QQuickItemPrivate *itemPriv = QQuickItemPrivate::get(item);
+ itemPriv->setHasHoverInChild(hasHover);
+ // The DA needs to resolve which items and handlers should now be hovered or unhovered.
+ // Marking the parent item dirty ensures that flushFrameSynchronousEvents() will be called from the render loop,
+ // even if this change is not in response to a mouse event and no item has already marked itself dirty.
+ itemPriv->dirty(QQuickItemPrivate::Content);
+}
+
QQuickHoverHandler::QQuickHoverHandler(QQuickItem *parent)
- : QQuickSinglePointHandler(parent)
+ : QQuickSinglePointHandler(*(new QQuickHoverHandlerPrivate), parent)
{
+ Q_D(QQuickHoverHandler);
// Tell QQuickPointerDeviceHandler::wantsPointerEvent() to ignore button state
- d_func()->acceptedButtons = Qt::NoButton;
+ d->acceptedButtons = Qt::NoButton;
+ if (parent)
+ d->updateHasHoverInChild(parent, true);
}
QQuickHoverHandler::~QQuickHoverHandler()
{
+ Q_D(QQuickHoverHandler);
if (auto parent = parentItem())
- QQuickItemPrivate::get(parent)->setHasHoverInChild(false);
+ d->updateHasHoverInChild(parent, false);
}
/*!
@@ -52,7 +99,7 @@ QQuickHoverHandler::~QQuickHoverHandler()
\since 6.3
Whether this handler prevents other items or handlers behind it from
- being hovered at the same timee. This property is \c false by default.
+ being hovered at the same time. This property is \c false by default.
*/
void QQuickHoverHandler::setBlocking(bool blocking)
{
@@ -81,10 +128,12 @@ bool QQuickHoverHandler::event(QEvent *event)
void QQuickHoverHandler::componentComplete()
{
+ Q_D(QQuickHoverHandler);
QQuickSinglePointHandler::componentComplete();
- if (auto par = parentItem()) {
- par->setAcceptHoverEvents(true);
- QQuickItemPrivate::get(par)->setHasHoverInChild(true);
+
+ if (d->enabled) {
+ if (auto parent = parentItem())
+ d->updateHasHoverInChild(parent, true);
}
}
@@ -108,6 +157,9 @@ bool QQuickHoverHandler::wantsPointerEvent(QPointerEvent *event)
// the hovered property to transition to false prematurely.
// If a QQuickPointerTabletEvent caused the hovered property to become true,
// then only another QQuickPointerTabletEvent can make it become false.
+ // But after kCursorOverrideTimeout ms, QQuickItemPrivate::effectiveCursorHandler()
+ // will ignore it, just in case there is no QQuickPointerTabletEvent to unset it.
+ // For example, a tablet proximity leave event could occur, but we don't deliver it to the window.
if (!(m_hoveredTablet && QQuickDeliveryAgentPrivate::isMouseEvent(event)))
setHovered(false);
@@ -284,6 +336,13 @@ void QQuickHoverHandler::setHovered(bool hovered)
\sa Qt::CursorShape, QQuickItem::cursor()
*/
+/*!
+ \internal
+ \qmlproperty flags HoverHandler::dragThreshold
+
+ This property is not used in HoverHandler.
+*/
+
QT_END_NAMESPACE
#include "moc_qquickhoverhandler_p.cpp"
diff --git a/src/quick/handlers/qquickhoverhandler_p.h b/src/quick/handlers/qquickhoverhandler_p.h
index 39ceb3df21..354a846428 100644
--- a/src/quick/handlers/qquickhoverhandler_p.h
+++ b/src/quick/handlers/qquickhoverhandler_p.h
@@ -22,6 +22,8 @@
QT_BEGIN_NAMESPACE
+class QQuickHoverHandlerPrivate;
+
class Q_QUICK_PRIVATE_EXPORT QQuickHoverHandler : public QQuickSinglePointHandler
{
Q_OBJECT
@@ -50,6 +52,8 @@ protected:
bool wantsPointerEvent(QPointerEvent *event) override;
void handleEventPoint(QPointerEvent *ev, QEventPoint &point) override;
+ Q_DECLARE_PRIVATE(QQuickHoverHandler)
+
private:
void setHovered(bool hovered);
diff --git a/src/quick/handlers/qquickmultipointhandler.cpp b/src/quick/handlers/qquickmultipointhandler.cpp
index aaee15d2f0..c50de437cd 100644
--- a/src/quick/handlers/qquickmultipointhandler.cpp
+++ b/src/quick/handlers/qquickmultipointhandler.cpp
@@ -51,7 +51,7 @@ bool QQuickMultiPointHandler::wantsPointerEvent(QPointerEvent *event)
// currentPoints, because we don't want to lose the pressPosition, and do
// not want to reshuffle the order either).
const auto candidatePoints = eligiblePoints(event);
- if (candidatePoints.count() != d->currentPoints.count()) {
+ if (candidatePoints.size() != d->currentPoints.size()) {
d->currentPoints.clear();
if (active()) {
setActive(false);
@@ -64,7 +64,7 @@ bool QQuickMultiPointHandler::wantsPointerEvent(QPointerEvent *event)
ret = ret || (candidatePoints.size() >= minimumPointCount() && candidatePoints.size() <= maximumPointCount());
if (ret) {
- const int c = candidatePoints.count();
+ const int c = candidatePoints.size();
d->currentPoints.resize(c);
for (int i = 0; i < c; ++i) {
d->currentPoints[i].reset(event, candidatePoints[i]);
@@ -229,7 +229,7 @@ void QQuickMultiPointHandler::setMaximumPointCount(int maximumPointCount)
/*!
\readonly
- \qmlproperty QtQuick::HandlerPoint QtQuick::MultiPointHandler::centroid
+ \qmlproperty QtQuick::handlerPoint QtQuick::MultiPointHandler::centroid
A point exactly in the middle of the currently-pressed touch points.
If only one point is pressed, it's the same as that point.
@@ -265,7 +265,7 @@ bool QQuickMultiPointHandler::hasCurrentPoints(QPointerEvent *event)
return false;
// TODO optimize: either ensure the points are sorted,
// or use std::equal with a predicate
- for (const QQuickHandlerPoint &p : qAsConst(d->currentPoints)) {
+ for (const QQuickHandlerPoint &p : std::as_const(d->currentPoints)) {
const QEventPoint *ep = event->pointById(p.id());
if (!ep)
return false;
@@ -302,7 +302,7 @@ QVector<QQuickMultiPointHandler::PointData> QQuickMultiPointHandler::angles(cons
{
Q_D(const QQuickMultiPointHandler);
QVector<PointData> angles;
- angles.reserve(d->currentPoints.count());
+ angles.reserve(d->currentPoints.size());
for (const QQuickHandlerPoint &p : d->currentPoints) {
qreal angle = QLineF(ref, p.scenePosition()).angle();
angles.append(PointData(p.id(), -angle)); // convert to clockwise, to be consistent with QQuickItem::rotation
@@ -362,7 +362,7 @@ bool QQuickMultiPointHandler::grabPoints(QPointerEvent *event, const QVector<QEv
}
}
if (allowed) {
- for (auto point : points)
+ for (const auto &point : std::as_const(points))
setExclusiveGrab(event, point);
}
return allowed;
diff --git a/src/quick/handlers/qquickpinchhandler.cpp b/src/quick/handlers/qquickpinchhandler.cpp
index 1ac08d5354..6cfe8d8936 100644
--- a/src/quick/handlers/qquickpinchhandler.cpp
+++ b/src/quick/handlers/qquickpinchhandler.cpp
@@ -203,8 +203,8 @@ void QQuickPinchHandler::onActiveChanged()
m_startRotation = t->rotation();
m_startPos = t->position();
} else {
- m_startScale = 1;
- m_startRotation = 0;
+ m_startScale = m_accumulatedScale;
+ m_startRotation = 0; // TODO m_accumulatedRotation (QTBUG-94168)
}
qCDebug(lcPinchHandler) << "activated with starting scale" << m_startScale << "rotation" << m_startRotation;
} else {
@@ -236,6 +236,7 @@ void QQuickPinchHandler::handlePointerEventImpl(QPointerEvent *event)
return;
case Qt::ZoomNativeGesture:
m_activeScale *= 1 + gesture->value();
+ m_activeScale = qBound(m_minimumScale, m_activeScale, m_maximumScale);
break;
case Qt::RotateNativeGesture:
m_activeRotation += gesture->value();
@@ -333,9 +334,9 @@ void QQuickPinchHandler::handlePointerEventImpl(QPointerEvent *event)
}
const bool requiredNumberOfPointsDraggedOverThreshold = numberOfPointsDraggedOverThreshold >= minimumPointCount() && numberOfPointsDraggedOverThreshold <= maximumPointCount();
- accumulatedMovementMagnitude /= currentPoints().count();
+ accumulatedMovementMagnitude /= currentPoints().size();
- QVector2D avgDrag = accumulatedDrag / currentPoints().count();
+ QVector2D avgDrag = accumulatedDrag / currentPoints().size();
if (!xAxis()->enabled())
avgDrag.setX(0);
if (!yAxis()->enabled())
@@ -425,8 +426,15 @@ void QQuickPinchHandler::handlePointerEventImpl(QPointerEvent *event)
}
/*!
+ \internal
+ \qmlproperty flags QtQuick::PinchHandler::acceptedButtons
+
+ This property is not used in PinchHandler.
+*/
+
+/*!
\readonly
- \qmlproperty QtQuick::HandlerPoint QtQuick::PinchHandler::centroid
+ \qmlproperty QtQuick::handlerPoint QtQuick::PinchHandler::centroid
A point exactly in the middle of the currently-pressed touch points.
The \l target will be rotated around this point.
@@ -471,6 +479,9 @@ void QQuickPinchHandler::handlePointerEventImpl(QPointerEvent *event)
The translation of the gesture \l centroid. It is \c (0, 0) when the
gesture begins.
+
+ \note On some touchpads, such as on a \macos trackpad, native gestures do
+ not generate any translation values, and this property stays at \c (0, 0).
*/
QT_END_NAMESPACE
diff --git a/src/quick/handlers/qquickpointerdevicehandler.cpp b/src/quick/handlers/qquickpointerdevicehandler.cpp
index 78e94d8c96..5da7849a44 100644
--- a/src/quick/handlers/qquickpointerdevicehandler.cpp
+++ b/src/quick/handlers/qquickpointerdevicehandler.cpp
@@ -31,7 +31,7 @@ QQuickPointerDeviceHandler::QQuickPointerDeviceHandler(QQuickPointerDeviceHandle
{
}
-QPointingDevice::DeviceTypes QQuickPointerDeviceHandler::acceptedDevices() const
+QInputDevice::DeviceTypes QQuickPointerDeviceHandler::acceptedDevices() const
{
Q_D(const QQuickPointerDeviceHandler);
return d->acceptedDevices;
@@ -139,7 +139,7 @@ void QQuickPointerDeviceHandler::setAcceptedDevices(QPointingDevice::DeviceTypes
By default, this property is set to
\l {QPointingDevice::PointerType} {PointerDevice.AllPointerTypes}.
If you set it to an OR combination of device types, it will ignore events
- from non-matching events.
+ from non-matching \l {PointerDevice}{devices}.
For example, a control could be made to respond to mouse, touch, and stylus clicks
in some way, but delete itself if tapped with an eraser tool on a graphics tablet,
diff --git a/src/quick/handlers/qquickpointerdevicehandler_p.h b/src/quick/handlers/qquickpointerdevicehandler_p.h
index 259b8a5ae7..1a62194d78 100644
--- a/src/quick/handlers/qquickpointerdevicehandler_p.h
+++ b/src/quick/handlers/qquickpointerdevicehandler_p.h
@@ -23,7 +23,8 @@ class QQuickPointerDeviceHandlerPrivate;
class Q_QUICK_PRIVATE_EXPORT QQuickPointerDeviceHandler : public QQuickPointerHandler
{
Q_OBJECT
- Q_PROPERTY(QPointingDevice::DeviceTypes acceptedDevices READ acceptedDevices WRITE setAcceptedDevices NOTIFY acceptedDevicesChanged)
+ Q_PROPERTY(QInputDevice::DeviceTypes acceptedDevices READ acceptedDevices WRITE
+ setAcceptedDevices NOTIFY acceptedDevicesChanged)
Q_PROPERTY(QPointingDevice::PointerTypes acceptedPointerTypes READ acceptedPointerTypes WRITE setAcceptedPointerTypes NOTIFY acceptedPointerTypesChanged)
Q_PROPERTY(Qt::MouseButtons acceptedButtons READ acceptedButtons WRITE setAcceptedButtons NOTIFY acceptedButtonsChanged)
Q_PROPERTY(Qt::KeyboardModifiers acceptedModifiers READ acceptedModifiers WRITE setAcceptedModifiers NOTIFY acceptedModifiersChanged)
@@ -31,13 +32,13 @@ class Q_QUICK_PRIVATE_EXPORT QQuickPointerDeviceHandler : public QQuickPointerHa
public:
explicit QQuickPointerDeviceHandler(QQuickItem *parent = nullptr);
- QPointingDevice::DeviceTypes acceptedDevices() const;
+ QInputDevice::DeviceTypes acceptedDevices() const;
QPointingDevice::PointerTypes acceptedPointerTypes() const;
Qt::MouseButtons acceptedButtons() const;
Qt::KeyboardModifiers acceptedModifiers() const;
public Q_SLOTS:
- void setAcceptedDevices(QPointingDevice::DeviceTypes acceptedDevices);
+ void setAcceptedDevices(QInputDevice::DeviceTypes acceptedDevices);
void setAcceptedPointerTypes(QPointingDevice::PointerTypes acceptedPointerTypes);
void setAcceptedButtons(Qt::MouseButtons buttons);
void setAcceptedModifiers(Qt::KeyboardModifiers acceptedModifiers);
diff --git a/src/quick/handlers/qquickpointerhandler.cpp b/src/quick/handlers/qquickpointerhandler.cpp
index 018a09fcc2..a851334b0e 100644
--- a/src/quick/handlers/qquickpointerhandler.cpp
+++ b/src/quick/handlers/qquickpointerhandler.cpp
@@ -401,6 +401,8 @@ bool QQuickPointerHandler::approveGrabTransition(QPointerEvent *event, const QEv
This handler can take the exclusive grab from another handler of the same class.
\value PointerHandler.CanTakeOverFromHandlersOfDifferentType
This handler can take the exclusive grab from any kind of handler.
+ \value PointerHandler.CanTakeOverFromItems
+ This handler can take the exclusive grab from any type of Item.
\value PointerHandler.CanTakeOverFromAnything
This handler can take the exclusive grab from any type of Item or Handler.
\value PointerHandler.ApprovesTakeOverByHandlersOfSameType
@@ -553,6 +555,8 @@ void QQuickPointerHandler::setEnabled(bool enabled)
return;
d->enabled = enabled;
+ d->onEnabledChanged();
+
emit enabledChanged();
}
@@ -593,15 +597,18 @@ QQuickItem *QQuickPointerHandler::parentItem() const
void QQuickPointerHandler::setParentItem(QQuickItem *p)
{
+ Q_D(QQuickPointerHandler);
if (QObject::parent() == p)
return;
qCDebug(lcHandlerParent) << "reparenting handler" << this << ":" << parent() << "->" << p;
- if (auto *oldParent = static_cast<QQuickItem *>(QObject::parent()))
+ auto *oldParent = static_cast<QQuickItem *>(QObject::parent());
+ if (oldParent)
QQuickItemPrivate::get(oldParent)->removePointerHandler(this);
setParent(p);
if (p)
QQuickItemPrivate::get(p)->addPointerHandler(this);
+ d->onParentChanged(oldParent, p);
emit parentChanged();
}
@@ -645,6 +652,7 @@ void QQuickPointerHandler::handlePointerEvent(QPointerEvent *event)
d->currentEvent = event;
if (wants) {
handlePointerEventImpl(event);
+ d->lastEventTime = event->timestamp();
} else {
#if QT_CONFIG(gestures)
if (event->type() != QEvent::NativeGesture)
diff --git a/src/quick/handlers/qquickpointerhandler_p_p.h b/src/quick/handlers/qquickpointerhandler_p_p.h
index 8823bcb897..aa09f4edb7 100644
--- a/src/quick/handlers/qquickpointerhandler_p_p.h
+++ b/src/quick/handlers/qquickpointerhandler_p_p.h
@@ -38,11 +38,15 @@ public:
bool dragOverThreshold(QVector2D delta) const;
bool dragOverThreshold(const QEventPoint &point) const;
+ virtual void onParentChanged(QQuickItem * /*oldParent*/, QQuickItem * /*newParent*/) {}
+ virtual void onEnabledChanged() {}
+
static QVector<QObject *> &deviceDeliveryTargets(const QInputDevice *device);
QPointerEvent *currentEvent = nullptr;
QQuickItem *target = nullptr;
qreal m_margin = 0;
+ quint64 lastEventTime = 0;
qint16 dragThreshold = -1; // -1 means use the platform default
uint8_t grabPermissions : 8;
Qt::CursorShape cursorShape : 6;
diff --git a/src/quick/handlers/qquickpointhandler.cpp b/src/quick/handlers/qquickpointhandler.cpp
index 1c5f36b6dd..2a9e0ff9bb 100644
--- a/src/quick/handlers/qquickpointhandler.cpp
+++ b/src/quick/handlers/qquickpointhandler.cpp
@@ -66,7 +66,8 @@ QT_BEGIN_NAMESPACE
PointHandler will not automatically manipulate the \c target item in any way.
You need to use bindings to make it react to the \l point.
- \note On macOS, PointHandler does not react to the trackpad by default.
+ \note On macOS, PointHandler does not react to multiple fingers on the
+ trackpad by default, although it does react to a pressed point (mouse position).
That is because macOS can provide either native gesture recognition, or raw
touchpoints, but not both. We prefer to use the native gesture event in
PinchHandler, so we do not want to disable it by enabling touch. However
@@ -75,7 +76,7 @@ QT_BEGIN_NAMESPACE
want to react to all the touchpoints but do not require the smooth
native-gesture experience.
- \sa MultiPointTouchArea
+ \sa MultiPointTouchArea, HoverHandler, {Pointer Handlers Example}
*/
QQuickPointHandler::QQuickPointHandler(QQuickItem *parent)
@@ -128,6 +129,127 @@ QVector2D QQuickPointHandler::translation() const
return QVector2D(point().position() - point().pressPosition());
}
+/*!
+ \qmlproperty flags PointHandler::acceptedButtons
+
+ The mouse buttons that can activate this PointHandler.
+
+ By default, this property is set to \l {QtQuick::MouseEvent::button} {Qt.LeftButton}.
+ It can be set to an OR combination of mouse buttons, and will ignore events
+ in which other buttons are pressed or held.
+
+ \snippet pointerHandlers/pointHandlerAcceptedButtons.qml 0
+
+ \note On a touchscreen, there are no buttons, so this property does not
+ prevent PointHandler from reacting to touchpoints.
+*/
+
+/*!
+ \qmlproperty flags PointHandler::acceptedDevices
+
+ The types of pointing devices that can activate this PointHandler.
+
+ By default, this property is set to
+ \l{QInputDevice::DeviceType}{PointerDevice.AllDevices}.
+ If you set it to an OR combination of device types, it will ignore events
+ from non-matching \l {PointerDevice}{devices}:
+
+ \snippet pointerHandlers/pointHandler.qml 1
+*/
+
+/*!
+ \qmlproperty flags PointHandler::acceptedPointerTypes
+
+ The types of pointing instruments (finger, stylus, eraser, etc.)
+ that can activate this PointHandler.
+
+ By default, this property is set to
+ \l {QPointingDevice::PointerType} {PointerDevice.AllPointerTypes}.
+ If you set it to an OR combination of device types, it will ignore events
+ from non-matching \l {PointerDevice}{devices}:
+
+ \snippet pointerHandlers/pointHandlerCanvasDrawing.qml 0
+
+ The \l {Pointer Handlers Example} includes a more complex example for
+ drawing on a Canvas with a graphics tablet.
+*/
+
+/*!
+ \qmlproperty flags PointHandler::acceptedModifiers
+
+ If this property is set, PointHandler requires the given keyboard modifiers
+ to be pressed in order to react to \l {PointerEvent}{PointerEvents}, and
+ otherwise ignores them.
+
+ If this property is set to \c Qt.KeyboardModifierMask (the default value),
+ then PointHandler ignores the modifier keys.
+
+ For example, an \l [QML] Item could have two handlers, one of which is
+ enabled only if the required keyboard modifier is pressed:
+
+ \snippet pointerHandlers/pointHandlerAcceptedModifiers.qml 0
+
+ If you set \c acceptedModifiers to an OR combination of modifier keys,
+ it means \e all of those modifiers must be pressed to activate the handler.
+
+ The available modifiers are as follows:
+
+ \value NoModifier No modifier key is allowed.
+ \value ShiftModifier A Shift key on the keyboard must be pressed.
+ \value ControlModifier A Ctrl key on the keyboard must be pressed.
+ \value AltModifier An Alt key on the keyboard must be pressed.
+ \value MetaModifier A Meta key on the keyboard must be pressed.
+ \value KeypadModifier A keypad button must be pressed.
+ \value GroupSwitchModifier X11 only (unless activated on Windows by a command line argument).
+ A Mode_switch key on the keyboard must be pressed.
+ \value KeyboardModifierMask The handler does not care which modifiers are pressed.
+
+ \sa Qt::KeyboardModifier
+*/
+
+/*!
+ \readonly
+ \qmlproperty bool PointHandler::active
+
+ This holds \c true whenever the constraints are satisfied and this
+ PointHandler is reacting. This means that it is keeping its properties
+ up-to-date according to the movements of the \l {eventPoint}{eventPoints}
+ that satisfy the constraints.
+*/
+
+/*!
+ \internal
+ \qmlproperty flags PointHandler::dragThreshold
+
+ This property is not used in PointHandler.
+*/
+
+/*!
+ \qmlproperty real PointHandler::margin
+
+ The margin beyond the bounds of the \l {PointerHandler::parent}{parent}
+ item within which an \l eventPoint can activate this handler.
+
+ The default value is \c 0.
+
+ \snippet pointerHandlers/pointHandlerMargin.qml 0
+*/
+
+/*!
+ \qmlproperty real PointHandler::target
+
+ A property that can conveniently hold an Item to be manipulated or to show
+ feedback. Unlike other \l {Qt Quick Input Handlers}{Pointer Handlers},
+ PointHandler does not do anything with the \c target on its own: you
+ usually need to create reactive bindings to properties such as
+ \l SinglePointHandler::point and \l PointHandler::active. If you declare
+ an Item instance here, you need to explicitly set its \l {Item::}{parent},
+ because PointHandler is not an Item.
+
+ By default, it is the same as the \l {PointerHandler::}{parent}, the Item
+ within which the handler is declared.
+*/
+
QT_END_NAMESPACE
#include "moc_qquickpointhandler_p.cpp"
diff --git a/src/quick/handlers/qquicksinglepointhandler.cpp b/src/quick/handlers/qquicksinglepointhandler.cpp
index c732a2562e..c7b642a7bc 100644
--- a/src/quick/handlers/qquicksinglepointhandler.cpp
+++ b/src/quick/handlers/qquicksinglepointhandler.cpp
@@ -171,7 +171,7 @@ QQuickHandlerPoint QQuickSinglePointHandler::point() const
/*!
\readonly
- \qmlproperty HandlerPoint QtQuick::SinglePointHandler::point
+ \qmlproperty handlerPoint QtQuick::SinglePointHandler::point
The event point currently being handled. When no point is currently being
handled, this object is reset to default values (all coordinates are 0).
diff --git a/src/quick/handlers/qquicktaphandler.cpp b/src/quick/handlers/qquicktaphandler.cpp
index 0ec7c0ab65..96c67aa778 100644
--- a/src/quick/handlers/qquicktaphandler.cpp
+++ b/src/quick/handlers/qquicktaphandler.cpp
@@ -117,24 +117,14 @@ bool QQuickTapHandler::wantsEventPoint(const QPointerEvent *event, const QEventP
void QQuickTapHandler::handleEventPoint(QPointerEvent *event, QEventPoint &point)
{
+ const bool isTouch = QQuickDeliveryAgentPrivate::isTouchEvent(event);
switch (point.state()) {
case QEventPoint::Pressed:
setPressed(true, false, event, point);
break;
case QEventPoint::Released: {
- // If the point has an exclusive grabber Item, then if it got the grab by filtering (like Flickable does),
- // it's OK for DragHandler to react in spite of that. But in other cases, if an exclusive grab
- // still exists at the time of release, TapHandler should not react, because it would be redundant:
- // some other item is already reacting, i.e. acting as if it has been clicked or tapped.
- // So in that case we cancel the pressed state and do not emit tapped().
- bool nonFilteringExclusiveGrabber = false;
- if (auto g = qmlobject_cast<QQuickItem *>(event->exclusiveGrabber(point))) {
- if (!g->filtersChildMouseEvents())
- nonFilteringExclusiveGrabber = true;
- }
- if (QQuickDeliveryAgentPrivate::isTouchEvent(event) ||
- (static_cast<const QSinglePointEvent *>(event)->buttons() & acceptedButtons()) == Qt::NoButton)
- setPressed(false, nonFilteringExclusiveGrabber, event, point);
+ if (isTouch || (static_cast<const QSinglePointEvent *>(event)->buttons() & acceptedButtons()) == Qt::NoButton)
+ setPressed(false, false, event, point);
break;
}
default:
@@ -142,6 +132,11 @@ void QQuickTapHandler::handleEventPoint(QPointerEvent *event, QEventPoint &point
}
QQuickSinglePointHandler::handleEventPoint(event, point);
+
+ // If TapHandler only needs a passive grab, it should not block other items and handlers from reacting.
+ // If the point is accepted, QQuickItemPrivate::localizedTouchEvent() would skip it.
+ if (isTouch && m_gesturePolicy == DragThreshold)
+ point.setAccepted(false);
}
/*!
@@ -194,16 +189,41 @@ void QQuickTapHandler::timerEvent(QTimerEvent *event)
The \c gesturePolicy also affects grab behavior as described below.
- \value TapHandler.DragThreshold
- (the default value) The event point must not move significantly.
- If the mouse, finger or stylus moves past the system-wide drag
- threshold (QStyleHints::startDragDistance), the tap gesture is
- canceled, even if the button or finger is still pressed. This policy
- can be useful whenever TapHandler needs to cooperate with other
- input handlers (for example \l DragHandler) or event-handling Items
- (for example QtQuick Controls), because in this case TapHandler
- will not take the exclusive grab, but merely a
- \l {QPointerEvent::addPassiveGrabber()}{passive grab}.
+ \table
+ \header
+ \li Constant
+ \li Description
+ \row
+ \li \c TapHandler.DragThreshold
+ \image pointerHandlers/tapHandlerOverlappingButtons.webp
+ Grab on press: \e passive
+ \li (the default value) The \l eventPoint must not move significantly.
+ If the mouse, finger or stylus moves past the system-wide drag
+ threshold (QStyleHints::startDragDistance), the tap gesture is
+ canceled, even if the device or finger is still pressed. This policy
+ can be useful whenever TapHandler needs to cooperate with other
+ input handlers (for example \l DragHandler) or event-handling Items
+ (for example \l {Qt Quick Controls}), because in this case TapHandler
+ will not take the exclusive grab, but merely a
+ \l {QPointerEvent::addPassiveGrabber()}{passive grab}.
+ That is, \c DragThreshold is especially useful to \e augment
+ existing behavior: it reacts to tap/click/long-press even when
+ another item or handler is already reacting, perhaps even in a
+ different layer of the UI. The following snippet shows one
+ TapHandler as used in one component; but if we stack up two
+ instances of the component, you will see the handlers in both of them
+ react simultaneously when a press occurs over both of them, because
+ the passive grab does not stop event propagation:
+ \quotefromfile pointerHandlers/tapHandlerOverlappingButtons.qml
+ \skipto Item
+ \printuntil component Button
+ \skipto TapHandler
+ \printuntil }
+ \skipuntil Text {
+ \skipuntil }
+ \printuntil Button
+ \printuntil Button
+ \printuntil }
\value TapHandler.WithinBounds
If the event point leaves the bounds of the \c parent Item, the tap
@@ -212,31 +232,47 @@ void QQuickTapHandler::timerEvent(QTimerEvent *event)
press, but will release the grab as soon as the boundary constraint
is no longer satisfied.
- \value TapHandler.ReleaseWithinBounds
- At the time of release (the mouse button is released or the finger
- is lifted), if the event point is outside the bounds of the
- \c parent Item, a tap gesture is not recognized. This corresponds to
- typical behavior for button widgets: you can cancel a click by
- dragging outside the button, and you can also change your mind by
- dragging back inside the button before release. Note that it's
- necessary for TapHandler to take the
- \l {QPointerEvent::setExclusiveGrabber}{exclusive grab} on press
- and retain it until release in order to detect this gesture.
-
- \value TapHandler.DragWithinBounds
- On press, TapHandler takes the
- \l {QPointerEvent::setExclusiveGrabber}{exclusive grab}; after that,
- the event point can be dragged within the bounds of the \c parent
- item, while the \l timeHeld property keeps counting, and the
- \l longPressed() signal will be emitted regardless of drag distance.
- However, like \c WithinBounds, if the point leaves the bounds,
- the tap gesture is \l {PointerHandler::}{canceled()}, \l active()
- becomes \c false, and \l timeHeld stops counting. This is suitable
- for implementing press-drag-release components, such as menus, in
- which a single TapHandler detects press, \c timeHeld drives an
- "opening" animation, and then the user can drag to a menu item and
- release, while never leaving the bounds of the parent scene containing
- the menu. This value was added in Qt 6.3.
+ \row
+ \li \c TapHandler.ReleaseWithinBounds
+ \image pointerHandlers/tapHandlerButtonReleaseWithinBounds.webp
+ Grab on press: \e exclusive
+ \li At the time of release (the mouse button is released or the finger
+ is lifted), if the \l eventPoint is outside the bounds of the
+ \c parent Item, a tap gesture is not recognized. This corresponds to
+ typical behavior for button widgets: you can cancel a click by
+ dragging outside the button, and you can also change your mind by
+ dragging back inside the button before release. Note that it's
+ necessary for TapHandler to take the
+ \l {QPointerEvent::setExclusiveGrabber}{exclusive grab} on press
+ and retain it until release in order to detect this gesture.
+ \snippet pointerHandlers/tapHandlerButtonReleaseWithinBounds.qml 1
+
+ \row
+ \li \c TapHandler.DragWithinBounds
+ \image pointerHandlers/dragReleaseMenu.webp
+ Grab on press: \e exclusive
+ \li On press, TapHandler takes the
+ \l {QPointerEvent::setExclusiveGrabber}{exclusive grab}; after that,
+ the \l eventPoint can be dragged within the bounds of the \c parent
+ item, while the \l timeHeld property keeps counting, and the
+ \l longPressed() signal will be emitted regardless of drag distance.
+ However, like \c WithinBounds, if the point leaves the bounds,
+ the tap gesture is \l {PointerHandler::}{canceled()}, \l active()
+ becomes \c false, and \l timeHeld stops counting. This is suitable
+ for implementing press-drag-release components, such as menus, in
+ which a single TapHandler detects press, \c timeHeld drives an
+ "opening" animation, and then the user can drag to a menu item and
+ release, while never leaving the bounds of the parent scene containing
+ the menu. This value was added in Qt 6.3.
+ \snippet pointerHandlers/dragReleaseMenu.qml 1
+ \endtable
+
+ \note If you find that TapHandler is reacting in cases that conflict with
+ some other behavior, the first thing you should try is to think about which
+ \c gesturePolicy is appropriate. If you cannot fix it by changing \c gesturePolicy,
+ some cases are better served by adjusting \l {PointerHandler::}{grabPermissions},
+ either in this handler, or in another handler that should \e prevent TapHandler
+ from reacting.
*/
void QQuickTapHandler::setGesturePolicy(QQuickTapHandler::GesturePolicy gesturePolicy)
{
diff --git a/src/quick/handlers/qquickwheelhandler.cpp b/src/quick/handlers/qquickwheelhandler.cpp
index ced584b0ad..84a3a69405 100644
--- a/src/quick/handlers/qquickwheelhandler.cpp
+++ b/src/quick/handlers/qquickwheelhandler.cpp
@@ -55,7 +55,7 @@ QQuickWheelHandler::QQuickWheelHandler(QQuickItem *parent)
}
/*!
- \qmlproperty enum QtQuick::WheelHandler::orientation
+ \qmlproperty enumeration QtQuick::WheelHandler::orientation
Which wheel to react to. The default is \c Qt.Vertical.
diff --git a/src/quick/items/context2d/qquickcanvasitem.cpp b/src/quick/items/context2d/qquickcanvasitem.cpp
index a6d58fec2c..0eb4fe40d3 100644
--- a/src/quick/items/context2d/qquickcanvasitem.cpp
+++ b/src/quick/items/context2d/qquickcanvasitem.cpp
@@ -616,6 +616,10 @@ void QQuickCanvasItem::invalidateSceneGraph()
d->textureProvider = nullptr;
delete d->nodeTexture;
d->nodeTexture = nullptr;
+
+ // As we can expect(/hope) that the SG will be "good again", we can requestPaint ( which does 'markDirty(canvasWindow);' )
+ // Otherwise this Canvas will be "blank" when SG comes back
+ requestPaint();
}
void QQuickCanvasItem::schedulePolish()
diff --git a/src/quick/items/context2d/qquickcontext2d.cpp b/src/quick/items/context2d/qquickcontext2d.cpp
index d2e24a8b30..d053da4766 100644
--- a/src/quick/items/context2d/qquickcontext2d.cpp
+++ b/src/quick/items/context2d/qquickcontext2d.cpp
@@ -101,7 +101,7 @@ Q_QUICK_PRIVATE_EXPORT QColor qt_color_from_string(const QV4::Value &name)
QByteArray str = name.toQString().toUtf8();
char *p = str.data();
- int len = str.length();
+ int len = str.size();
//rgb/hsl color string has at least 7 characters
if (!p || len > 255 || len <= 7)
return QColor::fromString(p);
diff --git a/src/quick/items/context2d/qquickcontext2dcommandbuffer_p.h b/src/quick/items/context2d/qquickcontext2dcommandbuffer_p.h
index 3c18c68856..52ba4896ed 100644
--- a/src/quick/items/context2d/qquickcontext2dcommandbuffer_p.h
+++ b/src/quick/items/context2d/qquickcontext2dcommandbuffer_p.h
@@ -168,7 +168,7 @@ public:
inline void setLineDash(const QVector<qreal> &pattern)
{
commands << QQuickContext2D::LineDash;
- reals << pattern.length();
+ reals << pattern.size();
for (qreal r : pattern)
reals << r;
}
diff --git a/src/quick/items/context2d/qquickcontext2dtexture.cpp b/src/quick/items/context2d/qquickcontext2dtexture.cpp
index 0dd95a9095..2dadae3ef7 100644
--- a/src/quick/items/context2d/qquickcontext2dtexture.cpp
+++ b/src/quick/items/context2d/qquickcontext2dtexture.cpp
@@ -113,7 +113,7 @@ bool QQuickContext2DTexture::setDirtyRect(const QRect &r)
{
bool doDirty = false;
if (m_tiledCanvas) {
- for (QQuickContext2DTile* t : qAsConst(m_tiles)) {
+ for (QQuickContext2DTile* t : std::as_const(m_tiles)) {
bool dirty = t->rect().intersected(r).isValid();
t->markDirty(dirty);
if (dirty)
@@ -197,7 +197,7 @@ void QQuickContext2DTexture::paint(QQuickContext2DCommandBuffer *ccb)
QRect tiledRegion = createTiles(m_canvasWindow.intersected(QRect(QPoint(0, 0), m_canvasSize)));
if (!tiledRegion.isEmpty()) {
QRect dirtyRect;
- for (QQuickContext2DTile* tile : qAsConst(m_tiles)) {
+ for (QQuickContext2DTile* tile : std::as_const(m_tiles)) {
if (tile->dirty()) {
if (dirtyRect.isEmpty())
dirtyRect = tile->rect();
@@ -208,7 +208,7 @@ void QQuickContext2DTexture::paint(QQuickContext2DCommandBuffer *ccb)
if (beginPainting()) {
QQuickContext2D::State oldState = m_state;
- for (QQuickContext2DTile* tile : qAsConst(m_tiles)) {
+ for (QQuickContext2DTile* tile : std::as_const(m_tiles)) {
if (tile->dirty()) {
ccb->replay(tile->createPainter(m_smooth, m_antialiasing), oldState, scaleFactor());
tile->drawFinished();
diff --git a/src/quick/items/qquickaccessibleattached.cpp b/src/quick/items/qquickaccessibleattached.cpp
index 45219dc69c..865fb8bf11 100644
--- a/src/quick/items/qquickaccessibleattached.cpp
+++ b/src/quick/items/qquickaccessibleattached.cpp
@@ -73,7 +73,7 @@ QT_BEGIN_NAMESPACE
This property sets an accessible description.
Similar to the name it describes the item. The description
can be a little more verbose and tell what the item does,
- for example the functionallity of the button it describes.
+ for example the functionality of the button it describes.
*/
/*!
@@ -312,11 +312,33 @@ QQuickAccessibleAttached::QQuickAccessibleAttached(QObject *parent)
QAccessibleEvent ev(item(), QAccessible::ObjectCreated);
QAccessible::updateAccessibility(&ev);
- if (!parent->property("value").isNull()) {
- connect(parent, SIGNAL(valueChanged()), this, SLOT(valueChanged()));
- }
- if (!parent->property("cursorPosition").isNull()) {
- connect(parent, SIGNAL(cursorPositionChanged()), this, SLOT(cursorPositionChanged()));
+ if (const QMetaObject *pmo = parent->metaObject()) {
+ auto connectPropertyChangeSignal = [parent, pmo, this](
+ const char *propertyName, const char *signalName, int slotIndex)
+ {
+ // basically does this:
+ // if the parent has the property \a propertyName with the associated \a signalName:
+ // connect(parent, signalName, this, slotIndex)
+
+ // Note that we explicitly want to only connect to standard property/signal naming
+ // convention: "value" & "valueChanged"
+ // (e.g. avoid a compound property with e.g. a signal notifier named "updated()")
+ int idxProperty = pmo->indexOfProperty(propertyName);
+ if (idxProperty != -1) {
+ const QMetaProperty property = pmo->property(idxProperty);
+ const QMetaMethod signal = property.notifySignal();
+ if (signal.name() == signalName)
+ QMetaObject::connect(parent, signal.methodIndex(), this, slotIndex);
+ }
+ return;
+ };
+ const QMetaObject &smo = staticMetaObject;
+ static const int valueChangedIndex = smo.indexOfSlot("valueChanged()");
+ connectPropertyChangeSignal("value", "valueChanged", valueChangedIndex);
+
+ static const int cursorPositionChangedIndex = smo.indexOfSlot("cursorPositionChanged()");
+ connectPropertyChangeSignal("cursorPosition", "cursorPositionChanged",
+ cursorPositionChangedIndex);
}
if (!sigPress.isValid()) {
diff --git a/src/quick/items/qquickcolorgroup.cpp b/src/quick/items/qquickcolorgroup.cpp
index fd913aba7a..273ee31fa2 100644
--- a/src/quick/items/qquickcolorgroup.cpp
+++ b/src/quick/items/qquickcolorgroup.cpp
@@ -45,6 +45,8 @@ QT_BEGIN_NAMESPACE
base: "green"
}
\endcode
+
+ The \l Palette type exposes color groups for each QML item state.
*/
/*!
@@ -180,8 +182,6 @@ QT_BEGIN_NAMESPACE
Additional signal indicates that the current state of this color group
has been changed. Usually it means that one of the colors is changed.
-
- \sa Palette
*/
/*!
diff --git a/src/quick/items/qquickdrag.cpp b/src/quick/items/qquickdrag.cpp
index 4d54a28d8a..6c1f56de63 100644
--- a/src/quick/items/qquickdrag.cpp
+++ b/src/quick/items/qquickdrag.cpp
@@ -446,7 +446,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
@@ -731,8 +733,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()) {
diff --git a/src/quick/items/qquickdrag_p.h b/src/quick/items/qquickdrag_p.h
index 611ed5df8f..806dbc7602 100644
--- a/src/quick/items/qquickdrag_p.h
+++ b/src/quick/items/qquickdrag_p.h
@@ -72,9 +72,12 @@ public:
void grab(QQuickItem *item) { m_items.insert(new Item(item)); }
iterator release(iterator at) { Item *item = *at; at = at.erase(); delete item; return at; }
+ auto& ignoreList() { return m_ignoreDragItems; }
+
private:
ItemList m_items;
+ QVarLengthArray<QQuickItem *, 4> m_ignoreDragItems;
QObject *m_target;
};
diff --git a/src/quick/items/qquickdroparea.cpp b/src/quick/items/qquickdroparea.cpp
index a553d758c5..1c865a6327 100644
--- a/src/quick/items/qquickdroparea.cpp
+++ b/src/quick/items/qquickdroparea.cpp
@@ -125,7 +125,7 @@ void QQuickDropArea::setKeys(const QStringList &keys)
d->keyRegExp = QRegularExpression();
} else {
QString pattern = QLatin1Char('(') + QRegularExpression::escape(keys.first());
- for (int i = 1; i < keys.count(); ++i)
+ for (int i = 1; i < keys.size(); ++i)
pattern += QLatin1Char('|') + QRegularExpression::escape(keys.at(i));
pattern += QLatin1Char(')');
d->keyRegExp = QRegularExpression(
diff --git a/src/quick/items/qquickflickable.cpp b/src/quick/items/qquickflickable.cpp
index b1d274cb98..fdb294cdfc 100644
--- a/src/quick/items/qquickflickable.cpp
+++ b/src/quick/items/qquickflickable.cpp
@@ -318,7 +318,7 @@ void QQuickFlickablePrivate::AxisData::updateVelocity()
}
}
-void QQuickFlickablePrivate::itemGeometryChanged(QQuickItem *item, QQuickGeometryChange change, const QRectF &)
+void QQuickFlickablePrivate::itemGeometryChanged(QQuickItem *item, QQuickGeometryChange change, const QRectF &oldGeom)
{
Q_Q(QQuickFlickable);
if (item == contentItem) {
@@ -327,8 +327,14 @@ void QQuickFlickablePrivate::itemGeometryChanged(QQuickItem *item, QQuickGeometr
orient |= Qt::Horizontal;
if (change.yChange())
orient |= Qt::Vertical;
- if (orient)
+ if (orient) {
q->viewportMoved(orient);
+ const QPointF deltaMoved = item->position() - oldGeom.topLeft();
+ if (hData.contentPositionChangedExternallyDuringDrag)
+ hData.pressPos += deltaMoved.x();
+ if (vData.contentPositionChangedExternallyDuringDrag)
+ vData.pressPos += deltaMoved.y();
+ }
if (orient & Qt::Horizontal)
emit q->contentXChanged();
if (orient & Qt::Vertical)
@@ -711,7 +717,8 @@ void QQuickFlickablePrivate::updateBeginningEnd()
/*!
\qmlsignal QtQuick::Flickable::flickEnded()
- This signal is emitted when the view stops moving due to a flick.
+ This signal is emitted when the view stops moving after a flick
+ or a series of flicks.
*/
/*!
@@ -788,8 +795,11 @@ void QQuickFlickable::setContentX(qreal pos)
d->hData.vTime = d->timeline.time();
if (isMoving() || isFlicking())
movementEnding(true, false);
- if (!qFuzzyCompare(-pos, d->hData.move.value()))
+ if (!qFuzzyCompare(-pos, d->hData.move.value())) {
+ d->hData.contentPositionChangedExternallyDuringDrag = d->hData.dragging;
d->hData.move.setValue(-pos);
+ d->hData.contentPositionChangedExternallyDuringDrag = false;
+ }
}
qreal QQuickFlickable::contentY() const
@@ -806,8 +816,11 @@ void QQuickFlickable::setContentY(qreal pos)
d->vData.vTime = d->timeline.time();
if (isMoving() || isFlicking())
movementEnding(false, true);
- if (!qFuzzyCompare(-pos, d->vData.move.value()))
+ if (!qFuzzyCompare(-pos, d->vData.move.value())) {
+ d->vData.contentPositionChangedExternallyDuringDrag = d->vData.dragging;
d->vData.move.setValue(-pos);
+ d->vData.contentPositionChangedExternallyDuringDrag = false;
+ }
}
/*!
@@ -1103,7 +1116,9 @@ void QQuickFlickablePrivate::maybeBeginDrag(qint64 currentTimestamp, const QPoin
pressPos = pressPosn;
hData.pressPos = hData.move.value();
vData.pressPos = vData.move.value();
- bool wasFlicking = hData.flicking || vData.flicking;
+ const bool wasFlicking = hData.flicking || vData.flicking;
+ hData.flickingWhenDragBegan = hData.flicking;
+ vData.flickingWhenDragBegan = vData.flicking;
if (hData.flicking) {
hData.flicking = false;
emit q->flickingHorizontallyChanged();
@@ -1434,8 +1449,15 @@ void QQuickFlickablePrivate::handleReleaseEvent(QPointerEvent *event)
fixupX();
flickingStarted(flickedHorizontally, flickedVertically);
- if (!isViewMoving())
+ if (!isViewMoving()) {
q->movementEnding();
+ } else {
+ if (flickedVertically)
+ vMoved = true;
+ if (flickedHorizontally)
+ hMoved = true;
+ q->movementStarting();
+ }
}
void QQuickFlickable::mousePressEvent(QMouseEvent *event)
@@ -2515,6 +2537,18 @@ bool QQuickFlickable::filterPointerEvent(QQuickItem *receiver, QPointerEvent *ev
if (isTouch && static_cast<QTouchEvent *>(event)->touchPointStates().testFlag(QEventPoint::State::Pressed))
d->stealMouse = false;
const auto &firstPoint = event->points().first();
+
+ if (event->pointCount() == 1 && event->exclusiveGrabber(firstPoint) == this) {
+ // We have an exclusive grab (since we're e.g dragging), but at the same time, we have
+ // a child with a passive grab (which is why this filter is being called). And because
+ // of that, we end up getting the same pointer events twice; First in our own event
+ // handlers (because of the grab), then once more in here, since we filter the child.
+ // To avoid processing the event twice (e.g avoid calling handleReleaseEvent once more
+ // from below), we mark the event as filtered, and simply return.
+ event->setAccepted(true);
+ return true;
+ }
+
QPointF localPos = mapFromScene(firstPoint.scenePosition());
bool receiverDisabled = receiver && !receiver->isEnabled();
bool stealThisEvent = d->stealMouse;
@@ -2884,6 +2918,12 @@ void QQuickFlickable::movementStarting()
if (!wasMoving && (d->hData.moving || d->vData.moving)) {
emit movingChanged();
emit movementStarted();
+#if QT_CONFIG(accessibility)
+ if (QAccessible::isActive()) {
+ QAccessibleEvent ev(this, QAccessible::ScrollingStart);
+ QAccessible::updateAccessibility(&ev);
+ }
+#endif
}
}
@@ -2897,7 +2937,7 @@ void QQuickFlickable::movementEnding(bool hMovementEnding, bool vMovementEnding)
Q_D(QQuickFlickable);
// emit flicking signals
- bool wasFlicking = d->hData.flicking || d->vData.flicking;
+ const bool wasFlicking = d->hData.flicking || d->vData.flicking;
if (hMovementEnding && d->hData.flicking) {
d->hData.flicking = false;
emit flickingHorizontallyChanged();
@@ -2909,6 +2949,10 @@ void QQuickFlickable::movementEnding(bool hMovementEnding, bool vMovementEnding)
if (wasFlicking && (!d->hData.flicking || !d->vData.flicking)) {
emit flickingChanged();
emit flickEnded();
+ } else if (d->hData.flickingWhenDragBegan || d->vData.flickingWhenDragBegan) {
+ d->hData.flickingWhenDragBegan = !hMovementEnding;
+ d->vData.flickingWhenDragBegan = !vMovementEnding;
+ emit flickEnded();
}
// emit moving signals
@@ -2928,6 +2972,12 @@ void QQuickFlickable::movementEnding(bool hMovementEnding, bool vMovementEnding)
if (wasMoving && !isMoving()) {
emit movingChanged();
emit movementEnded();
+#if QT_CONFIG(accessibility)
+ if (QAccessible::isActive()) {
+ QAccessibleEvent ev(this, QAccessible::ScrollingEnd);
+ QAccessible::updateAccessibility(&ev);
+ }
+#endif
}
if (hMovementEnding) {
diff --git a/src/quick/items/qquickflickable_p_p.h b/src/quick/items/qquickflickable_p_p.h
index ed7042ab90..04d27c0b8e 100644
--- a/src/quick/items/qquickflickable_p_p.h
+++ b/src/quick/items/qquickflickable_p_p.h
@@ -71,8 +71,9 @@ public:
, smoothVelocity(fp), atEnd(false), atBeginning(true)
, transitionToSet(false)
, fixingUp(false), inOvershoot(false), inRebound(false), moving(false), flicking(false)
- , dragging(false), extentsChanged(false)
+ , flickingWhenDragBegan(false), dragging(false), extentsChanged(false)
, explicitValue(false), minExtentDirty(true), maxExtentDirty(true)
+ , contentPositionChangedExternallyDuringDrag(false)
, unused(0)
{}
@@ -83,6 +84,7 @@ public:
dragStartOffset = 0;
fixingUp = false;
inOvershoot = false;
+ contentPositionChangedExternallyDuringDrag = false;
}
void markExtentsDirty() {
@@ -120,20 +122,22 @@ public:
int vTime;
QQuickFlickablePrivate::Velocity smoothVelocity;
QPODVector<qreal,10> velocityBuffer;
- bool atEnd : 1;
- bool atBeginning : 1;
- bool transitionToSet : 1;
- bool fixingUp : 1;
- bool inOvershoot : 1;
- bool inRebound : 1;
- bool moving : 1;
- bool flicking : 1;
- bool dragging : 1;
- bool extentsChanged : 1;
- bool explicitValue : 1;
- mutable bool minExtentDirty : 1;
- mutable bool maxExtentDirty : 1;
- uint unused : 19;
+ uint atEnd : 1;
+ uint atBeginning : 1;
+ uint transitionToSet : 1;
+ uint fixingUp : 1;
+ uint inOvershoot : 1;
+ uint inRebound : 1;
+ uint moving : 1;
+ uint flicking : 1;
+ uint flickingWhenDragBegan : 1;
+ uint dragging : 1;
+ uint extentsChanged : 1;
+ uint explicitValue : 1;
+ mutable uint minExtentDirty : 1;
+ mutable uint maxExtentDirty : 1;
+ uint contentPositionChangedExternallyDuringDrag : 1;
+ uint unused : 17;
};
bool flickX(qreal velocity);
diff --git a/src/quick/items/qquickflipable.cpp b/src/quick/items/qquickflipable.cpp
index d599618834..4ea085bb0c 100644
--- a/src/quick/items/qquickflipable.cpp
+++ b/src/quick/items/qquickflipable.cpp
@@ -3,7 +3,7 @@
#include "qquickflipable_p.h"
#include "qquickitem_p.h"
-
+#include "qquicktranslate_p.h"
#include <QtQml/qqmlinfo.h>
@@ -201,9 +201,20 @@ void QQuickFlipable::updatePolish()
d->updateSide();
}
-// determination on the currently visible side of the flipable
-// has to be done on the complete scene transform to give
-// correct results.
+/*! \internal
+ Flipable must use the complete scene transform to correctly determine the
+ currently visible side.
+
+ It must also be independent of camera distance, in case the contents are
+ too wide: for rotation transforms we simply call QMatrix4x4::rotate(),
+ whereas QQuickRotation::applyTo(QMatrix4x4*) calls
+ QMatrix4x4::projectedRotate() which by default assumes the camera distance
+ is 1024 virtual pixels. So for example if contents inside Flipable are to
+ be flipped around the y axis, and are wider than 1024*2, some of the
+ rendering goes behind the "camera". That's expected for rendering (since we
+ didn't provide API to change camera distance), but not ok for deciding when
+ to flip.
+*/
void QQuickFlipablePrivate::updateSide()
{
Q_Q(QQuickFlipable);
@@ -213,8 +224,39 @@ void QQuickFlipablePrivate::updateSide()
sideDirty = false;
- QTransform sceneTransform;
- itemToParentTransform(sceneTransform);
+ QMatrix4x4 sceneTransform;
+
+ const qreal tx = x.value();
+ const qreal ty = y.value();
+ if (!qFuzzyIsNull(tx) || !qFuzzyIsNull(ty))
+ sceneTransform.translate(tx, ty);
+
+ for (const auto *transform : std::as_const(transforms)) {
+ if (const auto *rot = qobject_cast<const QQuickRotation *>(transform)) {
+ // rotation is a special case: we want to call rotate() instead of projectedRotate()
+ const auto angle = rot->angle();
+ const auto axis = rot->axis();
+ if (!(qFuzzyIsNull(angle) || axis.isNull())) {
+ sceneTransform.translate(rot->origin());
+ sceneTransform.rotate(angle, axis.x(), axis.y(), axis.z());
+ sceneTransform.translate(-rot->origin());
+ }
+ } else {
+ transform->applyTo(&sceneTransform);
+ }
+ }
+
+ const bool hasRotation = !qFuzzyIsNull(rotation());
+ const bool hasScale = !qFuzzyCompare(scale(), 1);
+ if (hasScale || hasRotation) {
+ QPointF tp = computeTransformOrigin();
+ sceneTransform.translate(tp.x(), tp.y());
+ if (hasScale)
+ sceneTransform.scale(scale(), scale());
+ if (hasRotation)
+ sceneTransform.rotate(rotation(), 0, 0, 1);
+ sceneTransform.translate(-tp.x(), -tp.y());
+ }
QPointF p1(0, 0);
QPointF p2(1, 0);
diff --git a/src/quick/items/qquickgridview.cpp b/src/quick/items/qquickgridview.cpp
index d3dfe51d11..7f45d45708 100644
--- a/src/quick/items/qquickgridview.cpp
+++ b/src/quick/items/qquickgridview.cpp
@@ -462,7 +462,7 @@ bool QQuickGridViewPrivate::addVisibleItems(qreal fillFrom, qreal fillTo, qreal
{
qreal colPos = colPosAt(visibleIndex);
qreal rowPos = rowPosAt(visibleIndex);
- if (visibleItems.count()) {
+ if (visibleItems.size()) {
FxGridItemSG *lastItem = static_cast<FxGridItemSG*>(visibleItems.constLast());
rowPos = lastItem->rowPos();
int colNum = qFloor((lastItem->colPos()+colSize()/2) / colSize());
@@ -476,7 +476,7 @@ bool QQuickGridViewPrivate::addVisibleItems(qreal fillFrom, qreal fillTo, qreal
int modelIndex = findLastVisibleIndex();
modelIndex = modelIndex < 0 ? visibleIndex : modelIndex + 1;
- if (visibleItems.count() && (bufferFrom > rowPos + rowSize()*2
+ if (visibleItems.size() && (bufferFrom > rowPos + rowSize()*2
|| bufferTo < rowPosAt(visibleIndex) - rowSize())) {
// We've jumped more than a page. Estimate which items are now
// visible and fill from there.
@@ -520,7 +520,7 @@ bool QQuickGridViewPrivate::addVisibleItems(qreal fillFrom, qreal fillTo, qreal
return changed;
// Find first column
- if (visibleItems.count()) {
+ if (visibleItems.size()) {
FxGridItemSG *firstItem = static_cast<FxGridItemSG*>(visibleItems.constFirst());
rowPos = firstItem->rowPos();
colPos = firstItem->colPos();
@@ -569,7 +569,7 @@ bool QQuickGridViewPrivate::removeNonVisibleItems(qreal bufferFrom, qreal buffer
FxGridItemSG *item = nullptr;
bool changed = false;
- while (visibleItems.count() > 1
+ while (visibleItems.size() > 1
&& (item = static_cast<FxGridItemSG*>(visibleItems.constFirst()))
&& item->rowPos()+rowSize()-1 < bufferFrom - rowSize()*(item->colPos()/colSize()+1)/(columns+1)) {
if (item->attached->delayRemove())
@@ -581,12 +581,12 @@ bool QQuickGridViewPrivate::removeNonVisibleItems(qreal bufferFrom, qreal buffer
removeItem(item);
changed = true;
}
- while (visibleItems.count() > 1
+ while (visibleItems.size() > 1
&& (item = static_cast<FxGridItemSG*>(visibleItems.constLast()))
&& item->rowPos() > bufferTo + rowSize()*(columns - item->colPos()/colSize())/(columns+1)) {
if (item->attached->delayRemove())
break;
- qCDebug(lcItemViewDelegateLifecycle) << "refill: remove last" << visibleIndex+visibleItems.count()-1;
+ qCDebug(lcItemViewDelegateLifecycle) << "refill: remove last" << visibleIndex+visibleItems.size()-1;
visibleItems.removeLast();
removeItem(item);
changed = true;
@@ -603,7 +603,7 @@ void QQuickGridViewPrivate::updateViewport()
void QQuickGridViewPrivate::layoutVisibleItems(int fromModelIndex)
{
- if (visibleItems.count()) {
+ if (visibleItems.size()) {
const qreal from = isContentFlowReversed() ? -position()-displayMarginBeginning-size() : position()-displayMarginBeginning;
const qreal to = isContentFlowReversed() ? -position()+displayMarginEnd : position()+size()+displayMarginEnd;
@@ -616,7 +616,7 @@ void QQuickGridViewPrivate::layoutVisibleItems(int fromModelIndex)
firstItem->setPosition(colPos, rowPos);
}
firstItem->setVisible(firstItem->rowPos() + rowSize() >= from && firstItem->rowPos() <= to);
- for (int i = 1; i < visibleItems.count(); ++i) {
+ for (int i = 1; i < visibleItems.size(); ++i) {
FxGridItemSG *item = static_cast<FxGridItemSG*>(visibleItems.at(i));
if (++col >= columns) {
col = 0;
@@ -669,7 +669,7 @@ void QQuickGridViewPrivate::resetFirstItemPosition(qreal pos)
void QQuickGridViewPrivate::adjustFirstItem(qreal forwards, qreal backwards, int changeBeforeVisible)
{
- if (!visibleItems.count())
+ if (!visibleItems.size())
return;
int moveCount = (forwards - backwards) / rowSize();
@@ -802,7 +802,7 @@ void QQuickGridViewPrivate::updateFooter()
else
rowOffset += gridItem->item->height() - cellHeight;
}
- if (visibleItems.count()) {
+ if (visibleItems.size()) {
qreal endPos = lastPosition();
if (findLastVisibleIndex() == model->count()-1) {
gridItem->setPosition(colOffset, endPos + rowOffset);
@@ -855,7 +855,7 @@ void QQuickGridViewPrivate::updateHeader()
else
rowOffset += gridItem->item->height() - cellHeight;
}
- if (visibleItems.count()) {
+ if (visibleItems.size()) {
qreal startPos = originPosition();
if (visibleIndex == 0) {
gridItem->setPosition(colOffset, startPos + rowOffset);
@@ -2066,7 +2066,7 @@ void QQuickGridView::viewportMoved(Qt::Orientations orient)
// Set visibility of items to eliminate cost of items outside the visible area.
qreal from = d->isContentFlowReversed() ? -d->position()-d->displayMarginBeginning-d->size() : d->position()-d->displayMarginBeginning;
qreal to = d->isContentFlowReversed() ? -d->position()+d->displayMarginEnd : d->position()+d->size()+d->displayMarginEnd;
- for (FxViewItem *item : qAsConst(d->visibleItems)) {
+ for (FxViewItem *item : std::as_const(d->visibleItems)) {
FxGridItemSG *gridItem = static_cast<FxGridItemSG*>(item);
QQuickItemPrivate::get(gridItem->item)->setCulled(gridItem->rowPos() + d->rowSize() < from || gridItem->rowPos() > to);
}
@@ -2359,20 +2359,20 @@ bool QQuickGridViewPrivate::applyInsertionChange(const QQmlChangeSet::Change &ch
int modelIndex = change.index;
int count = change.count;
- int index = visibleItems.count() ? mapFromModel(modelIndex) : 0;
+ int index = visibleItems.size() ? mapFromModel(modelIndex) : 0;
if (index < 0) {
- int i = visibleItems.count() - 1;
+ int i = visibleItems.size() - 1;
while (i > 0 && visibleItems.at(i)->index == -1)
--i;
if (visibleItems.at(i)->index + 1 == modelIndex) {
// Special case of appending an item to the model.
- index = visibleItems.count();
+ index = visibleItems.size();
} else {
if (modelIndex <= visibleIndex) {
// Insert before visible items
visibleIndex += count;
- for (FxViewItem *item : qAsConst(visibleItems)) {
+ for (FxViewItem *item : std::as_const(visibleItems)) {
if (item->index != -1 && item->index >= modelIndex)
item->index += count;
}
@@ -2385,8 +2385,8 @@ bool QQuickGridViewPrivate::applyInsertionChange(const QQmlChangeSet::Change &ch
qreal colPos = 0;
qreal rowPos = 0;
int colNum = 0;
- if (visibleItems.count()) {
- if (index < visibleItems.count()) {
+ if (visibleItems.size()) {
+ if (index < visibleItems.size()) {
FxGridItemSG *gridItem = static_cast<FxGridItemSG*>(visibleItems.at(index));
colPos = gridItem->colPos();
rowPos = gridItem->rowPos();
@@ -2405,7 +2405,7 @@ bool QQuickGridViewPrivate::applyInsertionChange(const QQmlChangeSet::Change &ch
}
// Update the indexes of the following visible items.
- for (FxViewItem *item : qAsConst(visibleItems)) {
+ for (FxViewItem *item : std::as_const(visibleItems)) {
if (item->index != -1 && item->index >= modelIndex) {
item->index += count;
if (change.isMove())
@@ -2415,7 +2415,7 @@ bool QQuickGridViewPrivate::applyInsertionChange(const QQmlChangeSet::Change &ch
}
}
- int prevVisibleCount = visibleItems.count();
+ int prevVisibleCount = visibleItems.size();
if (insertResult->visiblePos.isValid() && rowPos < insertResult->visiblePos) {
// Insert items before the visible item.
int insertionIdx = index;
@@ -2464,7 +2464,7 @@ bool QQuickGridViewPrivate::applyInsertionChange(const QQmlChangeSet::Change &ch
// of the index shift/update done before the insertion just above.
// Find if there is any...
int firstOkIdx = -1;
- for (int i = 0; i <= insertionIdx && i < visibleItems.count() - 1; i++) {
+ for (int i = 0; i <= insertionIdx && i < visibleItems.size() - 1; i++) {
if (visibleItems.at(i)->index + 1 != visibleItems.at(i + 1)->index) {
firstOkIdx = i + 1;
break;
@@ -2520,7 +2520,7 @@ bool QQuickGridViewPrivate::applyInsertionChange(const QQmlChangeSet::Change &ch
updateVisibleIndex();
- return visibleItems.count() > prevVisibleCount;
+ return visibleItems.size() > prevVisibleCount;
}
void QQuickGridViewPrivate::translateAndTransitionItemsAfter(int afterModelIndex, const ChangeResult &insertionResult, const ChangeResult &removalResult)
@@ -2529,7 +2529,7 @@ void QQuickGridViewPrivate::translateAndTransitionItemsAfter(int afterModelIndex
return;
int markerItemIndex = -1;
- for (int i=0; i<visibleItems.count(); i++) {
+ for (int i=0; i<visibleItems.size(); i++) {
if (visibleItems.at(i)->index == afterModelIndex) {
markerItemIndex = i;
break;
@@ -2548,7 +2548,7 @@ void QQuickGridViewPrivate::translateAndTransitionItemsAfter(int afterModelIndex
countItemsRemoved -= removalResult.countChangeAfterVisibleItems;
- for (int i=markerItemIndex+1; i<visibleItems.count(); i++) {
+ for (int i=markerItemIndex+1; i<visibleItems.size(); i++) {
FxGridItemSG *gridItem = static_cast<FxGridItemSG *>(visibleItems.at(i));
if (gridItem->position() >= viewEndPos)
break;
diff --git a/src/quick/items/qquickimagebase.cpp b/src/quick/items/qquickimagebase.cpp
index f10446b7b5..78dfecc42a 100644
--- a/src/quick/items/qquickimagebase.cpp
+++ b/src/quick/items/qquickimagebase.cpp
@@ -291,8 +291,10 @@ void QQuickImageBase::loadPixmap(const QUrl &url, LoadPixmapOptions loadOptions)
const qreal targetDevicePixelRatio = (window() ? window()->effectiveDevicePixelRatio() : qApp->devicePixelRatio());
d->devicePixelRatio = 1.0;
bool updatedDevicePixelRatio = false;
- if (d->sourcesize.isValid() || isScalableImageFormat(d->url))
+ if (d->sourcesize.isValid()
+ || (isScalableImageFormat(d->url) && d->url.scheme() != QLatin1String("image"))) {
updatedDevicePixelRatio = d->updateDevicePixelRatio(targetDevicePixelRatio);
+ }
if (!updatedDevicePixelRatio) {
// (possible) local file: loadUrl and d->devicePixelRatio will be modified if
diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp
index dc1386fff9..b9f757dd78 100644
--- a/src/quick/items/qquickitem.cpp
+++ b/src/quick/items/qquickitem.cpp
@@ -61,6 +61,10 @@ Q_DECLARE_LOGGING_CATEGORY(lcPtr)
Q_DECLARE_LOGGING_CATEGORY(lcTransient)
Q_LOGGING_CATEGORY(lcHandlerParent, "qt.quick.handler.parent")
Q_LOGGING_CATEGORY(lcVP, "qt.quick.viewport")
+Q_LOGGING_CATEGORY(lcChangeListeners, "qt.quick.item.changelisteners")
+
+// after 100ms, a mouse/non-mouse cursor conflict is resolved in favor of the mouse handler
+static const quint64 kCursorOverrideTimeout = 100;
void debugFocusTree(QQuickItem *item, QQuickItem *scope = nullptr, int depth = 1)
{
@@ -319,6 +323,8 @@ void QQuickItemKeyFilter::shortcutOverride(QKeyEvent *event)
{
if (m_next)
m_next->shortcutOverride(event);
+ else
+ event->ignore();
}
void QQuickItemKeyFilter::componentComplete()
@@ -2614,6 +2620,12 @@ QQuickItem* QQuickItemPrivate::nextPrevItemInTabFocusChain(QQuickItem *item, boo
\e {QObject parent}. An item's visual parent may not necessarily be the
same as its object parent. See \l {Concepts - Visual Parent in Qt Quick}
for more details.
+
+ \note The notification signal for this property gets emitted during destruction
+ of the visual parent. C++ signal handlers cannot assume that items in the
+ visual parent hierarchy are still fully constructed. Use \l qobject_cast to
+ verify that items in the parent hierarchy can be used safely as the expected
+ type.
*/
QQuickItem *QQuickItem::parentItem() const
{
@@ -3362,7 +3374,7 @@ void QQuickItemPrivate::resources_clear(QQmlListProperty<QObject> *prop)
QQuickItem *quickItem = static_cast<QQuickItem *>(prop->object);
QQuickItemPrivate *quickItemPrivate = QQuickItemPrivate::get(quickItem);
if (quickItemPrivate->extra.isAllocated()) {//If extra is not allocated resources is empty.
- for (QObject *object : qAsConst(quickItemPrivate->extra->resourcesList)) {
+ for (QObject *object : std::as_const(quickItemPrivate->extra->resourcesList)) {
qmlobject_disconnect(object, QObject, SIGNAL(destroyed(QObject*)),
quickItem, QQuickItem, SLOT(_q_resourceObjectDeleted(QObject*)));
}
@@ -3890,9 +3902,23 @@ void QQuickItem::updatePolish()
{
}
+#define PRINT_LISTENERS() \
+do { \
+ qDebug().nospace() << q_func() << " (" << this \
+ << ") now has the following listeners:"; \
+ for (const auto &listener : std::as_const(changeListeners)) { \
+ const auto objectPrivate = dynamic_cast<QObjectPrivate*>(listener.listener); \
+ qDebug().nospace() << "- " << listener << " (QObject: " << (objectPrivate ? objectPrivate->q_func() : nullptr) << ")"; \
+ } \
+} \
+while (false)
+
void QQuickItemPrivate::addItemChangeListener(QQuickItemChangeListener *listener, ChangeTypes types)
{
changeListeners.append(ChangeListener(listener, types));
+
+ if (lcChangeListeners().isDebugEnabled())
+ PRINT_LISTENERS();
}
void QQuickItemPrivate::updateOrAddItemChangeListener(QQuickItemChangeListener *listener, ChangeTypes types)
@@ -3903,12 +3929,18 @@ void QQuickItemPrivate::updateOrAddItemChangeListener(QQuickItemChangeListener *
changeListeners[index].types = changeListener.types;
else
changeListeners.append(changeListener);
+
+ if (lcChangeListeners().isDebugEnabled())
+ PRINT_LISTENERS();
}
void QQuickItemPrivate::removeItemChangeListener(QQuickItemChangeListener *listener, ChangeTypes types)
{
ChangeListener change(listener, types);
changeListeners.removeOne(change);
+
+ if (lcChangeListeners().isDebugEnabled())
+ PRINT_LISTENERS();
}
void QQuickItemPrivate::updateOrAddGeometryChangeListener(QQuickItemChangeListener *listener,
@@ -3920,6 +3952,9 @@ void QQuickItemPrivate::updateOrAddGeometryChangeListener(QQuickItemChangeListen
changeListeners[index].gTypes = change.gTypes; //we may have different GeometryChangeTypes
else
changeListeners.append(change);
+
+ if (lcChangeListeners().isDebugEnabled())
+ PRINT_LISTENERS();
}
void QQuickItemPrivate::updateOrRemoveGeometryChangeListener(QQuickItemChangeListener *listener,
@@ -3933,6 +3968,9 @@ void QQuickItemPrivate::updateOrRemoveGeometryChangeListener(QQuickItemChangeLis
if (index > -1)
changeListeners[index].gTypes = change.gTypes; //we may have different GeometryChangeTypes
}
+
+ if (lcChangeListeners().isDebugEnabled())
+ PRINT_LISTENERS();
}
/*!
@@ -5192,6 +5230,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()
@@ -5477,9 +5522,10 @@ void QQuickItemPrivate::deliverInputMethodEvent(QInputMethodEvent *e)
void QQuickItemPrivate::deliverShortcutOverrideEvent(QKeyEvent *event)
{
- if (extra.isAllocated() && extra->keyHandler) {
+ if (extra.isAllocated() && extra->keyHandler)
extra->keyHandler->shortcutOverride(event);
- }
+ else
+ event->ignore();
}
bool QQuickItemPrivate::anyPointerHandlerWants(const QPointerEvent *event, const QEventPoint &point) const
@@ -5496,8 +5542,8 @@ bool QQuickItemPrivate::anyPointerHandlerWants(const QPointerEvent *event, const
/*!
\internal
Deliver the \a event to all this item's PointerHandlers, but skip
- HoverHandlers if the event is a QMouseEvent (they are visited in
- QQuickDeliveryAgentPrivate::deliverHoverEventToItem()), and skip handlers
+ HoverHandlers if the event is a QMouseEvent or QWheelEvent (they are visited
+ in QQuickDeliveryAgentPrivate::deliverHoverEventToItem()), and skip handlers
that are in QQuickPointerHandlerPrivate::deviceDeliveryTargets().
If \a avoidGrabbers is true, also skip delivery to any handler that
is exclusively or passively grabbing any point within \a event
@@ -5509,7 +5555,7 @@ bool QQuickItemPrivate::handlePointerEvent(QPointerEvent *event, bool avoidGrabb
if (extra.isAllocated()) {
for (QQuickPointerHandler *handler : extra->pointerHandlers) {
bool avoidThisHandler = false;
- if (QQuickDeliveryAgentPrivate::isMouseEvent(event) &&
+ if (QQuickDeliveryAgentPrivate::isMouseOrWheelEvent(event) &&
qmlobject_cast<const QQuickHoverHandler *>(handler)) {
avoidThisHandler = true;
} else if (avoidGrabbers) {
@@ -6247,6 +6293,12 @@ void QQuickItem::setOpacity(qreal newOpacity)
the parent's \c visible property. It does not change, for example, if this
item moves off-screen, or if the \l opacity changes to 0.
+ \note The notification signal for this property gets emitted during destruction
+ of the visual parent. C++ signal handlers cannot assume that items in the
+ visual parent hierarchy are still fully constructed. Use \l qobject_cast to
+ verify that items in the parent hierarchy can be used safely as the expected
+ type.
+
\sa opacity, enabled
*/
bool QQuickItem::isVisible() const
@@ -6305,6 +6357,15 @@ void QQuickItem::setVisible(bool v)
Setting this property to \c false automatically causes \l activeFocus to be
set to \c false, and this item will longer receive keyboard events.
+ \note Hover events are enabled separately by \l setAcceptHoverEvents().
+ Thus, a disabled item can continue to receive hover events, even when this
+ property is \c false. This makes it possible to show informational feedback
+ (such as \l ToolTip) even when an interactive item is disabled.
+ The same is also true for any \l {HoverHandlers}{QQuickHoverHandler}
+ added as children of the item. A HoverHandler can, however, be
+ \l{disabled}{QQuickHoverHandler::enabled} explicitly, or for example
+ be bound to the \c enabled state of the item.
+
\sa visible
*/
bool QQuickItem::isEnabled() const
@@ -7788,6 +7849,10 @@ void QQuickItem::setAcceptHoverEvents(bool enabled)
Q_D(QQuickItem);
d->hoverEnabled = enabled;
d->setHasHoverInChild(enabled);
+ // The DA needs to resolve which items and handlers should now be hovered or unhovered.
+ // Marking this item dirty ensures that flushFrameSynchronousEvents() will be called from the render loop,
+ // even if this change is not in response to a mouse event and no item has already marked itself dirty.
+ d->dirty(QQuickItemPrivate::Content);
}
/*!
@@ -7830,7 +7895,7 @@ void QQuickItemPrivate::setHasCursorInChild(bool hc)
if (!hc && subtreeCursorEnabled) {
if (hasCursor)
return; // nope! sorry, I have a cursor myself
- for (QQuickItem *otherChild : qAsConst(childItems)) {
+ for (QQuickItem *otherChild : std::as_const(childItems)) {
QQuickItemPrivate *otherChildPrivate = QQuickItemPrivate::get(otherChild);
if (otherChildPrivate->subtreeCursorEnabled || otherChildPrivate->hasCursor)
return; // nope! sorry, something else wants it kept on.
@@ -7857,11 +7922,14 @@ void QQuickItemPrivate::setHasHoverInChild(bool hasHover)
if (!hasHover && subtreeHoverEnabled) {
if (hoverEnabled)
return; // nope! sorry, I need hover myself
- for (QQuickItem *otherChild : qAsConst(childItems)) {
+ if (hasEnabledHoverHandlers())
+ return; // nope! sorry, this item has enabled HoverHandlers
+
+ for (QQuickItem *otherChild : std::as_const(childItems)) {
QQuickItemPrivate *otherChildPrivate = QQuickItemPrivate::get(otherChild);
if (otherChildPrivate->subtreeHoverEnabled || otherChildPrivate->hoverEnabled)
return; // nope! sorry, something else wants it kept on.
- if (otherChildPrivate->hasHoverHandlers())
+ if (otherChildPrivate->hasEnabledHoverHandlers())
return; // nope! sorry, we have pointer handlers which are interested.
}
}
@@ -7910,6 +7978,7 @@ void QQuickItem::setCursor(const QCursor &cursor)
Q_D(QQuickItem);
Qt::CursorShape oldShape = d->extra.isAllocated() ? d->extra->cursor.shape() : Qt::ArrowCursor;
+ qCDebug(lcHoverTrace) << oldShape << "->" << cursor.shape();
if (oldShape != cursor.shape() || oldShape >= Qt::LastCursor || cursor.shape() >= Qt::LastCursor) {
d->extra.value().cursor = cursor;
@@ -7946,6 +8015,7 @@ void QQuickItem::setCursor(const QCursor &cursor)
void QQuickItem::unsetCursor()
{
Q_D(QQuickItem);
+ qCDebug(lcHoverTrace) << "clearing cursor";
if (!d->hasCursor)
return;
d->hasCursor = false;
@@ -7997,27 +8067,82 @@ QCursor QQuickItemPrivate::effectiveCursor(const QQuickPointerHandler *handler)
Returns the Pointer Handler that is currently attempting to set the cursor shape,
or null if there is no such handler.
+ If there are multiple handlers attempting to set the cursor:
+ \list
+ \li an active handler has the highest priority (e.g. a DragHandler being dragged)
+ \li any HoverHandler that is reacting to a non-mouse device has priority for
+ kCursorOverrideTimeout ms (a tablet stylus is jittery so that's enough)
+ \li otherwise a HoverHandler that is reacting to the mouse, if any
+ \endlist
+
+ Within each category, if there are multiple handlers, the last-added one wins
+ (the one that is declared at the bottom wins, because users may intuitively
+ think it's "on top" even though there is no Z-order; or, one that is added
+ in a specific use case overrides an imported component).
+
\sa QtQuick::PointerHandler::cursor
*/
QQuickPointerHandler *QQuickItemPrivate::effectiveCursorHandler() const
{
if (!hasPointerHandlers())
return nullptr;
- QQuickPointerHandler *retHoverHandler = nullptr;
+ QQuickPointerHandler* activeHandler = nullptr;
+ QQuickPointerHandler* mouseHandler = nullptr;
+ QQuickPointerHandler* nonMouseHandler = nullptr;
for (QQuickPointerHandler *h : extra->pointerHandlers) {
if (!h->isCursorShapeExplicitlySet())
continue;
QQuickHoverHandler *hoverHandler = qmlobject_cast<QQuickHoverHandler *>(h);
- // For now, we don't expect multiple hover handlers in one Item, so we choose the first one found;
- // but a future use case could be to have different cursors for different tablet stylus devices.
- // In that case, this function needs more information: which device did the event come from.
- // TODO Qt 6: add QPointerDevice* as argument to this function? (it doesn't exist yet in Qt 5)
- if (!retHoverHandler && hoverHandler)
- retHoverHandler = hoverHandler;
+ // Prioritize any HoverHandler that is reacting to a non-mouse device.
+ // Otherwise, choose the first hovered handler that is found.
+ // TODO maybe: there was an idea to add QPointerDevice* as argument to this function
+ // and check the device type, but why? HoverHandler already does that.
+ if (!activeHandler && hoverHandler && hoverHandler->isHovered()) {
+ qCDebug(lcHoverTrace) << hoverHandler << hoverHandler->acceptedDevices() << "wants to set cursor" << hoverHandler->cursorShape();
+ if (hoverHandler->acceptedDevices().testFlag(QPointingDevice::DeviceType::Mouse)) {
+ // If there's a conflict, the last-added HoverHandler wins. Maybe the user is overriding a default...
+ if (mouseHandler && mouseHandler->cursorShape() != hoverHandler->cursorShape()) {
+ qCDebug(lcHoverTrace) << "mouse cursor conflict:" << mouseHandler << "wants" << mouseHandler->cursorShape()
+ << "but" << hoverHandler << "wants" << hoverHandler->cursorShape();
+ }
+ mouseHandler = hoverHandler;
+ } else {
+ // If there's a conflict, the last-added HoverHandler wins.
+ if (nonMouseHandler && nonMouseHandler->cursorShape() != hoverHandler->cursorShape()) {
+ qCDebug(lcHoverTrace) << "non-mouse cursor conflict:" << nonMouseHandler << "wants" << nonMouseHandler->cursorShape()
+ << "but" << hoverHandler << "wants" << hoverHandler->cursorShape();
+ }
+ nonMouseHandler = hoverHandler;
+ }
+ }
if (!hoverHandler && h->active())
- return h;
+ activeHandler = h;
+ }
+ if (activeHandler) {
+ qCDebug(lcHoverTrace) << "active handler choosing cursor" << activeHandler << activeHandler->cursorShape();
+ return activeHandler;
+ }
+ // Mouse events are often synthetic; so if a HoverHandler for a non-mouse device wanted to set the cursor,
+ // let it win, unless more than kCursorOverrideTimeout ms have passed
+ // since the last time the non-mouse handler actually reacted to an event.
+ // We could miss the fact that a tablet stylus has left proximity, because we don't deliver proximity events to windows.
+ if (nonMouseHandler) {
+ if (mouseHandler) {
+ const bool beforeTimeout =
+ QQuickPointerHandlerPrivate::get(mouseHandler)->lastEventTime <
+ QQuickPointerHandlerPrivate::get(nonMouseHandler)->lastEventTime + kCursorOverrideTimeout;
+ QQuickPointerHandler *winner = (beforeTimeout ? nonMouseHandler : mouseHandler);
+ qCDebug(lcHoverTrace) << "non-mouse handler reacted last time:" << QQuickPointerHandlerPrivate::get(nonMouseHandler)->lastEventTime
+ << "and mouse handler reacted at time:" << QQuickPointerHandlerPrivate::get(mouseHandler)->lastEventTime
+ << "choosing cursor according to" << winner << winner->cursorShape();
+ return winner;
+ }
+ qCDebug(lcHoverTrace) << "non-mouse handler choosing cursor" << nonMouseHandler << nonMouseHandler->cursorShape();
+ return nonMouseHandler;
}
- return retHoverHandler;
+ if (mouseHandler)
+ qCDebug(lcHoverTrace) << "mouse handler choosing cursor" << mouseHandler << mouseHandler->cursorShape();
+ return mouseHandler;
}
#endif
@@ -8667,18 +8792,18 @@ bool QQuickItem::event(QEvent *ev)
#endif // gestures
case QEvent::LanguageChange:
case QEvent::LocaleChange:
- for (QQuickItem *item : qAsConst(d->childItems))
+ for (QQuickItem *item : std::as_const(d->childItems))
QCoreApplication::sendEvent(item, ev);
break;
case QEvent::WindowActivate:
case QEvent::WindowDeactivate:
if (d->providesPalette())
d->setCurrentColorGroup();
- for (QQuickItem *item : qAsConst(d->childItems))
+ for (QQuickItem *item : std::as_const(d->childItems))
QCoreApplication::sendEvent(item, ev);
break;
case QEvent::ApplicationPaletteChange:
- for (QQuickItem *item : qAsConst(d->childItems))
+ for (QQuickItem *item : std::as_const(d->childItems))
QCoreApplication::sendEvent(item, ev);
break;
default:
@@ -8873,8 +8998,8 @@ void QQuickItemPrivate::localizedTouchEvent(const QTouchEvent *event, bool isFil
// So hopefully if we start from one passive grabber and go up the parent chain from there,
// we will find any filtering parent items that exist.
auto handler = qmlobject_cast<QQuickPointerHandler *>(pg.first());
- Q_ASSERT(handler);
- pointGrabber = handler->parentItem();
+ if (handler)
+ pointGrabber = handler->parentItem();
}
}
@@ -8935,12 +9060,12 @@ bool QQuickItemPrivate::hasPointerHandlers() const
return extra.isAllocated() && !extra->pointerHandlers.isEmpty();
}
-bool QQuickItemPrivate::hasHoverHandlers() const
+bool QQuickItemPrivate::hasEnabledHoverHandlers() const
{
if (!hasPointerHandlers())
return false;
for (QQuickPointerHandler *h : extra->pointerHandlers)
- if (qmlobject_cast<QQuickHoverHandler *>(h))
+ if (auto *hh = qmlobject_cast<QQuickHoverHandler *>(h); hh && hh->enabled())
return true;
return false;
}
@@ -9460,7 +9585,8 @@ void QQuickItemLayer::itemSiblingOrderChanged(QQuickItem *)
void QQuickItemLayer::itemVisibilityChanged(QQuickItem *)
{
QQuickItem *l = m_effect ? (QQuickItem *) m_effect : (QQuickItem *) m_effectSource;
- Q_ASSERT(l);
+ if (!l)
+ return;
l->setVisible(m_item->isVisible());
}
@@ -9469,21 +9595,24 @@ void QQuickItemLayer::updateZ()
if (!m_componentComplete || !m_enabled)
return;
QQuickItem *l = m_effect ? (QQuickItem *) m_effect : (QQuickItem *) m_effectSource;
- Q_ASSERT(l);
+ if (!l)
+ return;
l->setZ(m_item->z());
}
void QQuickItemLayer::updateOpacity()
{
QQuickItem *l = m_effect ? (QQuickItem *) m_effect : (QQuickItem *) m_effectSource;
- Q_ASSERT(l);
+ if (!l)
+ return;
l->setOpacity(m_item->opacity());
}
void QQuickItemLayer::updateGeometry()
{
QQuickItem *l = m_effect ? (QQuickItem *) m_effect : (QQuickItem *) m_effectSource;
- Q_ASSERT(l);
+ if (!l)
+ return;
// Avoid calling QQuickImage::boundingRect() or other overrides
// which may not be up-to-date at this time (QTBUG-104442, 104536)
QRectF bounds = m_item->QQuickItem::boundingRect();
@@ -9498,7 +9627,8 @@ void QQuickItemLayer::updateMatrix()
if (!m_componentComplete || !m_enabled)
return;
QQuickItem *l = m_effect ? (QQuickItem *) m_effect : (QQuickItem *) m_effectSource;
- Q_ASSERT(l);
+ if (!l)
+ return;
QQuickItemPrivate *ld = QQuickItemPrivate::get(l);
l->setScale(m_item->scale());
l->setRotation(m_item->rotation());
@@ -9558,7 +9688,7 @@ void QV4::Heap::QQuickItemWrapper::markObjects(QV4::Heap::Base *that, QV4::MarkS
{
QObjectWrapper *This = static_cast<QObjectWrapper *>(that);
if (QQuickItem *item = static_cast<QQuickItem*>(This->object())) {
- for (QQuickItem *child : qAsConst(QQuickItemPrivate::get(item)->childItems))
+ for (QQuickItem *child : std::as_const(QQuickItemPrivate::get(item)->childItems))
QV4::QObjectWrapper::markWrapper(child, markStack);
}
QObjectWrapper::markObjects(that, markStack);
@@ -9569,6 +9699,13 @@ quint64 QQuickItemPrivate::_q_createJSWrapper(QV4::ExecutionEngine *engine)
return (engine->memoryManager->allocate<QQuickItemWrapper>(q_func()))->asReturnedValue();
}
+QDebug operator<<(QDebug debug, const QQuickItemPrivate::ChangeListener &listener)
+{
+ QDebugStateSaver stateSaver(debug);
+ debug.nospace() << "ChangeListener listener=" << listener.listener << " types=" << listener.types;
+ return debug;
+}
+
QT_END_NAMESPACE
#include <moc_qquickitem.cpp>
diff --git a/src/quick/items/qquickitem_p.h b/src/quick/items/qquickitem_p.h
index 4e5e5bb34a..428878c45d 100644
--- a/src/quick/items/qquickitem_p.h
+++ b/src/quick/items/qquickitem_p.h
@@ -248,7 +248,7 @@ public:
void localizedTouchEvent(const QTouchEvent *event, bool isFiltering, QMutableTouchEvent *localized);
bool hasPointerHandlers() const;
- bool hasHoverHandlers() const;
+ bool hasEnabledHoverHandlers() const;
virtual void addPointerHandler(QQuickPointerHandler *h);
virtual void removePointerHandler(QQuickPointerHandler *h);
@@ -323,6 +323,11 @@ public:
QQuickItemChangeListener *listener;
ChangeTypes types;
QQuickGeometryChange gTypes; //NOTE: not used for ==
+
+#ifndef QT_NO_DEBUG_STREAM
+ private:
+ friend QDebug operator<<(QDebug debug, const QQuickItemPrivate::ChangeListener &listener);
+#endif // QT_NO_DEBUG_STREAM
};
// call QQuickItemChangeListener PMF
diff --git a/src/quick/items/qquickitemanimation.cpp b/src/quick/items/qquickitemanimation.cpp
index 2a79908a3e..51fd2a3588 100644
--- a/src/quick/items/qquickitemanimation.cpp
+++ b/src/quick/items/qquickitemanimation.cpp
@@ -173,7 +173,7 @@ struct QQuickParentAnimationData : public QAbstractAnimationAction
QList<QQuickParentChange *> pc;
void doAction() override
{
- for (int ii = 0; ii < actions.count(); ++ii) {
+ for (int ii = 0; ii < actions.size(); ++ii) {
const QQuickStateAction &action = actions.at(ii);
if (reverse)
action.event->reverse();
@@ -329,7 +329,7 @@ QAbstractAnimationJob* QQuickParentAnimation::transition(QQuickStateActions &act
}
}
- if (data->actions.count()) {
+ if (data->actions.size()) {
QSequentialAnimationGroupJob *topLevelGroup = new QSequentialAnimationGroupJob;
QActionAnimation *viaAction = d->via ? new QActionAnimation : nullptr;
QActionAnimation *targetAction = new QActionAnimation;
@@ -343,7 +343,7 @@ QAbstractAnimationJob* QQuickParentAnimation::transition(QQuickStateActions &act
//take care of any child animations
bool valid = d->defaultProperty.isValid();
QAbstractAnimationJob* anim;
- for (int ii = 0; ii < d->animations.count(); ++ii) {
+ for (int ii = 0; ii < d->animations.size(); ++ii) {
if (valid)
d->animations.at(ii)->setDefaultTarget(d->defaultProperty);
anim = d->animations.at(ii)->transition(actions, modified, direction, defaultTarget);
@@ -488,7 +488,7 @@ QAbstractAnimationJob* QQuickAnchorAnimation::transition(QQuickStateActions &act
data->fromIsSourced = false;
data->fromIsDefined = false;
- for (int ii = 0; ii < actions.count(); ++ii) {
+ for (int ii = 0; ii < actions.size(); ++ii) {
QQuickStateAction &action = actions[ii];
if (action.event && action.event->type() == QQuickStateActionEvent::AnchorChanges
&& (d->targets.isEmpty() || d->targets.contains(static_cast<QQuickAnchorChanges*>(action.event)->object()))) {
@@ -497,7 +497,7 @@ QAbstractAnimationJob* QQuickAnchorAnimation::transition(QQuickStateActions &act
}
QQuickBulkValueAnimator *animator = new QQuickBulkValueAnimator;
- if (data->actions.count()) {
+ if (data->actions.size()) {
animator->setAnimValue(data);
animator->setFromIsSourcedValue(&data->fromIsSourced);
} else {
@@ -823,9 +823,9 @@ QAbstractAnimationJob* QQuickPathAnimation::transition(QQuickStateActions &actio
data->fromIsSourced = false;
data->fromIsDefined = (d->path && d->path->hasStartX() && d->path->hasStartY()) ? true : false;
data->toIsDefined = d->path ? true : false;
- int origModifiedSize = modified.count();
+ int origModifiedSize = modified.size();
- for (int i = 0; i < actions.count(); ++i) {
+ for (int i = 0; i < actions.size(); ++i) {
QQuickStateAction &action = actions[i];
if (action.event)
continue;
@@ -841,7 +841,7 @@ QAbstractAnimationJob* QQuickPathAnimation::transition(QQuickStateActions &actio
}
}
- if (target && d->path && (modified.count() > origModifiedSize || data->toIsDefined)) {
+ if (target && d->path && (modified.size() > origModifiedSize || data->toIsDefined)) {
data->target = target;
data->path = d->path;
data->path->invalidateSequentialHistory();
diff --git a/src/quick/items/qquickitemgrabresult.cpp b/src/quick/items/qquickitemgrabresult.cpp
index e14a4c25dd..bcd1afc19d 100644
--- a/src/quick/items/qquickitemgrabresult.cpp
+++ b/src/quick/items/qquickitemgrabresult.cpp
@@ -187,7 +187,7 @@ bool QQuickItemGrabResult::saveToFile(const QUrl &filePath) const
*/
bool QQuickItemGrabResult::saveToFile(const QString &fileName)
{
- return qAsConst(*this).saveToFile(fileName);
+ return std::as_const(*this).saveToFile(fileName);
}
#endif
#endif // < Qt 6
@@ -345,17 +345,15 @@ QSharedPointer<QQuickItemGrabResult> QQuickItem::grabToImage(const QSize &target
*
* If the grab could not be initiated, the function returns \c false.
*
- * The following snippet shows how to grab an item and store the results to
- * a file.
+ * The following snippet shows how to grab an item and store the results in
+ * a file:
*
- * \snippet qml/itemGrab.qml grab-source
- * \snippet qml/itemGrab.qml grab-to-file
+ * \snippet qml/item/itemGrab.qml grab-to-file
*
* The following snippet shows how to grab an item and use the results in
- * another image element.
+ * another image element:
*
- * \snippet qml/itemGrab.qml grab-image-target
- * \snippet qml/itemGrab.qml grab-to-cache
+ * \snippet qml/item/itemGrab.qml grab-to-image
*
* \note This function will render the item to an offscreen surface and
* copy that surface from the GPU's memory into the CPU's memory, which can
diff --git a/src/quick/items/qquickitemsmodule.cpp b/src/quick/items/qquickitemsmodule.cpp
index 9cff9c4c4f..88136d7fad 100644
--- a/src/quick/items/qquickitemsmodule.cpp
+++ b/src/quick/items/qquickitemsmodule.cpp
@@ -160,4 +160,138 @@ void QQuickItemsModule::defineModule()
qt_quickitems_defineModule();
}
+/*!
+ \qmltype PointerEvent
+ \instantiates QPointerEvent
+ \inqmlmodule QtQuick
+ \brief QML equivalent for \l QPointerEvent.
+
+ PointerEvent is the QML name of the QPointerEvent class.
+*/
+
+/*!
+ \qmltype PointerDevice
+ \instantiates QPointingDevice
+ \inqmlmodule QtQuick
+ \brief QML equivalent for \l QPointingDevice.
+
+ PointerDevice is the QML name of the QPointingDevice class.
+ It has the same properties and enums as \l QPointingDevice.
+*/
+
+/*!
+ \qmlproperty enumeration PointerDevice::deviceType
+
+ This property tells the type of device that generated a PointerEvent.
+
+ Valid values are:
+
+ \value PointerDevice.Unknown The device cannot be identified.
+ \value PointerDevice.Mouse A mouse.
+ \value PointerDevice.TouchScreen A touchscreen.
+ \value PointerDevice.TouchPad A touchpad or trackpad.
+ \value PointerDevice.Stylus A stylus on a graphics tablet.
+ \value PointerDevice.Airbrush An airbrush on a graphics tablet.
+ \value PointerDevice.Puck A digitizer with crosshairs, on a graphics tablet.
+
+ \sa QInputDevice::DeviceType, PointerDeviceHandler::acceptedDevices
+*/
+
+/*!
+ \qmlproperty enumeration PointerDevice::pointerType
+
+ This property tells what is interacting with the PointerDevice.
+
+ There is some redundancy between this property and \l deviceType.
+ For example, if a touchscreen is used, then \c deviceType is
+ \c TouchScreen and \c pointerType is \c Finger. But on a graphics
+ tablet, it's often possible for both ends of the stylus to be used,
+ and programs need to distinguish them.
+ \l PointerDeviceHandler::acceptedDevices and
+ \l PointerDeviceHandler::acceptedPointerTypes can be used in combination
+ to filter the subset of events that a particular handler should react to.
+
+ Valid values are:
+
+ \value PointerDevice.Unknown The device cannot be identified.
+ \value PointerDevice.Generic A mouse or a device that emulates a mouse.
+ \value PointerDevice.Finger A finger on a touchscreen.
+ \value PointerDevice.Pen A stylus on a graphics tablet.
+ \value PointerDevice.Eraser An eraser on a graphics tablet.
+ \value PointerDevice.Cursor A digitizer with crosshairs, on a graphics tablet.
+
+ \sa QPointingDevice::PointerType, PointerDeviceHandler::acceptedPointerTypes
+*/
+
+/*!
+ \qmlproperty int PointerDevice::maximumPoints
+
+ This property tells the maximum number of simultaneous touch points
+ (fingers) that can be detected.
+*/
+
+/*!
+ \qmlproperty int PointerDevice::buttonCount
+
+ This property tells the maximum number of on-device buttons that can be
+ detected.
+*/
+
+/*!
+ \qmltype pointingDeviceUniqueId
+ \instantiates QPointingDeviceUniqueId
+ \inqmlmodule QtQuick
+ \brief QML equivalent for \l QPointingDeviceUniqueId.
+
+ pointingDeviceUniqueId is the QML name of the QPointingDeviceUniqueId class.
+*/
+
+/*!
+ \qmlproperty qint64 pointingDeviceUniqueId::numericId
+
+ This property gives the numeric ID of the \l PointerDevice, if available;
+ otherwise it is \c -1.
+*/
+
+/*!
+ \qmlproperty pointingDeviceUniqueId PointerDevice::uniqueId
+
+ This property may provide a unique ID for the device, if available. For
+ example, a graphics tablet stylus device may have a unique serial number.
+
+ \sa eventPoint, QEventPoint::uniqueId()
+*/
+
+/*!
+ \qmlsignal PointerDevice::grabChanged(QtObject grabber, enumeration transition, PointerEvent event, eventPoint point)
+
+ This signal is emitted when the \a grabber object gains or loses an
+ exclusive or passive grab of \a point during delivery of \a event.
+ The \a transition tells what happened, from the perspective of the
+ \c grabber object, which may be either an \l Item or an
+ \l {Qt Quick Input Handlers}{Input Handler}.
+
+ Valid values for \a transition are:
+
+ \value GrabExclusive
+ The \a grabber has taken primary responsibility for handling the \a point.
+ \value UngrabExclusive
+ The \a grabber has given up its previous exclusive grab.
+ \value CancelGrabExclusive
+ The exclusive grab of \a grabber has been taken over or cancelled.
+ \value GrabPassive
+ The \a grabber has acquired a passive grab, to monitor the \a point.
+ \value UngrabPassive
+ The \a grabber has given up its previous passive grab.
+ \value CancelGrabPassive
+ The previous passive grab has terminated abnormally.
+
+ \note A grab transition from one object to another results in two signals,
+ to notify that one object has lost its grab, and to notify that there is
+ another grabber. In other cases, when transitioning to or from a non-grabbing
+ state, only one signal is emitted.
+
+ \sa QPointerEvent::setExclusiveGrabber(), QPointerEvent::addPassiveGrabber(), QPointerEvent::removePassiveGrabber()
+*/
+
QT_END_NAMESPACE
diff --git a/src/quick/items/qquickitemview.cpp b/src/quick/items/qquickitemview.cpp
index 627ee1e933..1f3ec79190 100644
--- a/src/quick/items/qquickitemview.cpp
+++ b/src/quick/items/qquickitemview.cpp
@@ -964,7 +964,7 @@ void QQuickItemViewPrivate::applyPendingChanges()
int QQuickItemViewPrivate::findMoveKeyIndex(QQmlChangeSet::MoveKey key, const QVector<QQmlChangeSet::Change> &changes) const
{
- for (int i=0; i<changes.count(); i++) {
+ for (int i=0; i<changes.size(); i++) {
for (int j=changes[i].index; j<changes[i].index + changes[i].count; j++) {
if (changes[i].moveKey(j) == key)
return j;
@@ -1101,7 +1101,7 @@ void QQuickItemViewPrivate::applyDelegateChange()
void QQuickItemViewPrivate::checkVisible() const
{
int skip = 0;
- for (int i = 0; i < visibleItems.count(); ++i) {
+ for (int i = 0; i < visibleItems.size(); ++i) {
FxViewItem *item = visibleItems.at(i);
if (item->index == -1) {
++skip;
@@ -1353,7 +1353,7 @@ qreal QQuickItemView::maxYExtent() const
{
Q_D(const QQuickItemView);
if (d->layoutOrientation() == Qt::Horizontal)
- return height();
+ return QQuickFlickable::maxYExtent();
if (d->vData.maxExtentDirty) {
d->maxExtent = d->maxExtentForAxis(d->vData, false);
@@ -1381,7 +1381,7 @@ qreal QQuickItemView::maxXExtent() const
{
Q_D(const QQuickItemView);
if (d->layoutOrientation() == Qt::Vertical)
- return width();
+ return QQuickFlickable::maxXExtent();
if (d->hData.maxExtentDirty) {
d->maxExtent = d->maxExtentForAxis(d->hData, true);
@@ -1564,8 +1564,8 @@ int QQuickItemViewPrivate::findLastVisibleIndex(int defaultValue) const
}
FxViewItem *QQuickItemViewPrivate::visibleItem(int modelIndex) const {
- if (modelIndex >= visibleIndex && modelIndex < visibleIndex + visibleItems.count()) {
- for (int i = modelIndex - visibleIndex; i < visibleItems.count(); ++i) {
+ if (modelIndex >= visibleIndex && modelIndex < visibleIndex + visibleItems.size()) {
+ for (int i = modelIndex - visibleIndex; i < visibleItems.size(); ++i) {
FxViewItem *item = visibleItems.at(i);
if (item->index == modelIndex)
return item;
@@ -1580,7 +1580,7 @@ FxViewItem *QQuickItemViewPrivate::firstItemInView() const {
if (item->index != -1 && item->endPosition() > pos)
return item;
}
- return visibleItems.count() ? visibleItems.first() : 0;
+ return visibleItems.size() ? visibleItems.first() : 0;
}
int QQuickItemViewPrivate::findLastIndexInView() const
@@ -1599,9 +1599,9 @@ int QQuickItemViewPrivate::findLastIndexInView() const
// e.g. doing a removal animation
int QQuickItemViewPrivate::mapFromModel(int modelIndex) const
{
- if (modelIndex < visibleIndex || modelIndex >= visibleIndex + visibleItems.count())
+ if (modelIndex < visibleIndex || modelIndex >= visibleIndex + visibleItems.size())
return -1;
- for (int i = 0; i < visibleItems.count(); ++i) {
+ for (int i = 0; i < visibleItems.size(); ++i) {
FxViewItem *item = visibleItems.at(i);
if (item->index == modelIndex)
return i;
@@ -1682,7 +1682,7 @@ void QQuickItemViewPrivate::clear(bool onDestruction)
releaseVisibleItems(QQmlInstanceModel::NotReusable);
visibleIndex = 0;
- for (FxViewItem *item : qAsConst(releasePendingTransition)) {
+ for (FxViewItem *item : std::as_const(releasePendingTransition)) {
item->releaseAfterTransition = false;
releaseItem(item, QQmlInstanceModel::NotReusable);
}
@@ -1832,7 +1832,7 @@ void QQuickItemViewPrivate::layout()
// viewBounds contains bounds before any add/remove/move operation to the view
QRectF viewBounds(q->contentX(), q->contentY(), q->width(), q->height());
- if (!isValid() && !visibleItems.count()) {
+ if (!isValid() && !visibleItems.size()) {
clear();
setPosition(contentStartOffset());
updateViewport();
@@ -1846,7 +1846,7 @@ void QQuickItemViewPrivate::layout()
&& transitioner->canTransition(QQuickItemViewTransitioner::RemoveTransition, false)) {
// assume that any items moving now are moving due to the remove - if they schedule
// a different transition, that will override this one anyway
- for (int i=0; i<visibleItems.count(); i++)
+ for (int i=0; i<visibleItems.size(); i++)
visibleItems[i]->transitionNextReposition(transitioner, QQuickItemViewTransitioner::RemoveTransition, false);
}
@@ -1866,7 +1866,7 @@ void QQuickItemViewPrivate::layout()
// Give the view one more chance to refill itself,
// in case its size is changed such that more delegates become visible after component completed
refill();
- for (FxViewItem *item : qAsConst(visibleItems)) {
+ for (FxViewItem *item : std::as_const(visibleItems)) {
if (!item->transitionScheduledOrRunning())
item->transitionNextReposition(transitioner, QQuickItemViewTransitioner::PopulateTransition, true);
}
@@ -1903,14 +1903,14 @@ void QQuickItemViewPrivate::layout()
prepareVisibleItemTransitions();
// We cannot use iterators here as erasing from a container invalidates them.
- for (int i = 0, count = releasePendingTransition.count(); i < count;) {
+ for (int i = 0, count = releasePendingTransition.size(); i < count;) {
auto success = prepareNonVisibleItemTransition(releasePendingTransition[i], viewBounds);
// prepareNonVisibleItemTransition() may remove items while in fast flicking.
// Invisible animating items are kicked in or out the viewPort.
// Recheck count to test if the item got removed. In that case the same index points
// to a different item now.
const int old_count = count;
- count = releasePendingTransition.count();
+ count = releasePendingTransition.size();
if (old_count > count)
continue;
@@ -1923,15 +1923,18 @@ void QQuickItemViewPrivate::layout()
}
}
- for (int i=0; i<visibleItems.count(); i++)
+ for (int i=0; i<visibleItems.size(); i++)
visibleItems[i]->startTransition(transitioner);
- for (int i=0; i<releasePendingTransition.count(); i++)
+ for (int i=0; i<releasePendingTransition.size(); i++)
releasePendingTransition[i]->startTransition(transitioner);
transitioner->setPopulateTransitionEnabled(false);
transitioner->resetTargetLists();
}
+ if (!currentItem)
+ updateCurrent(currentIndex);
+
runDelayedRemoveTransition = false;
inLayout = false;
}
@@ -1949,9 +1952,9 @@ bool QQuickItemViewPrivate::applyModelChanges(ChangeResult *totalInsertionResult
updateUnrequestedIndexes();
- FxViewItem *prevVisibleItemsFirst = visibleItems.count() ? *visibleItems.constBegin() : nullptr;
+ FxViewItem *prevVisibleItemsFirst = visibleItems.size() ? *visibleItems.constBegin() : nullptr;
int prevItemCount = itemCount;
- int prevVisibleItemsCount = visibleItems.count();
+ int prevVisibleItemsCount = visibleItems.size();
bool visibleAffected = false;
bool viewportChanged = !currentChanges.pendingChanges.removes().isEmpty()
|| !currentChanges.pendingChanges.inserts().isEmpty();
@@ -1963,7 +1966,7 @@ bool QQuickItemViewPrivate::applyModelChanges(ChangeResult *totalInsertionResult
prevFirstItemInViewPos = prevFirstItemInView->position();
prevFirstItemInViewIndex = prevFirstItemInView->index;
}
- qreal prevVisibleItemsFirstPos = visibleItems.count() ? firstVisibleItemPosition : 0.0;
+ qreal prevVisibleItemsFirstPos = visibleItems.size() ? firstVisibleItemPosition : 0.0;
totalInsertionResult->visiblePos = prevFirstItemInViewPos;
totalRemovalResult->visiblePos = prevFirstItemInViewPos;
@@ -2016,7 +2019,7 @@ bool QQuickItemViewPrivate::applyModelChanges(ChangeResult *totalInsertionResult
QList<FxViewItem *> newItems;
QList<MovedItem> movingIntoView;
- for (int i=0; i<insertions.count(); i++) {
+ for (int i=0; i<insertions.size(); i++) {
bool wasEmpty = visibleItems.isEmpty();
if (applyInsertionChange(insertions[i], &insertionResult, &newItems, &movingIntoView))
visibleAffected = true;
@@ -2027,14 +2030,14 @@ bool QQuickItemViewPrivate::applyModelChanges(ChangeResult *totalInsertionResult
*totalInsertionResult += insertionResult;
// set positions correctly for the next insertion
- if (i < insertions.count() - 1) {
+ if (i < insertions.size() - 1) {
repositionFirstItem(prevVisibleItemsFirst, prevVisibleItemsFirstPos, prevFirstItemInView, &insertionResult, &removalResult);
layoutVisibleItems(insertions[i].index);
storeFirstVisibleItemPosition();
}
itemCount += insertions[i].count;
}
- for (FxViewItem *item : qAsConst(newItems)) {
+ for (FxViewItem *item : std::as_const(newItems)) {
if (item->attached)
item->attached->emitAdd();
}
@@ -2043,7 +2046,7 @@ bool QQuickItemViewPrivate::applyModelChanges(ChangeResult *totalInsertionResult
// find the index it was moved from in order to set its initial position, so that we
// can transition it from this "original" position to its new position in the view
if (transitioner && transitioner->canTransition(QQuickItemViewTransitioner::MoveTransition, true)) {
- for (const MovedItem &m : qAsConst(movingIntoView)) {
+ for (const MovedItem &m : std::as_const(movingIntoView)) {
int fromIndex = findMoveKeyIndex(m.moveKey, removals);
if (fromIndex >= 0) {
if (prevFirstItemInViewIndex >= 0 && fromIndex < prevFirstItemInViewIndex)
@@ -2099,7 +2102,7 @@ bool QQuickItemViewPrivate::applyRemovalChange(const QQmlChangeSet::Change &remo
Q_Q(QQuickItemView);
bool visibleAffected = false;
- if (visibleItems.count() && removal.index + removal.count > visibleItems.constLast()->index) {
+ if (visibleItems.size() && removal.index + removal.count > visibleItems.constLast()->index) {
if (removal.index > visibleItems.constLast()->index)
removeResult->countChangeAfterVisibleItems += removal.count;
else
@@ -2177,7 +2180,7 @@ void QQuickItemViewPrivate::repositionFirstItem(FxViewItem *prevVisibleItemsFirs
const QQmlNullableValue<qreal> prevViewPos = insertionResult->visiblePos;
// reposition visibleItems.first() correctly so that the content y doesn't jump
- if (visibleItems.count()) {
+ if (visibleItems.size()) {
if (prevVisibleItemsFirst && insertionResult->changedFirstItem)
resetFirstItemPosition(prevVisibleItemsFirstPos);
@@ -2224,7 +2227,7 @@ void QQuickItemViewPrivate::prepareVisibleItemTransitions()
// must call for every visible item to init or discard transitions
QRectF viewBounds(q->contentX(), q->contentY(), q->width(), q->height());
- for (int i=0; i<visibleItems.count(); i++)
+ for (int i=0; i<visibleItems.size(); i++)
visibleItems[i]->prepareTransition(transitioner, viewBounds);
}
@@ -2276,7 +2279,7 @@ bool QQuickItemViewPrivate::prepareNonVisibleItemTransition(FxViewItem *item, co
void QQuickItemViewPrivate::viewItemTransitionFinished(QQuickItemViewTransitionableItem *item)
{
- for (int i=0; i<releasePendingTransition.count(); i++) {
+ for (int i=0; i<releasePendingTransition.size(); i++) {
if (releasePendingTransition.at(i)->transitionableItem == item) {
releaseItem(releasePendingTransition.takeAt(i), reusableFlag);
return;
@@ -2296,7 +2299,7 @@ FxViewItem *QQuickItemViewPrivate::createItem(int modelIndex, QQmlIncubator::Inc
if (requestedIndex == modelIndex && incubationMode == QQmlIncubator::Asynchronous)
return nullptr;
- for (int i=0; i<releasePendingTransition.count(); i++) {
+ for (int i=0; i<releasePendingTransition.size(); i++) {
if (releasePendingTransition.at(i)->index == modelIndex
&& !releasePendingTransition.at(i)->isPendingRemoval()) {
releasePendingTransition[i]->releaseAfterTransition = false;
diff --git a/src/quick/items/qquicklistview.cpp b/src/quick/items/qquicklistview.cpp
index 9ea4624997..043c5e08d3 100644
--- a/src/quick/items/qquicklistview.cpp
+++ b/src/quick/items/qquicklistview.cpp
@@ -451,7 +451,7 @@ FxViewItem *QQuickListViewPrivate::itemBefore(int modelIndex) const
return nullptr;
int idx = 1;
int lastIndex = -1;
- while (idx < visibleItems.count()) {
+ while (idx < visibleItems.size()) {
FxViewItem *item = visibleItems.at(idx);
if (item->index != -1)
lastIndex = item->index;
@@ -497,7 +497,7 @@ qreal QQuickListViewPrivate::lastPosition() const
if (!visibleItems.isEmpty()) {
int invisibleCount = INT_MIN;
int delayRemovedCount = 0;
- for (int i = visibleItems.count()-1; i >= 0; --i) {
+ for (int i = visibleItems.size()-1; i >= 0; --i) {
FxViewItem *item = visibleItems.at(i);
if (item->index != -1) {
// Find the invisible count after the last visible item with known index
@@ -576,7 +576,7 @@ qreal QQuickListViewPrivate::snapPosAt(qreal pos)
{
if (FxListItemSG *snapItem = static_cast<FxListItemSG*>(snapItemAt(pos)))
return snapItem->itemPosition();
- if (visibleItems.count()) {
+ if (visibleItems.size()) {
qreal firstPos = (*visibleItems.constBegin())->position();
qreal endPos = (*(visibleItems.constEnd() - 1))->position();
if (pos < firstPos) {
@@ -593,7 +593,7 @@ FxViewItem *QQuickListViewPrivate::snapItemAt(qreal pos)
FxViewItem *snapItem = nullptr;
FxViewItem *prevItem = nullptr;
qreal prevItemSize = 0;
- for (FxViewItem *item : qAsConst(visibleItems)) {
+ for (FxViewItem *item : std::as_const(visibleItems)) {
if (item->index == -1)
continue;
@@ -721,7 +721,7 @@ bool QQuickListViewPrivate::releaseItem(FxViewItem *item, QQmlInstanceModel::Reu
bool QQuickListViewPrivate::addVisibleItems(qreal fillFrom, qreal fillTo, qreal bufferFrom, qreal bufferTo, bool doBuffer)
{
qreal itemEnd = visiblePos;
- if (visibleItems.count()) {
+ if (visibleItems.size()) {
visiblePos = (*visibleItems.constBegin())->position();
itemEnd = (*(visibleItems.constEnd() - 1))->endPosition() + spacing;
}
@@ -807,7 +807,7 @@ bool QQuickListViewPrivate::removeNonVisibleItems(qreal bufferFrom, qreal buffer
// removed, otherwise a zero-sized item is infinitely added and removed over and
// over by refill().
int index = 0;
- while (visibleItems.count() > 1 && index < visibleItems.count()
+ while (visibleItems.size() > 1 && index < visibleItems.size()
&& (item = visibleItems.at(index)) && item->endPosition() < bufferFrom) {
if (item->attached->delayRemove())
break;
@@ -830,10 +830,10 @@ bool QQuickListViewPrivate::removeNonVisibleItems(qreal bufferFrom, qreal buffer
}
}
- while (visibleItems.count() > 1 && (item = visibleItems.constLast()) && item->position() > bufferTo) {
+ while (visibleItems.size() > 1 && (item = visibleItems.constLast()) && item->position() > bufferTo) {
if (item->attached->delayRemove())
break;
- qCDebug(lcItemViewDelegateLifecycle) << "refill: remove last" << visibleIndex+visibleItems.count()-1 << item->position() << (QObject *)(item->item);
+ qCDebug(lcItemViewDelegateLifecycle) << "refill: remove last" << visibleIndex+visibleItems.size()-1 << item->position() << (QObject *)(item->item);
visibleItems.removeLast();
removeItem(item);
changed = true;
@@ -844,7 +844,7 @@ bool QQuickListViewPrivate::removeNonVisibleItems(qreal bufferFrom, qreal buffer
void QQuickListViewPrivate::visibleItemsChanged()
{
- if (visibleItems.count())
+ if (visibleItems.size())
visiblePos = (*visibleItems.constBegin())->position();
updateAverage();
if (currentIndex >= 0 && currentItem && !visibleItem(currentIndex)) {
@@ -874,7 +874,7 @@ void QQuickListViewPrivate::layoutVisibleItems(int fromModelIndex)
if (firstItem->section())
firstItem->setPosition(firstItem->position());
- for (int i=1; i < visibleItems.count(); ++i) {
+ for (int i=1; i < visibleItems.size(); ++i) {
FxListItemSG *item = static_cast<FxListItemSG*>(visibleItems.at(i));
if (item->index >= fromModelIndex) {
item->setPosition(pos);
@@ -884,7 +884,7 @@ void QQuickListViewPrivate::layoutVisibleItems(int fromModelIndex)
sum += item->size();
fixedCurrent = fixedCurrent || (currentItem && item->item == currentItem->item);
}
- averageSize = qRound(sum / visibleItems.count());
+ averageSize = qRound(sum / visibleItems.size());
// move current item if it is not a visible item.
if (currentIndex >= 0 && currentItem && !fixedCurrent)
@@ -929,7 +929,7 @@ void QQuickListViewPrivate::resetFirstItemPosition(qreal pos)
void QQuickListViewPrivate::adjustFirstItem(qreal forwards, qreal backwards, int)
{
- if (!visibleItems.count())
+ if (!visibleItems.size())
return;
qreal diff = forwards - backwards;
static_cast<FxListItemSG*>(visibleItems.constFirst())->setPosition(visibleItems.constFirst()->position() + diff);
@@ -1114,7 +1114,7 @@ void QQuickListViewPrivate::releaseSectionItem(QQuickItem *item)
void QQuickListViewPrivate::releaseSectionItems()
{
- for (FxViewItem *item : qAsConst(visibleItems)) {
+ for (FxViewItem *item : std::as_const(visibleItems)) {
FxListItemSG *listItem = static_cast<FxListItemSG *>(item);
if (listItem->section()) {
qreal pos = listItem->position();
@@ -1166,7 +1166,7 @@ void QQuickListViewPrivate::updateStickySections()
QQuickItem *sectionItem = nullptr;
QQuickItem *lastSectionItem = nullptr;
int index = 0;
- while (index < visibleItems.count()) {
+ while (index < visibleItems.size()) {
if (QQuickItem *section = static_cast<FxListItemSG *>(visibleItems.at(index))->section()) {
// Find the current section header and last visible section header
// and hide them if they will overlap a static section header.
@@ -1193,7 +1193,7 @@ void QQuickListViewPrivate::updateStickySections()
}
// Current section header
- if (sectionCriteria->labelPositioning() & QQuickViewSection::CurrentLabelAtStart && isValid() && visibleItems.count()) {
+ if (sectionCriteria->labelPositioning() & QQuickViewSection::CurrentLabelAtStart && isValid() && visibleItems.size()) {
if (!currentSectionItem) {
currentSectionItem = getSectionItem(currentSection);
} else if (QString::compare(currentStickySection, currentSection, Qt::CaseInsensitive)) {
@@ -1227,7 +1227,7 @@ void QQuickListViewPrivate::updateStickySections()
}
// Next section footer
- if (sectionCriteria->labelPositioning() & QQuickViewSection::NextLabelAtEnd && isValid() && visibleItems.count()) {
+ if (sectionCriteria->labelPositioning() & QQuickViewSection::NextLabelAtEnd && isValid() && visibleItems.size()) {
if (!nextSectionItem) {
nextSectionItem = getSectionItem(nextSection);
} else if (QString::compare(nextStickySection, nextSection, Qt::CaseInsensitive)) {
@@ -1274,7 +1274,7 @@ void QQuickListViewPrivate::updateSections()
QQuickListViewAttached *prevAtt = nullptr;
int prevIdx = -1;
int idx = -1;
- for (FxViewItem *item : qAsConst(visibleItems)) {
+ for (FxViewItem *item : std::as_const(visibleItems)) {
QQuickListViewAttached *attached = static_cast<QQuickListViewAttached*>(item->attached);
attached->setPrevSection(prevSection);
if (item->index != -1) {
@@ -1315,7 +1315,7 @@ void QQuickListViewPrivate::updateCurrentSection()
qreal startPos = hasStickyHeader() ? header->endPosition() : viewPos;
int index = 0;
int modelIndex = visibleIndex;
- while (index < visibleItems.count()) {
+ while (index < visibleItems.size()) {
FxViewItem *item = visibleItems.at(index);
if (item->endPosition() > startPos)
break;
@@ -1325,7 +1325,7 @@ void QQuickListViewPrivate::updateCurrentSection()
}
QString newSection = currentSection;
- if (index < visibleItems.count())
+ if (index < visibleItems.size())
newSection = visibleItems.at(index)->attached->section();
else
newSection = (*visibleItems.constBegin())->attached->section();
@@ -1344,7 +1344,7 @@ void QQuickListViewPrivate::updateCurrentSection()
qreal endPos = hasStickyFooter() ? footer->position() : viewPos + size();
if (nextSectionItem && !inlineSections)
endPos -= orient == QQuickListView::Vertical ? nextSectionItem->height() : nextSectionItem->width();
- while (index < visibleItems.count()) {
+ while (index < visibleItems.size()) {
FxListItemSG *listItem = static_cast<FxListItemSG *>(visibleItems.at(index));
if (listItem->itemPosition() >= endPos)
break;
@@ -1379,7 +1379,7 @@ void QQuickListViewPrivate::initializeCurrentItem()
// don't reposition the item if it is already in the visibleItems list
FxViewItem *actualItem = visibleItem(currentIndex);
if (!actualItem) {
- if (currentIndex == visibleIndex - 1 && visibleItems.count()) {
+ if (currentIndex == visibleIndex - 1 && visibleItems.size()) {
// We can calculate exact postion in this case
listItem->setPosition(visibleItems.constFirst()->position() - currentItem->size() - spacing);
} else {
@@ -1396,12 +1396,12 @@ void QQuickListViewPrivate::initializeCurrentItem()
void QQuickListViewPrivate::updateAverage()
{
- if (!visibleItems.count())
+ if (!visibleItems.size())
return;
qreal sum = 0.0;
- for (FxViewItem *item : qAsConst(visibleItems))
+ for (FxViewItem *item : std::as_const(visibleItems))
sum += item->size();
- averageSize = qRound(sum / visibleItems.count());
+ averageSize = qRound(sum / visibleItems.size());
}
qreal QQuickListViewPrivate::headerSize() const
@@ -1440,10 +1440,12 @@ void QQuickListViewPrivate::updateFooter()
FxListItemSG *listItem = static_cast<FxListItemSG*>(footer);
if (footerPositioning == QQuickListView::OverlayFooter) {
listItem->setPosition(isContentFlowReversed() ? -position() - footerSize() : position() + size() - footerSize());
- } else if (visibleItems.count()) {
+ } else if (visibleItems.size()) {
if (footerPositioning == QQuickListView::PullBackFooter) {
qreal viewPos = isContentFlowReversed() ? -position() : position() + size();
- qreal clampedPos = qBound(originPosition() - footerSize() + size(), listItem->position(), lastPosition());
+ // using qBound() would throw an assert here, because max < min is a valid case
+ // here, if the list's delegates do not fill the whole view
+ qreal clampedPos = qMax(originPosition() - footerSize() + size(), qMin(listItem->position(), lastPosition()));
listItem->setPosition(qBound(viewPos - footerSize(), clampedPos, viewPos));
} else {
qreal endPos = lastPosition();
@@ -1473,7 +1475,7 @@ void QQuickListViewPrivate::fixupHeader()
{
FxListItemSG *listItem = static_cast<FxListItemSG*>(header);
const bool fixingUp = (orient == QQuickListView::Vertical ? vData : hData).fixingUp;
- if (fixingUp && headerPositioning == QQuickListView::PullBackHeader && visibleItems.count()) {
+ if (fixingUp && headerPositioning == QQuickListView::PullBackHeader && visibleItems.size()) {
int fixupDura = timeline.duration();
if (fixupDura < 0)
fixupDura = fixupDuration/2;
@@ -1504,7 +1506,7 @@ void QQuickListViewPrivate::updateHeader()
FxListItemSG *listItem = static_cast<FxListItemSG*>(header);
if (headerPositioning == QQuickListView::OverlayHeader) {
listItem->setPosition(isContentFlowReversed() ? -position() - size() : position());
- } else if (visibleItems.count()) {
+ } else if (visibleItems.size()) {
const bool fixingUp = (orient == QQuickListView::Vertical ? vData : hData).fixingUp;
if (headerPositioning == QQuickListView::PullBackHeader) {
qreal headerPosition = listItem->position();
@@ -1512,7 +1514,9 @@ void QQuickListViewPrivate::updateHeader()
// Make sure the header is not shown if we absolutely do not have any plans to show it
if (fixingUp && !headerNeedsSeparateFixup)
headerPosition = viewPos - headerSize();
- qreal clampedPos = qBound(originPosition() - headerSize(), headerPosition, lastPosition() - size());
+ // using qBound() would throw an assert here, because max < min is a valid case
+ // here, if the list's delegates do not fill the whole view
+ qreal clampedPos = qMax(originPosition() - headerSize(), qMin(headerPosition, lastPosition() - size()));
listItem->setPosition(qBound(viewPos - headerSize(), clampedPos, viewPos));
} else {
qreal startPos = originPosition();
@@ -1573,7 +1577,7 @@ void QQuickListViewPrivate::itemGeometryChanged(QQuickItem *item, QQuickGeometry
// if visibleItems.first() has resized, adjust its pos since it is used to
// position all subsequent items
- if (visibleItems.count() && item == visibleItems.constFirst()->item) {
+ if (visibleItems.size() && item == visibleItems.constFirst()->item) {
FxListItemSG *listItem = static_cast<FxListItemSG*>(visibleItems.constFirst());
if (listItem->transitionScheduledOrRunning())
return;
@@ -1619,7 +1623,7 @@ void QQuickListViewPrivate::fixup(AxisData &data, qreal minExtent, qreal maxExte
}
// update footer if all visible items have been removed
- if (visibleItems.count() == 0)
+ if (visibleItems.size() == 0)
updateFooter();
correctFlick = false;
@@ -1824,15 +1828,15 @@ bool QQuickListViewPrivate::flick(AxisData &data, qreal minExtent, qreal maxExte
return QQuickItemViewPrivate::flick(data, minExtent, maxExtent, vSize, fixupCallback, velocity);
}
qreal maxDistance = 0;
- qreal dataValue = isContentFlowReversed() ? -data.move.value()+size() : data.move.value();
+ const qreal dataValue =
+ isContentFlowReversed() ? -data.move.value() + size() : data.move.value();
// -ve velocity means list is moving up/left
if (velocity > 0) {
if (data.move.value() < minExtent) {
if (snapMode == QQuickListView::SnapOneItem && !hData.flicking && !vData.flicking) {
- // if we've been dragged < averageSize/2 then bias towards the next item
- qreal dist = data.move.value() - data.pressPos;
- qreal bias = dist < averageSize/2 ? averageSize/2 : 0;
+ // averageSize/2 + 1 - next item
+ qreal bias = averageSize / 2 + 1 - (pressed ? data.pressPos : 0);
if (isContentFlowReversed())
bias = -bias;
data.flickTarget = -snapPosAt(-(dataValue - highlightRangeStart) - bias) + highlightRangeStart;
@@ -1847,12 +1851,12 @@ bool QQuickListViewPrivate::flick(AxisData &data, qreal minExtent, qreal maxExte
} else {
if (data.move.value() > maxExtent) {
if (snapMode == QQuickListView::SnapOneItem && !hData.flicking && !vData.flicking) {
- // if we've been dragged < averageSize/2 then bias towards the next item
- qreal dist = data.move.value() - data.pressPos;
- qreal bias = -dist < averageSize/2 ? averageSize/2 : 0;
+ // averageSize/2 + 1 - next item
+ qreal bias = averageSize / 2 + 1 - (pressed ? data.pressPos : 0);
if (isContentFlowReversed())
bias = -bias;
- data.flickTarget = -snapPosAt(-(dataValue - highlightRangeStart) + bias) + highlightRangeStart;
+ data.flickTarget =
+ -snapPosAt(-(dataValue - highlightRangeStart) + bias) + highlightRangeStart;
maxDistance = qAbs(data.flickTarget - data.move.value());
velocity = -maxVelocity;
} else {
@@ -2707,7 +2711,8 @@ void QQuickListView::setOrientation(QQuickListView::Orientation orientation)
\c section.delegate holds the delegate component for each section. The
default \l {QQuickItem::z}{stacking order} of section delegate instances
- is \c 2.
+ is \c 2. If you declare a \c required property named "section" in it,
+ that property will contain the section's title.
\c section.labelPositioning determines whether the current and/or
next section labels stick to the start/end of the view, and whether
@@ -3385,7 +3390,7 @@ void QQuickListView::viewportMoved(Qt::Orientations orient)
// Set visibility of items to eliminate cost of items outside the visible area.
qreal from = d->isContentFlowReversed() ? -d->position()-d->displayMarginBeginning-d->size() : d->position()-d->displayMarginBeginning;
qreal to = d->isContentFlowReversed() ? -d->position()+d->displayMarginEnd : d->position()+d->size()+d->displayMarginEnd;
- for (FxViewItem *item : qAsConst(d->visibleItems)) {
+ for (FxViewItem *item : std::as_const(d->visibleItems)) {
if (item->item)
QQuickItemPrivate::get(item->item)->setCulled(item->endPosition() < from || item->position() > to);
}
@@ -3610,25 +3615,25 @@ bool QQuickListViewPrivate::applyInsertionChange(const QQmlChangeSet::Change &ch
int count = change.count;
qreal tempPos = isContentFlowReversed() ? -position()-size() : position();
- int index = visibleItems.count() ? mapFromModel(modelIndex) : 0;
+ int index = visibleItems.size() ? mapFromModel(modelIndex) : 0;
qreal lastVisiblePos = buffer + displayMarginEnd + tempPos + size();
if (index < 0) {
- int i = visibleItems.count() - 1;
+ int i = visibleItems.size() - 1;
while (i > 0 && visibleItems.at(i)->index == -1)
--i;
if (i == 0 && visibleItems.constFirst()->index == -1) {
// there are no visible items except items marked for removal
- index = visibleItems.count();
+ index = visibleItems.size();
} else if (visibleItems.at(i)->index + 1 == modelIndex
&& visibleItems.at(i)->endPosition() <= lastVisiblePos) {
// Special case of appending an item to the model.
- index = visibleItems.count();
+ index = visibleItems.size();
} else {
if (modelIndex < visibleIndex) {
// Insert before visible items
visibleIndex += count;
- for (FxViewItem *item : qAsConst(visibleItems)) {
+ for (FxViewItem *item : std::as_const(visibleItems)) {
if (item->index != -1 && item->index >= modelIndex)
item->index += count;
}
@@ -3639,13 +3644,13 @@ bool QQuickListViewPrivate::applyInsertionChange(const QQmlChangeSet::Change &ch
// index can be the next item past the end of the visible items list (i.e. appended)
qreal pos = 0;
- if (visibleItems.count()) {
- pos = index < visibleItems.count() ? visibleItems.at(index)->position()
+ if (visibleItems.size()) {
+ pos = index < visibleItems.size() ? visibleItems.at(index)->position()
: visibleItems.constLast()->endPosition() + spacing;
}
// Update the indexes of the following visible items.
- for (FxViewItem *item : qAsConst(visibleItems)) {
+ for (FxViewItem *item : std::as_const(visibleItems)) {
if (item->index != -1 && item->index >= modelIndex) {
item->index += count;
if (change.isMove())
@@ -3698,7 +3703,7 @@ bool QQuickListViewPrivate::applyInsertionChange(const QQmlChangeSet::Change &ch
}
int firstOkIdx = -1;
- for (int i = 0; i <= insertionIdx && i < visibleItems.count() - 1; i++) {
+ for (int i = 0; i <= insertionIdx && i < visibleItems.size() - 1; i++) {
if (visibleItems.at(i)->index + 1 != visibleItems.at(i + 1)->index) {
firstOkIdx = i + 1;
break;
@@ -3749,13 +3754,13 @@ bool QQuickListViewPrivate::applyInsertionChange(const QQmlChangeSet::Change &ch
}
it.disconnect();
- if (0 < index && index < visibleItems.count()) {
+ if (0 < index && index < visibleItems.size()) {
FxViewItem *prevItem = visibleItems.at(index - 1);
FxViewItem *item = visibleItems.at(index);
if (prevItem->index != item->index - 1) {
int i = index;
qreal prevPos = prevItem->position();
- while (i < visibleItems.count()) {
+ while (i < visibleItems.size()) {
FxListItemSG *nvItem = static_cast<FxListItemSG *>(visibleItems.takeLast());
insertResult->sizeChangesAfterVisiblePos -= nvItem->size() + spacing;
addedItems->removeOne(nvItem);
@@ -3780,7 +3785,7 @@ void QQuickListViewPrivate::translateAndTransitionItemsAfter(int afterModelIndex
return;
int markerItemIndex = -1;
- for (int i=0; i<visibleItems.count(); i++) {
+ for (int i=0; i<visibleItems.size(); i++) {
if (visibleItems.at(i)->index == afterModelIndex) {
markerItemIndex = i;
break;
@@ -3793,7 +3798,7 @@ void QQuickListViewPrivate::translateAndTransitionItemsAfter(int afterModelIndex
qreal sizeRemoved = -removalResult.sizeChangesAfterVisiblePos
- (removalResult.countChangeAfterVisibleItems * (averageSize + spacing));
- for (int i=markerItemIndex+1; i<visibleItems.count(); i++) {
+ for (int i=markerItemIndex+1; i<visibleItems.size(); i++) {
FxListItemSG *listItem = static_cast<FxListItemSG *>(visibleItems.at(i));
if (listItem->position() >= viewEndPos)
break;
diff --git a/src/quick/items/qquickloader.cpp b/src/quick/items/qquickloader.cpp
index 7bb21a6d9d..d33e06a273 100644
--- a/src/quick/items/qquickloader.cpp
+++ b/src/quick/items/qquickloader.cpp
@@ -768,7 +768,7 @@ void QQuickLoader::componentComplete()
{
Q_D(QQuickLoader);
QQuickItem::componentComplete();
- if (active()) {
+ if (active() && (status() != Ready)) {
if (d->loadingFromSource)
d->createComponent();
d->load();
diff --git a/src/quick/items/qquickmousearea.cpp b/src/quick/items/qquickmousearea.cpp
index 53ce213a3c..31c74765f7 100644
--- a/src/quick/items/qquickmousearea.cpp
+++ b/src/quick/items/qquickmousearea.cpp
@@ -24,7 +24,7 @@ DEFINE_BOOL_CONFIG_OPTION(qmlVisualTouchDebugging, QML_VISUAL_TOUCH_DEBUGGING)
Q_DECLARE_LOGGING_CATEGORY(lcHoverTrace)
QQuickMouseAreaPrivate::QQuickMouseAreaPrivate()
-: enabled(true), scrollGestureEnabled(true), hovered(false), longPress(false),
+: enabled(true), hoverEnabled(false), scrollGestureEnabled(true), hovered(false), longPress(false),
moved(false), stealMouse(false), doubleClick(false), preventStealing(false),
propagateComposedEvents(false), overThreshold(false),
pressAndHoldInterval(-1)
@@ -117,7 +117,7 @@ bool QQuickMouseAreaPrivate::propagateHelper(QQuickMouseEvent *ev, QQuickItem *i
}
QList<QQuickItem *> children = itemPrivate->paintOrderChildItems();
- for (int ii = children.count() - 1; ii >= 0; --ii) {
+ for (int ii = children.size() - 1; ii >= 0; --ii) {
QQuickItem *child = children.at(ii);
if (!child->isVisible() || !child->isEnabled())
continue;
@@ -453,6 +453,7 @@ void QQuickMouseArea::setEnabled(bool a)
Q_D(QQuickMouseArea);
if (a != d->enabled) {
d->enabled = a;
+ setAcceptHoverEvents(a && d->hoverEnabled);
emit enabledChanged();
}
}
@@ -767,7 +768,7 @@ void QQuickMouseArea::mouseReleaseEvent(QMouseEvent *event)
d->drag->setActive(false);
#endif
// If we don't accept hover, we need to reset containsMouse.
- if (!acceptHoverEvents())
+ if (!hoverEnabled())
setHovered(false);
QQuickWindow *w = window();
if (w && w->mouseGrabberItem() == this)
@@ -802,6 +803,14 @@ void QQuickMouseArea::hoverEnterEvent(QHoverEvent *event)
{
Q_D(QQuickMouseArea);
if (!d->enabled && !d->pressed) {
+ // Note: The fact that MouseArea doesn't update 'containsMouse' when it's disabled, is a
+ // legacy behavior that is different from how hover events are supposed to work; Hover
+ // events are always delivered to both enabled and disabled items (when they explicitly
+ // subscribe for them), to open up for hover effects, like showing tooltips. Because of
+ // this difference, you cannot use a MouseArea to e.g trigger a tooltop on a parent that
+ // is disabled. But since MouseArea has always worked this way, it should (probably) stay
+ // that way to avoid regressions. HoverHandlers do not suffer from this limitation, and
+ // can therefore be used as a replacement to solve such cases.
QQuickItem::hoverEnterEvent(event);
} else {
d->lastPos = event->position();
@@ -843,7 +852,7 @@ void QQuickMouseArea::hoverMoveEvent(QHoverEvent *event)
void QQuickMouseArea::hoverLeaveEvent(QHoverEvent *event)
{
Q_D(QQuickMouseArea);
- if (!d->enabled && !d->pressed)
+ if (!d->enabled && !d->pressed && !d->hovered)
QQuickItem::hoverLeaveEvent(event);
else
setHovered(false);
@@ -1030,13 +1039,43 @@ void QQuickMouseArea::itemChange(ItemChange change, const ItemChangeData &value)
Q_D(QQuickMouseArea);
switch (change) {
case ItemVisibleHasChanged:
- if (d->effectiveEnable && d->enabled && acceptHoverEvents() && d->hovered != (isVisible() && isUnderMouse())) {
- if (!d->hovered) {
- QPointF cursorPos = QGuiApplicationPrivate::lastCursorPosition;
- d->lastScenePos = d->window->mapFromGlobal(cursorPos.toPoint());
- d->lastPos = mapFromScene(d->lastScenePos);
+ if (d->effectiveEnable && d->enabled && hoverEnabled()
+ && d->hovered != (isVisible() && isUnderMouse())) {
+ if (d->hovered) {
+ // If hovered but no longer under the mouse then un-hover.
+ setHovered(false);
+ } else {
+ // If under the mouse but not hovered then hover the QQuickMouseArea if it is
+ // marked as a hovered item under the windows QQuickDeliveryAgentPrivate instance.
+ // This is required as this QQuickMouseArea may be masked by another hoverable
+ // QQuickMouseArea higher up in the scenes z-index ordering.
+ QPointF globalPos{ QGuiApplicationPrivate::lastCursorPosition.toPoint() };
+ QPointF scenePos{ d->window->mapFromGlobal(globalPos) };
+
+ QQuickWindowPrivate *wd = QQuickWindowPrivate::get(d->window);
+ QQuickDeliveryAgentPrivate *dap = wd->deliveryAgentPrivate();
+
+ // If the QQuickDeliveryAgentPrivate has not already found a hovered leaf
+ // item then attempt to find one.
+ if (!dap->hoveredLeafItemFound) {
+ dap->deliverHoverEvent(scenePos, scenePos, Qt::NoModifier,
+ QDateTime::currentSecsSinceEpoch());
+ }
+
+ // Now if the QQuickDeliveryAgentPrivate has found a hovered leaf item check
+ // that this QQuickMouseArea item was one of the hovered items.
+ if (dap->hoveredLeafItemFound) {
+ for (auto hoverItem : dap->hoverItems) {
+ if (hoverItem.first == this) {
+ // Found a match so update the hover state.
+ d->lastScenePos = scenePos;
+ d->lastPos = mapFromScene(d->lastScenePos);
+ setHovered(true);
+ break;
+ }
+ }
+ }
}
- setHovered(!d->hovered);
}
if (d->pressed && (!isVisible())) {
// This happens when the mouse area sets itself disabled or hidden
@@ -1065,15 +1104,18 @@ void QQuickMouseArea::itemChange(ItemChange change, const ItemChangeData &value)
*/
bool QQuickMouseArea::hoverEnabled() const
{
- return acceptHoverEvents();
+ return d_func()->hoverEnabled;
}
void QQuickMouseArea::setHoverEnabled(bool h)
{
- if (h == acceptHoverEvents())
+ Q_D(QQuickMouseArea);
+ if (h == d->hoverEnabled)
return;
- setAcceptHoverEvents(h);
+ d->hoverEnabled = h;
+ setAcceptHoverEvents(h && d->enabled);
+
emit hoverEnabledChanged();
}
@@ -1082,8 +1124,10 @@ void QQuickMouseArea::setHoverEnabled(bool h)
\qmlproperty bool QtQuick::MouseArea::containsMouse
This property holds whether the mouse is currently inside the mouse area.
- \warning If hoverEnabled is false, containsMouse will only be valid
+ \warning If hoverEnabled is \c false, \c containsMouse will be \c true
when the mouse is pressed while the mouse cursor is inside the MouseArea.
+ But if you set \c {mouse.accepted = false} in an \c onPressed handler,
+ \c containsMouse will remain \c false because the press was rejected.
*/
bool QQuickMouseArea::hovered() const
{
@@ -1193,6 +1237,8 @@ bool QQuickMouseArea::setPressed(Qt::MouseButton button, bool p, Qt::MouseEventS
if (!me.isAccepted()) {
d->pressed = Qt::NoButton;
+ if (!hoverEnabled())
+ setHovered(false);
}
if (!oldPressed) {
diff --git a/src/quick/items/qquickmousearea_p_p.h b/src/quick/items/qquickmousearea_p_p.h
index 25287671a2..ede16e110b 100644
--- a/src/quick/items/qquickmousearea_p_p.h
+++ b/src/quick/items/qquickmousearea_p_p.h
@@ -51,6 +51,7 @@ public:
#endif
bool enabled : 1;
+ bool hoverEnabled : 1;
bool scrollGestureEnabled : 1;
bool hovered : 1;
bool longPress : 1;
diff --git a/src/quick/items/qquickmultipointtoucharea.cpp b/src/quick/items/qquickmultipointtoucharea.cpp
index d594861ee7..fc994fd18c 100644
--- a/src/quick/items/qquickmultipointtoucharea.cpp
+++ b/src/quick/items/qquickmultipointtoucharea.cpp
@@ -419,7 +419,7 @@ QQuickMultiPointTouchArea::QQuickMultiPointTouchArea(QQuickItem *parent)
QQuickMultiPointTouchArea::~QQuickMultiPointTouchArea()
{
clearTouchLists();
- for (QObject *obj : qAsConst(_touchPoints)) {
+ for (QObject *obj : std::as_const(_touchPoints)) {
QQuickTouchPoint *dtp = static_cast<QQuickTouchPoint*>(obj);
if (!dtp->isQmlDefined())
delete dtp;
@@ -578,9 +578,9 @@ void QQuickMultiPointTouchArea::updateTouchData(QEvent *event, RemapEventPoints
break;
}
- int numTouchPoints = touchPoints.count();
+ int numTouchPoints = touchPoints.size();
//always remove released touches, and make sure we handle all releases before adds.
- for (const QEventPoint &p : qAsConst(touchPoints)) {
+ for (const QEventPoint &p : std::as_const(touchPoints)) {
QEventPoint::State touchPointState = p.state();
int id = p.id();
if (touchPointState & QEventPoint::State::Released) {
@@ -625,7 +625,7 @@ void QQuickMultiPointTouchArea::updateTouchData(QEvent *event, RemapEventPoints
if (!_stealMouse /* !ignoring gesture*/) {
bool offerGrab = false;
const int dragThreshold = QGuiApplication::styleHints()->startDragDistance();
- for (const QEventPoint &p : qAsConst(touchPoints)) {
+ for (const QEventPoint &p : std::as_const(touchPoints)) {
if (p.state() == QEventPoint::State::Released)
continue;
const QPointF &currentPos = p.scenePosition();
@@ -659,7 +659,7 @@ void QQuickMultiPointTouchArea::updateTouchData(QEvent *event, RemapEventPoints
void QQuickMultiPointTouchArea::clearTouchLists()
{
- for (QObject *obj : qAsConst(_releasedTouchPoints)) {
+ for (QObject *obj : std::as_const(_releasedTouchPoints)) {
QQuickTouchPoint *dtp = static_cast<QQuickTouchPoint*>(obj);
if (!dtp->isQmlDefined()) {
_touchPoints.remove(dtp->pointId());
@@ -676,7 +676,7 @@ void QQuickMultiPointTouchArea::clearTouchLists()
void QQuickMultiPointTouchArea::addTouchPoint(const QEventPoint *p)
{
QQuickTouchPoint *dtp = nullptr;
- for (QQuickTouchPoint* tp : qAsConst(_touchPrototypes)) {
+ for (QQuickTouchPoint* tp : std::as_const(_touchPrototypes)) {
if (!tp->inUse()) {
tp->setInUse(true);
dtp = tp;
@@ -696,7 +696,7 @@ void QQuickMultiPointTouchArea::addTouchPoint(const QEventPoint *p)
void QQuickMultiPointTouchArea::addTouchPoint(const QMouseEvent *e)
{
QQuickTouchPoint *dtp = nullptr;
- for (QQuickTouchPoint *tp : qAsConst(_touchPrototypes)) {
+ for (QQuickTouchPoint *tp : std::as_const(_touchPrototypes)) {
if (!tp->inUse()) {
tp->setInUse(true);
dtp = tp;
@@ -743,7 +743,7 @@ void QQuickMultiPointTouchArea::setTouchEventsEnabled(bool enable)
void QQuickMultiPointTouchArea::addTouchPrototype(QQuickTouchPoint *prototype)
{
- int id = _touchPrototypes.count();
+ int id = _touchPrototypes.size();
prototype->setPointId(id);
_touchPrototypes.insert(id, prototype);
}
@@ -796,7 +796,7 @@ void QQuickMultiPointTouchArea::mousePressEvent(QMouseEvent *event)
if (event->source() != Qt::MouseEventNotSynthesized && event->source() != Qt::MouseEventSynthesizedByQt)
return;
- if (_touchPoints.count() >= _minimumTouchPoints - 1 && _touchPoints.count() < _maximumTouchPoints) {
+ if (_touchPoints.size() >= _minimumTouchPoints - 1 && _touchPoints.size() < _maximumTouchPoints) {
updateTouchData(event);
}
}
@@ -844,13 +844,13 @@ void QQuickMultiPointTouchArea::ungrab(bool normalRelease)
if (!normalRelease)
ungrabTouchPoints();
- if (_touchPoints.count()) {
- for (QObject *obj : qAsConst(_touchPoints))
+ if (_touchPoints.size()) {
+ for (QObject *obj : std::as_const(_touchPoints))
static_cast<QQuickTouchPoint*>(obj)->setPressed(false);
if (!normalRelease)
emit canceled(_touchPoints.values());
clearTouchLists();
- for (QObject *obj : qAsConst(_touchPoints)) {
+ for (QObject *obj : std::as_const(_touchPoints)) {
QQuickTouchPoint *dtp = static_cast<QQuickTouchPoint*>(obj);
if (!dtp->isQmlDefined())
delete dtp;
diff --git a/src/quick/items/qquickmultipointtoucharea_p.h b/src/quick/items/qquickmultipointtoucharea_p.h
index f6d2886716..f92705f28e 100644
--- a/src/quick/items/qquickmultipointtoucharea_p.h
+++ b/src/quick/items/qquickmultipointtoucharea_p.h
@@ -210,7 +210,7 @@ public:
static qsizetype touchPoint_count(QQmlListProperty<QQuickTouchPoint> *list) {
QQuickMultiPointTouchArea *q = static_cast<QQuickMultiPointTouchArea*>(list->object);
- return q->_touchPrototypes.count();
+ return q->_touchPrototypes.size();
}
static QQuickTouchPoint* touchPoint_at(QQmlListProperty<QQuickTouchPoint> *list, qsizetype index) {
diff --git a/src/quick/items/qquickpainteditem.cpp b/src/quick/items/qquickpainteditem.cpp
index 83eb88ff3e..d363fbcd31 100644
--- a/src/quick/items/qquickpainteditem.cpp
+++ b/src/quick/items/qquickpainteditem.cpp
@@ -47,6 +47,8 @@ public:
\note It important to understand the performance implications such items
can incur. See QQuickPaintedItem::RenderTarget and
QQuickPaintedItem::renderTarget.
+
+ \sa {Scene Graph - Painted Item}, {Writing QML Extensions with C++}
*/
/*!
diff --git a/src/quick/items/qquickpalette.cpp b/src/quick/items/qquickpalette.cpp
index 9a72807fe1..d8d01a7588 100644
--- a/src/quick/items/qquickpalette.cpp
+++ b/src/quick/items/qquickpalette.cpp
@@ -33,7 +33,7 @@ static constexpr bool is_valid(QPalette::ColorGroup cg) noexcept
\internal
\class QQuickPalette
- \brief The QQuickPalette class contains color groups for each QML item state.
+ \brief Contains color groups for each QML item state.
\inmodule QtQuick
\since 6.0
@@ -48,7 +48,7 @@ static constexpr bool is_valid(QPalette::ColorGroup cg) noexcept
\inherits QQuickColorGroup
\inqmlmodule QtQuick
\ingroup qtquick-visual
- \brief The QQuickPalette class contains color groups for each QML item state.
+ \brief Contains color groups for each QML item state.
A palette consists of three color groups: Active, Disabled, and Inactive.
Active color group is the default group, its colors are used for other groups
@@ -108,7 +108,7 @@ static constexpr bool is_valid(QPalette::ColorGroup cg) noexcept
*/
/*!
- \qmlproperty QQuickColorGroup QtQuick::Palette::active
+ \qmlproperty ColorGroup QtQuick::Palette::active
The Active group is used for windows that are in focus.
@@ -116,7 +116,7 @@ static constexpr bool is_valid(QPalette::ColorGroup cg) noexcept
*/
/*!
- \qmlproperty QQuickColorGroup QtQuick::Palette::inactive
+ \qmlproperty ColorGroup QtQuick::Palette::inactive
The Inactive group is used for windows that have no keyboard focus.
@@ -124,7 +124,7 @@ static constexpr bool is_valid(QPalette::ColorGroup cg) noexcept
*/
/*!
- \qmlproperty QQuickColorGroup QtQuick::Palette::disabled
+ \qmlproperty ColorGroup QtQuick::Palette::disabled
The Disabled group is used for elements that are disabled for some reason.
diff --git a/src/quick/items/qquickpathview.cpp b/src/quick/items/qquickpathview.cpp
index 3b4ced67c3..3e30f410f0 100644
--- a/src/quick/items/qquickpathview.cpp
+++ b/src/quick/items/qquickpathview.cpp
@@ -210,10 +210,10 @@ void QQuickPathViewPrivate::clear()
currentItem = nullptr;
}
- for (QQuickItem *p : qAsConst(items))
+ for (QQuickItem *p : std::as_const(items))
releaseItem(p);
- for (QQuickItem *p : qAsConst(itemCache))
+ for (QQuickItem *p : std::as_const(itemCache))
releaseItem(p);
if (requestedIndex >= 0) {
@@ -386,7 +386,7 @@ void QQuickPathViewPrivate::setHighlightPosition(qreal pos)
void QQuickPathView::pathUpdated()
{
Q_D(QQuickPathView);
- for (QQuickItem *item : qAsConst(d->items)) {
+ for (QQuickItem *item : std::as_const(d->items)) {
if (QQuickPathViewAttached *att = d->attached(item))
att->m_percent = -1;
}
@@ -1619,21 +1619,21 @@ void QQuickPathView::mousePressEvent(QMouseEvent *event)
void QQuickPathViewPrivate::handleMousePressEvent(QMouseEvent *event)
{
Q_Q(QQuickPathView);
- if (!interactive || !items.count() || !model || !modelCount)
+ if (!interactive || !items.size() || !model || !modelCount)
return;
velocityBuffer.clear();
int idx = 0;
- for (; idx < items.count(); ++idx) {
+ for (; idx < items.size(); ++idx) {
QQuickItem *item = items.at(idx);
if (item->contains(item->mapFromScene(event->scenePosition())))
break;
}
- if (idx == items.count() && qFuzzyIsNull(dragMargin)) // didn't click on an item
+ if (idx == items.size() && qFuzzyIsNull(dragMargin)) // didn't click on an item
return;
startPoint = pointNear(event->position(), &startPc);
startPos = event->position();
- if (idx == items.count()) {
+ if (idx == items.size()) {
qreal distance = qAbs(event->position().x() - startPoint.x()) + qAbs(event->position().y() - startPoint.y());
if (distance > dragMargin)
return;
@@ -1978,7 +1978,7 @@ void QQuickPathView::refill()
bool waiting = false;
if (d->modelCount) {
// add items as needed
- if (d->items.count() < count+d->cacheSize) {
+ if (d->items.size() < count+d->cacheSize) {
int endIdx = 0;
qreal endPos;
int startIdx = 0;
@@ -1989,7 +1989,7 @@ void QQuickPathView::refill()
endPos = -1;
startPos = 2;
- for (QQuickItem * item : qAsConst(d->items)) {
+ for (QQuickItem * item : std::as_const(d->items)) {
int idx = d->model->indexOf(item, nullptr);
qreal curPos = d->positionOfIndex(idx);
if (curPos > endPos) {
@@ -2016,9 +2016,9 @@ void QQuickPathView::refill()
if (idx >= d->modelCount)
idx = 0;
qreal nextPos = d->positionOfIndex(idx);
- while ((d->isInBound(nextPos, endPos, 1 + d->mappedCache) || !d->items.count())
- && d->items.count() < count+d->cacheSize) {
- qCDebug(lcItemViewDelegateLifecycle) << "append" << idx << "@" << nextPos << (d->currentIndex == idx ? "current" : "") << "items count was" << d->items.count();
+ while ((d->isInBound(nextPos, endPos, 1 + d->mappedCache) || !d->items.size())
+ && d->items.size() < count+d->cacheSize) {
+ qCDebug(lcItemViewDelegateLifecycle) << "append" << idx << "@" << nextPos << (d->currentIndex == idx ? "current" : "") << "items count was" << d->items.size();
QQuickItem *item = d->getItem(idx, idx+1, nextPos >= 1);
if (!item) {
waiting = true;
@@ -2049,8 +2049,8 @@ void QQuickPathView::refill()
idx = d->modelCount - 1;
nextPos = d->positionOfIndex(idx);
while (!waiting && d->isInBound(nextPos, d->mappedRange - d->mappedCache, startPos)
- && d->items.count() < count+d->cacheSize) {
- qCDebug(lcItemViewDelegateLifecycle) << "prepend" << idx << "@" << nextPos << (d->currentIndex == idx ? "current" : "") << "items count was" << d->items.count();
+ && d->items.size() < count+d->cacheSize) {
+ qCDebug(lcItemViewDelegateLifecycle) << "prepend" << idx << "@" << nextPos << (d->currentIndex == idx ? "current" : "") << "items count was" << d->items.size();
QQuickItem *item = d->getItem(idx, idx+1, nextPos >= 1);
if (!item) {
waiting = true;
@@ -2078,8 +2078,8 @@ void QQuickPathView::refill()
// new items appear in the middle. This more generic addition iteration handles this
// Since this is the rare case, we try append/prepend first and only do this if
// there are gaps still left to fill.
- if (!waiting && d->items.count() < count+d->cacheSize) {
- qCDebug(lcItemViewDelegateLifecycle) << "Checking for pathview middle inserts, items count was" << d->items.count();
+ if (!waiting && d->items.size() < count+d->cacheSize) {
+ qCDebug(lcItemViewDelegateLifecycle) << "Checking for pathview middle inserts, items count was" << d->items.size();
idx = startIdx;
QQuickItem *lastItem = d->items.at(0);
while (idx != endIdx) {
@@ -2095,7 +2095,7 @@ void QQuickPathView::refill()
if (!d->items.contains(item)) { //We found a hole
qCDebug(lcItemViewDelegateLifecycle) << "middle insert" << idx << "@" << nextPos
<< (d->currentIndex == idx ? "current" : "")
- << "items count was" << d->items.count();
+ << "items count was" << d->items.size();
if (d->currentIndex == idx) {
currentVisible = true;
d->currentItemOffset = nextPos;
@@ -2149,7 +2149,7 @@ void QQuickPathView::refill()
if (QQuickPathViewAttached *att = d->attached(d->highlightItem))
att->setOnPath(currentVisible);
}
- for (QQuickItem *item : qAsConst(d->itemCache))
+ for (QQuickItem *item : std::as_const(d->itemCache))
d->releaseItem(item);
d->itemCache.clear();
@@ -2235,7 +2235,7 @@ void QQuickPathView::modelUpdated(const QQmlChangeSet &changeSet, bool reset)
d->items.clear();
if (!d->modelCount) {
- for (QQuickItem * item : qAsConst(d->itemCache))
+ for (QQuickItem * item : std::as_const(d->itemCache))
d->releaseItem(item);
d->itemCache.clear();
d->offset = 0;
@@ -2288,7 +2288,7 @@ void QQuickPathView::movementEnding()
int QQuickPathViewPrivate::calcCurrentIndex()
{
int current = 0;
- if (modelCount && model && items.count()) {
+ if (modelCount && model && items.size()) {
offset = std::fmod(offset, qreal(modelCount));
if (offset < 0)
offset += modelCount;
@@ -2305,7 +2305,7 @@ void QQuickPathViewPrivate::createCurrentItem()
return;
bool inItems = false;
- for (QQuickItem *item : qAsConst(items)) {
+ for (QQuickItem *item : std::as_const(items)) {
if (model->indexOf(item, nullptr) == currentIndex) {
inItems = true;
break;
@@ -2360,7 +2360,7 @@ void QQuickPathViewPrivate::fixOffsetCallback(void *d)
void QQuickPathViewPrivate::fixOffset()
{
Q_Q(QQuickPathView);
- if (model && items.count()) {
+ if (model && items.size()) {
if (haveHighlightRange && (highlightRangeMode == QQuickPathView::StrictlyEnforceRange
|| snapMode != QQuickPathView::NoSnap)) {
int curr = calcCurrentIndex();
diff --git a/src/quick/items/qquickpincharea.cpp b/src/quick/items/qquickpincharea.cpp
index 02086bc4bd..d547fae6c9 100644
--- a/src/quick/items/qquickpincharea.cpp
+++ b/src/quick/items/qquickpincharea.cpp
@@ -324,7 +324,7 @@ void QQuickPinchArea::touchEvent(QTouchEvent *event)
void QQuickPinchArea::clearPinch(QTouchEvent *event)
{
Q_D(QQuickPinchArea);
- qCDebug(lcPA, "clear: %" PRIdQSIZETYPE " touchpoints", d->touchPoints.count());
+ qCDebug(lcPA, "clear: %" PRIdQSIZETYPE " touchpoints", d->touchPoints.size());
d->touchPoints.clear();
if (d->inPinch) {
d->inPinch = false;
@@ -354,12 +354,13 @@ void QQuickPinchArea::clearPinch(QTouchEvent *event)
}
}
setKeepTouchGrab(false);
+ setKeepMouseGrab(false);
}
void QQuickPinchArea::cancelPinch(QTouchEvent *event)
{
Q_D(QQuickPinchArea);
- qCDebug(lcPA, "cancel: %" PRIdQSIZETYPE " touchpoints", d->touchPoints.count());
+ qCDebug(lcPA, "cancel: %" PRIdQSIZETYPE " touchpoints", d->touchPoints.size());
d->touchPoints.clear();
if (d->inPinch) {
d->inPinch = false;
@@ -395,15 +396,17 @@ void QQuickPinchArea::cancelPinch(QTouchEvent *event)
event->setExclusiveGrabber(point, nullptr);
}
setKeepTouchGrab(false);
+ setKeepMouseGrab(false);
}
void QQuickPinchArea::updatePinch(QTouchEvent *event, bool filtering)
{
Q_D(QQuickPinchArea);
- if (d->touchPoints.count() < 2) {
+ if (d->touchPoints.size() < 2) {
// A pinch gesture is not occurring, so stealing the grab is permitted.
setKeepTouchGrab(false);
+ setKeepMouseGrab(false);
// During filtering, there's no need to hold a grab for one point,
// because filtering happens for every event anyway.
// But if we receive the event via direct delivery, and give up the grab,
@@ -414,7 +417,7 @@ void QQuickPinchArea::updatePinch(QTouchEvent *event, bool filtering)
event->setExclusiveGrabber(d->touchPoints.first(), nullptr);
}
- if (d->touchPoints.count() == 0) {
+ if (d->touchPoints.size() == 0) {
if (d->inPinch) {
d->inPinch = false;
QPointF pinchCenter = mapFromScene(d->sceneLastCenter);
@@ -427,6 +430,8 @@ void QQuickPinchArea::updatePinch(QTouchEvent *event, bool filtering)
pe.setStartPoint2(mapFromScene(d->sceneStartPoint2));
pe.setPoint1(mapFromScene(d->lastPoint1));
pe.setPoint2(mapFromScene(d->lastPoint2));
+ setKeepTouchGrab(false);
+ setKeepMouseGrab(false);
emit pinchFinished(&pe);
d->pinchStartDist = 0;
d->pinchActivated = false;
@@ -439,7 +444,7 @@ void QQuickPinchArea::updatePinch(QTouchEvent *event, bool filtering)
}
QEventPoint touchPoint1 = d->touchPoints.at(0);
- QEventPoint touchPoint2 = d->touchPoints.at(d->touchPoints. count() >= 2 ? 1 : 0);
+ QEventPoint touchPoint2 = d->touchPoints.at(d->touchPoints.size() >= 2 ? 1 : 0);
if (touchPoint1.state() == QEventPoint::State::Pressed)
d->sceneStartPoint1 = touchPoint1.scenePosition();
@@ -453,7 +458,7 @@ void QQuickPinchArea::updatePinch(QTouchEvent *event, bool filtering)
// Pinch is not started unless there are exactly two touch points
// AND one or more of the points has just now been pressed (wasn't pressed already)
// AND both points are inside the bounds.
- if (d->touchPoints.count() == 2
+ if (d->touchPoints.size() == 2
&& (touchPoint1.state() == QEventPoint::State::Pressed || touchPoint2.state() == QEventPoint::State::Pressed) &&
bounds.contains(touchPoint1.position()) && bounds.contains(touchPoint2.position())) {
d->id1 = touchPoint1.id();
@@ -463,6 +468,8 @@ void QQuickPinchArea::updatePinch(QTouchEvent *event, bool filtering)
d->initPinch = true;
event->setExclusiveGrabber(touchPoint1, this);
event->setExclusiveGrabber(touchPoint2, this);
+ setKeepTouchGrab(true);
+ setKeepMouseGrab(true);
}
if (d->pinchActivated && !d->pinchRejected) {
const int dragThreshold = QGuiApplication::styleHints()->startDragDistance();
@@ -473,7 +480,7 @@ void QQuickPinchArea::updatePinch(QTouchEvent *event, bool filtering)
qreal dist = qSqrt(dx*dx + dy*dy);
QPointF sceneCenter = (p1 + p2)/2;
qreal angle = QLineF(p1, p2).angle();
- if (d->touchPoints.count() == 1) {
+ if (d->touchPoints.size() == 1) {
// If we only have one point then just move the center
if (d->id1 == touchPoint1.id())
sceneCenter = d->sceneLastCenter + touchPoint1.scenePosition() - d->lastPoint1;
@@ -487,7 +494,7 @@ void QQuickPinchArea::updatePinch(QTouchEvent *event, bool filtering)
qCDebug(lcPA, "pinch \u2316 %.1lf,%.1lf \u21e4%.1lf\u21e5 \u2220 %.1lf",
sceneCenter.x(), sceneCenter.y(), dist, angle);
if (!d->inPinch || d->initPinch) {
- if (d->touchPoints.count() >= 2) {
+ if (d->touchPoints.size() >= 2) {
if (d->initPinch) {
if (!d->inPinch)
d->pinchStartDist = dist;
@@ -518,13 +525,16 @@ void QQuickPinchArea::updatePinch(QTouchEvent *event, bool filtering)
pe.setStartPoint2(mapFromScene(d->sceneStartPoint2));
pe.setPoint1(mapFromScene(d->lastPoint1));
pe.setPoint2(mapFromScene(d->lastPoint2));
- pe.setPointCount(d->touchPoints.count());
+ pe.setPointCount(d->touchPoints.size());
emit pinchStarted(&pe);
if (pe.accepted()) {
d->inPinch = true;
event->setExclusiveGrabber(touchPoint1, this);
event->setExclusiveGrabber(touchPoint2, this);
setKeepTouchGrab(true);
+ // So that PinchArea works in PathView, grab mouse events too.
+ // We should be able to remove these setKeepMouseGrab calls when QTBUG-105567 is fixed.
+ setKeepMouseGrab(true);
d->inPinch = true;
if (d->pinch && d->pinch->target()) {
auto targetParent = pinch()->target()->parentItem();
@@ -558,7 +568,7 @@ void QQuickPinchArea::updatePinch(QTouchEvent *event, bool filtering)
pe.setStartPoint2(mapFromScene(d->sceneStartPoint2));
pe.setPoint1(touchPoint1.position());
pe.setPoint2(touchPoint2.position());
- pe.setPointCount(d->touchPoints.count());
+ pe.setPointCount(d->touchPoints.size());
d->pinchLastScale = scale;
d->sceneLastCenter = sceneCenter;
d->pinchLastAngle = angle;
diff --git a/src/quick/items/qquickpositioners.cpp b/src/quick/items/qquickpositioners.cpp
index f7eca278ea..5bb1f4f6d9 100644
--- a/src/quick/items/qquickpositioners.cpp
+++ b/src/quick/items/qquickpositioners.cpp
@@ -223,7 +223,7 @@ void QQuickBasePositioner::componentComplete()
QQuickItem::componentComplete();
if (d->transitioner)
d->transitioner->setPopulateTransitionEnabled(true);
- positionedItems.reserve(childItems().count());
+ positionedItems.reserve(childItems().size());
prePositioning();
if (d->transitioner)
d->transitioner->setPopulateTransitionEnabled(false);
@@ -277,7 +277,7 @@ void QQuickBasePositioner::prePositioning()
unpositionedItems.clear();
int addedIndex = -1;
- for (int ii = 0; ii < children.count(); ++ii) {
+ for (int ii = 0; ii < children.size(); ++ii) {
QQuickItem *child = children.at(ii);
if (QQuickItemPrivate::get(child)->isTransparentForPositioner())
continue;
diff --git a/src/quick/items/qquickrectangle.cpp b/src/quick/items/qquickrectangle.cpp
index 499856a3d2..7037526264 100644
--- a/src/quick/items/qquickrectangle.cpp
+++ b/src/quick/items/qquickrectangle.cpp
@@ -542,8 +542,13 @@ QSGNode *QQuickRectangle::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData
if (d->pen && d->pen->isValid()) {
rectangle->setPenColor(d->pen->color());
- rectangle->setPenWidth(d->pen->width());
- rectangle->setAligned(d->pen->pixelAligned());
+ qreal penWidth = d->pen->width();
+ if (d->pen->pixelAligned()) {
+ qreal dpr = window() ? window()->effectiveDevicePixelRatio() : 1.0;
+ penWidth = qRound(penWidth * dpr) / dpr; // Ensures integer width after dpr scaling
+ }
+ rectangle->setPenWidth(penWidth);
+ rectangle->setAligned(false); // width rounding already done, so the Node should not do it
} else {
rectangle->setPenWidth(0);
}
diff --git a/src/quick/items/qquickrendercontrol.cpp b/src/quick/items/qquickrendercontrol.cpp
index b12667776c..62cfea12e3 100644
--- a/src/quick/items/qquickrendercontrol.cpp
+++ b/src/quick/items/qquickrendercontrol.cpp
@@ -193,7 +193,7 @@ void QQuickRenderControlPrivate::windowDestroyed()
QQuickWindowPrivate::get(window)->animationController.reset();
#if QT_CONFIG(quick_shadereffect)
- QSGRhiShaderEffectNode::cleanupMaterialTypeCache();
+ QSGRhiShaderEffectNode::cleanupMaterialTypeCache(window);
#endif
window = nullptr;
}
@@ -509,7 +509,7 @@ void QQuickRenderControlPrivate::maybeUpdate()
Reimplemented in subclasses to return the real window this render control
is rendering into.
- If \a offset in non-null, it is set to the offset of the control
+ If \a offset is non-null, it is set to the offset of the control
inside the window.
\note While not mandatory, reimplementing this function becomes essential for
@@ -521,7 +521,7 @@ void QQuickRenderControlPrivate::maybeUpdate()
/*!
Returns the real window that \a win is being rendered to, if any.
- If \a offset in non-null, it is set to the offset of the rendering
+ If \a offset is non-null, it is set to the offset of the rendering
inside its window.
*/
diff --git a/src/quick/items/qquickrendertarget.cpp b/src/quick/items/qquickrendertarget.cpp
index e29e8839ba..460ce7335f 100644
--- a/src/quick/items/qquickrendertarget.cpp
+++ b/src/quick/items/qquickrendertarget.cpp
@@ -591,6 +591,8 @@ QQuickRenderTarget QQuickRenderTarget::fromRhiRenderTarget(QRhiRenderTarget *ren
\note The QQuickRenderTarget does not take ownship of \a device, it is the
caller's responsibility to ensure the object exists as long as necessary.
+ \since 6.4
+
\sa QQuickWindow::setRenderTarget(), QQuickRenderControl
*/
QQuickRenderTarget QQuickRenderTarget::fromPaintDevice(QPaintDevice *device)
diff --git a/src/quick/items/qquickrepeater.cpp b/src/quick/items/qquickrepeater.cpp
index 811ea316fc..2c892a596c 100644
--- a/src/quick/items/qquickrepeater.cpp
+++ b/src/quick/items/qquickrepeater.cpp
@@ -297,7 +297,7 @@ int QQuickRepeater::count() const
QQuickItem *QQuickRepeater::itemAt(int index) const
{
Q_D(const QQuickRepeater);
- if (index >= 0 && index < d->deletables.count())
+ if (index >= 0 && index < d->deletables.size())
return d->deletables[index];
return nullptr;
}
@@ -329,14 +329,14 @@ void QQuickRepeater::clear()
if (d->model) {
// We remove in reverse order deliberately; so that signals are emitted
// with sensible indices.
- for (int i = d->deletables.count() - 1; i >= 0; --i) {
+ for (int i = d->deletables.size() - 1; i >= 0; --i) {
if (QQuickItem *item = d->deletables.at(i)) {
if (complete)
emit itemRemoved(i, item);
d->model->release(item);
}
}
- for (QQuickItem *item : qAsConst(d->deletables)) {
+ for (QQuickItem *item : std::as_const(d->deletables)) {
if (item)
item->setParentItem(nullptr);
}
@@ -441,8 +441,8 @@ void QQuickRepeater::modelUpdated(const QQmlChangeSet &changeSet, bool reset)
int difference = 0;
QHash<int, QVector<QPointer<QQuickItem> > > moved;
for (const QQmlChangeSet::Change &remove : changeSet.removes()) {
- int index = qMin(remove.index, d->deletables.count());
- int count = qMin(remove.index + remove.count, d->deletables.count()) - index;
+ int index = qMin(remove.index, d->deletables.size());
+ int count = qMin(remove.index + remove.count, d->deletables.size()) - index;
if (remove.isMove()) {
moved.insert(remove.moveId, d->deletables.mid(index, count));
d->deletables.erase(
@@ -463,16 +463,16 @@ void QQuickRepeater::modelUpdated(const QQmlChangeSet &changeSet, bool reset)
}
for (const QQmlChangeSet::Change &insert : changeSet.inserts()) {
- int index = qMin(insert.index, d->deletables.count());
+ int index = qMin(insert.index, d->deletables.size());
if (insert.isMove()) {
QVector<QPointer<QQuickItem> > items = moved.value(insert.moveId);
d->deletables = d->deletables.mid(0, index) + items + d->deletables.mid(index);
- QQuickItem *stackBefore = index + items.count() < d->deletables.count()
- ? d->deletables.at(index + items.count())
+ QQuickItem *stackBefore = index + items.size() < d->deletables.size()
+ ? d->deletables.at(index + items.size())
: this;
if (stackBefore) {
- for (int i = index; i < index + items.count(); ++i) {
- if (i < d->deletables.count()) {
+ for (int i = index; i < index + items.size(); ++i) {
+ if (i < d->deletables.size()) {
QPointer<QQuickItem> item = d->deletables.at(i);
if (item)
item->stackBefore(stackBefore);
diff --git a/src/quick/items/qquickshadereffect.cpp b/src/quick/items/qquickshadereffect.cpp
index 97d0c581b7..4b6505c998 100644
--- a/src/quick/items/qquickshadereffect.cpp
+++ b/src/quick/items/qquickshadereffect.cpp
@@ -1129,6 +1129,8 @@ QSGNode *QQuickShaderEffectImpl::handleUpdatePaintNode(QSGNode *oldNode, QQuickI
sd.fragment.shader = &m_shaders[Fragment];
sd.fragment.dirtyConstants = &m_dirtyConstants[Fragment];
sd.fragment.dirtyTextures = &m_dirtyTextures[Fragment];
+ sd.materialTypeCacheKey = m_item->window();
+
node->syncMaterial(&sd);
if (m_dirty & QSGShaderEffectNode::DirtyShaderMesh) {
@@ -1207,6 +1209,7 @@ bool QQuickShaderEffectImpl::updateUniformValue(const QByteArray &name, const QV
sd.fragment.shader = &m_shaders[Fragment];
sd.fragment.dirtyConstants = &dirtyConstants[Fragment];
sd.fragment.dirtyTextures = {};
+ sd.materialTypeCacheKey = m_item->window();
node->syncMaterial(&sd);
@@ -1218,7 +1221,7 @@ void QQuickShaderEffectImpl::handleItemChange(QQuickItem::ItemChange change, con
// Move the window ref.
if (change == QQuickItem::ItemSceneChange) {
for (int shaderType = 0; shaderType < NShader; ++shaderType) {
- for (const auto &vd : qAsConst(m_shaders[shaderType].varData)) {
+ for (const auto &vd : std::as_const(m_shaders[shaderType].varData)) {
if (vd.specialType == QSGShaderEffectNode::VariableData::Source) {
QQuickItem *source = qobject_cast<QQuickItem *>(qvariant_cast<QObject *>(vd.value));
if (source) {
@@ -1260,7 +1263,7 @@ void QQuickShaderEffectImpl::disconnectSignals(Shader shaderType)
if (mapper)
QObjectPrivate::disconnect(m_item, mapper->signalIndex(), &a);
}
- for (const auto &vd : qAsConst(m_shaders[shaderType].varData)) {
+ for (const auto &vd : std::as_const(m_shaders[shaderType].varData)) {
if (vd.specialType == QSGShaderEffectNode::VariableData::Source) {
QQuickItem *source = qobject_cast<QQuickItem *>(qvariant_cast<QObject *>(vd.value));
if (source) {
@@ -1274,7 +1277,7 @@ void QQuickShaderEffectImpl::disconnectSignals(Shader shaderType)
void QQuickShaderEffectImpl::clearMappers(QQuickShaderEffectImpl::Shader shaderType)
{
- for (auto *mapper : qAsConst(m_mappers[shaderType])) {
+ for (auto *mapper : std::as_const(m_mappers[shaderType])) {
if (mapper)
mapper->destroyIfLastRef();
}
@@ -1311,7 +1314,7 @@ bool QQuickShaderEffectImpl::updateShader(Shader shaderType, const QUrl &fileUrl
disconnectSignals(shaderType);
- m_shaders[shaderType].shaderInfo = QSGGuiThreadShaderEffectManager::ShaderInfo();
+ m_shaders[shaderType].shaderInfo.variables.clear();
m_shaders[shaderType].varData.clear();
if (!fileUrl.isEmpty()) {
@@ -1348,7 +1351,7 @@ bool QQuickShaderEffectImpl::updateShader(Shader shaderType, const QUrl &fileUrl
// provided and monitored like with an application-provided shader.
QSGGuiThreadShaderEffectManager::ShaderInfo::Variable v;
v.name = QByteArrayLiteral("source");
- v.bindPoint = 0; // fake
+ v.bindPoint = 1; // fake, must match the default source bindPoint in qquickshadereffectnode.cpp
v.type = texturesSeparate ? QSGGuiThreadShaderEffectManager::ShaderInfo::Texture
: QSGGuiThreadShaderEffectManager::ShaderInfo::Sampler;
m_shaders[shaderType].shaderInfo.variables.append(v);
@@ -1399,7 +1402,7 @@ void QQuickShaderEffectImpl::updateShaderVars(Shader shaderType)
const bool texturesSeparate = mgr->hasSeparateSamplerAndTextureObjects();
- const int varCount = m_shaders[shaderType].shaderInfo.variables.count();
+ const int varCount = m_shaders[shaderType].shaderInfo.variables.size();
m_shaders[shaderType].varData.resize(varCount);
// Recreate signal mappers when the shader has changed.
@@ -1496,7 +1499,7 @@ void QQuickShaderEffectImpl::updateShaderVars(Shader shaderType)
bool QQuickShaderEffectImpl::sourceIsUnique(QQuickItem *source, Shader typeToSkip, int indexToSkip) const
{
for (int shaderType = 0; shaderType < NShader; ++shaderType) {
- for (int idx = 0; idx < m_shaders[shaderType].varData.count(); ++idx) {
+ for (int idx = 0; idx < m_shaders[shaderType].varData.size(); ++idx) {
if (shaderType != typeToSkip || idx != indexToSkip) {
const auto &vd(m_shaders[shaderType].varData[idx]);
if (vd.specialType == QSGShaderEffectNode::VariableData::Source && qvariant_cast<QObject *>(vd.value) == source)
@@ -1511,7 +1514,7 @@ std::optional<int> QQuickShaderEffectImpl::findMappedShaderVariableId(const QByt
{
for (int shaderType = 0; shaderType < NShader; ++shaderType) {
const auto &vars = m_shaders[shaderType].shaderInfo.variables;
- for (int idx = 0; idx < vars.count(); ++idx) {
+ for (int idx = 0; idx < vars.size(); ++idx) {
if (vars[idx].name == name)
return indexToMappedId(shaderType, idx);
}
@@ -1527,10 +1530,11 @@ void QQuickShaderEffectImpl::propertyChanged(int mappedId)
const auto &v(m_shaders[type].shaderInfo.variables[idx]);
auto &vd(m_shaders[type].varData[idx]);
+ QVariant oldValue = vd.value;
vd.value = getValueFromProperty(m_item, m_itemMetaObject, v.name, vd.propertyIndex);
if (vd.specialType == QSGShaderEffectNode::VariableData::Source) {
- QQuickItem *source = qobject_cast<QQuickItem *>(qvariant_cast<QObject *>(vd.value));
+ QQuickItem *source = qobject_cast<QQuickItem *>(qvariant_cast<QObject *>(oldValue));
if (source) {
if (m_item->window())
QQuickItemPrivate::get(source)->derefWindow();
diff --git a/src/quick/items/qquickshadereffectmesh.cpp b/src/quick/items/qquickshadereffectmesh.cpp
index 118ae18df5..2acd1bcf31 100644
--- a/src/quick/items/qquickshadereffectmesh.cpp
+++ b/src/quick/items/qquickshadereffectmesh.cpp
@@ -54,7 +54,7 @@ QQuickGridMesh::QQuickGridMesh(QObject *parent)
bool QQuickGridMesh::validateAttributes(const QList<QByteArray> &attributes, int *posIndex)
{
- const int attrCount = attributes.count();
+ const int attrCount = attributes.size();
int positionIndex = attributes.indexOf(qtPositionAttributeName());
int texCoordIndex = attributes.indexOf(qtTexCoordAttributeName());
diff --git a/src/quick/items/qquickspriteengine.cpp b/src/quick/items/qquickspriteengine.cpp
index fd5b28b2ed..5d33092e6d 100644
--- a/src/quick/items/qquickspriteengine.cpp
+++ b/src/quick/items/qquickspriteengine.cpp
@@ -267,7 +267,7 @@ int QQuickSpriteEngine::spriteCount() const //TODO: Actually image state count,
void QQuickStochasticEngine::setGoal(int state, int sprite, bool jump)
{
- if (sprite >= m_things.count() || state >= m_states.count()
+ if (sprite >= m_things.size() || state >= m_states.size()
|| sprite < 0 || state < 0)
return;
if (!jump){
@@ -316,12 +316,13 @@ void QQuickSpriteEngine::startAssemblingImage()
return;
m_loaded = false;
m_errorsPrinted = false;
+ m_sprites.clear();
//This could also trigger the start of the image loading in Sprites, however that currently happens in Sprite::setSource
QList<QQuickStochasticState*> removals;
- for (QQuickStochasticState* s : qAsConst(m_states)) {
+ for (QQuickStochasticState* s : std::as_const(m_states)) {
QQuickSprite* sprite = qobject_cast<QQuickSprite*>(s);
if (sprite) {
m_sprites << sprite;
@@ -330,7 +331,7 @@ void QQuickSpriteEngine::startAssemblingImage()
qDebug() << "Error: Non-sprite in QQuickSpriteEngine";
}
}
- for (QQuickStochasticState* s : qAsConst(removals))
+ for (QQuickStochasticState* s : std::as_const(removals))
m_states.removeAll(s);
m_startedImageAssembly = true;
}
@@ -339,7 +340,7 @@ QImage QQuickSpriteEngine::assembledImage(int maxSize)
{
QQuickPixmap::Status stat = status();
if (!m_errorsPrinted && stat == QQuickPixmap::Error) {
- for (QQuickSprite* s : qAsConst(m_sprites))
+ for (QQuickSprite* s : std::as_const(m_sprites))
if (s->m_pix.isError())
qmlWarning(s) << s->m_pix.error();
m_errorsPrinted = true;
@@ -354,7 +355,7 @@ QImage QQuickSpriteEngine::assembledImage(int maxSize)
m_imageStateCount = 0;
qreal pixelRatio = 1.0;
- for (QQuickSprite* state : qAsConst(m_sprites)) {
+ for (QQuickSprite* state : std::as_const(m_sprites)) {
if (state->frames() > m_maxFrames)
m_maxFrames = state->frames();
@@ -414,7 +415,7 @@ QImage QQuickSpriteEngine::assembledImage(int maxSize)
image.fill(0);
QPainter p(&image);
int y = 0;
- for (QQuickSprite* state : qAsConst(m_sprites)) {
+ for (QQuickSprite* state : std::as_const(m_sprites)) {
QImage img(state->m_pix.image());
const int frameWidth = state->m_frameWidth;
const int frameHeight = state->m_frameHeight;
@@ -488,7 +489,7 @@ void QQuickStochasticEngine::setCount(int c)
void QQuickStochasticEngine::start(int index, int state)
{
- if (index >= m_things.count())
+ if (index >= m_things.size())
return;
m_things[index] = state;
m_duration[index] = m_states.at(state)->variedDuration();
@@ -504,10 +505,10 @@ void QQuickStochasticEngine::start(int index, int state)
void QQuickStochasticEngine::stop(int index)
{
- if (index >= m_things.count())
+ if (index >= m_things.size())
return;
//Will never change until start is called again with a new state (or manually advanced) - this is not a 'pause'
- for (int i=0; i<m_stateUpdates.count(); i++)
+ for (int i=0; i<m_stateUpdates.size(); i++)
m_stateUpdates[i].second.removeAll(index);
}
@@ -520,7 +521,7 @@ void QQuickStochasticEngine::restart(int index)
if (randomStart)
m_startTimes[index] -= QRandomGenerator::global()->bounded(m_duration.at(index));
int time = m_duration.at(index) + m_startTimes.at(index);
- for (int i=0; i<m_stateUpdates.count(); i++)
+ for (int i=0; i<m_stateUpdates.size(); i++)
m_stateUpdates[i].second.removeAll(index);
if (m_duration.at(index) >= 0)
addToUpdateList(time, index);
@@ -546,7 +547,7 @@ void QQuickSpriteEngine::restart(int index) //Reimplemented to recognize and han
time += spriteDuration(index);
}
- for (int i=0; i<m_stateUpdates.count(); i++)
+ for (int i=0; i<m_stateUpdates.size(); i++)
m_stateUpdates[i].second.removeAll(index);
addToUpdateList(time, index);
}
@@ -554,7 +555,7 @@ void QQuickSpriteEngine::restart(int index) //Reimplemented to recognize and han
void QQuickStochasticEngine::advance(int idx)
{
- if (idx >= m_things.count())
+ if (idx >= m_things.size())
return;//TODO: Proper fix(because this has happened and I just ignored it)
int nextIdx = nextState(m_things.at(idx), idx);
m_things[idx] = nextIdx;
@@ -571,7 +572,7 @@ void QQuickSpriteEngine::advance(int idx) //Reimplemented to recognize and handl
return;
}
- if (idx >= m_things.count())
+ if (idx >= m_things.size())
return;//TODO: Proper fix(because this has happened and I just ignored it)
if (m_duration.at(idx) == 0) {
if (m_sprites.at(m_things.at(idx))->frameSync()) {
@@ -614,7 +615,7 @@ int QQuickStochasticEngine::nextState(int curState, int curThing)
iter!=m_states.at(curState)->m_to.constEnd(); ++iter){
if (r < (*iter).toReal()){
bool superBreak = false;
- for (int i=0; i<m_states.count(); i++){
+ for (int i=0; i<m_states.size(); i++){
if (m_states.at(i)->name() == iter.key()){
nextIdx = i;
superBreak = true;
@@ -640,7 +641,7 @@ uint QQuickStochasticEngine::updateSprites(uint time)//### would returning a lis
m_timeOffset = time;
m_addAdvance = false;
int i = 0;
- for (; i < m_stateUpdates.count() && time >= m_stateUpdates.at(i).first; ++i) {
+ for (; i < m_stateUpdates.size() && time >= m_stateUpdates.at(i).first; ++i) {
const auto copy = m_stateUpdates.at(i).second;
for (int idx : copy)
advance(idx);
@@ -665,16 +666,16 @@ int QQuickStochasticEngine::goalSeek(int curIdx, int spriteIdx, int dist)
return -1;
//TODO: caching instead of excessively redoing iterative deepening (which was chosen arbitrarily anyways)
// Paraphrased - implement in an *efficient* manner
- for (int i=0; i<m_states.count(); i++)
+ for (int i=0; i<m_states.size(); i++)
if (m_states.at(curIdx)->name() == goalName)
return curIdx;
if (dist < 0)
- dist = m_states.count();
+ dist = m_states.size();
QQuickStochasticState* curState = m_states.at(curIdx);
for (QVariantMap::const_iterator iter = curState->m_to.constBegin();
iter!=curState->m_to.constEnd(); ++iter){
if (iter.key() == goalName)
- for (int i=0; i<m_states.count(); i++)
+ for (int i=0; i<m_states.size(); i++)
if (m_states.at(i)->name() == goalName)
return i;
}
@@ -683,7 +684,7 @@ int QQuickStochasticEngine::goalSeek(int curIdx, int spriteIdx, int dist)
for (QVariantMap::const_iterator iter = curState->m_to.constBegin();
iter!=curState->m_to.constEnd(); ++iter){
int option = -1;
- for (int j=0; j<m_states.count(); j++)//One place that could be a lot more efficient...
+ for (int j=0; j<m_states.size(); j++)//One place that could be a lot more efficient...
if (m_states.at(j)->name() == iter.key())
if (goalSeek(j, spriteIdx, i) != -1)
option = j;
@@ -691,7 +692,7 @@ int QQuickStochasticEngine::goalSeek(int curIdx, int spriteIdx, int dist)
options << option;
}
if (!options.isEmpty()){
- if (options.count()==1)
+ if (options.size()==1)
return *(options.begin());
int option = -1;
qreal r = QRandomGenerator::global()->generateDouble();
@@ -703,7 +704,7 @@ int QQuickStochasticEngine::goalSeek(int curIdx, int spriteIdx, int dist)
for (QVariantMap::const_iterator iter = curState->m_to.constBegin();
iter!=curState->m_to.constEnd(); ++iter){
bool superContinue = true;
- for (int j=0; j<m_states.count(); j++)
+ for (int j=0; j<m_states.size(); j++)
if (m_states.at(j)->name() == iter.key())
if (options.contains(j))
superContinue = false;
@@ -711,7 +712,7 @@ int QQuickStochasticEngine::goalSeek(int curIdx, int spriteIdx, int dist)
continue;
if (r < (*iter).toReal()){
bool superBreak = false;
- for (int j=0; j<m_states.count(); j++){
+ for (int j=0; j<m_states.size(); j++){
if (m_states.at(j)->name() == iter.key()){
option = j;
superBreak = true;
@@ -731,7 +732,7 @@ int QQuickStochasticEngine::goalSeek(int curIdx, int spriteIdx, int dist)
void QQuickStochasticEngine::addToUpdateList(uint t, int idx)
{
- for (int i=0; i<m_stateUpdates.count(); i++){
+ for (int i=0; i<m_stateUpdates.size(); i++){
if (m_stateUpdates.at(i).first == t){
m_stateUpdates[i].second << idx;
return;
diff --git a/src/quick/items/qquickspriteengine_p.h b/src/quick/items/qquickspriteengine_p.h
index 3b74df241a..ee2fa34f72 100644
--- a/src/quick/items/qquickspriteengine_p.h
+++ b/src/quick/items/qquickspriteengine_p.h
@@ -168,7 +168,7 @@ public:
return m_globalGoal;
}
- int count() const {return m_things.count();}
+ int count() const {return m_things.size();}
void setCount(int c);
void setGoal(int state, int sprite=0, bool jump=false);
@@ -181,13 +181,13 @@ public:
QQuickStochasticState* state(int idx) const {return m_states[idx];}
int stateIndex(QQuickStochasticState* s) const {return m_states.indexOf(s);}
int stateIndex(const QString& s) const {
- for (int i=0; i<m_states.count(); i++)
+ for (int i=0; i<m_states.size(); i++)
if (m_states[i]->name() == s)
return i;
return -1;
}
- int stateCount() {return m_states.count();}
+ int stateCount() {return m_states.size();}
private:
Q_SIGNALS:
@@ -291,7 +291,7 @@ inline void spriteClear(QQmlListProperty<QQuickSprite> *p)
inline qsizetype spriteCount(QQmlListProperty<QQuickSprite> *p)
{
- return reinterpret_cast<QList<QQuickSprite *> *>(p->data)->count();
+ return reinterpret_cast<QList<QQuickSprite *> *>(p->data)->size();
}
inline void spriteReplace(QQmlListProperty<QQuickSprite> *p, qsizetype idx, QQuickSprite *s)
diff --git a/src/quick/items/qquickspritesequence.cpp b/src/quick/items/qquickspritesequence.cpp
index 7e005935e4..4feb3402b1 100644
--- a/src/quick/items/qquickspritesequence.cpp
+++ b/src/quick/items/qquickspritesequence.cpp
@@ -161,7 +161,7 @@ void QQuickSpriteSequence::createEngine()
//TODO: delay until component complete
if (d->m_spriteEngine)
delete d->m_spriteEngine;
- if (d->m_sprites.count()) {
+ if (d->m_sprites.size()) {
d->m_spriteEngine = new QQuickSpriteEngine(d->m_sprites, this);
if (!d->m_goalState.isEmpty())
d->m_spriteEngine->setGoal(d->m_spriteEngine->stateIndex(d->m_goalState));
diff --git a/src/quick/items/qquickstateoperations.cpp b/src/quick/items/qquickstateoperations.cpp
index 9e1d771364..a6e5eed56c 100644
--- a/src/quick/items/qquickstateoperations.cpp
+++ b/src/quick/items/qquickstateoperations.cpp
@@ -504,7 +504,7 @@ void QQuickParentChange::saveCurrentValues()
return;
QList<QQuickItem *> children = d->rewind->parent->childItems();
- for (int ii = 0; ii < children.count() - 1; ++ii) {
+ for (int ii = 0; ii < children.size() - 1; ++ii) {
if (children.at(ii) == d->target) {
d->rewind->stackBefore = children.at(ii + 1);
break;
diff --git a/src/quick/items/qquicktableview.cpp b/src/quick/items/qquicktableview.cpp
index 54781968b4..cc5c45db72 100644
--- a/src/quick/items/qquicktableview.cpp
+++ b/src/quick/items/qquicktableview.cpp
@@ -188,13 +188,80 @@
\note \l{Qt Quick Controls} offers a SelectionRectangle that can be used
to let the user select cells.
+ \note By default, a cell will become
+ \l {QQuickItemSelectionModel::currentIndex()}{current}, and any selections will
+ be removed, when the user taps on it. If such default tap behavior is not wanted
+ (e.g if you use custom pointer handlers inside your delegate), you can set
+ \l pointerNavigationEnabled to \c false.
+
\section1 Keyboard navigation
In order to support keyboard navigation, you need to assign an \l ItemSelectionModel
to the \l selectionModel property. TableView will then use this model to manipulate
- the model's \l {QQuickItemSelectionModel::currentIndex()}{currentIndex}. You can
+ the model's \l {ItemSelectionModel::currentIndex}{currentIndex}. You can
disable keyboard navigation fully (in case you want to implement your own key
handlers) by setting \l keyNavigationEnabled to \c false.
+
+ \section1 Copy and paste
+
+ Implementing copy and paste operations for a TableView usually also includes using
+ a QUndoStack (or some other undo/redo framework). The QUndoStack can be used to
+ store the different operations done on the model, like adding or removing rows, or
+ pasting data from the clipboard, with a way to undo it again later. However, an
+ accompanying QUndoStack that describes the possible operations, and how to undo them,
+ should be designed according to the needs of the model and the application.
+ As such, TableView doesn't offer a built-in API for handling copy and paste.
+
+ The following snippet can be used as a reference for how to add copy and paste support
+ to your model and TableView. It uses the existing mime data API in QAbstractItemModel,
+ together with QClipboard. The snippet will work as it is, but can also be extended to
+ use a QUndoStack.
+
+ \code
+ // Inside your C++ QAbstractTableModel subclass:
+
+ Q_INVOKABLE void copyToClipboard(const QModelIndexList &indexes) const
+ {
+ QGuiApplication::clipboard()->setMimeData(mimeData(indexes));
+ }
+
+ Q_INVOKABLE bool pasteFromClipboard(const QModelIndex &targetIndex)
+ {
+ const QMimeData *mimeData = QGuiApplication::clipboard()->mimeData();
+ // Consider using a QUndoCommand for the following call. It should store
+ // the (mime) data for the model items that are about to be overwritten, so
+ // that a later call to undo can revert it.
+ return dropMimeData(mimeData, Qt::CopyAction, -1, -1, targetIndex);
+ }
+ \endcode
+
+ The two functions can, for example, be used from QML like this:
+
+ \code
+ TableView {
+ id: tableView
+ model: tableModel
+ selectionModel: ItemSelectionModel {}
+
+ Shortcut {
+ sequence: StandardKey.Copy
+ onActivated: {
+ let indexes = tableView.selectionModel.selectedIndexes
+ tableView.model.copyToClipboard(indexes)
+ }
+ }
+
+ Shortcut {
+ sequence: StandardKey.Paste
+ onActivated: {
+ let targetIndex = tableView.selectionModel.currentIndex
+ tableView.model.pasteFromClipboard(targetIndex)
+ }
+ }
+ }
+ \endcode
+
+ \sa mimeData(), dropMimeData(), QUndoStack, QUndoCommand, QClipboard
*/
/*!
@@ -792,13 +859,14 @@
/*!
\qmlmethod QModelIndex QtQuick::TableView::modelIndex(int column, int row)
\since 6.4
+ \deprecated
- Returns the \l QModelIndex that maps to \a column and \a row in the view.
-
- \a row and \a column should be the row and column in the view (table row and
- table column), and not a row and column in the model.
+ Use \l index(row, column) instead.
- \sa rowAtIndex(), columnAtIndex()
+ \note Because of an API incompatible change between Qt 6.4.0 and Qt 6.4.2, the
+ order of \c row and \c column was specified in the opposite order. If you
+ rely on the order to be \c {modelIndex(column, row)}, you can set the
+ environment variable \c QT_QUICK_TABLEVIEW_COMPAT_VERSION to \c 6.4
*/
/*!
@@ -811,8 +879,25 @@
\endcode
A cell is simply a \l point that combines row and column into
- a single type. Note that \c point.x will map to the column, and
- \c point.y will map to the row.
+ a single type.
+
+ \note \c {point.x} will map to the column, and \c {point.y} will map to the row.
+*/
+
+/*!
+ \qmlmethod QModelIndex QtQuick::TableView::index(int row, int column)
+ \since 6.4.3
+
+ Returns the \l QModelIndex that maps to \a row and \a column in the view.
+
+ \a row and \a column should be the row and column in the view (table row and
+ table column), and not a row and column in the model. For a plain
+ TableView, this is equivalent of calling \c {model.index(row, column).}
+ But for a subclass of TableView, like TreeView, where the data model is
+ wrapped inside an internal proxy model that flattens the tree structure
+ into a table, you need to use this function to resolve the model index.
+
+ \sa rowAtIndex(), columnAtIndex()
*/
/*!
@@ -821,7 +906,7 @@
Returns the row in the view that maps to \a modelIndex in the model.
- \sa columnAtIndex(), modelIndex()
+ \sa columnAtIndex(), index()
*/
/*!
@@ -830,7 +915,7 @@
Returns the column in the view that maps to \a modelIndex in the model.
- \sa rowAtIndex(), modelIndex()
+ \sa rowAtIndex(), index()
*/
/*!
@@ -845,8 +930,10 @@
\endcode
A cell is simply a \l point that combines row and column into
- a single type. Note that \c point.x will map to the column, and
- \c point.y will map to the row.
+ a single type.
+
+ \note that \c {point.x} will map to the column, and
+ \c {point.y} will map to the row.
*/
/*!
@@ -1693,7 +1780,7 @@ void QQuickTableViewPrivate::updateExtents()
relayoutTableItems();
// Inform the sync children that they need to rebuild to stay in sync
- for (auto syncChild : qAsConst(syncChildren)) {
+ for (auto syncChild : std::as_const(syncChildren)) {
auto syncChild_d = syncChild->d_func();
syncChild_d->scheduledRebuildOptions |= RebuildOption::ViewportOnly;
if (tableMovedHorizontally)
@@ -2687,19 +2774,20 @@ void QQuickTableViewPrivate::processRebuildTable()
if (rebuildState == RebuildState::LayoutTable) {
layoutAfterLoadingInitialTable();
+ loadAndUnloadVisibleEdges();
if (!moveToNextRebuildState())
return;
}
- if (rebuildState == RebuildState::LoadAndUnloadAfterLayout) {
+ if (rebuildState == RebuildState::CancelOvershoot) {
+ cancelOvershootAfterLayout();
loadAndUnloadVisibleEdges();
if (!moveToNextRebuildState())
return;
}
- if (rebuildState == RebuildState::CancelOvershoot) {
- cancelOvershootAfterLayout();
- loadAndUnloadVisibleEdges();
+ if (rebuildState == RebuildState::UpdateContentSize) {
+ updateContentSize();
if (!moveToNextRebuildState())
return;
}
@@ -2961,12 +3049,8 @@ void QQuickTableViewPrivate::loadInitialTable()
loadAndUnloadVisibleEdges();
}
-void QQuickTableViewPrivate::layoutAfterLoadingInitialTable()
+void QQuickTableViewPrivate::updateContentSize()
{
- clearEdgeSizeCache();
- relayoutTableItems();
- syncLoadedTableRectFromLoadedTable();
-
const bool allColumnsLoaded = atTableEnd(Qt::LeftEdge) && atTableEnd(Qt::RightEdge);
if (rebuildOptions.testFlag(RebuildOption::CalculateNewContentWidth) || allColumnsLoaded) {
updateAverageColumnWidth();
@@ -2980,6 +3064,16 @@ void QQuickTableViewPrivate::layoutAfterLoadingInitialTable()
}
updateExtents();
+}
+
+void QQuickTableViewPrivate::layoutAfterLoadingInitialTable()
+{
+ clearEdgeSizeCache();
+ relayoutTableItems();
+ syncLoadedTableRectFromLoadedTable();
+
+ updateContentSize();
+
adjustViewportXAccordingToAlignment();
adjustViewportYAccordingToAlignment();
}
@@ -3098,7 +3192,7 @@ void QQuickTableViewPrivate::unloadEdge(Qt::Edge edge)
void QQuickTableViewPrivate::loadEdge(Qt::Edge edge, QQmlIncubator::IncubationMode incubationMode)
{
const int edgeIndex = nextVisibleEdgeIndexAroundLoadedTable(edge);
- qCDebug(lcTableViewDelegateLifecycle) << edge << edgeIndex;
+ qCDebug(lcTableViewDelegateLifecycle) << edge << edgeIndex << q_func();
const auto &visibleCells = edge & (Qt::LeftEdge | Qt::RightEdge)
? loadedRows.values() : loadedColumns.values();
@@ -3653,6 +3747,13 @@ void QQuickTableViewPrivate::syncSyncView()
q->setLeftMargin(syncView->leftMargin());
q->setRightMargin(syncView->rightMargin());
updateContentWidth();
+
+ if (syncView->leftColumn() != q->leftColumn()) {
+ // The left column is no longer the same as the left
+ // column in syncView. This requires a rebuild.
+ scheduledRebuildOptions |= QQuickTableViewPrivate::RebuildOption::CalculateNewTopLeftColumn;
+ scheduledRebuildOptions.setFlag(RebuildOption::ViewportOnly);
+ }
}
if (syncVertically) {
@@ -3661,6 +3762,13 @@ void QQuickTableViewPrivate::syncSyncView()
q->setTopMargin(syncView->topMargin());
q->setBottomMargin(syncView->bottomMargin());
updateContentHeight();
+
+ if (syncView->topRow() != q->topRow()) {
+ // The top row is no longer the same as the top
+ // row in syncView. This requires a rebuild.
+ scheduledRebuildOptions |= QQuickTableViewPrivate::RebuildOption::CalculateNewTopLeftRow;
+ scheduledRebuildOptions.setFlag(RebuildOption::ViewportOnly);
+ }
}
if (syncView && loadedItems.isEmpty() && !tableSize.isEmpty()) {
@@ -4010,10 +4118,26 @@ void QQuickTableViewPrivate::setLocalViewportY(qreal contentY)
void QQuickTableViewPrivate::syncViewportRect()
{
- // Sync viewportRect so that it contains the actual geometry of the viewport
+ // Sync viewportRect so that it contains the actual geometry of the viewport.
+ // Since the column (and row) size of a sync child is decided by the column size
+ // of its sync view, the viewport width of a sync view needs to be the maximum of
+ // the sync views width, and its sync childrens width. This to ensure that no sync
+ // child loads a column which is not yet loaded by the sync view, since then the
+ // implicit column size cannot be resolved.
Q_Q(QQuickTableView);
- viewportRect = QRectF(q->contentX(), q->contentY(), q->width(), q->height());
- qCDebug(lcTableViewDelegateLifecycle) << viewportRect;
+
+ qreal w = q->width();
+ qreal h = q->height();
+
+ for (auto syncChild : std::as_const(syncChildren)) {
+ auto syncChild_d = syncChild->d_func();
+ if (syncChild_d->syncHorizontally)
+ w = qMax(w, syncChild->width());
+ if (syncChild_d->syncHorizontally)
+ h = qMax(h, syncChild->height());
+ }
+
+ viewportRect = QRectF(q->contentX(), q->contentY(), w, h);
}
void QQuickTableViewPrivate::init()
@@ -4030,7 +4154,7 @@ void QQuickTableViewPrivate::init()
positionYAnimation.setProperty(QStringLiteral("contentY"));
positionYAnimation.setEasing(QEasingCurve::OutQuart);
- auto tapHandler = new QQuickTapHandler(q->contentItem());
+ auto tapHandler = new QQuickTableViewTapHandler(q);
QObject::connect(tapHandler, &QQuickTapHandler::pressedChanged, [this, q, tapHandler] {
if (!pointerNavigationEnabled || !tapHandler->isPressed())
@@ -4071,7 +4195,7 @@ void QQuickTableViewPrivate::syncViewportPosRecursive()
}
}
- for (auto syncChild : qAsConst(syncChildren)) {
+ for (auto syncChild : std::as_const(syncChildren)) {
auto syncChild_d = syncChild->d_func();
if (!syncChild_d->inSyncViewportPosRecursive) {
if (syncChild_d->syncHorizontally)
@@ -4634,14 +4758,22 @@ void QQuickTableView::positionViewAtColumn(int column, PositionMode mode, qreal
void QQuickTableView::positionViewAtCell(const QPoint &cell, PositionMode mode, const QPointF &offset, const QRectF &subRect)
{
- positionViewAtRow(cell.y(), mode, offset.y(), subRect);
- positionViewAtColumn(cell.x(), mode, offset.x(), subRect);
+ positionViewAtCell(cell.x(), cell.y(), mode, offset, subRect);
}
void QQuickTableView::positionViewAtCell(int column, int row, PositionMode mode, const QPointF &offset, const QRectF &subRect)
{
- positionViewAtRow(row, mode, offset.y(), subRect);
- positionViewAtColumn(column, mode, offset.x(), subRect);
+ PositionMode horizontalMode = mode & ~(AlignTop | AlignBottom | AlignVCenter);
+ PositionMode verticalMode = mode & ~(AlignLeft | AlignRight | AlignHCenter);
+ if (!horizontalMode && !verticalMode) {
+ qmlWarning(this) << "Unsupported mode:" << int(mode);
+ return;
+ }
+
+ if (horizontalMode)
+ positionViewAtColumn(column, horizontalMode, offset.x(), subRect);
+ if (verticalMode)
+ positionViewAtRow(row, verticalMode, offset.y(), subRect);
}
QQuickItem *QQuickTableView::itemAtCell(const QPoint &cell) const
@@ -4814,7 +4946,26 @@ QPoint QQuickTableView::cellAtIndex(const QModelIndex &index) const
return {index.column(), index.row()};
}
-QModelIndex QQuickTableView::modelIndex(int column, int row) const
+#if QT_DEPRECATED_SINCE(6, 4)
+QModelIndex QQuickTableView::modelIndex(int row, int column) const
+{
+ static bool compat6_4 = qEnvironmentVariable("QT_QUICK_TABLEVIEW_COMPAT_VERSION") == QStringLiteral("6.4");
+ if (compat6_4) {
+ // In Qt 6.4.0 and 6.4.1, a source incompatible change led to row and column
+ // being documented to be specified in the opposite order.
+ // QT_QUICK_TABLEVIEW_COMPAT_VERSION can therefore be set to force tableview
+ // to continue accepting calls to modelIndex(column, row).
+ return modelIndex({row, column});
+ } else {
+ qmlWarning(this) << "modelIndex(row, column) is deprecated. "
+ "Use index(row, column) instead. For more information, see "
+ "https://doc.qt.io/qt-6/qml-qtquick-tableview-obsolete.html";
+ return modelIndex({column, row});
+ }
+}
+#endif
+
+QModelIndex QQuickTableView::index(int row, int column) const
{
return modelIndex({column, row});
}
@@ -4850,7 +5001,10 @@ void QQuickTableView::geometryChange(const QRectF &newGeometry, const QRectF &ol
d->tableModel->drainReusableItemsPool(0);
}
- polish();
+ d->scheduleRebuildTable(
+ QQuickTableViewPrivate::RebuildOption::LayoutOnly |
+ QQuickTableViewPrivate::RebuildOption::CalculateNewContentWidth |
+ QQuickTableViewPrivate::RebuildOption::CalculateNewContentHeight);
}
void QQuickTableView::viewportMoved(Qt::Orientations orientation)
@@ -4918,7 +5072,7 @@ void QQuickTableView::keyPressEvent(QKeyEvent *e)
case Qt::Key_Right:
// Special case: the current index doesn't map to a cell in the view (perhaps
// because it isn't set yet). In that case, we set it to be the top-left cell.
- const QModelIndex topLeftIndex = modelIndex(leftColumn(), topRow());
+ const QModelIndex topLeftIndex = index(topRow(), leftColumn());
d->selectionModel->setCurrentIndex(topLeftIndex, QItemSelectionModel::NoUpdate);
}
return;
@@ -5134,6 +5288,20 @@ QQuickTableSectionSizeProviderPrivate::~QQuickTableSectionSizeProviderPrivate()
}
+// ----------------------------------------------
+
+QQuickTableViewTapHandler::QQuickTableViewTapHandler(QQuickTableView *view)
+ : QQuickTapHandler(view->contentItem())
+{
+}
+
+bool QQuickTableViewTapHandler::wantsEventPoint(const QPointerEvent *event, const QEventPoint &point)
+{
+ auto tableView = static_cast<QQuickTableView *>(parentItem()->parent());
+ auto tableViewPrivate = QQuickTableViewPrivate::get(tableView);
+ return tableViewPrivate->pointerNavigationEnabled && QQuickTapHandler::wantsEventPoint(event, point);
+}
+
QT_END_NAMESPACE
#include "moc_qquicktableview_p.cpp"
diff --git a/src/quick/items/qquicktableview_p.h b/src/quick/items/qquicktableview_p.h
index 598e109093..442e490a87 100644
--- a/src/quick/items/qquicktableview_p.h
+++ b/src/quick/items/qquicktableview_p.h
@@ -77,8 +77,8 @@ public:
Visible = 0x01000,
Contain = 0x02000
};
- Q_FLAG(PositionModeFlag)
Q_DECLARE_FLAGS(PositionMode, PositionModeFlag)
+ Q_FLAG(PositionMode)
enum SelectionBehavior {
SelectionDisabled,
@@ -159,6 +159,8 @@ public:
Q_REVISION(6, 4) Q_INVOKABLE QPoint cellAtPosition(const QPointF &position, bool includeSpacing = false) const;
Q_REVISION(6, 4) Q_INVOKABLE QPoint cellAtPosition(qreal x, qreal y, bool includeSpacing = false) const;
#if QT_DEPRECATED_SINCE(6, 4)
+ QT_DEPRECATED_VERSION_X_6_4("Use index(row, column) instead")
+ Q_REVISION(6, 4) Q_INVOKABLE virtual QModelIndex modelIndex(int row, int column) const;
QT_DEPRECATED_VERSION_X_6_4("Use cellAtPosition() instead")
Q_INVOKABLE QPoint cellAtPos(const QPointF &position, bool includeSpacing = false) const;
Q_INVOKABLE QPoint cellAtPos(qreal x, qreal y, bool includeSpacing = false) const;
@@ -172,8 +174,8 @@ public:
Q_REVISION(6, 2) Q_INVOKABLE qreal implicitColumnWidth(int column) const;
Q_REVISION(6, 2) Q_INVOKABLE qreal implicitRowHeight(int row) const;
+ Q_REVISION(6, 4) Q_INVOKABLE QModelIndex index(int row, int column) const;
Q_REVISION(6, 4) Q_INVOKABLE virtual QModelIndex modelIndex(const QPoint &cell) const;
- Q_REVISION(6, 4) Q_INVOKABLE virtual QModelIndex modelIndex(int column, int row) const;
Q_REVISION(6, 4) Q_INVOKABLE virtual QPoint cellAtIndex(const QModelIndex &index) const;
Q_REVISION(6, 4) Q_INVOKABLE int rowAtIndex(const QModelIndex &index) const;
Q_REVISION(6, 4) Q_INVOKABLE int columnAtIndex(const QModelIndex &index) const;
diff --git a/src/quick/items/qquicktableview_p_p.h b/src/quick/items/qquicktableview_p_p.h
index 608eee8558..7c865169cb 100644
--- a/src/quick/items/qquicktableview_p_p.h
+++ b/src/quick/items/qquicktableview_p_p.h
@@ -29,6 +29,7 @@
#include <QtQuick/private/qquickitemviewfxitem_p_p.h>
#include <QtQuick/private/qquickanimation_p.h>
#include <QtQuick/private/qquickselectable_p.h>
+#include <QtQuick/private/qquicktaphandler_p.h>
QT_BEGIN_NAMESPACE
@@ -60,6 +61,21 @@ private:
Q_DECLARE_PRIVATE(QQuickTableSectionSizeProvider)
};
+/*! \internal
+ * QQuickTableViewTapHandler used to handle tap events explicitly for table view
+ */
+class QQuickTableViewTapHandler : public QQuickTapHandler
+{
+ Q_OBJECT
+
+public:
+ explicit QQuickTableViewTapHandler(QQuickTableView *view);
+ bool wantsEventPoint(const QPointerEvent *event, const QEventPoint &point) override;
+
+ friend class QQuickTableViewPrivate;
+};
+
+
class Q_QUICK_PRIVATE_EXPORT QQuickTableViewPrivate : public QQuickFlickablePrivate, public QQuickSelectable
{
public:
@@ -105,7 +121,7 @@ public:
inline bool isActive() const { return m_active; }
inline QPoint currentCell() const { return cellAt(m_currentIndex); }
- inline bool hasCurrentCell() const { return m_currentIndex < m_visibleCellsInEdge.count(); }
+ inline bool hasCurrentCell() const { return m_currentIndex < m_visibleCellsInEdge.size(); }
inline void moveToNextCell() { ++m_currentIndex; }
inline Qt::Edge edge() const { return m_edge; }
@@ -168,8 +184,8 @@ public:
LoadInitalTable,
VerifyTable,
LayoutTable,
- LoadAndUnloadAfterLayout,
CancelOvershoot,
+ UpdateContentSize,
PreloadColumns,
PreloadRows,
MovePreloadedItemsToPool,
@@ -416,6 +432,7 @@ public:
void adjustViewportXAccordingToAlignment();
void adjustViewportYAccordingToAlignment();
void cancelOvershootAfterLayout();
+ void updateContentSize();
void scheduleRebuildTable(QQuickTableViewPrivate::RebuildOptions options);
diff --git a/src/quick/items/qquicktext.cpp b/src/quick/items/qquicktext.cpp
index 877e120644..e25df1512f 100644
--- a/src/quick/items/qquicktext.cpp
+++ b/src/quick/items/qquicktext.cpp
@@ -285,7 +285,7 @@ void QQuickText::imageDownloadFinished()
if (d->extra.isAllocated() && d->extra->nbActiveDownloads == 0) {
bool needToUpdateLayout = false;
- for (QQuickStyledTextImgTag *img : qAsConst(d->extra->visibleImgTags)) {
+ for (QQuickStyledTextImgTag *img : std::as_const(d->extra->visibleImgTags)) {
if (!img->size.isValid()) {
img->size = img->pix->implicitSize();
needToUpdateLayout = true;
@@ -617,7 +617,7 @@ void QQuickTextPrivate::elideFormats(
{
const int end = start + length;
const QVector<QTextLayout::FormatRange> formats = layout.formats();
- for (int i = 0; i < formats.count(); ++i) {
+ for (int i = 0; i < formats.size(); ++i) {
QTextLayout::FormatRange format = formats.at(i);
const int formatLength = qMin(format.start + format.length, end) - qMax(format.start, start);
if (formatLength > 0) {
@@ -628,7 +628,7 @@ void QQuickTextPrivate::elideFormats(
}
}
-QString QQuickTextPrivate::elidedText(qreal lineWidth, const QTextLine &line, QTextLine *nextLine) const
+QString QQuickTextPrivate::elidedText(qreal lineWidth, const QTextLine &line, const QTextLine *nextLine) const
{
if (nextLine) {
return layout.engine()->elidedText(
@@ -641,7 +641,7 @@ QString QQuickTextPrivate::elidedText(qreal lineWidth, const QTextLine &line, QT
QString elideText = layout.text().mid(line.textStart(), line.textLength());
if (!styledText) {
// QFontMetrics won't help eliding styled text.
- elideText[elideText.length() - 1] = elideChar;
+ elideText[elideText.size() - 1] = elideChar;
// Appending the elide character may push the line over the maximum width
// in which case the elided text will need to be elided.
QFontMetricsF metrics(layout.font());
@@ -792,12 +792,14 @@ QRectF QQuickTextPrivate::setupTextLayout(qreal *const baseline)
br = QRectF();
QRectF unelidedRect;
- QTextLine line = layout.createLine();
+ QTextLine line;
for (visibleCount = 1; ; ++visibleCount) {
+ line = layout.createLine();
+
if (noBreakLastLine && visibleCount == maxLineCount)
layout.engine()->option.setWrapMode(QTextOption::WrapAnywhere);
if (customLayout) {
- setupCustomLineGeometry(line, naturalHeight, layoutText.length());
+ setupCustomLineGeometry(line, naturalHeight, layoutText.size());
} else {
setLineGeometry(line, lineWidth, naturalHeight);
}
@@ -819,7 +821,7 @@ QRectF QQuickTextPrivate::setupTextLayout(qreal *const baseline)
visibleCount -= 1;
- QTextLine previousLine = layout.lineAt(visibleCount - 1);
+ const QTextLine previousLine = layout.lineAt(visibleCount - 1);
elideText = layoutText.at(line.textStart() - 1) != QChar::LineSeparator
? elidedText(line.width(), previousLine, &line)
: elidedText(line.width(), previousLine);
@@ -830,10 +832,9 @@ QRectF QQuickTextPrivate::setupTextLayout(qreal *const baseline)
break;
}
- const QTextLine previousLine = line;
- line = layout.createLine();
- if (!line.isValid()) {
- if (singlelineElide && visibleCount == 1 && previousLine.naturalTextWidth() > previousLine.width()) {
+ const bool isLastLine = line.textStart() + line.textLength() >= layoutText.size();
+ if (isLastLine) {
+ if (singlelineElide && visibleCount == 1 && line.naturalTextWidth() > line.width()) {
// Elide a single previousLine of text if its width exceeds the element width.
elide = true;
widthExceeded = true;
@@ -843,26 +844,25 @@ QRectF QQuickTextPrivate::setupTextLayout(qreal *const baseline)
truncated = true;
elideText = layout.engine()->elidedText(
Qt::TextElideMode(elideMode),
- QFixed::fromReal(previousLine.width()),
+ QFixed::fromReal(line.width()),
0,
- previousLine.textStart(),
- previousLine.textLength());
- elideStart = previousLine.textStart();
- elideEnd = elideStart + previousLine.textLength();
+ line.textStart(),
+ line.textLength());
+ elideStart = line.textStart();
+ elideEnd = elideStart + line.textLength();
} else {
br = unelidedRect;
height = naturalHeight;
}
break;
} else {
- const bool wrappedLine = layoutText.at(line.textStart() - 1) != QChar::LineSeparator;
+ const bool wrappedLine = layoutText.at(line.textStart() + line.textLength() - 1) != QChar::LineSeparator;
wrapped |= wrappedLine;
if (!wrappedLine)
++unwrappedLineCount;
- // Stop if the maximum number of lines has been reached and elide the last line
- // if enabled.
+ // Stop if the maximum number of lines has been reached
if (visibleCount == maxLineCount) {
truncated = true;
heightExceeded |= wrapped;
@@ -871,10 +871,12 @@ QRectF QQuickTextPrivate::setupTextLayout(qreal *const baseline)
elide = true;
if (eos != -1) // There's an abbreviated string available
break;
+
+ const QTextLine nextLine = layout.createLine();
elideText = wrappedLine
- ? elidedText(previousLine.width(), previousLine, &line)
- : elidedText(previousLine.width(), previousLine);
- elideStart = previousLine.textStart();
+ ? elidedText(line.width(), line, &nextLine)
+ : elidedText(line.width(), line);
+ elideStart = line.textStart();
// elideEnd isn't required for right eliding.
} else {
br = unelidedRect;
@@ -911,8 +913,8 @@ QRectF QQuickTextPrivate::setupTextLayout(qreal *const baseline)
// implicit width.
const int eol = line.isValid()
? line.textStart() + line.textLength()
- : layoutText.length();
- if (eol < layoutText.length() && layoutText.at(eol) != QChar::LineSeparator)
+ : layoutText.size();
+ if (eol < layoutText.size() && layoutText.at(eol) != QChar::LineSeparator)
line = layout.createLine();
for (; line.isValid() && unwrappedLineCount <= maxLineCount; ++unwrappedLineCount)
line = layout.createLine();
@@ -1109,18 +1111,18 @@ QRectF QQuickTextPrivate::setupTextLayout(qreal *const baseline)
QVector<QTextLayout::FormatRange> formats;
switch (elideMode) {
case QQuickText::ElideRight:
- elideFormats(elideStart, elideText.length() - 1, 0, &formats);
+ elideFormats(elideStart, elideText.size() - 1, 0, &formats);
break;
case QQuickText::ElideLeft:
- elideFormats(elideEnd - elideText.length() + 1, elideText.length() - 1, 1, &formats);
+ elideFormats(elideEnd - elideText.size() + 1, elideText.size() - 1, 1, &formats);
break;
case QQuickText::ElideMiddle: {
const int index = elideText.indexOf(elideChar);
if (index != -1) {
elideFormats(elideStart, index, 0, &formats);
elideFormats(
- elideEnd - elideText.length() + index + 1,
- elideText.length() - index - 1,
+ elideEnd - elideText.size() + index + 1,
+ elideText.size() - index - 1,
index + 1,
&formats);
}
@@ -1140,7 +1142,7 @@ QRectF QQuickTextPrivate::setupTextLayout(qreal *const baseline)
QTextLine elidedLine = elideLayout->createLine();
elidedLine.setPosition(QPointF(0, height));
if (customLayout) {
- setupCustomLineGeometry(elidedLine, height, elideText.length(), visibleCount - 1);
+ setupCustomLineGeometry(elidedLine, height, elideText.size(), visibleCount - 1);
} else {
setLineGeometry(elidedLine, lineWidth, height);
}
@@ -1194,7 +1196,7 @@ void QQuickTextPrivate::setLineGeometry(QTextLine &line, qreal lineWidth, qreal
QList<QQuickStyledTextImgTag *> imagesInLine;
if (extra.isAllocated()) {
- for (QQuickStyledTextImgTag *image : qAsConst(extra->imgTags)) {
+ for (QQuickStyledTextImgTag *image : std::as_const(extra->imgTags)) {
if (image->position >= line.textStart() &&
image->position < line.textStart() + line.textLength()) {
@@ -1232,7 +1234,7 @@ void QQuickTextPrivate::setLineGeometry(QTextLine &line, qreal lineWidth, qreal
}
}
- for (QQuickStyledTextImgTag *image : qAsConst(imagesInLine)) {
+ for (QQuickStyledTextImgTag *image : std::as_const(imagesInLine)) {
totalLineHeight = qMax(totalLineHeight, textTop + image->pos.y() + image->size.height());
const int leadX = line.cursorToX(image->position);
const int trailX = line.cursorToX(image->position, QTextLine::Trailing);
@@ -2409,21 +2411,23 @@ void QQuickText::geometryChange(const QRectF &newGeometry, const QRectF &oldGeom
goto geomChangeDone;
if (!(widthChanged || widthMaximum) && !d->isLineLaidOutConnected()) { // only height has changed
- if (newGeometry.height() > oldGeometry.height()) {
- if (!d->heightExceeded && !qFuzzyIsNull(oldGeometry.height())) {
- // Height is adequate and growing, and it wasn't 0 previously.
- goto geomChangeDone;
- }
- if (d->lineCount == d->maximumLineCount()) // Reached maximum line and height is growing.
- goto geomChangeDone;
- } else if (newGeometry.height() < oldGeometry.height()) {
- if (d->lineCount < 2 && !verticalScale && newGeometry.height() > 0) // A single line won't be truncated until the text is 0 height.
- goto geomChangeDone;
-
- if (!verticalScale // no scaling, no eliding, and either unwrapped, or no maximum line count.
- && d->elideMode != QQuickText::ElideRight
- && !(d->maximumLineCountValid && d->widthExceeded)) {
- goto geomChangeDone;
+ if (!verticalPositionChanged) {
+ if (newGeometry.height() > oldGeometry.height()) {
+ if (!d->heightExceeded && !qFuzzyIsNull(oldGeometry.height())) {
+ // Height is adequate and growing, and it wasn't 0 previously.
+ goto geomChangeDone;
+ }
+ if (d->lineCount == d->maximumLineCount()) // Reached maximum line and height is growing.
+ goto geomChangeDone;
+ } else if (newGeometry.height() < oldGeometry.height()) {
+ if (d->lineCount < 2 && !verticalScale && newGeometry.height() > 0) // A single line won't be truncated until the text is 0 height.
+ goto geomChangeDone;
+
+ if (!verticalScale // no scaling, no eliding, and either unwrapped, or no maximum line count.
+ && d->elideMode != QQuickText::ElideRight
+ && !(d->maximumLineCountValid && d->widthExceeded)) {
+ goto geomChangeDone;
+ }
}
}
} else if (!heightChanged && widthMaximum) {
@@ -2509,7 +2513,7 @@ QSGNode *QQuickText::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data
node->addTextLayout(QPointF(dx, dy), d->elideLayout, color, d->style, styleColor, linkColor);
if (d->extra.isAllocated()) {
- for (QQuickStyledTextImgTag *img : qAsConst(d->extra->visibleImgTags)) {
+ for (QQuickStyledTextImgTag *img : std::as_const(d->extra->visibleImgTags)) {
QQuickPixmap *pix = img->pix;
if (pix && pix->isReady())
node->addImage(QRectF(img->pos.x() + dx, img->pos.y() + dy, pix->width(), pix->height()), pix->image());
diff --git a/src/quick/items/qquicktext_p_p.h b/src/quick/items/qquicktext_p_p.h
index 5966ff5f75..bfcca403bf 100644
--- a/src/quick/items/qquicktext_p_p.h
+++ b/src/quick/items/qquicktext_p_p.h
@@ -48,7 +48,7 @@ public:
void setLineGeometry(QTextLine &line, qreal lineWidth, qreal &height);
int lineHeightOffset() const;
- QString elidedText(qreal lineWidth, const QTextLine &line, QTextLine *nextLine = nullptr) const;
+ QString elidedText(qreal lineWidth, const QTextLine &line, const QTextLine *nextLine = nullptr) const;
void elideFormats(int start, int length, int offset, QVector<QTextLayout::FormatRange> *elidedFormats);
void clearFormats();
diff --git a/src/quick/items/qquicktextcontrol.cpp b/src/quick/items/qquicktextcontrol.cpp
index cbc9f10f9e..929ce10136 100644
--- a/src/quick/items/qquicktextcontrol.cpp
+++ b/src/quick/items/qquicktextcontrol.cpp
@@ -742,8 +742,7 @@ void QQuickTextControl::processEvent(QEvent *e, const QTransform &transform)
case QEvent::ShortcutOverride:
if (d->interactionFlags & Qt::TextEditable) {
QKeyEvent* ke = static_cast<QKeyEvent *>(e);
- if (isCommonTextEditShortcut(ke))
- ke->accept();
+ ke->setAccepted(isCommonTextEditShortcut(ke));
}
break;
default:
@@ -963,7 +962,7 @@ QRectF QQuickTextControlPrivate::rectForPosition(int position) const
if (relativePos == preeditPos)
relativePos += preeditCursor;
else if (relativePos > preeditPos)
- relativePos += layout->preeditAreaText().length();
+ relativePos += layout->preeditAreaText().size();
}
#endif
QTextLine line = layout->lineForTextPosition(relativePos);
@@ -1272,7 +1271,7 @@ bool QQuickTextControlPrivate::sendMouseEventToInputContext(QMouseEvent *e, cons
QTextLayout *layout = cursor.block().layout();
int cursorPos = q->hitTest(pos, Qt::FuzzyHit) - cursor.position();
- if (cursorPos >= 0 && cursorPos <= layout->preeditAreaText().length()) {
+ if (cursorPos >= 0 && cursorPos <= layout->preeditAreaText().size()) {
if (e->type() == QEvent::MouseButtonRelease) {
QGuiApplication::inputMethod()->invokeAction(QInputMethod::Click, cursorPos);
}
@@ -1344,7 +1343,7 @@ void QQuickTextControlPrivate::inputMethodEvent(QInputMethodEvent *e)
emit q->preeditTextChanged();
}
QVector<QTextLayout::FormatRange> overrides;
- preeditCursor = e->preeditString().length();
+ preeditCursor = e->preeditString().size();
hasImState = !e->preeditString().isEmpty();
cursorVisible = true;
for (int i = 0; i < e->attributes().size(); ++i) {
@@ -1417,7 +1416,7 @@ QVariant QQuickTextControl::inputMethodQuery(Qt::InputMethodQuery property, cons
QTextCursor tmpCursor = d->cursor;
int localPos = d->cursor.position() - block.position();
QString result = block.text().mid(localPos);
- while (result.length() < maxLength) {
+ while (result.size() < maxLength) {
int currentBlock = tmpCursor.blockNumber();
tmpCursor.movePosition(QTextCursor::NextBlock);
if (tmpCursor.blockNumber() == currentBlock)
diff --git a/src/quick/items/qquicktextdocument.cpp b/src/quick/items/qquicktextdocument.cpp
index 4f585f8333..ce0efb4d2a 100644
--- a/src/quick/items/qquicktextdocument.cpp
+++ b/src/quick/items/qquicktextdocument.cpp
@@ -183,7 +183,7 @@ QQuickPixmap *QQuickTextDocumentWithImageResources::loadPixmap(
void QQuickTextDocumentWithImageResources::clearResources()
{
- for (QQuickPixmap *pixmap : qAsConst(m_resources))
+ for (QQuickPixmap *pixmap : std::as_const(m_resources))
pixmap->clear(this);
qDeleteAll(m_resources);
m_resources.clear();
diff --git a/src/quick/items/qquicktextedit.cpp b/src/quick/items/qquicktextedit.cpp
index 8ce622d176..b1158899bf 100644
--- a/src/quick/items/qquicktextedit.cpp
+++ b/src/quick/items/qquicktextedit.cpp
@@ -405,6 +405,11 @@ void QQuickTextEdit::setText(const QString &text)
void QQuickTextEdit::invalidate()
{
+ QMetaObject::invokeMethod(this, &QQuickTextEdit::q_invalidate);
+}
+
+void QQuickTextEdit::q_invalidate()
+{
Q_D(QQuickTextEdit);
if (isComponentComplete()) {
if (d->document != nullptr)
@@ -1088,7 +1093,7 @@ int QQuickTextEdit::positionAt(qreal x, qreal y) const
// preedit or the next text block.
QTextLayout *layout = cursor.block().layout();
const int preeditLength = layout
- ? layout->preeditAreaText().length()
+ ? layout->preeditAreaText().size()
: 0;
if (preeditLength > 0
&& d->document->documentLayout()->blockBoundingRect(cursor.block()).contains(x, y)) {
@@ -2214,7 +2219,7 @@ QSGNode *QQuickTextEdit::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *
// Having nodes spanning across frame boundaries will break the current bookkeeping mechanism. We need to prevent that.
QList<int> frameBoundaries;
frameBoundaries.reserve(frames.size());
- for (QTextFrame *frame : qAsConst(frames))
+ for (QTextFrame *frame : std::as_const(frames))
frameBoundaries.append(frame->firstPosition());
std::sort(frameBoundaries.begin(), frameBoundaries.end());
@@ -2241,13 +2246,16 @@ QSGNode *QQuickTextEdit::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *
if (coveredRegion.top() > viewport.top() + 1) {
qCDebug(lcVP) << "checking backwards from block" << block.blockNumber() << "@" << nodeOffset.y() << coveredRegion;
while (it != textFrame->begin() && it.currentBlock().layout() &&
- it.currentBlock().layout()->boundingRect().top() + nodeOffset.y() > viewport.top())
+ it.currentBlock().layout()->boundingRect().top() + nodeOffset.y() > viewport.top()) {
+ nodeOffset = d->document->documentLayout()->blockBoundingRect(it.currentBlock()).topLeft();
--it;
+ }
if (!it.currentBlock().layout())
++it;
if (Q_LIKELY(it.currentBlock().layout())) {
block = it.currentBlock();
coveredRegion = block.layout()->boundingRect().adjusted(nodeOffset.x(), nodeOffset.y(), nodeOffset.x(), nodeOffset.y());
+ firstDirtyPos = it.currentBlock().position();
} else {
qCWarning(lcVP) << "failed to find a text block with layout during back-scrolling";
}
@@ -2271,11 +2279,13 @@ QSGNode *QQuickTextEdit::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *
}
}
+ bool createdNodeInView = false;
if (inView) {
if (!engine.hasContents()) {
if (node && !node->parent())
d->addCurrentTextNodeToRoot(&engine, rootNode, node, nodeIterator, nodeStart);
node = d->createTextNode();
+ createdNodeInView = true;
updateNodeTransform(node, nodeOffset);
nodeStart = block.position();
}
@@ -2285,18 +2295,18 @@ QSGNode *QQuickTextEdit::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *
if ((it.atEnd()) || block.next().position() >= firstCleanNode.startPos())
break; // last node that needed replacing or last block of the frame
-
QList<int>::const_iterator lowerBound = std::lower_bound(frameBoundaries.constBegin(), frameBoundaries.constEnd(), block.next().position());
if (node && (currentNodeSize > nodeBreakingSize || lowerBound == frameBoundaries.constEnd() || *lowerBound > nodeStart)) {
currentNodeSize = 0;
if (!node->parent())
d->addCurrentTextNodeToRoot(&engine, rootNode, node, nodeIterator, nodeStart);
- node = d->createTextNode();
+ if (!createdNodeInView)
+ node = d->createTextNode();
resetEngine(&engine, d->color, d->selectedTextColor, d->selectionColor);
nodeStart = block.next().position();
}
++it;
- }
+ } // loop over blocks in frame
}
if (Q_LIKELY(node && !node->parent()))
d->addCurrentTextNodeToRoot(&engine, rootNode, node, nodeIterator, nodeStart);
@@ -3357,6 +3367,16 @@ void QQuickTextEdit::clear()
d->control->clear();
}
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug debug, const QQuickTextEditPrivate::Node &n)
+{
+ QDebugStateSaver saver(debug);
+ debug.space();
+ debug << "Node(startPos:" << n.m_startPos << "dirty:" << n.m_dirty << n.m_node << ')';
+ return debug;
+}
+#endif
+
#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
void QQuickTextEdit::setOldSelectionDefault()
{
@@ -3365,7 +3385,7 @@ void QQuickTextEdit::setOldSelectionDefault()
setKeepMouseGrab(false);
d->control->setTextInteractionFlags(d->control->textInteractionFlags() & ~Qt::TextSelectableByMouse);
d->control->setTouchDragSelectionEnabled(true);
- qCDebug(lcTextEdit, "pre-6.4 behavior chosen by import version: selectByMouse defaults false; if enabled, touchscreen acts like a mouse");
+ qCDebug(lcTextEdit, "pre-6.4 behavior chosen: selectByMouse defaults false; if enabled, touchscreen acts like a mouse");
}
// TODO in 6.7.0: remove the note about versions prior to 6.4 in selectByMouse() documentation
diff --git a/src/quick/items/qquicktextedit_p.h b/src/quick/items/qquicktextedit_p.h
index b4a8e95cf4..c98d062c6b 100644
--- a/src/quick/items/qquicktextedit_p.h
+++ b/src/quick/items/qquicktextedit_p.h
@@ -338,6 +338,7 @@ public Q_SLOTS:
Q_REVISION(2, 7) void clear();
private Q_SLOTS:
+ void q_invalidate();
void q_textChanged();
void q_contentsChange(int, int, int);
void updateSelection();
diff --git a/src/quick/items/qquicktextedit_p_p.h b/src/quick/items/qquicktextedit_p_p.h
index b2cbd80626..db07462a5a 100644
--- a/src/quick/items/qquicktextedit_p_p.h
+++ b/src/quick/items/qquicktextedit_p_p.h
@@ -53,6 +53,10 @@ public:
int m_startPos;
QQuickTextNode* m_node;
bool m_dirty;
+
+#ifndef QT_NO_DEBUG_STREAM
+ friend QDebug Q_QUICK_PRIVATE_EXPORT operator<<(QDebug, const Node &);
+#endif
};
typedef QList<Node>::iterator TextNodeIterator;
@@ -202,6 +206,10 @@ public:
static const int largeTextSizeThreshold;
};
+#ifndef QT_NO_DEBUG_STREAM
+QDebug Q_QUICK_PRIVATE_EXPORT operator<<(QDebug debug, const QQuickTextEditPrivate::Node &);
+#endif
+
QT_END_NAMESPACE
#endif // QQUICKTEXTEDIT_P_P_H
diff --git a/src/quick/items/qquicktextinput.cpp b/src/quick/items/qquicktextinput.cpp
index a980e7fbaf..660496734b 100644
--- a/src/quick/items/qquicktextinput.cpp
+++ b/src/quick/items/qquicktextinput.cpp
@@ -31,7 +31,7 @@
QT_BEGIN_NAMESPACE
DEFINE_BOOL_CONFIG_OPTION(qmlDisableDistanceField, QML_DISABLE_DISTANCEFIELD)
-Q_LOGGING_CATEGORY(lcTextInput, "qt.quick.textInput")
+Q_LOGGING_CATEGORY(lcQuickTextInput, "qt.quick.textInput")
/*!
\qmltype TextInput
@@ -173,7 +173,7 @@ void QQuickTextInput::setRenderType(QQuickTextInput::RenderType renderType)
int QQuickTextInput::length() const
{
Q_D(const QQuickTextInput);
- return d->m_text.length();
+ return d->m_text.size();
}
/*!
@@ -833,7 +833,7 @@ int QQuickTextInput::cursorPosition() const
void QQuickTextInput::setCursorPosition(int cp)
{
Q_D(QQuickTextInput);
- if (cp < 0 || cp > text().length())
+ if (cp < 0 || cp > text().size())
return;
d->moveCursor(cp);
}
@@ -866,7 +866,7 @@ QRectF QQuickTextInput::cursorRectangle() const
qreal y = l.y() - d->vscroll + topPadding();
qreal w = 1;
if (d->overwriteMode) {
- if (c < text().length())
+ if (c < text().size())
w = l.cursorToX(c + 1) - x;
else
w = QFontMetrics(font()).horizontalAdvance(QLatin1Char(' ')); // in sync with QTextLine::draw()
@@ -922,7 +922,7 @@ int QQuickTextInput::selectionEnd() const
void QQuickTextInput::select(int start, int end)
{
Q_D(QQuickTextInput);
- if (start < 0 || end < 0 || start > d->m_text.length() || end > d->m_text.length())
+ if (start < 0 || end < 0 || start > d->m_text.size() || end > d->m_text.size())
return;
d->setSelection(start, end-start);
}
@@ -937,10 +937,10 @@ void QQuickTextInput::select(int start, int end)
It is equivalent to the following snippet, but is faster and easier
to use.
- \js
+ \qml
myTextInput.text.toString().substring(myTextInput.selectionStart,
myTextInput.selectionEnd);
- \endjs
+ \endqml
*/
QString QQuickTextInput::selectedText() const
{
@@ -1365,7 +1365,7 @@ QRectF QQuickTextInput::positionToRectangle(int pos) const
pos = 0;
#if QT_CONFIG(im)
else if (pos > d->m_cursor)
- pos += d->preeditAreaText().length();
+ pos += d->preeditAreaText().size();
#endif
QTextLine l = d->m_textLayout.lineForTextPosition(pos);
if (!l.isValid())
@@ -1374,7 +1374,7 @@ QRectF QQuickTextInput::positionToRectangle(int pos) const
qreal y = l.y() - d->vscroll;
qreal w = 1;
if (d->overwriteMode) {
- if (pos < text().length())
+ if (pos < text().size())
w = l.cursorToX(pos + 1) - x;
else
w = QFontMetrics(font()).horizontalAdvance(QLatin1Char(' ')); // in sync with QTextLine::draw()
@@ -1435,7 +1435,7 @@ void QQuickTextInput::positionAt(QQmlV4Function *args) const
const int cursor = d->m_cursor;
if (pos > cursor) {
#if QT_CONFIG(im)
- const int preeditLength = d->preeditAreaText().length();
+ const int preeditLength = d->preeditAreaText().size();
pos = pos > cursor + preeditLength
? pos - preeditLength
: cursor;
@@ -1503,7 +1503,7 @@ void QQuickTextInput::keyPressEvent(QKeyEvent* ev)
int cursorPosition = d->m_cursor;
if (cursorPosition == 0)
ignore = ev->key() == (d->layoutDirection() == Qt::LeftToRight ? Qt::Key_Left : Qt::Key_Right);
- if (!ignore && cursorPosition == d->m_text.length())
+ if (!ignore && cursorPosition == d->m_text.size())
ignore = ev->key() == (d->layoutDirection() == Qt::LeftToRight ? Qt::Key_Right : Qt::Key_Left);
}
if (ignore) {
@@ -1593,10 +1593,13 @@ void QQuickTextInput::mousePressEvent(QMouseEvent *event)
void QQuickTextInput::mouseMoveEvent(QMouseEvent *event)
{
- if (!QQuickDeliveryAgentPrivate::isEventFromMouseOrTouchpad(event))
- return;
-
Q_D(QQuickTextInput);
+ if (!QQuickDeliveryAgentPrivate::isEventFromMouseOrTouchpad(event)
+#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
+ && ! d->selectByTouchDrag
+#endif
+ )
+ return;
if (d->selectPressed) {
if (qAbs(int(event->position().x() - d->pressPos.x())) > QGuiApplication::styleHints()->startDragDistance())
@@ -1629,7 +1632,12 @@ void QQuickTextInput::mouseReleaseEvent(QMouseEvent *event)
d->selectPressed = false;
setKeepMouseGrab(false);
}
- const bool isMouse = QQuickDeliveryAgentPrivate::isEventFromMouseOrTouchpad(event);
+ const bool isMouse = QQuickDeliveryAgentPrivate::isEventFromMouseOrTouchpad(event)
+#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
+ || d->selectByTouchDrag
+#endif
+ ;
+
#if QT_CONFIG(clipboard)
if (isMouse && QGuiApplication::clipboard()->supportsSelection()) {
if (event->button() == Qt::LeftButton) {
@@ -1640,9 +1648,11 @@ void QQuickTextInput::mouseReleaseEvent(QMouseEvent *event)
}
}
#endif
+
// On a touchscreen or with a stylus, set cursor position and focus on release, not on press;
// if Flickable steals the grab in the meantime, the cursor won't move.
- if (!isMouse)
+ // Check d->hasSelectedText() to keep touch-and-hold word selection working.
+ if (!isMouse && !d->hasSelectedText())
d->moveCursor(d->positionAt(event->position()), false);
if (d->focusOnPress && qGuiApp->styleHints()->setFocusOnTouchRelease())
@@ -1658,7 +1668,7 @@ bool QQuickTextInputPrivate::sendMouseEventToInputContext(QMouseEvent *event)
if (composeMode()) {
int tmp_cursor = positionAt(event->position());
int mousePos = tmp_cursor - m_cursor;
- if (mousePos >= 0 && mousePos <= m_textLayout.preeditAreaText().length()) {
+ if (mousePos >= 0 && mousePos <= m_textLayout.preeditAreaText().size()) {
if (event->type() == QEvent::MouseButtonRelease) {
QGuiApplication::inputMethod()->invokeAction(QInputMethod::Click, mousePos);
}
@@ -1684,8 +1694,10 @@ bool QQuickTextInput::event(QEvent* ev)
#if QT_CONFIG(shortcut)
Q_D(QQuickTextInput);
if (ev->type() == QEvent::ShortcutOverride) {
- if (d->m_readOnly)
+ if (d->m_readOnly) {
+ ev->ignore();
return false;
+ }
QKeyEvent* ke = static_cast<QKeyEvent*>(ev);
if (ke == QKeySequence::Copy
|| ke == QKeySequence::Paste
@@ -1728,6 +1740,7 @@ bool QQuickTextInput::event(QEvent* ev)
}
}
}
+ ev->ignore();
}
#endif
@@ -1799,7 +1812,7 @@ void QQuickTextInputPrivate::updateHorizontalScroll()
{
if (autoScroll && m_echoMode != QQuickTextInput::NoEcho) {
#if QT_CONFIG(im)
- const int preeditLength = m_textLayout.preeditAreaText().length();
+ const int preeditLength = m_textLayout.preeditAreaText().size();
ensureVisible(m_cursor, m_preeditCursor, preeditLength);
#else
ensureVisible(m_cursor);
@@ -1813,7 +1826,7 @@ void QQuickTextInputPrivate::updateVerticalScroll()
{
Q_Q(QQuickTextInput);
#if QT_CONFIG(im)
- const int preeditLength = m_textLayout.preeditAreaText().length();
+ const int preeditLength = m_textLayout.preeditAreaText().size();
#endif
const qreal height = qMax<qreal>(0, q->height() - q->topPadding() - q->bottomPadding());
qreal heightUsed = contentSize.height();
@@ -2038,7 +2051,7 @@ void QQuickTextInput::deselect()
void QQuickTextInput::selectAll()
{
Q_D(QQuickTextInput);
- d->setSelection(0, text().length());
+ d->setSelection(0, text().size());
}
/*!
@@ -2151,7 +2164,7 @@ void QQuickTextInput::insert(int position, const QString &text)
if (d->m_passwordMaskDelay > 0)
d->m_passwordEchoTimer.start(d->m_passwordMaskDelay, this);
}
- if (position < 0 || position > d->m_text.length())
+ if (position < 0 || position > d->m_text.size())
return;
const int priorState = d->m_undoState;
@@ -2164,31 +2177,31 @@ void QQuickTextInput::insert(int position, const QString &text)
}
if (d->m_maskData) {
insertText = d->maskString(position, insertText);
- for (int i = 0; i < insertText.length(); ++i) {
+ for (int i = 0; i < insertText.size(); ++i) {
d->addCommand(QQuickTextInputPrivate::Command(
QQuickTextInputPrivate::DeleteSelection, position + i, d->m_text.at(position + i), -1, -1));
d->addCommand(QQuickTextInputPrivate::Command(
QQuickTextInputPrivate::Insert, position + i, insertText.at(i), -1, -1));
}
- d->m_text.replace(position, insertText.length(), insertText);
+ d->m_text.replace(position, insertText.size(), insertText);
if (!insertText.isEmpty())
d->m_textDirty = true;
- if (position < d->m_selend && position + insertText.length() > d->m_selstart)
+ if (position < d->m_selend && position + insertText.size() > d->m_selstart)
d->m_selDirty = true;
} else {
- int remaining = d->m_maxLength - d->m_text.length();
+ int remaining = d->m_maxLength - d->m_text.size();
if (remaining != 0) {
insertText = insertText.left(remaining);
d->m_text.insert(position, insertText);
- for (int i = 0; i < insertText.length(); ++i)
+ for (int i = 0; i < insertText.size(); ++i)
d->addCommand(QQuickTextInputPrivate::Command(
QQuickTextInputPrivate::Insert, position + i, insertText.at(i), -1, -1));
if (d->m_cursor >= position)
- d->m_cursor += insertText.length();
+ d->m_cursor += insertText.size();
if (d->m_selstart >= position)
- d->m_selstart += insertText.length();
+ d->m_selstart += insertText.size();
if (d->m_selend >= position)
- d->m_selend += insertText.length();
+ d->m_selend += insertText.size();
d->m_textDirty = true;
if (position >= d->m_selstart && position <= d->m_selend)
d->m_selDirty = true;
@@ -2221,8 +2234,8 @@ void QQuickTextInput::remove(int start, int end)
{
Q_D(QQuickTextInput);
- start = qBound(0, start, d->m_text.length());
- end = qBound(0, end, d->m_text.length());
+ start = qBound(0, start, d->m_text.size());
+ end = qBound(0, end, d->m_text.size());
if (start > end)
qSwap(start, end);
@@ -2320,7 +2333,7 @@ QString QQuickTextInput::passwordCharacter() const
void QQuickTextInput::setPasswordCharacter(const QString &str)
{
Q_D(QQuickTextInput);
- if (str.length() < 1)
+ if (str.size() < 1)
return;
d->m_passwordCharacter = str.constData()[0];
if (d->m_echoMode == Password || d->m_echoMode == PasswordEchoOnEdit)
@@ -2619,7 +2632,7 @@ void QQuickTextInput::moveCursorSelection(int pos, SelectionMode mode)
finder.setPosition(anchor);
const QTextBoundaryFinder::BoundaryReasons reasons = finder.boundaryReasons();
- if (anchor < text.length() && (reasons == QTextBoundaryFinder::NotAtBoundary
+ if (anchor < text.size() && (reasons == QTextBoundaryFinder::NotAtBoundary
|| (reasons & QTextBoundaryFinder::EndOfItem))) {
finder.toPreviousBoundary();
}
@@ -2628,7 +2641,7 @@ void QQuickTextInput::moveCursorSelection(int pos, SelectionMode mode)
finder.setPosition(pos);
if (pos > 0 && !finder.boundaryReasons())
finder.toNextBoundary();
- const int cursor = finder.position() != -1 ? finder.position() : text.length();
+ const int cursor = finder.position() != -1 ? finder.position() : text.size();
d->setSelection(anchor, cursor - anchor);
} else if (anchor > pos || (anchor == pos && cursor > pos)) {
@@ -2641,10 +2654,10 @@ void QQuickTextInput::moveCursorSelection(int pos, SelectionMode mode)
|| (reasons & QTextBoundaryFinder::StartOfItem))) {
finder.toNextBoundary();
}
- anchor = finder.position() != -1 ? finder.position() : text.length();
+ anchor = finder.position() != -1 ? finder.position() : text.size();
finder.setPosition(pos);
- if (pos < text.length() && !finder.boundaryReasons())
+ if (pos < text.size() && !finder.boundaryReasons())
finder.toPreviousBoundary();
const int cursor = finder.position() != -1 ? finder.position() : 0;
@@ -2900,7 +2913,7 @@ void QQuickTextInputPrivate::updateDisplayText(bool forceUpdate)
if (m_echoMode == QQuickTextInput::Password) {
str.fill(m_passwordCharacter);
- if (m_passwordEchoTimer.isActive() && m_cursor > 0 && m_cursor <= m_text.length()) {
+ if (m_passwordEchoTimer.isActive() && m_cursor > 0 && m_cursor <= m_text.size()) {
int cursor = m_cursor - 1;
QChar uc = m_text.at(cursor);
str[cursor] = uc;
@@ -2920,7 +2933,7 @@ void QQuickTextInputPrivate::updateDisplayText(bool forceUpdate)
// drawing boxes when using fonts that don't have glyphs for such
// characters)
QChar* uc = str.data();
- for (int i = 0; i < str.length(); ++i) {
+ for (int i = 0; i < str.size(); ++i) {
if (uc[i] == QChar::LineSeparator
|| uc[i] == QChar::ParagraphSeparator
|| uc[i] == QChar::ObjectReplacementCharacter)
@@ -3292,7 +3305,7 @@ void QQuickTextInputPrivate::clear()
int priorState = m_undoState;
separateSelection();
m_selstart = 0;
- m_selend = m_text.length();
+ m_selend = m_text.size();
removeSelectedText();
separate();
finishChange(priorState, /*update*/false, /*edited*/false);
@@ -3313,7 +3326,7 @@ void QQuickTextInputPrivate::setSelection(int start, int length)
commitPreedit();
#endif
- if (start < 0 || start > m_text.length()) {
+ if (start < 0 || start > m_text.size()) {
qWarning("QQuickTextInputPrivate::setSelection: Invalid start position");
return;
}
@@ -3322,7 +3335,7 @@ void QQuickTextInputPrivate::setSelection(int start, int length)
if (start == m_selstart && start + length == m_selend && m_cursor == m_selend)
return;
m_selstart = start;
- m_selend = qMin(start + length, m_text.length());
+ m_selend = qMin(start + length, m_text.size());
m_cursor = m_selend;
} else if (length < 0) {
if (start == m_selend && start + length == m_selstart && m_cursor == m_selstart)
@@ -3454,14 +3467,14 @@ void QQuickTextInputPrivate::processInputMethodEvent(QInputMethodEvent *event)
if (m_echoMode == QQuickTextInput::PasswordEchoOnEdit && !m_passwordEchoEditing) {
updatePasswordEchoEditing(true);
m_selstart = 0;
- m_selend = m_text.length();
+ m_selend = m_text.size();
}
removeSelectedText();
}
int c = m_cursor; // cursor position after insertion of commit string
if (event->replacementStart() <= 0)
- c += event->commitString().length() - qMin(-event->replacementStart(), event->replacementLength());
+ c += event->commitString().size() - qMin(-event->replacementStart(), event->replacementLength());
int cursorInsertPos = m_cursor + event->replacementStart();
if (cursorInsertPos < 0)
@@ -3471,7 +3484,7 @@ void QQuickTextInputPrivate::processInputMethodEvent(QInputMethodEvent *event)
if (event->replacementLength()) {
m_selstart = cursorInsertPos;
m_selend = m_selstart + event->replacementLength();
- m_selend = qMin(m_selend, m_text.length());
+ m_selend = qMin(m_selend, m_text.size());
removeSelectedText();
}
m_cursor = cursorInsertPos;
@@ -3480,7 +3493,7 @@ void QQuickTextInputPrivate::processInputMethodEvent(QInputMethodEvent *event)
internalInsert(event->commitString());
cursorPositionChanged = true;
} else {
- m_cursor = qBound(0, c, m_text.length());
+ m_cursor = qBound(0, c, m_text.size());
}
for (int i = 0; i < event->attributes().size(); ++i) {
@@ -3491,15 +3504,16 @@ void QQuickTextInputPrivate::processInputMethodEvent(QInputMethodEvent *event)
// not seem to take the mask into account, so it will reset cursor
// to an invalid position in such case.
if (!cursorPositionChanged)
- m_cursor = qBound(0, a.start + a.length, m_text.length());
+ m_cursor = qBound(0, a.start + a.length, m_text.size());
if (a.length) {
- m_selstart = qMax(0, qMin(a.start, m_text.length()));
+ m_selstart = qMax(0, qMin(a.start, m_text.size()));
m_selend = m_cursor;
if (m_selend < m_selstart) {
qSwap(m_selstart, m_selend);
}
selectionChange = true;
} else {
+ selectionChange = m_selstart != m_selend;
m_selstart = m_selend = 0;
}
cursorPositionChanged = true;
@@ -3514,7 +3528,7 @@ void QQuickTextInputPrivate::processInputMethodEvent(QInputMethodEvent *event)
m_undoPreeditState = priorState;
}
const int oldPreeditCursor = m_preeditCursor;
- m_preeditCursor = event->preeditString().length();
+ m_preeditCursor = event->preeditString().size();
hasImState = !event->preeditString().isEmpty();
bool cursorVisible = true;
QVector<QTextLayout::FormatRange> formats;
@@ -3642,7 +3656,7 @@ bool QQuickTextInputPrivate::finishChange(int validateFromState, bool update, bo
validateFromState = m_undoPreeditState;
#endif
if (validateFromState >= 0 && wasValidInput && !m_validInput) {
- if (m_transactions.count())
+ if (m_transactions.size())
return false;
internalUndo(validateFromState);
m_history.resize(m_undoState);
@@ -3707,7 +3721,7 @@ void QQuickTextInputPrivate::internalSetText(const QString &txt, int pos, bool e
QString oldText = m_text;
if (m_maskData) {
m_text = maskString(0, txt, true);
- m_text += clearString(m_text.length(), m_maxLength - m_text.length());
+ m_text += clearString(m_text.size(), m_maxLength - m_text.size());
} else {
m_text = txt.isEmpty() ? txt : txt.left(m_maxLength);
}
@@ -3716,7 +3730,7 @@ void QQuickTextInputPrivate::internalSetText(const QString &txt, int pos, bool e
#if QT_CONFIG(im)
m_undoPreeditState = -1;
#endif
- m_cursor = (pos < 0 || pos > m_text.length()) ? m_text.length() : pos;
+ m_cursor = (pos < 0 || pos > m_text.size()) ? m_text.size() : pos;
m_textDirty = (oldText != m_text);
bool changed = finishChange(-1, true, edited);
@@ -3772,16 +3786,16 @@ void QQuickTextInputPrivate::internalInsert(const QString &s)
Q_ASSERT(!hasSelectedText()); // insert(), processInputMethodEvent() call removeSelectedText() first.
if (m_maskData) {
QString ms = maskString(m_cursor, s);
- for (int i = 0; i < ms.length(); ++i) {
+ for (int i = 0; i < ms.size(); ++i) {
addCommand (Command(DeleteSelection, m_cursor + i, m_text.at(m_cursor + i), -1, -1));
addCommand(Command(Insert, m_cursor + i, ms.at(i), -1, -1));
}
- m_text.replace(m_cursor, ms.length(), ms);
- m_cursor += ms.length();
+ m_text.replace(m_cursor, ms.size(), ms);
+ m_cursor += ms.size();
m_cursor = nextMaskBlank(m_cursor);
m_textDirty = true;
} else {
- int remaining = m_maxLength - m_text.length();
+ int remaining = m_maxLength - m_text.size();
if (remaining != 0) {
const QStringView remainingStr = QStringView{s}.left(remaining);
m_text.insert(m_cursor, remainingStr);
@@ -3805,7 +3819,7 @@ void QQuickTextInputPrivate::internalInsert(const QString &s)
*/
void QQuickTextInputPrivate::internalDelete(bool wasBackspace)
{
- if (m_cursor < m_text.length()) {
+ if (m_cursor < m_text.size()) {
cancelPasswordEchoTimer();
Q_ASSERT(!hasSelectedText()); // del(), backspace() call removeSelectedText() first.
addCommand(Command((CommandType)((m_maskData ? 2 : 0) + (wasBackspace ? Remove : Delete)),
@@ -3831,7 +3845,7 @@ void QQuickTextInputPrivate::internalDelete(bool wasBackspace)
*/
void QQuickTextInputPrivate::removeSelectedText()
{
- if (m_selstart < m_selend && m_selend <= m_text.length()) {
+ if (m_selstart < m_selend && m_selend <= m_text.size()) {
cancelPasswordEchoTimer();
int i ;
if (m_selstart <= m_cursor && m_cursor < m_selend) {
@@ -3901,13 +3915,13 @@ void QQuickTextInputPrivate::parseInputMask(const QString &maskFields)
m_inputMask = maskFields;
} else {
m_inputMask = maskFields.left(delimiter);
- m_blank = (delimiter + 1 < maskFields.length()) ? maskFields[delimiter + 1] : QLatin1Char(' ');
+ m_blank = (delimiter + 1 < maskFields.size()) ? maskFields[delimiter + 1] : QLatin1Char(' ');
}
// calculate m_maxLength / m_maskData length
m_maxLength = 0;
QChar c = u'\0';
- for (int i=0; i<m_inputMask.length(); i++) {
+ for (int i=0; i<m_inputMask.size(); i++) {
c = m_inputMask.at(i);
if (i > 0 && m_inputMask.at(i-1) == QLatin1Char('\\')) {
m_maxLength++;
@@ -3927,7 +3941,7 @@ void QQuickTextInputPrivate::parseInputMask(const QString &maskFields)
bool s;
bool escape = false;
int index = 0;
- for (int i = 0; i < m_inputMask.length(); i++) {
+ for (int i = 0; i < m_inputMask.size(); i++) {
c = m_inputMask.at(i);
if (escape) {
s = true;
@@ -4078,7 +4092,7 @@ QQuickTextInputPrivate::ValidatorState QQuickTextInputPrivate::hasAcceptableInpu
if (!m_maskData)
return AcceptableInput;
- if (str.length() != m_maxLength)
+ if (str.size() != m_maxLength)
return InvalidInput;
for (int i=0; i < m_maxLength; ++i) {
@@ -4113,7 +4127,7 @@ QString QQuickTextInputPrivate::maskString(uint pos, const QString &str, bool cl
QString s = QString::fromLatin1("");
int i = pos;
while (i < m_maxLength) {
- if (strIndex < str.length()) {
+ if (strIndex < str.size()) {
if (m_maskData[i].separator) {
s += m_maskData[i].maskChar;
if (str[strIndex] == m_maskData[i].maskChar)
@@ -4136,7 +4150,7 @@ QString QQuickTextInputPrivate::maskString(uint pos, const QString &str, bool cl
// search for separator first
int n = findInMask(i, true, true, str[strIndex]);
if (n != -1) {
- if (str.length() != 1 || i == 0 || (i > 0 && (!m_maskData[i-1].separator || m_maskData[i-1].maskChar != str[strIndex]))) {
+ if (str.size() != 1 || i == 0 || (i > 0 && (!m_maskData[i-1].separator || m_maskData[i-1].maskChar != str[strIndex]))) {
s += QStringView{fill}.mid(i, n-i+1);
i = n + 1; // update i to find + 1
}
@@ -4204,7 +4218,7 @@ QString QQuickTextInputPrivate::stripString(const QString &str) const
return str;
QString s;
- int end = qMin(m_maxLength, str.length());
+ int end = qMin(m_maxLength, str.size());
for (int i = 0; i < end; ++i) {
if (m_maskData[i].separator)
s += m_maskData[i].maskChar;
@@ -4629,7 +4643,7 @@ void QQuickTextInputPrivate::processKeyEvent(QKeyEvent* event)
// no need to call del() if we have a selection, insert
// does it already
&& !hasSelectedText()
- && !(m_cursor == q_func()->text().length())) {
+ && !(m_cursor == q_func()->text().size())) {
del();
}
@@ -4872,7 +4886,7 @@ void QQuickTextInput::setOldSelectionDefault()
Q_D(QQuickTextInput);
d->selectByMouse = false;
d->selectByTouchDrag = true;
- qCDebug(lcTextInput, "pre-6.4 behavior chosen by import version: selectByMouse defaults false; if enabled, touchscreen acts like a mouse");
+ qCDebug(lcQuickTextInput, "pre-6.4 behavior chosen: selectByMouse defaults false; if enabled, touchscreen acts like a mouse");
}
// TODO in 6.7.0: remove the note about versions prior to 6.4 in selectByMouse() documentation
diff --git a/src/quick/items/qquicktextinput_p_p.h b/src/quick/items/qquicktextinput_p_p.h
index 3facf42496..01d90f6b10 100644
--- a/src/quick/items/qquicktextinput_p_p.h
+++ b/src/quick/items/qquicktextinput_p_p.h
@@ -315,7 +315,7 @@ public:
#endif
}
- bool allSelected() const { return !m_text.isEmpty() && m_selstart == 0 && m_selend == (int)m_text.length(); }
+ bool allSelected() const { return !m_text.isEmpty() && m_selstart == 0 && m_selend == (int)m_text.size(); }
bool hasSelectedText() const { return !m_text.isEmpty() && m_selend > m_selstart; }
void setSelection(int start, int length);
@@ -342,7 +342,7 @@ public:
}
int start() const { return 0; }
- int end() const { return m_text.length(); }
+ int end() const { return m_text.size(); }
QString realText() const;
@@ -379,18 +379,18 @@ public:
void cursorWordBackward(bool mark) { moveCursor(m_textLayout.previousCursorPosition(m_cursor, QTextLayout::SkipWords), mark); }
void home(bool mark) { moveCursor(0, mark); }
- void end(bool mark) { moveCursor(q_func()->text().length(), mark); }
+ void end(bool mark) { moveCursor(q_func()->text().size(), mark); }
void backspace();
void del();
void deselect() { internalDeselect(); finishChange(); }
- void selectAll() { m_selstart = m_selend = m_cursor = 0; moveCursor(m_text.length(), true); }
+ void selectAll() { m_selstart = m_selend = m_cursor = 0; moveCursor(m_text.size(), true); }
void insert(const QString &);
void clear();
void selectWordAtPos(int);
- void setCursorPosition(int pos) { if (pos <= m_text.length()) moveCursor(qMax(0, pos)); }
+ void setCursorPosition(int pos) { if (pos <= m_text.size()) moveCursor(qMax(0, pos)); }
bool fixup();
diff --git a/src/quick/items/qquicktextnode.cpp b/src/quick/items/qquicktextnode.cpp
index 84fae432d3..171cbdee8b 100644
--- a/src/quick/items/qquicktextnode.cpp
+++ b/src/quick/items/qquicktextnode.cpp
@@ -223,7 +223,7 @@ void QQuickTextNode::addTextLayout(const QPointF &position, QTextLayout *textLay
engine.setPosition(position);
#if QT_CONFIG(im)
- int preeditLength = textLayout->preeditAreaText().length();
+ int preeditLength = textLayout->preeditAreaText().size();
int preeditPosition = textLayout->preeditAreaPosition();
#endif
diff --git a/src/quick/items/qquicktextnodeengine.cpp b/src/quick/items/qquicktextnodeengine.cpp
index df96a4af41..d2256128cf 100644
--- a/src/quick/items/qquicktextnodeengine.cpp
+++ b/src/quick/items/qquicktextnodeengine.cpp
@@ -175,10 +175,7 @@ void QQuickTextNodeEngine::addTextDecorations(const QVarLengthArray<TextDecorati
{
QRectF &rect = textDecoration.rect;
- rect.setY(qRound(rect.y()
- + m_currentLine.ascent()
- + (m_currentLine.leadingIncluded() ? m_currentLine.leading() : qreal(0.0f))
- + offset));
+ rect.setY(qRound(rect.y() + m_currentLine.ascent() + offset));
rect.setHeight(thickness);
}
@@ -960,7 +957,7 @@ void QQuickTextNodeEngine::addTextBlock(QTextDocument *textDocument, const QText
{
Q_ASSERT(textDocument);
#if QT_CONFIG(im)
- int preeditLength = block.isValid() ? block.layout()->preeditAreaText().length() : 0;
+ int preeditLength = block.isValid() ? block.layout()->preeditAreaText().size() : 0;
int preeditPosition = block.isValid() ? block.layout()->preeditAreaPosition() : -1;
#endif
@@ -1082,14 +1079,14 @@ void QQuickTextNodeEngine::addTextBlock(QTextDocument *textDocument, const QText
}
QQuickTextNodeEngine::SelectionState selectionState =
- (selectionStart < textPos + text.length()
+ (selectionStart < textPos + text.size()
&& selectionEnd >= textPos)
? QQuickTextNodeEngine::Selected
: QQuickTextNodeEngine::Unselected;
addTextObject(block, QPointF(), charFormat, selectionState, textDocument, textPos);
}
- textPos += text.length();
+ textPos += text.size();
} else {
if (charFormat.foreground().style() != Qt::NoBrush)
setTextColor(charFormat.foreground().color());
diff --git a/src/quick/items/qquicktreeview.cpp b/src/quick/items/qquicktreeview.cpp
index a8df1ac00a..3ba739d0ca 100644
--- a/src/quick/items/qquicktreeview.cpp
+++ b/src/quick/items/qquicktreeview.cpp
@@ -67,7 +67,7 @@
\li \c {required property bool expanded}
- Is \c true if the model item drawn by the delegate is expanded
in the view.
- \li \c {required property int hasChildren}
+ \li \c {required property bool hasChildren}
- Is \c true if the model item drawn by the delegate has children
in the model.
\li \c {required property int depth}
@@ -338,8 +338,8 @@ void QQuickTreeViewPrivate::updateSelection(const QRect &oldSelection, const QRe
for (int row = newRect.y(); row <= newRect.y() + newRect.height(); ++row) {
if (oldRect.y() != -1 && oldRect.y() <= row && row <= oldRect.y() + oldRect.height())
continue;
- const QModelIndex startIndex = q->modelIndex(newRect.x(), row);
- const QModelIndex endIndex = q->modelIndex(newRect.x() + newRect.width(), row);
+ const QModelIndex startIndex = q->index(row, newRect.x());
+ const QModelIndex endIndex = q->index(row, newRect.x() + newRect.width());
selectionModel->select(QItemSelection(startIndex, endIndex), QItemSelectionModel::Select);
}
@@ -351,15 +351,15 @@ void QQuickTreeViewPrivate::updateSelection(const QRect &oldSelection, const QRe
if (oldRect.x() <= column && column <= oldRect.x() + oldRect.width())
continue;
for (int row = newRect.y(); row <= newRect.y() + newRect.height(); ++row)
- selectionModel->select(q->modelIndex(column, row), QItemSelectionModel::Select);
+ selectionModel->select(q->index(row, column), QItemSelectionModel::Select);
}
// Unselect the rows inside oldRect that don't overlap with newRect
for (int row = oldRect.y(); row <= oldRect.y() + oldRect.height(); ++row) {
if (newRect.y() <= row && row <= newRect.y() + newRect.height())
continue;
- const QModelIndex startIndex = q->modelIndex(oldRect.x(), row);
- const QModelIndex endIndex = q->modelIndex(oldRect.x() + oldRect.width(), row);
+ const QModelIndex startIndex = q->index(row, oldRect.x());
+ const QModelIndex endIndex = q->index(row, oldRect.x() + oldRect.width());
selectionModel->select(QItemSelection(startIndex, endIndex), QItemSelectionModel::Deselect);
}
@@ -375,7 +375,7 @@ void QQuickTreeViewPrivate::updateSelection(const QRect &oldSelection, const QRe
// performance. But large selections containing a lot of columns is not normally
// the case for a treeview, so accept this potential corner case for now.
for (int row = newRect.y(); row <= newRect.y() + newRect.height(); ++row)
- selectionModel->select(q->modelIndex(column, row), QItemSelectionModel::Deselect);
+ selectionModel->select(q->index(row, column), QItemSelectionModel::Deselect);
}
}
}
@@ -588,10 +588,25 @@ QPoint QQuickTreeView::cellAtIndex(const QModelIndex &index) const
return QPoint(tableIndex.column(), tableIndex.row());
}
-QModelIndex QQuickTreeView::modelIndex(int column, int row) const
+#if QT_DEPRECATED_SINCE(6, 4)
+QModelIndex QQuickTreeView::modelIndex(int row, int column) const
{
- return modelIndex({column, row});
+ static const bool compat6_4 = qEnvironmentVariable("QT_QUICK_TABLEVIEW_COMPAT_VERSION") == QStringLiteral("6.4");
+ if (compat6_4) {
+ // XXX Qt 7: Remove this compatibility path here and in QQuickTableView.
+ // In Qt 6.4.0 and 6.4.1, a source incompatible change led to row and column
+ // being documented to be specified in the opposite order.
+ // QT_QUICK_TABLEVIEW_COMPAT_VERSION can therefore be set to force tableview
+ // to continue accepting calls to modelIndex(column, row).
+ return modelIndex({row, column});
+ } else {
+ qmlWarning(this) << "modelIndex(row, column) is deprecated. "
+ "Use index(row, column) instead. For more information, see "
+ "https://doc.qt.io/qt-6/qml-qtquick-tableview-obsolete.html";
+ return modelIndex({column, row});
+ }
}
+#endif
void QQuickTreeView::keyPressEvent(QKeyEvent *event)
{
diff --git a/src/quick/items/qquicktreeview_p.h b/src/quick/items/qquicktreeview_p.h
index f86d6f9369..3b77477684 100644
--- a/src/quick/items/qquicktreeview_p.h
+++ b/src/quick/items/qquicktreeview_p.h
@@ -44,9 +44,13 @@ public:
Q_REVISION(6, 4) Q_INVOKABLE void expandToIndex(const QModelIndex &index);
Q_INVOKABLE QModelIndex modelIndex(const QPoint &cell) const override;
- Q_INVOKABLE QModelIndex modelIndex(int column, int row) const override;
Q_INVOKABLE QPoint cellAtIndex(const QModelIndex &index) const override;
+#if QT_DEPRECATED_SINCE(6, 4)
+ QT_DEPRECATED_VERSION_X_6_4("Use index(row, column) instead")
+ Q_REVISION(6, 4) Q_INVOKABLE QModelIndex modelIndex(int row, int column) const override;
+#endif
+
Q_SIGNALS:
void expanded(int row, int depth);
void collapsed(int row, bool recursively);
diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp
index 2026d41fdf..692e7f284d 100644
--- a/src/quick/items/qquickwindow.cpp
+++ b/src/quick/items/qquickwindow.cpp
@@ -53,6 +53,7 @@
QT_BEGIN_NAMESPACE
+Q_DECLARE_LOGGING_CATEGORY(lcHoverTrace)
Q_DECLARE_LOGGING_CATEGORY(lcMouse)
Q_DECLARE_LOGGING_CATEGORY(lcTouch)
Q_DECLARE_LOGGING_CATEGORY(lcPtr)
@@ -279,7 +280,7 @@ struct PolishLoopDetector
**/
bool check(QQuickItem *item, int itemsRemainingBeforeUpdatePolish)
{
- if (itemsToPolish.count() > itemsRemainingBeforeUpdatePolish) {
+ if (itemsToPolish.size() > itemsRemainingBeforeUpdatePolish) {
// Detected potential polish loop.
++numPolishLoopsInSequence;
if (numPolishLoopsInSequence >= 1000) {
@@ -338,7 +339,7 @@ void QQuickWindowPrivate::polishItems()
QQuickItem *item = itemsToPolish.takeLast();
QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
itemPrivate->polishScheduled = false;
- const int itemsRemaining = itemsToPolish.count();
+ const int itemsRemaining = itemsToPolish.size();
itemPrivate->updatePolish();
item->updatePolish();
if (polishLoopDetector.check(item, itemsRemaining) == true)
@@ -651,7 +652,7 @@ void QQuickWindowPrivate::renderSceneGraph(const QSize &size, const QSize &surfa
pixelSize = size * devicePixelRatio;
else
pixelSize = surfaceSize;
- QSizeF logicalSize = QSizeF(pixelSize) / devicePixelRatio;
+ QSize logicalSize = pixelSize / devicePixelRatio;
renderer->setDevicePixelRatio(devicePixelRatio);
renderer->setDeviceRect(QRect(QPoint(0, 0), pixelSize));
@@ -1078,7 +1079,11 @@ QQuickWindow::QQuickWindow(QQuickWindowPrivate &dd, QWindow *parent)
}
/*!
- \internal
+ Constructs a window for displaying a QML scene, whose rendering will
+ be controlled by the \a control object.
+ Please refer to QQuickRenderControl's documentation for more information.
+
+ \since 5.4
*/
QQuickWindow::QQuickWindow(QQuickRenderControl *control)
: QWindow(*(new QQuickWindowPrivate), nullptr)
@@ -1381,6 +1386,7 @@ bool QQuickWindow::event(QEvent *event)
for (pt : pe->points()) would only iterate once, so we might as well skip that logic.
*/
if (pe->pointCount()) {
+ const bool synthMouse = QQuickDeliveryAgentPrivate::isSynthMouse(pe);
if (QQuickDeliveryAgentPrivate::subsceneAgentsExist) {
bool ret = false;
// Split up the multi-point event according to the relevant QQuickDeliveryAgent that should deliver to each existing grabber
@@ -1389,7 +1395,7 @@ bool QQuickWindow::event(QEvent *event)
QEventPoint::States eventStates;
auto insert = [&](QQuickDeliveryAgent *ptda, const QEventPoint &pt) {
- if (pt.state() == QEventPoint::Pressed)
+ if (pt.state() == QEventPoint::Pressed && !synthMouse)
pe->clearPassiveGrabbers(pt);
auto &ptList = deliveryAgentsNeedingPoints[ptda];
auto idEquals = [](auto id) { return [id] (const auto &e) { return e.id() == id; }; };
@@ -1452,7 +1458,9 @@ bool QQuickWindow::event(QEvent *event)
if (ret)
return true;
- } else {
+ } else if (!synthMouse) {
+ // clear passive grabbers unless it's a system synth-mouse event
+ // QTBUG-104890: Windows sends synth mouse events (which should be ignored) after touch events
for (const auto &pt : pe->points()) {
if (pt.state() == QEventPoint::Pressed)
pe->clearPassiveGrabbers(pt);
@@ -1665,10 +1673,14 @@ void QQuickWindowPrivate::updateCursor(const QPointF &scenePos, QQuickItem *root
QWindow *window = renderWindow ? renderWindow : q;
cursorItem = cursorItemAndHandler.first;
cursorHandler = cursorItemAndHandler.second;
- if (cursorItem)
- window->setCursor(QQuickItemPrivate::get(cursorItem)->effectiveCursor(cursorHandler));
- else
+ if (cursorItem) {
+ const auto cursor = QQuickItemPrivate::get(cursorItem)->effectiveCursor(cursorHandler);
+ qCDebug(lcHoverTrace) << "setting cursor" << cursor << "from" << cursorHandler << "or" << cursorItem;
+ window->setCursor(cursor);
+ } else {
+ qCDebug(lcHoverTrace) << "unsetting cursor";
window->unsetCursor();
+ }
}
}
@@ -1683,7 +1695,7 @@ QPair<QQuickItem*, QQuickPointerHandler*> QQuickWindowPrivate::findCursorItemAnd
if (itemPrivate->subtreeCursorEnabled) {
QList<QQuickItem *> children = itemPrivate->paintOrderChildItems();
- for (int ii = children.count() - 1; ii >= 0; --ii) {
+ for (int ii = children.size() - 1; ii >= 0; --ii) {
QQuickItem *child = children.at(ii);
if (!child->isVisible() || !child->isEnabled() || QQuickItemPrivate::get(child)->culled)
continue;
@@ -1806,7 +1818,7 @@ void QQuickWindowPrivate::rhiCreationFailureMessage(const QString &backendName,
void QQuickWindowPrivate::cleanupNodes()
{
- for (int ii = 0; ii < cleanupNodeList.count(); ++ii)
+ for (int ii = 0; ii < cleanupNodeList.size(); ++ii)
delete cleanupNodeList.at(ii);
cleanupNodeList.clear();
}
@@ -1841,7 +1853,7 @@ void QQuickWindowPrivate::cleanupNodesOnShutdown(QQuickItem *item)
}
}
- for (int ii = 0; ii < p->childItems.count(); ++ii)
+ for (int ii = 0; ii < p->childItems.size(); ++ii)
cleanupNodesOnShutdown(p->childItems.at(ii));
}
@@ -1896,7 +1908,7 @@ static QSGNode *fetchNextNode(QQuickItemPrivate *itemPriv, int &ii, bool &return
{
QList<QQuickItem *> orderedChildren = itemPriv->paintOrderChildItems();
- for (; ii < orderedChildren.count() && orderedChildren.at(ii)->z() < 0; ++ii) {
+ for (; ii < orderedChildren.size() && orderedChildren.at(ii)->z() < 0; ++ii) {
QQuickItemPrivate *childPrivate = QQuickItemPrivate::get(orderedChildren.at(ii));
if (!childPrivate->explicitVisible &&
(!childPrivate->extra.isAllocated() || !childPrivate->extra->effectRefCount))
@@ -1911,7 +1923,7 @@ static QSGNode *fetchNextNode(QQuickItemPrivate *itemPriv, int &ii, bool &return
return itemPriv->paintNode;
}
- for (; ii < orderedChildren.count(); ++ii) {
+ for (; ii < orderedChildren.size(); ++ii) {
QQuickItemPrivate *childPrivate = QQuickItemPrivate::get(orderedChildren.at(ii));
if (!childPrivate->explicitVisible &&
(!childPrivate->extra.isAllocated() || !childPrivate->extra->effectRefCount))
@@ -1939,7 +1951,7 @@ void QQuickWindowPrivate::updateDirtyNode(QQuickItem *item)
if (itemPriv->x != 0. || itemPriv->y != 0.)
matrix.translate(itemPriv->x, itemPriv->y);
- for (int ii = itemPriv->transforms.count() - 1; ii >= 0; --ii)
+ for (int ii = itemPriv->transforms.size() - 1; ii >= 0; --ii)
itemPriv->transforms.at(ii)->applyTo(&matrix);
if (itemPriv->scale() != 1. || itemPriv->rotation() != 0.) {
@@ -3706,7 +3718,7 @@ void QQuickWindowPrivate::runAndClearJobs(QList<QRunnable *> *jobs)
jobs->clear();
renderJobMutex.unlock();
- for (QRunnable *r : qAsConst(jobList)) {
+ for (QRunnable *r : std::as_const(jobList)) {
r->run();
delete r;
}
@@ -3824,7 +3836,7 @@ QSGRendererInterface *QQuickWindow::rendererInterface() const
graphics API based on the platform and other conditions, set \a api to
QSGRendererInterface::Unknown.
- \since 5.8
+ \since 6.0
*/
void QQuickWindow::setGraphicsApi(QSGRendererInterface::GraphicsApi api)
{
diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwarecontext.cpp b/src/quick/scenegraph/adaptations/software/qsgsoftwarecontext.cpp
index 4da188bbfe..0c0ee5e579 100644
--- a/src/quick/scenegraph/adaptations/software/qsgsoftwarecontext.cpp
+++ b/src/quick/scenegraph/adaptations/software/qsgsoftwarecontext.cpp
@@ -107,6 +107,18 @@ void QSGSoftwareRenderContext::initializeIfNeeded()
void QSGSoftwareRenderContext::invalidate()
{
+ qDeleteAll(m_texturesToDelete);
+ m_texturesToDelete.clear();
+
+ qDeleteAll(m_textures);
+ m_textures.clear();
+
+ qDeleteAll(m_fontEnginesToClean);
+ m_fontEnginesToClean.clear();
+
+ qDeleteAll(m_glyphCaches);
+ m_glyphCaches.clear();
+
m_sg->renderContextInvalidated(this);
emit invalidated();
}
diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwareinternalrectanglenode.cpp b/src/quick/scenegraph/adaptations/software/qsgsoftwareinternalrectanglenode.cpp
index 71e9c7b2aa..488f622dce 100644
--- a/src/quick/scenegraph/adaptations/software/qsgsoftwareinternalrectanglenode.cpp
+++ b/src/quick/scenegraph/adaptations/software/qsgsoftwareinternalrectanglenode.cpp
@@ -84,7 +84,7 @@ void QSGSoftwareInternalRectangleNode::setGradientStops(const QGradientStops &st
{
//normalize stops
bool needsNormalization = false;
- for (const QGradientStop &stop : qAsConst(stops)) {
+ for (const QGradientStop &stop : std::as_const(stops)) {
if (stop.first < 0.0 || stop.first > 1.0) {
needsNormalization = true;
break;
@@ -93,7 +93,7 @@ void QSGSoftwareInternalRectangleNode::setGradientStops(const QGradientStops &st
if (needsNormalization) {
QGradientStops normalizedStops;
- if (stops.count() == 1) {
+ if (stops.size() == 1) {
//If there is only one stop, then the position does not matter
//It is just treated as a color
QGradientStop stop = stops.at(0);
@@ -104,7 +104,7 @@ void QSGSoftwareInternalRectangleNode::setGradientStops(const QGradientStops &st
int below = -1;
int above = -1;
QVector<int> between;
- for (int i = 0; i < stops.count(); ++i) {
+ for (int i = 0; i < stops.size(); ++i) {
if (stops.at(i).first < 0.0) {
below = i;
} else if (stops.at(i).first > 1.0) {
@@ -118,7 +118,7 @@ void QSGSoftwareInternalRectangleNode::setGradientStops(const QGradientStops &st
//Interpoloate new color values for above and below
if (below != -1 ) {
//If there are more than one stops left, interpolate
- if (below + 1 < stops.count()) {
+ if (below + 1 < stops.size()) {
normalizedStops.append(interpolateStop(stops.at(below), stops.at(below + 1), 0.0));
} else {
QGradientStop singleStop;
@@ -128,7 +128,7 @@ void QSGSoftwareInternalRectangleNode::setGradientStops(const QGradientStops &st
}
}
- for (int i = 0; i < between.count(); ++i)
+ for (int i = 0; i < between.size(); ++i)
normalizedStops.append(stops.at(between.at(i)));
if (above != -1) {
@@ -249,8 +249,8 @@ bool QSGSoftwareInternalRectangleNode::isOpaque() const
return false;
if (m_penWidth > 0.0f && m_penColor.alpha() < 255)
return false;
- if (m_stops.count() > 0) {
- for (const QGradientStop &stop : qAsConst(m_stops)) {
+ if (m_stops.size() > 0) {
+ for (const QGradientStop &stop : std::as_const(m_stops)) {
if (stop.second.alpha() < 255)
return false;
}
diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenodeupdater.cpp b/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenodeupdater.cpp
index 56400161bb..20e1ca5b8b 100644
--- a/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenodeupdater.cpp
+++ b/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenodeupdater.cpp
@@ -47,7 +47,7 @@ void QSGSoftwareRenderableNodeUpdater::endVisit(QSGTransformNode *)
bool QSGSoftwareRenderableNodeUpdater::visit(QSGClipNode *node)
{
// Make sure to translate the clip rect into world coordinates
- if (m_clipState.count() == 0 || (m_clipState.count() == 1 && m_clipState.top().isNull())) {
+ if (m_clipState.size() == 0 || (m_clipState.size() == 1 && m_clipState.top().isNull())) {
m_clipState.push(m_transformState.top().map(QRegion(node->clipRect().toRect())));
m_hasClip = true;
} else {
@@ -61,7 +61,7 @@ bool QSGSoftwareRenderableNodeUpdater::visit(QSGClipNode *node)
void QSGSoftwareRenderableNodeUpdater::endVisit(QSGClipNode *)
{
m_clipState.pop();
- if (m_clipState.count() == 0 || (m_clipState.count() == 1 && m_clipState.top().isNull()))
+ if (m_clipState.size() == 0 || (m_clipState.size() == 1 && m_clipState.top().isNull()))
m_hasClip = false;
}
diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwarethreadedrenderloop.cpp b/src/quick/scenegraph/adaptations/software/qsgsoftwarethreadedrenderloop.cpp
index fa709deea2..d12deec9f6 100644
--- a/src/quick/scenegraph/adaptations/software/qsgsoftwarethreadedrenderloop.cpp
+++ b/src/quick/scenegraph/adaptations/software/qsgsoftwarethreadedrenderloop.cpp
@@ -754,7 +754,7 @@ void QSGSoftwareThreadedRenderLoop::onAnimationStarted()
{
startOrStopAnimationTimer();
- for (const WindowData &w : qAsConst(m_windows))
+ for (const WindowData &w : std::as_const(m_windows))
w.window->requestUpdate();
}
diff --git a/src/quick/scenegraph/compressedtexture/qsgcompressedatlastexture_p.h b/src/quick/scenegraph/compressedtexture/qsgcompressedatlastexture_p.h
index 8ae245f07e..46c2c1022f 100644
--- a/src/quick/scenegraph/compressedtexture/qsgcompressedatlastexture_p.h
+++ b/src/quick/scenegraph/compressedtexture/qsgcompressedatlastexture_p.h
@@ -63,7 +63,7 @@ public:
QSGTexture *removedFromAtlas(QRhiResourceUpdateBatch *) const override;
const QByteArray &data() const { return m_data; }
- int sizeInBytes() const { return m_data.length(); }
+ int sizeInBytes() const { return m_data.size(); }
private:
QRectF m_texture_coords_rect;
diff --git a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp
index df7575a33e..29d507a8fb 100644
--- a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp
+++ b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp
@@ -272,14 +272,14 @@ void ShaderManager::invalidated()
void ShaderManager::clearCachedRendererData()
{
- for (ShaderManager::Shader *sms : qAsConst(stockShaders)) {
+ for (ShaderManager::Shader *sms : std::as_const(stockShaders)) {
QSGMaterialShader *s = sms->programRhi.program;
if (s) {
QSGMaterialShaderPrivate *sd = QSGMaterialShaderPrivate::get(s);
sd->clearCachedRendererData();
}
}
- for (ShaderManager::Shader *sms : qAsConst(rewrittenShaders)) {
+ for (ShaderManager::Shader *sms : std::as_const(rewrittenShaders)) {
QSGMaterialShader *s = sms->programRhi.program;
if (s) {
QSGMaterialShaderPrivate *sd = QSGMaterialShaderPrivate::get(s);
@@ -915,8 +915,14 @@ Renderer::~Renderer()
qsg_wipeBatch(m_batchPool.at(i));
}
- for (Node *n : qAsConst(m_nodes))
+ for (Node *n : std::as_const(m_nodes)) {
+ if (n->type() == QSGNode::GeometryNodeType) {
+ Element *e = n->element();
+ if (!e->removed)
+ m_elementsToDelete.add(e);
+ }
m_nodeAllocator.release(n);
+ }
// Remaining elements...
for (int i=0; i<m_elementsToDelete.size(); ++i)
@@ -1980,7 +1986,7 @@ void Renderer::uploadBatch(Batch *b)
bool canMerge = (g->drawingMode() == QSGGeometry::DrawTriangles || g->drawingMode() == QSGGeometry::DrawTriangleStrip ||
g->drawingMode() == QSGGeometry::DrawLines || g->drawingMode() == QSGGeometry::DrawPoints)
&& b->positionAttribute >= 0
- && g->indexType() == QSGGeometry::UnsignedShortType
+ && (g->indexType() == QSGGeometry::UnsignedShortType && g->indexCount() > 0)
&& (flags & (QSGMaterial::NoBatching | QSGMaterial_FullMatrix)) == 0
&& ((flags & QSGMaterial::RequiresFullMatrixExceptTranslate) == 0 || b->isTranslateOnlyToRoot())
&& b->isSafeToBatch();
@@ -2869,11 +2875,11 @@ void Renderer::updateMaterialDynamicData(ShaderManager::Shader *sms,
pd->samplerBindingTable[binding] = samplers; // does not own
}
- if (pd->textureBindingTable[binding].count() == pd->samplerBindingTable[binding].count()) {
+ if (pd->textureBindingTable[binding].size() == pd->samplerBindingTable[binding].size()) {
QVarLengthArray<QRhiShaderResourceBinding::TextureAndSampler, 4> textureSamplers;
- for (int i = 0; i < pd->textureBindingTable[binding].count(); ++i) {
+ for (int i = 0; i < pd->textureBindingTable[binding].size(); ++i) {
QRhiTexture *texture = pd->textureBindingTable[binding].at(i)->rhiTexture();
@@ -2960,7 +2966,7 @@ void Renderer::updateMaterialDynamicData(ShaderManager::Shader *sms,
// with increasing binding points afterwards, so the list is already sorted based
// on the binding points, thus we can save some time by telling the QRhi backend
// not to sort again.
- if (pd->ubufBinding <= 0 || bindings.count() <= 1)
+ if (pd->ubufBinding <= 0 || bindings.size() <= 1)
flags |= QRhiShaderResourceBindings::BindingsAreSorted;
e->srb->updateResources(flags);
@@ -3440,7 +3446,7 @@ void Renderer::releaseElement(Element *e, bool inDestructor)
} else {
if (e->srb) {
if (!inDestructor) {
- if (m_shaderManager->srbPool.count() < m_srbPoolThreshold)
+ if (m_shaderManager->srbPool.size() < m_srbPoolThreshold)
m_shaderManager->srbPool.insert(e->srb->serializedLayoutDescription(), e->srb);
else
delete e->srb;
@@ -3783,7 +3789,7 @@ void Renderer::recordRenderPass(RenderPassContext *ctx)
QRhiCommandBuffer *cb = commandBuffer();
cb->debugMarkBegin(QByteArrayLiteral("Qt Quick scene render"));
- for (int i = 0, ie = ctx->opaqueRenderBatches.count(); i != ie; ++i) {
+ for (int i = 0, ie = ctx->opaqueRenderBatches.size(); i != ie; ++i) {
PreparedRenderBatch *renderBatch = &ctx->opaqueRenderBatches[i];
if (renderBatch->batch->merged)
renderMergedBatch(renderBatch);
@@ -3791,7 +3797,7 @@ void Renderer::recordRenderPass(RenderPassContext *ctx)
renderUnmergedBatch(renderBatch);
}
- for (int i = 0, ie = ctx->alphaRenderBatches.count(); i != ie; ++i) {
+ for (int i = 0, ie = ctx->alphaRenderBatches.size(); i != ie; ++i) {
PreparedRenderBatch *renderBatch = &ctx->alphaRenderBatches[i];
if (renderBatch->batch->merged)
renderMergedBatch(renderBatch);
@@ -3803,7 +3809,7 @@ void Renderer::recordRenderPass(RenderPassContext *ctx)
if (m_renderMode == QSGRendererInterface::RenderMode3D) {
// depth post-pass
- for (int i = 0, ie = ctx->alphaRenderBatches.count(); i != ie; ++i) {
+ for (int i = 0, ie = ctx->alphaRenderBatches.size(); i != ie; ++i) {
PreparedRenderBatch *renderBatch = &ctx->alphaRenderBatches[i];
if (renderBatch->batch->merged)
renderMergedBatch(renderBatch, true);
diff --git a/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h b/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h
index 06771d2686..5b0c024466 100644
--- a/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h
+++ b/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h
@@ -115,7 +115,7 @@ public:
// one. when an item is released, we'll reset m_freePage anyway.
if (!p) {
p = new AllocatorPage<Type, PageSize>();
- m_freePage = pages.count();
+ m_freePage = pages.size();
pages.push_back(p);
}
uint pos = p->blocks[PageSize - p->available];
diff --git a/src/quick/scenegraph/coreapi/qsggeometry.cpp b/src/quick/scenegraph/coreapi/qsggeometry.cpp
index bd082a8d79..9541107b78 100644
--- a/src/quick/scenegraph/coreapi/qsggeometry.cpp
+++ b/src/quick/scenegraph/coreapi/qsggeometry.cpp
@@ -370,8 +370,10 @@ const QSGGeometry::AttributeSet &QSGGeometry::defaultAttributes_ColoredPoint2D()
Geometry objects are constructed by default with DrawTriangleStrip as
the drawing mode.
- The attribute structure is assumed to be POD and the geometry object
- assumes this will not go away. There is no memory management involved.
+ \note \a attributes and the \l Attribute objects referenced by it must
+ stay valid for the entire lifetime of the QSGGeometry.
+ QSGGeometry stores a reference to \a attributes and does not delete
+ the \l Attribute objects.
*/
QSGGeometry::QSGGeometry(const QSGGeometry::AttributeSet &attributes,
@@ -494,13 +496,18 @@ const void *QSGGeometry::indexData() const
Specifies the drawing mode, also called primitive topology.
+ \note Starting with Qt 6 the scene graph only exposes topologies that are
+ supported across all the supported 3D graphics APIs. As a result, the
+ values \c DrawLineLoop and \c DrawTriangleFan are no longer supported at
+ run time in Qt 6, even though the enum values themselves are still present.
+
\value DrawPoints
\value DrawLines
- \value DrawLineLoop
+ \omitvalue DrawLineLoop
\value DrawLineStrip
\value DrawTriangles
\value DrawTriangleStrip
- \value DrawTriangleFan
+ \omitvalue DrawTriangleFan
*/
/*!
@@ -534,10 +541,10 @@ void QSGGeometry::setDrawingMode(unsigned int mode)
}
/*!
- Gets the current line or point width or to be used for this
- geometry. This property only applies to line width when the drawingMode
- is DrawLines, DarwLineStrip, or DrawLineLoop. When supported, it also
- applies to point size when the drawingMode is DrawPoints.
+ Gets the current line or point width or to be used for this geometry. This
+ property only applies to line width when the drawingMode is DrawLines or
+ DrawLineStrip. When supported, it also applies to point size when the
+ drawingMode is DrawPoints.
The default value is \c 1.0
@@ -556,10 +563,10 @@ float QSGGeometry::lineWidth() const
}
/*!
- Sets the line or point width to be used for this geometry to \a
- width. This property only applies to line width when the drawingMode is
- DrawLines, DrawLineStrip, or DrawLineLoop. When supported, it also
- applies to point size when the drawingMode is DrawPoints.
+ Sets the line or point width to be used for this geometry to \a width. This
+ property only applies to line width when the drawingMode is DrawLines or
+ DrawLineStrip. When supported, it also applies to point size when the
+ drawingMode is DrawPoints.
\note Support for point and line drawing may be limited at run time,
depending on the platform and graphics API. For example, some APIs do
diff --git a/src/quick/scenegraph/coreapi/qsggeometry.h b/src/quick/scenegraph/coreapi/qsggeometry.h
index 1583bfd5b2..4392070b6e 100644
--- a/src/quick/scenegraph/coreapi/qsggeometry.h
+++ b/src/quick/scenegraph/coreapi/qsggeometry.h
@@ -165,6 +165,7 @@ public:
void setLineWidth(float w);
private:
+ Q_DISABLE_COPY_MOVE(QSGGeometry)
friend class QSGGeometryData;
int m_drawing_mode;
diff --git a/src/quick/scenegraph/coreapi/qsgmaterialshader.cpp b/src/quick/scenegraph/coreapi/qsgmaterialshader.cpp
index e1edbc2445..a3e8b179b3 100644
--- a/src/quick/scenegraph/coreapi/qsgmaterialshader.cpp
+++ b/src/quick/scenegraph/coreapi/qsgmaterialshader.cpp
@@ -247,7 +247,7 @@ void QSGMaterialShaderPrivate::prepare(QShader::Variant vertexShaderVariant)
const QShaderDescription desc = it->shader.description();
const QVector<QShaderDescription::UniformBlock> ubufs = desc.uniformBlocks();
- const int ubufCount = ubufs.count();
+ const int ubufCount = ubufs.size();
if (ubufCount > 1) {
qWarning("Multiple uniform blocks found in shader. "
"This should be avoided as Qt Quick supports only one.");
@@ -272,7 +272,7 @@ void QSGMaterialShaderPrivate::prepare(QShader::Variant vertexShaderVariant)
}
const QVector<QShaderDescription::InOutVariable> imageSamplers = desc.combinedImageSamplers();
- const int imageSamplersCount = imageSamplers.count();
+ const int imageSamplersCount = imageSamplers.size();
for (int i = 0; i < imageSamplersCount; ++i) {
const QShaderDescription::InOutVariable &var(imageSamplers[i]);
diff --git a/src/quick/scenegraph/coreapi/qsgrhivisualizer.cpp b/src/quick/scenegraph/coreapi/qsgrhivisualizer.cpp
index 4352b9e795..9183de29d9 100644
--- a/src/quick/scenegraph/coreapi/qsgrhivisualizer.cpp
+++ b/src/quick/scenegraph/coreapi/qsgrhivisualizer.cpp
@@ -275,7 +275,7 @@ QRhiGraphicsPipeline *RhiVisualizer::PipelineCache::pipeline(RhiVisualizer *visu
quint32 vertexStride,
bool blendOneOne)
{
- for (int i = 0, ie = pipelines.count(); i != ie; ++i) {
+ for (int i = 0, ie = pipelines.size(); i != ie; ++i) {
const Pipeline &p(pipelines.at(i));
if (p.topology == topology && p.format == vertexFormat && p.stride == vertexStride)
return p.ps;
@@ -316,7 +316,7 @@ QRhiGraphicsPipeline *RhiVisualizer::PipelineCache::pipeline(RhiVisualizer *visu
void RhiVisualizer::PipelineCache::releaseResources()
{
- for (int i = 0, ie = pipelines.count(); i != ie; ++i)
+ for (int i = 0, ie = pipelines.size(); i != ie; ++i)
delete pipelines.at(i).ps;
pipelines.clear();
diff --git a/src/quick/scenegraph/coreapi/qsgtexture.cpp b/src/quick/scenegraph/coreapi/qsgtexture.cpp
index 15167f8ae5..f9c1f86436 100644
--- a/src/quick/scenegraph/coreapi/qsgtexture.cpp
+++ b/src/quick/scenegraph/coreapi/qsgtexture.cpp
@@ -686,6 +686,7 @@ namespace QNativeInterface {
\inmodule QtQuick
\ingroup native-interfaces
\ingroup native-interfaces-qsgtexture
+ \inheaderfile QSGTexture
\brief Provides access to and enables adopting OpenGL texture objects.
\since 6.0
*/
@@ -786,6 +787,7 @@ namespace QNativeInterface {
\inmodule QtQuick
\ingroup native-interfaces
\ingroup native-interfaces-qsgtexture
+ \inheaderfile QSGTexture
\brief Provides access to and enables adopting Direct3D 11 texture objects.
\since 6.0
*/
@@ -846,6 +848,7 @@ namespace QNativeInterface {
\inmodule QtQuick
\ingroup native-interfaces
\ingroup native-interfaces-qsgtexture
+ \inheaderfile QSGTexture
\brief Provides access to and enables adopting Metal texture objects.
\since 6.0
*/
@@ -893,6 +896,7 @@ namespace QNativeInterface {
\inmodule QtQuick
\ingroup native-interfaces
\ingroup native-interfaces-qsgtexture
+ \inheaderfile QSGTexture
\brief Provides access to and enables adopting Vulkan image objects.
\since 6.0
*/
diff --git a/src/quick/scenegraph/qsgadaptationlayer.cpp b/src/quick/scenegraph/qsgadaptationlayer.cpp
index b2932a12ea..c20a126dce 100644
--- a/src/quick/scenegraph/qsgadaptationlayer.cpp
+++ b/src/quick/scenegraph/qsgadaptationlayer.cpp
@@ -91,7 +91,7 @@ void QSGDistanceFieldGlyphCache::populate(const QVector<glyph_t> &glyphs)
{
QSet<glyph_t> referencedGlyphs;
QSet<glyph_t> newGlyphs;
- int count = glyphs.count();
+ int count = glyphs.size();
for (int i = 0; i < count; ++i) {
glyph_t glyphIndex = glyphs.at(i);
if ((int) glyphIndex >= glyphCount() && glyphCount() > 0) {
@@ -124,7 +124,7 @@ void QSGDistanceFieldGlyphCache::populate(const QVector<glyph_t> &glyphs)
void QSGDistanceFieldGlyphCache::release(const QVector<glyph_t> &glyphs)
{
QSet<glyph_t> unusedGlyphs;
- int count = glyphs.count();
+ int count = glyphs.size();
for (int i = 0; i < count; ++i) {
glyph_t glyphIndex = glyphs.at(i);
GlyphData &gd = glyphData(glyphIndex);
@@ -180,7 +180,7 @@ void QSGDistanceFieldGlyphCache::update()
storeGlyphs(distanceFields);
#if defined(QSG_DISTANCEFIELD_CACHE_DEBUG)
- for (Texture texture : qAsConst(m_textures))
+ for (Texture texture : std::as_const(m_textures))
saveTexture(texture.texture, m_referenceFont.familyName());
#endif
@@ -203,7 +203,7 @@ void QSGDistanceFieldGlyphCache::setGlyphsPosition(const QList<GlyphPosition> &g
{
QVector<quint32> invalidatedGlyphs;
- int count = glyphs.count();
+ int count = glyphs.size();
for (int i = 0; i < count; ++i) {
GlyphPosition glyph = glyphs.at(i);
GlyphData &gd = glyphData(glyph.glyph);
@@ -254,7 +254,7 @@ void QSGDistanceFieldGlyphCache::setGlyphsTexture(const QVector<glyph_t> &glyphs
QVector<quint32> invalidatedGlyphs;
- int count = glyphs.count();
+ int count = glyphs.size();
for (int j = 0; j < count; ++j) {
glyph_t glyphIndex = glyphs.at(j);
GlyphData &gd = glyphData(glyphIndex);
@@ -272,14 +272,14 @@ void QSGDistanceFieldGlyphCache::setGlyphsTexture(const QVector<glyph_t> &glyphs
void QSGDistanceFieldGlyphCache::markGlyphsToRender(const QVector<glyph_t> &glyphs)
{
- int count = glyphs.count();
+ int count = glyphs.size();
for (int i = 0; i < count; ++i)
m_pendingGlyphs.add(glyphs.at(i));
}
void QSGDistanceFieldGlyphCache::updateRhiTexture(QRhiTexture *oldTex, QRhiTexture *newTex, const QSize &newTexSize)
{
- int count = m_textures.count();
+ int count = m_textures.size();
for (int i = 0; i < count; ++i) {
Texture &tex = m_textures[i];
if (tex.texture == oldTex) {
diff --git a/src/quick/scenegraph/qsgadaptationlayer_p.h b/src/quick/scenegraph/qsgadaptationlayer_p.h
index c20a99a8a9..a1edc97f52 100644
--- a/src/quick/scenegraph/qsgadaptationlayer_p.h
+++ b/src/quick/scenegraph/qsgadaptationlayer_p.h
@@ -256,7 +256,6 @@ public:
Texture // for APIs with separate texture and sampler objects
};
struct Variable {
- Variable() {}
VariableType type = Constant;
QByteArray name;
uint offset = 0; // for cbuffer members
@@ -337,6 +336,7 @@ public:
};
ShaderSyncData vertex;
ShaderSyncData fragment;
+ void *materialTypeCacheKey;
};
// Each ShaderEffect item has one node (render thread) and one manager (gui thread).
diff --git a/src/quick/scenegraph/qsgcontextplugin.cpp b/src/quick/scenegraph/qsgcontextplugin.cpp
index 192bd565a9..e21f2fbb6f 100644
--- a/src/quick/scenegraph/qsgcontextplugin.cpp
+++ b/src/quick/scenegraph/qsgcontextplugin.cpp
@@ -81,7 +81,7 @@ QSGAdaptationBackendData *contextFactory()
const QStringList args = QGuiApplication::arguments();
QString requestedBackend = backendData->quickWindowBackendRequest; // empty or set via QQuickWindow::setSceneGraphBackend()
- for (int index = 0; index < args.count(); ++index) {
+ for (int index = 0; index < args.size(); ++index) {
if (args.at(index).startsWith(QLatin1String("--device="))) {
requestedBackend = args.at(index).mid(9);
break;
@@ -129,7 +129,7 @@ QSGAdaptationBackendData *contextFactory()
qCDebug(QSG_LOG_INFO, "Loading backend %s", qUtf8Printable(requestedBackend));
// First look for a built-in adaptation.
- for (QSGContextFactoryInterface *builtInBackend : qAsConst(backendData->builtIns)) {
+ for (QSGContextFactoryInterface *builtInBackend : std::as_const(backendData->builtIns)) {
if (builtInBackend->keys().contains(requestedBackend)) {
backendData->factory = builtInBackend;
backendData->name = requestedBackend;
diff --git a/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp b/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp
index 429d7ad4e1..43a7e919bc 100644
--- a/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp
+++ b/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp
@@ -472,9 +472,11 @@ void QSGTextMaskMaterial::populate(const QPointF &p,
bool supportsSubPixelPositions = fontD->fontEngine->supportsHorizontalSubPixelPositions();
for (int i=0; i<glyphIndexes.size(); ++i) {
QPointF glyphPosition = glyphPositions.at(i) + position;
+ QFixedPoint fixedPointPosition = fixedPointPositions.at(i);
+
QFixed subPixelPosition;
if (supportsSubPixelPositions)
- subPixelPosition = fontD->fontEngine->subPixelPositionForX(QFixed::fromReal(glyphPosition.x() * glyphCacheScaleX));
+ subPixelPosition = fontD->fontEngine->subPixelPositionForX(QFixed::fromReal(fixedPointPosition.x.toReal() * glyphCacheScaleX));
QTextureGlyphCache::GlyphAndSubPixelPosition glyph(glyphIndexes.at(i),
QFixedPoint(subPixelPosition, 0));
diff --git a/src/quick/scenegraph/qsgdefaultrendercontext.cpp b/src/quick/scenegraph/qsgdefaultrendercontext.cpp
index 3fee9d9faf..cd0a5b6d28 100644
--- a/src/quick/scenegraph/qsgdefaultrendercontext.cpp
+++ b/src/quick/scenegraph/qsgdefaultrendercontext.cpp
@@ -119,7 +119,7 @@ void QSGDefaultRenderContext::invalidate()
qDeleteAll(m_glyphCaches);
m_glyphCaches.clear();
- releaseGlyphCacheResourceUpdates();
+ resetGlyphCacheResources();
m_rhi = nullptr;
@@ -264,12 +264,23 @@ QRhiResourceUpdateBatch *QSGDefaultRenderContext::glyphCacheResourceUpdates()
return m_glyphCacheResourceUpdates;
}
-void QSGDefaultRenderContext::releaseGlyphCacheResourceUpdates()
+void QSGDefaultRenderContext::deferredReleaseGlyphCacheTexture(QRhiTexture *texture)
+{
+ if (texture)
+ m_pendingGlyphCacheTextures.insert(texture);
+}
+
+void QSGDefaultRenderContext::resetGlyphCacheResources()
{
if (m_glyphCacheResourceUpdates) {
m_glyphCacheResourceUpdates->release();
m_glyphCacheResourceUpdates = nullptr;
}
+
+ for (QRhiTexture *t : std::as_const(m_pendingGlyphCacheTextures))
+ t->deleteLater(); // the QRhiTexture object stays valid for the current frame
+
+ m_pendingGlyphCacheTextures.clear();
}
QT_END_NAMESPACE
diff --git a/src/quick/scenegraph/qsgdefaultrendercontext_p.h b/src/quick/scenegraph/qsgdefaultrendercontext_p.h
index 448255a594..580a973e85 100644
--- a/src/quick/scenegraph/qsgdefaultrendercontext_p.h
+++ b/src/quick/scenegraph/qsgdefaultrendercontext_p.h
@@ -24,6 +24,7 @@ class QRhi;
class QRhiCommandBuffer;
class QRhiRenderPassDescriptor;
class QRhiResourceUpdateBatch;
+class QRhiTexture;
class QSGMaterialShader;
class QSurface;
@@ -102,7 +103,8 @@ public:
QRhiResourceUpdateBatch *maybeGlyphCacheResourceUpdates();
QRhiResourceUpdateBatch *glyphCacheResourceUpdates();
- void releaseGlyphCacheResourceUpdates();
+ void deferredReleaseGlyphCacheTexture(QRhiTexture *texture);
+ void resetGlyphCacheResources();
protected:
static QString fontKey(const QRawFont &font, int renderTypeQuality);
@@ -116,6 +118,7 @@ protected:
qreal m_currentDevicePixelRatio;
bool m_useDepthBufferFor2D;
QRhiResourceUpdateBatch *m_glyphCacheResourceUpdates;
+ QSet<QRhiTexture *> m_pendingGlyphCacheTextures;
};
QT_END_NAMESPACE
diff --git a/src/quick/scenegraph/qsgdistancefieldglyphnode.cpp b/src/quick/scenegraph/qsgdistancefieldglyphnode.cpp
index bff5d0404d..64f862f948 100644
--- a/src/quick/scenegraph/qsgdistancefieldglyphnode.cpp
+++ b/src/quick/scenegraph/qsgdistancefieldglyphnode.cpp
@@ -101,11 +101,11 @@ void QSGDistanceFieldGlyphNode::setGlyphs(const QPointF &position, const QGlyphR
m_glyph_cache->populate(glyphs.glyphIndexes());
const QVector<quint32> glyphIndexes = m_glyphs.glyphIndexes();
- for (int i = 0; i < glyphIndexes.count(); ++i)
+ for (int i = 0; i < glyphIndexes.size(); ++i)
m_allGlyphIndexesLookup.insert(glyphIndexes.at(i));
qCDebug(lcSgText, "inserting %" PRIdQSIZETYPE " glyphs, %" PRIdQSIZETYPE " unique",
- glyphIndexes.count(),
- m_allGlyphIndexesLookup.count());
+ glyphIndexes.size(),
+ m_allGlyphIndexesLookup.size());
#ifdef QSG_RUNTIME_DESCRIPTION
qsgnode_set_description(this, QString::number(glyphs.glyphIndexes().count()) + QStringLiteral(" DF glyphs: ") +
m_glyphs.rawFont().familyName() + QStringLiteral(" ") + QString::number(m_glyphs.rawFont().pixelSize()));
@@ -147,7 +147,7 @@ void QSGDistanceFieldGlyphNode::invalidateGlyphs(const QVector<quint32> &glyphs)
if (m_dirtyGeometry)
return;
- for (int i = 0; i < glyphs.count(); ++i) {
+ for (int i = 0; i < glyphs.size(); ++i) {
if (m_allGlyphIndexesLookup.contains(glyphs.at(i))) {
m_dirtyGeometry = true;
setFlag(UsePreprocess);
@@ -289,12 +289,12 @@ void QSGDistanceFieldGlyphNode::updateGeometry()
Q_ASSERT(m_glyphsInOtherTextures.isEmpty());
} else {
if (!m_glyphsInOtherTextures.isEmpty())
- qCDebug(lcSgText, "%" PRIdQSIZETYPE " 'other' textures", m_glyphsInOtherTextures.count());
+ qCDebug(lcSgText, "%" PRIdQSIZETYPE " 'other' textures", m_glyphsInOtherTextures.size());
QHash<const QSGDistanceFieldGlyphCache::Texture *, GlyphInfo>::const_iterator ite = m_glyphsInOtherTextures.constBegin();
while (ite != m_glyphsInOtherTextures.constEnd()) {
QGlyphRun subNodeGlyphRun(m_glyphs);
- for (int i = 0; i < ite->indexes.count(); i += maxIndexCount) {
- int len = qMin(maxIndexCount, ite->indexes.count() - i);
+ for (int i = 0; i < ite->indexes.size(); i += maxIndexCount) {
+ int len = qMin(maxIndexCount, ite->indexes.size() - i);
subNodeGlyphRun.setRawData(ite->indexes.constData() + i, ite->positions.constData() + i, len);
qCDebug(lcSgText) << "subNodeGlyphRun has" << len << "positions:"
<< *(ite->positions.constData() + i) << "->" << *(ite->positions.constData() + i + len - 1);
diff --git a/src/quick/scenegraph/qsgrenderloop.cpp b/src/quick/scenegraph/qsgrenderloop.cpp
index 5545ea05d9..6dee0304ab 100644
--- a/src/quick/scenegraph/qsgrenderloop.cpp
+++ b/src/quick/scenegraph/qsgrenderloop.cpp
@@ -329,7 +329,7 @@ void QSGGuiThreadRenderLoop::windowDestroyed(QQuickWindow *window)
d->cleanupNodesOnShutdown();
#if QT_CONFIG(quick_shadereffect)
- QSGRhiShaderEffectNode::cleanupMaterialTypeCache();
+ QSGRhiShaderEffectNode::cleanupMaterialTypeCache(window);
#endif
if (m_windows.size() == 0) {
diff --git a/src/quick/scenegraph/qsgrhidistancefieldglyphcache.cpp b/src/quick/scenegraph/qsgrhidistancefieldglyphcache.cpp
index abd0f9c790..54cf298943 100644
--- a/src/quick/scenegraph/qsgrhidistancefieldglyphcache.cpp
+++ b/src/quick/scenegraph/qsgrhidistancefieldglyphcache.cpp
@@ -32,19 +32,10 @@ QSGRhiDistanceFieldGlyphCache::QSGRhiDistanceFieldGlyphCache(QSGDefaultRenderCon
QSGRhiDistanceFieldGlyphCache::~QSGRhiDistanceFieldGlyphCache()
{
- // A plain delete should work, but just in case commitResourceUpdates was
- // not called and something is enqueued on the update batch for a texture,
- // defer until the end of the frame.
- for (int i = 0; i < m_textures.count(); ++i) {
- if (m_textures[i].texture)
- m_textures[i].texture->deleteLater();
- }
+ for (const TextureInfo &t : std::as_const(m_textures))
+ m_rc->deferredReleaseGlyphCacheTexture(t.texture);
delete m_areaAllocator;
-
- // should be empty, but just in case
- for (QRhiTexture *t : qAsConst(m_pendingDispose))
- t->deleteLater();
}
void QSGRhiDistanceFieldGlyphCache::requestGlyphs(const QSet<glyph_t> &glyphs)
@@ -113,7 +104,7 @@ void QSGRhiDistanceFieldGlyphCache::requestGlyphs(const QSet<glyph_t> &glyphs)
bool QSGRhiDistanceFieldGlyphCache::isActive() const
{
- return m_unusedGlyphs.size() != m_glyphsTexture.size();
+ return !m_referencedGlyphs.empty();
}
void QSGRhiDistanceFieldGlyphCache::storeGlyphs(const QList<QDistanceField> &glyphs)
@@ -176,11 +167,13 @@ void QSGRhiDistanceFieldGlyphCache::storeGlyphs(const QList<QDistanceField> &gly
void QSGRhiDistanceFieldGlyphCache::referenceGlyphs(const QSet<glyph_t> &glyphs)
{
+ m_referencedGlyphs += glyphs;
m_unusedGlyphs -= glyphs;
}
void QSGRhiDistanceFieldGlyphCache::releaseGlyphs(const QSet<glyph_t> &glyphs)
{
+ m_referencedGlyphs -= glyphs;
m_unusedGlyphs += glyphs;
}
@@ -241,7 +234,7 @@ void QSGRhiDistanceFieldGlyphCache::resizeTexture(TextureInfo *texInfo, int widt
resourceUpdates->copyTexture(texInfo->texture, oldTexture);
}
- m_pendingDispose.insert(oldTexture);
+ m_rc->deferredReleaseGlyphCacheTexture(oldTexture);
}
bool QSGRhiDistanceFieldGlyphCache::useTextureResizeWorkaround() const
@@ -520,14 +513,8 @@ void QSGRhiDistanceFieldGlyphCache::commitResourceUpdates(QRhiResourceUpdateBatc
{
if (QRhiResourceUpdateBatch *resourceUpdates = m_rc->maybeGlyphCacheResourceUpdates()) {
mergeInto->merge(resourceUpdates);
- m_rc->releaseGlyphCacheResourceUpdates();
+ m_rc->resetGlyphCacheResources();
}
-
- // now let's assume the resource updates will be committed in this frame
- for (QRhiTexture *t : qAsConst(m_pendingDispose))
- t->deleteLater(); // will be deleted after the frame is submitted -> safe
-
- m_pendingDispose.clear();
}
bool QSGRhiDistanceFieldGlyphCache::eightBitFormatIsAlphaSwizzled() const
diff --git a/src/quick/scenegraph/qsgrhidistancefieldglyphcache_p.h b/src/quick/scenegraph/qsgrhidistancefieldglyphcache_p.h
index aed2739c89..b7653881f5 100644
--- a/src/quick/scenegraph/qsgrhidistancefieldglyphcache_p.h
+++ b/src/quick/scenegraph/qsgrhidistancefieldglyphcache_p.h
@@ -71,7 +71,7 @@ private:
TextureInfo *textureInfo(int index)
{
- for (int i = m_textures.count(); i <= index; ++i) {
+ for (int i = m_textures.size(); i <= index; ++i) {
if (createFullSizeTextures())
m_textures.append(QRect(0, 0, maxTextureSize(), maxTextureSize()));
else
@@ -89,6 +89,7 @@ private:
QList<TextureInfo> m_textures;
QHash<glyph_t, TextureInfo *> m_glyphsTexture;
QSet<glyph_t> m_unusedGlyphs;
+ QSet<glyph_t> m_referencedGlyphs;
QSet<QRhiTexture *> m_pendingDispose;
};
diff --git a/src/quick/scenegraph/qsgrhishadereffectnode.cpp b/src/quick/scenegraph/qsgrhishadereffectnode.cpp
index e831c97a80..e7c2b0fb0d 100644
--- a/src/quick/scenegraph/qsgrhishadereffectnode.cpp
+++ b/src/quick/scenegraph/qsgrhishadereffectnode.cpp
@@ -11,6 +11,7 @@
#include <QQmlFile>
#include <QFile>
#include <QFileSelector>
+#include <QMutexLocker>
QT_BEGIN_NAMESPACE
@@ -27,14 +28,18 @@ void QSGRhiShaderLinker::reset(const QShader &vs, const QShader &fs)
m_samplers.clear();
m_samplerNameMap.clear();
m_subRectBindings.clear();
+
+ m_constants.reserve(8);
+ m_samplers.reserve(4);
+ m_samplerNameMap.reserve(4);
}
void QSGRhiShaderLinker::feedConstants(const QSGShaderEffectNode::ShaderData &shader, const QSet<int> *dirtyIndices)
{
- Q_ASSERT(shader.shaderInfo.variables.count() == shader.varData.count());
+ Q_ASSERT(shader.shaderInfo.variables.size() == shader.varData.size());
if (!dirtyIndices) {
m_constantBufferSize = qMax(m_constantBufferSize, shader.shaderInfo.constantDataSize);
- for (int i = 0; i < shader.shaderInfo.variables.count(); ++i) {
+ for (int i = 0; i < shader.shaderInfo.variables.size(); ++i) {
const QSGGuiThreadShaderEffectManager::ShaderInfo::Variable &var(shader.shaderInfo.variables.at(i));
if (var.type == QSGGuiThreadShaderEffectManager::ShaderInfo::Constant) {
const QSGShaderEffectNode::VariableData &vd(shader.varData.at(i));
@@ -75,11 +80,17 @@ void QSGRhiShaderLinker::feedConstants(const QSGShaderEffectNode::ShaderData &sh
void QSGRhiShaderLinker::feedSamplers(const QSGShaderEffectNode::ShaderData &shader, const QSet<int> *dirtyIndices)
{
if (!dirtyIndices) {
- for (int i = 0; i < shader.shaderInfo.variables.count(); ++i) {
+ for (int i = 0; i < shader.shaderInfo.variables.size(); ++i) {
const QSGGuiThreadShaderEffectManager::ShaderInfo::Variable &var(shader.shaderInfo.variables.at(i));
const QSGShaderEffectNode::VariableData &vd(shader.varData.at(i));
if (var.type == QSGGuiThreadShaderEffectManager::ShaderInfo::Sampler) {
Q_ASSERT(vd.specialType == QSGShaderEffectNode::VariableData::Source);
+
+#ifndef QT_NO_DEBUG
+ int existingBindPoint = m_samplerNameMap.value(var.name, -1);
+ Q_ASSERT(existingBindPoint < 0 || existingBindPoint == var.bindPoint);
+#endif
+
m_samplers.insert(var.bindPoint, vd.value);
m_samplerNameMap.insert(var.name, var.bindPoint);
}
@@ -88,6 +99,12 @@ void QSGRhiShaderLinker::feedSamplers(const QSGShaderEffectNode::ShaderData &sha
for (int idx : *dirtyIndices) {
const QSGGuiThreadShaderEffectManager::ShaderInfo::Variable &var(shader.shaderInfo.variables.at(idx));
const QSGShaderEffectNode::VariableData &vd(shader.varData.at(idx));
+
+#ifndef QT_NO_DEBUG
+ int existingBindPoint = m_samplerNameMap.value(var.name, -1);
+ Q_ASSERT(existingBindPoint < 0 || existingBindPoint == var.bindPoint);
+#endif
+
m_samplers.insert(var.bindPoint, vd.value);
m_samplerNameMap.insert(var.name, var.bindPoint);
}
@@ -142,11 +159,18 @@ struct QSGRhiShaderMaterialTypeCache
void reset() { qDeleteAll(m_types); m_types.clear(); }
struct Key {
- QShader blob[2];
- Key() { }
- Key(const QShader &vs, const QShader &fs) { blob[0] = vs; blob[1] = fs; }
+ QShader vs;
+ QShader fs;
+ size_t hash;
+ Key(const QShader &vs, const QShader &fs)
+ : vs(vs),
+ fs(fs)
+ {
+ QtPrivate::QHashCombine hashGen;
+ hash = hashGen(hashGen(0, vs), fs);
+ }
bool operator==(const Key &other) const {
- return blob[0] == other.blob[0] && blob[1] == other.blob[1];
+ return vs == other.vs && fs == other.fs;
}
};
QHash<Key, QSGMaterialType *> m_types;
@@ -154,10 +178,7 @@ struct QSGRhiShaderMaterialTypeCache
size_t qHash(const QSGRhiShaderMaterialTypeCache::Key &key, size_t seed = 0)
{
- size_t hash = seed;
- for (int i = 0; i < 2; ++i)
- hash = hash * 31337 + qHash(key.blob[i]);
- return hash;
+ return seed ^ key.hash;
}
QSGMaterialType *QSGRhiShaderMaterialTypeCache::get(const QShader &vs, const QShader &fs)
@@ -171,7 +192,8 @@ QSGMaterialType *QSGRhiShaderMaterialTypeCache::get(const QShader &vs, const QSh
return t;
}
-static QSGRhiShaderMaterialTypeCache shaderMaterialTypeCache;
+static QHash<void *, QSGRhiShaderMaterialTypeCache> shaderMaterialTypeCache;
+static QMutex shaderMaterialTypeCacheMutex;
class QSGRhiShaderEffectMaterialShader : public QSGMaterialShader
{
@@ -447,7 +469,7 @@ int QSGRhiShaderEffectMaterial::compare(const QSGMaterial *other) const
if (int diff = m_cullMode - o->m_cullMode)
return diff;
- if (int diff = m_textureProviders.count() - o->m_textureProviders.count())
+ if (int diff = m_textureProviders.size() - o->m_textureProviders.size())
return diff;
if (m_linker.m_constants != o->m_linker.m_constants)
@@ -459,7 +481,7 @@ int QSGRhiShaderEffectMaterial::compare(const QSGMaterial *other) const
if (hasAtlasTexture(o->m_textureProviders) && !o->m_geometryUsesTextureSubRect)
return 1;
- for (int binding = 0, count = m_textureProviders.count(); binding != count; ++binding) {
+ for (int binding = 0, count = m_textureProviders.size(); binding != count; ++binding) {
QSGTextureProvider *tp1 = m_textureProviders.at(binding);
QSGTextureProvider *tp2 = o->m_textureProviders.at(binding);
if (tp1 && tp2) {
@@ -559,7 +581,7 @@ QRectF QSGRhiShaderEffectNode::updateNormalizedTextureSubRect(bool supportsAtlas
bool geometryUsesTextureSubRect = false;
if (supportsAtlasTextures) {
QSGTextureProvider *tp = nullptr;
- for (int binding = 0, count = m_material.m_textureProviders.count(); binding != count; ++binding) {
+ for (int binding = 0, count = m_material.m_textureProviders.size(); binding != count; ++binding) {
if (QSGTextureProvider *candidate = m_material.m_textureProviders.at(binding)) {
if (!tp) {
tp = candidate;
@@ -627,7 +649,12 @@ void QSGRhiShaderEffectNode::syncMaterial(SyncData *syncData)
m_material.m_fragmentShader = defaultFragmentShader;
}
- m_material.m_materialType = shaderMaterialTypeCache.get(m_material.m_vertexShader, m_material.m_fragmentShader);
+ {
+ QMutexLocker lock(&shaderMaterialTypeCacheMutex);
+ m_material.m_materialType = shaderMaterialTypeCache[syncData->materialTypeCacheKey].get(m_material.m_vertexShader,
+ m_material.m_fragmentShader);
+ }
+
m_material.m_linker.reset(m_material.m_vertexShader, m_material.m_fragmentShader);
if (m_material.m_hasCustomVertexShader) {
@@ -675,7 +702,7 @@ void QSGRhiShaderEffectNode::syncMaterial(SyncData *syncData)
v.bindPoint = 1;
v.type = QSGGuiThreadShaderEffectManager::ShaderInfo::Sampler;
defaultSD.shaderInfo.variables.append(v);
- for (const QSGShaderEffectNode::VariableData &extVarData : qAsConst(syncData->fragment.shader->varData)) {
+ for (const QSGShaderEffectNode::VariableData &extVarData : std::as_const(syncData->fragment.shader->varData)) {
if (extVarData.specialType == QSGShaderEffectNode::VariableData::Source) {
vd.value = extVarData.value;
break;
@@ -745,9 +772,10 @@ void QSGRhiShaderEffectNode::preprocess()
}
}
-void QSGRhiShaderEffectNode::cleanupMaterialTypeCache()
+void QSGRhiShaderEffectNode::cleanupMaterialTypeCache(void *materialTypeCacheKey)
{
- shaderMaterialTypeCache.reset();
+ QMutexLocker lock(&shaderMaterialTypeCacheMutex);
+ shaderMaterialTypeCache[materialTypeCacheKey].reset();
}
bool QSGRhiGuiThreadShaderEffectManager::hasSeparateSamplerAndTextureObjects() const
@@ -818,7 +846,7 @@ bool QSGRhiGuiThreadShaderEffectManager::reflect(ShaderInfo *result)
int ubufBinding = -1;
const QVector<QShaderDescription::UniformBlock> ubufs = desc.uniformBlocks();
- const int ubufCount = ubufs.count();
+ const int ubufCount = ubufs.size();
for (int i = 0; i < ubufCount; ++i) {
const QShaderDescription::UniformBlock &ubuf(ubufs[i]);
if (ubufBinding == -1 && ubuf.binding >= 0) {
@@ -839,7 +867,7 @@ bool QSGRhiGuiThreadShaderEffectManager::reflect(ShaderInfo *result)
}
const QVector<QShaderDescription::InOutVariable> combinedImageSamplers = desc.combinedImageSamplers();
- const int samplerCount = combinedImageSamplers.count();
+ const int samplerCount = combinedImageSamplers.size();
for (int i = 0; i < samplerCount; ++i) {
const QShaderDescription::InOutVariable &combinedImageSampler(combinedImageSamplers[i]);
ShaderInfo::Variable v;
diff --git a/src/quick/scenegraph/qsgrhishadereffectnode_p.h b/src/quick/scenegraph/qsgrhishadereffectnode_p.h
index a901a6651e..b606871af6 100644
--- a/src/quick/scenegraph/qsgrhishadereffectnode_p.h
+++ b/src/quick/scenegraph/qsgrhishadereffectnode_p.h
@@ -99,7 +99,7 @@ public:
void syncMaterial(SyncData *syncData) override;
void preprocess() override;
- static void cleanupMaterialTypeCache();
+ static void cleanupMaterialTypeCache(void *materialTypeCacheKey);
private Q_SLOTS:
void handleTextureChange();
diff --git a/src/quick/scenegraph/qsgrhisupport.cpp b/src/quick/scenegraph/qsgrhisupport.cpp
index ede98e865a..d37786901c 100644
--- a/src/quick/scenegraph/qsgrhisupport.cpp
+++ b/src/quick/scenegraph/qsgrhisupport.cpp
@@ -883,7 +883,7 @@ int QSGRhiSupport::chooseSampleCount(int samples, QRhi *rhi)
const QVector<int> supportedSampleCounts = rhi->supportedSampleCounts();
if (!supportedSampleCounts.contains(msaaSampleCount)) {
int reducedSampleCount = 1;
- for (int i = supportedSampleCounts.count() - 1; i >= 0; --i) {
+ for (int i = supportedSampleCounts.size() - 1; i >= 0; --i) {
if (supportedSampleCounts[i] <= msaaSampleCount) {
reducedSampleCount = supportedSampleCounts[i];
break;
diff --git a/src/quick/scenegraph/qsgrhitextureglyphcache.cpp b/src/quick/scenegraph/qsgrhitextureglyphcache.cpp
index a2d7de9a0a..9fe1b2ad01 100644
--- a/src/quick/scenegraph/qsgrhitextureglyphcache.cpp
+++ b/src/quick/scenegraph/qsgrhitextureglyphcache.cpp
@@ -23,15 +23,7 @@ QSGRhiTextureGlyphCache::QSGRhiTextureGlyphCache(QSGDefaultRenderContext *rc,
QSGRhiTextureGlyphCache::~QSGRhiTextureGlyphCache()
{
- // A plain delete should work, but just in case commitResourceUpdates was
- // not called and something is enqueued on the update batch for m_texture,
- // defer until the end of the frame.
- if (m_texture)
- m_texture->deleteLater();
-
- // should be empty, but just in case
- for (QRhiTexture *t : qAsConst(m_pendingDispose))
- t->deleteLater();
+ m_rc->deferredReleaseGlyphCacheTexture(m_texture);
}
QRhiTexture *QSGRhiTextureGlyphCache::createEmptyTexture(QRhiTexture::Format format)
@@ -97,7 +89,7 @@ void QSGRhiTextureGlyphCache::resizeTextureData(int width, int height)
resourceUpdates->uploadTexture(t, QRhiTextureUploadEntry(0, 0, subresDesc));
}
- m_pendingDispose.insert(m_texture);
+ m_rc->deferredReleaseGlyphCacheTexture(m_texture);
m_texture = t;
}
}
@@ -197,7 +189,10 @@ void QSGRhiTextureGlyphCache::endFillTexture()
int QSGRhiTextureGlyphCache::glyphPadding() const
{
- return 1;
+ if (m_format == QFontEngine::Format_Mono)
+ return 8;
+ else
+ return 1;
}
int QSGRhiTextureGlyphCache::maxTextureWidth() const
@@ -217,14 +212,8 @@ void QSGRhiTextureGlyphCache::commitResourceUpdates(QRhiResourceUpdateBatch *mer
{
if (QRhiResourceUpdateBatch *resourceUpdates = m_rc->maybeGlyphCacheResourceUpdates()) {
mergeInto->merge(resourceUpdates);
- m_rc->releaseGlyphCacheResourceUpdates();
+ m_rc->resetGlyphCacheResources();
}
-
- // now let's assume the resource updates will be committed in this frame
- for (QRhiTexture *t : qAsConst(m_pendingDispose))
- t->deleteLater(); // will be deleted after the frame is submitted -> safe
-
- m_pendingDispose.clear();
}
bool QSGRhiTextureGlyphCache::eightBitFormatIsAlphaSwizzled() const
diff --git a/src/quick/scenegraph/qsgrhitextureglyphcache_p.h b/src/quick/scenegraph/qsgrhitextureglyphcache_p.h
index 2960c91b01..3c6b99bc9f 100644
--- a/src/quick/scenegraph/qsgrhitextureglyphcache_p.h
+++ b/src/quick/scenegraph/qsgrhitextureglyphcache_p.h
@@ -60,7 +60,6 @@ private:
QSize m_size;
bool m_bgra = false;
QVarLengthArray<QRhiTextureUploadEntry, 16> m_uploads;
- QSet<QRhiTexture *> m_pendingDispose;
};
QT_END_NAMESPACE
diff --git a/src/quick/scenegraph/qsgthreadedrenderloop.cpp b/src/quick/scenegraph/qsgthreadedrenderloop.cpp
index e20ded6c5a..c9b7ca2084 100644
--- a/src/quick/scenegraph/qsgthreadedrenderloop.cpp
+++ b/src/quick/scenegraph/qsgthreadedrenderloop.cpp
@@ -476,7 +476,7 @@ void QSGRenderThread::invalidateGraphics(QQuickWindow *window, bool inDestructor
if (wipeSG) {
dd->cleanupNodesOnShutdown();
#if QT_CONFIG(quick_shadereffect)
- QSGRhiShaderEffectNode::cleanupMaterialTypeCache();
+ QSGRhiShaderEffectNode::cleanupMaterialTypeCache(window);
#endif
} else {
qCDebug(QSG_LOG_RENDERLOOP, QSG_RT_PAD, "- persistent SG, avoiding cleanup");
@@ -505,6 +505,7 @@ void QSGRenderThread::invalidateGraphics(QQuickWindow *window, bool inDestructor
if (ownRhi)
QSGRhiSupport::instance()->destroyRhi(rhi);
rhi = nullptr;
+ dd->rhi = nullptr;
qCDebug(QSG_LOG_RENDERLOOP, QSG_RT_PAD, "- QRhi destroyed");
} else {
qCDebug(QSG_LOG_RENDERLOOP, QSG_RT_PAD, "- persistent GL, avoiding cleanup");
diff --git a/src/quick/util/qquickanimation.cpp b/src/quick/util/qquickanimation.cpp
index b2bf0c6d19..2301e0780b 100644
--- a/src/quick/util/qquickanimation.cpp
+++ b/src/quick/util/qquickanimation.cpp
@@ -965,7 +965,7 @@ void QQuickScriptActionPrivate::debugAction(QDebug d, int indentLevel) const
QString exprStr = expr.expression();
int endOfFirstLine = exprStr.indexOf(u'\n');
d << "\n" << ind.constData() << QStringView{exprStr}.left(endOfFirstLine);
- if (endOfFirstLine != -1 && endOfFirstLine < exprStr.length())
+ if (endOfFirstLine != -1 && endOfFirstLine < exprStr.size())
d << "...";
}
}
@@ -998,7 +998,7 @@ QAbstractAnimationJob* QQuickScriptAction::transition(QQuickStateActions &action
d->hasRunScriptScript = false;
d->reversing = (direction == Backward);
if (!d->name.isEmpty()) {
- for (int ii = 0; ii < actions.count(); ++ii) {
+ for (int ii = 0; ii < actions.size(); ++ii) {
QQuickStateAction &action = actions[ii];
if (action.event && action.event->type() == QQuickStateActionEvent::Script
@@ -1178,14 +1178,14 @@ QAbstractAnimationJob* QQuickPropertyAction::transition(QQuickStateActions &acti
QQuickStateActions actions;
void doAction() override
{
- for (int ii = 0; ii < actions.count(); ++ii) {
+ for (int ii = 0; ii < actions.size(); ++ii) {
const QQuickStateAction &action = actions.at(ii);
QQmlPropertyPrivate::write(action.property, action.toValue, QQmlPropertyData::BypassInterceptor | QQmlPropertyData::DontRemoveBinding);
}
}
void debugAction(QDebug d, int indentLevel) const override {
QByteArray ind(indentLevel, ' ');
- for (int ii = 0; ii < actions.count(); ++ii) {
+ for (int ii = 0; ii < actions.size(); ++ii) {
const QQuickStateAction &action = actions.at(ii);
d << "\n" << ind.constData() << "target:" << action.property.object() << "property:" << action.property.name()
<< "value:" << action.toValue;
@@ -1194,7 +1194,7 @@ QAbstractAnimationJob* QQuickPropertyAction::transition(QQuickStateActions &acti
};
QStringList props = d->properties.isEmpty() ? QStringList() : d->properties.split(QLatin1Char(','));
- for (int ii = 0; ii < props.count(); ++ii)
+ for (int ii = 0; ii < props.size(); ++ii)
props[ii] = props.at(ii).trimmed();
if (!d->propertyName.isEmpty())
props << d->propertyName;
@@ -1218,8 +1218,8 @@ QAbstractAnimationJob* QQuickPropertyAction::transition(QQuickStateActions &acti
bool hasExplicit = false;
//an explicit animation has been specified
if (d->value.isValid()) {
- for (int i = 0; i < props.count(); ++i) {
- for (int j = 0; j < targets.count(); ++j) {
+ for (int i = 0; i < props.size(); ++i) {
+ for (int j = 0; j < targets.size(); ++j) {
QQuickStateAction myAction;
myAction.property = d->createProperty(targets.at(j), props.at(i), this);
if (myAction.property.isValid()) {
@@ -1227,7 +1227,7 @@ QAbstractAnimationJob* QQuickPropertyAction::transition(QQuickStateActions &acti
QQuickPropertyAnimationPrivate::convertVariant(myAction.toValue, myAction.property.propertyMetaType());
data->actions << myAction;
hasExplicit = true;
- for (int ii = 0; ii < actions.count(); ++ii) {
+ for (int ii = 0; ii < actions.size(); ++ii) {
QQuickStateAction &action = actions[ii];
if (action.property.object() == myAction.property.object() &&
myAction.property.name() == action.property.name()) {
@@ -1241,7 +1241,7 @@ QAbstractAnimationJob* QQuickPropertyAction::transition(QQuickStateActions &acti
}
if (!hasExplicit)
- for (int ii = 0; ii < actions.count(); ++ii) {
+ for (int ii = 0; ii < actions.size(); ++ii) {
QQuickStateAction &action = actions[ii];
QObject *obj = action.property.object();
@@ -1266,7 +1266,7 @@ QAbstractAnimationJob* QQuickPropertyAction::transition(QQuickStateActions &acti
}
QActionAnimation *action = new QActionAnimation;
- if (data->actions.count()) {
+ if (data->actions.size()) {
action->setAnimAction(data);
} else {
delete data;
@@ -1688,7 +1688,7 @@ QQuickAbstractAnimation *QQuickAnimationGroupPrivate::at_animation(QQmlListPrope
qsizetype QQuickAnimationGroupPrivate::count_animation(QQmlListProperty<QQuickAbstractAnimation> *list)
{
if (auto q = qmlobject_cast<QQuickAnimationGroup *>(list->object))
- return q->d_func()->animations.count();
+ return q->d_func()->animations.size();
return 0;
}
@@ -1696,7 +1696,7 @@ void QQuickAnimationGroupPrivate::clear_animation(QQmlListProperty<QQuickAbstrac
{
QQuickAnimationGroup *q = qobject_cast<QQuickAnimationGroup *>(list->object);
if (q) {
- while (q->d_func()->animations.count()) {
+ while (q->d_func()->animations.size()) {
QQuickAbstractAnimation *firstAnim = q->d_func()->animations.at(0);
firstAnim->setGroup(nullptr);
}
@@ -1723,7 +1723,7 @@ void QQuickAnimationGroupPrivate::removeLast_animation(QQmlListProperty<QQuickAb
QQuickAnimationGroup::~QQuickAnimationGroup()
{
Q_D(QQuickAnimationGroup);
- for (int i = 0; i < d->animations.count(); ++i)
+ for (int i = 0; i < d->animations.size(); ++i)
d->animations.at(i)->d_func()->group = nullptr;
d->animations.clear();
}
@@ -1812,14 +1812,14 @@ QAbstractAnimationJob* QQuickSequentialAnimation::transition(QQuickStateActions
int from = 0;
if (direction == Backward) {
inc = -1;
- from = d->animations.count() - 1;
+ from = d->animations.size() - 1;
}
ThreadingModel execution = threadingModel();
bool valid = d->defaultProperty.isValid();
QAbstractAnimationJob* anim;
- for (int ii = from; ii < d->animations.count() && ii >= 0; ii += inc) {
+ for (int ii = from; ii < d->animations.size() && ii >= 0; ii += inc) {
if (valid)
d->animations.at(ii)->setDefaultTarget(d->defaultProperty);
anim = d->animations.at(ii)->transition(actions, modified, direction, defaultTarget);
@@ -1902,7 +1902,7 @@ QAbstractAnimationJob* QQuickParallelAnimation::transition(QQuickStateActions &a
bool valid = d->defaultProperty.isValid();
QAbstractAnimationJob* anim;
- for (int ii = 0; ii < d->animations.count(); ++ii) {
+ for (int ii = 0; ii < d->animations.size(); ++ii) {
if (valid)
d->animations.at(ii)->setDefaultTarget(d->defaultProperty);
anim = d->animations.at(ii)->transition(actions, modified, direction, defaultTarget);
@@ -2084,7 +2084,7 @@ void QQuickBulkValueAnimator::debugAnimation(QDebug d) const
Note that PropertyAnimation inherits the abstract \l Animation type.
This includes additional properties and methods for controlling the animation.
- \section1 Modifying Properties Duration Animations
+ \section1 Modifying running animations
Since Qt 6.4, it is possible to set the \l from, \l to, \l duration, and
\l easing properties on a top-level animation while it is running. The
@@ -2594,7 +2594,7 @@ void QQuickAnimationPropertyUpdater::setValue(qreal v)
wasDeleted = &deleted;
if (reverse)
v = 1 - v;
- for (int ii = 0; ii < actions.count(); ++ii) {
+ for (int ii = 0; ii < actions.size(); ++ii) {
QQuickStateAction &action = actions[ii];
if (v == 1.) {
@@ -2626,7 +2626,7 @@ void QQuickAnimationPropertyUpdater::setValue(qreal v)
void QQuickAnimationPropertyUpdater::debugUpdater(QDebug d, int indentLevel) const
{
QByteArray ind(indentLevel, ' ');
- for (int i = 0; i < actions.count(); ++i) {
+ for (int i = 0; i < actions.size(); ++i) {
const QQuickStateAction &action = actions.at(i);
d << "\n" << ind.constData() << "target:" << action.property.object() << "property:" << action.property.name()
<< "from:" << action.fromValue << "to:" << action.toValue;
@@ -2641,7 +2641,7 @@ QQuickStateActions QQuickPropertyAnimation::createTransitionActions(QQuickStateA
QQuickStateActions newActions;
QStringList props = d->properties.isEmpty() ? QStringList() : d->properties.split(QLatin1Char(','));
- for (int ii = 0; ii < props.count(); ++ii)
+ for (int ii = 0; ii < props.size(); ++ii)
props[ii] = props.at(ii).trimmed();
if (!d->propertyName.isEmpty())
props << d->propertyName;
@@ -2673,8 +2673,8 @@ QQuickStateActions QQuickPropertyAnimation::createTransitionActions(QQuickStateA
QVector<QString> errorMessages;
bool successfullyCreatedDefaultProperty = false;
- for (int i = 0; i < props.count(); ++i) {
- for (int j = 0; j < targets.count(); ++j) {
+ for (int i = 0; i < props.size(); ++i) {
+ for (int j = 0; j < targets.size(); ++j) {
QQuickStateAction myAction;
QString errorMessage;
const QString &propertyName = props.at(i);
@@ -2691,7 +2691,7 @@ QQuickStateActions QQuickPropertyAnimation::createTransitionActions(QQuickStateA
d->convertVariant(myAction.toValue, d->interpolatorType ? QMetaType(d->interpolatorType) : myAction.property.propertyMetaType());
newActions << myAction;
hasExplicit = true;
- for (int ii = 0; ii < actions.count(); ++ii) {
+ for (int ii = 0; ii < actions.size(); ++ii) {
QQuickStateAction &action = actions[ii];
if (action.property.object() == myAction.property.object() &&
myAction.property.name() == action.property.name()) {
@@ -2706,13 +2706,13 @@ QQuickStateActions QQuickPropertyAnimation::createTransitionActions(QQuickStateA
}
if (!successfullyCreatedDefaultProperty) {
- for (const QString &errorMessage : qAsConst(errorMessages))
+ for (const QString &errorMessage : std::as_const(errorMessages))
qmlWarning(this) << errorMessage;
}
}
if (!hasExplicit)
- for (int ii = 0; ii < actions.count(); ++ii) {
+ for (int ii = 0; ii < actions.size(); ++ii) {
QQuickStateAction &action = actions[ii];
QObject *obj = action.property.object();
diff --git a/src/quick/util/qquickanimatorcontroller.cpp b/src/quick/util/qquickanimatorcontroller.cpp
index ab3ea93a71..d7c25dadc1 100644
--- a/src/quick/util/qquickanimatorcontroller.cpp
+++ b/src/quick/util/qquickanimatorcontroller.cpp
@@ -36,7 +36,7 @@ static void qquickanimator_invalidate_jobs(QAbstractAnimationJob *job)
void QQuickAnimatorController::windowNodesDestroyed()
{
- for (const QSharedPointer<QAbstractAnimationJob> &toStop : qAsConst(m_rootsPendingStop)) {
+ for (const QSharedPointer<QAbstractAnimationJob> &toStop : std::as_const(m_rootsPendingStop)) {
qquickanimator_invalidate_jobs(toStop.data());
toStop->stop();
}
@@ -59,14 +59,14 @@ void QQuickAnimatorController::windowNodesDestroyed()
void QQuickAnimatorController::advance()
{
bool running = false;
- for (const QSharedPointer<QAbstractAnimationJob> &job : qAsConst(m_animationRoots)) {
+ for (const QSharedPointer<QAbstractAnimationJob> &job : std::as_const(m_animationRoots)) {
if (job->isRunning()) {
running = true;
break;
}
}
- for (QQuickAnimatorJob *job : qAsConst(m_runningAnimators))
+ for (QQuickAnimatorJob *job : std::as_const(m_runningAnimators))
job->commit();
if (running)
@@ -85,18 +85,18 @@ static void qquickanimator_sync_before_start(QAbstractAnimationJob *job)
void QQuickAnimatorController::beforeNodeSync()
{
- for (const QSharedPointer<QAbstractAnimationJob> &toStop : qAsConst(m_rootsPendingStop)) {
+ for (const QSharedPointer<QAbstractAnimationJob> &toStop : std::as_const(m_rootsPendingStop)) {
toStop->stop();
m_animationRoots.remove(toStop.data());
}
m_rootsPendingStop.clear();
- for (QQuickAnimatorJob *job : qAsConst(m_runningAnimators))
+ for (QQuickAnimatorJob *job : std::as_const(m_runningAnimators))
job->preSync();
// Start pending jobs
- for (const QSharedPointer<QAbstractAnimationJob> &job : qAsConst(m_rootsPendingStart)) {
+ for (const QSharedPointer<QAbstractAnimationJob> &job : std::as_const(m_rootsPendingStart)) {
Q_ASSERT(!job->isRunning());
// We want to make sure that presync is called before
@@ -118,7 +118,7 @@ void QQuickAnimatorController::beforeNodeSync()
void QQuickAnimatorController::afterNodeSync()
{
- for (QQuickAnimatorJob *job : qAsConst(m_runningAnimators))
+ for (QQuickAnimatorJob *job : std::as_const(m_runningAnimators))
job->postSync();
}
diff --git a/src/quick/util/qquickanimatorjob.cpp b/src/quick/util/qquickanimatorjob.cpp
index af49244b6d..599b5515cb 100644
--- a/src/quick/util/qquickanimatorjob.cpp
+++ b/src/quick/util/qquickanimatorjob.cpp
@@ -358,11 +358,12 @@ void QQuickTransformAnimatorJob::Helper::sync()
wasSynced = true;
}
+ // We update the node before checking on dirty, as the node might have changed without the animator running
+ node = d->itemNode();
+
if (dirty == 0)
return;
- node = d->itemNode();
-
if (dirty & QQuickItemPrivate::Position) {
dx = item->x();
dy = item->y();
diff --git a/src/quick/util/qquickapplication.cpp b/src/quick/util/qquickapplication.cpp
index ee3e15d15f..bee3b7313f 100644
--- a/src/quick/util/qquickapplication.cpp
+++ b/src/quick/util/qquickapplication.cpp
@@ -277,7 +277,7 @@ void QQuickApplication::setDisplayName(const QString &displayName)
qsizetype screens_count(QQmlListProperty<QQuickScreenInfo> *prop)
{
- return static_cast<QVector<QQuickScreenInfo *> *>(prop->data)->count();
+ return static_cast<QVector<QQuickScreenInfo *> *>(prop->data)->size();
}
QQuickScreenInfo *screens_at(QQmlListProperty<QQuickScreenInfo> *prop, qsizetype idx)
@@ -294,8 +294,8 @@ QQmlListProperty<QQuickScreenInfo> QQuickApplication::screens()
void QQuickApplication::updateScreens()
{
const QList<QScreen *> screenList = QGuiApplication::screens();
- m_screens.resize(screenList.count());
- for (int i = 0; i < screenList.count(); ++i) {
+ m_screens.resize(screenList.size());
+ for (int i = 0; i < screenList.size(); ++i) {
if (!m_screens[i])
m_screens[i] = new QQuickScreenInfo(this);
m_screens[i]->setWrappedScreen(screenList[i]);
diff --git a/src/quick/util/qquickdeliveryagent.cpp b/src/quick/util/qquickdeliveryagent.cpp
index 2bb0d52b09..78a95aa33c 100644
--- a/src/quick/util/qquickdeliveryagent.cpp
+++ b/src/quick/util/qquickdeliveryagent.cpp
@@ -48,6 +48,7 @@ void QQuickDeliveryAgentPrivate::touchToMouseEvent(QEvent::Type type, const QEve
(type == QEvent::MouseButtonRelease ? Qt::NoButton : Qt::LeftButton),
touchEvent->modifiers(), Qt::MouseEventSynthesizedByQt);
ret.setAccepted(true); // this now causes the persistent touchpoint to be accepted too
+ ret.setTimestamp(touchEvent->timestamp());
*mouseEvent = ret;
}
@@ -119,7 +120,7 @@ bool QQuickDeliveryAgentPrivate::deliverTouchAsMouse(QQuickItem *item, QTouchEve
// FIXME: make this work for mouse events too and get rid of the asTouchEvent in here.
QMutableTouchEvent event;
QQuickItemPrivate::get(item)->localizedTouchEvent(pointerEvent, false, &event);
- if (!event.points().count())
+ if (!event.points().size())
return false;
// For each point, check if it is accepted, if not, try the next point.
@@ -424,7 +425,7 @@ void QQuickDeliveryAgentPrivate::setFocusInScope(QQuickItem *scope, QQuickItem *
emit rootItem->window()->focusObjectChanged(activeFocusItem);
if (!changed.isEmpty())
- notifyFocusChangesRecur(changed.data(), changed.count() - 1, reason);
+ notifyFocusChangesRecur(changed.data(), changed.size() - 1, reason);
if (isSubsceneAgent) {
auto da = QQuickWindowPrivate::get(rootItem->window())->deliveryAgent;
qCDebug(lcFocus) << " delegating setFocusInScope to" << da;
@@ -524,8 +525,12 @@ void QQuickDeliveryAgentPrivate::clearFocusInScope(QQuickItem *scope, QQuickItem
emit rootItem->window()->focusObjectChanged(activeFocusItem);
if (!changed.isEmpty())
- notifyFocusChangesRecur(changed.data(), changed.count() - 1, reason);
-
+ notifyFocusChangesRecur(changed.data(), changed.size() - 1, reason);
+ if (isSubsceneAgent) {
+ auto da = QQuickWindowPrivate::get(rootItem->window())->deliveryAgent;
+ qCDebug(lcFocus) << " delegating clearFocusInScope to" << da;
+ QQuickWindowPrivate::get(rootItem->window())->deliveryAgentPrivate()->clearFocusInScope(da->rootItem(), item, reason, options);
+ }
if (oldActiveFocusItem == activeFocusItem)
qCDebug(lcFocus) << "activeFocusItem remains" << activeFocusItem << "in" << q;
else
@@ -717,10 +722,13 @@ bool QQuickDeliveryAgent::event(QEvent *ev)
if (!d->rootItem)
return false;
QEnterEvent *enter = static_cast<QEnterEvent*>(ev);
- bool accepted = d->deliverHoverEvent(enter->scenePosition(),
+ const auto scenePos = enter->scenePosition();
+ bool accepted = d->deliverHoverEvent(scenePos,
enter->points().first().sceneLastPosition(),
enter->modifiers(), enter->timestamp());
- d->lastMousePosition = enter->scenePosition();
+ d->lastMousePosition = scenePos;
+ // deliverHoverEvent() constructs QHoverEvents: check that EPD didn't end up with corrupted scenePos
+ Q_ASSERT(enter->scenePosition() == scenePos);
enter->setAccepted(accepted);
#if QT_CONFIG(cursor)
QQuickWindowPrivate::get(d->rootItem->window())->updateCursor(enter->scenePosition(), d->rootItem);
@@ -751,8 +759,7 @@ bool QQuickDeliveryAgent::event(QEvent *ev)
break;
#endif
case QEvent::ShortcutOverride:
- if (d->activeFocusItem)
- QCoreApplication::sendEvent(d->activeFocusItem, ev);
+ d->deliverKeyEvent(static_cast<QKeyEvent *>(ev));
break;
case QEvent::InputMethod:
case QEvent::InputMethodQuery:
@@ -792,7 +799,13 @@ bool QQuickDeliveryAgent::event(QEvent *ev)
case QEvent::TabletPress:
case QEvent::TabletMove:
case QEvent::TabletRelease:
- d->deliverPointerEvent(static_cast<QPointerEvent *>(ev));
+ {
+ auto *tabletEvent = static_cast<QTabletEvent *>(ev);
+ d->deliverPointerEvent(tabletEvent); // visits HoverHandlers too (unlike the mouse event case)
+#if QT_CONFIG(cursor)
+ QQuickWindowPrivate::get(d->rootItem->window())->updateCursor(tabletEvent->scenePosition(), d->rootItem);
+#endif
+ }
break;
#endif
default:
@@ -806,10 +819,16 @@ void QQuickDeliveryAgentPrivate::deliverKeyEvent(QKeyEvent *e)
{
if (activeFocusItem) {
const bool keyPress = (e->type() == QEvent::KeyPress);
- if (keyPress)
+ switch (e->type()) {
+ case QEvent::KeyPress:
Q_QUICK_INPUT_PROFILE(QQuickProfiler::Key, QQuickProfiler::InputKeyPress, e->key(), e->modifiers());
- else
+ break;
+ case QEvent::KeyRelease:
Q_QUICK_INPUT_PROFILE(QQuickProfiler::Key, QQuickProfiler::InputKeyRelease, e->key(), e->modifiers());
+ break;
+ default:
+ break;
+ }
QQuickItem *item = activeFocusItem;
@@ -819,12 +838,10 @@ void QQuickDeliveryAgentPrivate::deliverKeyEvent(QKeyEvent *e)
e->key(), e->modifiers(), e->text(),
e->isAutoRepeat(), e->count());
- e->accept();
- QCoreApplication::sendEvent(item, e);
- while (!e->isAccepted() && (item = item->parentItem())) {
+ do {
e->accept();
QCoreApplication::sendEvent(item, e);
- }
+ } while (!e->isAccepted() && (item = item->parentItem()));
}
}
@@ -926,11 +943,11 @@ bool QQuickDeliveryAgentPrivate::sendHoverEvent(QEvent::Type type, QQuickItem *i
const auto transform = itemPrivate->windowToItemTransform();
const auto transformToGlobal = itemPrivate->windowToGlobalTransform();
auto globalPos = transformToGlobal.map(scenePos);
- QHoverEvent hoverEvent(type, transform.map(scenePos), globalPos, transform.map(lastScenePos), modifiers);
+ QHoverEvent hoverEvent(type, scenePos, globalPos, transform.map(lastScenePos), modifiers);
hoverEvent.setTimestamp(timestamp);
hoverEvent.setAccepted(true);
QEventPoint &point = hoverEvent.point(0);
- QMutableEventPoint::setScenePosition(point, scenePos);
+ QMutableEventPoint::setPosition(point, transform.map(scenePos));
QMutableEventPoint::setGlobalLastPosition(point, transformToGlobal.map(lastScenePos));
hasFiltered.clear();
@@ -952,9 +969,6 @@ bool QQuickDeliveryAgentPrivate::deliverHoverEvent(
const QPointF &scenePos, const QPointF &lastScenePos,
Qt::KeyboardModifiers modifiers, ulong timestamp)
{
- if (!QQuickItemPrivate::get(rootItem)->subtreeHoverEnabled)
- return false;
-
// The first time this function is called, hoverItems is empty.
// We then call deliverHoverEventRecursive from the rootItem, and
// populate the list with all the children and grandchildren that
@@ -970,11 +984,19 @@ bool QQuickDeliveryAgentPrivate::deliverHoverEvent(
// visit will still have an old hoverId. We can therefore go through the
// list at the end of this function and look for items with an old hoverId,
// remove them from the list, and update their state accordingly.
- currentHoverId++;
- hoveredLeafItemFound = false;
+ const bool subtreeHoverEnabled = QQuickItemPrivate::get(rootItem)->subtreeHoverEnabled;
const bool itemsWasHovered = !hoverItems.isEmpty();
- deliverHoverEventRecursive(rootItem, scenePos, lastScenePos, modifiers, timestamp);
+
+ if (!subtreeHoverEnabled && !itemsWasHovered)
+ return false;
+
+ currentHoverId++;
+
+ if (subtreeHoverEnabled) {
+ hoveredLeafItemFound = false;
+ deliverHoverEventRecursive(rootItem, scenePos, lastScenePos, modifiers, timestamp);
+ }
// Prune the list for items that are no longer hovered
for (auto it = hoverItems.begin(); it != hoverItems.end();) {
@@ -1005,10 +1027,11 @@ bool QQuickDeliveryAgentPrivate::deliverHoverEvent(
accepted, recursion stops. Returns \c true in that case, or \c false if the
event is rejected.
- All items that have hover enabled (either explicitly, from
- setAcceptHoverEvents(), or implicitly by having HoverHandlers) will have
- the QQuickItemPrivate::hoverEnabled flag set. And all their anchestors will
- have the QQuickItemPrivate::subtreeHoverEnabledset. This function will
+ Each item that has hover enabled (from setAcceptHoverEvents()) has the
+ QQuickItemPrivate::hoverEnabled flag set. This only controls whether we
+ should send hover events to the item itself. (HoverHandlers no longer set
+ this flag.) When an item has hoverEnabled set, all its ancestors have the
+ QQuickItemPrivate::subtreeHoverEnabled set. This function will
follow the subtrees that have subtreeHoverEnabled by recursing into each
child with that flag set. And for each child (in addition to the item
itself) that also has hoverEnabled set, we call deliverHoverEventToItem()
@@ -1020,10 +1043,19 @@ bool QQuickDeliveryAgentPrivate::deliverHoverEvent(
of an item that is stacked underneath, will not. Note that since siblings
can overlap, there can be more than one leaf item under the mouse.
+ Note that HoverHandler doesn't set the hoverEnabled flag on the parent item.
+ But still, adding a HoverHandler to an item will set its subtreeHoverEnabled flag.
+ So all the propagation logic described above will otherwise be the same.
+ But the hoverEnabled flag can be used to resolve if subtreeHoverEnabled is on
+ because the application explicitly requested it (setAcceptHoverEvents()), or
+ indirectly, because the item has HoverHandlers.
+
For legacy reasons (Qt 6.1), as soon as we find a leaf item that has hover
enabled, and therefore receives the event, we stop recursing into the remaining
siblings (even if the event was ignored). This means that we only allow hover
events to propagate up the direct parent-child hierarchy, and not to siblings.
+ However, if the first candidate HoverHandler is disabled, delivery continues
+ to the next one, which may be a sibling (QTBUG-106548).
*/
bool QQuickDeliveryAgentPrivate::deliverHoverEventRecursive(
QQuickItem *item, const QPointF &scenePos, const QPointF &lastScenePos,
@@ -1033,13 +1065,13 @@ bool QQuickDeliveryAgentPrivate::deliverHoverEventRecursive(
const QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
const QList<QQuickItem *> children = itemPrivate->paintOrderChildItems();
- for (int ii = children.count() - 1; ii >= 0; --ii) {
+ for (int ii = children.size() - 1; ii >= 0; --ii) {
QQuickItem *child = children.at(ii);
const QQuickItemPrivate *childPrivate = QQuickItemPrivate::get(child);
if (!child->isVisible() || childPrivate->culled)
continue;
- if (!child->isEnabled() && !childPrivate->subtreeHoverEnabled)
+ if (!childPrivate->subtreeHoverEnabled)
continue;
if (childPrivate->flags & QQuickItem::ItemClipsChildrenToShape) {
const QPointF localPos = child->mapFromScene(scenePos);
@@ -1061,8 +1093,7 @@ bool QQuickDeliveryAgentPrivate::deliverHoverEventRecursive(
// All decendants have been visited.
// Now deliver the event to the item
- if (itemPrivate->hoverEnabled)
- return deliverHoverEventToItem(item, scenePos, lastScenePos, modifiers, timestamp, false);
+ return deliverHoverEventToItem(item, scenePos, lastScenePos, modifiers, timestamp, false);
// Continue propagation / recursion
return false;
@@ -1089,14 +1120,17 @@ bool QQuickDeliveryAgentPrivate::deliverHoverEventToItem(
qCDebug(lcHoverTrace) << "item:" << item << "scene pos:" << scenePos << "localPos:" << localPos
<< "wasHovering:" << wasHovering << "isHovering:" << isHovering;
- if (isHovering)
- hoveredLeafItemFound = true;
-
- // Send enter/move/leave event to the item
bool accepted = false;
- if (isHovering && !clearHover) {
+
+ // Start by sending out enter/move/leave events to the item.
+ // Note that hoverEnabled only controls if we should send out hover events to the
+ // item itself. HoverHandlers are not included, and are dealt with separately below.
+ if (itemPrivate->hoverEnabled && isHovering && !clearHover) {
// Add the item to the list of hovered items (if it doesn't exist there
// from before), and update hoverId to mark that it's (still) hovered.
+ // Also set hoveredLeafItemFound, so that only propagate in a straight
+ // line towards the root from now on.
+ hoveredLeafItemFound = true;
hoverItems[item] = currentHoverId;
if (wasHovering)
accepted = sendHoverEvent(QEvent::HoverMove, item, scenePos, lastScenePos, modifiers, timestamp);
@@ -1111,6 +1145,7 @@ bool QQuickDeliveryAgentPrivate::deliverHoverEventToItem(
if (!itemPrivate->hasPointerHandlers())
return accepted;
+ // Next, send out hover events to the hover handlers.
// If the item didn't accept the hover event, 'accepted' is now false.
// Otherwise it's true, and then it should stay the way regardless of
// whether or not the hoverhandlers themselves are hovered.
@@ -1124,6 +1159,8 @@ bool QQuickDeliveryAgentPrivate::deliverHoverEventToItem(
for (QQuickPointerHandler *h : itemPrivate->extra->pointerHandlers) {
if (QQuickHoverHandler *hh = qmlobject_cast<QQuickHoverHandler *>(h)) {
+ if (!hh->isHovered())
+ continue;
hoverEvent.setAccepted(true);
QCoreApplication::sendEvent(hh, &hoverEvent);
}
@@ -1134,11 +1171,14 @@ bool QQuickDeliveryAgentPrivate::deliverHoverEventToItem(
for (QQuickPointerHandler *h : itemPrivate->extra->pointerHandlers) {
if (QQuickHoverHandler *hh = qmlobject_cast<QQuickHoverHandler *>(h)) {
+ if (!hh->enabled())
+ continue;
hoverEvent.setAccepted(true);
hh->handlePointerEvent(&hoverEvent);
if (hh->isHovered()) {
// Mark the whole item as updated, even if only the handler is
// actually in a hovered state (because of HoverHandler.margins)
+ hoveredLeafItemFound = true;
hoverItems[item] = currentHoverId;
if (hh->isBlocking()) {
qCDebug(lcHoverTrace) << "skipping rest of hover delivery due to blocking" << hh;
@@ -1157,7 +1197,7 @@ bool QQuickDeliveryAgentPrivate::deliverHoverEventToItem(
// in the usual reverse-paint-order until propagation is stopped
bool QQuickDeliveryAgentPrivate::deliverSinglePointEventUntilAccepted(QPointerEvent *event)
{
- Q_ASSERT(event->points().count() == 1);
+ Q_ASSERT(event->points().size() == 1);
QQuickPointerHandlerPrivate::deviceDeliveryTargets(event->pointingDevice()).clear();
QEventPoint &point = event->point(0);
QVector<QQuickItem *> targetItems = pointerTargets(rootItem, event, point, false, false);
@@ -1331,6 +1371,11 @@ bool QQuickDeliveryAgentPrivate::isMouseEvent(const QPointerEvent *ev)
}
}
+bool QQuickDeliveryAgentPrivate::isMouseOrWheelEvent(const QPointerEvent *ev)
+{
+ return isMouseEvent(ev) || ev->type() == QEvent::Wheel;
+}
+
bool QQuickDeliveryAgentPrivate::isHoverEvent(const QPointerEvent *ev)
{
switch (ev->type()) {
@@ -1377,6 +1422,11 @@ bool QQuickDeliveryAgentPrivate::isEventFromMouseOrTouchpad(const QPointerEvent
devType == QInputDevice::DeviceType::TouchPad;
}
+bool QQuickDeliveryAgentPrivate::isSynthMouse(const QPointerEvent *ev)
+{
+ return (!isEventFromMouseOrTouchpad(ev) && isMouseEvent(ev));
+}
+
QQuickPointingDeviceExtra *QQuickDeliveryAgentPrivate::deviceExtra(const QInputDevice *device)
{
QInputDevicePrivate *devPriv = QInputDevicePrivate::get(const_cast<QInputDevice *>(device));
@@ -1417,6 +1467,11 @@ QQuickPointingDeviceExtra *QQuickDeliveryAgentPrivate::deviceExtra(const QInputD
*/
bool QQuickDeliveryAgentPrivate::compressTouchEvent(QTouchEvent *event)
{
+ // If this is a subscene agent, don't store any events, because
+ // flushFrameSynchronousEvents() is only called on the window's DA.
+ if (isSubsceneAgent)
+ return false;
+
QEventPoint::States states = event->touchPointStates();
if (states.testFlag(QEventPoint::State::Pressed) || states.testFlag(QEventPoint::State::Released)) {
qCDebug(lcTouchCmprs) << "no compression" << event;
@@ -1554,17 +1609,18 @@ void QQuickDeliveryAgentPrivate::handleMouseEvent(QMouseEvent *event)
Q_QUICK_INPUT_PROFILE(QQuickProfiler::Mouse, QQuickProfiler::InputMouseMove,
event->position().x(), event->position().y());
-#if QT_CONFIG(cursor)
- QQuickWindowPrivate::get(rootItem->window())->updateCursor(event->scenePosition());
-#endif
const QPointF last = lastMousePosition.isNull() ? event->scenePosition() : lastMousePosition;
lastMousePosition = event->scenePosition();
qCDebug(lcHoverTrace) << q << "mouse pos" << last << "->" << lastMousePosition;
- if (!event->points().count() || !event->exclusiveGrabber(event->point(0))) {
+ if (!event->points().size() || !event->exclusiveGrabber(event->point(0))) {
bool accepted = deliverHoverEvent(event->scenePosition(), last, event->modifiers(), event->timestamp());
event->setAccepted(accepted);
}
deliverPointerEvent(event);
+#if QT_CONFIG(cursor)
+ // The pointer event could result in a cursor change (reaction), so update it afterwards.
+ QQuickWindowPrivate::get(rootItem->window())->updateCursor(event->scenePosition());
+#endif
break;
}
default:
@@ -1641,64 +1697,59 @@ void QQuickDeliveryAgentPrivate::onGrabChanged(QObject *grabber, QPointingDevice
handler->onGrabChanged(handler, transition, const_cast<QPointerEvent *>(event),
const_cast<QEventPoint &>(point));
}
- } else {
+ } else if (auto *grabberItem = qmlobject_cast<QQuickItem *>(grabber)) {
switch (transition) {
case QPointingDevice::CancelGrabExclusive:
case QPointingDevice::UngrabExclusive:
- if (auto *item = qmlobject_cast<QQuickItem *>(grabber)) {
- bool filtered = false;
- if (isDeliveringTouchAsMouse() ||
- point.device()->type() == QInputDevice::DeviceType::Mouse ||
- point.device()->type() == QInputDevice::DeviceType::TouchPad) {
- QMutableSinglePointEvent e(QEvent::UngrabMouse, point.device(), point);
- hasFiltered.clear();
- filtered = sendFilteredMouseEvent(&e, item, item->parentItem());
- if (!filtered) {
- lastUngrabbed = item;
- item->mouseUngrabEvent();
- }
+ if (isDeliveringTouchAsMouse()
+ || point.device()->type() == QInputDevice::DeviceType::Mouse
+ || point.device()->type() == QInputDevice::DeviceType::TouchPad) {
+ QMutableSinglePointEvent e(QEvent::UngrabMouse, point.device(), point);
+ hasFiltered.clear();
+ if (!sendFilteredMouseEvent(&e, grabberItem, grabberItem->parentItem())) {
+ lastUngrabbed = grabberItem;
+ grabberItem->mouseUngrabEvent();
}
- if (point.device()->type() == QInputDevice::DeviceType::TouchScreen) {
- bool allReleasedOrCancelled = true;
- if (transition == QPointingDevice::UngrabExclusive && event) {
- for (const auto &pt : event->points()) {
- if (pt.state() != QEventPoint::State::Released) {
- allReleasedOrCancelled = false;
- break;
- }
+ }
+ if (point.device()->type() == QInputDevice::DeviceType::TouchScreen) {
+ bool allReleasedOrCancelled = true;
+ if (transition == QPointingDevice::UngrabExclusive && event) {
+ for (const auto &pt : event->points()) {
+ if (pt.state() != QEventPoint::State::Released) {
+ allReleasedOrCancelled = false;
+ break;
}
}
- if (allReleasedOrCancelled)
- item->touchUngrabEvent();
}
+ if (allReleasedOrCancelled)
+ grabberItem->touchUngrabEvent();
}
break;
default:
break;
}
- auto grabberItem = static_cast<QQuickItem *>(grabber); // cannot be a handler: we checked above
- if (grabberItem) {
- auto itemPriv = QQuickItemPrivate::get(grabberItem);
- deliveryAgent = itemPriv->deliveryAgent();
- // An item that is NOT a subscene root needs to track whether it got a grab via a subscene delivery agent,
- // whereas the subscene root item already knows it has its own DA.
- if (isSubsceneAgent && grabGained && (!itemPriv->extra.isAllocated() || !itemPriv->extra->subsceneDeliveryAgent))
- itemPriv->maybeHasSubsceneDeliveryAgent = true;
- }
+ auto *itemPriv = QQuickItemPrivate::get(grabberItem);
+ deliveryAgent = itemPriv->deliveryAgent();
+ // An item that is NOT a subscene root needs to track whether it got a grab via a subscene delivery agent,
+ // whereas the subscene root item already knows it has its own DA.
+ if (isSubsceneAgent && grabGained && (!itemPriv->extra.isAllocated() || !itemPriv->extra->subsceneDeliveryAgent))
+ itemPriv->maybeHasSubsceneDeliveryAgent = true;
}
if (currentEventDeliveryAgent == q && event && event->device()) {
- auto epd = QPointingDevicePrivate::get(const_cast<QPointingDevice*>(event->pointingDevice()))->queryPointById(point.id());
- Q_ASSERT(epd);
switch (transition) {
case QPointingDevice::GrabPassive: {
+ auto epd = QPointingDevicePrivate::get(const_cast<QPointingDevice*>(event->pointingDevice()))->queryPointById(point.id());
+ Q_ASSERT(epd);
QPointingDevicePrivate::setPassiveGrabberContext(epd, grabber, q);
qCDebug(lcPtr) << "remembering that" << q << "handles point" << point.id() << "after" << transition;
} break;
- case QPointingDevice::GrabExclusive:
+ case QPointingDevice::GrabExclusive: {
+ auto epd = QPointingDevicePrivate::get(const_cast<QPointingDevice*>(event->pointingDevice()))->queryPointById(point.id());
+ Q_ASSERT(epd);
epd->exclusiveGrabberContext = q;
qCDebug(lcPtr) << "remembering that" << q << "handles point" << point.id() << "after" << transition;
- break;
+ } break;
case QPointingDevice::CancelGrabExclusive:
case QPointingDevice::UngrabExclusive:
// taken care of in QPointingDevicePrivate::setExclusiveGrabber(,,nullptr), removeExclusiveGrabber()
@@ -1831,7 +1882,7 @@ QVector<QQuickItem *> QQuickDeliveryAgentPrivate::pointerTargets(QQuickItem *ite
children.insert(it, item);
}
- for (int ii = children.count() - 1; ii >= 0; --ii) {
+ for (int ii = children.size() - 1; ii >= 0; --ii) {
QQuickItem *child = children.at(ii);
auto childPrivate = QQuickItemPrivate::get(child);
if (!child->isVisible() || !child->isEnabled() || childPrivate->culled ||
@@ -1855,8 +1906,8 @@ QVector<QQuickItem *> QQuickDeliveryAgentPrivate::mergePointerTargets(const QVec
// start at the end of list2
// if item not in list, append it
// if item found, move to next one, inserting before the last found one
- int insertPosition = targets.length();
- for (int i = list2.length() - 1; i >= 0; --i) {
+ int insertPosition = targets.size();
+ for (int i = list2.size() - 1; i >= 0; --i) {
int newInsertPosition = targets.lastIndexOf(list2.at(i), insertPosition);
if (newInsertPosition >= 0) {
Q_ASSERT(newInsertPosition <= insertPosition);
@@ -1912,7 +1963,7 @@ void QQuickDeliveryAgentPrivate::deliverUpdatedPoints(QPointerEvent *event)
continue;
}
QList<QPointer<QObject>> relevantPassiveGrabbers;
- for (int i = 0; i < epd->passiveGrabbersContext.count(); ++i) {
+ for (int i = 0; i < epd->passiveGrabbersContext.size(); ++i) {
if (epd->passiveGrabbersContext.at(i).data() == q)
relevantPassiveGrabbers << epd->passiveGrabbers.at(i);
}
@@ -1932,7 +1983,7 @@ void QQuickDeliveryAgentPrivate::deliverUpdatedPoints(QPointerEvent *event)
if (point.state() == QEventPoint::Pressed || qmlobject_cast<QQuickItem *>(event->exclusiveGrabber(point)))
continue;
QVector<QQuickItem *> targetItemsForPoint = pointerTargets(rootItem, event, point, false, false);
- if (targetItems.count()) {
+ if (targetItems.size()) {
targetItems = mergePointerTargets(targetItems, targetItemsForPoint);
} else {
targetItems = targetItemsForPoint;
@@ -1975,7 +2026,7 @@ bool QQuickDeliveryAgentPrivate::deliverPressOrReleaseEvent(QPointerEvent *event
for (int i = 0; i < event->pointCount(); ++i) {
auto &point = event->point(i);
QVector<QQuickItem *> targetItemsForPoint = pointerTargets(rootItem, event, point, !isTouch, isTouch);
- if (targetItems.count()) {
+ if (targetItems.size()) {
targetItems = mergePointerTargets(targetItems, targetItemsForPoint);
} else {
targetItems = targetItemsForPoint;
@@ -2069,7 +2120,7 @@ void QQuickDeliveryAgentPrivate::deliverMatchingPointsToItem(QQuickItem *item, b
item->mouseUngrabEvent();
lastUngrabbed = item;
}
- } else if (item->isEnabled() && item->isVisible() && point.state() != QEventPoint::State::Released) {
+ } else if (item->isEnabled() && item->isVisible() && point.state() == QEventPoint::State::Pressed) {
pointerEvent->setExclusiveGrabber(point, item);
}
point.setAccepted(true);
@@ -2099,18 +2150,16 @@ void QQuickDeliveryAgentPrivate::deliverMatchingPointsToItem(QQuickItem *item, b
qCDebug(lcTouch) << "actually delivering" << &touchEvent << " to " << item;
QCoreApplication::sendEvent(item, &touchEvent);
eventAccepted = touchEvent.isAccepted();
- } else if (Q_LIKELY(QCoreApplication::testAttribute(Qt::AA_SynthesizeMouseForUnhandledTouchEvents))) {
+ } else {
// If the touch event wasn't accepted, synthesize a mouse event and see if the item wants it.
- if (!eventAccepted && (itemPrivate->acceptedMouseButtons() & Qt::LeftButton)) {
- // send mouse event
- if (deliverTouchAsMouse(item, &touchEvent))
- eventAccepted = true;
- }
+ if (Q_LIKELY(QCoreApplication::testAttribute(Qt::AA_SynthesizeMouseForUnhandledTouchEvents)) &&
+ !eventAccepted && (itemPrivate->acceptedMouseButtons() & Qt::LeftButton))
+ deliverTouchAsMouse(item, &touchEvent);
+ return;
}
+ Q_ASSERT(item->acceptTouchEvents()); // else we would've returned early above
if (eventAccepted) {
- // If the touch was accepted (regardless by whom or in what form),
- // update accepted new points.
bool isPressOrRelease = pointerEvent->isBeginEvent() || pointerEvent->isEndEvent();
for (int i = 0; i < touchEvent.pointCount(); ++i) {
auto &point = touchEvent.point(i);
@@ -2163,6 +2212,7 @@ void QQuickDeliveryAgentPrivate::deliverDragEvent(QQuickDragGrabber *grabber, QE
QDragLeaveEvent leaveEvent;
for (; grabItem != grabber->end(); grabItem = grabber->release(grabItem))
QCoreApplication::sendEvent(**grabItem, &leaveEvent);
+ grabber->ignoreList().clear();
return;
} else {
QDragMoveEvent *moveEvent = static_cast<QDragMoveEvent *>(event);
@@ -2220,6 +2270,8 @@ void QQuickDeliveryAgentPrivate::deliverDragEvent(QQuickDragGrabber *grabber, QE
e->modifiers());
QQuickDropEventEx::copyActions(&enterEvent, *e);
event->setAccepted(deliverDragEvent(grabber, rootItem, &enterEvent));
+ } else {
+ grabber->ignoreList().clear();
}
}
@@ -2233,8 +2285,13 @@ bool QQuickDeliveryAgentPrivate::deliverDragEvent(
QPointF p = item->mapFromScene(event->position().toPoint());
bool itemContained = item->contains(p);
- if (!itemContained && itemPrivate->flags & QQuickItem::ItemClipsChildrenToShape) {
- return false;
+ const int itemIndex = grabber->ignoreList().indexOf(item);
+ if (!itemContained) {
+ if (itemIndex >= 0)
+ grabber->ignoreList().remove(itemIndex);
+
+ if (itemPrivate->flags & QQuickItem::ItemClipsChildrenToShape)
+ return false;
}
QDragEnterEvent enterEvent(
@@ -2247,7 +2304,7 @@ bool QQuickDeliveryAgentPrivate::deliverDragEvent(
QList<QQuickItem *> children = itemPrivate->paintOrderChildItems();
// Check children in front of this item first
- for (int ii = children.count() - 1; ii >= 0; --ii) {
+ for (int ii = children.size() - 1; ii >= 0; --ii) {
if (children.at(ii)->z() < 0)
continue;
if (deliverDragEvent(grabber, children.at(ii), &enterEvent, currentGrabItems, formerTarget))
@@ -2264,15 +2321,19 @@ bool QQuickDeliveryAgentPrivate::deliverDragEvent(
}
if (event->type() == QEvent::DragMove || itemPrivate->flags & QQuickItem::ItemAcceptsDrops) {
- if (event->type() == QEvent::DragEnter && formerTarget) {
- QQuickItem *formerTargetItem = qobject_cast<QQuickItem *>(formerTarget);
- if (formerTargetItem && currentGrabItems) {
- QDragLeaveEvent leaveEvent;
- QCoreApplication::sendEvent(formerTarget, &leaveEvent);
-
- // Remove the item from the currentGrabItems so a leave event won't be generated
- // later on
- currentGrabItems->removeAll(formerTarget);
+ if (event->type() == QEvent::DragEnter) {
+ if (formerTarget) {
+ QQuickItem *formerTargetItem = qobject_cast<QQuickItem *>(formerTarget);
+ if (formerTargetItem && currentGrabItems) {
+ QDragLeaveEvent leaveEvent;
+ QCoreApplication::sendEvent(formerTarget, &leaveEvent);
+
+ // Remove the item from the currentGrabItems so a leave event won't be generated
+ // later on
+ currentGrabItems->removeAll(formerTarget);
+ }
+ } else if (itemIndex >= 0) {
+ return false;
}
}
@@ -2288,6 +2349,8 @@ bool QQuickDeliveryAgentPrivate::deliverDragEvent(
grabber->grab(item);
grabber->setTarget(item);
return true;
+ } else if (itemIndex < 0) {
+ grabber->ignoreList().append(item);
}
} else {
return true;
@@ -2296,7 +2359,7 @@ bool QQuickDeliveryAgentPrivate::deliverDragEvent(
}
// Check children behind this item if this item or any higher children have not accepted
- for (int ii = children.count() - 1; ii >= 0; --ii) {
+ for (int ii = children.size() - 1; ii >= 0; --ii) {
if (children.at(ii)->z() >= 0)
continue;
if (deliverDragEvent(grabber, children.at(ii), &enterEvent, currentGrabItems, formerTarget))
@@ -2363,8 +2426,11 @@ bool QQuickDeliveryAgentPrivate::sendFilteredPointerEventImpl(QPointerEvent *eve
if (filteringParent->childMouseEventFilter(receiver, &filteringParentTouchEvent)) {
qCDebug(lcTouch) << "touch event intercepted by childMouseEventFilter of " << filteringParent;
skipDelivery.append(filteringParent);
- for (auto point : filteringParentTouchEvent.points())
- event->setExclusiveGrabber(point, filteringParent);
+ for (auto point : filteringParentTouchEvent.points()) {
+ const QQuickItem *exclusiveGrabber = qobject_cast<const QQuickItem *>(event->exclusiveGrabber(point));
+ if (!exclusiveGrabber || !exclusiveGrabber->keepTouchGrab())
+ event->setExclusiveGrabber(point, filteringParent);
+ }
return true;
} else if (Q_LIKELY(QCoreApplication::testAttribute(Qt::AA_SynthesizeMouseForUnhandledTouchEvents)) &&
!filteringParent->acceptTouchEvents()) {
diff --git a/src/quick/util/qquickdeliveryagent_p_p.h b/src/quick/util/qquickdeliveryagent_p_p.h
index 66249f69c8..66db4bc88c 100644
--- a/src/quick/util/qquickdeliveryagent_p_p.h
+++ b/src/quick/util/qquickdeliveryagent_p_p.h
@@ -139,10 +139,12 @@ public:
static bool anyPointGrabbed(const QPointerEvent *ev);
static bool allPointsGrabbed(const QPointerEvent *ev);
static bool isMouseEvent(const QPointerEvent *ev);
+ static bool isMouseOrWheelEvent(const QPointerEvent *ev);
static bool isHoverEvent(const QPointerEvent *ev);
static bool isTouchEvent(const QPointerEvent *ev);
static bool isTabletEvent(const QPointerEvent *ev);
static bool isEventFromMouseOrTouchpad(const QPointerEvent *ev);
+ static bool isSynthMouse(const QPointerEvent *ev);
static QQuickPointingDeviceExtra *deviceExtra(const QInputDevice *device);
// delivery of pointer events:
diff --git a/src/quick/util/qquickframeanimation.cpp b/src/quick/util/qquickframeanimation.cpp
index 61e7e43875..bbdd0e79e0 100644
--- a/src/quick/util/qquickframeanimation.cpp
+++ b/src/quick/util/qquickframeanimation.cpp
@@ -263,10 +263,11 @@ int QQuickFrameAnimation::currentFrame() const
\code
Rectangle {
id: rect
- property real speed: 360
+ property real speed: 90
width: 100
height: 100
color: "red"
+ anchors.centerIn: parent
}
FrameAnimation {
@@ -274,7 +275,7 @@ int QQuickFrameAnimation::currentFrame() const
running: true
onTriggered: {
// Rotate the item speed-degrees / second.
- rect.rotation = rect.speed * frameTime
+ rect.rotation += rect.speed * frameTime
}
}
\endcode
diff --git a/src/quick/util/qquickglobal.cpp b/src/quick/util/qquickglobal.cpp
index 1e9a419cfb..5b6ed25692 100644
--- a/src/quick/util/qquickglobal.cpp
+++ b/src/quick/util/qquickglobal.cpp
@@ -72,7 +72,7 @@ void QQmlQtQuick2DebugStatesDelegate::buildStatesList(bool cleanList,
m_allStates.clear();
//only root context has all instances
- for (int ii = 0; ii < instances.count(); ++ii) {
+ for (int ii = 0; ii < instances.size(); ++ii) {
buildStatesList(instances.at(ii));
}
}
@@ -84,7 +84,7 @@ void QQmlQtQuick2DebugStatesDelegate::buildStatesList(QObject *obj)
}
QObjectList children = obj->children();
- for (int ii = 0; ii < children.count(); ++ii) {
+ for (int ii = 0; ii < children.size(); ++ii) {
buildStatesList(children.at(ii));
}
}
@@ -99,7 +99,7 @@ void QQmlQtQuick2DebugStatesDelegate::updateBinding(QQmlContext *context,
typedef QPointer<QQuickState> QuickStatePointer;
QObject *object = property.object();
QString propertyName = property.name();
- for (const QuickStatePointer& statePointer : qAsConst(m_allStates)) {
+ for (const QuickStatePointer& statePointer : std::as_const(m_allStates)) {
if (QQuickState *state = statePointer.data()) {
// here we assume that the revert list on itself defines the base state
if (state->isStateActive() && state->containsPropertyInRevertList(object, propertyName)) {
diff --git a/src/quick/util/qquickimageprovider.cpp b/src/quick/util/qquickimageprovider.cpp
index ee2414432d..e3b96ddad4 100644
--- a/src/quick/util/qquickimageprovider.cpp
+++ b/src/quick/util/qquickimageprovider.cpp
@@ -433,7 +433,7 @@ QQuickTextureFactory *QQuickImageProvider::requestTexture(const QString &id, QSi
\class QQuickAsyncImageProvider
\since 5.6
\inmodule QtQuick
- \brief The QQuickAsyncImageProvider class provides an interface for for asynchronous control of QML image requests.
+ \brief The QQuickAsyncImageProvider class provides an interface for asynchronous control of QML image requests.
See the \l {imageresponseprovider}{Image Response Provider Example} for a complete implementation.
diff --git a/src/quick/util/qquickpath.cpp b/src/quick/util/qquickpath.cpp
index b8aaf4e7ae..a38de75753 100644
--- a/src/quick/util/qquickpath.cpp
+++ b/src/quick/util/qquickpath.cpp
@@ -271,7 +271,7 @@ qsizetype QQuickPath::pathElements_count(QQmlListProperty<QQuickPathElement> *pr
{
QQuickPathPrivate *d = privatePath(property->object);
- return d->_pathElements.count();
+ return d->_pathElements.size();
}
void QQuickPath::pathElements_clear(QQmlListProperty<QQuickPathElement> *property)
@@ -327,10 +327,10 @@ void QQuickPath::endpoint(const QString &name)
Q_D(QQuickPath);
const AttributePoint &first = d->_attributePoints.first();
qreal val = first.values.value(name);
- for (int ii = d->_attributePoints.count() - 1; ii >= 0; ii--) {
+ for (int ii = d->_attributePoints.size() - 1; ii >= 0; ii--) {
const AttributePoint &point = d->_attributePoints.at(ii);
if (point.values.contains(name)) {
- for (int jj = ii + 1; jj < d->_attributePoints.count(); ++jj) {
+ for (int jj = ii + 1; jj < d->_attributePoints.size(); ++jj) {
AttributePoint &setPoint = d->_attributePoints[jj];
setPoint.values.insert(name, val);
}
@@ -343,10 +343,10 @@ void QQuickPath::endpoint(QList<AttributePoint> &attributePoints, const QString
{
const AttributePoint &first = attributePoints.first();
qreal val = first.values.value(name);
- for (int ii = attributePoints.count() - 1; ii >= 0; ii--) {
+ for (int ii = attributePoints.size() - 1; ii >= 0; ii--) {
const AttributePoint &point = attributePoints.at(ii);
if (point.values.contains(name)) {
- for (int jj = ii + 1; jj < attributePoints.count(); ++jj) {
+ for (int jj = ii + 1; jj < attributePoints.size(); ++jj) {
AttributePoint &setPoint = attributePoints[jj];
setPoint.values.insert(name, val);
}
@@ -401,7 +401,7 @@ QPainterPath QQuickPath::createPath(const QPointF &startPoint, const QPointF &en
QPainterPath path;
AttributePoint first;
- for (int ii = 0; ii < attributes.count(); ++ii)
+ for (int ii = 0; ii < attributes.size(); ++ii)
first.values[attributes.at(ii)] = 0;
attributePoints << first;
@@ -413,7 +413,7 @@ QPainterPath QQuickPath::createPath(const QPointF &startPoint, const QPointF &en
bool usesPercent = false;
int index = 0;
- for (QQuickPathElement *pathElement : qAsConst(d->_pathElements)) {
+ for (QQuickPathElement *pathElement : std::as_const(d->_pathElements)) {
if (QQuickCurve *curve = qobject_cast<QQuickCurve *>(pathElement)) {
QQuickPathData data;
data.index = index;
@@ -427,11 +427,11 @@ QPainterPath QQuickPath::createPath(const QPointF &startPoint, const QPointF &en
} else if (QQuickPathAttribute *attribute = qobject_cast<QQuickPathAttribute *>(pathElement)) {
AttributePoint &point = attributePoints.last();
point.values[attribute->name()] = attribute->value();
- interpolate(attributePoints, attributePoints.count() - 1, attribute->name(), attribute->value());
+ interpolate(attributePoints, attributePoints.size() - 1, attribute->name(), attribute->value());
} else if (QQuickPathPercent *percent = qobject_cast<QQuickPathPercent *>(pathElement)) {
AttributePoint &point = attributePoints.last();
point.values[percentString] = percent->value();
- interpolate(attributePoints, attributePoints.count() - 1, percentString, percent->value());
+ interpolate(attributePoints, attributePoints.size() - 1, percentString, percent->value());
usesPercent = true;
} else if (QQuickPathText *text = qobject_cast<QQuickPathText *>(pathElement)) {
text->addToPath(path);
@@ -440,13 +440,13 @@ QPainterPath QQuickPath::createPath(const QPointF &startPoint, const QPointF &en
// Fixup end points
const AttributePoint &last = attributePoints.constLast();
- for (int ii = 0; ii < attributes.count(); ++ii) {
+ for (int ii = 0; ii < attributes.size(); ++ii) {
if (!last.values.contains(attributes.at(ii)))
endpoint(attributePoints, attributes.at(ii));
}
if (usesPercent && !last.values.contains(percentString)) {
d->_attributePoints.last().values[percentString] = 1;
- interpolate(d->_attributePoints.count() - 1, percentString, 1);
+ interpolate(d->_attributePoints.size() - 1, percentString, 1);
}
scalePath(path, d->scale);
@@ -454,7 +454,7 @@ QPainterPath QQuickPath::createPath(const QPointF &startPoint, const QPointF &en
qreal length = path.length();
qreal prevpercent = 0;
qreal prevorigpercent = 0;
- for (int ii = 0; ii < attributePoints.count(); ++ii) {
+ for (int ii = 0; ii < attributePoints.size(); ++ii) {
const AttributePoint &point = attributePoints.at(ii);
if (point.values.contains(percentString)) { //special string for QQuickPathPercent
if ( ii > 0) {
@@ -495,7 +495,7 @@ QPainterPath QQuickPath::createShapePath(const QPointF &startPoint, const QPoint
path.moveTo(startX, startY);
int index = 0;
- for (QQuickCurve *curve : qAsConst(d->_pathCurves)) {
+ for (QQuickCurve *curve : std::as_const(d->_pathCurves)) {
QQuickPathData data;
data.index = index;
data.endPoint = endPoint;
@@ -504,7 +504,7 @@ QPainterPath QQuickPath::createShapePath(const QPointF &startPoint, const QPoint
++index;
}
- for (QQuickPathText *text : qAsConst(d->_pathTexts))
+ for (QQuickPathText *text : std::as_const(d->_pathTexts))
text->addToPath(path);
if (closed) {
@@ -550,7 +550,7 @@ void QQuickPath::gatherAttributes()
QSet<QString> attributes;
// First gather up all the attributes
- for (QQuickPathElement *pathElement : qAsConst(d->_pathElements)) {
+ for (QQuickPathElement *pathElement : std::as_const(d->_pathElements)) {
if (QQuickCurve *curve = qobject_cast<QQuickCurve *>(pathElement))
d->_pathCurves.append(curve);
else if (QQuickPathText *text = qobject_cast<QQuickPathText *>(pathElement))
@@ -676,10 +676,10 @@ void QQuickPath::createPointCache() const
//find which set we are in
qreal prevPercent = 0;
qreal prevOrigPercent = 0;
- for (int ii = 0; ii < d->_attributePoints.count(); ++ii) {
+ for (int ii = 0; ii < d->_attributePoints.size(); ++ii) {
qreal percent = qreal(i)/segments;
const AttributePoint &point = d->_attributePoints.at(ii);
- if (percent < point.percent || ii == d->_attributePoints.count() - 1) { //### || is special case for very last item
+ if (percent < point.percent || ii == d->_attributePoints.size() - 1) { //### || is special case for very last item
qreal elementPercent = (percent - prevPercent);
qreal spc = prevOrigPercent + elementPercent * point.scale;
@@ -773,10 +773,10 @@ QPointF QQuickPath::forwardsPointAt(const QPainterPath &path, const qreal &pathL
//find which set we are in
qreal prevPercent = 0;
qreal prevOrigPercent = 0;
- for (int ii = 0; ii < attributePoints.count(); ++ii) {
+ for (int ii = 0; ii < attributePoints.size(); ++ii) {
qreal percent = p;
const AttributePoint &point = attributePoints.at(ii);
- if (percent < point.percent || ii == attributePoints.count() - 1) {
+ if (percent < point.percent || ii == attributePoints.size() - 1) {
qreal elementPercent = (percent - prevPercent);
qreal spc = prevOrigPercent + elementPercent * point.scale;
@@ -827,7 +827,7 @@ QPointF QQuickPath::backwardsPointAt(const QPainterPath &path, const qreal &path
qreal prevLength = currLength - bezLength;
qreal epc = prevLength / pathLength;
- for (int ii = attributePoints.count() - 1; ii > 0; --ii) {
+ for (int ii = attributePoints.size() - 1; ii > 0; --ii) {
qreal percent = p;
const AttributePoint &point = attributePoints.at(ii);
const AttributePoint &prevPoint = attributePoints.at(ii-1);
@@ -928,7 +928,7 @@ qreal QQuickPath::attributeAt(const QString &name, qreal percent) const
if (percent < 0 || percent > 1)
return 0;
- for (int ii = 0; ii < d->_attributePoints.count(); ++ii) {
+ for (int ii = 0; ii < d->_attributePoints.size(); ++ii) {
const AttributePoint &point = d->_attributePoints.at(ii);
if (point.percent == percent) {
@@ -1711,17 +1711,17 @@ void QQuickPathCatmullRomCurve::addToPath(QPainterPath &path, const QQuickPathDa
} else {
prev = path.currentPosition();
bool prevFarSet = false;
- if (index == -1 && data.curves.count() > 1) {
- if (qobject_cast<QQuickPathCatmullRomCurve*>(data.curves.at(data.curves.count()-1))) {
+ if (index == -1 && data.curves.size() > 1) {
+ if (qobject_cast<QQuickPathCatmullRomCurve*>(data.curves.at(data.curves.size()-1))) {
//TODO: profile and optimize
QPointF pos = prev;
QQuickPathData loopData;
loopData.endPoint = data.endPoint;
loopData.curves = data.curves;
- for (int i = data.index; i < data.curves.count(); ++i) {
+ for (int i = data.index; i < data.curves.size(); ++i) {
loopData.index = i;
pos = positionForCurve(loopData, pos);
- if (i == data.curves.count()-2)
+ if (i == data.curves.size()-2)
prevFar = pos;
}
if (pos == QPointF(path.elementAt(0))) {
@@ -1740,7 +1740,7 @@ void QQuickPathCatmullRomCurve::addToPath(QPainterPath &path, const QQuickPathDa
//get next point
index = data.index + 1;
- if (index < data.curves.count() && qobject_cast<QQuickPathCatmullRomCurve*>(data.curves.at(index))) {
+ if (index < data.curves.size() && qobject_cast<QQuickPathCatmullRomCurve*>(data.curves.at(index))) {
QQuickPathData nextData;
nextData.index = index;
nextData.endPoint = data.endPoint;
diff --git a/src/quick/util/qquickpixmapcache.cpp b/src/quick/util/qquickpixmapcache.cpp
index 51be6f8e51..7644ab4447 100644
--- a/src/quick/util/qquickpixmapcache.cpp
+++ b/src/quick/util/qquickpixmapcache.cpp
@@ -466,7 +466,7 @@ static QString existingImageFileForPath(const QString &localFile)
return localFile;
QString tryFile = localFile + QStringLiteral(".xxxx");
- const int suffixIdx = localFile.length() + 1;
+ const int suffixIdx = localFile.size() + 1;
for (const QString &suffix : backendSupport()->fileSuffixes) {
tryFile.replace(suffixIdx, 10, suffix);
if (QFileInfo::exists(tryFile))
@@ -499,7 +499,7 @@ QQuickPixmapReader::~QQuickPixmapReader()
mutex.lock();
// manually cancel all outstanding jobs.
- for (QQuickPixmapReply *reply : qAsConst(jobs)) {
+ for (QQuickPixmapReply *reply : std::as_const(jobs)) {
if (reply->data && reply->data->reply == reply)
reply->data->reply = nullptr;
delete reply;
@@ -514,10 +514,10 @@ QQuickPixmapReader::~QQuickPixmapReader()
}
};
- for (auto *reply : qAsConst(networkJobs))
+ for (auto *reply : std::as_const(networkJobs))
cancelJob(reply);
- for (auto *reply : qAsConst(asyncResponses))
+ for (auto *reply : std::as_const(asyncResponses))
cancelJob(reply);
#endif
if (threadObject) threadObject->processJobs();
@@ -660,7 +660,7 @@ void QQuickPixmapReader::processJobs()
// Clean cancelled jobs
if (!cancelled.isEmpty()) {
- for (int i = 0; i < cancelled.count(); ++i) {
+ for (int i = 0; i < cancelled.size(); ++i) {
QQuickPixmapReply *job = cancelled.at(i);
#if QT_CONFIG(qml_network)
QNetworkReply *reply = networkJobs.key(job, 0);
@@ -688,7 +688,7 @@ void QQuickPixmapReader::processJobs()
if (!jobs.isEmpty()) {
// Find a job we can use
bool usableJob = false;
- for (int i = jobs.count() - 1; !usableJob && i >= 0; i--) {
+ for (int i = jobs.size() - 1; !usableJob && i >= 0; i--) {
QQuickPixmapReply *job = jobs.at(i);
const QUrl url = job->url;
QString localFile;
@@ -706,7 +706,7 @@ void QQuickPixmapReader::processJobs()
localFile = QQmlFile::urlToLocalFileOrQrc(url);
usableJob = !localFile.isEmpty()
#if QT_CONFIG(qml_network)
- || networkJobs.count() < IMAGEREQUEST_MAX_NETWORK_REQUEST_COUNT
+ || networkJobs.size() < IMAGEREQUEST_MAX_NETWORK_REQUEST_COUNT
#endif
;
}
@@ -1301,7 +1301,7 @@ void QQuickPixmapData::addToCache()
pixmapStore()->m_cache.insert(key, this);
inCache = true;
PIXMAP_PROFILE(pixmapCountChanged<QQuickProfiler::PixmapCacheCountChanged>(
- url, pixmapStore()->m_cache.count()));
+ url, pixmapStore()->m_cache.size()));
}
}
@@ -1315,7 +1315,7 @@ void QQuickPixmapData::removeFromCache(QQuickPixmapStore *store)
store->m_cache.remove(key);
inCache = false;
PIXMAP_PROFILE(pixmapCountChanged<QQuickProfiler::PixmapCacheCountChanged>(
- url, store->m_cache.count()));
+ url, store->m_cache.size()));
}
}
@@ -1747,8 +1747,7 @@ void QQuickPixmap::loadImageFromDevice(QQmlEngine *engine, QIODevice *device, co
QQuickPixmapReader::readerMutex.lock();
d->reply = QQuickPixmapReader::instance(engine)->getImage(d);
if (oldD) {
- QObject::connect(d->reply, &QQuickPixmapReply::finished, [oldD, this]() {
- oldD->declarativePixmaps.remove(this);
+ QObject::connect(d->reply, &QQuickPixmapReply::finished, [oldD]() {
oldD->release();
});
}
diff --git a/src/quick/util/qquickpropertychanges.cpp b/src/quick/util/qquickpropertychanges.cpp
index efa6b1dfa0..fcb6e71e17 100644
--- a/src/quick/util/qquickpropertychanges.cpp
+++ b/src/quick/util/qquickpropertychanges.cpp
@@ -238,7 +238,7 @@ void QQuickPropertyChangesPrivate::decode()
if (decoded)
return;
- for (const QV4::CompiledData::Binding *binding : qAsConst(bindings))
+ for (const QV4::CompiledData::Binding *binding : std::as_const(bindings))
decodeBinding(QString(), compilationUnit, binding);
bindings.clear();
@@ -333,7 +333,7 @@ void QQuickPropertyChangesPrivate::decodeBinding(const QString &propertyPrefix,
void QQuickPropertyChangesParser::verifyBindings(const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit, const QList<const QV4::CompiledData::Binding *> &props)
{
- for (int ii = 0; ii < props.count(); ++ii)
+ for (int ii = 0; ii < props.size(); ++ii)
verifyList(compilationUnit, props.at(ii));
}
@@ -358,7 +358,7 @@ QQuickPropertyChanges::QQuickPropertyChanges()
QQuickPropertyChanges::~QQuickPropertyChanges()
{
Q_D(QQuickPropertyChanges);
- for(int ii = 0; ii < d->signalReplacements.count(); ++ii)
+ for(int ii = 0; ii < d->signalReplacements.size(); ++ii)
delete d->signalReplacements.at(ii);
}
@@ -427,7 +427,7 @@ QQuickPropertyChanges::ActionList QQuickPropertyChanges::actions()
ActionList list;
- for (int ii = 0; ii < d->properties.count(); ++ii) {
+ for (int ii = 0; ii < d->properties.size(); ++ii) {
QQmlProperty prop = d->property(d->properties.at(ii).first);
QQuickStateAction a(d->object, prop, d->properties.at(ii).first,
@@ -439,7 +439,7 @@ QQuickPropertyChanges::ActionList QQuickPropertyChanges::actions()
}
}
- for (int ii = 0; ii < d->signalReplacements.count(); ++ii) {
+ for (int ii = 0; ii < d->signalReplacements.size(); ++ii) {
QQuickReplaceSignalHandler *handler = d->signalReplacements.at(ii);
if (handler->property.isValid()) {
@@ -449,7 +449,7 @@ QQuickPropertyChanges::ActionList QQuickPropertyChanges::actions()
}
}
- for (int ii = 0; ii < d->expressions.count(); ++ii) {
+ for (int ii = 0; ii < d->expressions.size(); ++ii) {
QQuickPropertyChangesPrivate::ExpressionChange e = d->expressions.at(ii);
const QString &property = e.name;
diff --git a/src/quick/util/qquickshortcut.cpp b/src/quick/util/qquickshortcut.cpp
index 7b93936cfe..51de063090 100644
--- a/src/quick/util/qquickshortcut.cpp
+++ b/src/quick/util/qquickshortcut.cpp
@@ -209,7 +209,7 @@ void QQuickShortcut::setSequences(const QVariantList &values)
// if nothing has changed, just return:
if (m_shortcuts.size() == requestedShortcuts.size()) {
bool changed = false;
- for (int i = 0; i < requestedShortcuts.count(); ++i) {
+ for (int i = 0; i < requestedShortcuts.size(); ++i) {
const Shortcut &requestedShortcut = requestedShortcuts[i];
const Shortcut &shortcut = m_shortcuts[i];
if (!(requestedShortcut.userValue == shortcut.userValue
@@ -373,7 +373,7 @@ bool QQuickShortcut::event(QEvent *event)
QShortcutEvent *se = static_cast<QShortcutEvent *>(event);
bool match = m_shortcut.matches(se);
int i = 0;
- while (!match && i < m_shortcuts.count())
+ while (!match && i < m_shortcuts.size())
match |= m_shortcuts.at(i++).matches(se);
if (match) {
if (se->isAmbiguous())
diff --git a/src/quick/util/qquickshortcut_p.h b/src/quick/util/qquickshortcut_p.h
index f303043008..baa884b6f0 100644
--- a/src/quick/util/qquickshortcut_p.h
+++ b/src/quick/util/qquickshortcut_p.h
@@ -22,12 +22,13 @@
#include <QtQml/qqmlparserstatus.h>
#include <QtQml/qqml.h>
#include <QtCore/private/qglobal_p.h>
+#include <QtQuick/private/qtquickglobal_p.h>
QT_BEGIN_NAMESPACE
class QShortcutEvent;
-class QQuickShortcut : public QObject, public QQmlParserStatus
+class Q_QUICK_PRIVATE_EXPORT QQuickShortcut : public QObject, public QQmlParserStatus
{
Q_OBJECT
Q_INTERFACES(QQmlParserStatus)
diff --git a/src/quick/util/qquicksmoothedanimation.cpp b/src/quick/util/qquicksmoothedanimation.cpp
index 5e05da302d..4681d5919e 100644
--- a/src/quick/util/qquicksmoothedanimation.cpp
+++ b/src/quick/util/qquicksmoothedanimation.cpp
@@ -351,7 +351,7 @@ QQuickSmoothedAnimationPrivate::~QQuickSmoothedAnimationPrivate()
void QQuickSmoothedAnimationPrivate::updateRunningAnimations()
{
- for (QSmoothedAnimation *ease : qAsConst(activeAnimations)) {
+ for (QSmoothedAnimation *ease : std::as_const(activeAnimations)) {
ease->maximumEasingTime = anim->maximumEasingTime;
ease->reversingMode = anim->reversingMode;
ease->velocity = anim->velocity;
diff --git a/src/quick/util/qquickstate.cpp b/src/quick/util/qquickstate.cpp
index 09eaf60819..51bc9852f4 100644
--- a/src/quick/util/qquickstate.cpp
+++ b/src/quick/util/qquickstate.cpp
@@ -243,7 +243,7 @@ QQmlListProperty<QQuickStateOperation> QQuickState::changes()
int QQuickState::operationCount() const
{
Q_D(const QQuickState);
- return d->operations.count();
+ return d->operations.size();
}
QQuickStateOperation *QQuickState::operationAt(int index) const
@@ -263,8 +263,8 @@ void QQuickStatePrivate::complete()
{
Q_Q(QQuickState);
- for (int ii = 0; ii < reverting.count(); ++ii) {
- for (int jj = 0; jj < revertList.count(); ++jj) {
+ for (int ii = 0; ii < reverting.size(); ++ii) {
+ for (int jj = 0; jj < revertList.size(); ++jj) {
const QQuickRevertAction &revert = reverting.at(ii);
const QQuickSimpleAction &simple = revertList.at(jj);
if ((revert.event && simple.event() == revert.event) ||
@@ -295,7 +295,7 @@ QQuickStatePrivate::generateActionList() const
if (!extends.isEmpty()) {
QList<QQuickState *> states = group ? group->states() : QList<QQuickState *>();
- for (int ii = 0; ii < states.count(); ++ii)
+ for (int ii = 0; ii < states.size(); ++ii)
if (states.at(ii)->name() == extends) {
qmlExecuteDeferred(states.at(ii));
applyList = static_cast<QQuickStatePrivate*>(states.at(ii)->d_func())->generateActionList();
@@ -447,7 +447,7 @@ void QQuickState::addEntriesToRevertList(const QList<QQuickStateAction> &actionL
Q_D(QQuickState);
if (isStateActive()) {
QList<QQuickSimpleAction> simpleActionList;
- simpleActionList.reserve(actionList.count());
+ simpleActionList.reserve(actionList.size());
for (const QQuickStateAction &action : actionList) {
QQuickSimpleAction simpleAction(action);
@@ -520,14 +520,14 @@ void QQuickState::apply(QQuickTransition *trans, QQuickState *revert)
// List of actions that need to be reverted to roll back (just) this state
QQuickStatePrivate::SimpleActionList additionalReverts;
// First add the reverse of all the applyList actions
- for (int ii = 0; ii < applyList.count(); ++ii) {
+ for (int ii = 0; ii < applyList.size(); ++ii) {
QQuickStateAction &action = applyList[ii];
if (action.event) {
if (!action.event->isReversable())
continue;
bool found = false;
- for (int jj = 0; jj < d->revertList.count(); ++jj) {
+ for (int jj = 0; jj < d->revertList.size(); ++jj) {
QQuickStateActionEvent *event = d->revertList.at(jj).event();
if (event && event->type() == action.event->type()) {
if (action.event->mayOverride(event)) {
@@ -558,7 +558,7 @@ void QQuickState::apply(QQuickTransition *trans, QQuickState *revert)
bool found = false;
action.fromBinding = QQmlAnyBinding::ofProperty(action.property);
- for (int jj = 0; jj < d->revertList.count(); ++jj) {
+ for (int jj = 0; jj < d->revertList.size(); ++jj) {
if (d->revertList.at(jj).property() == action.property) {
found = true;
if (d->revertList.at(jj).binding() != action.fromBinding) {
@@ -583,13 +583,13 @@ void QQuickState::apply(QQuickTransition *trans, QQuickState *revert)
// Any reverts from a previous state that aren't carried forth
// into this state need to be translated into apply actions
- for (int ii = 0; ii < d->revertList.count(); ++ii) {
+ for (int ii = 0; ii < d->revertList.size(); ++ii) {
bool found = false;
if (d->revertList.at(ii).event()) {
QQuickStateActionEvent *event = d->revertList.at(ii).event();
if (!event->isReversable())
continue;
- for (int jj = 0; !found && jj < applyList.count(); ++jj) {
+ for (int jj = 0; !found && jj < applyList.size(); ++jj) {
const QQuickStateAction &action = applyList.at(jj);
if (action.event && action.event->type() == event->type()) {
if (action.event->mayOverride(event))
@@ -597,7 +597,7 @@ void QQuickState::apply(QQuickTransition *trans, QQuickState *revert)
}
}
} else {
- for (int jj = 0; !found && jj < applyList.count(); ++jj) {
+ for (int jj = 0; !found && jj < applyList.size(); ++jj) {
const QQuickStateAction &action = applyList.at(jj);
if (action.property == d->revertList.at(ii).property())
found = true;
@@ -636,7 +636,7 @@ void QQuickState::apply(QQuickTransition *trans, QQuickState *revert)
d->revertList << additionalReverts;
if (lcStates().isDebugEnabled()) {
- for (const QQuickStateAction &action : qAsConst(applyList)) {
+ for (const QQuickStateAction &action : std::as_const(applyList)) {
if (action.event)
qCDebug(lcStates) << "QQuickStateAction event:" << action.event->type();
else
diff --git a/src/quick/util/qquickstate_p_p.h b/src/quick/util/qquickstate_p_p.h
index 528682a5ba..cd7c1be5aa 100644
--- a/src/quick/util/qquickstate_p_p.h
+++ b/src/quick/util/qquickstate_p_p.h
@@ -206,7 +206,7 @@ public:
}
static qsizetype operations_count(QQmlListProperty<QQuickStateOperation> *prop) {
QList<OperationGuard> *list = static_cast<QList<OperationGuard> *>(prop->data);
- return list->count();
+ return list->size();
}
static QQuickStateOperation *operations_at(QQmlListProperty<QQuickStateOperation> *prop, qsizetype index) {
QList<OperationGuard> *list = static_cast<QList<OperationGuard> *>(prop->data);
diff --git a/src/quick/util/qquickstategroup.cpp b/src/quick/util/qquickstategroup.cpp
index 2812b5824a..b4be946dc3 100644
--- a/src/quick/util/qquickstategroup.cpp
+++ b/src/quick/util/qquickstategroup.cpp
@@ -96,7 +96,7 @@ QQuickStateGroup::QQuickStateGroup(QObject *parent)
QQuickStateGroup::~QQuickStateGroup()
{
Q_D(const QQuickStateGroup);
- for (int i = 0; i < d->states.count(); ++i)
+ for (int i = 0; i < d->states.size(); ++i)
d->states.at(i)->setStateGroup(nullptr);
if (d->nullState)
d->nullState->setStateGroup(nullptr);
@@ -153,7 +153,7 @@ void QQuickStateGroupPrivate::append_state(QQmlListProperty<QQuickState> *list,
qsizetype QQuickStateGroupPrivate::count_state(QQmlListProperty<QQuickState> *list)
{
QQuickStateGroup *_this = static_cast<QQuickStateGroup *>(list->object);
- return _this->d_func()->states.count();
+ return _this->d_func()->states.size();
}
QQuickState *QQuickStateGroupPrivate::at_state(QQmlListProperty<QQuickState> *list, qsizetype index)
@@ -166,7 +166,7 @@ void QQuickStateGroupPrivate::clear_states(QQmlListProperty<QQuickState> *list)
{
QQuickStateGroup *_this = static_cast<QQuickStateGroup *>(list->object);
_this->d_func()->setCurrentStateInternal(QString(), true);
- for (qsizetype i = 0; i < _this->d_func()->states.count(); ++i) {
+ for (qsizetype i = 0; i < _this->d_func()->states.size(); ++i) {
_this->d_func()->states.at(i)->setStateGroup(nullptr);
}
_this->d_func()->states.clear();
@@ -190,7 +190,7 @@ void QQuickStateGroupPrivate::removeLast_states(QQmlListProperty<QQuickState> *l
{
auto *d = qobject_cast<QQuickStateGroup *>(list->object)->d_func();
if (d->currentState == d->states.last()->name())
- d->setCurrentStateInternal(d->states.length() > 1 ? d->states.first()->name() : QString(), true);
+ d->setCurrentStateInternal(d->states.size() > 1 ? d->states.first()->name() : QString(), true);
d->states.last()->setStateGroup(nullptr);
d->states.removeLast();
}
@@ -234,7 +234,7 @@ void QQuickStateGroupPrivate::append_transition(QQmlListProperty<QQuickTransitio
qsizetype QQuickStateGroupPrivate::count_transitions(QQmlListProperty<QQuickTransition> *list)
{
QQuickStateGroup *_this = static_cast<QQuickStateGroup *>(list->object);
- return _this->d_func()->transitions.count();
+ return _this->d_func()->transitions.size();
}
QQuickTransition *QQuickStateGroupPrivate::at_transition(QQmlListProperty<QQuickTransition> *list, qsizetype index)
@@ -257,14 +257,14 @@ void QQuickStateGroupPrivate::clear_transitions(QQmlListProperty<QQuickTransitio
This property is often used in scripts to change between states. For
example:
- \js
+ \qml
function toggle() {
if (button.state == 'On')
button.state = 'Off';
else
button.state = 'On';
}
- \endjs
+ \endqml
If the state group is in its base state (i.e. no explicit state has been
set), \c state will be a blank string. Likewise, you can return a
@@ -299,8 +299,8 @@ void QQuickStateGroup::componentComplete()
d->componentComplete = true;
QVarLengthArray<QString, 4> names;
- names.reserve(d->states.count());
- for (int ii = 0; ii < d->states.count(); ++ii) {
+ names.reserve(d->states.size());
+ for (int ii = 0; ii < d->states.size(); ++ii) {
QQuickState *state = d->states.at(ii);
if (!state->isNamed())
state->setName(QLatin1String("anonymousState") + QString::number(++d->unnamedCount));
@@ -338,7 +338,7 @@ bool QQuickStateGroupPrivate::updateAutoState()
return false;
bool revert = false;
- for (int ii = 0; ii < states.count(); ++ii) {
+ for (int ii = 0; ii < states.size(); ++ii) {
QQuickState *state = states.at(ii);
if (state->isWhenKnown()) {
if (state->isNamed()) {
@@ -353,11 +353,10 @@ bool QQuickStateGroupPrivate::updateAutoState()
if (abstractBinding && abstractBinding->kind() == QQmlAbstractBinding::QmlBinding) {
QQmlBinding *binding = static_cast<QQmlBinding *>(abstractBinding);
if (binding->hasValidContext()) {
- QVariant evalResult = binding->evaluate();
- if (evalResult.metaType() == QMetaType::fromType<QJSValue>())
- whenValue = evalResult.value<QJSValue>().toBool();
- else
- whenValue = evalResult.toBool();
+ const auto boolType = QMetaType::fromType<bool>();
+ const bool isUndefined = !binding->evaluate(&whenValue, boolType);
+ if (isUndefined)
+ whenValue = false;
}
}
@@ -391,7 +390,7 @@ QQuickTransition *QQuickStateGroupPrivate::findTransition(const QString &from, c
bool reversed = false;
bool done = false;
- for (int ii = 0; !done && ii < transitions.count(); ++ii) {
+ for (int ii = 0; !done && ii < transitions.size(); ++ii) {
QQuickTransition *t = transitions.at(ii);
if (!t->enabled())
continue;
@@ -405,10 +404,10 @@ QQuickTransition *QQuickStateGroupPrivate::findTransition(const QString &from, c
const QString toStateStr = t->toState();
auto fromState = QStringView{fromStateStr}.split(QLatin1Char(','));
- for (int jj = 0; jj < fromState.count(); ++jj)
+ for (int jj = 0; jj < fromState.size(); ++jj)
fromState[jj] = fromState.at(jj).trimmed();
auto toState = QStringView{toStateStr}.split(QLatin1Char(','));
- for (int jj = 0; jj < toState.count(); ++jj)
+ for (int jj = 0; jj < toState.size(); ++jj)
toState[jj] = toState.at(jj).trimmed();
if (ii == 1)
qSwap(fromState, toState);
@@ -476,7 +475,7 @@ void QQuickStateGroupPrivate::setCurrentStateInternal(const QString &state,
QQuickState *oldState = nullptr;
if (!currentState.isEmpty()) {
- for (int ii = 0; ii < states.count(); ++ii) {
+ for (int ii = 0; ii < states.size(); ++ii) {
if (states.at(ii)->name() == currentState) {
oldState = states.at(ii);
break;
@@ -488,7 +487,7 @@ void QQuickStateGroupPrivate::setCurrentStateInternal(const QString &state,
emit q->stateChanged(currentState);
QQuickState *newState = nullptr;
- for (int ii = 0; ii < states.count(); ++ii) {
+ for (int ii = 0; ii < states.size(); ++ii) {
if (states.at(ii)->name() == currentState) {
newState = states.at(ii);
break;
@@ -512,7 +511,7 @@ void QQuickStateGroupPrivate::setCurrentStateInternal(const QString &state,
QQuickState *QQuickStateGroup::findState(const QString &name) const
{
Q_D(const QQuickStateGroup);
- for (int i = 0; i < d->states.count(); ++i) {
+ for (int i = 0; i < d->states.size(); ++i) {
QQuickState *state = d->states.at(i);
if (state->name() == name)
return state;
diff --git a/src/quick/util/qquickstyledtext.cpp b/src/quick/util/qquickstyledtext.cpp
index b542869913..1bee09a421 100644
--- a/src/quick/util/qquickstyledtext.cpp
+++ b/src/quick/util/qquickstyledtext.cpp
@@ -127,6 +127,13 @@ const QChar QQuickStyledTextPrivate::square(0x25a1);
const QChar QQuickStyledTextPrivate::lineFeed(QLatin1Char('\n'));
const QChar QQuickStyledTextPrivate::space(QLatin1Char(' '));
+namespace {
+bool is_equal_ignoring_case(QStringView s1, QLatin1StringView s2) noexcept
+{
+ return s1.compare(s2, Qt::CaseInsensitive) == 0;
+}
+}
+
QQuickStyledText::QQuickStyledText(const QString &string, QTextLayout &layout,
QList<QQuickStyledTextImgTag*> &imgTags,
const QUrl &baseUrl,
@@ -181,31 +188,31 @@ void QQuickStyledTextPrivate::parse()
hasSpace = true;
}
- if (rangeStart != drawText.length() && formatStack.count()) {
+ if (rangeStart != drawText.size() && formatStack.size()) {
if (formatChanged) {
QTextLayout::FormatRange formatRange;
formatRange.format = formatStack.top();
formatRange.start = rangeStart;
- formatRange.length = drawText.length() - rangeStart;
+ formatRange.length = drawText.size() - rangeStart;
ranges.append(formatRange);
formatChanged = false;
- } else if (ranges.count()) {
- ranges.last().length += drawText.length() - rangeStart;
+ } else if (ranges.size()) {
+ ranges.last().length += drawText.size() - rangeStart;
}
}
- rangeStart = drawText.length();
+ rangeStart = drawText.size();
++ch;
if (*ch == slash) {
++ch;
if (parseCloseTag(ch, text, drawText)) {
- if (formatStack.count()) {
+ if (formatStack.size()) {
formatChanged = true;
formatStack.pop();
}
}
} else {
QTextCharFormat format;
- if (formatStack.count())
+ if (formatStack.size())
format = formatStack.top();
if (parseTag(ch, text, drawText, format)) {
formatChanged = true;
@@ -245,15 +252,15 @@ void QQuickStyledTextPrivate::parse()
}
if (textLength)
appendText(text, textStart, textLength, drawText);
- if (rangeStart != drawText.length() && formatStack.count()) {
+ if (rangeStart != drawText.size() && formatStack.size()) {
if (formatChanged) {
QTextLayout::FormatRange formatRange;
formatRange.format = formatStack.top();
formatRange.start = rangeStart;
- formatRange.length = drawText.length() - rangeStart;
+ formatRange.length = drawText.size() - rangeStart;
ranges.append(formatRange);
- } else if (ranges.count()) {
- ranges.last().length += drawText.length() - rangeStart;
+ } else if (ranges.size()) {
+ ranges.last().length += drawText.size() - rangeStart;
}
}
@@ -296,12 +303,12 @@ bool QQuickStyledTextPrivate::parseTag(const QChar *&ch, const QString &textIn,
if (tagLength == 0)
return false;
auto tag = QStringView(textIn).mid(tagStart, tagLength);
- const QChar char0 = tag.at(0);
+ const QChar char0 = tag.at(0).toLower();
if (char0 == QLatin1Char('b')) {
if (tagLength == 1) {
format.setFontWeight(QFont::Bold);
return true;
- } else if (tagLength == 2 && tag.at(1) == QLatin1Char('r')) {
+ } else if (tagLength == 2 && tag.at(1).toLower() == QLatin1Char('r')) {
textOut.append(QChar(QChar::LineSeparator));
hasSpace = true;
prependSpace = false;
@@ -318,7 +325,7 @@ bool QQuickStyledTextPrivate::parseTag(const QChar *&ch, const QString &textIn,
textOut.append(QChar::LineSeparator);
hasSpace = true;
prependSpace = false;
- } else if (tag == QLatin1String("pre")) {
+ } else if (is_equal_ignoring_case(tag, QLatin1String("pre"))) {
preFormat = true;
if (!hasNewLine)
textOut.append(QChar::LineSeparator);
@@ -330,7 +337,7 @@ bool QQuickStyledTextPrivate::parseTag(const QChar *&ch, const QString &textIn,
if (tagLength == 1) {
format.setFontUnderline(true);
return true;
- } else if (tag == QLatin1String("ul")) {
+ } else if (is_equal_ignoring_case(tag, QLatin1String("ul"))) {
List listItem;
listItem.level = 0;
listItem.type = Unordered;
@@ -352,20 +359,20 @@ bool QQuickStyledTextPrivate::parseTag(const QChar *&ch, const QString &textIn,
if (tagLength == 1) {
format.setFontStrikeOut(true);
return true;
- } else if (tag == QLatin1String("strong")) {
+ } else if (is_equal_ignoring_case(tag, QLatin1String("strong"))) {
format.setFontWeight(QFont::Bold);
return true;
}
- } else if (tag == QLatin1String("del")) {
+ } else if (is_equal_ignoring_case(tag, QLatin1String("del"))) {
format.setFontStrikeOut(true);
return true;
- } else if (tag == QLatin1String("ol")) {
+ } else if (is_equal_ignoring_case(tag, QLatin1String("ol"))) {
List listItem;
listItem.level = 0;
listItem.type = Ordered;
listItem.format = Decimal;
listStack.push(listItem);
- } else if (tag == QLatin1String("li")) {
+ } else if (is_equal_ignoring_case(tag, QLatin1String("li"))) {
if (!hasNewLine)
textOut.append(QChar(QChar::LineSeparator));
if (!listStack.isEmpty()) {
@@ -405,20 +412,20 @@ bool QQuickStyledTextPrivate::parseTag(const QChar *&ch, const QString &textIn,
} else if (ch->isSpace()) {
// may have params.
auto tag = QStringView(textIn).mid(tagStart, tagLength);
- if (tag == QLatin1String("font"))
+ if (is_equal_ignoring_case(tag, QLatin1String("font")))
return parseFontAttributes(ch, textIn, format);
- if (tag == QLatin1String("ol")) {
+ if (is_equal_ignoring_case(tag, QLatin1String("ol"))) {
parseOrderedListAttributes(ch, textIn);
return false; // doesn't modify format
}
- if (tag == QLatin1String("ul")) {
+ if (is_equal_ignoring_case(tag, QLatin1String("ul"))) {
parseUnorderedListAttributes(ch, textIn);
return false; // doesn't modify format
}
- if (tag == QLatin1String("a")) {
+ if (is_equal_ignoring_case(tag, QLatin1String("a"))) {
return parseAnchorAttributes(ch, textIn, format);
}
- if (tag == QLatin1String("img")) {
+ if (is_equal_ignoring_case(tag, QLatin1String("img"))) {
parseImageAttributes(ch, textIn, textOut);
return false;
}
@@ -443,12 +450,12 @@ bool QQuickStyledTextPrivate::parseCloseTag(const QChar *&ch, const QString &tex
if (tagLength == 0)
return false;
auto tag = QStringView(textIn).mid(tagStart, tagLength);
- const QChar char0 = tag.at(0);
+ const QChar char0 = tag.at(0).toLower();
hasNewLine = false;
if (char0 == QLatin1Char('b')) {
if (tagLength == 1)
return true;
- else if (tag.at(1) == QLatin1Char('r') && tagLength == 2)
+ else if (tag.at(1).toLower() == QLatin1Char('r') && tagLength == 2)
return false;
} else if (char0 == QLatin1Char('i')) {
if (tagLength == 1)
@@ -462,7 +469,7 @@ bool QQuickStyledTextPrivate::parseCloseTag(const QChar *&ch, const QString &tex
hasNewLine = true;
hasSpace = true;
return false;
- } else if (tag == QLatin1String("pre")) {
+ } else if (is_equal_ignoring_case(tag, QLatin1String("pre"))) {
preFormat = false;
if (!hasNewLine)
textOut.append(QChar::LineSeparator);
@@ -473,10 +480,10 @@ bool QQuickStyledTextPrivate::parseCloseTag(const QChar *&ch, const QString &tex
} else if (char0 == QLatin1Char('u')) {
if (tagLength == 1)
return true;
- else if (tag == QLatin1String("ul")) {
+ else if (is_equal_ignoring_case(tag, QLatin1String("ul"))) {
if (!listStack.isEmpty()) {
listStack.pop();
- if (!listStack.count())
+ if (!listStack.size())
textOut.append(QChar::LineSeparator);
}
return false;
@@ -486,24 +493,24 @@ bool QQuickStyledTextPrivate::parseCloseTag(const QChar *&ch, const QString &tex
hasNewLine = true;
hasSpace = true;
return true;
- } else if (tag == QLatin1String("font")) {
+ } else if (is_equal_ignoring_case(tag, QLatin1String("font"))) {
return true;
} else if (char0 == QLatin1Char('s')) {
if (tagLength == 1) {
return true;
- } else if (tag == QLatin1String("strong")) {
+ } else if (is_equal_ignoring_case(tag, QLatin1String("strong"))) {
return true;
}
- } else if (tag == QLatin1String("del")) {
+ } else if (is_equal_ignoring_case(tag, QLatin1String("del"))) {
return true;
- } else if (tag == QLatin1String("ol")) {
+ } else if (is_equal_ignoring_case(tag, QLatin1String("ol"))) {
if (!listStack.isEmpty()) {
listStack.pop();
- if (!listStack.count())
+ if (!listStack.size())
textOut.append(QChar::LineSeparator);
}
return false;
- } else if (tag == QLatin1String("li")) {
+ } else if (is_equal_ignoring_case(tag, QLatin1String("li"))) {
return false;
}
return false;
@@ -545,10 +552,10 @@ bool QQuickStyledTextPrivate::parseFontAttributes(const QChar *&ch, const QStrin
QPair<QStringView,QStringView> attr;
do {
attr = parseAttribute(ch, textIn);
- if (attr.first == QLatin1String("color")) {
+ if (is_equal_ignoring_case(attr.first, QLatin1String("color"))) {
valid = true;
format.setForeground(QColor::fromString(attr.second));
- } else if (attr.first == QLatin1String("size")) {
+ } else if (is_equal_ignoring_case(attr.first, QLatin1String("size"))) {
valid = true;
int size = attr.second.toInt();
if (attr.second.at(0) == QLatin1Char('-') || attr.second.at(0) == QLatin1Char('+'))
@@ -573,7 +580,7 @@ bool QQuickStyledTextPrivate::parseOrderedListAttributes(const QChar *&ch, const
QPair<QStringView,QStringView> attr;
do {
attr = parseAttribute(ch, textIn);
- if (attr.first == QLatin1String("type")) {
+ if (is_equal_ignoring_case(attr.first, QLatin1String("type"))) {
valid = true;
if (attr.second == QLatin1String("a"))
listItem.format = LowerAlpha;
@@ -602,11 +609,11 @@ bool QQuickStyledTextPrivate::parseUnorderedListAttributes(const QChar *&ch, con
QPair<QStringView,QStringView> attr;
do {
attr = parseAttribute(ch, textIn);
- if (attr.first == QLatin1String("type")) {
+ if (is_equal_ignoring_case(attr.first, QLatin1String("type"))) {
valid = true;
- if (attr.second == QLatin1String("disc"))
+ if (is_equal_ignoring_case(attr.second, QLatin1String("disc")))
listItem.format = Disc;
- else if (attr.second == QLatin1String("square"))
+ else if (is_equal_ignoring_case(attr.second, QLatin1String("square")))
listItem.format = Square;
}
} while (!ch->isNull() && !attr.first.isEmpty());
@@ -622,7 +629,7 @@ bool QQuickStyledTextPrivate::parseAnchorAttributes(const QChar *&ch, const QStr
QPair<QStringView,QStringView> attr;
do {
attr = parseAttribute(ch, textIn);
- if (attr.first == QLatin1String("href")) {
+ if (is_equal_ignoring_case(attr.first, QLatin1String("href"))) {
format.setAnchorHref(attr.second.toString());
format.setAnchor(true);
format.setFontUnderline(true);
@@ -642,21 +649,21 @@ void QQuickStyledTextPrivate::parseImageAttributes(const QChar *&ch, const QStri
if (!updateImagePositions) {
QQuickStyledTextImgTag *image = new QQuickStyledTextImgTag;
- image->position = textOut.length() + (trailingSpace ? 0 : 1);
+ image->position = textOut.size() + (trailingSpace ? 0 : 1);
QPair<QStringView,QStringView> attr;
do {
attr = parseAttribute(ch, textIn);
- if (attr.first == QLatin1String("src")) {
+ if (is_equal_ignoring_case(attr.first, QLatin1String("src"))) {
image->url = QUrl(attr.second.toString());
- } else if (attr.first == QLatin1String("width")) {
+ } else if (is_equal_ignoring_case(attr.first, QLatin1String("width"))) {
image->size.setWidth(attr.second.toString().toInt());
- } else if (attr.first == QLatin1String("height")) {
+ } else if (is_equal_ignoring_case(attr.first, QLatin1String("height"))) {
image->size.setHeight(attr.second.toString().toInt());
- } else if (attr.first == QLatin1String("align")) {
- if (attr.second.toString() == QLatin1String("top")) {
+ } else if (is_equal_ignoring_case(attr.first, QLatin1String("align"))) {
+ if (is_equal_ignoring_case(attr.second, QLatin1String("top"))) {
image->align = QQuickStyledTextImgTag::Top;
- } else if (attr.second.toString() == QLatin1String("middle")) {
+ } else if (is_equal_ignoring_case(attr.second, QLatin1String("middle"))) {
image->align = QQuickStyledTextImgTag::Middle;
}
}
@@ -686,7 +693,7 @@ void QQuickStyledTextPrivate::parseImageAttributes(const QChar *&ch, const QStri
// if we already have a list of img tags for this text
// we only want to update the positions of these tags.
QQuickStyledTextImgTag *image = imgTags->value(nbImages);
- image->position = textOut.length() + (trailingSpace ? 0 : 1);
+ image->position = textOut.size() + (trailingSpace ? 0 : 1);
imgWidth = image->size.width();
image->offset = -std::fmod(imgWidth, spaceWidth) / 2.0;
QPair<QStringView,QStringView> attr;
diff --git a/src/quick/util/qquicksvgparser.cpp b/src/quick/util/qquicksvgparser.cpp
index a4f1ac8e80..5f88805ef7 100644
--- a/src/quick/util/qquicksvgparser.cpp
+++ b/src/quick/util/qquicksvgparser.cpp
@@ -249,7 +249,7 @@ bool QQuickSvgParser::parsePathDataFast(const QString &dataStr, QPainterPath &pa
if (pathElem == QLatin1Char('z') || pathElem == QLatin1Char('Z'))
arg.append(0);//dummy
const qreal *num = arg.constData();
- int count = arg.count();
+ int count = arg.size();
while (count > 0) {
qreal offsetX = x; // correction offsets
qreal offsetY = y; // for relative commands
diff --git a/src/quick/util/qquicktimeline.cpp b/src/quick/util/qquicktimeline.cpp
index ab59969ce5..e53dbe0fd9 100644
--- a/src/quick/util/qquicktimeline.cpp
+++ b/src/quick/util/qquicktimeline.cpp
@@ -786,7 +786,7 @@ int QQuickTimeLinePrivate::advance(int t)
std::sort(updates.begin(), updates.end());
updateQueue = &updates;
- for (int ii = 0; ii < updates.count(); ++ii) {
+ for (int ii = 0; ii < updates.size(); ++ii) {
const Update &v = updates.at(ii).second;
if (v.g) {
v.g->setValue(v.v);
@@ -836,7 +836,7 @@ void QQuickTimeLine::remove(QQuickTimeLineObject *v)
}
if (d->updateQueue) {
- for (int ii = 0; ii < d->updateQueue->count(); ++ii) {
+ for (int ii = 0; ii < d->updateQueue->size(); ++ii) {
if (d->updateQueue->at(ii).second.g == v ||
d->updateQueue->at(ii).second.e.callbackObject() == v) {
d->updateQueue->removeAt(ii);
diff --git a/src/quick/util/qquicktransition.cpp b/src/quick/util/qquicktransition.cpp
index 1d2c9e2f41..062e6e2656 100644
--- a/src/quick/util/qquicktransition.cpp
+++ b/src/quick/util/qquicktransition.cpp
@@ -115,7 +115,7 @@ void QQuickTransitionPrivate::append_animation(QQmlListProperty<QQuickAbstractAn
qsizetype QQuickTransitionPrivate::animation_count(QQmlListProperty<QQuickAbstractAnimation> *list)
{
QQuickTransition *q = static_cast<QQuickTransition *>(list->object);
- return q->d_func()->animations.count();
+ return q->d_func()->animations.size();
}
QQuickAbstractAnimation* QQuickTransitionPrivate::animation_at(QQmlListProperty<QQuickAbstractAnimation> *list, qsizetype pos)
@@ -127,7 +127,7 @@ QQuickAbstractAnimation* QQuickTransitionPrivate::animation_at(QQmlListProperty<
void QQuickTransitionPrivate::clear_animations(QQmlListProperty<QQuickAbstractAnimation> *list)
{
QQuickTransition *q = static_cast<QQuickTransition *>(list->object);
- while (q->d_func()->animations.count()) {
+ while (q->d_func()->animations.size()) {
QQuickAbstractAnimation *firstAnim = q->d_func()->animations.at(0);
q->d_func()->animations.removeAll(firstAnim);
}
@@ -232,8 +232,8 @@ QQuickTransitionInstance *QQuickTransition::prepare(QQuickStateOperation::Action
group->manager = manager;
QQuickAbstractAnimation::TransitionDirection direction = d->reversed ? QQuickAbstractAnimation::Backward : QQuickAbstractAnimation::Forward;
- int start = d->reversed ? d->animations.count() - 1 : 0;
- int end = d->reversed ? -1 : d->animations.count();
+ int start = d->reversed ? d->animations.size() - 1 : 0;
+ int end = d->reversed ? -1 : d->animations.size();
QAbstractAnimationJob *anim = nullptr;
for (int i = start; i != end;) {
diff --git a/src/quick/util/qquicktransitionmanager.cpp b/src/quick/util/qquicktransitionmanager.cpp
index 53aa6608aa..efaa01c305 100644
--- a/src/quick/util/qquicktransitionmanager.cpp
+++ b/src/quick/util/qquicktransitionmanager.cpp
@@ -59,7 +59,7 @@ void QQuickTransitionManager::complete()
// Explicitly take a copy in case the write action triggers a script that modifies the list.
QQuickTransitionManagerPrivate::SimpleActionList completeListCopy = d->completeList;
- for (const QQuickSimpleAction &action : qAsConst(completeListCopy))
+ for (const QQuickSimpleAction &action : std::as_const(completeListCopy))
action.property().write(action.value());
d->completeList.clear();
@@ -72,7 +72,7 @@ void QQuickTransitionManager::complete()
void QQuickTransitionManagerPrivate::applyBindings()
{
- for (const QQuickStateAction &action : qAsConst(bindingsList)) {
+ for (const QQuickStateAction &action : std::as_const(bindingsList)) {
if (auto binding = action.toBinding; binding) {
binding.installOn(action.property, QQmlAnyBinding::RespectInterceptors);
} else if (action.event) {
@@ -101,11 +101,13 @@ void QQuickTransitionManager::transition(const QList<QQuickStateAction> &list,
QQuickStateOperation::ActionList applyList = list;
// Determine which actions are binding changes and disable any current bindings
- for (const QQuickStateAction &action : qAsConst(applyList)) {
+ for (const QQuickStateAction &action : std::as_const(applyList)) {
if (action.toBinding)
d->bindingsList << action;
- if (action.fromBinding)
- QQmlPropertyPrivate::removeBinding(action.property); // Disable current binding
+ if (action.fromBinding) {
+ auto property = action.property;
+ QQmlAnyBinding::removeBindingFrom(property); // Disable current binding
+ }
if (action.event && action.event->changesBindings()) { //### assume isReversable()?
d->bindingsList << action;
action.event->clearBindings();
@@ -123,7 +125,7 @@ void QQuickTransitionManager::transition(const QList<QQuickStateAction> &list,
if (transition && !d->bindingsList.isEmpty()) {
// Apply all the property and binding changes
- for (const QQuickStateAction &action : qAsConst(applyList)) {
+ for (const QQuickStateAction &action : std::as_const(applyList)) {
if (auto binding = action.toBinding; binding) {
binding.installOn(action.property);
} else if (!action.event) {
@@ -148,7 +150,7 @@ void QQuickTransitionManager::transition(const QList<QQuickStateAction> &list,
}
// Revert back to the original values
- for (const QQuickStateAction &action : qAsConst(applyList)) {
+ for (const QQuickStateAction &action : std::as_const(applyList)) {
if (action.event) {
if (action.event->isReversable()) {
action.event->clearBindings();
@@ -158,8 +160,10 @@ void QQuickTransitionManager::transition(const QList<QQuickStateAction> &list,
continue;
}
- if (action.toBinding)
- QQmlPropertyPrivate::removeBinding(action.property); // Make sure this is disabled during the transition
+ if (action.toBinding) {
+ auto property = action.property;
+ QQmlAnyBinding::removeBindingFrom(property); // Make sure this is disabled during the transition
+ }
QQmlPropertyPrivate::write(action.property, action.fromValue, QQmlPropertyData::BypassInterceptor | QQmlPropertyData::DontRemoveBinding);
}
@@ -194,7 +198,7 @@ void QQuickTransitionManager::transition(const QList<QQuickStateAction> &list,
// be applied immediately. We skip applying bindings, as they are all
// applied at the end in applyBindings() to avoid any nastiness mid
// transition
- for (const QQuickStateAction &action : qAsConst(applyList)) {
+ for (const QQuickStateAction &action : std::as_const(applyList)) {
if (action.event && !action.event->changesBindings()) {
if (action.event->isReversable() && action.reverseEvent)
action.event->reverse();
@@ -205,7 +209,7 @@ void QQuickTransitionManager::transition(const QList<QQuickStateAction> &list,
}
}
if (lcStates().isDebugEnabled()) {
- for (const QQuickStateAction &action : qAsConst(applyList)) {
+ for (const QQuickStateAction &action : std::as_const(applyList)) {
if (action.event)
qCDebug(lcStates) << "no transition for event:" << action.event->type();
else
@@ -224,9 +228,10 @@ void QQuickTransitionManager::cancel()
if (d->transitionInstance && d->transitionInstance->isRunning())
RETURN_IF_DELETED(d->transitionInstance->stop());
- for (const QQuickStateAction &action : qAsConst(d->bindingsList)) {
+ for (const QQuickStateAction &action : std::as_const(d->bindingsList)) {
if (action.toBinding && action.deletableToBinding) {
- QQmlPropertyPrivate::removeBinding(action.property);
+ auto property = action.property;
+ QQmlAnyBinding::removeBindingFrom(property);
} else if (action.event) {
//### what do we do here?
}