1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qlistwidget.h"
5
6#include <qitemdelegate.h>
7#include <private/qlistview_p.h>
8#include <private/qwidgetitemdata_p.h>
9#include <private/qlistwidget_p.h>
10
11#include <algorithm>
12
13QT_BEGIN_NAMESPACE
14
15class QListWidgetMimeData : public QMimeData
16{
17 Q_OBJECT
18public:
19 QList<QListWidgetItem*> items;
20};
21
22QT_BEGIN_INCLUDE_NAMESPACE
23#include "qlistwidget.moc"
24QT_END_INCLUDE_NAMESPACE
25
26QListModel::QListModel(QListWidget *parent)
27 : QAbstractListModel(parent)
28{
29}
30
31QListModel::~QListModel()
32{
33 clear();
34}
35
36void QListModel::clear()
37{
38 beginResetModel();
39 for (int i = 0; i < items.size(); ++i) {
40 if (items.at(i)) {
41 items.at(i)->d->theid = -1;
42 items.at(i)->view = nullptr;
43 delete items.at(i);
44 }
45 }
46 items.clear();
47 endResetModel();
48}
49
50QListWidgetItem *QListModel::at(int row) const
51{
52 return items.value(i: row);
53}
54
55void QListModel::remove(QListWidgetItem *item)
56{
57 if (!item)
58 return;
59 int row = items.indexOf(t: item); // ### use index(item) - it's faster
60 Q_ASSERT(row != -1);
61 beginRemoveRows(parent: QModelIndex(), first: row, last: row);
62 items.at(i: row)->d->theid = -1;
63 items.at(i: row)->view = nullptr;
64 items.removeAt(i: row);
65 endRemoveRows();
66}
67
68void QListModel::insert(int row, QListWidgetItem *item)
69{
70 if (!item)
71 return;
72
73 item->view = qobject_cast<QListWidget*>(object: QObject::parent());
74 if (item->view && item->view->isSortingEnabled()) {
75 // sorted insertion
76 QList<QListWidgetItem*>::iterator it;
77 it = sortedInsertionIterator(begin: items.begin(), end: items.end(),
78 order: item->view->sortOrder(), item);
79 row = qMax<qsizetype>(a: it - items.begin(), b: 0);
80 } else {
81 if (row < 0)
82 row = 0;
83 else if (row > items.size())
84 row = items.size();
85 }
86 beginInsertRows(parent: QModelIndex(), first: row, last: row);
87 items.insert(i: row, t: item);
88 item->d->theid = row;
89 endInsertRows();
90}
91
92void QListModel::insert(int row, const QStringList &labels)
93{
94 const int count = labels.size();
95 if (count <= 0)
96 return;
97 QListWidget *view = qobject_cast<QListWidget*>(object: QObject::parent());
98 if (view && view->isSortingEnabled()) {
99 // sorted insertion
100 for (int i = 0; i < count; ++i) {
101 QListWidgetItem *item = new QListWidgetItem(labels.at(i));
102 insert(row, item);
103 }
104 } else {
105 if (row < 0)
106 row = 0;
107 else if (row > items.size())
108 row = items.size();
109 beginInsertRows(parent: QModelIndex(), first: row, last: row + count - 1);
110 for (int i = 0; i < count; ++i) {
111 QListWidgetItem *item = new QListWidgetItem(labels.at(i));
112 item->d->theid = row;
113 item->view = qobject_cast<QListWidget*>(object: QObject::parent());
114 items.insert(i: row++, t: item);
115 }
116 endInsertRows();
117 }
118}
119
120QListWidgetItem *QListModel::take(int row)
121{
122 if (row < 0 || row >= items.size())
123 return nullptr;
124
125 beginRemoveRows(parent: QModelIndex(), first: row, last: row);
126 items.at(i: row)->d->theid = -1;
127 items.at(i: row)->view = nullptr;
128 QListWidgetItem *item = items.takeAt(i: row);
129 endRemoveRows();
130 return item;
131}
132
133void QListModel::move(int srcRow, int dstRow)
134{
135 if (srcRow == dstRow
136 || srcRow < 0 || srcRow >= items.size()
137 || dstRow < 0 || dstRow > items.size())
138 return;
139
140 if (!beginMoveRows(sourceParent: QModelIndex(), sourceFirst: srcRow, sourceLast: srcRow, destinationParent: QModelIndex(), destinationRow: dstRow))
141 return;
142 if (srcRow < dstRow)
143 --dstRow;
144 items.move(from: srcRow, to: dstRow);
145 endMoveRows();
146}
147
148int QListModel::rowCount(const QModelIndex &parent) const
149{
150 return parent.isValid() ? 0 : items.size();
151}
152
153QModelIndex QListModel::index(const QListWidgetItem *item_) const
154{
155 QListWidgetItem *item = const_cast<QListWidgetItem *>(item_);
156 if (!item || !item->view || static_cast<const QListModel *>(item->view->model()) != this
157 || items.isEmpty())
158 return QModelIndex();
159 int row;
160 const int theid = item->d->theid;
161 if (theid >= 0 && theid < items.size() && items.at(i: theid) == item) {
162 row = theid;
163 } else { // we need to search for the item
164 row = items.lastIndexOf(t: item); // lastIndexOf is an optimization in favor of indexOf
165 if (row == -1) // not found
166 return QModelIndex();
167 item->d->theid = row;
168 }
169 return createIndex(arow: row, acolumn: 0, adata: item);
170}
171
172QModelIndex QListModel::index(int row, int column, const QModelIndex &parent) const
173{
174 if (hasIndex(row, column, parent))
175 return createIndex(arow: row, acolumn: column, adata: items.at(i: row));
176 return QModelIndex();
177}
178
179QVariant QListModel::data(const QModelIndex &index, int role) const
180{
181 if (!index.isValid() || index.row() >= items.size())
182 return QVariant();
183 return items.at(i: index.row())->data(role);
184}
185
186bool QListModel::setData(const QModelIndex &index, const QVariant &value, int role)
187{
188 if (!index.isValid() || index.row() >= items.size())
189 return false;
190 items.at(i: index.row())->setData(role, value);
191 return true;
192}
193
194bool QListModel::clearItemData(const QModelIndex &index)
195{
196 if (!checkIndex(index, options: CheckIndexOption::IndexIsValid))
197 return false;
198 QListWidgetItem *item = items.at(i: index.row());
199 const auto beginIter = item->d->values.cbegin();
200 const auto endIter = item->d->values.cend();
201 if (std::all_of(first: beginIter, last: endIter, pred: [](const QWidgetItemData& data) -> bool { return !data.value.isValid(); }))
202 return true; //it's already cleared
203 item->d->values.clear();
204 emit dataChanged(topLeft: index, bottomRight: index, roles: QList<int> {});
205 return true;
206}
207
208QMap<int, QVariant> QListModel::itemData(const QModelIndex &index) const
209{
210 QMap<int, QVariant> roles;
211 if (!index.isValid() || index.row() >= items.size())
212 return roles;
213 QListWidgetItem *itm = items.at(i: index.row());
214 for (int i = 0; i < itm->d->values.size(); ++i) {
215 roles.insert(key: itm->d->values.at(i).role,
216 value: itm->d->values.at(i).value);
217 }
218 return roles;
219}
220
221bool QListModel::insertRows(int row, int count, const QModelIndex &parent)
222{
223 if (count < 1 || row < 0 || row > rowCount() || parent.isValid())
224 return false;
225
226 beginInsertRows(parent: QModelIndex(), first: row, last: row + count - 1);
227 QListWidget *view = qobject_cast<QListWidget*>(object: QObject::parent());
228 QListWidgetItem *itm = nullptr;
229
230 for (int r = row; r < row + count; ++r) {
231 itm = new QListWidgetItem;
232 itm->view = view;
233 itm->d->theid = r;
234 items.insert(i: r, t: itm);
235 }
236
237 endInsertRows();
238 return true;
239}
240
241bool QListModel::removeRows(int row, int count, const QModelIndex &parent)
242{
243 if (count < 1 || row < 0 || (row + count) > rowCount() || parent.isValid())
244 return false;
245
246 beginRemoveRows(parent: QModelIndex(), first: row, last: row + count - 1);
247 QListWidgetItem *itm = nullptr;
248 for (int r = row; r < row + count; ++r) {
249 itm = items.takeAt(i: row);
250 itm->view = nullptr;
251 itm->d->theid = -1;
252 delete itm;
253 }
254 endRemoveRows();
255 return true;
256}
257
258/*!
259 \since 5.13
260 \reimp
261*/
262bool QListModel::moveRows(const QModelIndex &sourceParent, int sourceRow, int count, const QModelIndex &destinationParent, int destinationChild)
263{
264 if (sourceRow < 0
265 || sourceRow + count - 1 >= rowCount(parent: sourceParent)
266 || destinationChild < 0
267 || destinationChild > rowCount(parent: destinationParent)
268 || sourceRow == destinationChild
269 || sourceRow == destinationChild - 1
270 || count <= 0
271 || sourceParent.isValid()
272 || destinationParent.isValid()) {
273 return false;
274 }
275 if (!beginMoveRows(sourceParent: QModelIndex(), sourceFirst: sourceRow, sourceLast: sourceRow + count - 1, destinationParent: QModelIndex(), destinationRow: destinationChild))
276 return false;
277
278 int fromRow = sourceRow;
279 if (destinationChild < sourceRow)
280 fromRow += count - 1;
281 else
282 destinationChild--;
283 while (count--)
284 items.move(from: fromRow, to: destinationChild);
285 endMoveRows();
286 return true;
287}
288
289Qt::ItemFlags QListModel::flags(const QModelIndex &index) const
290{
291 if (!index.isValid() || index.row() >= items.size() || index.model() != this)
292 return Qt::ItemIsDropEnabled; // we allow drops outside the items
293 return items.at(i: index.row())->flags();
294}
295
296void QListModel::sort(int column, Qt::SortOrder order)
297{
298 if (column != 0)
299 return;
300
301 emit layoutAboutToBeChanged(parents: {}, hint: QAbstractItemModel::VerticalSortHint);
302
303 QList<QPair<QListWidgetItem *, int>> sorting(items.size());
304 for (int i = 0; i < items.size(); ++i) {
305 QListWidgetItem *item = items.at(i);
306 sorting[i].first = item;
307 sorting[i].second = i;
308 }
309
310 const auto compare = (order == Qt::AscendingOrder ? &itemLessThan : &itemGreaterThan);
311 std::sort(first: sorting.begin(), last: sorting.end(), comp: compare);
312 QModelIndexList fromIndexes;
313 QModelIndexList toIndexes;
314 const int sortingCount = sorting.size();
315 fromIndexes.reserve(asize: sortingCount);
316 toIndexes.reserve(asize: sortingCount);
317 for (int r = 0; r < sortingCount; ++r) {
318 QListWidgetItem *item = sorting.at(i: r).first;
319 toIndexes.append(t: createIndex(arow: r, acolumn: 0, adata: item));
320 fromIndexes.append(t: createIndex(arow: sorting.at(i: r).second, acolumn: 0, adata: sorting.at(i: r).first));
321 items[r] = sorting.at(i: r).first;
322 }
323 changePersistentIndexList(from: fromIndexes, to: toIndexes);
324
325 emit layoutChanged(parents: {}, hint: QAbstractItemModel::VerticalSortHint);
326}
327
328/**
329 * This function assumes that all items in the model except the items that are between
330 * (inclusive) start and end are sorted.
331 * With these assumptions, this function can ensure that the model is sorted in a
332 * much more efficient way than doing a naive 'sort everything'.
333 * (provided that the range is relatively small compared to the total number of items)
334 */
335void QListModel::ensureSorted(int column, Qt::SortOrder order, int start, int end)
336{
337 if (column != 0)
338 return;
339
340 const int count = end - start + 1;
341 QList<QPair<QListWidgetItem *, int>> sorting(count);
342 for (int i = 0; i < count; ++i) {
343 sorting[i].first = items.at(i: start + i);
344 sorting[i].second = start + i;
345 }
346
347 const auto compare = (order == Qt::AscendingOrder ? &itemLessThan : &itemGreaterThan);
348 std::sort(first: sorting.begin(), last: sorting.end(), comp: compare);
349
350 QModelIndexList oldPersistentIndexes = persistentIndexList();
351 QModelIndexList newPersistentIndexes = oldPersistentIndexes;
352 QList<QListWidgetItem*> tmp = items;
353 QList<QListWidgetItem*>::iterator lit = tmp.begin();
354 bool changed = false;
355 for (int i = 0; i < count; ++i) {
356 int oldRow = sorting.at(i).second;
357 int tmpitepos = lit - tmp.begin();
358 QListWidgetItem *item = tmp.takeAt(i: oldRow);
359 if (tmpitepos > tmp.size())
360 --tmpitepos;
361 lit = tmp.begin() + tmpitepos;
362 lit = sortedInsertionIterator(begin: lit, end: tmp.end(), order, item);
363 int newRow = qMax<qsizetype>(a: lit - tmp.begin(), b: 0);
364 lit = tmp.insert(before: lit, t: item);
365 if (newRow != oldRow) {
366 if (!changed) {
367 emit layoutAboutToBeChanged(parents: {}, hint: QAbstractItemModel::VerticalSortHint);
368 oldPersistentIndexes = persistentIndexList();
369 newPersistentIndexes = oldPersistentIndexes;
370 changed = true;
371 }
372 for (int j = i + 1; j < count; ++j) {
373 int otherRow = sorting.at(i: j).second;
374 if (oldRow < otherRow && newRow >= otherRow)
375 --sorting[j].second;
376 else if (oldRow > otherRow && newRow <= otherRow)
377 ++sorting[j].second;
378 }
379 for (int k = 0; k < newPersistentIndexes.size(); ++k) {
380 QModelIndex pi = newPersistentIndexes.at(i: k);
381 int oldPersistentRow = pi.row();
382 int newPersistentRow = oldPersistentRow;
383 if (oldPersistentRow == oldRow)
384 newPersistentRow = newRow;
385 else if (oldRow < oldPersistentRow && newRow >= oldPersistentRow)
386 newPersistentRow = oldPersistentRow - 1;
387 else if (oldRow > oldPersistentRow && newRow <= oldPersistentRow)
388 newPersistentRow = oldPersistentRow + 1;
389 if (newPersistentRow != oldPersistentRow)
390 newPersistentIndexes[k] = createIndex(arow: newPersistentRow,
391 acolumn: pi.column(), adata: pi.internalPointer());
392 }
393 }
394 }
395
396 if (changed) {
397 items = tmp;
398 changePersistentIndexList(from: oldPersistentIndexes, to: newPersistentIndexes);
399 emit layoutChanged(parents: {}, hint: QAbstractItemModel::VerticalSortHint);
400 }
401}
402
403bool QListModel::itemLessThan(const QPair<QListWidgetItem*,int> &left,
404 const QPair<QListWidgetItem*,int> &right)
405{
406 return (*left.first) < (*right.first);
407}
408
409bool QListModel::itemGreaterThan(const QPair<QListWidgetItem*,int> &left,
410 const QPair<QListWidgetItem*,int> &right)
411{
412 return (*right.first) < (*left.first);
413}
414
415QList<QListWidgetItem*>::iterator QListModel::sortedInsertionIterator(
416 const QList<QListWidgetItem*>::iterator &begin,
417 const QList<QListWidgetItem*>::iterator &end,
418 Qt::SortOrder order, QListWidgetItem *item)
419{
420 if (order == Qt::AscendingOrder)
421 return std::lower_bound(first: begin, last: end, val: item, comp: QListModelLessThan());
422 return std::lower_bound(first: begin, last: end, val: item, comp: QListModelGreaterThan());
423}
424
425void QListModel::itemChanged(QListWidgetItem *item, const QList<int> &roles)
426{
427 const QModelIndex idx = index(item_: item);
428 emit dataChanged(topLeft: idx, bottomRight: idx, roles);
429}
430
431QStringList QListModel::mimeTypes() const
432{
433 const QListWidget *view = qobject_cast<const QListWidget*>(object: QObject::parent());
434 if (view)
435 return view->mimeTypes();
436 return {};
437}
438
439QMimeData *QListModel::internalMimeData() const
440{
441 return QAbstractItemModel::mimeData(indexes: cachedIndexes);
442}
443
444QMimeData *QListModel::mimeData(const QModelIndexList &indexes) const
445{
446 QList<QListWidgetItem*> itemlist;
447 const int indexesCount = indexes.size();
448 itemlist.reserve(asize: indexesCount);
449 for (int i = 0; i < indexesCount; ++i)
450 itemlist << at(row: indexes.at(i).row());
451 const QListWidget *view = qobject_cast<const QListWidget*>(object: QObject::parent());
452
453 cachedIndexes = indexes;
454 QMimeData *mimeData = view->mimeData(items: itemlist);
455 cachedIndexes.clear();
456 return mimeData;
457}
458
459#if QT_CONFIG(draganddrop)
460bool QListModel::dropMimeData(const QMimeData *data, Qt::DropAction action,
461 int row, int column, const QModelIndex &index)
462{
463 Q_UNUSED(column);
464 QListWidget *view = qobject_cast<QListWidget*>(object: QObject::parent());
465 if (index.isValid())
466 row = index.row();
467 else if (row == -1)
468 row = items.size();
469
470 return view->dropMimeData(index: row, data, action);
471}
472
473Qt::DropActions QListModel::supportedDropActions() const
474{
475 const QListWidget *view = qobject_cast<const QListWidget*>(object: QObject::parent());
476 return view->supportedDropActions();
477}
478#endif // QT_CONFIG(draganddrop)
479
480/*!
481 \class QListWidgetItem
482 \brief The QListWidgetItem class provides an item for use with the
483 QListWidget item view class.
484
485 \ingroup model-view
486 \inmodule QtWidgets
487
488 A QListWidgetItem represents a single item in a QListWidget. Each item can
489 hold several pieces of information, and will display them appropriately.
490
491 The item view convenience classes use a classic item-based interface rather
492 than a pure model/view approach. For a more flexible list view widget,
493 consider using the QListView class with a standard model.
494
495 List items can be inserted automatically into a list, when they are
496 constructed, by specifying the list widget:
497
498 \snippet qlistwidget-using/mainwindow.cpp 2
499
500 Alternatively, list items can also be created without a parent widget, and
501 later inserted into a list using QListWidget::insertItem().
502
503 List items are typically used to display text() and an icon(). These are
504 set with the setText() and setIcon() functions. The appearance of the text
505 can be customized with setFont(), setForeground(), and setBackground().
506 Text in list items can be aligned using the setTextAlignment() function.
507 Tooltips, status tips and "What's This?" help can be added to list items
508 with setToolTip(), setStatusTip(), and setWhatsThis().
509
510 By default, items are enabled, selectable, checkable, and can be the source
511 of drag and drop operations.
512
513 Each item's flags can be changed by calling setFlags() with the appropriate
514 value (see Qt::ItemFlags). Checkable items can be checked, unchecked and
515 partially checked with the setCheckState() function. The corresponding
516 checkState() function indicates the item's current check state.
517
518 The isHidden() function can be used to determine whether the item is
519 hidden. To hide an item, use setHidden().
520
521
522 \section1 Subclassing
523
524 When subclassing QListWidgetItem to provide custom items, it is possible to
525 define new types for them enabling them to be distinguished from standard
526 items. For subclasses that require this feature, ensure that you call the
527 base class constructor with a new type value equal to or greater than
528 \l UserType, within \e your constructor.
529
530 \sa QListWidget, {Model/View Programming}, QTreeWidgetItem, QTableWidgetItem
531*/
532
533/*!
534 \enum QListWidgetItem::ItemType
535
536 This enum describes the types that are used to describe list widget items.
537
538 \value Type The default type for list widget items.
539 \value UserType The minimum value for custom types. Values below UserType are
540 reserved by Qt.
541
542 You can define new user types in QListWidgetItem subclasses to ensure that
543 custom items are treated specially.
544
545 \sa type()
546*/
547
548/*!
549 \fn int QListWidgetItem::type() const
550
551 Returns the type passed to the QListWidgetItem constructor.
552*/
553
554/*!
555 \fn QListWidget *QListWidgetItem::listWidget() const
556
557 Returns the list widget containing the item.
558*/
559
560/*!
561 \fn void QListWidgetItem::setHidden(bool hide)
562 \since 4.2
563
564 Hides the item if \a hide is true; otherwise shows the item.
565
566 \sa isHidden()
567*/
568
569/*!
570 \fn bool QListWidgetItem::isHidden() const
571 \since 4.2
572
573 Returns \c true if the item is hidden; otherwise returns \c false.
574
575 \sa setHidden()
576*/
577
578/*!
579 \fn QListWidgetItem::QListWidgetItem(QListWidget *parent, int type)
580
581 Constructs an empty list widget item of the specified \a type with the
582 given \a parent. If \a parent is not specified, the item will need to be
583 inserted into a list widget with QListWidget::insertItem().
584
585 This constructor inserts the item into the model of the parent that is
586 passed to the constructor. If the model is sorted then the behavior of the
587 insert is undetermined since the model will call the \c '<' operator method
588 on the item which, at this point, is not yet constructed. To avoid the
589 undetermined behavior, we recommend not to specify the parent and use
590 QListWidget::insertItem() instead.
591
592 \sa type()
593*/
594QListWidgetItem::QListWidgetItem(QListWidget *listview, int type)
595 : rtti(type), view(listview), d(new QListWidgetItemPrivate(this)),
596 itemFlags(Qt::ItemIsSelectable
597 |Qt::ItemIsUserCheckable
598 |Qt::ItemIsEnabled
599 |Qt::ItemIsDragEnabled)
600{
601 if (QListModel *model = listModel())
602 model->insert(row: model->rowCount(), item: this);
603}
604
605/*!
606 \fn QListWidgetItem::QListWidgetItem(const QString &text, QListWidget *parent, int type)
607
608 Constructs an empty list widget item of the specified \a type with the
609 given \a text and \a parent. If the parent is not specified, the item will
610 need to be inserted into a list widget with QListWidget::insertItem().
611
612 This constructor inserts the item into the model of the parent that is
613 passed to the constructor. If the model is sorted then the behavior of the
614 insert is undetermined since the model will call the \c '<' operator method
615 on the item which, at this point, is not yet constructed. To avoid the
616 undetermined behavior, we recommend not to specify the parent and use
617 QListWidget::insertItem() instead.
618
619 \sa type()
620*/
621QListWidgetItem::QListWidgetItem(const QString &text, QListWidget *listview, int type)
622 : rtti(type), view(listview), d(new QListWidgetItemPrivate(this)),
623 itemFlags(Qt::ItemIsSelectable
624 |Qt::ItemIsUserCheckable
625 |Qt::ItemIsEnabled
626 |Qt::ItemIsDragEnabled)
627{
628 QListModel *model = listModel();
629 {
630 QSignalBlocker b(view);
631 QSignalBlocker bm(model);
632 setData(role: Qt::DisplayRole, value: text);
633 }
634 if (model)
635 model->insert(row: model->rowCount(), item: this);
636}
637
638/*!
639 \fn QListWidgetItem::QListWidgetItem(const QIcon &icon, const QString &text, QListWidget *parent, int type)
640
641 Constructs an empty list widget item of the specified \a type with the
642 given \a icon, \a text and \a parent. If the parent is not specified, the
643 item will need to be inserted into a list widget with
644 QListWidget::insertItem().
645
646 This constructor inserts the item into the model of the parent that is
647 passed to the constructor. If the model is sorted then the behavior of the
648 insert is undetermined since the model will call the \c '<' operator method
649 on the item which, at this point, is not yet constructed. To avoid the
650 undetermined behavior, we recommend not to specify the parent and use
651 QListWidget::insertItem() instead.
652
653 \sa type()
654*/
655QListWidgetItem::QListWidgetItem(const QIcon &icon,const QString &text,
656 QListWidget *listview, int type)
657 : rtti(type), view(listview), d(new QListWidgetItemPrivate(this)),
658 itemFlags(Qt::ItemIsSelectable
659 |Qt::ItemIsUserCheckable
660 |Qt::ItemIsEnabled
661 |Qt::ItemIsDragEnabled)
662{
663 QListModel *model = listModel();
664 {
665 QSignalBlocker b(view);
666 QSignalBlocker bm(model);
667 setData(role: Qt::DisplayRole, value: text);
668 setData(role: Qt::DecorationRole, value: icon);
669 }
670 if (model)
671 model->insert(row: model->rowCount(), item: this);
672}
673
674/*!
675 Destroys the list item.
676*/
677QListWidgetItem::~QListWidgetItem()
678{
679 if (QListModel *model = listModel())
680 model->remove(item: this);
681 delete d;
682}
683
684/*!
685 Creates an exact copy of the item.
686*/
687QListWidgetItem *QListWidgetItem::clone() const
688{
689 return new QListWidgetItem(*this);
690}
691
692/*!
693 Sets the data for a given \a role to the given \a value. Reimplement this
694 function if you need extra roles or special behavior for certain roles.
695
696 \note The default implementation treats Qt::EditRole and Qt::DisplayRole as
697 referring to the same data.
698
699 \sa Qt::ItemDataRole, data()
700*/
701void QListWidgetItem::setData(int role, const QVariant &value)
702{
703 bool found = false;
704 role = (role == Qt::EditRole ? Qt::DisplayRole : role);
705 for (int i = 0; i < d->values.size(); ++i) {
706 if (d->values.at(i).role == role) {
707 if (d->values.at(i).value == value)
708 return;
709 d->values[i].value = value;
710 found = true;
711 break;
712 }
713 }
714 if (!found)
715 d->values.append(t: QWidgetItemData(role, value));
716 if (QListModel *model = listModel()) {
717 const QList<int> roles((role == Qt::DisplayRole)
718 ? QList<int>({ Qt::DisplayRole, Qt::EditRole })
719 : QList<int>({ role }));
720 model->itemChanged(item: this, roles);
721 }
722}
723
724/*!
725 Returns the item's data for a given \a role. Reimplement this function if
726 you need extra roles or special behavior for certain roles.
727
728 \sa Qt::ItemDataRole, setData()
729*/
730QVariant QListWidgetItem::data(int role) const
731{
732 role = (role == Qt::EditRole ? Qt::DisplayRole : role);
733 for (int i = 0; i < d->values.size(); ++i)
734 if (d->values.at(i).role == role)
735 return d->values.at(i).value;
736 return QVariant();
737}
738
739/*!
740 Returns \c true if this item's text is less then \a other item's text;
741 otherwise returns \c false.
742*/
743bool QListWidgetItem::operator<(const QListWidgetItem &other) const
744{
745 const QVariant v1 = data(role: Qt::DisplayRole), v2 = other.data(role: Qt::DisplayRole);
746 return QAbstractItemModelPrivate::variantLessThan(v1, v2);
747}
748
749#ifndef QT_NO_DATASTREAM
750
751/*!
752 Reads the item from stream \a in.
753
754 \sa write()
755*/
756void QListWidgetItem::read(QDataStream &in)
757{
758 in >> d->values;
759}
760
761/*!
762 Writes the item to stream \a out.
763
764 \sa read()
765*/
766void QListWidgetItem::write(QDataStream &out) const
767{
768 out << d->values;
769}
770#endif // QT_NO_DATASTREAM
771
772/*!
773 \since 4.1
774
775 Constructs a copy of \a other. Note that type() and listWidget() are not
776 copied.
777
778 This function is useful when reimplementing clone().
779
780 \sa data(), flags()
781*/
782QListWidgetItem::QListWidgetItem(const QListWidgetItem &other)
783 : rtti(Type), view(nullptr),
784 d(new QListWidgetItemPrivate(this)),
785 itemFlags(other.itemFlags)
786{
787 d->values = other.d->values;
788}
789
790/*!
791 Assigns \a other's data and flags to this item. Note that type() and
792 listWidget() are not copied.
793
794 This function is useful when reimplementing clone().
795
796 \sa data(), flags()
797*/
798QListWidgetItem &QListWidgetItem::operator=(const QListWidgetItem &other)
799{
800 d->values = other.d->values;
801 itemFlags = other.itemFlags;
802 return *this;
803}
804
805/*!
806 \internal
807 returns the QListModel if a view is set
808 */
809QListModel *QListWidgetItem::listModel() const
810{
811 return (view ? qobject_cast<QListModel*>(object: view->model()) : nullptr);
812}
813
814#ifndef QT_NO_DATASTREAM
815
816/*!
817 \relates QListWidgetItem
818
819 Writes the list widget item \a item to stream \a out.
820
821 This operator uses QListWidgetItem::write().
822
823 \sa {Serializing Qt Data Types}
824*/
825QDataStream &operator<<(QDataStream &out, const QListWidgetItem &item)
826{
827 item.write(out);
828 return out;
829}
830
831/*!
832 \relates QListWidgetItem
833
834 Reads a list widget item from stream \a in into \a item.
835
836 This operator uses QListWidgetItem::read().
837
838 \sa {Serializing Qt Data Types}
839*/
840QDataStream &operator>>(QDataStream &in, QListWidgetItem &item)
841{
842 item.read(in);
843 return in;
844}
845
846#endif // QT_NO_DATASTREAM
847
848/*!
849 \fn Qt::ItemFlags QListWidgetItem::flags() const
850
851 Returns the item flags for this item (see \l{Qt::ItemFlags}).
852*/
853
854/*!
855 \fn QString QListWidgetItem::text() const
856
857 Returns the list item's text.
858
859 \sa setText()
860*/
861
862/*!
863 \fn QIcon QListWidgetItem::icon() const
864
865 Returns the list item's icon.
866
867 \sa setIcon(), {QAbstractItemView::iconSize}{iconSize}
868*/
869
870/*!
871 \fn QString QListWidgetItem::statusTip() const
872
873 Returns the list item's status tip.
874
875 \sa setStatusTip()
876*/
877
878/*!
879 \fn QString QListWidgetItem::toolTip() const
880
881 Returns the list item's tooltip.
882
883 \sa setToolTip(), statusTip(), whatsThis()
884*/
885
886/*!
887 \fn QString QListWidgetItem::whatsThis() const
888
889 Returns the list item's "What's This?" help text.
890
891 \sa setWhatsThis(), statusTip(), toolTip()
892*/
893
894/*!
895 \fn QFont QListWidgetItem::font() const
896
897 Returns the font used to display this list item's text.
898*/
899
900/*!
901 \if defined(qt7)
902
903 \fn Qt::Alignment QListWidgetItem::textAlignment() const
904
905 Returns the text alignment for the list item.
906
907 \else
908
909 \fn int QListWidgetItem::textAlignment() const
910
911 Returns the text alignment for the list item.
912
913 \note This function returns an int for historical reasons. It will
914 be corrected to return Qt::Alignment in Qt 7.
915
916 \sa Qt::Alignment
917
918 \endif
919*/
920
921/*!
922 \fn QBrush QListWidgetItem::background() const
923 \since 4.2
924
925 Returns the brush used to display the list item's background.
926
927 \sa setBackground(), foreground()
928*/
929
930/*!
931 \fn QBrush QListWidgetItem::foreground() const
932 \since 4.2
933
934 Returns the brush used to display the list item's foreground (e.g. text).
935
936 \sa setForeground(), background()
937*/
938
939/*!
940 \fn Qt::CheckState QListWidgetItem::checkState() const
941
942 Returns the checked state of the list item (see \l{Qt::CheckState}).
943
944 \sa flags()
945*/
946
947/*!
948 \fn QSize QListWidgetItem::sizeHint() const
949 \since 4.1
950
951 Returns the size hint set for the list item.
952*/
953
954/*!
955 \fn void QListWidgetItem::setSizeHint(const QSize &size)
956 \since 4.1
957
958 Sets the size hint for the list item to be \a size.
959 If no size hint is set or \a size is invalid, the item
960 delegate will compute the size hint based on the item data.
961*/
962
963/*!
964 \fn void QListWidgetItem::setSelected(bool select)
965 \since 4.2
966
967 Sets the selected state of the item to \a select.
968
969 \sa isSelected()
970*/
971void QListWidgetItem::setSelected(bool select)
972{
973 const QListModel *model = listModel();
974 if (!model || !view->selectionModel())
975 return;
976 const QAbstractItemView::SelectionMode selectionMode = view->selectionMode();
977 if (selectionMode == QAbstractItemView::NoSelection)
978 return;
979 const QModelIndex index = model->index(item_: this);
980 if (selectionMode == QAbstractItemView::SingleSelection)
981 view->selectionModel()->select(index, command: select
982 ? QItemSelectionModel::ClearAndSelect
983 : QItemSelectionModel::Deselect);
984 else
985 view->selectionModel()->select(index, command: select
986 ? QItemSelectionModel::Select
987 : QItemSelectionModel::Deselect);
988}
989
990/*!
991 \fn bool QListWidgetItem::isSelected() const
992 \since 4.2
993
994 Returns \c true if the item is selected; otherwise returns \c false.
995
996 \sa setSelected()
997*/
998bool QListWidgetItem::isSelected() const
999{
1000 const QListModel *model = listModel();
1001 if (!model || !view->selectionModel())
1002 return false;
1003 const QModelIndex index = model->index(item_: this);
1004 return view->selectionModel()->isSelected(index);
1005}
1006
1007/*!
1008 \fn void QListWidgetItem::setFlags(Qt::ItemFlags flags)
1009
1010 Sets the item flags for the list item to \a flags.
1011
1012 \sa Qt::ItemFlags
1013*/
1014void QListWidgetItem::setFlags(Qt::ItemFlags aflags)
1015{
1016 itemFlags = aflags;
1017 if (QListModel *model = listModel())
1018 model->itemChanged(item: this);
1019}
1020
1021
1022/*!
1023 \fn void QListWidgetItem::setText(const QString &text)
1024
1025 Sets the text for the list widget item's to the given \a text.
1026
1027 \sa text()
1028*/
1029
1030/*!
1031 \fn void QListWidgetItem::setIcon(const QIcon &icon)
1032
1033 Sets the icon for the list item to the given \a icon.
1034
1035 \sa icon(), text(), {QAbstractItemView::iconSize}{iconSize}
1036*/
1037
1038/*!
1039 \fn void QListWidgetItem::setStatusTip(const QString &statusTip)
1040
1041 Sets the status tip for the list item to the text specified by
1042 \a statusTip. QListWidget mouseTracking needs to be enabled for this
1043 feature to work.
1044
1045 \sa statusTip(), setToolTip(), setWhatsThis(), QWidget::setMouseTracking()
1046*/
1047
1048/*!
1049 \fn void QListWidgetItem::setToolTip(const QString &toolTip)
1050
1051 Sets the tooltip for the list item to the text specified by \a toolTip.
1052
1053 \sa toolTip(), setStatusTip(), setWhatsThis()
1054*/
1055
1056/*!
1057 \fn void QListWidgetItem::setWhatsThis(const QString &whatsThis)
1058
1059 Sets the "What's This?" help for the list item to the text specified by
1060 \a whatsThis.
1061
1062 \sa whatsThis(), setStatusTip(), setToolTip()
1063*/
1064
1065/*!
1066 \fn void QListWidgetItem::setFont(const QFont &font)
1067
1068 Sets the font used when painting the item to the given \a font.
1069*/
1070
1071/*!
1072 \obsolete [6.4] Use the overload that takes a Qt::Alignment argument.
1073
1074 \fn void QListWidgetItem::setTextAlignment(int alignment)
1075
1076 Sets the list item's text alignment to \a alignment.
1077
1078 \sa Qt::Alignment
1079*/
1080
1081/*!
1082 \since 6.4
1083
1084 \fn void QListWidgetItem::setTextAlignment(Qt::Alignment alignment)
1085
1086 Sets the list item's text alignment to \a alignment.
1087*/
1088
1089/*!
1090 \fn void QListWidgetItem::setTextAlignment(Qt::AlignmentFlag alignment)
1091 \internal
1092*/
1093
1094/*!
1095 \fn void QListWidgetItem::setBackground(const QBrush &brush)
1096 \since 4.2
1097
1098 Sets the background brush of the list item to the given \a brush.
1099 Setting a default-constructed brush will let the view use the
1100 default color from the style.
1101
1102 \sa background(), setForeground()
1103*/
1104
1105/*!
1106 \fn void QListWidgetItem::setForeground(const QBrush &brush)
1107 \since 4.2
1108
1109 Sets the foreground brush of the list item to the given \a brush.
1110 Setting a default-constructed brush will let the view use the
1111 default color from the style.
1112
1113 \sa foreground(), setBackground()
1114*/
1115
1116/*!
1117 \fn void QListWidgetItem::setCheckState(Qt::CheckState state)
1118
1119 Sets the check state of the list item to \a state.
1120
1121 \sa checkState()
1122*/
1123
1124void QListWidgetPrivate::setup()
1125{
1126 Q_Q(QListWidget);
1127 q->QListView::setModel(new QListModel(q));
1128 // view signals
1129 QObject::connect(sender: q, SIGNAL(pressed(QModelIndex)), receiver: q, SLOT(_q_emitItemPressed(QModelIndex)));
1130 QObject::connect(sender: q, SIGNAL(clicked(QModelIndex)), receiver: q, SLOT(_q_emitItemClicked(QModelIndex)));
1131 QObject::connect(sender: q, SIGNAL(doubleClicked(QModelIndex)),
1132 receiver: q, SLOT(_q_emitItemDoubleClicked(QModelIndex)));
1133 QObject::connect(sender: q, SIGNAL(activated(QModelIndex)),
1134 receiver: q, SLOT(_q_emitItemActivated(QModelIndex)));
1135 QObject::connect(sender: q, SIGNAL(entered(QModelIndex)), receiver: q, SLOT(_q_emitItemEntered(QModelIndex)));
1136 QObject::connect(sender: model, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
1137 receiver: q, SLOT(_q_emitItemChanged(QModelIndex)));
1138 QObject::connect(sender: model, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
1139 receiver: q, SLOT(_q_dataChanged(QModelIndex,QModelIndex)));
1140 QObject::connect(sender: model, SIGNAL(columnsRemoved(QModelIndex,int,int)), receiver: q, SLOT(_q_sort()));
1141}
1142
1143void QListWidgetPrivate::_q_emitItemPressed(const QModelIndex &index)
1144{
1145 Q_Q(QListWidget);
1146 emit q->itemPressed(item: listModel()->at(row: index.row()));
1147}
1148
1149void QListWidgetPrivate::_q_emitItemClicked(const QModelIndex &index)
1150{
1151 Q_Q(QListWidget);
1152 emit q->itemClicked(item: listModel()->at(row: index.row()));
1153}
1154
1155void QListWidgetPrivate::_q_emitItemDoubleClicked(const QModelIndex &index)
1156{
1157 Q_Q(QListWidget);
1158 emit q->itemDoubleClicked(item: listModel()->at(row: index.row()));
1159}
1160
1161void QListWidgetPrivate::_q_emitItemActivated(const QModelIndex &index)
1162{
1163 Q_Q(QListWidget);
1164 emit q->itemActivated(item: listModel()->at(row: index.row()));
1165}
1166
1167void QListWidgetPrivate::_q_emitItemEntered(const QModelIndex &index)
1168{
1169 Q_Q(QListWidget);
1170 emit q->itemEntered(item: listModel()->at(row: index.row()));
1171}
1172
1173void QListWidgetPrivate::_q_emitItemChanged(const QModelIndex &index)
1174{
1175 Q_Q(QListWidget);
1176 emit q->itemChanged(item: listModel()->at(row: index.row()));
1177}
1178
1179void QListWidgetPrivate::_q_emitCurrentItemChanged(const QModelIndex &current,
1180 const QModelIndex &previous)
1181{
1182 Q_Q(QListWidget);
1183 QPersistentModelIndex persistentCurrent = current;
1184 QListWidgetItem *currentItem = listModel()->at(row: persistentCurrent.row());
1185 emit q->currentItemChanged(current: currentItem, previous: listModel()->at(row: previous.row()));
1186
1187 //persistentCurrent is invalid if something changed the model in response
1188 //to the currentItemChanged signal emission and the item was removed
1189 if (!persistentCurrent.isValid()) {
1190 currentItem = nullptr;
1191 }
1192
1193 emit q->currentTextChanged(currentText: currentItem ? currentItem->text() : QString());
1194 emit q->currentRowChanged(currentRow: persistentCurrent.row());
1195}
1196
1197void QListWidgetPrivate::_q_sort()
1198{
1199 if (sortingEnabled)
1200 model->sort(column: 0, order: sortOrder);
1201}
1202
1203void QListWidgetPrivate::_q_dataChanged(const QModelIndex &topLeft,
1204 const QModelIndex &bottomRight)
1205{
1206 if (sortingEnabled && topLeft.isValid() && bottomRight.isValid())
1207 listModel()->ensureSorted(column: topLeft.column(), order: sortOrder,
1208 start: topLeft.row(), end: bottomRight.row());
1209}
1210
1211/*!
1212 \class QListWidget
1213 \brief The QListWidget class provides an item-based list widget.
1214
1215 \ingroup model-view
1216 \inmodule QtWidgets
1217
1218 \image windows-listview.png
1219
1220 QListWidget is a convenience class that provides a list view similar to the
1221 one supplied by QListView, but with a classic item-based interface for
1222 adding and removing items. QListWidget uses an internal model to manage
1223 each QListWidgetItem in the list.
1224
1225 For a more flexible list view widget, use the QListView class with a
1226 standard model.
1227
1228 List widgets are constructed in the same way as other widgets:
1229
1230 \snippet qlistwidget-using/mainwindow.cpp 0
1231
1232 The selectionMode() of a list widget determines how many of the items in
1233 the list can be selected at the same time, and whether complex selections
1234 of items can be created. This can be set with the setSelectionMode()
1235 function.
1236
1237 There are two ways to add items to the list: they can be constructed with
1238 the list widget as their parent widget, or they can be constructed with no
1239 parent widget and added to the list later. If a list widget already exists
1240 when the items are constructed, the first method is easier to use:
1241
1242 \snippet qlistwidget-using/mainwindow.cpp 1
1243
1244 If you need to insert a new item into the list at a particular position,
1245 then it should be constructed without a parent widget. The insertItem()
1246 function should then be used to place it within the list. The list widget
1247 will take ownership of the item.
1248
1249 \snippet qlistwidget-using/mainwindow.cpp 6
1250 \snippet qlistwidget-using/mainwindow.cpp 7
1251
1252 For multiple items, insertItems() can be used instead. The number of items
1253 in the list is found with the count() function. To remove items from the
1254 list, use takeItem().
1255
1256 The current item in the list can be found with currentItem(), and changed
1257 with setCurrentItem(). The user can also change the current item by
1258 navigating with the keyboard or clicking on a different item. When the
1259 current item changes, the currentItemChanged() signal is emitted with the
1260 new current item and the item that was previously current.
1261
1262 \sa QListWidgetItem, QListView, QTreeView, {Model/View Programming},
1263 {Tab Dialog Example}
1264*/
1265
1266/*!
1267 \fn void QListWidget::addItem(QListWidgetItem *item)
1268
1269 Inserts the \a item at the end of the list widget.
1270
1271 \warning A QListWidgetItem can only be added to a QListWidget once. Adding
1272 the same QListWidgetItem multiple times to a QListWidget will result in
1273 undefined behavior.
1274
1275 \sa insertItem()
1276*/
1277
1278/*!
1279 \fn void QListWidget::addItem(const QString &label)
1280
1281 Inserts an item with the text \a label at the end of the list widget.
1282*/
1283
1284/*!
1285 \fn void QListWidget::addItems(const QStringList &labels)
1286
1287 Inserts items with the text \a labels at the end of the list widget.
1288
1289 \sa insertItems()
1290*/
1291
1292/*!
1293 \fn void QListWidget::itemPressed(QListWidgetItem *item)
1294
1295 This signal is emitted with the specified \a item when a mouse button is
1296 pressed on an item in the widget.
1297
1298 \sa itemClicked(), itemDoubleClicked()
1299*/
1300
1301/*!
1302 \fn void QListWidget::itemClicked(QListWidgetItem *item)
1303
1304 This signal is emitted with the specified \a item when a mouse button is
1305 clicked on an item in the widget.
1306
1307 \sa itemPressed(), itemDoubleClicked()
1308*/
1309
1310/*!
1311 \fn void QListWidget::itemDoubleClicked(QListWidgetItem *item)
1312
1313 This signal is emitted with the specified \a item when a mouse button is
1314 double clicked on an item in the widget.
1315
1316 \sa itemClicked(), itemPressed()
1317*/
1318
1319/*!
1320 \fn void QListWidget::itemActivated(QListWidgetItem *item)
1321
1322 This signal is emitted when the \a item is activated. The \a item is
1323 activated when the user clicks or double clicks on it, depending on the
1324 system configuration. It is also activated when the user presses the
1325 activation key (on Windows and X11 this is the \uicontrol Return key, on Mac OS
1326 X it is \uicontrol{Command+O}).
1327*/
1328
1329/*!
1330 \fn void QListWidget::itemEntered(QListWidgetItem *item)
1331
1332 This signal is emitted when the mouse cursor enters an item. The \a item is
1333 the item entered. This signal is only emitted when mouseTracking is turned
1334 on, or when a mouse button is pressed while moving into an item.
1335
1336 \sa QWidget::setMouseTracking()
1337*/
1338
1339/*!
1340 \fn void QListWidget::itemChanged(QListWidgetItem *item)
1341
1342 This signal is emitted whenever the data of \a item has changed.
1343*/
1344
1345/*!
1346 \fn void QListWidget::currentItemChanged(QListWidgetItem *current, QListWidgetItem *previous)
1347
1348 This signal is emitted whenever the current item changes.
1349
1350 \a previous is the item that previously had the focus; \a current is the
1351 new current item.
1352*/
1353
1354/*!
1355 \fn void QListWidget::currentTextChanged(const QString &currentText)
1356
1357 This signal is emitted whenever the current item changes.
1358
1359 \a currentText is the text data in the current item. If there is no current
1360 item, the \a currentText is invalid.
1361*/
1362
1363/*!
1364 \fn void QListWidget::currentRowChanged(int currentRow)
1365
1366 This signal is emitted whenever the current item changes.
1367
1368 \a currentRow is the row of the current item. If there is no current item,
1369 the \a currentRow is -1.
1370*/
1371
1372/*!
1373 \fn void QListWidget::itemSelectionChanged()
1374
1375 This signal is emitted whenever the selection changes.
1376
1377 \sa selectedItems(), QListWidgetItem::isSelected(), currentItemChanged()
1378*/
1379
1380/*!
1381 \since 4.3
1382
1383 \fn void QListWidget::removeItemWidget(QListWidgetItem *item)
1384
1385 Removes the widget set on the given \a item.
1386
1387 To remove an item (row) from the list entirely, either delete the item or
1388 use takeItem().
1389
1390 \sa itemWidget(), setItemWidget()
1391*/
1392
1393/*!
1394 Constructs an empty QListWidget with the given \a parent.
1395*/
1396
1397QListWidget::QListWidget(QWidget *parent)
1398 : QListView(*new QListWidgetPrivate(), parent)
1399{
1400 Q_D(QListWidget);
1401 d->setup();
1402}
1403
1404/*!
1405 Destroys the list widget and all its items.
1406*/
1407
1408QListWidget::~QListWidget()
1409{
1410}
1411
1412/*!
1413 \reimp
1414*/
1415
1416void QListWidget::setSelectionModel(QItemSelectionModel *selectionModel)
1417{
1418 Q_D(QListWidget);
1419
1420 if (d->selectionModel) {
1421 QObject::disconnect(sender: d->selectionModel, SIGNAL(currentChanged(QModelIndex,QModelIndex)),
1422 receiver: this, SLOT(_q_emitCurrentItemChanged(QModelIndex,QModelIndex)));
1423 QObject::disconnect(sender: d->selectionModel, SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
1424 receiver: this, SIGNAL(itemSelectionChanged()));
1425 }
1426
1427 QListView::setSelectionModel(selectionModel);
1428
1429 if (d->selectionModel) {
1430 QObject::connect(sender: d->selectionModel, SIGNAL(currentChanged(QModelIndex,QModelIndex)),
1431 receiver: this, SLOT(_q_emitCurrentItemChanged(QModelIndex,QModelIndex)));
1432 QObject::connect(sender: d->selectionModel, SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
1433 receiver: this, SIGNAL(itemSelectionChanged()));
1434 }
1435}
1436
1437/*!
1438 Returns the item that occupies the given \a row in the list if one has been
1439 set; otherwise returns \nullptr.
1440
1441 \sa row()
1442*/
1443
1444QListWidgetItem *QListWidget::item(int row) const
1445{
1446 Q_D(const QListWidget);
1447 if (row < 0 || row >= d->model->rowCount())
1448 return nullptr;
1449 return d->listModel()->at(row);
1450}
1451
1452/*!
1453 Returns the row containing the given \a item.
1454
1455 \sa item()
1456*/
1457
1458int QListWidget::row(const QListWidgetItem *item) const
1459{
1460 Q_D(const QListWidget);
1461 return d->listModel()->index(item_: const_cast<QListWidgetItem*>(item)).row();
1462}
1463
1464
1465/*!
1466 Inserts the \a item at the position in the list given by \a row.
1467
1468 \sa addItem()
1469*/
1470
1471void QListWidget::insertItem(int row, QListWidgetItem *item)
1472{
1473 Q_D(QListWidget);
1474 if (item && !item->view)
1475 d->listModel()->insert(row, item);
1476}
1477
1478/*!
1479 Inserts an item with the text \a label in the list widget at the position
1480 given by \a row.
1481
1482 \sa addItem()
1483*/
1484
1485void QListWidget::insertItem(int row, const QString &label)
1486{
1487 Q_D(QListWidget);
1488 d->listModel()->insert(row, item: new QListWidgetItem(label));
1489}
1490
1491/*!
1492 Inserts items from the list of \a labels into the list, starting at the
1493 given \a row.
1494
1495 \sa insertItem(), addItem()
1496*/
1497
1498void QListWidget::insertItems(int row, const QStringList &labels)
1499{
1500 Q_D(QListWidget);
1501 d->listModel()->insert(row, labels);
1502}
1503
1504/*!
1505 Removes and returns the item from the given \a row in the list widget;
1506 otherwise returns \nullptr.
1507
1508 Items removed from a list widget will not be managed by Qt, and will need
1509 to be deleted manually.
1510
1511 \sa insertItem(), addItem()
1512*/
1513
1514QListWidgetItem *QListWidget::takeItem(int row)
1515{
1516 Q_D(QListWidget);
1517 if (row < 0 || row >= d->model->rowCount())
1518 return nullptr;
1519 return d->listModel()->take(row);
1520}
1521
1522/*!
1523 \property QListWidget::count
1524 \brief the number of items in the list including any hidden items.
1525*/
1526
1527int QListWidget::count() const
1528{
1529 Q_D(const QListWidget);
1530 return d->model->rowCount();
1531}
1532
1533/*!
1534 Returns the current item.
1535*/
1536QListWidgetItem *QListWidget::currentItem() const
1537{
1538 Q_D(const QListWidget);
1539 return d->listModel()->at(row: currentIndex().row());
1540}
1541
1542
1543/*!
1544 Sets the current item to \a item.
1545
1546 Unless the selection mode is \l{QAbstractItemView::}{NoSelection},
1547 the item is also selected.
1548*/
1549void QListWidget::setCurrentItem(QListWidgetItem *item)
1550{
1551 setCurrentRow(row(item));
1552}
1553
1554/*!
1555 \since 4.4
1556 Set the current item to \a item, using the given \a command.
1557*/
1558void QListWidget::setCurrentItem(QListWidgetItem *item, QItemSelectionModel::SelectionFlags command)
1559{
1560 setCurrentRow(row: row(item), command);
1561}
1562
1563/*!
1564 \property QListWidget::currentRow
1565 \brief the row of the current item.
1566
1567 Depending on the current selection mode, the row may also be selected.
1568*/
1569
1570int QListWidget::currentRow() const
1571{
1572 return currentIndex().row();
1573}
1574
1575void QListWidget::setCurrentRow(int row)
1576{
1577 Q_D(QListWidget);
1578 QModelIndex index = d->listModel()->index(row);
1579 if (d->selectionMode == SingleSelection)
1580 selectionModel()->setCurrentIndex(index, command: QItemSelectionModel::ClearAndSelect);
1581 else if (d->selectionMode == NoSelection)
1582 selectionModel()->setCurrentIndex(index, command: QItemSelectionModel::NoUpdate);
1583 else
1584 selectionModel()->setCurrentIndex(index, command: QItemSelectionModel::SelectCurrent);
1585}
1586
1587/*!
1588 \since 4.4
1589
1590 Sets the current row to be the given \a row, using the given \a command,
1591*/
1592void QListWidget::setCurrentRow(int row, QItemSelectionModel::SelectionFlags command)
1593{
1594 Q_D(QListWidget);
1595 d->selectionModel->setCurrentIndex(index: d->listModel()->index(row), command);
1596}
1597
1598/*!
1599 Returns a pointer to the item at the coordinates \a p. The coordinates
1600 are relative to the list widget's \l{QAbstractScrollArea::}{viewport()}.
1601
1602*/
1603QListWidgetItem *QListWidget::itemAt(const QPoint &p) const
1604{
1605 Q_D(const QListWidget);
1606 return d->listModel()->at(row: indexAt(p).row());
1607
1608}
1609
1610/*!
1611 \fn QListWidgetItem *QListWidget::itemAt(int x, int y) const
1612 \overload
1613
1614 Returns a pointer to the item at the coordinates (\a x, \a y).
1615 The coordinates are relative to the list widget's
1616 \l{QAbstractScrollArea::}{viewport()}.
1617
1618*/
1619
1620
1621/*!
1622 Returns the rectangle on the viewport occupied by the item at \a item.
1623*/
1624QRect QListWidget::visualItemRect(const QListWidgetItem *item) const
1625{
1626 Q_D(const QListWidget);
1627 QModelIndex index = d->listModel()->index(item_: const_cast<QListWidgetItem*>(item));
1628 return visualRect(index);
1629}
1630
1631/*!
1632 Sorts all the items in the list widget according to the specified \a order.
1633*/
1634void QListWidget::sortItems(Qt::SortOrder order)
1635{
1636 Q_D(QListWidget);
1637 d->sortOrder = order;
1638 d->listModel()->sort(column: 0, order);
1639}
1640
1641/*!
1642 \since 4.2
1643 \property QListWidget::sortingEnabled
1644 \brief whether sorting is enabled
1645
1646 If this property is \c true, sorting is enabled for the list; if the property
1647 is false, sorting is not enabled.
1648
1649 The default value is false.
1650*/
1651void QListWidget::setSortingEnabled(bool enable)
1652{
1653 Q_D(QListWidget);
1654 d->sortingEnabled = enable;
1655}
1656
1657bool QListWidget::isSortingEnabled() const
1658{
1659 Q_D(const QListWidget);
1660 return d->sortingEnabled;
1661}
1662
1663/*!
1664 \internal
1665*/
1666Qt::SortOrder QListWidget::sortOrder() const
1667{
1668 Q_D(const QListWidget);
1669 return d->sortOrder;
1670}
1671
1672/*!
1673 Starts editing the \a item if it is editable.
1674*/
1675
1676void QListWidget::editItem(QListWidgetItem *item)
1677{
1678 Q_D(QListWidget);
1679 edit(index: d->listModel()->index(item_: item));
1680}
1681
1682/*!
1683 Opens an editor for the given \a item. The editor remains open after
1684 editing.
1685
1686 \sa closePersistentEditor(), isPersistentEditorOpen()
1687*/
1688void QListWidget::openPersistentEditor(QListWidgetItem *item)
1689{
1690 Q_D(QListWidget);
1691 QModelIndex index = d->listModel()->index(item_: item);
1692 QAbstractItemView::openPersistentEditor(index);
1693}
1694
1695/*!
1696 Closes the persistent editor for the given \a item.
1697
1698 \sa openPersistentEditor(), isPersistentEditorOpen()
1699*/
1700void QListWidget::closePersistentEditor(QListWidgetItem *item)
1701{
1702 Q_D(QListWidget);
1703 QModelIndex index = d->listModel()->index(item_: item);
1704 QAbstractItemView::closePersistentEditor(index);
1705}
1706
1707/*!
1708 \since 5.10
1709
1710 Returns whether a persistent editor is open for item \a item.
1711
1712 \sa openPersistentEditor(), closePersistentEditor()
1713*/
1714bool QListWidget::isPersistentEditorOpen(QListWidgetItem *item) const
1715{
1716 Q_D(const QListWidget);
1717 const QModelIndex index = d->listModel()->index(item_: item);
1718 return QAbstractItemView::isPersistentEditorOpen(index);
1719}
1720
1721/*!
1722 \since 4.1
1723
1724 Returns the widget displayed in the given \a item.
1725
1726 \sa setItemWidget(), removeItemWidget()
1727*/
1728QWidget *QListWidget::itemWidget(QListWidgetItem *item) const
1729{
1730 Q_D(const QListWidget);
1731 QModelIndex index = d->listModel()->index(item_: item);
1732 return QAbstractItemView::indexWidget(index);
1733}
1734
1735/*!
1736 \since 4.1
1737
1738 Sets the \a widget to be displayed in the given \a item.
1739
1740 This function should only be used to display static content in the place of
1741 a list widget item. If you want to display custom dynamic content or
1742 implement a custom editor widget, use QListView and subclass QStyledItemDelegate
1743 instead.
1744
1745 \sa itemWidget(), removeItemWidget(), {Delegate Classes}
1746*/
1747void QListWidget::setItemWidget(QListWidgetItem *item, QWidget *widget)
1748{
1749 Q_D(QListWidget);
1750 QModelIndex index = d->listModel()->index(item_: item);
1751 QAbstractItemView::setIndexWidget(index, widget);
1752}
1753
1754/*!
1755 Returns a list of all selected items in the list widget.
1756*/
1757
1758QList<QListWidgetItem*> QListWidget::selectedItems() const
1759{
1760 Q_D(const QListWidget);
1761 QModelIndexList indexes = selectionModel()->selectedIndexes();
1762 QList<QListWidgetItem*> items;
1763 const int numIndexes = indexes.size();
1764 items.reserve(asize: numIndexes);
1765 for (int i = 0; i < numIndexes; ++i)
1766 items.append(t: d->listModel()->at(row: indexes.at(i).row()));
1767 return items;
1768}
1769
1770/*!
1771 Finds items with the text that matches the string \a text using the given
1772 \a flags.
1773*/
1774
1775QList<QListWidgetItem*> QListWidget::findItems(const QString &text, Qt::MatchFlags flags) const
1776{
1777 Q_D(const QListWidget);
1778 QModelIndexList indexes = d->listModel()->match(start: model()->index(row: 0, column: 0, parent: QModelIndex()),
1779 role: Qt::DisplayRole, value: text, hits: -1, flags);
1780 QList<QListWidgetItem*> items;
1781 const int indexesSize = indexes.size();
1782 items.reserve(asize: indexesSize);
1783 for (int i = 0; i < indexesSize; ++i)
1784 items.append(t: d->listModel()->at(row: indexes.at(i).row()));
1785 return items;
1786}
1787
1788/*!
1789 Scrolls the view if necessary to ensure that the \a item is visible.
1790
1791 \a hint specifies where the \a item should be located after the operation.
1792*/
1793
1794void QListWidget::scrollToItem(const QListWidgetItem *item, QAbstractItemView::ScrollHint hint)
1795{
1796 Q_D(QListWidget);
1797 QModelIndex index = d->listModel()->index(item_: const_cast<QListWidgetItem*>(item));
1798 QListView::scrollTo(index, hint);
1799}
1800
1801/*!
1802 Removes all items and selections in the view.
1803
1804 \warning All items will be permanently deleted.
1805*/
1806void QListWidget::clear()
1807{
1808 Q_D(QListWidget);
1809 selectionModel()->clear();
1810 d->listModel()->clear();
1811}
1812
1813/*!
1814 Returns a list of MIME types that can be used to describe a list of
1815 listwidget items.
1816
1817 \sa mimeData()
1818*/
1819QStringList QListWidget::mimeTypes() const
1820{
1821 return d_func()->listModel()->QAbstractListModel::mimeTypes();
1822}
1823
1824/*!
1825 Returns an object that contains a serialized description of the specified
1826 \a items. The format used to describe the items is obtained from the
1827 mimeTypes() function.
1828
1829 If the list of items is empty, \nullptr is returned instead of a
1830 serialized empty list.
1831*/
1832QMimeData *QListWidget::mimeData(const QList<QListWidgetItem *> &items) const
1833{
1834 Q_D(const QListWidget);
1835
1836 QModelIndexList &cachedIndexes = d->listModel()->cachedIndexes;
1837
1838 // if non empty, it's called from the model's own mimeData
1839 if (cachedIndexes.isEmpty()) {
1840 cachedIndexes.reserve(asize: items.size());
1841 for (QListWidgetItem *item : items)
1842 cachedIndexes << indexFromItem(item);
1843
1844 QMimeData *result = d->listModel()->internalMimeData();
1845
1846 cachedIndexes.clear();
1847 return result;
1848 }
1849
1850 return d->listModel()->internalMimeData();
1851}
1852
1853#if QT_CONFIG(draganddrop)
1854/*!
1855 Handles \a data supplied by an external drag and drop operation that ended
1856 with the given \a action in the given \a index. Returns \c true if \a data and
1857 \a action can be handled by the model; otherwise returns \c false.
1858
1859 \sa supportedDropActions()
1860*/
1861bool QListWidget::dropMimeData(int index, const QMimeData *data, Qt::DropAction action)
1862{
1863 QModelIndex idx;
1864 int row = index;
1865 int column = 0;
1866 if (dropIndicatorPosition() == QAbstractItemView::OnItem) {
1867 // QAbstractListModel::dropMimeData will overwrite on the index if row == -1 and column == -1
1868 idx = model()->index(row, column);
1869 row = -1;
1870 column = -1;
1871 }
1872 return d_func()->listModel()->QAbstractListModel::dropMimeData(data, action , row, column, parent: idx);
1873}
1874
1875/*! \reimp */
1876void QListWidget::dropEvent(QDropEvent *event)
1877{
1878 QListView::dropEvent(e: event);
1879}
1880
1881/*!
1882 Returns the drop actions supported by this view.
1883
1884 \sa Qt::DropActions
1885*/
1886Qt::DropActions QListWidget::supportedDropActions() const
1887{
1888 Q_D(const QListWidget);
1889 return d->listModel()->QAbstractListModel::supportedDropActions() | Qt::MoveAction;
1890}
1891#endif // QT_CONFIG(draganddrop)
1892
1893/*!
1894 Returns a list of pointers to the items contained in the \a data object. If
1895 the object was not created by a QListWidget in the same process, the list
1896 is empty.
1897*/
1898QList<QListWidgetItem*> QListWidget::items(const QMimeData *data) const
1899{
1900 const QListWidgetMimeData *lwd = qobject_cast<const QListWidgetMimeData*>(object: data);
1901 if (lwd)
1902 return lwd->items;
1903 return QList<QListWidgetItem*>();
1904}
1905
1906/*!
1907 Returns the QModelIndex associated with the given \a item.
1908
1909 \note In Qt versions prior to 5.10, this function took a non-\c{const} \a item.
1910*/
1911
1912QModelIndex QListWidget::indexFromItem(const QListWidgetItem *item) const
1913{
1914 Q_D(const QListWidget);
1915 return d->listModel()->index(item_: item);
1916}
1917
1918/*!
1919 Returns a pointer to the QListWidgetItem associated with the given \a index.
1920*/
1921
1922QListWidgetItem *QListWidget::itemFromIndex(const QModelIndex &index) const
1923{
1924 Q_D(const QListWidget);
1925 if (d->isIndexValid(index))
1926 return d->listModel()->at(row: index.row());
1927 return nullptr;
1928}
1929
1930/*!
1931 \internal
1932*/
1933void QListWidget::setModel(QAbstractItemModel * /*model*/)
1934{
1935 Q_ASSERT(!"QListWidget::setModel() - Changing the model of the QListWidget is not allowed.");
1936}
1937
1938/*!
1939 \reimp
1940*/
1941bool QListWidget::event(QEvent *e)
1942{
1943 return QListView::event(e);
1944}
1945
1946QT_END_NAMESPACE
1947
1948#include "moc_qlistwidget.cpp"
1949#include "moc_qlistwidget_p.cpp"
1950

source code of qtbase/src/widgets/itemviews/qlistwidget.cpp