Skip to content

Commit

Permalink
Don't edit the item if we did not get the press event on the same item
Browse files Browse the repository at this point in the history
With a QTreeView it is possible that collapsing an item can cause the
item under the mouse to be a new one and over the checkbox area for the
new item. As a result, a release can cause it to change the check state
even though it did not get the press for that item. This ensures that
it only allows the edit if it got the press as well.

Fixes: QTBUG-61476
Change-Id: I9a0821466afc84c97c9819755ccbacd729f7fbd7
Reviewed-by: Christian Ehrlicher <[email protected]>
  • Loading branch information
AndyShawQt committed Feb 26, 2019
1 parent 9694d75 commit 7e60858
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 1 deletion.
2 changes: 1 addition & 1 deletion src/widgets/itemviews/qabstractitemview.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1912,7 +1912,7 @@ void QAbstractItemView::mouseReleaseEvent(QMouseEvent *event)
bool click = (index == d->pressedIndex && index.isValid());
bool selectedClicked = click && (event->button() == Qt::LeftButton) && d->pressedAlreadySelected;
EditTrigger trigger = (selectedClicked ? SelectedClicked : NoEditTriggers);
bool edited = edit(index, trigger, event);
const bool edited = click ? edit(index, trigger, event) : false;

d->ctrlDragSelectionFlag = QItemSelectionModel::NoUpdate;

Expand Down
54 changes: 54 additions & 0 deletions tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,7 @@ private slots:
void taskQTBUG_45697_crash();
void taskQTBUG_7232_AllowUserToControlSingleStep();
void taskQTBUG_8376();
void taskQTBUG_61476();
void testInitialFocus();
};

Expand Down Expand Up @@ -4726,5 +4727,58 @@ void tst_QTreeView::taskQTBUG_8376()
QCOMPARE(rowHeightLvl1Visible, rowHeightLvl1Visible2);
}

void tst_QTreeView::taskQTBUG_61476()
{
// This checks that if a user clicks on an item to collapse it that it
// does not edit (in this case change the check state) the item that is
// now over the mouse just because it got a release event
QTreeView tv;
QStandardItemModel model;
QStandardItem *lastTopLevel = nullptr;
{
for (int i = 0; i < 4; ++i) {
QStandardItem *item = new QStandardItem(QLatin1String("Row Item"));
item->setCheckable(true);
item->setCheckState(Qt::Checked);
model.appendRow(item);
lastTopLevel = item;
for (int j = 0; j < 2; ++j) {
QStandardItem *childItem = new QStandardItem(QLatin1String("Child row Item"));
childItem->setCheckable(true);
childItem->setCheckState(Qt::Checked);
item->appendRow(childItem);
QStandardItem *grandChild = new QStandardItem(QLatin1String("Grand child row Item"));
grandChild->setCheckable(true);
grandChild->setCheckState(Qt::Checked);
childItem->appendRow(grandChild);
}
}
}
tv.setModel(&model);
tv.expandAll();
// We need it to be this size so that the effect of the collapsing will
// cause the parent item to move to be under the cursor
tv.resize(200, 200);
tv.show();
QVERIFY(QTest::qWaitForWindowActive(&tv));
tv.verticalScrollBar()->setValue(tv.verticalScrollBar()->maximum());

// We want to press specifically right around where a checkbox for the
// parent item could be when collapsing
QTreeViewPrivate *priv = static_cast<QTreeViewPrivate*>(qt_widget_private(&tv));
const QModelIndex mi = lastTopLevel->child(0)->index();
const QRect rect = priv->itemDecorationRect(mi);
const QPoint pos = rect.center();

QTest::mousePress(tv.viewport(), Qt::LeftButton, 0, pos);
if (tv.style()->styleHint(QStyle::SH_ListViewExpand_SelectMouseType, 0, &tv) ==
QEvent::MouseButtonPress)
QTRY_VERIFY(!tv.isExpanded(mi));

QTest::mouseRelease(tv.viewport(), Qt::LeftButton, 0, pos);
QTRY_VERIFY(!tv.isExpanded(mi));
QCOMPARE(lastTopLevel->checkState(), Qt::Checked);
}

QTEST_MAIN(tst_QTreeView)
#include "tst_qtreeview.moc"

0 comments on commit 7e60858

Please sign in to comment.