summaryrefslogtreecommitdiffstats
path: root/src/widgets/itemviews/qlistwidget.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/widgets/itemviews/qlistwidget.cpp')
-rw-r--r--src/widgets/itemviews/qlistwidget.cpp222
1 files changed, 99 insertions, 123 deletions
diff --git a/src/widgets/itemviews/qlistwidget.cpp b/src/widgets/itemviews/qlistwidget.cpp
index afef9ba591..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>
@@ -36,7 +35,7 @@ QListModel::~QListModel()
void QListModel::clear()
{
beginResetModel();
- for (int i = 0; i < items.count(); ++i) {
+ for (int i = 0; i < items.size(); ++i) {
if (items.at(i)) {
items.at(i)->d->theid = -1;
items.at(i)->view = nullptr;
@@ -80,8 +79,8 @@ void QListModel::insert(int row, QListWidgetItem *item)
} else {
if (row < 0)
row = 0;
- else if (row > items.count())
- row = items.count();
+ else if (row > items.size())
+ row = items.size();
}
beginInsertRows(QModelIndex(), row, row);
items.insert(row, item);
@@ -91,7 +90,7 @@ void QListModel::insert(int row, QListWidgetItem *item)
void QListModel::insert(int row, const QStringList &labels)
{
- const int count = labels.count();
+ const int count = labels.size();
if (count <= 0)
return;
QListWidget *view = qobject_cast<QListWidget*>(QObject::parent());
@@ -104,8 +103,8 @@ void QListModel::insert(int row, const QStringList &labels)
} else {
if (row < 0)
row = 0;
- else if (row > items.count())
- row = items.count();
+ else if (row > items.size())
+ row = items.size();
beginInsertRows(QModelIndex(), row, row + count - 1);
for (int i = 0; i < count; ++i) {
QListWidgetItem *item = new QListWidgetItem(labels.at(i));
@@ -119,7 +118,7 @@ void QListModel::insert(int row, const QStringList &labels)
QListWidgetItem *QListModel::take(int row)
{
- if (row < 0 || row >= items.count())
+ if (row < 0 || row >= items.size())
return nullptr;
beginRemoveRows(QModelIndex(), row, row);
@@ -133,8 +132,8 @@ QListWidgetItem *QListModel::take(int row)
void QListModel::move(int srcRow, int dstRow)
{
if (srcRow == dstRow
- || srcRow < 0 || srcRow >= items.count()
- || dstRow < 0 || dstRow > items.count())
+ || srcRow < 0 || srcRow >= items.size()
+ || dstRow < 0 || dstRow > items.size())
return;
if (!beginMoveRows(QModelIndex(), srcRow, srcRow, QModelIndex(), dstRow))
@@ -147,7 +146,7 @@ void QListModel::move(int srcRow, int dstRow)
int QListModel::rowCount(const QModelIndex &parent) const
{
- return parent.isValid() ? 0 : items.count();
+ return parent.isValid() ? 0 : items.size();
}
QModelIndex QListModel::index(const QListWidgetItem *item_) const
@@ -158,7 +157,7 @@ QModelIndex QListModel::index(const QListWidgetItem *item_) const
return QModelIndex();
int row;
const int theid = item->d->theid;
- if (theid >= 0 && theid < items.count() && items.at(theid) == item) {
+ if (theid >= 0 && theid < items.size() && items.at(theid) == item) {
row = theid;
} else { // we need to search for the item
row = items.lastIndexOf(item); // lastIndexOf is an optimization in favor of indexOf
@@ -178,14 +177,14 @@ QModelIndex QListModel::index(int row, int column, const QModelIndex &parent) co
QVariant QListModel::data(const QModelIndex &index, int role) const
{
- if (!index.isValid() || index.row() >= items.count())
+ if (!index.isValid() || index.row() >= items.size())
return QVariant();
return items.at(index.row())->data(role);
}
bool QListModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
- if (!index.isValid() || index.row() >= items.count())
+ if (!index.isValid() || index.row() >= items.size())
return false;
items.at(index.row())->setData(role, value);
return true;
@@ -208,10 +207,10 @@ bool QListModel::clearItemData(const QModelIndex &index)
QMap<int, QVariant> QListModel::itemData(const QModelIndex &index) const
{
QMap<int, QVariant> roles;
- if (!index.isValid() || index.row() >= items.count())
+ if (!index.isValid() || index.row() >= items.size())
return roles;
QListWidgetItem *itm = items.at(index.row());
- for (int i = 0; i < itm->d->values.count(); ++i) {
+ for (int i = 0; i < itm->d->values.size(); ++i) {
roles.insert(itm->d->values.at(i).role,
itm->d->values.at(i).value);
}
@@ -288,7 +287,7 @@ bool QListModel::moveRows(const QModelIndex &sourceParent, int sourceRow, int co
Qt::ItemFlags QListModel::flags(const QModelIndex &index) const
{
- if (!index.isValid() || index.row() >= items.count() || index.model() != this)
+ if (!index.isValid() || index.row() >= items.size() || index.model() != this)
return Qt::ItemIsDropEnabled; // we allow drops outside the items
return items.at(index.row())->flags();
}
@@ -300,18 +299,18 @@ void QListModel::sort(int column, Qt::SortOrder order)
emit layoutAboutToBeChanged({}, QAbstractItemModel::VerticalSortHint);
- QList<QPair<QListWidgetItem *, int>> sorting(items.count());
- for (int i = 0; i < items.count(); ++i) {
+ QList<QPair<QListWidgetItem *, int>> sorting(items.size());
+ for (int i = 0; i < items.size(); ++i) {
QListWidgetItem *item = items.at(i);
sorting[i].first = item;
sorting[i].second = i;
}
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.count();
+ const int sortingCount = sorting.size();
fromIndexes.reserve(sortingCount);
toIndexes.reserve(sortingCount);
for (int r = 0; r < sortingCount; ++r) {
@@ -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.count(); ++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,
@@ -444,7 +401,7 @@ QMimeData *QListModel::internalMimeData() const
QMimeData *QListModel::mimeData(const QModelIndexList &indexes) const
{
QList<QListWidgetItem*> itemlist;
- const int indexesCount = indexes.count();
+ const int indexesCount = indexes.size();
itemlist.reserve(indexesCount);
for (int i = 0; i < indexesCount; ++i)
itemlist << at(indexes.at(i).row());
@@ -465,7 +422,7 @@ bool QListModel::dropMimeData(const QMimeData *data, Qt::DropAction action,
if (index.isValid())
row = index.row();
else if (row == -1)
- row = items.count();
+ row = items.size();
return view->dropMimeData(row, data, action);
}
@@ -702,7 +659,7 @@ void QListWidgetItem::setData(int role, const QVariant &value)
{
bool found = false;
role = (role == Qt::EditRole ? Qt::DisplayRole : role);
- for (int i = 0; i < d->values.count(); ++i) {
+ for (int i = 0; i < d->values.size(); ++i) {
if (d->values.at(i).role == role) {
if (d->values.at(i).value == value)
return;
@@ -730,7 +687,7 @@ void QListWidgetItem::setData(int role, const QVariant &value)
QVariant QListWidgetItem::data(int role) const
{
role = (role == Qt::EditRole ? Qt::DisplayRole : role);
- for (int i = 0; i < d->values.count(); ++i)
+ for (int i = 0; i < d->values.size(); ++i)
if (d->values.at(i).role == role)
return d->values.at(i).value;
return QVariant();
@@ -1087,6 +1044,11 @@ void QListWidgetItem::setFlags(Qt::ItemFlags aflags)
*/
/*!
+ \fn void QListWidgetItem::setTextAlignment(Qt::AlignmentFlag alignment)
+ \internal
+*/
+
+/*!
\fn void QListWidgetItem::setBackground(const QBrush &brush)
\since 4.2
@@ -1121,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);
@@ -1189,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,
@@ -1402,6 +1378,8 @@ QListWidget::QListWidget(QWidget *parent)
QListWidget::~QListWidget()
{
+ Q_D(QListWidget);
+ d->clearConnections();
}
/*!
@@ -1412,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)
+ };
}
}
@@ -1755,7 +1731,7 @@ QList<QListWidgetItem*> QListWidget::selectedItems() const
Q_D(const QListWidget);
QModelIndexList indexes = selectionModel()->selectedIndexes();
QList<QListWidgetItem*> items;
- const int numIndexes = indexes.count();
+ const int numIndexes = indexes.size();
items.reserve(numIndexes);
for (int i = 0; i < numIndexes; ++i)
items.append(d->listModel()->at(indexes.at(i).row()));
@@ -1832,7 +1808,7 @@ QMimeData *QListWidget::mimeData(const QList<QListWidgetItem *> &items) const
// if non empty, it's called from the model's own mimeData
if (cachedIndexes.isEmpty()) {
- cachedIndexes.reserve(items.count());
+ cachedIndexes.reserve(items.size());
for (QListWidgetItem *item : items)
cachedIndexes << indexFromItem(item);