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

Provided by KDAB

Privacy Policy
Learn to use CMake with our Intro Training
Find out more

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