diff options
-rw-r--r-- | src/gui/itemviews/qabstractitemview.cpp | 12 | ||||
-rw-r--r-- | src/gui/itemviews/qabstractitemview_p.h | 1 | ||||
-rw-r--r-- | src/gui/itemviews/qtableview.cpp | 28 | ||||
-rw-r--r-- | tests/auto/qtableview/tst_qtableview.cpp | 114 |
4 files changed, 153 insertions, 2 deletions
diff --git a/src/gui/itemviews/qabstractitemview.cpp b/src/gui/itemviews/qabstractitemview.cpp index 9d977a5..757ded9 100644 --- a/src/gui/itemviews/qabstractitemview.cpp +++ b/src/gui/itemviews/qabstractitemview.cpp @@ -69,6 +69,7 @@ QAbstractItemViewPrivate::QAbstractItemViewPrivate() : model(QAbstractItemModelPrivate::staticEmptyModel()), itemDelegate(0), selectionModel(0), + ctrlDragSelectionFlag(QItemSelectionModel::NoUpdate), selectionMode(QAbstractItemView::ExtendedSelection), selectionBehavior(QAbstractItemView::SelectItems), currentlyCommittingEditor(0), @@ -1589,6 +1590,11 @@ void QAbstractItemView::mousePressEvent(QMouseEvent *event) d->selectionModel->setCurrentIndex(index, QItemSelectionModel::NoUpdate); d->autoScroll = autoScroll; QRect rect(d->pressedPosition - offset, pos); + if (command.testFlag(QItemSelectionModel::Toggle)) { + command &= ~QItemSelectionModel::Toggle; + d->ctrlDragSelectionFlag = d->selectionModel->isSelected(index) ? QItemSelectionModel::Deselect : QItemSelectionModel::Select; + command |= d->ctrlDragSelectionFlag; + } setSelection(rect, command); // signal handlers may change the model @@ -1659,6 +1665,10 @@ void QAbstractItemView::mouseMoveEvent(QMouseEvent *event) if ((event->buttons() & Qt::LeftButton) && d->selectionAllowed(index) && d->selectionModel) { setState(DragSelectingState); QItemSelectionModel::SelectionFlags command = selectionCommand(index, event); + if (command.testFlag(QItemSelectionModel::Toggle)) { + command &= ~QItemSelectionModel::Toggle; + command |= d->ctrlDragSelectionFlag; + } // Do the normalize ourselves, since QRect::normalized() is flawed QRect selectionRect = QRect(topLeft, bottomRight); @@ -1699,6 +1709,8 @@ void QAbstractItemView::mouseReleaseEvent(QMouseEvent *event) EditTrigger trigger = (selectedClicked ? SelectedClicked : NoEditTriggers); bool edited = edit(index, trigger, event); + d->ctrlDragSelectionFlag = QItemSelectionModel::NoUpdate; + //in the case the user presses on no item we might decide to clear the selection if (d->selectionModel && !index.isValid()) d->selectionModel->select(QModelIndex(), selectionCommand(index, event)); diff --git a/src/gui/itemviews/qabstractitemview_p.h b/src/gui/itemviews/qabstractitemview_p.h index 725d0a9..6b1ec8e 100644 --- a/src/gui/itemviews/qabstractitemview_p.h +++ b/src/gui/itemviews/qabstractitemview_p.h @@ -342,6 +342,7 @@ public: QMap<int, QPointer<QAbstractItemDelegate> > rowDelegates; QMap<int, QPointer<QAbstractItemDelegate> > columnDelegates; QPointer<QItemSelectionModel> selectionModel; + QItemSelectionModel::SelectionFlag ctrlDragSelectionFlag; QAbstractItemView::SelectionMode selectionMode; QAbstractItemView::SelectionBehavior selectionBehavior; diff --git a/src/gui/itemviews/qtableview.cpp b/src/gui/itemviews/qtableview.cpp index 684da3f..f1ffaa6 100644 --- a/src/gui/itemviews/qtableview.cpp +++ b/src/gui/itemviews/qtableview.cpp @@ -2519,9 +2519,21 @@ void QTableViewPrivate::selectRow(int row, bool anchor) QModelIndex index = model->index(row, column, root); QItemSelectionModel::SelectionFlags command = q->selectionCommand(index); selectionModel->setCurrentIndex(index, QItemSelectionModel::NoUpdate); - if ((!(command & QItemSelectionModel::Current) && anchor) + if ((anchor && !(command & QItemSelectionModel::Current)) || (q->selectionMode() == QTableView::SingleSelection)) rowSectionAnchor = row; + + if (q->selectionMode() != QTableView::SingleSelection + && command.testFlag(QItemSelectionModel::Toggle)) { + if (anchor) + ctrlDragSelectionFlag = verticalHeader->selectionModel()->selectedRows().contains(index) + ? QItemSelectionModel::Deselect : QItemSelectionModel::Select; + command &= ~QItemSelectionModel::Toggle; + command |= ctrlDragSelectionFlag; + if (!anchor) + command |= QItemSelectionModel::Current; + } + QModelIndex tl = model->index(qMin(rowSectionAnchor, row), 0, root); QModelIndex br = model->index(qMax(rowSectionAnchor, row), model->columnCount(root) - 1, root); if (verticalHeader->sectionsMoved() && tl.row() != br.row()) @@ -2545,9 +2557,21 @@ void QTableViewPrivate::selectColumn(int column, bool anchor) QModelIndex index = model->index(row, column, root); QItemSelectionModel::SelectionFlags command = q->selectionCommand(index); selectionModel->setCurrentIndex(index, QItemSelectionModel::NoUpdate); - if ((!(command & QItemSelectionModel::Current) && anchor) + if ((anchor && !(command & QItemSelectionModel::Current)) || (q->selectionMode() == QTableView::SingleSelection)) columnSectionAnchor = column; + + if (q->selectionMode() != QTableView::SingleSelection + && command.testFlag(QItemSelectionModel::Toggle)) { + if (anchor) + ctrlDragSelectionFlag = horizontalHeader->selectionModel()->selectedColumns().contains(index) + ? QItemSelectionModel::Deselect : QItemSelectionModel::Select; + command &= ~QItemSelectionModel::Toggle; + command |= ctrlDragSelectionFlag; + if (!anchor) + command |= QItemSelectionModel::Current; + } + QModelIndex tl = model->index(0, qMin(columnSectionAnchor, column), root); QModelIndex br = model->index(model->rowCount(root) - 1, qMax(columnSectionAnchor, column), root); diff --git a/tests/auto/qtableview/tst_qtableview.cpp b/tests/auto/qtableview/tst_qtableview.cpp index 8d9a50c..48fcb3e 100644 --- a/tests/auto/qtableview/tst_qtableview.cpp +++ b/tests/auto/qtableview/tst_qtableview.cpp @@ -43,6 +43,7 @@ #include <QtGui/QtGui> #include <QtTest/QtTest> #include "../../shared/util.h" +#include "private/qapplication_p.h" //TESTED_CLASS= //TESTED_FILES= @@ -179,6 +180,7 @@ private slots: void task240266_veryBigColumn(); void task248688_autoScrollNavigation(); void task259308_scrollVerticalHeaderSwappedSections(); + void task191545_dragSelectRows(); void mouseWheel_data(); void mouseWheel(); @@ -3300,5 +3302,117 @@ void tst_QTableView::task259308_scrollVerticalHeaderSwappedSections() QTRY_COMPARE(tv.rowAt(tv.viewport()->height() - 1), tv.verticalHeader()->logicalIndex(model.rowCount() - 1)); } +template <typename T> +struct ValueSaver { + T &var, value; + ValueSaver(T &v) : var(v), value(v) { } + ~ValueSaver() { var = value; } +}; + +void tst_QTableView::task191545_dragSelectRows() +{ + QStandardItemModel model(10, 10); + QTableView table; + table.setModel(&model); + table.setSelectionBehavior(QAbstractItemView::SelectItems); + table.setSelectionMode(QAbstractItemView::ExtendedSelection); + table.setMinimumSize(1000, 400); + table.show(); + QTest::qWait(200); + + ValueSaver<Qt::KeyboardModifiers> saver(QApplicationPrivate::modifier_buttons); + QApplicationPrivate::modifier_buttons = Qt::ControlModifier; + + { + QRect cellRect = table.visualRect(model.index(3, 0)); + QHeaderView *vHeader = table.verticalHeader(); + QWidget *vHeaderVp = vHeader->viewport(); + QPoint rowPos(5, (cellRect.top() + cellRect.bottom()) / 2); + QMouseEvent rowPressEvent(QEvent::MouseButtonPress, rowPos, Qt::LeftButton, Qt::NoButton, Qt::ControlModifier); + qApp->sendEvent(vHeaderVp, &rowPressEvent); + + for (int i = 0; i < 4; ++i) { + rowPos.setY(rowPos.y() + cellRect.height()); + QMouseEvent moveEvent(QEvent::MouseMove, rowPos, Qt::NoButton, Qt::LeftButton, Qt::ControlModifier); + qApp->sendEvent(vHeaderVp, &moveEvent); + } + QMouseEvent rowReleaseEvent(QEvent::MouseButtonRelease, rowPos, Qt::LeftButton, Qt::NoButton, Qt::ControlModifier); + qApp->sendEvent(vHeaderVp, &rowReleaseEvent); + + for (int i = 0; i < 4; ++i) { + QModelIndex index = model.index(3 + i, 0, table.rootIndex()); + QVERIFY(vHeader->selectionModel()->selectedRows().contains(index)); + } + } + + { + QRect cellRect = table.visualRect(model.index(0, 3)); + QHeaderView *hHeader = table.horizontalHeader(); + QWidget *hHeaderVp = hHeader->viewport(); + QPoint colPos((cellRect.left() + cellRect.right()) / 2, 5); + QMouseEvent colPressEvent(QEvent::MouseButtonPress, colPos, Qt::LeftButton, Qt::NoButton, Qt::ControlModifier); + qApp->sendEvent(hHeaderVp, &colPressEvent); + + for (int i = 0; i < 4; ++i) { + colPos.setX(colPos.x() + cellRect.width()); + QMouseEvent moveEvent(QEvent::MouseMove, colPos, Qt::NoButton, Qt::LeftButton, Qt::ControlModifier); + qApp->sendEvent(hHeaderVp, &moveEvent); + } + QMouseEvent colReleaseEvent(QEvent::MouseButtonRelease, colPos, Qt::LeftButton, Qt::NoButton, Qt::ControlModifier); + qApp->sendEvent(hHeaderVp, &colReleaseEvent); + + for (int i = 0; i < 4; ++i) { + QModelIndex index = model.index(0, 3 + i, table.rootIndex()); + QVERIFY(hHeader->selectionModel()->selectedColumns().contains(index)); + } + } + + { + QRect cellRect = table.visualRect(model.index(2, 2)); + QWidget *tableVp = table.viewport(); + QPoint cellPos = cellRect.center(); + QMouseEvent cellPressEvent(QEvent::MouseButtonPress, cellPos, Qt::LeftButton, Qt::NoButton, Qt::ControlModifier); + qApp->sendEvent(tableVp, &cellPressEvent); + + for (int i = 0; i < 6; ++i) { + cellPos.setX(cellPos.x() + cellRect.width()); + cellPos.setY(cellPos.y() + cellRect.height()); + QMouseEvent moveEvent(QEvent::MouseMove, cellPos, Qt::NoButton, Qt::LeftButton, Qt::ControlModifier); + qApp->sendEvent(tableVp, &moveEvent); + } + QMouseEvent cellReleaseEvent(QEvent::MouseButtonRelease, cellPos, Qt::LeftButton, Qt::NoButton, Qt::ControlModifier); + qApp->sendEvent(tableVp, &cellReleaseEvent); + + for (int i = 0; i < 6; ++i) + for (int j = 0; j < 6; ++j) { + QModelIndex index = model.index(2 + i, 2 + j, table.rootIndex()); + QVERIFY(table.selectionModel()->isSelected(index)); + } + } + + { + QRect cellRect = table.visualRect(model.index(3, 3)); + QWidget *tableVp = table.viewport(); + QPoint cellPos = cellRect.center(); + QMouseEvent cellPressEvent(QEvent::MouseButtonPress, cellPos, Qt::LeftButton, Qt::NoButton, Qt::ControlModifier); + qApp->sendEvent(tableVp, &cellPressEvent); + + for (int i = 0; i < 6; ++i) { + cellPos.setX(cellPos.x() + cellRect.width()); + cellPos.setY(cellPos.y() + cellRect.height()); + QMouseEvent moveEvent(QEvent::MouseMove, cellPos, Qt::NoButton, Qt::LeftButton, Qt::ControlModifier); + qApp->sendEvent(tableVp, &moveEvent); + } + QMouseEvent cellReleaseEvent(QEvent::MouseButtonRelease, cellPos, Qt::LeftButton, Qt::NoButton, Qt::ControlModifier); + qApp->sendEvent(tableVp, &cellReleaseEvent); + + for (int i = 0; i < 6; ++i) + for (int j = 0; j < 6; ++j) { + QModelIndex index = model.index(3 + i, 3 + j, table.rootIndex()); + QVERIFY(!table.selectionModel()->isSelected(index)); + } + } +} + QTEST_MAIN(tst_QTableView) #include "tst_qtableview.moc" |