Fix crash when dragging an invalid item in the header view

Dragging an invalid item in the header view leads to a crash. It's
better to safeguard before operating anything w.r.t. to the dragged
item.

This patch fixes that issue by validating the invalid item before
performing drag operation. Also added an test case to verify the same.

Fixes: QTBUG-127782
Pick-to: 6.8
Change-Id: I95398c7410d6fb6427ec06ff4b7da42472bc6d18
Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@qt.io>
Reviewed-by: MohammadHossein Qanbari <mohammad.qanbari@qt.io>
This commit is contained in:
Santhosh Kumar 2024-08-07 15:33:12 +02:00
parent 5ca8a2477a
commit 6c36d341e0
3 changed files with 73 additions and 2 deletions

View File

@ -7307,6 +7307,8 @@ void QQuickTableViewSectionDragHandler::handleEventPoint(QPointerEvent *event, Q
// Grab the image for dragging header
const QPoint cell = tableView->cellAtPosition(point.position(), true);
auto *item = tableView->itemAtCell(cell);
if (!item)
break;
if (m_drag.isNull()) {
m_drag = new QDrag(item);
connect(m_drag.data(), &QDrag::actionChanged, this,

View File

@ -0,0 +1,39 @@
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
import TestTableModelWithHeader
ApplicationWindow {
width: 400
height: 400
property alias headerView: headerView
Column {
HorizontalHeaderView {
id: headerView
objectName: "horizontalHeader"
syncView: tableView
textRole: "customRole"
movableColumns: true
}
TableView {
id: tableView
width: 100
height: 100
model: TestTableModelWithHeader {
rowCount: 2
columnCount: 2
}
delegate: Label {
text: customRole
leftPadding: 10
rightPadding: 10
required property string customRole
}
}
}
}

View File

@ -226,10 +226,9 @@ private slots:
void listModel();
void resizableHandlerBlockingEvents();
void headerData();
void warnMissingDefaultRole();
void dragInvalidItemDuringReorder();
private:
QQmlEngine *engine;
@ -459,6 +458,37 @@ void tst_QQuickHeaderView::warnMissingDefaultRole()
QVERIFY(QTest::qWaitForWindowExposed(window));
}
void tst_QQuickHeaderView::dragInvalidItemDuringReorder()
{
QQuickApplicationHelper helper(this, QStringLiteral("reorderHeader.qml"));
QVERIFY2(helper.errorMessage.isEmpty(), helper.errorMessage);
QQuickWindow *window = helper.window;
window->show();
QVERIFY(QTest::qWaitForWindowExposed(window));
auto hhv = window->findChild<QQuickHorizontalHeaderView *>("horizontalHeader");
QVERIFY(hhv);
const auto item = hhv->itemAtIndex(hhv->index(0, 0));
QQuickWindow *itemWindow = item->window();
QSignalSpy columnMovedSpy(hhv, SIGNAL(columnMoved(int, int, int)));
QVERIFY(columnMovedSpy.isValid());
const QPoint localPos = QPoint(item->width() - 5, item->height() - 5);
const QPoint startPos = itemWindow->contentItem()->mapFromItem(item, localPos).toPoint();
const QPoint startDragDist = QPoint(0, qApp->styleHints()->startDragDistance() + 1);
const QPoint dragLength(0, 100);
QTest::mousePress(itemWindow, Qt::LeftButton, Qt::NoModifier, startPos);
QTest::mouseMove(itemWindow, startPos + startDragDist);
QTest::mouseMove(itemWindow, startPos + dragLength);
QTest::mouseRelease(itemWindow, Qt::LeftButton, Qt::NoModifier, startPos + dragLength);
QVERIFY(!QQuickTest::qIsPolishScheduled(item));
QCOMPARE(columnMovedSpy.size(), 0);
}
QTEST_MAIN(tst_QQuickHeaderView)
#include "tst_qquickheaderview.moc"