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

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