diff options
Diffstat (limited to 'src/widgets/itemviews/qabstractitemview.cpp')
-rw-r--r-- | src/widgets/itemviews/qabstractitemview.cpp | 406 |
1 files changed, 231 insertions, 175 deletions
diff --git a/src/widgets/itemviews/qabstractitemview.cpp b/src/widgets/itemviews/qabstractitemview.cpp index 0401379c38..85e478a71e 100644 --- a/src/widgets/itemviews/qabstractitemview.cpp +++ b/src/widgets/itemviews/qabstractitemview.cpp @@ -102,15 +102,16 @@ void QAbstractItemViewPrivate::init() vbar->setRange(0, 0); hbar->setRange(0, 0); - QObject::connect(vbar, SIGNAL(actionTriggered(int)), - q, SLOT(verticalScrollbarAction(int))); - QObject::connect(hbar, SIGNAL(actionTriggered(int)), - q, SLOT(horizontalScrollbarAction(int))); - QObject::connect(vbar, SIGNAL(valueChanged(int)), - q, SLOT(verticalScrollbarValueChanged(int))); - QObject::connect(hbar, SIGNAL(valueChanged(int)), - q, SLOT(horizontalScrollbarValueChanged(int))); - + scrollbarConnections = { + QObject::connect(vbar, &QScrollBar::actionTriggered, + q, &QAbstractItemView::verticalScrollbarAction), + QObject::connect(hbar, &QScrollBar::actionTriggered, + q, &QAbstractItemView::horizontalScrollbarAction), + QObject::connect(vbar, &QScrollBar::valueChanged, + q, &QAbstractItemView::verticalScrollbarValueChanged), + QObject::connect(hbar, &QScrollBar::valueChanged, + q, &QAbstractItemView::horizontalScrollbarValueChanged) + }; viewport->setBackgroundRole(QPalette::Base); q->setAttribute(Qt::WA_InputMethodEnabled); @@ -129,8 +130,8 @@ void QAbstractItemViewPrivate::setHoverIndex(const QPersistentModelIndex &index) q->update(hover); //update the old one q->update(index); //update the new one } else { - QRect oldHoverRect = q->visualRect(hover); - QRect newHoverRect = q->visualRect(index); + const QRect oldHoverRect = visualRect(hover); + const QRect newHoverRect = visualRect(index); viewport->update(QRect(0, newHoverRect.y(), viewport->width(), newHoverRect.height())); viewport->update(QRect(0, oldHoverRect.y(), viewport->width(), oldHoverRect.height())); } @@ -172,7 +173,7 @@ void QAbstractItemViewPrivate::checkMouseMove(const QPersistentModelIndex &index #if QT_CONFIG(gestures) && QT_CONFIG(scroller) // stores and restores the selection and current item when flicking -void QAbstractItemViewPrivate::_q_scrollerStateChanged() +void QAbstractItemViewPrivate::scrollerStateChanged() { Q_Q(QAbstractItemView); @@ -208,7 +209,7 @@ void QAbstractItemViewPrivate::_q_scrollerStateChanged() #endif // QT_NO_GESTURES -void QAbstractItemViewPrivate::_q_delegateSizeHintChanged(const QModelIndex &index) +void QAbstractItemViewPrivate::delegateSizeHintChanged(const QModelIndex &index) { Q_Q(QAbstractItemView); if (model) { @@ -218,6 +219,63 @@ void QAbstractItemViewPrivate::_q_delegateSizeHintChanged(const QModelIndex &ind QMetaObject::invokeMethod(q, &QAbstractItemView::doItemsLayout, Qt::QueuedConnection); } +void QAbstractItemViewPrivate::connectDelegate(QAbstractItemDelegate *delegate) +{ + if (!delegate) + return; + Q_Q(QAbstractItemView); + QObject::connect(delegate, &QAbstractItemDelegate::closeEditor, + q, &QAbstractItemView::closeEditor); + QObject::connect(delegate, &QAbstractItemDelegate::commitData, + q, &QAbstractItemView::commitData); + QObjectPrivate::connect(delegate, &QAbstractItemDelegate::sizeHintChanged, + this, &QAbstractItemViewPrivate::delegateSizeHintChanged); +} + +void QAbstractItemViewPrivate::disconnectDelegate(QAbstractItemDelegate *delegate) +{ + if (!delegate) + return; + Q_Q(QAbstractItemView); + QObject::disconnect(delegate, &QAbstractItemDelegate::closeEditor, + q, &QAbstractItemView::closeEditor); + QObject::disconnect(delegate, &QAbstractItemDelegate::commitData, + q, &QAbstractItemView::commitData); + QObjectPrivate::disconnect(delegate, &QAbstractItemDelegate::sizeHintChanged, + this, &QAbstractItemViewPrivate::delegateSizeHintChanged); +} + +void QAbstractItemViewPrivate::disconnectAll() +{ + Q_Q(QAbstractItemView); + for (const QMetaObject::Connection &connection : modelConnections) + QObject::disconnect(connection); + for (const QMetaObject::Connection &connection : scrollbarConnections) + QObject::disconnect(connection); + disconnectDelegate(itemDelegate); + for (QAbstractItemDelegate *delegate : std::as_const(rowDelegates)) + disconnectDelegate(delegate); + for (QAbstractItemDelegate *delegate : std::as_const(columnDelegates)) + disconnectDelegate(delegate); + if (model && selectionModel) { + QObject::disconnect(model, &QAbstractItemModel::destroyed, + selectionModel, &QItemSelectionModel::deleteLater); + } + if (selectionModel) { + QObject::disconnect(selectionModel, &QItemSelectionModel::selectionChanged, + q, &QAbstractItemView::selectionChanged); + QObject::disconnect(selectionModel, &QItemSelectionModel::currentChanged, + q, &QAbstractItemView::currentChanged); + } + for (const auto &info : std::as_const(indexEditorHash)) { + if (!info.isStatic && info.widget) + QObject::disconnect(info.widget, &QWidget::destroyed, q, &QAbstractItemView::editorDestroyed); + } +#if QT_CONFIG(gestures) && QT_CONFIG(scroller) + QObject::disconnect(scollerConnection); +#endif +} + /*! \class QAbstractItemView @@ -318,7 +376,7 @@ void QAbstractItemViewPrivate::_q_delegateSizeHintChanged(const QModelIndex &ind \l{QWidget::update()}{update()} as all painting operations take place on the viewport. - \sa {View Classes}, {Model/View Programming}, QAbstractItemModel, {Chart Example} + \sa {View Classes}, {Model/View Programming}, QAbstractItemModel */ /*! @@ -631,6 +689,7 @@ QAbstractItemView::~QAbstractItemView() d->autoScrollTimer.stop(); d->delayedLayout.stop(); d->fetchMoreTimer.stop(); + d->disconnectAll(); } /*! @@ -659,68 +718,47 @@ void QAbstractItemView::setModel(QAbstractItemModel *model) if (model == d->model) return; if (d->model && d->model != QAbstractItemModelPrivate::staticEmptyModel()) { - disconnect(d->model, SIGNAL(destroyed()), - this, SLOT(_q_modelDestroyed())); - disconnect(d->model, SIGNAL(dataChanged(QModelIndex, QModelIndex, QList<int>)), this, - SLOT(dataChanged(QModelIndex, QModelIndex, QList<int>))); - disconnect(d->model, SIGNAL(headerDataChanged(Qt::Orientation,int,int)), - this, SLOT(_q_headerDataChanged())); - disconnect(d->model, SIGNAL(rowsInserted(QModelIndex,int,int)), - this, SLOT(rowsInserted(QModelIndex,int,int))); - disconnect(d->model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)), - this, SLOT(rowsAboutToBeRemoved(QModelIndex,int,int))); - disconnect(d->model, SIGNAL(rowsRemoved(QModelIndex,int,int)), - this, SLOT(_q_rowsRemoved(QModelIndex,int,int))); - disconnect(d->model, SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int)), - this, SLOT(_q_rowsMoved(QModelIndex,int,int,QModelIndex,int))); - disconnect(d->model, SIGNAL(rowsInserted(QModelIndex,int,int)), - this, SLOT(_q_rowsInserted(QModelIndex,int,int))); - disconnect(d->model, SIGNAL(columnsAboutToBeRemoved(QModelIndex,int,int)), - this, SLOT(_q_columnsAboutToBeRemoved(QModelIndex,int,int))); - disconnect(d->model, SIGNAL(columnsRemoved(QModelIndex,int,int)), - this, SLOT(_q_columnsRemoved(QModelIndex,int,int))); - disconnect(d->model, SIGNAL(columnsInserted(QModelIndex,int,int)), - this, SLOT(_q_columnsInserted(QModelIndex,int,int))); - disconnect(d->model, SIGNAL(columnsMoved(QModelIndex,int,int,QModelIndex,int)), - this, SLOT(_q_columnsMoved(QModelIndex,int,int,QModelIndex,int))); - - disconnect(d->model, SIGNAL(modelReset()), this, SLOT(reset())); - disconnect(d->model, SIGNAL(layoutChanged()), this, SLOT(_q_layoutChanged())); + for (const QMetaObject::Connection &connection : d->modelConnections) + disconnect(connection); } d->model = (model ? model : QAbstractItemModelPrivate::staticEmptyModel()); if (d->model != QAbstractItemModelPrivate::staticEmptyModel()) { - connect(d->model, SIGNAL(destroyed()), - this, SLOT(_q_modelDestroyed())); - connect(d->model, SIGNAL(dataChanged(QModelIndex, QModelIndex, QList<int>)), this, - SLOT(dataChanged(QModelIndex, QModelIndex, QList<int>))); - connect(d->model, SIGNAL(headerDataChanged(Qt::Orientation,int,int)), - this, SLOT(_q_headerDataChanged())); - connect(d->model, SIGNAL(rowsInserted(QModelIndex,int,int)), - this, SLOT(rowsInserted(QModelIndex,int,int))); - connect(d->model, SIGNAL(rowsInserted(QModelIndex,int,int)), - this, SLOT(_q_rowsInserted(QModelIndex,int,int))); - connect(d->model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)), - this, SLOT(rowsAboutToBeRemoved(QModelIndex,int,int))); - connect(d->model, SIGNAL(rowsRemoved(QModelIndex,int,int)), - this, SLOT(_q_rowsRemoved(QModelIndex,int,int))); - connect(d->model, SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int)), - this, SLOT(_q_rowsMoved(QModelIndex,int,int,QModelIndex,int))); - connect(d->model, SIGNAL(columnsAboutToBeRemoved(QModelIndex,int,int)), - this, SLOT(_q_columnsAboutToBeRemoved(QModelIndex,int,int))); - connect(d->model, SIGNAL(columnsRemoved(QModelIndex,int,int)), - this, SLOT(_q_columnsRemoved(QModelIndex,int,int))); - connect(d->model, SIGNAL(columnsInserted(QModelIndex,int,int)), - this, SLOT(_q_columnsInserted(QModelIndex,int,int))); - connect(d->model, SIGNAL(columnsMoved(QModelIndex,int,int,QModelIndex,int)), - this, SLOT(_q_columnsMoved(QModelIndex,int,int,QModelIndex,int))); - - connect(d->model, SIGNAL(modelReset()), this, SLOT(reset())); - connect(d->model, SIGNAL(layoutChanged()), this, SLOT(_q_layoutChanged())); + d->modelConnections = { + QObjectPrivate::connect(d->model, &QAbstractItemModel::destroyed, + d, &QAbstractItemViewPrivate::modelDestroyed), + QObject::connect(d->model, &QAbstractItemModel::dataChanged, + this, &QAbstractItemView::dataChanged), + QObjectPrivate::connect(d->model, &QAbstractItemModel::headerDataChanged, + d, &QAbstractItemViewPrivate::headerDataChanged), + QObject::connect(d->model, &QAbstractItemModel::rowsInserted, + this, &QAbstractItemView::rowsInserted), + QObjectPrivate::connect(d->model, &QAbstractItemModel::rowsInserted, + d, &QAbstractItemViewPrivate::rowsInserted), + QObject::connect(d->model, &QAbstractItemModel::rowsAboutToBeRemoved, + this, &QAbstractItemView::rowsAboutToBeRemoved), + QObjectPrivate::connect(d->model, &QAbstractItemModel::rowsRemoved, + d, &QAbstractItemViewPrivate::rowsRemoved), + QObjectPrivate::connect(d->model, &QAbstractItemModel::rowsMoved, + d, &QAbstractItemViewPrivate::rowsMoved), + QObjectPrivate::connect(d->model, &QAbstractItemModel::columnsAboutToBeRemoved, + d, &QAbstractItemViewPrivate::columnsAboutToBeRemoved), + QObjectPrivate::connect(d->model, &QAbstractItemModel::columnsRemoved, + d, &QAbstractItemViewPrivate::columnsRemoved), + QObjectPrivate::connect(d->model, &QAbstractItemModel::columnsInserted, + d, &QAbstractItemViewPrivate::columnsInserted), + QObjectPrivate::connect(d->model, &QAbstractItemModel::columnsMoved, + d, &QAbstractItemViewPrivate::columnsMoved), + QObject::connect(d->model, &QAbstractItemModel::modelReset, + this, &QAbstractItemView::reset), + QObjectPrivate::connect(d->model, &QAbstractItemModel::layoutChanged, + d, &QAbstractItemViewPrivate::layoutChanged), + }; } QItemSelectionModel *selection_model = new QItemSelectionModel(d->model, this); - connect(d->model, SIGNAL(destroyed()), selection_model, SLOT(deleteLater())); + connect(d->model, &QAbstractItemModel::destroyed, + selection_model, &QItemSelectionModel::deleteLater); setSelectionModel(selection_model); reset(); // kill editors, set new root and do layout @@ -770,20 +808,19 @@ void QAbstractItemView::setSelectionModel(QItemSelectionModel *selectionModel) oldSelection = d->selectionModel->selection(); oldCurrentIndex = d->selectionModel->currentIndex(); } - - disconnect(d->selectionModel, SIGNAL(selectionChanged(QItemSelection,QItemSelection)), - this, SLOT(selectionChanged(QItemSelection,QItemSelection))); - disconnect(d->selectionModel, SIGNAL(currentChanged(QModelIndex,QModelIndex)), - this, SLOT(currentChanged(QModelIndex,QModelIndex))); + disconnect(d->selectionModel, &QItemSelectionModel::selectionChanged, + this, &QAbstractItemView::selectionChanged); + disconnect(d->selectionModel, &QItemSelectionModel::currentChanged, + this, &QAbstractItemView::currentChanged); } d->selectionModel = selectionModel; if (d->selectionModel) { - connect(d->selectionModel, SIGNAL(selectionChanged(QItemSelection,QItemSelection)), - this, SLOT(selectionChanged(QItemSelection,QItemSelection))); - connect(d->selectionModel, SIGNAL(currentChanged(QModelIndex,QModelIndex)), - this, SLOT(currentChanged(QModelIndex,QModelIndex))); + connect(d->selectionModel, &QItemSelectionModel::selectionChanged, + this, &QAbstractItemView::selectionChanged); + connect(d->selectionModel, &QItemSelectionModel::currentChanged, + this, &QAbstractItemView::currentChanged); selectionChanged(d->selectionModel->selection(), oldSelection); currentChanged(d->selectionModel->currentIndex(), oldCurrentIndex); @@ -823,21 +860,13 @@ void QAbstractItemView::setItemDelegate(QAbstractItemDelegate *delegate) return; if (d->itemDelegate) { - if (d->delegateRefCount(d->itemDelegate) == 1) { - disconnect(d->itemDelegate, SIGNAL(closeEditor(QWidget*,QAbstractItemDelegate::EndEditHint)), - this, SLOT(closeEditor(QWidget*,QAbstractItemDelegate::EndEditHint))); - disconnect(d->itemDelegate, SIGNAL(commitData(QWidget*)), this, SLOT(commitData(QWidget*))); - disconnect(d->itemDelegate, SIGNAL(sizeHintChanged(QModelIndex)), this, SLOT(_q_delegateSizeHintChanged(QModelIndex))); - } + if (d->delegateRefCount(d->itemDelegate) == 1) + d->disconnectDelegate(delegate); } if (delegate) { - if (d->delegateRefCount(delegate) == 0) { - connect(delegate, SIGNAL(closeEditor(QWidget*,QAbstractItemDelegate::EndEditHint)), - this, SLOT(closeEditor(QWidget*,QAbstractItemDelegate::EndEditHint))); - connect(delegate, SIGNAL(commitData(QWidget*)), this, SLOT(commitData(QWidget*))); - connect(delegate, SIGNAL(sizeHintChanged(QModelIndex)), this, SLOT(_q_delegateSizeHintChanged(QModelIndex))); - } + if (d->delegateRefCount(delegate) == 0) + d->connectDelegate(delegate); } d->itemDelegate = delegate; viewport()->update(); @@ -907,21 +936,13 @@ void QAbstractItemView::setItemDelegateForRow(int row, QAbstractItemDelegate *de { Q_D(QAbstractItemView); if (QAbstractItemDelegate *rowDelegate = d->rowDelegates.value(row, nullptr)) { - if (d->delegateRefCount(rowDelegate) == 1) { - disconnect(rowDelegate, SIGNAL(closeEditor(QWidget*,QAbstractItemDelegate::EndEditHint)), - this, SLOT(closeEditor(QWidget*,QAbstractItemDelegate::EndEditHint))); - disconnect(rowDelegate, SIGNAL(commitData(QWidget*)), this, SLOT(commitData(QWidget*))); - disconnect(rowDelegate, SIGNAL(sizeHintChanged(QModelIndex)), this, SLOT(_q_delegateSizeHintChanged(QModelIndex))); - } + if (d->delegateRefCount(rowDelegate) == 1) + d->disconnectDelegate(rowDelegate); d->rowDelegates.remove(row); } if (delegate) { - if (d->delegateRefCount(delegate) == 0) { - connect(delegate, SIGNAL(closeEditor(QWidget*,QAbstractItemDelegate::EndEditHint)), - this, SLOT(closeEditor(QWidget*,QAbstractItemDelegate::EndEditHint))); - connect(delegate, SIGNAL(commitData(QWidget*)), this, SLOT(commitData(QWidget*))); - connect(delegate, SIGNAL(sizeHintChanged(QModelIndex)), this, SLOT(_q_delegateSizeHintChanged(QModelIndex))); - } + if (d->delegateRefCount(delegate) == 0) + d->connectDelegate(delegate); d->rowDelegates.insert(row, delegate); } viewport()->update(); @@ -967,21 +988,13 @@ void QAbstractItemView::setItemDelegateForColumn(int column, QAbstractItemDelega { Q_D(QAbstractItemView); if (QAbstractItemDelegate *columnDelegate = d->columnDelegates.value(column, nullptr)) { - if (d->delegateRefCount(columnDelegate) == 1) { - disconnect(columnDelegate, SIGNAL(closeEditor(QWidget*,QAbstractItemDelegate::EndEditHint)), - this, SLOT(closeEditor(QWidget*,QAbstractItemDelegate::EndEditHint))); - disconnect(columnDelegate, SIGNAL(commitData(QWidget*)), this, SLOT(commitData(QWidget*))); - disconnect(columnDelegate, SIGNAL(sizeHintChanged(QModelIndex)), this, SLOT(_q_delegateSizeHintChanged(QModelIndex))); - } + if (d->delegateRefCount(columnDelegate) == 1) + d->disconnectDelegate(columnDelegate); d->columnDelegates.remove(column); } if (delegate) { - if (d->delegateRefCount(delegate) == 0) { - connect(delegate, SIGNAL(closeEditor(QWidget*,QAbstractItemDelegate::EndEditHint)), - this, SLOT(closeEditor(QWidget*,QAbstractItemDelegate::EndEditHint))); - connect(delegate, SIGNAL(commitData(QWidget*)), this, SLOT(commitData(QWidget*))); - connect(delegate, SIGNAL(sizeHintChanged(QModelIndex)), this, SLOT(_q_delegateSizeHintChanged(QModelIndex))); - } + if (d->delegateRefCount(delegate) == 0) + d->connectDelegate(delegate); d->columnDelegates.insert(column, delegate); } viewport()->update(); @@ -1119,7 +1132,11 @@ void QAbstractItemView::reset() { Q_D(QAbstractItemView); d->delayedReset.stop(); //make sure we stop the timer - foreach (const QEditorInfo &info, d->indexEditorHash) { + // Taking a copy because releaseEditor() eventurally calls deleteLater() on the + // editor, which calls QCoreApplication::postEvent(), the latter may invoke unknown + // code that may modify d->indexEditorHash. + const auto copy = d->indexEditorHash; + for (const auto &[index, info] : copy.asKeyValueRange()) { if (info.widget) d->releaseEditor(info.widget.data(), d->indexForEditor(info.widget.data())); } @@ -1153,6 +1170,12 @@ void QAbstractItemView::setRootIndex(const QModelIndex &index) return; } d->root = index; +#if QT_CONFIG(accessibility) + if (QAccessible::isActive()) { + QAccessibleTableModelChangeEvent accessibleEvent(this, QAccessibleTableModelChangeEvent::ModelReset); + QAccessible::updateAccessibility(&accessibleEvent); + } +#endif d->doDelayedItemsLayout(); d->updateGeometry(); } @@ -1545,7 +1568,7 @@ QAbstractItemView::DragDropMode QAbstractItemView::dragDropMode() const /*! \property QAbstractItemView::defaultDropAction - \brief the drop action that will be used by default in QAbstractItemView::drag() + \brief the drop action that will be used by default in QAbstractItemView::drag(). If the property is not set, the drop action is CopyAction when the supported actions support CopyAction. @@ -1638,7 +1661,7 @@ Qt::TextElideMode QAbstractItemView::textElideMode() const bool QAbstractItemView::focusNextPrevChild(bool next) { Q_D(QAbstractItemView); - if (d->tabKeyNavigation && isEnabled() && d->viewport->isEnabled()) { + if (d->tabKeyNavigation && isVisible() && isEnabled() && d->viewport->isEnabled()) { QKeyEvent event(QEvent::KeyPress, next ? Qt::Key_Tab : Qt::Key_Backtab, Qt::NoModifier); keyPressEvent(&event); if (event.isAccepted()) @@ -1762,7 +1785,10 @@ bool QAbstractItemView::viewportEvent(QEvent *event) case QEvent::ScrollPrepare: executeDelayedItemsLayout(); #if QT_CONFIG(gestures) && QT_CONFIG(scroller) - connect(QScroller::scroller(d->viewport), SIGNAL(stateChanged(QScroller::State)), this, SLOT(_q_scrollerStateChanged()), Qt::UniqueConnection); + d->scollerConnection = QObjectPrivate::connect( + QScroller::scroller(d->viewport), &QScroller::stateChanged, + d, &QAbstractItemViewPrivate::scrollerStateChanged, + Qt::UniqueConnection); #endif break; @@ -1857,7 +1883,6 @@ void QAbstractItemView::mousePressEvent(QMouseEvent *event) void QAbstractItemView::mouseMoveEvent(QMouseEvent *event) { Q_D(QAbstractItemView); - QPoint topLeft; QPoint bottomRight = event->position().toPoint(); d->draggedPosition = bottomRight + d->offset(); @@ -1867,13 +1892,7 @@ void QAbstractItemView::mouseMoveEvent(QMouseEvent *event) #if QT_CONFIG(draganddrop) if (state() == DraggingState) { - topLeft = d->pressedPosition - d->offset(); - if ((topLeft - bottomRight).manhattanLength() > QApplication::startDragDistance()) { - d->pressedIndex = QModelIndex(); - startDrag(d->model->supportedDragActions()); - setState(NoState); // the startDrag will return when the dnd operation is done - stopAutoScroll(); - } + d->maybeStartDrag(bottomRight); return; } #endif // QT_CONFIG(draganddrop) @@ -1884,10 +1903,8 @@ void QAbstractItemView::mouseMoveEvent(QMouseEvent *event) || edit(index, NoEditTriggers, event)) return; - if (d->selectionMode != SingleSelection) - topLeft = d->pressedPosition - d->offset(); - else - topLeft = bottomRight; + const QPoint topLeft = + d->selectionMode != SingleSelection ? d->pressedPosition - d->offset() : bottomRight; d->checkMouseMove(index); @@ -1898,6 +1915,7 @@ void QAbstractItemView::mouseMoveEvent(QMouseEvent *event) && (event->buttons() != Qt::NoButton) && !d->selectedDraggableIndexes().isEmpty()) { setState(DraggingState); + d->maybeStartDrag(bottomRight); return; } #endif @@ -2918,41 +2936,50 @@ void QAbstractItemView::closeEditor(QWidget *editor, QAbstractItemDelegate::EndE // Close the editor if (editor) { - bool isPersistent = d->persistent.contains(editor); - bool hadFocus = editor->hasFocus(); - QModelIndex index = d->indexForEditor(editor); + const bool isPersistent = d->persistent.contains(editor); + const QModelIndex index = d->indexForEditor(editor); if (!index.isValid()) { - qWarning("QAbstractItemView::closeEditor called with an editor that does not belong to this view"); - return; // the editor was not registered - } - - // start a timer that expires immediately when we return to the event loop - // to identify whether this close was triggered by a mousepress-initiated - // focus event - d->pressClosedEditorWatcher.start(0, this); - d->lastEditedIndex = index; - - if (!isPersistent) { - setState(NoState); - QModelIndex index = d->indexForEditor(editor); - editor->removeEventFilter(itemDelegateForIndex(index)); - d->removeEditor(editor); - } - if (hadFocus) { - if (focusPolicy() != Qt::NoFocus) - setFocus(); // this will send a focusLost event to the editor - else - editor->clearFocus(); + if (!editor->isVisible()) { + // The commit might have removed the index (e.g. it might get filtered), in + // which case the editor is already hidden and scheduled for deletion. We + // don't have to do anything, except reset the state, and continue with + // EndEditHint processing. + if (!isPersistent) + setState(NoState); + } else { + qWarning("QAbstractItemView::closeEditor called with an editor that does not belong to this view"); + return; + } } else { - d->checkPersistentEditorFocus(); - } + const bool hadFocus = editor->hasFocus(); + // start a timer that expires immediately when we return to the event loop + // to identify whether this close was triggered by a mousepress-initiated + // focus event + d->pressClosedEditorWatcher.start(0, this); + d->lastEditedIndex = index; + + if (!isPersistent) { + setState(NoState); + QModelIndex index = d->indexForEditor(editor); + editor->removeEventFilter(itemDelegateForIndex(index)); + d->removeEditor(editor); + } + if (hadFocus) { + if (focusPolicy() != Qt::NoFocus) + setFocus(); // this will send a focusLost event to the editor + else + editor->clearFocus(); + } else { + d->checkPersistentEditorFocus(); + } - QPointer<QWidget> ed = editor; - QCoreApplication::sendPostedEvents(editor, 0); - editor = ed; + QPointer<QWidget> ed = editor; + QCoreApplication::sendPostedEvents(editor, 0); + editor = ed; - if (!isPersistent && editor) - d->releaseEditor(editor, index); + if (!isPersistent && editor) + d->releaseEditor(editor, index); + } } // The EndEditHint part @@ -3354,7 +3381,7 @@ void QAbstractItemView::update(const QModelIndex &index) { Q_D(QAbstractItemView); if (index.isValid()) { - const QRect rect = visualRect(index); + const QRect rect = d->visualRect(index); //this test is important for performance reason //For example in dataChanged we simply update all the cells without checking //it can be a major bottleneck to update rects that aren't even part of the viewport @@ -3505,10 +3532,21 @@ void QAbstractItemView::rowsAboutToBeRemoved(const QModelIndex &parent, int star } // Remove all affected editors; this is more efficient than waiting for updateGeometries() to clean out editors for invalid indexes + const auto findDirectChildOf = [](const QModelIndex &parent, QModelIndex child) + { + while (child.isValid()) { + const auto parentIndex = child.parent(); + if (parentIndex == parent) + return child; + child = parentIndex; + } + return QModelIndex(); + }; QEditorIndexHash::iterator i = d->editorIndexHash.begin(); while (i != d->editorIndexHash.end()) { const QModelIndex index = i.value(); - if (index.row() >= start && index.row() <= end && d->model->parent(index) == parent) { + const QModelIndex directChild = findDirectChildOf(parent, index); + if (directChild.isValid() && directChild.row() >= start && directChild.row() <= end) { QWidget *editor = i.key(); QEditorInfo info = d->indexEditorHash.take(index); i = d->editorIndexHash.erase(i); @@ -3527,7 +3565,7 @@ void QAbstractItemView::rowsAboutToBeRemoved(const QModelIndex &parent, int star rows are those under the given \a parent from \a start to \a end inclusive. */ -void QAbstractItemViewPrivate::_q_rowsRemoved(const QModelIndex &index, int start, int end) +void QAbstractItemViewPrivate::rowsRemoved(const QModelIndex &index, int start, int end) { Q_UNUSED(index); Q_UNUSED(start); @@ -3555,7 +3593,7 @@ void QAbstractItemViewPrivate::_q_rowsRemoved(const QModelIndex &index, int star columns are those under the given \a parent from \a start to \a end inclusive. */ -void QAbstractItemViewPrivate::_q_columnsAboutToBeRemoved(const QModelIndex &parent, int start, int end) +void QAbstractItemViewPrivate::columnsAboutToBeRemoved(const QModelIndex &parent, int start, int end) { Q_Q(QAbstractItemView); @@ -3618,7 +3656,7 @@ void QAbstractItemViewPrivate::_q_columnsAboutToBeRemoved(const QModelIndex &par rows are those under the given \a parent from \a start to \a end inclusive. */ -void QAbstractItemViewPrivate::_q_columnsRemoved(const QModelIndex &index, int start, int end) +void QAbstractItemViewPrivate::columnsRemoved(const QModelIndex &index, int start, int end) { Q_UNUSED(index); Q_UNUSED(start); @@ -3645,7 +3683,7 @@ void QAbstractItemViewPrivate::_q_columnsRemoved(const QModelIndex &index, int s This slot is called when rows have been inserted. */ -void QAbstractItemViewPrivate::_q_rowsInserted(const QModelIndex &index, int start, int end) +void QAbstractItemViewPrivate::rowsInserted(const QModelIndex &index, int start, int end) { Q_UNUSED(index); Q_UNUSED(start); @@ -3668,7 +3706,7 @@ void QAbstractItemViewPrivate::_q_rowsInserted(const QModelIndex &index, int sta This slot is called when columns have been inserted. */ -void QAbstractItemViewPrivate::_q_columnsInserted(const QModelIndex &index, int start, int end) +void QAbstractItemViewPrivate::columnsInserted(const QModelIndex &index, int start, int end) { Q_UNUSED(index); Q_UNUSED(start); @@ -3691,7 +3729,7 @@ void QAbstractItemViewPrivate::_q_columnsInserted(const QModelIndex &index, int /*! \internal */ -void QAbstractItemViewPrivate::_q_modelDestroyed() +void QAbstractItemViewPrivate::modelDestroyed() { model = QAbstractItemModelPrivate::staticEmptyModel(); doDelayedReset(); @@ -3702,7 +3740,7 @@ void QAbstractItemViewPrivate::_q_modelDestroyed() This slot is called when the layout is changed. */ -void QAbstractItemViewPrivate::_q_layoutChanged() +void QAbstractItemViewPrivate::layoutChanged() { doDelayedItemsLayout(); #if QT_CONFIG(accessibility) @@ -3714,14 +3752,14 @@ void QAbstractItemViewPrivate::_q_layoutChanged() #endif } -void QAbstractItemViewPrivate::_q_rowsMoved(const QModelIndex &, int, int, const QModelIndex &, int) +void QAbstractItemViewPrivate::rowsMoved(const QModelIndex &, int, int, const QModelIndex &, int) { - _q_layoutChanged(); + layoutChanged(); } -void QAbstractItemViewPrivate::_q_columnsMoved(const QModelIndex &, int, int, const QModelIndex &, int) +void QAbstractItemViewPrivate::columnsMoved(const QModelIndex &, int, int, const QModelIndex &, int) { - _q_layoutChanged(); + layoutChanged(); } QRect QAbstractItemViewPrivate::intersectedRect(const QRect rect, const QModelIndex &topLeft, const QModelIndex &bottomRight) const @@ -4263,6 +4301,7 @@ QItemSelectionModel::SelectionFlags QAbstractItemViewPrivate::extendedSelectionC default: break; } + break; } default: break; @@ -4431,7 +4470,7 @@ QWidget *QAbstractItemViewPrivate::editor(const QModelIndex &index, w = delegate->createEditor(viewport, options, index); if (w) { w->installEventFilter(delegate); - QObject::connect(w, SIGNAL(destroyed(QObject*)), q, SLOT(editorDestroyed(QObject*))); + QObject::connect(w, &QWidget::destroyed, q, &QAbstractItemView::editorDestroyed); delegate->updateEditorGeometry(w, options, index); delegate->setEditorData(w, index); addEditor(index, w, false); @@ -4568,6 +4607,9 @@ QModelIndex QAbstractItemViewPrivate::indexForEditor(QWidget *editor) const void QAbstractItemViewPrivate::removeEditor(QWidget *editor) { + Q_Q(QAbstractItemView); + if (editor) + QObject::disconnect(editor, &QWidget::destroyed, q, &QAbstractItemView::editorDestroyed); const auto it = editorIndexHash.constFind(editor); if (it != editorIndexHash.cend()) { indexEditorHash.remove(it.value()); @@ -4701,6 +4743,20 @@ QModelIndexList QAbstractItemViewPrivate::selectedDraggableIndexes() const indexes.removeIf(isNotDragEnabled); return indexes; } + +void QAbstractItemViewPrivate::maybeStartDrag(QPoint eventPosition) +{ + Q_Q(QAbstractItemView); + + const QPoint topLeft = pressedPosition - offset(); + if ((topLeft - eventPosition).manhattanLength() > QApplication::startDragDistance()) { + pressedIndex = QModelIndex(); + q->startDrag(model->supportedDragActions()); + q->setState(QAbstractItemView::NoState); // the startDrag will return when the dnd operation + // is done + q->stopAutoScroll(); + } +} #endif /*! |