summaryrefslogtreecommitdiffstats
path: root/src/widgets/itemviews
diff options
context:
space:
mode:
Diffstat (limited to 'src/widgets/itemviews')
-rw-r--r--src/widgets/itemviews/qabstractitemdelegate.cpp10
-rw-r--r--src/widgets/itemviews/qabstractitemview.cpp461
-rw-r--r--src/widgets/itemviews/qabstractitemview.h14
-rw-r--r--src/widgets/itemviews/qabstractitemview_p.h53
-rw-r--r--src/widgets/itemviews/qcolumnview.cpp82
-rw-r--r--src/widgets/itemviews/qcolumnview.h3
-rw-r--r--src/widgets/itemviews/qcolumnview_p.h17
-rw-r--r--src/widgets/itemviews/qdatawidgetmapper.cpp73
-rw-r--r--src/widgets/itemviews/qdatawidgetmapper.h6
-rw-r--r--src/widgets/itemviews/qheaderview.cpp201
-rw-r--r--src/widgets/itemviews/qheaderview.h10
-rw-r--r--src/widgets/itemviews/qheaderview_p.h32
-rw-r--r--src/widgets/itemviews/qitemdelegate.cpp36
-rw-r--r--src/widgets/itemviews/qitemeditorfactory.cpp8
-rw-r--r--src/widgets/itemviews/qlistview.cpp26
-rw-r--r--src/widgets/itemviews/qlistview_p.h1
-rw-r--r--src/widgets/itemviews/qlistwidget.cpp167
-rw-r--r--src/widgets/itemviews/qlistwidget.h10
-rw-r--r--src/widgets/itemviews/qlistwidget_p.h25
-rw-r--r--src/widgets/itemviews/qstyleditemdelegate.cpp34
-rw-r--r--src/widgets/itemviews/qtableview.cpp226
-rw-r--r--src/widgets/itemviews/qtableview.h7
-rw-r--r--src/widgets/itemviews/qtableview_p.h32
-rw-r--r--src/widgets/itemviews/qtablewidget.cpp88
-rw-r--r--src/widgets/itemviews/qtablewidget.h16
-rw-r--r--src/widgets/itemviews/qtablewidget_p.h30
-rw-r--r--src/widgets/itemviews/qtreeview.cpp306
-rw-r--r--src/widgets/itemviews/qtreeview.h5
-rw-r--r--src/widgets/itemviews/qtreeview_p.h42
-rw-r--r--src/widgets/itemviews/qtreewidget.cpp90
-rw-r--r--src/widgets/itemviews/qtreewidget.h13
-rw-r--r--src/widgets/itemviews/qtreewidget_p.h29
-rw-r--r--src/widgets/itemviews/qwidgetitemdata_p.h1
33 files changed, 1212 insertions, 942 deletions
diff --git a/src/widgets/itemviews/qabstractitemdelegate.cpp b/src/widgets/itemviews/qabstractitemdelegate.cpp
index 73af3b6b1d..23e8ef0901 100644
--- a/src/widgets/itemviews/qabstractitemdelegate.cpp
+++ b/src/widgets/itemviews/qabstractitemdelegate.cpp
@@ -81,7 +81,7 @@ QT_BEGIN_NAMESPACE
The second approach is to handle user events directly by reimplementing
editorEvent().
- \sa {model-view-programming}{Model/View Programming}, {Pixelator Example},
+ \sa {model-view-programming}{Model/View Programming},
QStyledItemDelegate, QStyle
*/
@@ -514,6 +514,14 @@ bool QAbstractItemDelegatePrivate::tryFixup(QWidget *editor)
return e->hasAcceptableInput();
}
}
+#endif
+#if QT_CONFIG(spinbox)
+ // Give a chance to the spinbox to interpret the text and emit
+ // the appropriate signals before committing data.
+ if (QAbstractSpinBox *sb = qobject_cast<QAbstractSpinBox *>(editor)) {
+ if (!sb->keyboardTracking())
+ sb->interpretText();
+ }
#else
Q_UNUSED(editor);
#endif // QT_CONFIG(lineedit)
diff --git a/src/widgets/itemviews/qabstractitemview.cpp b/src/widgets/itemviews/qabstractitemview.cpp
index 7a7b5c4753..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())
@@ -1709,6 +1732,12 @@ bool QAbstractItemView::viewportEvent(QEvent *event)
{
Q_D(QAbstractItemView);
switch (event->type()) {
+ case QEvent::Paint:
+ // Similar to pre-painting in QAbstractItemView::event to update scrollbar
+ // visibility, make sure that all pending layout requests have been executed
+ // so that the view's data structures are up-to-date before rendering.
+ d->executePostedLayout();
+ break;
case QEvent::HoverMove:
case QEvent::HoverEnter:
d->setHoverIndex(indexAt(static_cast<QHoverEvent*>(event)->position().toPoint()));
@@ -1756,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;
@@ -1793,9 +1825,11 @@ void QAbstractItemView::mousePressEvent(QMouseEvent *event)
QPoint offset = d->offset();
d->draggedPosition = pos + offset;
+#if QT_CONFIG(draganddrop)
// update the pressed position when drag was enable
if (d->dragEnabled)
d->pressedPosition = d->draggedPosition;
+#endif
if (!(command & QItemSelectionModel::Current)) {
d->pressedPosition = pos + offset;
@@ -1849,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();
@@ -1859,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)
@@ -1876,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);
@@ -1890,6 +1915,7 @@ void QAbstractItemView::mouseMoveEvent(QMouseEvent *event)
&& (event->buttons() != Qt::NoButton)
&& !d->selectedDraggableIndexes().isEmpty()) {
setState(DraggingState);
+ d->maybeStartDrag(bottomRight);
return;
}
#endif
@@ -1939,7 +1965,9 @@ void QAbstractItemView::mouseReleaseEvent(QMouseEvent *event)
}
bool click = (index == d->pressedIndex && index.isValid() && !releaseFromDoubleClick);
- bool selectedClicked = click && (event->button() == Qt::LeftButton) && d->pressedAlreadySelected;
+ bool selectedClicked = click && d->pressedAlreadySelected
+ && (event->button() == Qt::LeftButton)
+ && (event->modifiers() == Qt::NoModifier);
EditTrigger trigger = (selectedClicked ? SelectedClicked : NoEditTriggers);
const bool edited = click && !d->pressClosedEditor ? edit(index, trigger, event) : false;
@@ -1947,7 +1975,7 @@ void QAbstractItemView::mouseReleaseEvent(QMouseEvent *event)
if (d->selectionModel && d->noSelectionOnMousePress) {
d->noSelectionOnMousePress = false;
- if (!edited && !d->pressClosedEditor)
+ if (!d->pressClosedEditor)
d->selectionModel->select(index, selectionCommand(index, event));
}
@@ -2366,11 +2394,12 @@ void QAbstractItemView::keyPressEvent(QKeyEvent *event)
#if !defined(QT_NO_CLIPBOARD) && !defined(QT_NO_SHORTCUT)
if (event == QKeySequence::Copy) {
- QVariant variant;
- if (d->model)
- variant = d->model->data(currentIndex(), Qt::DisplayRole);
- if (variant.canConvert<QString>())
- QGuiApplication::clipboard()->setText(variant.toString());
+ const QModelIndex index = currentIndex();
+ if (index.isValid() && d->model) {
+ const QVariant variant = d->model->data(index, Qt::DisplayRole);
+ if (variant.canConvert<QString>())
+ QGuiApplication::clipboard()->setText(variant.toString());
+ }
event->accept();
}
#endif
@@ -2907,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
@@ -3343,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
@@ -3494,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);
@@ -3516,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);
@@ -3544,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);
@@ -3607,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);
@@ -3634,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);
@@ -3657,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);
@@ -3680,7 +3729,7 @@ void QAbstractItemViewPrivate::_q_columnsInserted(const QModelIndex &index, int
/*!
\internal
*/
-void QAbstractItemViewPrivate::_q_modelDestroyed()
+void QAbstractItemViewPrivate::modelDestroyed()
{
model = QAbstractItemModelPrivate::staticEmptyModel();
doDelayedReset();
@@ -3691,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)
@@ -3703,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
@@ -4091,8 +4140,12 @@ QItemSelectionModel::SelectionFlags QAbstractItemView::selectionCommand(const QM
if (d->pressedAlreadySelected)
return QItemSelectionModel::NoUpdate;
break;
- case QEvent::KeyPress:
case QEvent::MouseButtonRelease:
+ // clicking into area with no items does nothing
+ if (!index.isValid())
+ return QItemSelectionModel::NoUpdate;
+ Q_FALLTHROUGH();
+ case QEvent::KeyPress:
// ctrl-release on selected item deselects
if ((keyModifiers & Qt::ControlModifier) && d->selectionModel->isSelected(index))
return QItemSelectionModel::Deselect | d->selectionBehaviorFlags();
@@ -4127,13 +4180,21 @@ QItemSelectionModel::SelectionFlags QAbstractItemViewPrivate::multiSelectionComm
case QEvent::MouseButtonPress:
if (static_cast<const QMouseEvent*>(event)->button() == Qt::LeftButton) {
// since the press might start a drag, deselect only on release
- if (!pressedAlreadySelected || !dragEnabled || !isIndexDragEnabled(index))
+ if (!pressedAlreadySelected
+#if QT_CONFIG(draganddrop)
+ || !dragEnabled || !isIndexDragEnabled(index)
+#endif
+ )
return QItemSelectionModel::Toggle|selectionBehaviorFlags(); // toggle
}
break;
case QEvent::MouseButtonRelease:
if (static_cast<const QMouseEvent*>(event)->button() == Qt::LeftButton) {
- if (pressedAlreadySelected && dragEnabled && isIndexDragEnabled(index) && index == pressedIndex)
+ if (pressedAlreadySelected
+#if QT_CONFIG(draganddrop)
+ && dragEnabled && isIndexDragEnabled(index)
+#endif
+ && index == pressedIndex)
return QItemSelectionModel::Toggle|selectionBehaviorFlags();
return QItemSelectionModel::NoUpdate|selectionBehaviorFlags(); // finalize
}
@@ -4181,7 +4242,10 @@ QItemSelectionModel::SelectionFlags QAbstractItemViewPrivate::extendedSelectionC
return QItemSelectionModel::NoUpdate;
// since the press might start a drag, deselect only on release
if (controlKeyPressed && !rightButtonPressed && pressedAlreadySelected
- && dragEnabled && isIndexDragEnabled(index)) {
+#if QT_CONFIG(draganddrop)
+ && dragEnabled && isIndexDragEnabled(index)
+#endif
+ ) {
return QItemSelectionModel::NoUpdate;
}
break;
@@ -4197,7 +4261,10 @@ QItemSelectionModel::SelectionFlags QAbstractItemViewPrivate::extendedSelectionC
&& !shiftKeyPressed && !controlKeyPressed && (!rightButtonPressed || !index.isValid()))
return QItemSelectionModel::ClearAndSelect|selectionBehaviorFlags();
if (index == pressedIndex && controlKeyPressed && !rightButtonPressed
- && dragEnabled && isIndexDragEnabled(index)) {
+#if QT_CONFIG(draganddrop)
+ && dragEnabled && isIndexDragEnabled(index)
+#endif
+ ) {
break;
}
return QItemSelectionModel::NoUpdate;
@@ -4234,6 +4301,7 @@ QItemSelectionModel::SelectionFlags QAbstractItemViewPrivate::extendedSelectionC
default:
break;
}
+ break;
}
default:
break;
@@ -4402,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);
@@ -4539,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());
@@ -4661,6 +4732,7 @@ void QAbstractItemViewPrivate::selectAll(QItemSelectionModel::SelectionFlags com
selectionModel->select(selection, command);
}
+#if QT_CONFIG(draganddrop)
QModelIndexList QAbstractItemViewPrivate::selectedDraggableIndexes() const
{
Q_Q(const QAbstractItemView);
@@ -4672,6 +4744,21 @@ QModelIndexList QAbstractItemViewPrivate::selectedDraggableIndexes() const
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
+
/*!
\reimp
*/
diff --git a/src/widgets/itemviews/qabstractitemview.h b/src/widgets/itemviews/qabstractitemview.h
index d5a433943a..837419100a 100644
--- a/src/widgets/itemviews/qabstractitemview.h
+++ b/src/widgets/itemviews/qabstractitemview.h
@@ -326,20 +326,6 @@ protected:
private:
Q_DECLARE_PRIVATE(QAbstractItemView)
Q_DISABLE_COPY(QAbstractItemView)
- Q_PRIVATE_SLOT(d_func(), void _q_columnsAboutToBeRemoved(const QModelIndex&, int, int))
- Q_PRIVATE_SLOT(d_func(), void _q_columnsRemoved(const QModelIndex&, int, int))
- Q_PRIVATE_SLOT(d_func(), void _q_columnsInserted(const QModelIndex&, int, int))
- Q_PRIVATE_SLOT(d_func(), void _q_rowsInserted(const QModelIndex&, int, int))
- Q_PRIVATE_SLOT(d_func(), void _q_rowsRemoved(const QModelIndex&, int, int))
- Q_PRIVATE_SLOT(d_func(), void _q_columnsMoved(const QModelIndex&, int, int, const QModelIndex&, int))
- Q_PRIVATE_SLOT(d_func(), void _q_rowsMoved(const QModelIndex&, int, int, const QModelIndex&, int))
- Q_PRIVATE_SLOT(d_func(), void _q_modelDestroyed())
- Q_PRIVATE_SLOT(d_func(), void _q_layoutChanged())
- Q_PRIVATE_SLOT(d_func(), void _q_headerDataChanged())
-#if QT_CONFIG(gestures) && QT_CONFIG(scroller)
- Q_PRIVATE_SLOT(d_func(), void _q_scrollerStateChanged())
-#endif
- Q_PRIVATE_SLOT(d_func(), void _q_delegateSizeHintChanged(const QModelIndex&))
friend class ::tst_QAbstractItemView;
friend class ::tst_QTreeView;
diff --git a/src/widgets/itemviews/qabstractitemview_p.h b/src/widgets/itemviews/qabstractitemview_p.h
index 257e368175..433429f48b 100644
--- a/src/widgets/itemviews/qabstractitemview_p.h
+++ b/src/widgets/itemviews/qabstractitemview_p.h
@@ -16,17 +16,22 @@
//
#include <QtWidgets/private/qtwidgetsglobal_p.h>
+#include "qabstractitemview.h"
#include "private/qabstractscrollarea_p.h"
#include "private/qabstractitemmodel_p.h"
#include "QtWidgets/qapplication.h"
#include "QtGui/qevent.h"
#include "QtCore/qmimedata.h"
#include "QtGui/qpainter.h"
-#include "QtCore/qpair.h"
#include "QtGui/qregion.h"
+
#include "QtCore/qdebug.h"
#include "QtCore/qbasictimer.h"
#include "QtCore/qelapsedtimer.h"
+#include <QtCore/qpointer.h>
+
+
+#include <array>
QT_REQUIRE_CONFIG(itemviews);
@@ -63,20 +68,20 @@ public:
void init();
- virtual void _q_rowsRemoved(const QModelIndex &parent, int start, int end);
- virtual void _q_rowsInserted(const QModelIndex &parent, int start, int end);
- virtual void _q_columnsAboutToBeRemoved(const QModelIndex &parent, int start, int end);
- virtual void _q_columnsRemoved(const QModelIndex &parent, int start, int end);
- virtual void _q_columnsInserted(const QModelIndex &parent, int start, int end);
- virtual void _q_modelDestroyed();
- virtual void _q_layoutChanged();
- virtual void _q_rowsMoved(const QModelIndex &source, int sourceStart, int sourceEnd, const QModelIndex &destination, int destinationStart);
- virtual void _q_columnsMoved(const QModelIndex &source, int sourceStart, int sourceEnd, const QModelIndex &destination, int destinationStart);
+ virtual void rowsRemoved(const QModelIndex &parent, int start, int end);
+ virtual void rowsInserted(const QModelIndex &parent, int start, int end);
+ virtual void columnsAboutToBeRemoved(const QModelIndex &parent, int start, int end);
+ virtual void columnsRemoved(const QModelIndex &parent, int start, int end);
+ virtual void columnsInserted(const QModelIndex &parent, int start, int end);
+ virtual void modelDestroyed();
+ virtual void layoutChanged();
+ virtual void rowsMoved(const QModelIndex &source, int sourceStart, int sourceEnd, const QModelIndex &destination, int destinationStart);
+ virtual void columnsMoved(const QModelIndex &source, int sourceStart, int sourceEnd, const QModelIndex &destination, int destinationStart);
virtual QRect intersectedRect(const QRect rect, const QModelIndex &topLeft, const QModelIndex &bottomRight) const;
- void _q_headerDataChanged() { doDelayedItemsLayout(); }
- void _q_scrollerStateChanged();
- void _q_delegateSizeHintChanged(const QModelIndex &index);
+ void headerDataChanged() { doDelayedItemsLayout(); }
+ void scrollerStateChanged();
+ void delegateSizeHintChanged(const QModelIndex &index);
void fetchMore();
@@ -178,8 +183,8 @@ public:
inline void releaseEditor(QWidget *editor, const QModelIndex &index = QModelIndex()) const {
if (editor) {
Q_Q(const QAbstractItemView);
- QObject::disconnect(editor, SIGNAL(destroyed(QObject*)),
- q_func(), SLOT(editorDestroyed(QObject*)));
+ QObject::disconnect(editor, &QWidget::destroyed,
+ q, &QAbstractItemView::editorDestroyed);
editor->removeEventFilter(itemDelegate);
editor->hide();
QAbstractItemDelegate *delegate = q->itemDelegateForIndex(index);
@@ -252,12 +257,14 @@ public:
inline bool isIndexEnabled(const QModelIndex &index) const {
return (model->flags(index) & Qt::ItemIsEnabled);
}
+#if QT_CONFIG(draganddrop)
inline bool isIndexDropEnabled(const QModelIndex &index) const {
return (model->flags(index) & Qt::ItemIsDropEnabled);
}
inline bool isIndexDragEnabled(const QModelIndex &index) const {
return (model->flags(index) & Qt::ItemIsDragEnabled);
}
+#endif
virtual bool selectionAllowed(const QModelIndex &index) const {
// in some views we want to go ahead with selections, even if the index is invalid
@@ -304,13 +311,16 @@ public:
return static_cast<QAbstractItemModelPrivate *>(model->d_ptr.data())->persistent.indexes.contains(index);
}
+#if QT_CONFIG(draganddrop)
QModelIndexList selectedDraggableIndexes() const;
+ void maybeStartDrag(QPoint eventPoint);
+#endif
void doDelayedReset()
{
//we delay the reset of the timer because some views (QTableView)
//with headers can't handle the fact that the model has been destroyed
- //all _q_modelDestroyed slots must have been called
+ //all modelDestroyed() slots must have been called
if (!delayedReset.isActive())
delayedReset.start(0, q_func());
}
@@ -411,7 +421,18 @@ public:
bool verticalScrollModeSet;
bool horizontalScrollModeSet;
+ virtual QRect visualRect(const QModelIndex &index) const { return q_func()->visualRect(index); }
+
+ std::array<QMetaObject::Connection, 14> modelConnections;
+ std::array<QMetaObject::Connection, 4> scrollbarConnections;
+#if QT_CONFIG(gestures) && QT_CONFIG(scroller)
+ QMetaObject::Connection scollerConnection;
+#endif
+
private:
+ void connectDelegate(QAbstractItemDelegate *delegate);
+ void disconnectDelegate(QAbstractItemDelegate *delegate);
+ void disconnectAll();
inline QAbstractItemDelegate *delegateForIndex(const QModelIndex &index) const {
QMap<int, QPointer<QAbstractItemDelegate> >::ConstIterator it;
diff --git a/src/widgets/itemviews/qcolumnview.cpp b/src/widgets/itemviews/qcolumnview.cpp
index 040bddb311..04bc8f5f88 100644
--- a/src/widgets/itemviews/qcolumnview.cpp
+++ b/src/widgets/itemviews/qcolumnview.cpp
@@ -68,7 +68,9 @@ void QColumnViewPrivate::initialize()
Q_Q(QColumnView);
q->setTextElideMode(Qt::ElideMiddle);
#if QT_CONFIG(animation)
- QObject::connect(&currentAnimation, SIGNAL(finished()), q, SLOT(_q_changeCurrentColumn()));
+ animationConnection =
+ QObjectPrivate::connect(&currentAnimation, &QPropertyAnimation::finished,
+ this, &QColumnViewPrivate::changeCurrentColumn);
currentAnimation.setTargetObject(hbar);
currentAnimation.setPropertyName("value");
currentAnimation.setEasingCurve(QEasingCurve::InOutQuad);
@@ -77,11 +79,26 @@ void QColumnViewPrivate::initialize()
q->setItemDelegate(new QColumnViewDelegate(q));
}
+void QColumnViewPrivate::clearConnections()
+{
+#if QT_CONFIG(animation)
+ QObject::disconnect(animationConnection);
+#endif
+ for (const QMetaObject::Connection &connection : gripConnections)
+ QObject::disconnect(connection);
+ const auto copy = viewConnections; // disconnectView modifies this container
+ for (auto it = copy.keyBegin(); it != copy.keyEnd(); ++it)
+ disconnectView(*it);
+}
+
+
/*!
Destroys the column view.
*/
QColumnView::~QColumnView()
{
+ Q_D(QColumnView);
+ d->clearConnections();
}
/*!
@@ -98,12 +115,15 @@ void QColumnView::setResizeGripsVisible(bool visible)
if (d->showResizeGrips == visible)
return;
d->showResizeGrips = visible;
- for (int i = 0; i < d->columns.size(); ++i) {
- QAbstractItemView *view = d->columns[i];
+ d->gripConnections.clear();
+ for (QAbstractItemView *view : std::as_const(d->columns)) {
if (visible) {
QColumnViewGrip *grip = new QColumnViewGrip(view);
view->setCornerWidget(grip);
- connect(grip, SIGNAL(gripMoved(int)), this, SLOT(_q_gripMoved(int)));
+ d->gripConnections.push_back(
+ QObjectPrivate::connect(grip, &QColumnViewGrip::gripMoved,
+ d, &QColumnViewPrivate::gripMoved)
+ );
} else {
QWidget *widget = view->cornerWidget();
view->setCornerWidget(nullptr);
@@ -267,7 +287,7 @@ void QColumnView::scrollTo(const QModelIndex &index, ScrollHint hint)
if (leftEdge > -horizontalOffset()
&& rightEdge <= ( -horizontalOffset() + viewport()->size().width())) {
d->columns.at(indexColumn)->scrollTo(index);
- d->_q_changeCurrentColumn();
+ d->changeCurrentColumn();
return;
}
@@ -486,7 +506,7 @@ QSize QColumnView::sizeHint() const
\internal
Move all widgets from the corner grip and to the right
*/
-void QColumnViewPrivate::_q_gripMoved(int offset)
+void QColumnViewPrivate::gripMoved(int offset)
{
Q_Q(QColumnView);
@@ -578,8 +598,10 @@ void QColumnViewPrivate::closeColumns(const QModelIndex &parent, bool build)
QAbstractItemView* notShownAnymore = columns.at(i);
columns.removeAt(i);
notShownAnymore->setVisible(false);
- if (notShownAnymore != previewColumn)
+ if (notShownAnymore != previewColumn) {
notShownAnymore->deleteLater();
+ disconnectView(notShownAnymore);
+ }
}
if (columns.isEmpty()) {
@@ -598,7 +620,17 @@ void QColumnViewPrivate::closeColumns(const QModelIndex &parent, bool build)
createColumn(parent, false);
}
-void QColumnViewPrivate::_q_clicked(const QModelIndex &index)
+void QColumnViewPrivate::disconnectView(QAbstractItemView *view)
+{
+ const auto it = viewConnections.find(view);
+ if (it == viewConnections.end())
+ return;
+ for (const QMetaObject::Connection &connection : it.value())
+ QObject::disconnect(connection);
+ viewConnections.erase(it);
+}
+
+void QColumnViewPrivate::clicked(const QModelIndex &index)
{
Q_Q(QColumnView);
QModelIndex parent = index.parent();
@@ -631,10 +663,11 @@ QAbstractItemView *QColumnViewPrivate::createColumn(const QModelIndex &index, bo
{
Q_Q(QColumnView);
QAbstractItemView *view = nullptr;
+ QMetaObject::Connection clickedConnection;
if (model->hasChildren(index)) {
view = q->createColumn(index);
- q->connect(view, SIGNAL(clicked(QModelIndex)),
- q, SLOT(_q_clicked(QModelIndex)));
+ clickedConnection = QObjectPrivate::connect(view, &QAbstractItemView::clicked,
+ this, &QColumnViewPrivate::clicked);
} else {
if (!previewColumn)
setPreviewWidget(new QWidget(q));
@@ -642,16 +675,14 @@ QAbstractItemView *QColumnViewPrivate::createColumn(const QModelIndex &index, bo
view->setMinimumWidth(qMax(view->minimumWidth(), previewWidget->minimumWidth()));
}
- q->connect(view, SIGNAL(activated(QModelIndex)),
- q, SIGNAL(activated(QModelIndex)));
- q->connect(view, SIGNAL(clicked(QModelIndex)),
- q, SIGNAL(clicked(QModelIndex)));
- q->connect(view, SIGNAL(doubleClicked(QModelIndex)),
- q, SIGNAL(doubleClicked(QModelIndex)));
- q->connect(view, SIGNAL(entered(QModelIndex)),
- q, SIGNAL(entered(QModelIndex)));
- q->connect(view, SIGNAL(pressed(QModelIndex)),
- q, SIGNAL(pressed(QModelIndex)));
+ viewConnections[view] = {
+ QObject::connect(view, &QAbstractItemView::activated, q, &QColumnView::activated),
+ QObject::connect(view, &QAbstractItemView::clicked, q, &QColumnView::clicked),
+ QObject::connect(view, &QAbstractItemView::doubleClicked, q, &QColumnView::doubleClicked),
+ QObject::connect(view, &QAbstractItemView::entered, q, &QColumnView::entered),
+ QObject::connect(view, &QAbstractItemView::pressed, q, &QColumnView::pressed),
+ clickedConnection
+ };
view->setFocusPolicy(Qt::NoFocus);
view->setParent(viewport);
@@ -661,7 +692,10 @@ QAbstractItemView *QColumnViewPrivate::createColumn(const QModelIndex &index, bo
if (showResizeGrips) {
QColumnViewGrip *grip = new QColumnViewGrip(view);
view->setCornerWidget(grip);
- q->connect(grip, SIGNAL(gripMoved(int)), q, SLOT(_q_gripMoved(int)));
+ gripConnections.push_back(
+ QObjectPrivate::connect(grip, &QColumnViewGrip::gripMoved,
+ this, &QColumnViewPrivate::gripMoved)
+ );
}
if (columnSizes.size() > columns.size()) {
@@ -915,7 +949,7 @@ void QColumnView::currentChanged(const QModelIndex &current, const QModelIndex &
We have change the current column and need to update focus and selection models
on the new current column.
*/
-void QColumnViewPrivate::_q_changeCurrentColumn()
+void QColumnViewPrivate::changeCurrentColumn()
{
Q_Q(QColumnView);
if (columns.isEmpty())
@@ -1022,9 +1056,9 @@ QColumnViewPrivate::~QColumnViewPrivate()
\internal
*/
-void QColumnViewPrivate::_q_columnsInserted(const QModelIndex &parent, int start, int end)
+void QColumnViewPrivate::columnsInserted(const QModelIndex &parent, int start, int end)
{
- QAbstractItemViewPrivate::_q_columnsInserted(parent, start, end);
+ QAbstractItemViewPrivate::columnsInserted(parent, start, end);
checkColumnCreation(parent);
}
diff --git a/src/widgets/itemviews/qcolumnview.h b/src/widgets/itemviews/qcolumnview.h
index 25b15b5273..c0c1398692 100644
--- a/src/widgets/itemviews/qcolumnview.h
+++ b/src/widgets/itemviews/qcolumnview.h
@@ -67,9 +67,6 @@ protected:
private:
Q_DECLARE_PRIVATE(QColumnView)
Q_DISABLE_COPY(QColumnView)
- Q_PRIVATE_SLOT(d_func(), void _q_gripMoved(int))
- Q_PRIVATE_SLOT(d_func(), void _q_changeCurrentColumn())
- Q_PRIVATE_SLOT(d_func(), void _q_clicked(const QModelIndex &))
};
QT_END_NAMESPACE
diff --git a/src/widgets/itemviews/qcolumnview_p.h b/src/widgets/itemviews/qcolumnview_p.h
index 7c68ab2314..f9b2f3baa4 100644
--- a/src/widgets/itemviews/qcolumnview_p.h
+++ b/src/widgets/itemviews/qcolumnview_p.h
@@ -31,6 +31,8 @@
#include <qevent.h>
#include <qscrollbar.h>
+#include <vector>
+
QT_REQUIRE_CONFIG(columnview);
QT_BEGIN_NAMESPACE
@@ -116,20 +118,22 @@ public:
QColumnViewPrivate();
~QColumnViewPrivate();
void initialize();
+ void clearConnections();
QAbstractItemView *createColumn(const QModelIndex &index, bool show);
void updateScrollbars();
void closeColumns(const QModelIndex &parent = QModelIndex(), bool build = false);
+ void disconnectView(QAbstractItemView *view);
void doLayout();
void setPreviewWidget(QWidget *widget);
void checkColumnCreation(const QModelIndex &parent);
- void _q_gripMoved(int offset);
- void _q_changeCurrentColumn();
- void _q_clicked(const QModelIndex &index);
- void _q_columnsInserted(const QModelIndex &parent, int start, int end) override;
+ void gripMoved(int offset);
+ void changeCurrentColumn();
+ void clicked(const QModelIndex &index);
+ void columnsInserted(const QModelIndex &parent, int start, int end) override;
QList<QAbstractItemView*> columns;
QList<int> columnSizes; // used during init and corner moving
@@ -137,7 +141,12 @@ public:
int offset;
#if QT_CONFIG(animation)
QPropertyAnimation currentAnimation;
+ QMetaObject::Connection animationConnection;
#endif
+ std::vector<QMetaObject::Connection> gripConnections;
+ using ViewConnections = std::vector<QMetaObject::Connection>;
+ QHash<QAbstractItemView *, ViewConnections> viewConnections;
+
QWidget *previewWidget;
QAbstractItemView *previewColumn;
};
diff --git a/src/widgets/itemviews/qdatawidgetmapper.cpp b/src/widgets/itemviews/qdatawidgetmapper.cpp
index 5160d06519..3b7e97eed9 100644
--- a/src/widgets/itemviews/qdatawidgetmapper.cpp
+++ b/src/widgets/itemviews/qdatawidgetmapper.cpp
@@ -4,13 +4,15 @@
#include "qdatawidgetmapper.h"
#include "qabstractitemmodel.h"
-#include "qitemdelegate.h"
#include "qmetaobject.h"
#include "qwidget.h"
#include "qstyleditemdelegate.h"
+
#include "private/qobject_p.h"
#include "private/qabstractitemmodel_p.h"
+#include <QtCore/qpointer.h>
+#include <array>
#include <iterator>
QT_BEGIN_NAMESPACE
@@ -67,11 +69,22 @@ public:
void populate();
// private slots
- void _q_dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight,
- const QList<int> &);
- void _q_commitData(QWidget *);
- void _q_closeEditor(QWidget *, QAbstractItemDelegate::EndEditHint);
- void _q_modelDestroyed();
+ void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight,
+ const QList<int> &);
+ void commitData(QWidget *);
+ void closeEditor(QWidget *, QAbstractItemDelegate::EndEditHint);
+ void modelDestroyed();
+
+ void disconnectModel()
+ {
+ for (const QMetaObject::Connection &connection : modelConnections)
+ QObject::disconnect(connection);
+ }
+ void disconnectDelegate()
+ {
+ for (const QMetaObject::Connection &connection : delegateConnections)
+ QObject::disconnect(connection);
+ }
struct WidgetMapper
{
@@ -87,6 +100,8 @@ public:
bool commit(const WidgetMapper &m);
std::vector<WidgetMapper> widgetMap;
+ std::array<QMetaObject::Connection, 2> modelConnections;
+ std::array<QMetaObject::Connection, 2> delegateConnections;
};
Q_DECLARE_TYPEINFO(QDataWidgetMapperPrivate::WidgetMapper, Q_RELOCATABLE_TYPE);
@@ -142,8 +157,8 @@ static bool qContainsIndex(const QModelIndex &idx, const QModelIndex &topLeft,
&& idx.column() >= topLeft.column() && idx.column() <= bottomRight.column();
}
-void QDataWidgetMapperPrivate::_q_dataChanged(const QModelIndex &topLeft,
- const QModelIndex &bottomRight, const QList<int> &)
+void QDataWidgetMapperPrivate::dataChanged(const QModelIndex &topLeft,
+ const QModelIndex &bottomRight, const QList<int> &)
{
if (topLeft.parent() != rootIndex)
return; // not in our hierarchy
@@ -154,7 +169,7 @@ void QDataWidgetMapperPrivate::_q_dataChanged(const QModelIndex &topLeft,
}
}
-void QDataWidgetMapperPrivate::_q_commitData(QWidget *w)
+void QDataWidgetMapperPrivate::commitData(QWidget *w)
{
if (submitPolicy == QDataWidgetMapper::ManualSubmit)
return;
@@ -166,7 +181,7 @@ void QDataWidgetMapperPrivate::_q_commitData(QWidget *w)
commit(widgetMap[idx]);
}
-void QDataWidgetMapperPrivate::_q_closeEditor(QWidget *w, QAbstractItemDelegate::EndEditHint hint)
+void QDataWidgetMapperPrivate::closeEditor(QWidget *w, QAbstractItemDelegate::EndEditHint hint)
{
int idx = findWidget(w);
if (idx == -1)
@@ -189,7 +204,7 @@ void QDataWidgetMapperPrivate::_q_closeEditor(QWidget *w, QAbstractItemDelegate:
}
}
-void QDataWidgetMapperPrivate::_q_modelDestroyed()
+void QDataWidgetMapperPrivate::modelDestroyed()
{
Q_Q(QDataWidgetMapper);
@@ -220,7 +235,7 @@ void QDataWidgetMapperPrivate::_q_modelDestroyed()
instead of the default user property.
It is possible to set an item delegate to support custom widgets. By default,
- a QItemDelegate is used to synchronize the model with the widgets.
+ a QStyledItemDelegate is used to synchronize the model with the widgets.
Let us assume that we have an item model named \c{model} with the following contents:
@@ -299,6 +314,9 @@ QDataWidgetMapper::QDataWidgetMapper(QObject *parent)
*/
QDataWidgetMapper::~QDataWidgetMapper()
{
+ Q_D(QDataWidgetMapper);
+ d->disconnectModel();
+ d->disconnectDelegate();
}
/*!
@@ -314,21 +332,19 @@ void QDataWidgetMapper::setModel(QAbstractItemModel *model)
if (d->model == model)
return;
- if (d->model) {
- disconnect(d->model, SIGNAL(dataChanged(QModelIndex, QModelIndex, QList<int>)), this,
- SLOT(_q_dataChanged(QModelIndex, QModelIndex, QList<int>)));
- disconnect(d->model, SIGNAL(destroyed()), this,
- SLOT(_q_modelDestroyed()));
- }
+ d->disconnectModel();
clearMapping();
d->rootIndex = QModelIndex();
d->currentTopLeft = QModelIndex();
d->model = model;
- connect(model, SIGNAL(dataChanged(QModelIndex, QModelIndex, QList<int>)),
- SLOT(_q_dataChanged(QModelIndex, QModelIndex, QList<int>)));
- connect(model, SIGNAL(destroyed()), SLOT(_q_modelDestroyed()));
+ d->modelConnections = {
+ QObjectPrivate::connect(model, &QAbstractItemModel::dataChanged,
+ d, &QDataWidgetMapperPrivate::dataChanged),
+ QObjectPrivate::connect(model, &QAbstractItemModel::destroyed,
+ d, &QDataWidgetMapperPrivate::modelDestroyed)
+ };
}
/*!
@@ -364,18 +380,17 @@ void QDataWidgetMapper::setItemDelegate(QAbstractItemDelegate *delegate)
{
Q_D(QDataWidgetMapper);
QAbstractItemDelegate *oldDelegate = d->delegate;
- if (oldDelegate) {
- disconnect(oldDelegate, SIGNAL(commitData(QWidget*)), this, SLOT(_q_commitData(QWidget*)));
- disconnect(oldDelegate, SIGNAL(closeEditor(QWidget*,QAbstractItemDelegate::EndEditHint)),
- this, SLOT(_q_closeEditor(QWidget*,QAbstractItemDelegate::EndEditHint)));
- }
+ d->disconnectDelegate();
d->delegate = delegate;
if (delegate) {
- connect(delegate, SIGNAL(commitData(QWidget*)), SLOT(_q_commitData(QWidget*)));
- connect(delegate, SIGNAL(closeEditor(QWidget*,QAbstractItemDelegate::EndEditHint)),
- SLOT(_q_closeEditor(QWidget*,QAbstractItemDelegate::EndEditHint)));
+ d->delegateConnections = {
+ QObjectPrivate::connect(delegate, &QAbstractItemDelegate::commitData,
+ d, &QDataWidgetMapperPrivate::commitData),
+ QObjectPrivate::connect(delegate, &QAbstractItemDelegate::closeEditor,
+ d, &QDataWidgetMapperPrivate::closeEditor)
+ };
}
d->flipEventFilters(oldDelegate, delegate);
diff --git a/src/widgets/itemviews/qdatawidgetmapper.h b/src/widgets/itemviews/qdatawidgetmapper.h
index 56243f1190..6c7beff7fc 100644
--- a/src/widgets/itemviews/qdatawidgetmapper.h
+++ b/src/widgets/itemviews/qdatawidgetmapper.h
@@ -72,12 +72,6 @@ Q_SIGNALS:
private:
Q_DECLARE_PRIVATE(QDataWidgetMapper)
Q_DISABLE_COPY(QDataWidgetMapper)
- Q_PRIVATE_SLOT(d_func(),
- void _q_dataChanged(const QModelIndex &, const QModelIndex &,
- const QList<int> &))
- Q_PRIVATE_SLOT(d_func(), void _q_commitData(QWidget *))
- Q_PRIVATE_SLOT(d_func(), void _q_closeEditor(QWidget *, QAbstractItemDelegate::EndEditHint))
- Q_PRIVATE_SLOT(d_func(), void _q_modelDestroyed())
};
QT_END_NAMESPACE
diff --git a/src/widgets/itemviews/qheaderview.cpp b/src/widgets/itemviews/qheaderview.cpp
index b5b0f17f4a..9ce09dbacc 100644
--- a/src/widgets/itemviews/qheaderview.cpp
+++ b/src/widgets/itemviews/qheaderview.cpp
@@ -295,6 +295,8 @@ QHeaderView::QHeaderView(QHeaderViewPrivate &dd,
QHeaderView::~QHeaderView()
{
+ Q_D(QHeaderView);
+ d->disconnectModel();
}
/*!
@@ -322,68 +324,35 @@ void QHeaderView::setModel(QAbstractItemModel *model)
return;
Q_D(QHeaderView);
d->layoutChangePersistentSections.clear();
- if (d->model && d->model != QAbstractItemModelPrivate::staticEmptyModel()) {
- if (d->orientation == Qt::Horizontal) {
- QObject::disconnect(d->model, SIGNAL(columnsInserted(QModelIndex,int,int)),
- this, SLOT(sectionsInserted(QModelIndex,int,int)));
- QObject::disconnect(d->model, SIGNAL(columnsAboutToBeRemoved(QModelIndex,int,int)),
- this, SLOT(sectionsAboutToBeRemoved(QModelIndex,int,int)));
- QObject::disconnect(d->model, SIGNAL(columnsRemoved(QModelIndex,int,int)),
- this, SLOT(_q_sectionsRemoved(QModelIndex,int,int)));
- QObject::disconnect(d->model, SIGNAL(columnsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)),
- this, SLOT(_q_sectionsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)));
- QObject::disconnect(d->model, SIGNAL(columnsMoved(QModelIndex,int,int,QModelIndex,int)),
- this, SLOT(_q_sectionsMoved(QModelIndex,int,int,QModelIndex,int)));
- } else {
- QObject::disconnect(d->model, SIGNAL(rowsInserted(QModelIndex,int,int)),
- this, SLOT(sectionsInserted(QModelIndex,int,int)));
- QObject::disconnect(d->model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
- this, SLOT(sectionsAboutToBeRemoved(QModelIndex,int,int)));
- QObject::disconnect(d->model, SIGNAL(rowsRemoved(QModelIndex,int,int)),
- this, SLOT(_q_sectionsRemoved(QModelIndex,int,int)));
- QObject::disconnect(d->model, SIGNAL(rowsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)),
- this, SLOT(_q_sectionsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)));
- QObject::disconnect(d->model, SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int)),
- this, SLOT(_q_sectionsMoved(QModelIndex,int,int,QModelIndex,int)));
- }
- QObject::disconnect(d->model, SIGNAL(headerDataChanged(Qt::Orientation,int,int)),
- this, SLOT(headerDataChanged(Qt::Orientation,int,int)));
- QObject::disconnect(d->model, SIGNAL(layoutAboutToBeChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint)),
- this, SLOT(_q_sectionsAboutToBeChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint)));
- QObject::disconnect(d->model, SIGNAL(layoutChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint)),
- this, SLOT(_q_sectionsChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint)));
- }
+ if (d->model && d->model != QAbstractItemModelPrivate::staticEmptyModel())
+ d->disconnectModel();
if (model && model != QAbstractItemModelPrivate::staticEmptyModel()) {
- if (d->orientation == Qt::Horizontal) {
- QObject::connect(model, SIGNAL(columnsInserted(QModelIndex,int,int)),
- this, SLOT(sectionsInserted(QModelIndex,int,int)));
- QObject::connect(model, SIGNAL(columnsAboutToBeRemoved(QModelIndex,int,int)),
- this, SLOT(sectionsAboutToBeRemoved(QModelIndex,int,int)));
- QObject::connect(model, SIGNAL(columnsRemoved(QModelIndex,int,int)),
- this, SLOT(_q_sectionsRemoved(QModelIndex,int,int)));
- QObject::connect(model, SIGNAL(columnsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)),
- this, SLOT(_q_sectionsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)));
- QObject::connect(model, SIGNAL(columnsMoved(QModelIndex,int,int,QModelIndex,int)),
- this, SLOT(_q_sectionsMoved(QModelIndex,int,int,QModelIndex,int)));
- } else {
- QObject::connect(model, SIGNAL(rowsInserted(QModelIndex,int,int)),
- this, SLOT(sectionsInserted(QModelIndex,int,int)));
- QObject::connect(model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
- this, SLOT(sectionsAboutToBeRemoved(QModelIndex,int,int)));
- QObject::connect(model, SIGNAL(rowsRemoved(QModelIndex,int,int)),
- this, SLOT(_q_sectionsRemoved(QModelIndex,int,int)));
- QObject::connect(model, SIGNAL(rowsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)),
- this, SLOT(_q_sectionsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)));
- QObject::connect(model, SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int)),
- this, SLOT(_q_sectionsMoved(QModelIndex,int,int,QModelIndex,int)));
- }
- QObject::connect(model, SIGNAL(headerDataChanged(Qt::Orientation,int,int)),
- this, SLOT(headerDataChanged(Qt::Orientation,int,int)));
- QObject::connect(model, SIGNAL(layoutAboutToBeChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint)),
- this, SLOT(_q_sectionsAboutToBeChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint)));
- QObject::connect(model, SIGNAL(layoutChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint)),
- this, SLOT(_q_sectionsChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint)));
+ const bool hor = d->orientation == Qt::Horizontal;
+ d->modelConnections = {
+ QObject::connect(model, hor ? &QAbstractItemModel::columnsInserted
+ : &QAbstractItemModel::rowsInserted,
+ this, &QHeaderView::sectionsInserted),
+ QObject::connect(model, hor ? &QAbstractItemModel::columnsAboutToBeRemoved
+ : &QAbstractItemModel::rowsAboutToBeRemoved,
+ this, &QHeaderView::sectionsAboutToBeRemoved),
+ QObjectPrivate::connect(model, hor ? &QAbstractItemModel::columnsRemoved
+ : &QAbstractItemModel::rowsRemoved,
+ d, &QHeaderViewPrivate::sectionsRemoved),
+ QObjectPrivate::connect(model, hor ? &QAbstractItemModel::columnsAboutToBeMoved
+ : &QAbstractItemModel::rowsAboutToBeMoved,
+ d, &QHeaderViewPrivate::sectionsAboutToBeMoved),
+ QObjectPrivate::connect(model, hor ? &QAbstractItemModel::columnsMoved
+ : &QAbstractItemModel::rowsMoved,
+ d, &QHeaderViewPrivate::sectionsMoved),
+
+ QObject::connect(model, &QAbstractItemModel::headerDataChanged,
+ this, &QHeaderView::headerDataChanged),
+ QObjectPrivate::connect(model, &QAbstractItemModel::layoutAboutToBeChanged,
+ d, &QHeaderViewPrivate::sectionsAboutToBeChanged),
+ QObjectPrivate::connect(model, &QAbstractItemModel::layoutChanged,
+ d, &QHeaderViewPrivate::sectionsChanged)
+ };
}
d->state = QHeaderViewPrivate::NoClear;
@@ -418,7 +387,7 @@ Qt::Orientation QHeaderView::orientation() const
int QHeaderView::offset() const
{
Q_D(const QHeaderView);
- return d->offset;
+ return d->headerOffset;
}
/*!
@@ -432,10 +401,10 @@ int QHeaderView::offset() const
void QHeaderView::setOffset(int newOffset)
{
Q_D(QHeaderView);
- if (d->offset == (int)newOffset)
+ if (d->headerOffset == newOffset)
return;
- int ndelta = d->offset - newOffset;
- d->offset = newOffset;
+ int ndelta = d->headerOffset - newOffset;
+ d->headerOffset = newOffset;
if (d->orientation == Qt::Horizontal)
d->viewport->scroll(isRightToLeft() ? -ndelta : ndelta, 0);
else
@@ -591,7 +560,7 @@ int QHeaderView::visualIndexAt(int position) const
if (d->reverse())
vposition = d->viewport->width() - vposition - 1;
- vposition += d->offset;
+ vposition += d->headerOffset;
if (vposition > d->length)
return -1;
@@ -681,7 +650,7 @@ int QHeaderView::sectionViewportPosition(int logicalIndex) const
int position = sectionPosition(logicalIndex);
if (position < 0)
return position; // the section was hidden
- int offsetPosition = position - d->offset;
+ int offsetPosition = position - d->headerOffset;
if (d->reverse())
return d->viewport->width() - (offsetPosition + sectionSize(logicalIndex));
return offsetPosition;
@@ -1087,19 +1056,22 @@ int QHeaderView::logicalIndex(int visualIndex) const
}
/*!
- \since 5.0
+ \property QHeaderView::sectionsMovable
- If \a movable is true, the header sections may be moved by the user;
+ If \a sectionsMovable is true, the header sections may be moved by the user;
otherwise they are fixed in place.
When used in combination with QTreeView, the first column is not
movable (since it contains the tree structure), by default.
You can make it movable with setFirstSectionMovable(true).
- \sa sectionsMovable(), sectionMoved()
+ \sa sectionMoved()
\sa setFirstSectionMovable()
*/
+/*!
+ Sets \l sectionsMovable to \a movable.
+ */
void QHeaderView::setSectionsMovable(bool movable)
{
Q_D(QHeaderView);
@@ -1107,17 +1079,8 @@ void QHeaderView::setSectionsMovable(bool movable)
}
/*!
- \since 5.0
-
- Returns \c true if the header can be moved by the user; otherwise returns
- false.
-
- By default, sections are movable in QTreeView (except for the first one),
- and not movable in QTableView.
-
- \sa setSectionsMovable()
+ Returns \l sectionsMovable.
*/
-
bool QHeaderView::sectionsMovable() const
{
Q_D(const QHeaderView);
@@ -1137,6 +1100,11 @@ bool QHeaderView::sectionsMovable() const
In such a scenario, it is recommended to call QTreeView::setRootIsDecorated(false)
as well.
+ \code
+ treeView->setRootIsDecorated(false);
+ treeView->header()->setFirstSectionMovable(true);
+ \endcode
+
Setting it to true has no effect unless setSectionsMovable(true) is called
as well.
@@ -1156,14 +1124,17 @@ bool QHeaderView::isFirstSectionMovable() const
}
/*!
- \since 5.0
+ \property QHeaderView::sectionsClickable
- If \a clickable is true, the header will respond to single clicks.
+ Holds \c true if the header is clickable; otherwise \c false. A
+ clickable header could be set up to allow the user to change the
+ representation of the data in the view related to the header.
- \sa sectionsClickable(), sectionClicked(), sectionPressed(),
- setSortIndicatorShown()
+ \sa sectionPressed(), setSortIndicatorShown()
+*/
+/*!
+ Set \l sectionsClickable to \a clickable.
*/
-
void QHeaderView::setSectionsClickable(bool clickable)
{
Q_D(QHeaderView);
@@ -1171,15 +1142,8 @@ void QHeaderView::setSectionsClickable(bool clickable)
}
/*!
- \since 5.0
-
- Returns \c true if the header is clickable; otherwise returns \c false. A
- clickable header could be set up to allow the user to change the
- representation of the data in the view related to the header.
-
- \sa setSectionsClickable()
+ Returns \l sectionsClickable.
*/
-
bool QHeaderView::sectionsClickable() const
{
Q_D(const QHeaderView);
@@ -1880,8 +1844,9 @@ void QHeaderView::sectionsInserted(const QModelIndex &parent,
int logicalFirst, int logicalLast)
{
Q_D(QHeaderView);
- if (parent != d->root)
- return; // we only handle changes in the root level
+ // only handle root level changes and return on no-op
+ if (parent != d->root || d->modelSectionCount() == d->sectionCount())
+ return;
int oldCount = d->sectionCount();
d->invalidateCachedSizeHint();
@@ -2004,8 +1969,8 @@ void QHeaderViewPrivate::updateHiddenSections(int logicalFirst, int logicalLast)
hiddenSectionSize = newHiddenSectionSize;
}
-void QHeaderViewPrivate::_q_sectionsRemoved(const QModelIndex &parent,
- int logicalFirst, int logicalLast)
+void QHeaderViewPrivate::sectionsRemoved(const QModelIndex &parent,
+ int logicalFirst, int logicalLast)
{
Q_Q(QHeaderView);
if (parent != root)
@@ -2090,28 +2055,32 @@ void QHeaderViewPrivate::_q_sectionsRemoved(const QModelIndex &parent,
viewport->update();
}
-void QHeaderViewPrivate::_q_sectionsAboutToBeMoved(const QModelIndex &sourceParent, int logicalStart, int logicalEnd, const QModelIndex &destinationParent, int logicalDestination)
+void QHeaderViewPrivate::sectionsAboutToBeMoved(const QModelIndex &sourceParent, int logicalStart,
+ int logicalEnd, const QModelIndex &destinationParent,
+ int logicalDestination)
{
if (sourceParent != root || destinationParent != root)
return; // we only handle changes in the root level
Q_UNUSED(logicalStart);
Q_UNUSED(logicalEnd);
Q_UNUSED(logicalDestination);
- _q_sectionsAboutToBeChanged();
+ sectionsAboutToBeChanged();
}
-void QHeaderViewPrivate::_q_sectionsMoved(const QModelIndex &sourceParent, int logicalStart, int logicalEnd, const QModelIndex &destinationParent, int logicalDestination)
+void QHeaderViewPrivate::sectionsMoved(const QModelIndex &sourceParent, int logicalStart,
+ int logicalEnd, const QModelIndex &destinationParent,
+ int logicalDestination)
{
if (sourceParent != root || destinationParent != root)
return; // we only handle changes in the root level
Q_UNUSED(logicalStart);
Q_UNUSED(logicalEnd);
Q_UNUSED(logicalDestination);
- _q_sectionsChanged();
+ sectionsChanged();
}
-void QHeaderViewPrivate::_q_sectionsAboutToBeChanged(const QList<QPersistentModelIndex> &,
- QAbstractItemModel::LayoutChangeHint hint)
+void QHeaderViewPrivate::sectionsAboutToBeChanged(const QList<QPersistentModelIndex> &,
+ QAbstractItemModel::LayoutChangeHint hint)
{
if ((hint == QAbstractItemModel::VerticalSortHint && orientation == Qt::Horizontal) ||
(hint == QAbstractItemModel::HorizontalSortHint && orientation == Qt::Vertical))
@@ -2156,8 +2125,8 @@ void QHeaderViewPrivate::_q_sectionsAboutToBeChanged(const QList<QPersistentMode
}
}
-void QHeaderViewPrivate::_q_sectionsChanged(const QList<QPersistentModelIndex> &,
- QAbstractItemModel::LayoutChangeHint hint)
+void QHeaderViewPrivate::sectionsChanged(const QList<QPersistentModelIndex> &,
+ QAbstractItemModel::LayoutChangeHint hint)
{
if ((hint == QAbstractItemModel::VerticalSortHint && orientation == Qt::Horizontal) ||
(hint == QAbstractItemModel::HorizontalSortHint && orientation == Qt::Vertical))
@@ -2187,7 +2156,7 @@ void QHeaderViewPrivate::_q_sectionsChanged(const QList<QPersistentModelIndex> &
}
// Though far from perfect we here try to retain earlier/existing behavior
- // ### See QHeaderViewPrivate::_q_layoutAboutToBeChanged()
+ // ### See QHeaderViewPrivate::layoutAboutToBeChanged()
// When we don't have valid hasPersistantIndexes it can be due to
// - all sections are default sections
// - the row/column 0 which is used for persistent indexes is gone
@@ -2513,9 +2482,9 @@ void QHeaderView::paintEvent(QPaintEvent *e)
for (int a = 0, i = 0; i < d->sectionItems.count(); ++i) {
QColor color((i & 4 ? 255 : 0), (i & 2 ? 255 : 0), (i & 1 ? 255 : 0));
if (d->orientation == Qt::Horizontal)
- painter.fillRect(a - d->offset, 0, d->sectionItems.at(i).size, 4, color);
+ painter.fillRect(a - d->headerOffset, 0, d->sectionItems.at(i).size, 4, color);
else
- painter.fillRect(0, a - d->offset, 4, d->sectionItems.at(i).size, color);
+ painter.fillRect(0, a - d->headerOffset, 4, d->sectionItems.at(i).size, color);
a += d->sectionItems.at(i).size;
}
@@ -2574,7 +2543,7 @@ void QHeaderView::mousePressEvent(QMouseEvent *e)
void QHeaderView::mouseMoveEvent(QMouseEvent *e)
{
Q_D(QHeaderView);
- int pos = d->orientation == Qt::Horizontal ? e->position().toPoint().x() : e->position().toPoint().y();
+ const int pos = d->orientation == Qt::Horizontal ? e->position().toPoint().x() : e->position().toPoint().y();
if (pos < 0 && d->state != QHeaderViewPrivate::SelectSections)
return;
if (e->buttons() == Qt::NoButton) {
@@ -2602,8 +2571,10 @@ void QHeaderView::mouseMoveEvent(QMouseEvent *e)
return;
}
case QHeaderViewPrivate::MoveSection: {
- if (d->shouldAutoScroll(e->position().toPoint()))
+ if (d->shouldAutoScroll(e->position().toPoint())) {
+ d->draggedPosition = e->pos() + d->offset();
d->startAutoScroll();
+ }
if (qAbs(pos - d->firstPos) >= QApplication::startDragDistance()
#if QT_CONFIG(label)
|| !d->sectionIndicator->isHidden()
@@ -2615,7 +2586,7 @@ void QHeaderView::mouseMoveEvent(QMouseEvent *e)
if (visual == 0 && logicalIndex(0) == 0 && !d->allowUserMoveOfSection0)
return;
- const int posThreshold = d->headerSectionPosition(visual) - d->offset + d->headerSectionSize(visual) / 2;
+ const int posThreshold = d->headerSectionPosition(visual) - d->headerOffset + d->headerSectionSize(visual) / 2;
const int checkPos = d->reverse() ? d->viewport->width() - pos : pos;
int moving = visualIndex(d->section);
int oldTarget = d->target;
@@ -2639,7 +2610,7 @@ void QHeaderView::mouseMoveEvent(QMouseEvent *e)
return;
}
case QHeaderViewPrivate::SelectSections: {
- int logical = logicalIndexAt(qMax(-d->offset, pos));
+ int logical = logicalIndexAt(qMax(-d->headerOffset, pos));
if (logical == -1 && pos > 0)
logical = logicalIndex(d->lastVisibleVisualIndex());
if (logical == d->pressed)
@@ -3061,7 +3032,7 @@ int QHeaderView::horizontalOffset() const
{
Q_D(const QHeaderView);
if (d->orientation == Qt::Horizontal)
- return d->offset;
+ return d->headerOffset;
return 0;
}
@@ -3076,7 +3047,7 @@ int QHeaderView::verticalOffset() const
{
Q_D(const QHeaderView);
if (d->orientation == Qt::Vertical)
- return d->offset;
+ return d->headerOffset;
return 0;
}
@@ -3800,12 +3771,9 @@ void QHeaderViewPrivate::cascadingResize(int visual, int newSize)
if (currentSectionSize <= minimumSize)
continue;
int newSectionSize = qMax(currentSectionSize - delta, minimumSize);
- //qDebug() << "### cascading to" << i << newSectionSize - currentSectionSize << delta;
resizeSectionItem(i, currentSectionSize, newSectionSize);
saveCascadingSectionSize(i, currentSectionSize);
delta = delta - (currentSectionSize - newSectionSize);
- //qDebug() << "new delta" << delta;
- //if (newSectionSize != minimumSize)
if (delta <= 0)
break;
}
@@ -3823,7 +3791,6 @@ void QHeaderViewPrivate::cascadingResize(int visual, int newSize)
int newSectionSize = currentSectionSize - delta;
resizeSectionItem(i, currentSectionSize, newSectionSize);
if (newSectionSize >= originalSectionSize && false) {
- //qDebug() << "section" << i << "restored to" << originalSectionSize;
cascadingSectionSize.remove(i); // the section is now restored
}
sectionResized = true;
diff --git a/src/widgets/itemviews/qheaderview.h b/src/widgets/itemviews/qheaderview.h
index 6118faa868..bd0050df5e 100644
--- a/src/widgets/itemviews/qheaderview.h
+++ b/src/widgets/itemviews/qheaderview.h
@@ -19,6 +19,8 @@ class Q_WIDGETS_EXPORT QHeaderView : public QAbstractItemView
Q_OBJECT
Q_PROPERTY(bool firstSectionMovable READ isFirstSectionMovable WRITE setFirstSectionMovable)
Q_PROPERTY(bool showSortIndicator READ isSortIndicatorShown WRITE setSortIndicatorShown)
+ Q_PROPERTY(bool sectionsMovable READ sectionsMovable WRITE setSectionsMovable)
+ Q_PROPERTY(bool sectionsClickable READ sectionsClickable WRITE setSectionsClickable)
Q_PROPERTY(bool highlightSections READ highlightSections WRITE setHighlightSections)
Q_PROPERTY(bool stretchLastSection READ stretchLastSection WRITE setStretchLastSection)
Q_PROPERTY(bool cascadingSectionResizes READ cascadingSectionResizes
@@ -211,14 +213,6 @@ protected:
private:
void initStyleOption(QStyleOptionFrame *option) const override;
- // ### Qt6: make them protected slots in QHeaderViewPrivate
- Q_PRIVATE_SLOT(d_func(), void _q_sectionsRemoved(const QModelIndex &parent, int logicalFirst, int logicalLast))
- Q_PRIVATE_SLOT(d_func(), void _q_sectionsAboutToBeMoved(const QModelIndex &sourceParent, int logicalStart, int logicalEnd, const QModelIndex &destinationParent, int logicalDestination))
- Q_PRIVATE_SLOT(d_func(), void _q_sectionsMoved(const QModelIndex &sourceParent, int logicalStart, int logicalEnd, const QModelIndex &destinationParent, int logicalDestination))
- Q_PRIVATE_SLOT(d_func(), void _q_sectionsAboutToBeChanged(const QList<QPersistentModelIndex> &parents = QList<QPersistentModelIndex>(),
- QAbstractItemModel::LayoutChangeHint hint = QAbstractItemModel::NoLayoutChangeHint))
- Q_PRIVATE_SLOT(d_func(), void _q_sectionsChanged(const QList<QPersistentModelIndex> &parents = QList<QPersistentModelIndex>(),
- QAbstractItemModel::LayoutChangeHint hint = QAbstractItemModel::NoLayoutChangeHint))
Q_DECLARE_PRIVATE(QHeaderView)
Q_DISABLE_COPY(QHeaderView)
};
diff --git a/src/widgets/itemviews/qheaderview_p.h b/src/widgets/itemviews/qheaderview_p.h
index c599aeff8d..8b214e1d03 100644
--- a/src/widgets/itemviews/qheaderview_p.h
+++ b/src/widgets/itemviews/qheaderview_p.h
@@ -16,6 +16,7 @@
//
#include <QtWidgets/private/qtwidgetsglobal_p.h>
+#include "qheaderview.h"
#include "private/qabstractitemview_p.h"
#include "QtCore/qbitarray.h"
@@ -24,6 +25,8 @@
#include "QtWidgets/qlabel.h"
#endif
+#include <array>
+
QT_REQUIRE_CONFIG(itemviews);
QT_BEGIN_NAMESPACE
@@ -37,7 +40,7 @@ public:
QHeaderViewPrivate()
: state(NoState),
- offset(0),
+ headerOffset(0),
sortIndicatorOrder(Qt::DescendingOrder),
sortIndicatorSection(0),
sortIndicatorShown(false),
@@ -85,13 +88,17 @@ public:
void updateSectionIndicator(int section, int position);
void updateHiddenSections(int logicalFirst, int logicalLast);
void resizeSections(QHeaderView::ResizeMode globalMode, bool useGlobalMode = false);
- void _q_sectionsRemoved(const QModelIndex &,int,int);
- void _q_sectionsAboutToBeMoved(const QModelIndex &sourceParent, int logicalStart, int logicalEnd, const QModelIndex &destinationParent, int logicalDestination);
- void _q_sectionsMoved(const QModelIndex &sourceParent, int logicalStart, int logicalEnd, const QModelIndex &destinationParent, int logicalDestination);
- void _q_sectionsAboutToBeChanged(const QList<QPersistentModelIndex> &parents = QList<QPersistentModelIndex>(),
- QAbstractItemModel::LayoutChangeHint hint = QAbstractItemModel::NoLayoutChangeHint);
- void _q_sectionsChanged(const QList<QPersistentModelIndex> &parents = QList<QPersistentModelIndex>(),
- QAbstractItemModel::LayoutChangeHint hint = QAbstractItemModel::NoLayoutChangeHint);
+ void sectionsRemoved(const QModelIndex &,int,int);
+ void sectionsAboutToBeMoved(const QModelIndex &sourceParent, int logicalStart,
+ int logicalEnd, const QModelIndex &destinationParent,
+ int logicalDestination);
+ void sectionsMoved(const QModelIndex &sourceParent, int logicalStart,
+ int logicalEnd, const QModelIndex &destinationParent,
+ int logicalDestination);
+ void sectionsAboutToBeChanged(const QList<QPersistentModelIndex> &parents = QList<QPersistentModelIndex>(),
+ QAbstractItemModel::LayoutChangeHint hint = QAbstractItemModel::NoLayoutChangeHint);
+ void sectionsChanged(const QList<QPersistentModelIndex> &parents = QList<QPersistentModelIndex>(),
+ QAbstractItemModel::LayoutChangeHint hint = QAbstractItemModel::NoLayoutChangeHint);
bool isSectionSelected(int section) const;
bool isFirstVisibleSection(int section) const;
@@ -212,6 +219,12 @@ public:
}
}
+ inline void disconnectModel()
+ {
+ for (const QMetaObject::Connection &connection : modelConnections)
+ QObject::disconnect(connection);
+ }
+
void clear();
void flipSortIndicator(int section);
Qt::SortOrder defaultSortOrderForSection(int section) const;
@@ -219,7 +232,7 @@ public:
enum State { NoState, ResizeSection, MoveSection, SelectSections, NoClear } state;
- int offset;
+ int headerOffset;
Qt::Orientation orientation;
Qt::SortOrder sortIndicatorOrder;
int sortIndicatorSection;
@@ -304,6 +317,7 @@ public:
SectionItem section;
};
QList<LayoutChangeItem> layoutChangePersistentSections;
+ std::array<QMetaObject::Connection, 8> modelConnections;
void createSectionItems(int start, int end, int sectionSize, QHeaderView::ResizeMode mode);
void removeSectionsFromSectionItems(int start, int end);
diff --git a/src/widgets/itemviews/qitemdelegate.cpp b/src/widgets/itemviews/qitemdelegate.cpp
index 79ee203aca..d1c7bb3d58 100644
--- a/src/widgets/itemviews/qitemdelegate.cpp
+++ b/src/widgets/itemviews/qitemdelegate.cpp
@@ -257,17 +257,27 @@ QSizeF QItemDelegatePrivate::doTextLayout(int lineWidth) const
When subclassing QItemDelegate to create a delegate that displays items
using a custom renderer, it is important to ensure that the delegate can
- render items suitably for all the required states; e.g. selected,
+ render items suitably for all the required states; such as selected,
disabled, checked. The documentation for the paint() function contains
some hints to show how this can be achieved.
- You can provide custom editors by using a QItemEditorFactory. The
- \l{Color Editor Factory Example} shows how a custom editor can be
- made available to delegates with the default item editor
- factory. This way, there is no need to subclass QItemDelegate. An
- alternative is to reimplement createEditor(), setEditorData(),
- setModelData(), and updateEditorGeometry(). This process is
- described in the \l{Spin Box Delegate Example}.
+ You can provide custom editors by using a QItemEditorFactory. The following
+ code shows how a custom editor can be made available to delegates with the
+ default item editor factory.
+
+ \snippet code/src_gui_itemviews_qitemeditorfactory.cpp setDefaultFactory
+
+ After the default factory has been set, all standard item delegates
+ will use it (also the delegates that were created before setting the
+ default factory).
+
+ This way, you can avoid subclassing QItemDelegate, and all values of the
+ specified type (for example QMetaType::QDateTime) will be edited using the
+ provided editor (like \c{MyFancyDateTimeEdit} in the above example).
+
+ An alternative is to reimplement createEditor(), setEditorData(),
+ setModelData(), and updateEditorGeometry(). This process is described
+ in the \l{A simple delegate}{Model/View Programming overview documentation}.
\section1 QStyledItemDelegate vs. QItemDelegate
@@ -281,9 +291,7 @@ QSizeF QItemDelegatePrivate::doTextLayout(int lineWidth) const
for either class should be equal unless the custom delegate needs to use
the style for drawing.
- \sa {Delegate Classes}, QStyledItemDelegate, QAbstractItemDelegate,
- {Spin Box Delegate Example}, {Settings Editor Example},
- {Icons Example}
+ \sa {Delegate Classes}, QStyledItemDelegate, QAbstractItemDelegate
*/
/*!
@@ -343,8 +351,10 @@ QString QItemDelegatePrivate::valueToText(const QVariant &value, const QStyleOpt
For example, a selected item may need to be displayed differently to
unselected items, as shown in the following code:
- \snippet itemviews/pixelator/pixeldelegate.cpp 2
- \dots
+ \code
+ if (option.state & QStyle::State_Selected)
+ painter->fillRect(option.rect, option.palette.highlight());
+ \endcode
After painting, you should ensure that the painter is returned to its
the state it was supplied in when this function was called. For example,
diff --git a/src/widgets/itemviews/qitemeditorfactory.cpp b/src/widgets/itemviews/qitemeditorfactory.cpp
index 609df364cf..70d11e1b38 100644
--- a/src/widgets/itemviews/qitemeditorfactory.cpp
+++ b/src/widgets/itemviews/qitemeditorfactory.cpp
@@ -120,7 +120,7 @@ Q_SIGNALS:
Additional editors can be registered with the registerEditor() function.
- \sa QStyledItemDelegate, {Model/View Programming}, {Color Editor Factory Example}
+ \sa QStyledItemDelegate, {Model/View Programming}
*/
/*!
@@ -363,7 +363,7 @@ void QItemEditorFactory::setDefaultFactory(QItemEditorFactory *factory)
to register widgets without the need to subclass QItemEditorCreatorBase.
\sa QStandardItemEditorCreator, QItemEditorFactory,
- {Model/View Programming}, {Color Editor Factory Example}
+ {Model/View Programming}
*/
/*!
@@ -432,7 +432,7 @@ QItemEditorCreatorBase::~QItemEditorCreatorBase()
property, you should use QStandardItemEditorCreator instead.
\sa QItemEditorCreatorBase, QStandardItemEditorCreator,
- QItemEditorFactory, {Color Editor Factory Example}
+ QItemEditorFactory
*/
/*!
@@ -488,7 +488,7 @@ QItemEditorCreatorBase::~QItemEditorCreatorBase()
\snippet code/src_gui_itemviews_qitemeditorfactory.cpp 3
\sa QItemEditorCreatorBase, QItemEditorCreator,
- QItemEditorFactory, QStyledItemDelegate, {Color Editor Factory Example}
+ QItemEditorFactory, QStyledItemDelegate
*/
/*!
diff --git a/src/widgets/itemviews/qlistview.cpp b/src/widgets/itemviews/qlistview.cpp
index b03c1a47f5..a7f1931947 100644
--- a/src/widgets/itemviews/qlistview.cpp
+++ b/src/widgets/itemviews/qlistview.cpp
@@ -88,7 +88,7 @@ extern bool qt_sendSpontaneousEvent(QObject *receiver, QEvent *event);
that can be taken for views that are intended to display items with equal sizes
is to set the \l uniformItemSizes property to true.
- \sa {View Classes}, {Item Views Puzzle Example}, QTreeView, QTableView, QListWidget
+ \sa {View Classes}, QTreeView, QTableView, QListWidget
*/
/*!
@@ -352,7 +352,7 @@ int QListView::spacing() const
/*!
\property QListView::batchSize
\brief the number of items laid out in each batch if \l layoutMode is
- set to \l Batched
+ set to \l Batched.
The default value is 100.
@@ -755,7 +755,10 @@ void QListView::mouseMoveEvent(QMouseEvent *e)
&& d->selectionMode != NoSelection) {
QRect rect(d->pressedPosition, e->position().toPoint() + QPoint(horizontalOffset(), verticalOffset()));
rect = rect.normalized();
- d->viewport->update(d->mapToViewport(rect.united(d->elasticBand)));
+ const int margin = 2 * style()->pixelMetric(QStyle::PM_DefaultFrameWidth);
+ const QRect viewPortRect = rect.united(d->elasticBand)
+ .adjusted(-margin, -margin, margin, margin);
+ d->viewport->update(d->mapToViewport(viewPortRect));
d->elasticBand = rect;
}
}
@@ -769,7 +772,9 @@ void QListView::mouseReleaseEvent(QMouseEvent *e)
QAbstractItemView::mouseReleaseEvent(e);
// #### move this implementation into a dynamic class
if (d->showElasticBand && d->elasticBand.isValid()) {
- d->viewport->update(d->mapToViewport(d->elasticBand));
+ const int margin = 2 * style()->pixelMetric(QStyle::PM_DefaultFrameWidth);
+ const QRect viewPortRect = d->elasticBand.adjusted(-margin, -margin, margin, margin);
+ d->viewport->update(d->mapToViewport(viewPortRect));
d->elasticBand = QRect();
}
}
@@ -910,7 +915,8 @@ void QListView::dropEvent(QDropEvent *event)
bool dataMoved = false;
for (int i = 0; i < persIndexes.size(); ++i) {
const QPersistentModelIndex &pIndex = persIndexes.at(i);
- if (r != pIndex.row()) {
+ // only generate a move when not same row or behind itself
+ if (r != pIndex.row() && r != pIndex.row() + 1) {
// try to move (preserves selection)
dataMoved |= model()->moveRow(QModelIndex(), pIndex.row(), QModelIndex(), r);
if (!dataMoved) // can't move - abort and let QAbstractItemView handle this
@@ -1621,6 +1627,12 @@ void QListView::setModelColumn(int column)
return;
d->column = column;
d->doDelayedItemsLayout();
+#if QT_CONFIG(accessibility)
+ if (QAccessible::isActive()) {
+ QAccessibleTableModelChangeEvent event(this, QAccessibleTableModelChangeEvent::ModelReset);
+ QAccessible::updateAccessibility(&event);
+ }
+#endif
}
int QListView::modelColumn() const
@@ -1790,7 +1802,7 @@ void QListViewPrivate::prepareItemsLayout()
if (q->style()->styleHint(QStyle::SH_ScrollView_FrameOnlyAroundContents)) {
QStyleOption option;
option.initFrom(q);
- frameAroundContents = q->style()->pixelMetric(QStyle::PM_DefaultFrameWidth, &option) * 2;
+ frameAroundContents = q->style()->pixelMetric(QStyle::PM_DefaultFrameWidth, &option, q) * 2;
}
// maximumViewportSize() already takes scrollbar into account if policy is
@@ -3401,7 +3413,7 @@ void QListView::currentChanged(const QModelIndex &current, const QModelIndex &pr
QAbstractItemView::currentChanged(current, previous);
#if QT_CONFIG(accessibility)
if (QAccessible::isActive()) {
- if (current.isValid()) {
+ if (current.isValid() && hasFocus()) {
int entry = visualIndex(current);
QAccessibleEvent event(this, QAccessible::Focus);
event.setChild(entry);
diff --git a/src/widgets/itemviews/qlistview_p.h b/src/widgets/itemviews/qlistview_p.h
index de928bbb28..40dabf5656 100644
--- a/src/widgets/itemviews/qlistview_p.h
+++ b/src/widgets/itemviews/qlistview_p.h
@@ -16,6 +16,7 @@
//
#include <QtWidgets/private/qtwidgetsglobal_p.h>
+#include "qlistview.h"
#include "private/qabstractitemview_p.h"
#include "qbitarray.h"
#include "qbsptree_p.h"
diff --git a/src/widgets/itemviews/qlistwidget.cpp b/src/widgets/itemviews/qlistwidget.cpp
index cc0ccf84da..a91902813a 100644
--- a/src/widgets/itemviews/qlistwidget.cpp
+++ b/src/widgets/itemviews/qlistwidget.cpp
@@ -3,7 +3,6 @@
#include "qlistwidget.h"
-#include <qitemdelegate.h>
#include <private/qlistview_p.h>
#include <private/qwidgetitemdata_p.h>
#include <private/qlistwidget_p.h>
@@ -308,7 +307,7 @@ void QListModel::sort(int column, Qt::SortOrder order)
}
const auto compare = (order == Qt::AscendingOrder ? &itemLessThan : &itemGreaterThan);
- std::sort(sorting.begin(), sorting.end(), compare);
+ std::stable_sort(sorting.begin(), sorting.end(), compare);
QModelIndexList fromIndexes;
QModelIndexList toIndexes;
const int sortingCount = sorting.size();
@@ -328,76 +327,34 @@ void QListModel::sort(int column, Qt::SortOrder order)
/**
* This function assumes that all items in the model except the items that are between
* (inclusive) start and end are sorted.
- * With these assumptions, this function can ensure that the model is sorted in a
- * much more efficient way than doing a naive 'sort everything'.
- * (provided that the range is relatively small compared to the total number of items)
*/
void QListModel::ensureSorted(int column, Qt::SortOrder order, int start, int end)
{
if (column != 0)
return;
- const int count = end - start + 1;
- QList<QPair<QListWidgetItem *, int>> sorting(count);
- for (int i = 0; i < count; ++i) {
- sorting[i].first = items.at(start + i);
- sorting[i].second = start + i;
- }
+ const auto compareLt = [](const QListWidgetItem *left, const QListWidgetItem *right) -> bool {
+ return *left < *right;
+ };
- const auto compare = (order == Qt::AscendingOrder ? &itemLessThan : &itemGreaterThan);
- std::sort(sorting.begin(), sorting.end(), compare);
-
- QModelIndexList oldPersistentIndexes = persistentIndexList();
- QModelIndexList newPersistentIndexes = oldPersistentIndexes;
- QList<QListWidgetItem*> tmp = items;
- QList<QListWidgetItem*>::iterator lit = tmp.begin();
- bool changed = false;
- for (int i = 0; i < count; ++i) {
- int oldRow = sorting.at(i).second;
- int tmpitepos = lit - tmp.begin();
- QListWidgetItem *item = tmp.takeAt(oldRow);
- if (tmpitepos > tmp.size())
- --tmpitepos;
- lit = tmp.begin() + tmpitepos;
- lit = sortedInsertionIterator(lit, tmp.end(), order, item);
- int newRow = qMax<qsizetype>(lit - tmp.begin(), 0);
- lit = tmp.insert(lit, item);
- if (newRow != oldRow) {
- if (!changed) {
- emit layoutAboutToBeChanged({}, QAbstractItemModel::VerticalSortHint);
- oldPersistentIndexes = persistentIndexList();
- newPersistentIndexes = oldPersistentIndexes;
- changed = true;
- }
- for (int j = i + 1; j < count; ++j) {
- int otherRow = sorting.at(j).second;
- if (oldRow < otherRow && newRow >= otherRow)
- --sorting[j].second;
- else if (oldRow > otherRow && newRow <= otherRow)
- ++sorting[j].second;
- }
- for (int k = 0; k < newPersistentIndexes.size(); ++k) {
- QModelIndex pi = newPersistentIndexes.at(k);
- int oldPersistentRow = pi.row();
- int newPersistentRow = oldPersistentRow;
- if (oldPersistentRow == oldRow)
- newPersistentRow = newRow;
- else if (oldRow < oldPersistentRow && newRow >= oldPersistentRow)
- newPersistentRow = oldPersistentRow - 1;
- else if (oldRow > oldPersistentRow && newRow <= oldPersistentRow)
- newPersistentRow = oldPersistentRow + 1;
- if (newPersistentRow != oldPersistentRow)
- newPersistentIndexes[k] = createIndex(newPersistentRow,
- pi.column(), pi.internalPointer());
- }
- }
- }
+ const auto compareGt = [](const QListWidgetItem *left, const QListWidgetItem *right) -> bool {
+ return *right < *left;
+ };
- if (changed) {
- items = tmp;
- changePersistentIndexList(oldPersistentIndexes, newPersistentIndexes);
- emit layoutChanged({}, QAbstractItemModel::VerticalSortHint);
- }
+ /** Check if range [start,end] is already in sorted position in list.
+ * Take for this the assumption, that outside [start,end] the list
+ * is already sorted. Therefore the sorted check has to be extended
+ * to the first element that is known to be sorted before the range
+ * [start, end], which is (start-1) and the first element after the
+ * range [start, end], which is (end+2) due to end being included.
+ */
+ const auto beginChangedIterator = items.constBegin() + qMax(start - 1, 0);
+ const auto endChangedIterator = items.constBegin() + qMin(end + 2, items.size());
+ const bool needsSorting = !std::is_sorted(beginChangedIterator, endChangedIterator,
+ order == Qt::AscendingOrder ? compareLt : compareGt);
+
+ if (needsSorting)
+ sort(column, order);
}
bool QListModel::itemLessThan(const QPair<QListWidgetItem*,int> &left,
@@ -1126,57 +1083,71 @@ void QListWidgetPrivate::setup()
Q_Q(QListWidget);
q->QListView::setModel(new QListModel(q));
// view signals
- QObject::connect(q, SIGNAL(pressed(QModelIndex)), q, SLOT(_q_emitItemPressed(QModelIndex)));
- QObject::connect(q, SIGNAL(clicked(QModelIndex)), q, SLOT(_q_emitItemClicked(QModelIndex)));
- QObject::connect(q, SIGNAL(doubleClicked(QModelIndex)),
- q, SLOT(_q_emitItemDoubleClicked(QModelIndex)));
- QObject::connect(q, SIGNAL(activated(QModelIndex)),
- q, SLOT(_q_emitItemActivated(QModelIndex)));
- QObject::connect(q, SIGNAL(entered(QModelIndex)), q, SLOT(_q_emitItemEntered(QModelIndex)));
- QObject::connect(model, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
- q, SLOT(_q_emitItemChanged(QModelIndex)));
- QObject::connect(model, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
- q, SLOT(_q_dataChanged(QModelIndex,QModelIndex)));
- QObject::connect(model, SIGNAL(columnsRemoved(QModelIndex,int,int)), q, SLOT(_q_sort()));
-}
-
-void QListWidgetPrivate::_q_emitItemPressed(const QModelIndex &index)
+ connections = {
+ QObjectPrivate::connect(q, &QListWidget::pressed,
+ this, &QListWidgetPrivate::emitItemPressed),
+ QObjectPrivate::connect(q, &QListWidget::clicked,
+ this, &QListWidgetPrivate::emitItemClicked),
+ QObjectPrivate::connect(q, &QListWidget::doubleClicked,
+ this, &QListWidgetPrivate::emitItemDoubleClicked),
+ QObjectPrivate::connect(q, &QListWidget::activated,
+ this, &QListWidgetPrivate::emitItemActivated),
+ QObjectPrivate::connect(q, &QListWidget::entered,
+ this, &QListWidgetPrivate::emitItemEntered),
+ QObjectPrivate::connect(model, &QAbstractItemModel::dataChanged,
+ this, &QListWidgetPrivate::emitItemChanged),
+ QObjectPrivate::connect(model, &QAbstractItemModel::dataChanged,
+ this, &QListWidgetPrivate::dataChanged),
+ QObjectPrivate::connect(model, &QAbstractItemModel::columnsRemoved,
+ this, &QListWidgetPrivate::sort)
+ };
+}
+
+void QListWidgetPrivate::clearConnections()
+{
+ for (const QMetaObject::Connection &connection : connections)
+ QObject::disconnect(connection);
+ for (const QMetaObject::Connection &connection : selectionModelConnections)
+ QObject::disconnect(connection);
+}
+
+void QListWidgetPrivate::emitItemPressed(const QModelIndex &index)
{
Q_Q(QListWidget);
emit q->itemPressed(listModel()->at(index.row()));
}
-void QListWidgetPrivate::_q_emitItemClicked(const QModelIndex &index)
+void QListWidgetPrivate::emitItemClicked(const QModelIndex &index)
{
Q_Q(QListWidget);
emit q->itemClicked(listModel()->at(index.row()));
}
-void QListWidgetPrivate::_q_emitItemDoubleClicked(const QModelIndex &index)
+void QListWidgetPrivate::emitItemDoubleClicked(const QModelIndex &index)
{
Q_Q(QListWidget);
emit q->itemDoubleClicked(listModel()->at(index.row()));
}
-void QListWidgetPrivate::_q_emitItemActivated(const QModelIndex &index)
+void QListWidgetPrivate::emitItemActivated(const QModelIndex &index)
{
Q_Q(QListWidget);
emit q->itemActivated(listModel()->at(index.row()));
}
-void QListWidgetPrivate::_q_emitItemEntered(const QModelIndex &index)
+void QListWidgetPrivate::emitItemEntered(const QModelIndex &index)
{
Q_Q(QListWidget);
emit q->itemEntered(listModel()->at(index.row()));
}
-void QListWidgetPrivate::_q_emitItemChanged(const QModelIndex &index)
+void QListWidgetPrivate::emitItemChanged(const QModelIndex &index)
{
Q_Q(QListWidget);
emit q->itemChanged(listModel()->at(index.row()));
}
-void QListWidgetPrivate::_q_emitCurrentItemChanged(const QModelIndex &current,
+void QListWidgetPrivate::emitCurrentItemChanged(const QModelIndex &current,
const QModelIndex &previous)
{
Q_Q(QListWidget);
@@ -1194,14 +1165,14 @@ void QListWidgetPrivate::_q_emitCurrentItemChanged(const QModelIndex &current,
emit q->currentRowChanged(persistentCurrent.row());
}
-void QListWidgetPrivate::_q_sort()
+void QListWidgetPrivate::sort()
{
if (sortingEnabled)
model->sort(0, sortOrder);
}
-void QListWidgetPrivate::_q_dataChanged(const QModelIndex &topLeft,
- const QModelIndex &bottomRight)
+void QListWidgetPrivate::dataChanged(const QModelIndex &topLeft,
+ const QModelIndex &bottomRight)
{
if (sortingEnabled && topLeft.isValid() && bottomRight.isValid())
listModel()->ensureSorted(topLeft.column(), sortOrder,
@@ -1407,6 +1378,8 @@ QListWidget::QListWidget(QWidget *parent)
QListWidget::~QListWidget()
{
+ Q_D(QListWidget);
+ d->clearConnections();
}
/*!
@@ -1417,20 +1390,18 @@ void QListWidget::setSelectionModel(QItemSelectionModel *selectionModel)
{
Q_D(QListWidget);
- if (d->selectionModel) {
- QObject::disconnect(d->selectionModel, SIGNAL(currentChanged(QModelIndex,QModelIndex)),
- this, SLOT(_q_emitCurrentItemChanged(QModelIndex,QModelIndex)));
- QObject::disconnect(d->selectionModel, SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
- this, SIGNAL(itemSelectionChanged()));
- }
+ for (const QMetaObject::Connection &connection : d->selectionModelConnections)
+ disconnect(connection);
QListView::setSelectionModel(selectionModel);
if (d->selectionModel) {
- QObject::connect(d->selectionModel, SIGNAL(currentChanged(QModelIndex,QModelIndex)),
- this, SLOT(_q_emitCurrentItemChanged(QModelIndex,QModelIndex)));
- QObject::connect(d->selectionModel, SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
- this, SIGNAL(itemSelectionChanged()));
+ d->selectionModelConnections = {
+ QObjectPrivate::connect(d->selectionModel, &QItemSelectionModel::currentChanged,
+ d, &QListWidgetPrivate::emitCurrentItemChanged),
+ QObject::connect(d->selectionModel, &QItemSelectionModel::selectionChanged,
+ this, &QListWidget::itemSelectionChanged)
+ };
}
}
diff --git a/src/widgets/itemviews/qlistwidget.h b/src/widgets/itemviews/qlistwidget.h
index 516553b71b..c6ba714c43 100644
--- a/src/widgets/itemviews/qlistwidget.h
+++ b/src/widgets/itemviews/qlistwidget.h
@@ -258,16 +258,6 @@ private:
Q_DECLARE_PRIVATE(QListWidget)
Q_DISABLE_COPY(QListWidget)
-
- Q_PRIVATE_SLOT(d_func(), void _q_emitItemPressed(const QModelIndex &index))
- Q_PRIVATE_SLOT(d_func(), void _q_emitItemClicked(const QModelIndex &index))
- Q_PRIVATE_SLOT(d_func(), void _q_emitItemDoubleClicked(const QModelIndex &index))
- Q_PRIVATE_SLOT(d_func(), void _q_emitItemActivated(const QModelIndex &index))
- Q_PRIVATE_SLOT(d_func(), void _q_emitItemEntered(const QModelIndex &index))
- Q_PRIVATE_SLOT(d_func(), void _q_emitItemChanged(const QModelIndex &index))
- Q_PRIVATE_SLOT(d_func(), void _q_emitCurrentItemChanged(const QModelIndex &previous, const QModelIndex &current))
- Q_PRIVATE_SLOT(d_func(), void _q_sort())
- Q_PRIVATE_SLOT(d_func(), void _q_dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight))
};
inline void QListWidget::removeItemWidget(QListWidgetItem *aItem)
diff --git a/src/widgets/itemviews/qlistwidget_p.h b/src/widgets/itemviews/qlistwidget_p.h
index edcacf0436..1007542ddc 100644
--- a/src/widgets/itemviews/qlistwidget_p.h
+++ b/src/widgets/itemviews/qlistwidget_p.h
@@ -18,10 +18,11 @@
#include <QtCore/qabstractitemmodel.h>
#include <QtWidgets/qabstractitemview.h>
#include <QtWidgets/qlistwidget.h>
-#include <qitemdelegate.h>
#include <private/qlistview_p.h>
#include <private/qwidgetitemdata_p.h>
+#include <array>
+
QT_REQUIRE_CONFIG(listwidget);
QT_BEGIN_NAMESPACE
@@ -113,17 +114,21 @@ public:
QListWidgetPrivate() : QListViewPrivate(), sortOrder(Qt::AscendingOrder), sortingEnabled(false) {}
inline QListModel *listModel() const { return qobject_cast<QListModel*>(model); }
void setup();
- void _q_emitItemPressed(const QModelIndex &index);
- void _q_emitItemClicked(const QModelIndex &index);
- void _q_emitItemDoubleClicked(const QModelIndex &index);
- void _q_emitItemActivated(const QModelIndex &index);
- void _q_emitItemEntered(const QModelIndex &index);
- void _q_emitItemChanged(const QModelIndex &index);
- void _q_emitCurrentItemChanged(const QModelIndex &current, const QModelIndex &previous);
- void _q_sort();
- void _q_dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight);
+ void clearConnections();
+ void emitItemPressed(const QModelIndex &index);
+ void emitItemClicked(const QModelIndex &index);
+ void emitItemDoubleClicked(const QModelIndex &index);
+ void emitItemActivated(const QModelIndex &index);
+ void emitItemEntered(const QModelIndex &index);
+ void emitItemChanged(const QModelIndex &index);
+ void emitCurrentItemChanged(const QModelIndex &current, const QModelIndex &previous);
+ void sort();
+ void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight);
Qt::SortOrder sortOrder;
bool sortingEnabled;
+
+ std::array<QMetaObject::Connection, 8> connections;
+ std::array<QMetaObject::Connection, 2> selectionModelConnections;
};
class QListWidgetItemPrivate
diff --git a/src/widgets/itemviews/qstyleditemdelegate.cpp b/src/widgets/itemviews/qstyleditemdelegate.cpp
index 7442fc58c8..54c1fb4f52 100644
--- a/src/widgets/itemviews/qstyleditemdelegate.cpp
+++ b/src/widgets/itemviews/qstyleditemdelegate.cpp
@@ -137,12 +137,17 @@ public:
instance provided by QItemEditorFactory is installed on all item
delegates. You can set a custom factory using
setItemEditorFactory() or set a new default factory with
- QItemEditorFactory::setDefaultFactory(). It is the data stored in
- the item model with the \l{Qt::}{EditRole} that is edited. See the
- QItemEditorFactory class for a more high-level introduction to
- item editor factories. The \l{Color Editor Factory Example}{Color
- Editor Factory} example shows how to create custom editors with a
- factory.
+ QItemEditorFactory::setDefaultFactory().
+
+ \snippet code/src_gui_itemviews_qitemeditorfactory.cpp setDefaultFactory
+
+ After the new factory has been set, all standard item delegates
+ will use it (i.e, also delegates that were created before the new
+ default factory was set).
+
+ It is the data stored in the item model with the \l{Qt::}{EditRole}
+ that is edited. See the QItemEditorFactory class for a more
+ high-level introduction to item editor factories.
\section1 Subclassing QStyledItemDelegate
@@ -204,8 +209,7 @@ public:
documentation for details.
\sa {Delegate Classes}, QItemDelegate, QAbstractItemDelegate, QStyle,
- {Spin Box Delegate Example}, {Star Delegate Example}, {Color
- Editor Factory Example}
+ {Star Delegate Example}
*/
@@ -285,6 +289,10 @@ void QStyledItemDelegate::initStyleOption(QStyleOptionViewItem *option,
switch (value->userType()) {
case QMetaType::QIcon: {
option->icon = qvariant_cast<QIcon>(*value);
+ if (option->icon.isNull()) {
+ option->features &= ~QStyleOptionViewItem::HasDecoration;
+ break;
+ }
QIcon::Mode mode;
if (!(option->state & QStyle::State_Enabled))
mode = QIcon::Disabled;
@@ -473,15 +481,7 @@ void QStyledItemDelegate::updateEditorGeometry(QWidget *editor,
QStyleOptionViewItem opt = option;
initStyleOption(&opt, index);
- // let the editor take up all available space
- //if the editor is not a QLineEdit
- //or it is in a QTableView
-#if QT_CONFIG(tableview) && QT_CONFIG(lineedit)
- if (qobject_cast<QExpandingLineEdit*>(editor) && !qobject_cast<const QTableView*>(widget))
- opt.showDecorationSelected = editor->style()->styleHint(QStyle::SH_ItemView_ShowDecorationSelected, nullptr, editor);
- else
-#endif
- opt.showDecorationSelected = true;
+ opt.showDecorationSelected = editor->style()->styleHint(QStyle::SH_ItemView_ShowDecorationSelected, nullptr, editor);
QStyle *style = widget ? widget->style() : QApplication::style();
QRect geom = style->subElementRect(QStyle::SE_ItemViewItemText, &opt, widget);
diff --git a/src/widgets/itemviews/qtableview.cpp b/src/widgets/itemviews/qtableview.cpp
index cfde93a477..5726348bc5 100644
--- a/src/widgets/itemviews/qtableview.cpp
+++ b/src/widgets/itemviews/qtableview.cpp
@@ -4,7 +4,7 @@
#include "qtableview.h"
#include <qheaderview.h>
-#include <qitemdelegate.h>
+#include <qabstractitemdelegate.h>
#include <qapplication.h>
#include <qpainter.h>
#include <qstyle.h>
@@ -170,6 +170,13 @@ QDebug operator<<(QDebug str, const QSpanCollection::Span &span)
str << '(' << span.top() << ',' << span.left() << ',' << span.bottom() << ',' << span.right() << ')';
return str;
}
+
+QDebug operator<<(QDebug debug, const QSpanCollection::SpanList &spans)
+{
+ for (const auto *span : spans)
+ debug << span << *span;
+ return debug;
+}
#endif
/** \internal
@@ -200,8 +207,7 @@ void QSpanCollection::updateInsertedRows(int start, int end)
#ifdef DEBUG_SPAN_UPDATE
qDebug("After");
- foreach (QSpanCollection::Span *span, spans)
- qDebug() << span << *span;
+ qDebug() << spans;
#endif
for (Index::iterator it_y = index.begin(); it_y != index.end(); ) {
@@ -247,8 +253,7 @@ void QSpanCollection::updateInsertedColumns(int start, int end)
#ifdef DEBUG_SPAN_UPDATE
qDebug("After");
- foreach (QSpanCollection::Span *span, spans)
- qDebug() << span << *span;
+ qDebug() << spans;
#endif
for (Index::iterator it_y = index.begin(); it_y != index.end(); ++it_y) {
@@ -352,8 +357,7 @@ void QSpanCollection::updateRemovedRows(int start, int end)
#ifdef DEBUG_SPAN_UPDATE
qDebug("After");
- foreach (QSpanCollection::Span *span, spans)
- qDebug() << span << *span;
+ qDebug() << spans;
#endif
if (spans.empty()) {
qDeleteAll(spansToBeDeleted);
@@ -420,8 +424,7 @@ void QSpanCollection::updateRemovedRows(int start, int end)
#ifdef DEBUG_SPAN_UPDATE
qDebug() << index;
qDebug("Deleted");
- foreach (QSpanCollection::Span *span, spansToBeDeleted)
- qDebug() << span << *span;
+ qDebug() << spansToBeDeleted;
#endif
qDeleteAll(spansToBeDeleted);
}
@@ -479,8 +482,7 @@ void QSpanCollection::updateRemovedColumns(int start, int end)
#ifdef DEBUG_SPAN_UPDATE
qDebug("After");
- foreach (QSpanCollection::Span *span, spans)
- qDebug() << span << *span;
+ qDebug() << spans;
#endif
if (spans.empty()) {
qDeleteAll(toBeDeleted);
@@ -499,8 +501,7 @@ void QSpanCollection::updateRemovedColumns(int start, int end)
#ifdef DEBUG_SPAN_UPDATE
qDebug() << index;
qDebug("Deleted");
- foreach (QSpanCollection::Span *span, toBeDeleted)
- qDebug() << span << *span;
+ qDebug() << toBeDeleted;
#endif
qDeleteAll(toBeDeleted);
}
@@ -592,7 +593,25 @@ void QTableViewPrivate::init()
#if QT_CONFIG(abstractbutton)
cornerWidget = new QTableCornerButton(q);
cornerWidget->setFocusPolicy(Qt::NoFocus);
- QObject::connect(cornerWidget, SIGNAL(clicked()), q, SLOT(selectAll()));
+ cornerWidgetConnection = QObject::connect(
+ cornerWidget, &QTableCornerButton::clicked,
+ q, &QTableView::selectAll);
+#endif
+}
+
+void QTableViewPrivate::clearConnections()
+{
+ for (const QMetaObject::Connection &connection : modelConnections)
+ QObject::disconnect(connection);
+ for (const QMetaObject::Connection &connection : verHeaderConnections)
+ QObject::disconnect(connection);
+ for (const QMetaObject::Connection &connection : horHeaderConnections)
+ QObject::disconnect(connection);
+ for (const QMetaObject::Connection &connection : dynHorHeaderConnections)
+ QObject::disconnect(connection);
+ QObject::disconnect(selectionmodelConnection);
+#if QT_CONFIG(abstractbutton)
+ QObject::disconnect(cornerWidgetConnection);
#endif
}
@@ -956,7 +975,7 @@ void QTableViewPrivate::drawAndClipSpans(const QRegion &area, QPainter *painter,
\internal
Updates spans after row insertion.
*/
-void QTableViewPrivate::_q_updateSpanInsertedRows(const QModelIndex &parent, int start, int end)
+void QTableViewPrivate::updateSpanInsertedRows(const QModelIndex &parent, int start, int end)
{
Q_UNUSED(parent);
spans.updateInsertedRows(start, end);
@@ -966,7 +985,7 @@ void QTableViewPrivate::_q_updateSpanInsertedRows(const QModelIndex &parent, int
\internal
Updates spans after column insertion.
*/
-void QTableViewPrivate::_q_updateSpanInsertedColumns(const QModelIndex &parent, int start, int end)
+void QTableViewPrivate::updateSpanInsertedColumns(const QModelIndex &parent, int start, int end)
{
Q_UNUSED(parent);
spans.updateInsertedColumns(start, end);
@@ -976,7 +995,7 @@ void QTableViewPrivate::_q_updateSpanInsertedColumns(const QModelIndex &parent,
\internal
Updates spans after row removal.
*/
-void QTableViewPrivate::_q_updateSpanRemovedRows(const QModelIndex &parent, int start, int end)
+void QTableViewPrivate::updateSpanRemovedRows(const QModelIndex &parent, int start, int end)
{
Q_UNUSED(parent);
spans.updateRemovedRows(start, end);
@@ -986,7 +1005,7 @@ void QTableViewPrivate::_q_updateSpanRemovedRows(const QModelIndex &parent, int
\internal
Updates spans after column removal.
*/
-void QTableViewPrivate::_q_updateSpanRemovedColumns(const QModelIndex &parent, int start, int end)
+void QTableViewPrivate::updateSpanRemovedColumns(const QModelIndex &parent, int start, int end)
{
Q_UNUSED(parent);
spans.updateRemovedColumns(start, end);
@@ -996,7 +1015,7 @@ void QTableViewPrivate::_q_updateSpanRemovedColumns(const QModelIndex &parent, i
\internal
Sort the model when the header sort indicator changed
*/
-void QTableViewPrivate::_q_sortIndicatorChanged(int column, Qt::SortOrder order)
+void QTableViewPrivate::sortIndicatorChanged(int column, Qt::SortOrder order)
{
model->sort(column, order);
}
@@ -1188,7 +1207,7 @@ int QTableViewPrivate::heightHintForIndex(const QModelIndex &index, int hint, QS
operations between x-coordinates and column indexes.
\sa QTableWidget, {View Classes}, QAbstractItemModel, QAbstractItemView,
- {Chart Example}, {Pixelator Example}, {Table Model Example}
+ {Table Model Example}
*/
/*!
@@ -1219,6 +1238,8 @@ QTableView::QTableView(QTableViewPrivate &dd, QWidget *parent)
*/
QTableView::~QTableView()
{
+ Q_D(QTableView);
+ d->clearConnections();
}
/*!
@@ -1242,28 +1263,23 @@ void QTableView::setModel(QAbstractItemModel *model)
return;
//let's disconnect from the old model
if (d->model && d->model != QAbstractItemModelPrivate::staticEmptyModel()) {
- disconnect(d->model, SIGNAL(rowsInserted(QModelIndex,int,int)),
- this, SLOT(_q_updateSpanInsertedRows(QModelIndex,int,int)));
- disconnect(d->model, SIGNAL(columnsInserted(QModelIndex,int,int)),
- this, SLOT(_q_updateSpanInsertedColumns(QModelIndex,int,int)));
- disconnect(d->model, SIGNAL(rowsRemoved(QModelIndex,int,int)),
- this, SLOT(_q_updateSpanRemovedRows(QModelIndex,int,int)));
- disconnect(d->model, SIGNAL(columnsRemoved(QModelIndex,int,int)),
- this, SLOT(_q_updateSpanRemovedColumns(QModelIndex,int,int)));
+ for (const QMetaObject::Connection &connection : d->modelConnections)
+ disconnect(connection);
}
if (d->selectionModel) { // support row editing
- disconnect(d->selectionModel, SIGNAL(currentRowChanged(QModelIndex,QModelIndex)),
- d->model, SLOT(submit()));
+ disconnect(d->selectionmodelConnection);
}
if (model) { //and connect to the new one
- connect(model, SIGNAL(rowsInserted(QModelIndex,int,int)),
- this, SLOT(_q_updateSpanInsertedRows(QModelIndex,int,int)));
- connect(model, SIGNAL(columnsInserted(QModelIndex,int,int)),
- this, SLOT(_q_updateSpanInsertedColumns(QModelIndex,int,int)));
- connect(model, SIGNAL(rowsRemoved(QModelIndex,int,int)),
- this, SLOT(_q_updateSpanRemovedRows(QModelIndex,int,int)));
- connect(model, SIGNAL(columnsRemoved(QModelIndex,int,int)),
- this, SLOT(_q_updateSpanRemovedColumns(QModelIndex,int,int)));
+ d->modelConnections = {
+ QObjectPrivate::connect(model, &QAbstractItemModel::rowsInserted,
+ d, &QTableViewPrivate::updateSpanInsertedRows),
+ QObjectPrivate::connect(model, &QAbstractItemModel::columnsInserted,
+ d, &QTableViewPrivate::updateSpanInsertedColumns),
+ QObjectPrivate::connect(model, &QAbstractItemModel::rowsRemoved,
+ d, &QTableViewPrivate::updateSpanRemovedRows),
+ QObjectPrivate::connect(model, &QAbstractItemModel::columnsRemoved,
+ d, &QTableViewPrivate::updateSpanRemovedColumns)
+ };
}
d->verticalHeader->setModel(model);
d->horizontalHeader->setModel(model);
@@ -1305,8 +1321,7 @@ void QTableView::setSelectionModel(QItemSelectionModel *selectionModel)
Q_ASSERT(selectionModel);
if (d->selectionModel) {
// support row editing
- disconnect(d->selectionModel, SIGNAL(currentRowChanged(QModelIndex,QModelIndex)),
- d->model, SLOT(submit()));
+ disconnect(d->selectionmodelConnection);
}
d->verticalHeader->setSelectionModel(selectionModel);
@@ -1315,8 +1330,9 @@ void QTableView::setSelectionModel(QItemSelectionModel *selectionModel)
if (d->selectionModel) {
// support row editing
- connect(d->selectionModel, SIGNAL(currentRowChanged(QModelIndex,QModelIndex)),
- d->model, SLOT(submit()));
+ d->selectionmodelConnection =
+ connect(d->selectionModel, &QItemSelectionModel::currentRowChanged,
+ d->model, &QAbstractItemModel::submit);
}
}
@@ -1353,6 +1369,8 @@ void QTableView::setHorizontalHeader(QHeaderView *header)
if (!header || header == d->horizontalHeader)
return;
+ for (const QMetaObject::Connection &connection : d->horHeaderConnections)
+ disconnect(connection);
if (d->horizontalHeader && d->horizontalHeader->parent() == this)
delete d->horizontalHeader;
d->horizontalHeader = header;
@@ -1364,18 +1382,18 @@ void QTableView::setHorizontalHeader(QHeaderView *header)
d->horizontalHeader->setSelectionModel(d->selectionModel);
}
- connect(d->horizontalHeader,SIGNAL(sectionResized(int,int,int)),
- this, SLOT(columnResized(int,int,int)));
- connect(d->horizontalHeader, SIGNAL(sectionMoved(int,int,int)),
- this, SLOT(columnMoved(int,int,int)));
- connect(d->horizontalHeader, SIGNAL(sectionCountChanged(int,int)),
- this, SLOT(columnCountChanged(int,int)));
- connect(d->horizontalHeader, SIGNAL(sectionPressed(int)), this, SLOT(selectColumn(int)));
- connect(d->horizontalHeader, SIGNAL(sectionEntered(int)), this, SLOT(_q_selectColumn(int)));
- connect(d->horizontalHeader, SIGNAL(sectionHandleDoubleClicked(int)),
- this, SLOT(resizeColumnToContents(int)));
- connect(d->horizontalHeader, SIGNAL(geometriesChanged()), this, SLOT(updateGeometries()));
-
+ d->horHeaderConnections = {
+ connect(d->horizontalHeader,&QHeaderView::sectionResized,
+ this, &QTableView::columnResized),
+ connect(d->horizontalHeader, &QHeaderView::sectionMoved,
+ this, &QTableView::columnMoved),
+ connect(d->horizontalHeader, &QHeaderView::sectionCountChanged,
+ this, &QTableView::columnCountChanged),
+ connect(d->horizontalHeader, &QHeaderView::sectionHandleDoubleClicked,
+ this, &QTableView::resizeColumnToContents),
+ connect(d->horizontalHeader, &QHeaderView::geometriesChanged,
+ this, &QTableView::updateGeometries),
+ };
//update the sorting enabled states on the new header
setSortingEnabled(d->sortingEnabled);
}
@@ -1391,6 +1409,8 @@ void QTableView::setVerticalHeader(QHeaderView *header)
if (!header || header == d->verticalHeader)
return;
+ for (const QMetaObject::Connection &connection : d->verHeaderConnections)
+ disconnect(connection);
if (d->verticalHeader && d->verticalHeader->parent() == this)
delete d->verticalHeader;
d->verticalHeader = header;
@@ -1402,17 +1422,22 @@ void QTableView::setVerticalHeader(QHeaderView *header)
d->verticalHeader->setSelectionModel(d->selectionModel);
}
- connect(d->verticalHeader, SIGNAL(sectionResized(int,int,int)),
- this, SLOT(rowResized(int,int,int)));
- connect(d->verticalHeader, SIGNAL(sectionMoved(int,int,int)),
- this, SLOT(rowMoved(int,int,int)));
- connect(d->verticalHeader, SIGNAL(sectionCountChanged(int,int)),
- this, SLOT(rowCountChanged(int,int)));
- connect(d->verticalHeader, SIGNAL(sectionPressed(int)), this, SLOT(selectRow(int)));
- connect(d->verticalHeader, SIGNAL(sectionEntered(int)), this, SLOT(_q_selectRow(int)));
- connect(d->verticalHeader, SIGNAL(sectionHandleDoubleClicked(int)),
- this, SLOT(resizeRowToContents(int)));
- connect(d->verticalHeader, SIGNAL(geometriesChanged()), this, SLOT(updateGeometries()));
+ d->verHeaderConnections = {
+ connect(d->verticalHeader, &QHeaderView::sectionResized,
+ this, &QTableView::rowResized),
+ connect(d->verticalHeader, &QHeaderView::sectionMoved,
+ this, &QTableView::rowMoved),
+ connect(d->verticalHeader, &QHeaderView::sectionCountChanged,
+ this, &QTableView::rowCountChanged),
+ connect(d->verticalHeader, &QHeaderView::sectionPressed,
+ this, &QTableView::selectRow),
+ connect(d->verticalHeader, &QHeaderView::sectionHandleDoubleClicked,
+ this, &QTableView::resizeRowToContents),
+ connect(d->verticalHeader, &QHeaderView::geometriesChanged,
+ this, &QTableView::updateGeometries),
+ connect(d->verticalHeader, &QHeaderView::sectionEntered,
+ this, [d](int row) { d->selectRow(row, false); })
+ };
}
/*!
@@ -2407,12 +2432,12 @@ int QTableView::sizeHintForRow(int row) const
break;
}
- int actualRight = d->model->columnCount(d->root) - 1;
+ const int actualRight = d->model->columnCount(d->root) - 1;
int idxLeft = left;
int idxRight = column - 1;
- if (maximumProcessCols == 0)
- columnsProcessed = 0; // skip the while loop
+ if (maximumProcessCols == 0 || actualRight < idxLeft)
+ columnsProcessed = maximumProcessCols; // skip the while loop
while (columnsProcessed != maximumProcessCols && (idxLeft > 0 || idxRight < actualRight)) {
int logicalIdx = -1;
@@ -2436,11 +2461,10 @@ int QTableView::sizeHintForRow(int row) const
break;
}
}
- if (logicalIdx < 0)
- continue;
-
- index = d->model->index(row, logicalIdx, d->root);
- hint = d->heightHintForIndex(index, hint, option);
+ if (logicalIdx >= 0) {
+ index = d->model->index(row, logicalIdx, d->root);
+ hint = d->heightHintForIndex(index, hint, option);
+ }
++columnsProcessed;
}
@@ -2496,12 +2520,12 @@ int QTableView::sizeHintForColumn(int column) const
break;
}
- int actualBottom = d->model->rowCount(d->root) - 1;
+ const int actualBottom = d->model->rowCount(d->root) - 1;
int idxTop = top;
int idxBottom = row - 1;
- if (maximumProcessRows == 0)
- rowsProcessed = 0; // skip the while loop
+ if (maximumProcessRows == 0 || actualBottom < idxTop)
+ rowsProcessed = maximumProcessRows; // skip the while loop
while (rowsProcessed != maximumProcessRows && (idxTop > 0 || idxBottom < actualBottom)) {
int logicalIdx = -1;
@@ -2525,11 +2549,10 @@ int QTableView::sizeHintForColumn(int column) const
break;
}
}
- if (logicalIdx < 0)
- continue;
-
- index = d->model->index(logicalIdx, column, d->root);
- hint = d->widthHintForIndex(index, hint, option);
+ if (logicalIdx >= 0) {
+ index = d->model->index(logicalIdx, column, d->root);
+ hint = d->widthHintForIndex(index, hint, option);
+ }
++rowsProcessed;
}
@@ -2704,24 +2727,25 @@ void QTableView::setSortingEnabled(bool enable)
{
Q_D(QTableView);
horizontalHeader()->setSortIndicatorShown(enable);
+ for (const QMetaObject::Connection &connection : d->dynHorHeaderConnections)
+ disconnect(connection);
+ d->dynHorHeaderConnections.clear();
if (enable) {
- disconnect(d->horizontalHeader, SIGNAL(sectionEntered(int)),
- this, SLOT(_q_selectColumn(int)));
- disconnect(horizontalHeader(), SIGNAL(sectionPressed(int)),
- this, SLOT(selectColumn(int)));
//sortByColumn has to be called before we connect or set the sortingEnabled flag
// because otherwise it will not call sort on the model.
- sortByColumn(horizontalHeader()->sortIndicatorSection(),
- horizontalHeader()->sortIndicatorOrder());
- connect(horizontalHeader(), SIGNAL(sortIndicatorChanged(int,Qt::SortOrder)),
- this, SLOT(_q_sortIndicatorChanged(int,Qt::SortOrder)), Qt::UniqueConnection);
+ sortByColumn(d->horizontalHeader->sortIndicatorSection(),
+ d->horizontalHeader->sortIndicatorOrder());
+ d->dynHorHeaderConnections = {
+ QObjectPrivate::connect(d->horizontalHeader, &QHeaderView::sortIndicatorChanged,
+ d, &QTableViewPrivate::sortIndicatorChanged)
+ };
} else {
- connect(d->horizontalHeader, SIGNAL(sectionEntered(int)),
- this, SLOT(_q_selectColumn(int)), Qt::UniqueConnection);
- connect(horizontalHeader(), SIGNAL(sectionPressed(int)),
- this, SLOT(selectColumn(int)), Qt::UniqueConnection);
- disconnect(horizontalHeader(), SIGNAL(sortIndicatorChanged(int,Qt::SortOrder)),
- this, SLOT(_q_sortIndicatorChanged(int,Qt::SortOrder)));
+ d->dynHorHeaderConnections = {
+ connect(d->horizontalHeader, &QHeaderView::sectionPressed,
+ this, &QTableView::selectColumn),
+ connect(d->horizontalHeader, &QHeaderView::sectionEntered,
+ this, [d](int column) {d->selectColumn(column, false); })
+ };
}
d->sortingEnabled = enable;
}
@@ -3381,16 +3405,6 @@ void QTableView::clearSpans()
d->viewport->update();
}
-void QTableViewPrivate::_q_selectRow(int row)
-{
- selectRow(row, false);
-}
-
-void QTableViewPrivate::_q_selectColumn(int column)
-{
- selectColumn(column, false);
-}
-
void QTableViewPrivate::selectRow(int row, bool anchor)
{
Q_Q(QTableView);
@@ -3478,7 +3492,7 @@ void QTableView::currentChanged(const QModelIndex &current, const QModelIndex &p
{
#if QT_CONFIG(accessibility)
if (QAccessible::isActive()) {
- if (current.isValid()) {
+ if (current.isValid() && hasFocus()) {
Q_D(QTableView);
int entry = d->accessibleTable2Index(current);
QAccessibleEvent event(this, QAccessible::Focus);
diff --git a/src/widgets/itemviews/qtableview.h b/src/widgets/itemviews/qtableview.h
index 955b29995c..eff0ea3502 100644
--- a/src/widgets/itemviews/qtableview.h
+++ b/src/widgets/itemviews/qtableview.h
@@ -145,13 +145,6 @@ private:
Q_DECLARE_PRIVATE(QTableView)
Q_DISABLE_COPY(QTableView)
- Q_PRIVATE_SLOT(d_func(), void _q_selectRow(int))
- Q_PRIVATE_SLOT(d_func(), void _q_selectColumn(int))
- Q_PRIVATE_SLOT(d_func(), void _q_updateSpanInsertedRows(QModelIndex,int,int))
- Q_PRIVATE_SLOT(d_func(), void _q_updateSpanInsertedColumns(QModelIndex,int,int))
- Q_PRIVATE_SLOT(d_func(), void _q_updateSpanRemovedRows(QModelIndex,int,int))
- Q_PRIVATE_SLOT(d_func(), void _q_updateSpanRemovedColumns(QModelIndex,int,int))
- Q_PRIVATE_SLOT(d_func(), void _q_sortIndicatorChanged(int column, Qt::SortOrder order))
};
QT_END_NAMESPACE
diff --git a/src/widgets/itemviews/qtableview_p.h b/src/widgets/itemviews/qtableview_p.h
index 582330c7b5..862a016d5f 100644
--- a/src/widgets/itemviews/qtableview_p.h
+++ b/src/widgets/itemviews/qtableview_p.h
@@ -16,13 +16,18 @@
//
#include <QtWidgets/private/qtwidgetsglobal_p.h>
+#include "qtableview.h"
+#include "qheaderview.h"
+
#include <QtCore/QList>
#include <QtCore/QMap>
#include <QtCore/QSet>
#include <QtCore/QDebug>
#include "private/qabstractitemview_p.h"
+#include <array>
#include <list>
+#include <vector>
QT_REQUIRE_CONFIG(tableview);
@@ -93,7 +98,9 @@ private:
Q_DECLARE_TYPEINFO ( QSpanCollection::Span, Q_RELOCATABLE_TYPE);
-
+#if QT_CONFIG(abstractbutton)
+class QTableCornerButton;
+#endif
class Q_AUTOTEST_EXPORT QTableViewPrivate : public QAbstractItemViewPrivate
{
Q_DECLARE_PUBLIC(QTableView)
@@ -111,6 +118,7 @@ public:
#endif
}
void init();
+ void clearConnections();
void trimHiddenSelections(QItemSelectionRange *range) const;
QRect intersectedRect(const QRect rect, const QModelIndex &topLeft, const QModelIndex &bottomRight) const override;
@@ -156,8 +164,15 @@ public:
QHeaderView *horizontalHeader;
QHeaderView *verticalHeader;
#if QT_CONFIG(abstractbutton)
- QWidget *cornerWidget;
+ QTableCornerButton *cornerWidget;
+ QMetaObject::Connection cornerWidgetConnection;
#endif
+ QMetaObject::Connection selectionmodelConnection;
+ std::array<QMetaObject::Connection, 4> modelConnections;
+ std::array<QMetaObject::Connection, 7> verHeaderConnections;
+ std::array<QMetaObject::Connection, 5> horHeaderConnections;
+ std::vector<QMetaObject::Connection> dynHorHeaderConnections;
+
bool sortingEnabled;
bool geometryRecursionBlock;
QPoint visualCursor; // (Row,column) cell coordinates to track through span navigation.
@@ -210,17 +225,14 @@ public:
QRect visualSpanRect(const QSpanCollection::Span &span) const;
- void _q_selectRow(int row);
- void _q_selectColumn(int column);
-
void selectRow(int row, bool anchor);
void selectColumn(int column, bool anchor);
- void _q_updateSpanInsertedRows(const QModelIndex &parent, int start, int end);
- void _q_updateSpanInsertedColumns(const QModelIndex &parent, int start, int end);
- void _q_updateSpanRemovedRows(const QModelIndex &parent, int start, int end);
- void _q_updateSpanRemovedColumns(const QModelIndex &parent, int start, int end);
- void _q_sortIndicatorChanged(int column, Qt::SortOrder order);
+ void updateSpanInsertedRows(const QModelIndex &parent, int start, int end);
+ void updateSpanInsertedColumns(const QModelIndex &parent, int start, int end);
+ void updateSpanRemovedRows(const QModelIndex &parent, int start, int end);
+ void updateSpanRemovedColumns(const QModelIndex &parent, int start, int end);
+ void sortIndicatorChanged(int column, Qt::SortOrder order);
};
QT_END_NAMESPACE
diff --git a/src/widgets/itemviews/qtablewidget.cpp b/src/widgets/itemviews/qtablewidget.cpp
index 67886be94f..6dd812f6fb 100644
--- a/src/widgets/itemviews/qtablewidget.cpp
+++ b/src/widgets/itemviews/qtablewidget.cpp
@@ -3,7 +3,6 @@
#include "qtablewidget.h"
-#include <qitemdelegate.h>
#include <qpainter.h>
#include <private/qtablewidget_p.h>
@@ -248,7 +247,7 @@ void QTableModel::setHorizontalHeaderItem(int section, QTableWidgetItem *item)
if (item) {
item->view = view;
- item->itemFlags = Qt::ItemFlags(int(item->itemFlags)|ItemIsHeaderItem);
+ item->d->headerItem = true;
}
horizontalHeaderItems[section] = item;
emit headerDataChanged(Qt::Horizontal, section, section);
@@ -270,7 +269,7 @@ void QTableModel::setVerticalHeaderItem(int section, QTableWidgetItem *item)
if (item) {
item->view = view;
- item->itemFlags = Qt::ItemFlags(int(item->itemFlags)|ItemIsHeaderItem);
+ item->d->headerItem = true;
}
verticalHeaderItems[section] = item;
emit headerDataChanged(Qt::Vertical, section, section);
@@ -283,7 +282,7 @@ QTableWidgetItem *QTableModel::takeHorizontalHeaderItem(int section)
QTableWidgetItem *itm = horizontalHeaderItems.at(section);
if (itm) {
itm->view = nullptr;
- itm->itemFlags &= ~ItemIsHeaderItem;
+ itm->d->headerItem = false;
horizontalHeaderItems[section] = 0;
}
return itm;
@@ -296,7 +295,7 @@ QTableWidgetItem *QTableModel::takeVerticalHeaderItem(int section)
QTableWidgetItem *itm = verticalHeaderItems.at(section);
if (itm) {
itm->view = nullptr;
- itm->itemFlags &= ~ItemIsHeaderItem;
+ itm->d->headerItem = false;
verticalHeaderItems[section] = 0;
}
return itm;
@@ -761,7 +760,7 @@ void QTableModel::itemChanged(QTableWidgetItem *item, const QList<int> &roles)
{
if (!item)
return;
- if (item->flags() & ItemIsHeaderItem) {
+ if (item->d->headerItem) {
int row = verticalHeaderItems.indexOf(item);
if (row >= 0) {
emit headerDataChanged(Qt::Vertical, row, row);
@@ -1592,28 +1591,41 @@ QTableWidgetItem &QTableWidgetItem::operator=(const QTableWidgetItem &other)
void QTableWidgetPrivate::setup()
{
Q_Q(QTableWidget);
- // view signals
- QObject::connect(q, SIGNAL(pressed(QModelIndex)), q, SLOT(_q_emitItemPressed(QModelIndex)));
- QObject::connect(q, SIGNAL(clicked(QModelIndex)), q, SLOT(_q_emitItemClicked(QModelIndex)));
- QObject::connect(q, SIGNAL(doubleClicked(QModelIndex)),
- q, SLOT(_q_emitItemDoubleClicked(QModelIndex)));
- QObject::connect(q, SIGNAL(activated(QModelIndex)), q, SLOT(_q_emitItemActivated(QModelIndex)));
- QObject::connect(q, SIGNAL(entered(QModelIndex)), q, SLOT(_q_emitItemEntered(QModelIndex)));
- // model signals
- QObject::connect(model, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
- q, SLOT(_q_emitItemChanged(QModelIndex)));
- // selection signals
- QObject::connect(q->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)),
- q, SLOT(_q_emitCurrentItemChanged(QModelIndex,QModelIndex)));
- QObject::connect(q->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
- q, SIGNAL(itemSelectionChanged()));
- // sorting
- QObject::connect(model, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
- q, SLOT(_q_dataChanged(QModelIndex,QModelIndex)));
- QObject::connect(model, SIGNAL(columnsRemoved(QModelIndex,int,int)), q, SLOT(_q_sort()));
-}
-
-void QTableWidgetPrivate::_q_emitItemPressed(const QModelIndex &index)
+ connections = {
+ // view signals
+ QObjectPrivate::connect(q, &QTableWidget::pressed,
+ this, &QTableWidgetPrivate::emitItemPressed),
+ QObjectPrivate::connect(q, &QTableWidget::clicked,
+ this, &QTableWidgetPrivate::emitItemClicked),
+ QObjectPrivate::connect(q, &QTableWidget::doubleClicked,
+ this, &QTableWidgetPrivate::emitItemDoubleClicked),
+ QObjectPrivate::connect(q, &QTableWidget::activated,
+ this, &QTableWidgetPrivate::emitItemActivated),
+ QObjectPrivate::connect(q, &QTableWidget::entered,
+ this, &QTableWidgetPrivate::emitItemEntered),
+ // model signals
+ QObjectPrivate::connect(model, &QAbstractItemModel::dataChanged,
+ this, &QTableWidgetPrivate::emitItemChanged),
+ // selection signals
+ QObjectPrivate::connect(q->selectionModel(), &QItemSelectionModel::currentChanged,
+ this, &QTableWidgetPrivate::emitCurrentItemChanged),
+ QObject::connect(q->selectionModel(), &QItemSelectionModel::selectionChanged,
+ q, &QTableWidget::itemSelectionChanged),
+ // sorting
+ QObjectPrivate::connect(model, &QAbstractItemModel::dataChanged,
+ this, &QTableWidgetPrivate::dataChanged),
+ QObjectPrivate::connect(model, &QAbstractItemModel::columnsRemoved,
+ this, &QTableWidgetPrivate::sort)
+ };
+}
+
+void QTableWidgetPrivate::clearConnections()
+{
+ for (const QMetaObject::Connection &connection : connections)
+ QObject::disconnect(connection);
+}
+
+void QTableWidgetPrivate::emitItemPressed(const QModelIndex &index)
{
Q_Q(QTableWidget);
if (QTableWidgetItem *item = tableModel()->item(index))
@@ -1621,7 +1633,7 @@ void QTableWidgetPrivate::_q_emitItemPressed(const QModelIndex &index)
emit q->cellPressed(index.row(), index.column());
}
-void QTableWidgetPrivate::_q_emitItemClicked(const QModelIndex &index)
+void QTableWidgetPrivate::emitItemClicked(const QModelIndex &index)
{
Q_Q(QTableWidget);
if (QTableWidgetItem *item = tableModel()->item(index))
@@ -1629,7 +1641,7 @@ void QTableWidgetPrivate::_q_emitItemClicked(const QModelIndex &index)
emit q->cellClicked(index.row(), index.column());
}
-void QTableWidgetPrivate::_q_emitItemDoubleClicked(const QModelIndex &index)
+void QTableWidgetPrivate::emitItemDoubleClicked(const QModelIndex &index)
{
Q_Q(QTableWidget);
if (QTableWidgetItem *item = tableModel()->item(index))
@@ -1637,7 +1649,7 @@ void QTableWidgetPrivate::_q_emitItemDoubleClicked(const QModelIndex &index)
emit q->cellDoubleClicked(index.row(), index.column());
}
-void QTableWidgetPrivate::_q_emitItemActivated(const QModelIndex &index)
+void QTableWidgetPrivate::emitItemActivated(const QModelIndex &index)
{
Q_Q(QTableWidget);
if (QTableWidgetItem *item = tableModel()->item(index))
@@ -1645,7 +1657,7 @@ void QTableWidgetPrivate::_q_emitItemActivated(const QModelIndex &index)
emit q->cellActivated(index.row(), index.column());
}
-void QTableWidgetPrivate::_q_emitItemEntered(const QModelIndex &index)
+void QTableWidgetPrivate::emitItemEntered(const QModelIndex &index)
{
Q_Q(QTableWidget);
if (QTableWidgetItem *item = tableModel()->item(index))
@@ -1653,7 +1665,7 @@ void QTableWidgetPrivate::_q_emitItemEntered(const QModelIndex &index)
emit q->cellEntered(index.row(), index.column());
}
-void QTableWidgetPrivate::_q_emitItemChanged(const QModelIndex &index)
+void QTableWidgetPrivate::emitItemChanged(const QModelIndex &index)
{
Q_Q(QTableWidget);
if (QTableWidgetItem *item = tableModel()->item(index))
@@ -1661,7 +1673,7 @@ void QTableWidgetPrivate::_q_emitItemChanged(const QModelIndex &index)
emit q->cellChanged(index.row(), index.column());
}
-void QTableWidgetPrivate::_q_emitCurrentItemChanged(const QModelIndex &current,
+void QTableWidgetPrivate::emitCurrentItemChanged(const QModelIndex &current,
const QModelIndex &previous)
{
Q_Q(QTableWidget);
@@ -1672,7 +1684,7 @@ void QTableWidgetPrivate::_q_emitCurrentItemChanged(const QModelIndex &current,
emit q->currentCellChanged(current.row(), current.column(), previous.row(), previous.column());
}
-void QTableWidgetPrivate::_q_sort()
+void QTableWidgetPrivate::sort()
{
if (sortingEnabled) {
int column = horizontalHeader->sortIndicatorSection();
@@ -1681,8 +1693,8 @@ void QTableWidgetPrivate::_q_sort()
}
}
-void QTableWidgetPrivate::_q_dataChanged(const QModelIndex &topLeft,
- const QModelIndex &bottomRight)
+void QTableWidgetPrivate::dataChanged(const QModelIndex &topLeft,
+ const QModelIndex &bottomRight)
{
if (sortingEnabled && topLeft.isValid() && bottomRight.isValid()) {
int column = horizontalHeader->sortIndicatorSection();
@@ -1880,6 +1892,8 @@ QTableWidget::QTableWidget(int rows, int columns, QWidget *parent)
*/
QTableWidget::~QTableWidget()
{
+ Q_D(QTableWidget);
+ d->clearConnections();
}
/*!
diff --git a/src/widgets/itemviews/qtablewidget.h b/src/widgets/itemviews/qtablewidget.h
index c7545f13dd..303f4d5f5b 100644
--- a/src/widgets/itemviews/qtablewidget.h
+++ b/src/widgets/itemviews/qtablewidget.h
@@ -23,8 +23,10 @@ public:
friend bool operator==(const QTableWidgetSelectionRange &lhs,
const QTableWidgetSelectionRange &rhs) noexcept
- { return lhs.m_top == rhs.m_top && lhs.m_left == rhs.m_left
- && lhs.m_bottom == rhs.m_bottom && lhs.m_right == rhs.m_right; };
+ {
+ return lhs.m_top == rhs.m_top && lhs.m_left == rhs.m_left && lhs.m_bottom == rhs.m_bottom
+ && lhs.m_right == rhs.m_right;
+ }
friend bool operator!=(const QTableWidgetSelectionRange &lhs,
const QTableWidgetSelectionRange &rhs) noexcept
{ return !(lhs == rhs); }
@@ -310,16 +312,6 @@ private:
Q_DECLARE_PRIVATE(QTableWidget)
Q_DISABLE_COPY(QTableWidget)
-
- Q_PRIVATE_SLOT(d_func(), void _q_emitItemPressed(const QModelIndex &index))
- Q_PRIVATE_SLOT(d_func(), void _q_emitItemClicked(const QModelIndex &index))
- Q_PRIVATE_SLOT(d_func(), void _q_emitItemDoubleClicked(const QModelIndex &index))
- Q_PRIVATE_SLOT(d_func(), void _q_emitItemActivated(const QModelIndex &index))
- Q_PRIVATE_SLOT(d_func(), void _q_emitItemEntered(const QModelIndex &index))
- Q_PRIVATE_SLOT(d_func(), void _q_emitItemChanged(const QModelIndex &index))
- Q_PRIVATE_SLOT(d_func(), void _q_emitCurrentItemChanged(const QModelIndex &previous, const QModelIndex &current))
- Q_PRIVATE_SLOT(d_func(), void _q_sort())
- Q_PRIVATE_SLOT(d_func(), void _q_dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight))
};
inline void QTableWidget::removeCellWidget(int arow, int acolumn)
diff --git a/src/widgets/itemviews/qtablewidget_p.h b/src/widgets/itemviews/qtablewidget_p.h
index 1d893224c0..210910fc52 100644
--- a/src/widgets/itemviews/qtablewidget_p.h
+++ b/src/widgets/itemviews/qtablewidget_p.h
@@ -22,6 +22,8 @@
#include <private/qtableview_p.h>
#include <private/qwidgetitemdata_p.h>
+#include <array>
+
QT_REQUIRE_CONFIG(tablewidget);
QT_BEGIN_NAMESPACE
@@ -53,10 +55,6 @@ class QTableModel : public QAbstractTableModel
friend class QTableWidget;
public:
- enum ItemFlagsExtension {
- ItemIsHeaderItem = 128
- }; // we need this to separate header items from other items
-
QTableModel(int rows, int columns, QTableWidget *parent);
~QTableModel();
@@ -154,28 +152,32 @@ public:
QTableWidgetPrivate() : QTableViewPrivate() {}
inline QTableModel *tableModel() const { return qobject_cast<QTableModel*>(model); }
void setup();
+ void clearConnections();
// view signals
- void _q_emitItemPressed(const QModelIndex &index);
- void _q_emitItemClicked(const QModelIndex &index);
- void _q_emitItemDoubleClicked(const QModelIndex &index);
- void _q_emitItemActivated(const QModelIndex &index);
- void _q_emitItemEntered(const QModelIndex &index);
+ void emitItemPressed(const QModelIndex &index);
+ void emitItemClicked(const QModelIndex &index);
+ void emitItemDoubleClicked(const QModelIndex &index);
+ void emitItemActivated(const QModelIndex &index);
+ void emitItemEntered(const QModelIndex &index);
// model signals
- void _q_emitItemChanged(const QModelIndex &index);
+ void emitItemChanged(const QModelIndex &index);
// selection signals
- void _q_emitCurrentItemChanged(const QModelIndex &previous, const QModelIndex &current);
+ void emitCurrentItemChanged(const QModelIndex &previous, const QModelIndex &current);
// sorting
- void _q_sort();
- void _q_dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight);
+ void sort();
+ void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight);
+
+ std::array<QMetaObject::Connection, 10> connections;
};
class QTableWidgetItemPrivate
{
public:
- QTableWidgetItemPrivate(QTableWidgetItem *item) : q(item), id(-1) {}
+ QTableWidgetItemPrivate(QTableWidgetItem *item) : q(item), id(-1), headerItem(false) {}
QTableWidgetItem *q;
int id;
+ bool headerItem; // Qt 7 TODO: inline this stuff in the public class.
};
QT_END_NAMESPACE
diff --git a/src/widgets/itemviews/qtreeview.cpp b/src/widgets/itemviews/qtreeview.cpp
index 065c42d6b7..1ae81023c5 100644
--- a/src/widgets/itemviews/qtreeview.cpp
+++ b/src/widgets/itemviews/qtreeview.cpp
@@ -3,7 +3,7 @@
#include "qtreeview.h"
#include <qheaderview.h>
-#include <qitemdelegate.h>
+#include <qabstractitemdelegate.h>
#include <qapplication.h>
#include <qscrollbar.h>
#include <qpainter.h>
@@ -124,8 +124,7 @@ QT_BEGIN_NAMESPACE
that can be taken for views that are intended to display items with equal heights
is to set the \l uniformRowHeights property to true.
- \sa QListView, QTreeWidget, {View Classes}, QAbstractItemModel, QAbstractItemView,
- {Dir View Example}
+ \sa QListView, QTreeWidget, {View Classes}, QAbstractItemModel, QAbstractItemView
*/
@@ -170,6 +169,8 @@ QTreeView::QTreeView(QTreeViewPrivate &dd, QWidget *parent)
*/
QTreeView::~QTreeView()
{
+ Q_D(QTreeView);
+ d->clearConnections();
}
/*!
@@ -181,18 +182,12 @@ void QTreeView::setModel(QAbstractItemModel *model)
if (model == d->model)
return;
if (d->model && d->model != QAbstractItemModelPrivate::staticEmptyModel()) {
- disconnect(d->model, SIGNAL(rowsRemoved(QModelIndex,int,int)),
- this, SLOT(rowsRemoved(QModelIndex,int,int)));
-
- disconnect(d->model, SIGNAL(modelAboutToBeReset()), this, SLOT(_q_modelAboutToBeReset()));
+ for (const QMetaObject::Connection &connection : d->modelConnections)
+ QObject::disconnect(connection);
}
if (d->selectionModel) { // support row editing
- disconnect(d->selectionModel, SIGNAL(currentRowChanged(QModelIndex,QModelIndex)),
- d->model, SLOT(submit()));
- disconnect(d->model, SIGNAL(rowsRemoved(QModelIndex,int,int)),
- this, SLOT(rowsRemoved(QModelIndex,int,int)));
- disconnect(d->model, SIGNAL(modelAboutToBeReset()), this, SLOT(_q_modelAboutToBeReset()));
+ QObject::disconnect(d->selectionmodelConnection);
}
d->viewItems.clear();
d->expandedIndexes.clear();
@@ -202,20 +197,24 @@ void QTreeView::setModel(QAbstractItemModel *model)
d->geometryRecursionBlock = false;
QAbstractItemView::setModel(model);
- // QAbstractItemView connects to a private slot
- disconnect(d->model, SIGNAL(rowsRemoved(QModelIndex,int,int)),
- this, SLOT(_q_rowsRemoved(QModelIndex,int,int)));
- // do header layout after the tree
- disconnect(d->model, SIGNAL(layoutChanged()),
- d->header, SLOT(_q_layoutChanged()));
- // QTreeView has a public slot for this
- connect(d->model, SIGNAL(rowsRemoved(QModelIndex,int,int)),
- this, SLOT(rowsRemoved(QModelIndex,int,int)));
-
- connect(d->model, SIGNAL(modelAboutToBeReset()), SLOT(_q_modelAboutToBeReset()));
-
+ if (d->model) {
+ // QAbstractItemView connects to a private slot
+ QObjectPrivate::disconnect(d->model, &QAbstractItemModel::rowsRemoved,
+ d, &QAbstractItemViewPrivate::rowsRemoved);
+ // do header layout after the tree
+ QObjectPrivate::disconnect(d->model, &QAbstractItemModel::layoutChanged,
+ d->header->d_func(), &QAbstractItemViewPrivate::layoutChanged);
+
+ d->modelConnections = {
+ // QTreeView has a public slot for this
+ QObject::connect(d->model, &QAbstractItemModel::rowsRemoved,
+ this, &QTreeView::rowsRemoved),
+ QObjectPrivate::connect(d->model, &QAbstractItemModel::modelAboutToBeReset,
+ d, &QTreeViewPrivate::modelAboutToBeReset)
+ };
+ }
if (d->sortingEnabled)
- d->_q_sortIndicatorChanged(header()->sortIndicatorSection(), header()->sortIndicatorOrder());
+ d->sortIndicatorChanged(header()->sortIndicatorSection(), header()->sortIndicatorOrder());
}
/*!
@@ -237,8 +236,7 @@ void QTreeView::setSelectionModel(QItemSelectionModel *selectionModel)
Q_ASSERT(selectionModel);
if (d->selectionModel) {
// support row editing
- disconnect(d->selectionModel, SIGNAL(currentRowChanged(QModelIndex,QModelIndex)),
- d->model, SLOT(submit()));
+ QObject::disconnect(d->selectionmodelConnection);
}
d->header->setSelectionModel(selectionModel);
@@ -246,8 +244,9 @@ void QTreeView::setSelectionModel(QItemSelectionModel *selectionModel)
if (d->selectionModel) {
// support row editing
- connect(d->selectionModel, SIGNAL(currentRowChanged(QModelIndex,QModelIndex)),
- d->model, SLOT(submit()));
+ d->selectionmodelConnection =
+ connect(d->selectionModel, &QItemSelectionModel::currentRowChanged,
+ d->model, &QAbstractItemModel::submit);
}
}
@@ -287,16 +286,18 @@ void QTreeView::setHeader(QHeaderView *header)
d->header->setSelectionModel(d->selectionModel);
}
- connect(d->header, SIGNAL(sectionResized(int,int,int)),
- this, SLOT(columnResized(int,int,int)));
- connect(d->header, SIGNAL(sectionMoved(int,int,int)),
- this, SLOT(columnMoved()));
- connect(d->header, SIGNAL(sectionCountChanged(int,int)),
- this, SLOT(columnCountChanged(int,int)));
- connect(d->header, SIGNAL(sectionHandleDoubleClicked(int)),
- this, SLOT(resizeColumnToContents(int)));
- connect(d->header, SIGNAL(geometriesChanged()),
- this, SLOT(updateGeometries()));
+ d->headerConnections = {
+ connect(d->header, &QHeaderView::sectionResized,
+ this, &QTreeView::columnResized),
+ connect(d->header, &QHeaderView::sectionMoved,
+ this, &QTreeView::columnMoved),
+ connect(d->header, &QHeaderView::sectionCountChanged,
+ this, &QTreeView::columnCountChanged),
+ connect(d->header, &QHeaderView::sectionHandleDoubleClicked,
+ this, &QTreeView::resizeColumnToContents),
+ connect(d->header, &QHeaderView::geometriesChanged,
+ this, &QTreeView::updateGeometries)
+ };
setSortingEnabled(d->sortingEnabled);
d->updateGeometry();
@@ -840,11 +841,12 @@ void QTreeView::setSortingEnabled(bool enable)
//sortByColumn has to be called before we connect or set the sortingEnabled flag
// because otherwise it will not call sort on the model.
sortByColumn(header()->sortIndicatorSection(), header()->sortIndicatorOrder());
- connect(header(), SIGNAL(sortIndicatorChanged(int,Qt::SortOrder)),
- this, SLOT(_q_sortIndicatorChanged(int,Qt::SortOrder)), Qt::UniqueConnection);
+ d->sortHeaderConnection =
+ QObjectPrivate::connect(header(), &QHeaderView::sortIndicatorChanged,
+ d, &QTreeViewPrivate::sortIndicatorChanged,
+ Qt::UniqueConnection);
} else {
- disconnect(header(), SIGNAL(sortIndicatorChanged(int,Qt::SortOrder)),
- this, SLOT(_q_sortIndicatorChanged(int,Qt::SortOrder)));
+ QObject::disconnect(d->sortHeaderConnection);
}
d->sortingEnabled = enable;
}
@@ -1068,33 +1070,64 @@ void QTreeView::keyboardSearch(const QString &search)
QRect QTreeView::visualRect(const QModelIndex &index) const
{
Q_D(const QTreeView);
+ return d->visualRect(index, QTreeViewPrivate::SingleSection);
+}
- if (!d->isIndexValid(index) || isIndexHidden(index))
+/*!
+ \internal
+ \return the visual rectangle at \param index, according to \param rule.
+ \list
+ \li SingleSection
+ The return value matches the section, which \a index points to.
+ \li FullRow
+ Return the rectangle of the entire row, no matter which section
+ \a index points to.
+ \li AddRowIndicatorToFirstSection
+ Like SingleSection. If \index points to the first section, add the
+ row indicator and its margins.
+ \endlist
+ */
+QRect QTreeViewPrivate::visualRect(const QModelIndex &index, RectRule rule) const
+{
+ Q_Q(const QTreeView);
+
+ if (!isIndexValid(index))
return QRect();
- d->executePostedLayout();
+ // Calculate the entire row's rectangle, even if one of the elements is hidden
+ if (q->isIndexHidden(index) && rule != FullRow)
+ return QRect();
+
+ executePostedLayout();
- int vi = d->viewIndex(index);
- if (vi < 0)
+ const int viewIndex = this->viewIndex(index);
+ if (viewIndex < 0)
return QRect();
- bool spanning = d->viewItems.at(vi).spanning;
+ const bool spanning = viewItems.at(viewIndex).spanning;
+ const int column = index.column();
// if we have a spanning item, make the selection stretch from left to right
- int x = (spanning ? 0 : columnViewportPosition(index.column()));
- int w = (spanning ? d->header->length() : columnWidth(index.column()));
- // handle indentation
- if (d->isTreePosition(index.column())) {
- int i = d->indentationForItem(vi);
- w -= i;
- if (!isRightToLeft())
- x += i;
+ int x = (spanning ? 0 : q->columnViewportPosition(column));
+ int width = (spanning ? header->length() : q->columnWidth(column));
+
+ const bool addIndentation = isTreePosition(column) && (column > 0 || rule == SingleSection);
+
+ if (rule == FullRow) {
+ x = 0;
+ width = q->viewport()->width();
+ } else if (addIndentation) {
+ // calculate indentation
+ const int indentation = indentationForItem(viewIndex);
+ width -= indentation;
+ if (!q->isRightToLeft())
+ x += indentation;
}
- int y = d->coordinateForItem(vi);
- int h = d->itemHeight(vi);
+ const int y = coordinateForItem(viewIndex);
+ const int height = itemHeight(viewIndex);
- return QRect(x, y, w, h);
+ return QRect(x, y, width, height);
}
/*!
@@ -1277,16 +1310,13 @@ bool QTreeView::viewportEvent(QEvent *event)
case QEvent::HoverLeave:
case QEvent::HoverMove: {
QHoverEvent *he = static_cast<QHoverEvent*>(event);
- int oldBranch = d->hoverBranch;
+ const int oldBranch = d->hoverBranch;
d->hoverBranch = d->itemDecorationAt(he->position().toPoint());
QModelIndex newIndex = indexAt(he->position().toPoint());
if (d->hover != newIndex || d->hoverBranch != oldBranch) {
// Update the whole hovered over row. No need to update the old hovered
// row, that is taken care in superclass hover handling.
- QRect rect = visualRect(newIndex);
- rect.setX(0);
- rect.setWidth(viewport()->width());
- viewport()->update(rect);
+ viewport()->update(d->visualRect(newIndex, QTreeViewPrivate::FullRow));
}
break; }
default:
@@ -1369,28 +1399,61 @@ bool QTreeViewPrivate::expandOrCollapseItemAtPos(const QPoint &pos)
return false;
}
-void QTreeViewPrivate::_q_modelDestroyed()
+void QTreeViewPrivate::modelDestroyed()
{
//we need to clear the viewItems because it contains QModelIndexes to
//the model currently being destroyed
viewItems.clear();
- QAbstractItemViewPrivate::_q_modelDestroyed();
+ QAbstractItemViewPrivate::modelDestroyed();
}
QRect QTreeViewPrivate::intersectedRect(const QRect rect, const QModelIndex &topLeft, const QModelIndex &bottomRight) const
{
- Q_Q(const QTreeView);
-
const auto parentIdx = topLeft.parent();
executePostedLayout();
QRect updateRect;
- for (int r = topLeft.row(); r <= bottomRight.row(); ++r) {
- if (isRowHidden(model->index(r, 0, parentIdx)))
+ int left = std::numeric_limits<int>::max();
+ int right = std::numeric_limits<int>::min();
+ for (int row = topLeft.row(); row <= bottomRight.row(); ++row) {
+ const auto idxCol0 = model->index(row, 0, parentIdx);
+ if (isRowHidden(idxCol0))
continue;
- for (int c = topLeft.column(); c <= bottomRight.column(); ++c) {
- const QModelIndex idx(model->index(r, c, parentIdx));
- updateRect |= q->visualRect(idx);
+ QRect rowRect;
+ if (left != std::numeric_limits<int>::max()) {
+ // we already know left and right boundary of the rect to update
+ rowRect = visualRect(idxCol0, FullRow);
+ if (!rowRect.intersects(rect))
+ continue;
+ rowRect = QRect(left, rowRect.top(), right, rowRect.bottom());
+ } else if (!spanningIndexes.isEmpty() && spanningIndexes.contains(idxCol0)) {
+ // isFirstColumnSpanned re-creates the child index so take a shortcut here
+ // spans the whole row, therefore ask for FullRow instead for every cell
+ rowRect = visualRect(idxCol0, FullRow);
+ if (!rowRect.intersects(rect))
+ continue;
+ } else {
+ for (int col = topLeft.column(); col <= bottomRight.column(); ++col) {
+ if (header->isSectionHidden(col))
+ continue;
+ const QModelIndex idx(model->index(row, col, parentIdx));
+ const QRect idxRect = visualRect(idx, SingleSection);
+ if (idxRect.isNull())
+ continue;
+ // early exit when complete row is out of viewport
+ if (idxRect.top() > rect.bottom() && idxRect.bottom() < rect.top())
+ break;
+ if (!idxRect.intersects(rect))
+ continue;
+ rowRect = rowRect.united(idxRect);
+ if (rowRect.left() < rect.left() && rowRect.right() > rect.right())
+ break;
+ }
+ left = std::min(left, rowRect.left());
+ right = std::max(right, rowRect.right());
}
+ updateRect = updateRect.united(rowRect);
+ if (updateRect.contains(rect)) // already full rect covered?
+ break;
}
return rect.intersected(updateRect);
}
@@ -1496,8 +1559,9 @@ void QTreeView::drawTree(QPainter *painter, const QRegion &region) const
// paint the visible rows
for (; i < viewItems.size() && y <= area.bottom(); ++i) {
+ const QModelIndex &index = viewItems.at(i).index;
const int itemHeight = d->itemHeight(i);
- option.rect.setRect(0, y, viewportWidth, itemHeight);
+ option.rect = d->visualRect(index, QTreeViewPrivate::FullRow);
option.state = state | (viewItems.at(i).expanded ? QStyle::State_Open : QStyle::State_None)
| (viewItems.at(i).hasChildren ? QStyle::State_Children : QStyle::State_None)
| (viewItems.at(i).hasMoreSiblings ? QStyle::State_Sibling : QStyle::State_None);
@@ -2116,6 +2180,7 @@ void QTreeView::doItemsLayout()
}
QAbstractItemView::doItemsLayout();
d->header->doItemsLayout();
+ d->updateAccessibility();
}
/*!
@@ -2192,9 +2257,8 @@ QModelIndex QTreeView::moveCursor(CursorAction cursorAction, Qt::KeyboardModifie
}
return QModelIndex();
}
- int vi = -1;
- if (vi < 0)
- vi = qMax(0, d->viewIndex(current));
+
+ const int vi = qMax(0, d->viewIndex(current));
if (isRightToLeft()) {
if (cursorAction == MoveRight)
@@ -2368,7 +2432,7 @@ QRegion QTreeView::visualRegionForSelection(const QItemSelection &selection) con
}
if (!leftIndex.isValid())
continue;
- const QRect leftRect = visualRect(leftIndex);
+ const QRect leftRect = d->visualRect(leftIndex, QTreeViewPrivate::SingleSection);
int top = leftRect.top();
QModelIndex rightIndex = range.bottomRight();
while (rightIndex.isValid() && isIndexHidden(rightIndex)) {
@@ -2379,7 +2443,7 @@ QRegion QTreeView::visualRegionForSelection(const QItemSelection &selection) con
}
if (!rightIndex.isValid())
continue;
- const QRect rightRect = visualRect(rightIndex);
+ const QRect rightRect = d->visualRect(rightIndex, QTreeViewPrivate::SingleSection);
int bottom = rightRect.bottom();
if (top > bottom)
qSwap<int>(top, bottom);
@@ -2555,7 +2619,7 @@ void QTreeView::rowsRemoved(const QModelIndex &parent, int start, int end)
d->viewItems.clear();
d->doDelayedItemsLayout();
d->hasRemovedItems = true;
- d->_q_rowsRemoved(parent, start, end);
+ d->rowsRemoved(parent, start, end);
}
/*!
@@ -2646,7 +2710,8 @@ QSize QTreeView::viewportSizeHint() const
return QAbstractItemView::viewportSizeHint();
// Get rect for last item
- const QRect deepestRect = visualRect(d->viewItems.last().index);
+ const QRect deepestRect = d->visualRect(d->viewItems.last().index,
+ QTreeViewPrivate::SingleSection);
if (!deepestRect.isValid())
return QAbstractItemView::viewportSizeHint();
@@ -2679,6 +2744,7 @@ void QTreeView::expandAll()
d->layout(-1, true);
updateGeometries();
d->viewport->update();
+ d->updateAccessibility();
}
/*!
@@ -2802,6 +2868,7 @@ void QTreeView::expandToDepth(int depth)
updateGeometries();
d->viewport->update();
+ d->updateAccessibility();
}
/*!
@@ -3062,10 +3129,25 @@ void QTreeViewPrivate::initialize()
q->setHeader(header);
#if QT_CONFIG(animation)
animationsEnabled = q->style()->styleHint(QStyle::SH_Widget_Animation_Duration, nullptr, q) > 0;
- QObject::connect(&animatedOperation, SIGNAL(finished()), q, SLOT(_q_endAnimatedOperation()));
+ animationConnection =
+ QObjectPrivate::connect(&animatedOperation, &QVariantAnimation::finished,
+ this, &QTreeViewPrivate::endAnimatedOperation);
#endif // animation
}
+void QTreeViewPrivate::clearConnections()
+{
+ for (const QMetaObject::Connection &connection : modelConnections)
+ QObject::disconnect(connection);
+ for (const QMetaObject::Connection &connection : headerConnections)
+ QObject::disconnect(connection);
+ QObject::disconnect(selectionmodelConnection);
+ QObject::disconnect(sortHeaderConnection);
+#if QT_CONFIG(animation)
+ QObject::disconnect(animationConnection);
+#endif
+}
+
void QTreeViewPrivate::expand(int item, bool emitSignal)
{
Q_Q(QTreeView);
@@ -3098,6 +3180,7 @@ void QTreeViewPrivate::expand(int item, bool emitSignal)
beginAnimatedOperation();
#endif // animation
}
+ updateAccessibility();
}
void QTreeViewPrivate::insertViewItems(int pos, int count, const QTreeViewItem &viewItem)
@@ -3258,7 +3341,7 @@ QPixmap QTreeViewPrivate::renderTreeToPixmapForAnimation(const QRect &rect) cons
for (QEditorIndexHash::const_iterator it = editorIndexHash.constBegin(); it != editorIndexHash.constEnd(); ++it) {
QWidget *editor = it.key();
const QModelIndex &index = it.value();
- option.rect = q->visualRect(index);
+ option.rect = visualRect(index, SingleSection);
if (option.rect.isValid()) {
if (QAbstractItemDelegate *delegate = q->itemDelegateForIndex(index))
@@ -3278,7 +3361,7 @@ QPixmap QTreeViewPrivate::renderTreeToPixmapForAnimation(const QRect &rect) cons
return pixmap;
}
-void QTreeViewPrivate::_q_endAnimatedOperation()
+void QTreeViewPrivate::endAnimatedOperation()
{
Q_Q(QTreeView);
q->setState(stateBeforeAnimation);
@@ -3287,25 +3370,40 @@ void QTreeViewPrivate::_q_endAnimatedOperation()
}
#endif // animation
-void QTreeViewPrivate::_q_modelAboutToBeReset()
+void QTreeViewPrivate::modelAboutToBeReset()
{
viewItems.clear();
}
-void QTreeViewPrivate::_q_columnsAboutToBeRemoved(const QModelIndex &parent, int start, int end)
+void QTreeViewPrivate::columnsAboutToBeRemoved(const QModelIndex &parent, int start, int end)
{
if (start <= 0 && 0 <= end)
viewItems.clear();
- QAbstractItemViewPrivate::_q_columnsAboutToBeRemoved(parent, start, end);
+ QAbstractItemViewPrivate::columnsAboutToBeRemoved(parent, start, end);
}
-void QTreeViewPrivate::_q_columnsRemoved(const QModelIndex &parent, int start, int end)
+void QTreeViewPrivate::columnsRemoved(const QModelIndex &parent, int start, int end)
{
if (start <= 0 && 0 <= end)
doDelayedItemsLayout();
- QAbstractItemViewPrivate::_q_columnsRemoved(parent, start, end);
+ QAbstractItemViewPrivate::columnsRemoved(parent, start, end);
}
+void QTreeViewPrivate::updateAccessibility()
+{
+#if QT_CONFIG(accessibility)
+ Q_Q(QTreeView);
+ if (pendingAccessibilityUpdate) {
+ pendingAccessibilityUpdate = false;
+ if (QAccessible::isActive()) {
+ QAccessibleTableModelChangeEvent event(q, QAccessibleTableModelChangeEvent::ModelReset);
+ QAccessible::updateAccessibility(&event);
+ }
+ }
+#endif
+}
+
+
/** \internal
creates and initialize the viewItem structure of the children of the element \li
@@ -3326,6 +3424,15 @@ void QTreeViewPrivate::layout(int i, bool recursiveExpanding, bool afterIsUninit
return;
}
+#if QT_CONFIG(accessibility)
+ // QAccessibleTree's rowCount implementation uses viewItems.size(), so
+ // we need to invalidate any cached accessibility data structures if
+ // that value changes during the run of this function.
+ const auto resetModelIfNeeded = qScopeGuard([oldViewItemsSize = viewItems.size(), this]{
+ pendingAccessibilityUpdate |= oldViewItemsSize != viewItems.size();
+ });
+#endif
+
int count = 0;
if (model->hasChildren(parent)) {
if (model->canFetchMore(parent)) {
@@ -3964,7 +4071,7 @@ bool QTreeViewPrivate::hasVisibleChildren(const QModelIndex& parent) const
return false;
}
-void QTreeViewPrivate::_q_sortIndicatorChanged(int column, Qt::SortOrder order)
+void QTreeViewPrivate::sortIndicatorChanged(int column, Qt::SortOrder order)
{
model->sort(column, order);
}
@@ -3988,24 +4095,17 @@ void QTreeViewPrivate::updateIndentationFromStyle()
*/
void QTreeView::currentChanged(const QModelIndex &current, const QModelIndex &previous)
{
+ Q_D(QTreeView);
QAbstractItemView::currentChanged(current, previous);
if (allColumnsShowFocus()) {
- if (previous.isValid()) {
- QRect previousRect = visualRect(previous);
- previousRect.setX(0);
- previousRect.setWidth(viewport()->width());
- viewport()->update(previousRect);
- }
- if (current.isValid()) {
- QRect currentRect = visualRect(current);
- currentRect.setX(0);
- currentRect.setWidth(viewport()->width());
- viewport()->update(currentRect);
- }
+ if (previous.isValid())
+ viewport()->update(d->visualRect(previous, QTreeViewPrivate::FullRow));
+ if (current.isValid())
+ viewport()->update(d->visualRect(current, QTreeViewPrivate::FullRow));
}
#if QT_CONFIG(accessibility)
- if (QAccessible::isActive() && current.isValid()) {
+ if (QAccessible::isActive() && current.isValid() && hasFocus()) {
Q_D(QTreeView);
QAccessibleEvent event(this, QAccessible::Focus);
diff --git a/src/widgets/itemviews/qtreeview.h b/src/widgets/itemviews/qtreeview.h
index d73ca5e2cd..1dd4650c5d 100644
--- a/src/widgets/itemviews/qtreeview.h
+++ b/src/widgets/itemviews/qtreeview.h
@@ -195,11 +195,6 @@ private:
Q_DECLARE_PRIVATE(QTreeView)
Q_DISABLE_COPY(QTreeView)
-#if QT_CONFIG(animation)
- Q_PRIVATE_SLOT(d_func(), void _q_endAnimatedOperation())
-#endif // animation
- Q_PRIVATE_SLOT(d_func(), void _q_modelAboutToBeReset())
- Q_PRIVATE_SLOT(d_func(), void _q_sortIndicatorChanged(int column, Qt::SortOrder order))
};
QT_END_NAMESPACE
diff --git a/src/widgets/itemviews/qtreeview_p.h b/src/widgets/itemviews/qtreeview_p.h
index 22f6eaec22..d0afdf1223 100644
--- a/src/widgets/itemviews/qtreeview_p.h
+++ b/src/widgets/itemviews/qtreeview_p.h
@@ -23,6 +23,8 @@
#include <QtCore/qvariantanimation.h>
#endif
+#include <array>
+
QT_REQUIRE_CONFIG(treeview);
QT_BEGIN_NAMESPACE
@@ -62,6 +64,7 @@ public:
~QTreeViewPrivate() {}
void initialize();
+ void clearConnections();
int logicalIndexForTree() const;
inline bool isTreePosition(int logicalIndex) const
{
@@ -88,17 +91,17 @@ public:
void beginAnimatedOperation();
void drawAnimatedOperation(QPainter *painter) const;
QPixmap renderTreeToPixmapForAnimation(const QRect &rect) const;
- void _q_endAnimatedOperation();
+ void endAnimatedOperation();
#endif // animation
void expand(int item, bool emitSignal);
void collapse(int item, bool emitSignal);
- void _q_columnsAboutToBeRemoved(const QModelIndex &, int, int) override;
- void _q_columnsRemoved(const QModelIndex &, int, int) override;
- void _q_modelAboutToBeReset();
- void _q_sortIndicatorChanged(int column, Qt::SortOrder order);
- void _q_modelDestroyed() override;
+ void columnsAboutToBeRemoved(const QModelIndex &, int, int) override;
+ void columnsRemoved(const QModelIndex &, int, int) override;
+ void modelAboutToBeReset();
+ void sortIndicatorChanged(int column, Qt::SortOrder order);
+ void modelDestroyed() override;
QRect intersectedRect(const QRect rect, const QModelIndex &topLeft, const QModelIndex &bottomRight) const override;
void layout(int item, bool recusiveExpanding = false, bool afterIsUninitialized = false);
@@ -150,6 +153,21 @@ public:
QList<QStyleOptionViewItem::ViewItemPosition> *itemPositions, int left,
int right) const;
int widthHintForIndex(const QModelIndex &index, int hint, const QStyleOptionViewItem &option, int i) const;
+
+ enum RectRule {
+ FullRow,
+ SingleSection,
+ AddRowIndicatorToFirstSection
+ };
+
+ // Base class will get the first visual rect including row indicator
+ QRect visualRect(const QModelIndex &index) const override
+ {
+ return visualRect(index, AddRowIndicatorToFirstSection);
+ }
+
+ QRect visualRect(const QModelIndex &index, RectRule rule) const;
+
QHeaderView *header;
int indent;
@@ -239,6 +257,18 @@ public:
// tree position
int treePosition;
+
+ // pending accessibility update
+#if QT_CONFIG(accessibility)
+ bool pendingAccessibilityUpdate = false;
+#endif
+ void updateAccessibility();
+
+ QMetaObject::Connection animationConnection;
+ QMetaObject::Connection selectionmodelConnection;
+ std::array<QMetaObject::Connection, 2> modelConnections;
+ std::array<QMetaObject::Connection, 5> headerConnections;
+ QMetaObject::Connection sortHeaderConnection;
};
QT_END_NAMESPACE
diff --git a/src/widgets/itemviews/qtreewidget.cpp b/src/widgets/itemviews/qtreewidget.cpp
index 3fa8a7e1b9..8e46a0efbe 100644
--- a/src/widgets/itemviews/qtreewidget.cpp
+++ b/src/widgets/itemviews/qtreewidget.cpp
@@ -5,7 +5,6 @@
#include <qheaderview.h>
#include <qpainter.h>
-#include <qitemdelegate.h>
#include <qstack.h>
#include <qdebug.h>
#include <private/qtreewidget_p.h>
@@ -2301,37 +2300,43 @@ QDataStream &operator>>(QDataStream &in, QTreeWidgetItem &item)
#endif // QT_NO_DATASTREAM
-void QTreeWidgetPrivate::_q_emitItemPressed(const QModelIndex &index)
+void QTreeWidgetPrivate::clearConnections()
+{
+ for (const QMetaObject::Connection &connection : connections)
+ QObject::disconnect(connection);
+}
+
+void QTreeWidgetPrivate::emitItemPressed(const QModelIndex &index)
{
Q_Q(QTreeWidget);
emit q->itemPressed(item(index), index.column());
}
-void QTreeWidgetPrivate::_q_emitItemClicked(const QModelIndex &index)
+void QTreeWidgetPrivate::emitItemClicked(const QModelIndex &index)
{
Q_Q(QTreeWidget);
emit q->itemClicked(item(index), index.column());
}
-void QTreeWidgetPrivate::_q_emitItemDoubleClicked(const QModelIndex &index)
+void QTreeWidgetPrivate::emitItemDoubleClicked(const QModelIndex &index)
{
Q_Q(QTreeWidget);
emit q->itemDoubleClicked(item(index), index.column());
}
-void QTreeWidgetPrivate::_q_emitItemActivated(const QModelIndex &index)
+void QTreeWidgetPrivate::emitItemActivated(const QModelIndex &index)
{
Q_Q(QTreeWidget);
emit q->itemActivated(item(index), index.column());
}
-void QTreeWidgetPrivate::_q_emitItemEntered(const QModelIndex &index)
+void QTreeWidgetPrivate::emitItemEntered(const QModelIndex &index)
{
Q_Q(QTreeWidget);
emit q->itemEntered(item(index), index.column());
}
-void QTreeWidgetPrivate::_q_emitItemChanged(const QModelIndex &index)
+void QTreeWidgetPrivate::emitItemChanged(const QModelIndex &index)
{
Q_Q(QTreeWidget);
QTreeWidgetItem *indexItem = item(index);
@@ -2339,19 +2344,19 @@ void QTreeWidgetPrivate::_q_emitItemChanged(const QModelIndex &index)
emit q->itemChanged(indexItem, index.column());
}
-void QTreeWidgetPrivate::_q_emitItemExpanded(const QModelIndex &index)
+void QTreeWidgetPrivate::emitItemExpanded(const QModelIndex &index)
{
Q_Q(QTreeWidget);
emit q->itemExpanded(item(index));
}
-void QTreeWidgetPrivate::_q_emitItemCollapsed(const QModelIndex &index)
+void QTreeWidgetPrivate::emitItemCollapsed(const QModelIndex &index)
{
Q_Q(QTreeWidget);
emit q->itemCollapsed(item(index));
}
-void QTreeWidgetPrivate::_q_emitCurrentItemChanged(const QModelIndex &current,
+void QTreeWidgetPrivate::emitCurrentItemChanged(const QModelIndex &current,
const QModelIndex &previous)
{
Q_Q(QTreeWidget);
@@ -2360,7 +2365,7 @@ void QTreeWidgetPrivate::_q_emitCurrentItemChanged(const QModelIndex &current,
emit q->currentItemChanged(currentItem, previousItem);
}
-void QTreeWidgetPrivate::_q_sort()
+void QTreeWidgetPrivate::sort()
{
if (sortingEnabled) {
int column = header->sortIndicatorSection();
@@ -2369,7 +2374,7 @@ void QTreeWidgetPrivate::_q_sort()
}
}
-void QTreeWidgetPrivate::_q_selectionChanged(const QItemSelection &selected, const QItemSelection &deselected)
+void QTreeWidgetPrivate::selectionChanged(const QItemSelection &selected, const QItemSelection &deselected)
{
Q_Q(QTreeWidget);
QModelIndexList indices = selected.indexes();
@@ -2389,8 +2394,8 @@ void QTreeWidgetPrivate::_q_selectionChanged(const QItemSelection &selected, con
emit q->itemSelectionChanged();
}
-void QTreeWidgetPrivate::_q_dataChanged(const QModelIndex &topLeft,
- const QModelIndex &bottomRight)
+void QTreeWidgetPrivate::dataChanged(const QModelIndex &topLeft,
+ const QModelIndex &bottomRight)
{
if (sortingEnabled && topLeft.isValid() && bottomRight.isValid()
&& !treeModel()->sortPendingTimer.isActive()) {
@@ -2448,7 +2453,7 @@ void QTreeWidgetPrivate::_q_dataChanged(const QModelIndex &topLeft,
whether sorting is enabled.
\sa QTreeWidgetItem, QTreeWidgetItemIterator, QTreeView,
- {Model/View Programming}, {Settings Editor Example}
+ {Model/View Programming}
*/
/*!
@@ -2570,31 +2575,34 @@ void QTreeWidgetPrivate::_q_dataChanged(const QModelIndex &topLeft,
QTreeWidget::QTreeWidget(QWidget *parent)
: QTreeView(*new QTreeWidgetPrivate(), parent)
{
+ Q_D(QTreeWidget);
QTreeView::setModel(new QTreeModel(1, this));
- connect(this, SIGNAL(pressed(QModelIndex)),
- SLOT(_q_emitItemPressed(QModelIndex)));
- connect(this, SIGNAL(clicked(QModelIndex)),
- SLOT(_q_emitItemClicked(QModelIndex)));
- connect(this, SIGNAL(doubleClicked(QModelIndex)),
- SLOT(_q_emitItemDoubleClicked(QModelIndex)));
- connect(this, SIGNAL(activated(QModelIndex)),
- SLOT(_q_emitItemActivated(QModelIndex)));
- connect(this, SIGNAL(entered(QModelIndex)),
- SLOT(_q_emitItemEntered(QModelIndex)));
- connect(this, SIGNAL(expanded(QModelIndex)),
- SLOT(_q_emitItemExpanded(QModelIndex)));
- connect(this, SIGNAL(collapsed(QModelIndex)),
- SLOT(_q_emitItemCollapsed(QModelIndex)));
- connect(selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)),
- this, SLOT(_q_emitCurrentItemChanged(QModelIndex,QModelIndex)));
- connect(model(), SIGNAL(dataChanged(QModelIndex,QModelIndex)),
- this, SLOT(_q_emitItemChanged(QModelIndex)));
- connect(model(), SIGNAL(dataChanged(QModelIndex,QModelIndex)),
- this, SLOT(_q_dataChanged(QModelIndex,QModelIndex)));
- connect(model(), SIGNAL(columnsRemoved(QModelIndex,int,int)),
- this, SLOT(_q_sort()));
- connect(selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
- this, SLOT(_q_selectionChanged(QItemSelection,QItemSelection)));
+ d->connections = {
+ QObjectPrivate::connect(this, &QTreeWidget::pressed,
+ d, &QTreeWidgetPrivate::emitItemPressed),
+ QObjectPrivate::connect(this, &QTreeWidget::clicked,
+ d, &QTreeWidgetPrivate::emitItemClicked),
+ QObjectPrivate::connect(this, &QTreeWidget::doubleClicked,
+ d, &QTreeWidgetPrivate::emitItemDoubleClicked),
+ QObjectPrivate::connect(this, &QTreeWidget::activated,
+ d, &QTreeWidgetPrivate::emitItemActivated),
+ QObjectPrivate::connect(this, &QTreeWidget::entered,
+ d, &QTreeWidgetPrivate::emitItemEntered),
+ QObjectPrivate::connect(this, &QTreeWidget::expanded,
+ d, &QTreeWidgetPrivate::emitItemExpanded),
+ QObjectPrivate::connect(this, &QTreeWidget::collapsed,
+ d, &QTreeWidgetPrivate::emitItemCollapsed),
+ QObjectPrivate::connect(model(), &QAbstractItemModel::dataChanged,
+ d, &QTreeWidgetPrivate::emitItemChanged),
+ QObjectPrivate::connect(model(), &QAbstractItemModel::dataChanged,
+ d, &QTreeWidgetPrivate::dataChanged),
+ QObjectPrivate::connect(model(), &QAbstractItemModel::columnsRemoved,
+ d, &QTreeWidgetPrivate::sort),
+ QObjectPrivate::connect(selectionModel(), &QItemSelectionModel::currentChanged,
+ d, &QTreeWidgetPrivate::emitCurrentItemChanged),
+ QObjectPrivate::connect(selectionModel(), &QItemSelectionModel::selectionChanged,
+ d, &QTreeWidgetPrivate::selectionChanged)
+ };
header()->setSectionsClickable(false);
}
@@ -2604,6 +2612,8 @@ QTreeWidget::QTreeWidget(QWidget *parent)
QTreeWidget::~QTreeWidget()
{
+ Q_D(QTreeWidget);
+ d->clearConnections();
}
/*
@@ -3119,7 +3129,7 @@ void QTreeWidget::setSelectionModel(QItemSelectionModel *selectionModel)
QTreeView::setSelectionModel(selectionModel);
QItemSelection newSelection = selectionModel->selection();
if (!newSelection.isEmpty())
- d->_q_selectionChanged(newSelection, QItemSelection());
+ d->selectionChanged(newSelection, QItemSelection());
}
/*!
diff --git a/src/widgets/itemviews/qtreewidget.h b/src/widgets/itemviews/qtreewidget.h
index f83cf421ed..992f6cdb1c 100644
--- a/src/widgets/itemviews/qtreewidget.h
+++ b/src/widgets/itemviews/qtreewidget.h
@@ -323,19 +323,6 @@ private:
Q_DECLARE_PRIVATE(QTreeWidget)
Q_DISABLE_COPY(QTreeWidget)
-
- Q_PRIVATE_SLOT(d_func(), void _q_emitItemPressed(const QModelIndex &index))
- Q_PRIVATE_SLOT(d_func(), void _q_emitItemClicked(const QModelIndex &index))
- Q_PRIVATE_SLOT(d_func(), void _q_emitItemDoubleClicked(const QModelIndex &index))
- Q_PRIVATE_SLOT(d_func(), void _q_emitItemActivated(const QModelIndex &index))
- Q_PRIVATE_SLOT(d_func(), void _q_emitItemEntered(const QModelIndex &index))
- Q_PRIVATE_SLOT(d_func(), void _q_emitItemChanged(const QModelIndex &index))
- Q_PRIVATE_SLOT(d_func(), void _q_emitItemExpanded(const QModelIndex &index))
- Q_PRIVATE_SLOT(d_func(), void _q_emitItemCollapsed(const QModelIndex &index))
- Q_PRIVATE_SLOT(d_func(), void _q_emitCurrentItemChanged(const QModelIndex &previous, const QModelIndex &current))
- Q_PRIVATE_SLOT(d_func(), void _q_sort())
- Q_PRIVATE_SLOT(d_func(), void _q_dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight))
- Q_PRIVATE_SLOT(d_func(), void _q_selectionChanged(const QItemSelection &selected, const QItemSelection &deselected))
};
inline void QTreeWidget::removeItemWidget(QTreeWidgetItem *item, int column)
diff --git a/src/widgets/itemviews/qtreewidget_p.h b/src/widgets/itemviews/qtreewidget_p.h
index fd7560ffd6..53fdea3ca8 100644
--- a/src/widgets/itemviews/qtreewidget_p.h
+++ b/src/widgets/itemviews/qtreewidget_p.h
@@ -23,6 +23,8 @@
#include <private/qtreeview_p.h>
#include <QtWidgets/qheaderview.h>
+#include <array>
+
QT_REQUIRE_CONFIG(treewidget);
QT_BEGIN_NAMESPACE
@@ -186,26 +188,29 @@ class QTreeWidgetPrivate : public QTreeViewPrivate
Q_DECLARE_PUBLIC(QTreeWidget)
public:
QTreeWidgetPrivate() : QTreeViewPrivate(), explicitSortColumn(-1) {}
+ void clearConnections();
inline QTreeModel *treeModel() const { return qobject_cast<QTreeModel*>(model); }
inline QModelIndex index(const QTreeWidgetItem *item, int column = 0) const
{ return treeModel()->index(item, column); }
inline QTreeWidgetItem *item(const QModelIndex &index) const
{ return treeModel()->item(index); }
- void _q_emitItemPressed(const QModelIndex &index);
- void _q_emitItemClicked(const QModelIndex &index);
- void _q_emitItemDoubleClicked(const QModelIndex &index);
- void _q_emitItemActivated(const QModelIndex &index);
- void _q_emitItemEntered(const QModelIndex &index);
- void _q_emitItemChanged(const QModelIndex &index);
- void _q_emitItemExpanded(const QModelIndex &index);
- void _q_emitItemCollapsed(const QModelIndex &index);
- void _q_emitCurrentItemChanged(const QModelIndex &previous, const QModelIndex &index);
- void _q_sort();
- void _q_dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight);
- void _q_selectionChanged(const QItemSelection &selected, const QItemSelection &deselected);
+ void emitItemPressed(const QModelIndex &index);
+ void emitItemClicked(const QModelIndex &index);
+ void emitItemDoubleClicked(const QModelIndex &index);
+ void emitItemActivated(const QModelIndex &index);
+ void emitItemEntered(const QModelIndex &index);
+ void emitItemChanged(const QModelIndex &index);
+ void emitItemExpanded(const QModelIndex &index);
+ void emitItemCollapsed(const QModelIndex &index);
+ void emitCurrentItemChanged(const QModelIndex &previous, const QModelIndex &index);
+ void sort();
+ void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight);
+ void selectionChanged(const QItemSelection &selected, const QItemSelection &deselected);
// used by QTreeWidgetItem::sortChildren to make sure the column argument is used
int explicitSortColumn;
+
+ std::array<QMetaObject::Connection, 12> connections;
};
QT_END_NAMESPACE
diff --git a/src/widgets/itemviews/qwidgetitemdata_p.h b/src/widgets/itemviews/qwidgetitemdata_p.h
index 0fbaae34bd..f8c2d47085 100644
--- a/src/widgets/itemviews/qwidgetitemdata_p.h
+++ b/src/widgets/itemviews/qwidgetitemdata_p.h
@@ -6,6 +6,7 @@
#include <QtWidgets/private/qtwidgetsglobal_p.h>
#include <QtCore/qdatastream.h>
+#include <QtCore/qvariant.h>
//
// W A R N I N G