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

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