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 
49 QT_BEGIN_NAMESPACE
50 
51 class QListWidgetMimeData : public QMimeData
52 {
53     Q_OBJECT
54 public:
55     QList<QListWidgetItem*> items;
56 };
57 
58 QT_BEGIN_INCLUDE_NAMESPACE
59 #include "qlistwidget.moc"
60 QT_END_INCLUDE_NAMESPACE
61 
QListModel(QListWidget * parent)62 QListModel::QListModel(QListWidget *parent)
63     : QAbstractListModel(parent)
64 {
65 }
66 
~QListModel()67 QListModel::~QListModel()
68 {
69     clear();
70 }
71 
clear()72 void 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 
at(int row) const86 QListWidgetItem *QListModel::at(int row) const
87 {
88     return items.value(row);
89 }
90 
remove(QListWidgetItem * item)91 void QListModel::remove(QListWidgetItem *item)
92 {
93     if (!item)
94         return;
95     int row = items.indexOf(item); // ### use index(item) - it's faster
96     Q_ASSERT(row != -1);
97     beginRemoveRows(QModelIndex(), row, row);
98     items.at(row)->d->theid = -1;
99     items.at(row)->view = nullptr;
100     items.removeAt(row);
101     endRemoveRows();
102 }
103 
insert(int row,QListWidgetItem * item)104 void QListModel::insert(int row, QListWidgetItem *item)
105 {
106     if (!item)
107         return;
108 
109     item->view = qobject_cast<QListWidget*>(QObject::parent());
110     if (item->view && item->view->isSortingEnabled()) {
111         // sorted insertion
112         QList<QListWidgetItem*>::iterator it;
113         it = sortedInsertionIterator(items.begin(), items.end(),
114                                      item->view->sortOrder(), item);
115         row = qMax(it - items.begin(), 0);
116     } else {
117         if (row < 0)
118             row = 0;
119         else if (row > items.count())
120             row = items.count();
121     }
122     beginInsertRows(QModelIndex(), row, row);
123     items.insert(row, item);
124     item->d->theid = row;
125     endInsertRows();
126 }
127 
insert(int row,const QStringList & labels)128 void 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*>(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(QModelIndex(), row, 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*>(QObject::parent());
150             items.insert(row++, item);
151         }
152         endInsertRows();
153     }
154 }
155 
take(int row)156 QListWidgetItem *QListModel::take(int row)
157 {
158     if (row < 0 || row >= items.count())
159         return nullptr;
160 
161     beginRemoveRows(QModelIndex(), row, row);
162     items.at(row)->d->theid = -1;
163     items.at(row)->view = nullptr;
164     QListWidgetItem *item = items.takeAt(row);
165     endRemoveRows();
166     return item;
167 }
168 
move(int srcRow,int dstRow)169 void 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(QModelIndex(), srcRow, srcRow, QModelIndex(), dstRow))
177         return;
178     if (srcRow < dstRow)
179         --dstRow;
180     items.move(srcRow, dstRow);
181     endMoveRows();
182 }
183 
rowCount(const QModelIndex & parent) const184 int QListModel::rowCount(const QModelIndex &parent) const
185 {
186     return parent.isValid() ? 0 : items.count();
187 }
188 
index(const QListWidgetItem * item_) const189 QModelIndex 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(theid) == item) {
198         row = theid;
199     } else { // we need to search for the item
200         row = items.lastIndexOf(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(row, 0, item);
206 }
207 
index(int row,int column,const QModelIndex & parent) const208 QModelIndex QListModel::index(int row, int column, const QModelIndex &parent) const
209 {
210     if (hasIndex(row, column, parent))
211         return createIndex(row, column, items.at(row));
212     return QModelIndex();
213 }
214 
data(const QModelIndex & index,int role) const215 QVariant QListModel::data(const QModelIndex &index, int role) const
216 {
217     if (!index.isValid() || index.row() >= items.count())
218         return QVariant();
219     return items.at(index.row())->data(role);
220 }
221 
setData(const QModelIndex & index,const QVariant & value,int role)222 bool 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(index.row())->setData(role, value);
227     return true;
228 }
229 
230 #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
clearItemData(const QModelIndex & index)231 bool 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 
itemData(const QModelIndex & index) const246 QMap<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(index.row());
252     for (int i = 0; i < itm->d->values.count(); ++i) {
253         roles.insert(itm->d->values.at(i).role,
254                      itm->d->values.at(i).value);
255     }
256     return roles;
257 }
258 
insertRows(int row,int count,const QModelIndex & parent)259 bool 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(QModelIndex(), row, row + count - 1);
265     QListWidget *view = qobject_cast<QListWidget*>(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(r, itm);
273     }
274 
275     endInsertRows();
276     return true;
277 }
278 
removeRows(int row,int count,const QModelIndex & parent)279 bool 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(QModelIndex(), row, row + count - 1);
285     QListWidgetItem *itm = nullptr;
286     for (int r = row; r < row + count; ++r) {
287         itm = items.takeAt(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 */
moveRows(const QModelIndex & sourceParent,int sourceRow,int count,const QModelIndex & destinationParent,int destinationChild)300 bool QListModel::moveRows(const QModelIndex &sourceParent, int sourceRow, int count, const QModelIndex &destinationParent, int destinationChild)
301 {
302     if (sourceRow < 0
303         || sourceRow + count - 1 >= rowCount(sourceParent)
304         || destinationChild < 0
305         || destinationChild > rowCount(destinationParent)
306         || sourceRow == destinationChild
307         || sourceRow == destinationChild - 1
308         || count <= 0
309         || sourceParent.isValid()
310         || destinationParent.isValid()) {
311         return false;
312     }
313     if (!beginMoveRows(QModelIndex(), sourceRow, sourceRow + count - 1, QModelIndex(), 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(fromRow, destinationChild);
323     endMoveRows();
324     return true;
325 }
326 
flags(const QModelIndex & index) const327 Qt::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(index.row())->flags();
332 }
333 
sort(int column,Qt::SortOrder order)334 void QListModel::sort(int column, Qt::SortOrder order)
335 {
336     if (column != 0)
337         return;
338 
339     emit layoutAboutToBeChanged({}, 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(sorting.begin(), sorting.end(), compare);
350     QModelIndexList fromIndexes;
351     QModelIndexList toIndexes;
352     const int sortingCount = sorting.count();
353     fromIndexes.reserve(sortingCount);
354     toIndexes.reserve(sortingCount);
355     for (int r = 0; r < sortingCount; ++r) {
356         QListWidgetItem *item = sorting.at(r).first;
357         toIndexes.append(createIndex(r, 0, item));
358         fromIndexes.append(createIndex(sorting.at(r).second, 0, sorting.at(r).first));
359         items[r] = sorting.at(r).first;
360     }
361     changePersistentIndexList(fromIndexes, toIndexes);
362 
363     emit layoutChanged({}, 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  */
ensureSorted(int column,Qt::SortOrder order,int start,int end)373 void 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(start + i);
382         sorting[i].second = start + i;
383     }
384 
385     const auto compare = (order == Qt::AscendingOrder ? &itemLessThan : &itemGreaterThan);
386     std::sort(sorting.begin(), sorting.end(), 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(oldRow);
397         if (tmpitepos > tmp.size())
398             --tmpitepos;
399         lit = tmp.begin() + tmpitepos;
400         lit = sortedInsertionIterator(lit, tmp.end(), order, item);
401         int newRow = qMax(lit - tmp.begin(), 0);
402         lit = tmp.insert(lit, item);
403         if (newRow != oldRow) {
404             changed = true;
405             for (int j = i + 1; j < count; ++j) {
406                 int otherRow = sorting.at(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(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(newPersistentRow,
424                                                           pi.column(), pi.internalPointer());
425             }
426         }
427     }
428 
429     if (changed) {
430         emit layoutAboutToBeChanged();
431         items = tmp;
432         changePersistentIndexList(oldPersistentIndexes, newPersistentIndexes);
433         emit layoutChanged();
434     }
435 }
436 
itemLessThan(const QPair<QListWidgetItem *,int> & left,const QPair<QListWidgetItem *,int> & right)437 bool QListModel::itemLessThan(const QPair<QListWidgetItem*,int> &left,
438                               const QPair<QListWidgetItem*,int> &right)
439 {
440     return (*left.first) < (*right.first);
441 }
442 
itemGreaterThan(const QPair<QListWidgetItem *,int> & left,const QPair<QListWidgetItem *,int> & right)443 bool QListModel::itemGreaterThan(const QPair<QListWidgetItem*,int> &left,
444                                  const QPair<QListWidgetItem*,int> &right)
445 {
446     return (*right.first) < (*left.first);
447 }
448 
sortedInsertionIterator(const QList<QListWidgetItem * >::iterator & begin,const QList<QListWidgetItem * >::iterator & end,Qt::SortOrder order,QListWidgetItem * item)449 QList<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(begin, end, item, QListModelLessThan());
456     return std::lower_bound(begin, end, item, QListModelGreaterThan());
457 }
458 
itemChanged(QListWidgetItem * item,const QVector<int> & roles)459 void QListModel::itemChanged(QListWidgetItem *item, const QVector<int> &roles)
460 {
461     const QModelIndex idx = index(item);
462     emit dataChanged(idx, idx, roles);
463 }
464 
mimeTypes() const465 QStringList QListModel::mimeTypes() const
466 {
467     const QListWidget *view = qobject_cast<const QListWidget*>(QObject::parent());
468     if (view)
469         return view->mimeTypes();
470     return {};
471 }
472 
internalMimeData() const473 QMimeData *QListModel::internalMimeData()  const
474 {
475     return QAbstractItemModel::mimeData(cachedIndexes);
476 }
477 
mimeData(const QModelIndexList & indexes) const478 QMimeData *QListModel::mimeData(const QModelIndexList &indexes) const
479 {
480     QList<QListWidgetItem*> itemlist;
481     const int indexesCount = indexes.count();
482     itemlist.reserve(indexesCount);
483     for (int i = 0; i < indexesCount; ++i)
484         itemlist << at(indexes.at(i).row());
485     const QListWidget *view = qobject_cast<const QListWidget*>(QObject::parent());
486 
487     cachedIndexes = indexes;
488     QMimeData *mimeData = view->mimeData(itemlist);
489     cachedIndexes.clear();
490     return mimeData;
491 }
492 
493 #if QT_CONFIG(draganddrop)
dropMimeData(const QMimeData * data,Qt::DropAction action,int row,int column,const QModelIndex & index)494 bool 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*>(QObject::parent());
499     if (index.isValid())
500         row = index.row();
501     else if (row == -1)
502         row = items.count();
503 
504     return view->dropMimeData(row, data, action);
505 }
506 
supportedDropActions() const507 Qt::DropActions QListModel::supportedDropActions() const
508 {
509     const QListWidget *view = qobject_cast<const QListWidget*>(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 */
QListWidgetItem(QListWidget * listview,int type)628 QListWidgetItem::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(model->rowCount(), 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 */
QListWidgetItem(const QString & text,QListWidget * listview,int type)655 QListWidgetItem::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(Qt::DisplayRole, text);
667     }
668     if (model)
669         model->insert(model->rowCount(), 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 */
QListWidgetItem(const QIcon & icon,const QString & text,QListWidget * listview,int type)689 QListWidgetItem::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(Qt::DisplayRole, text);
702         setData(Qt::DecorationRole, icon);
703     }
704     if (model)
705         model->insert(model->rowCount(), this);
706 }
707 
708 /*!
709     Destroys the list item.
710 */
~QListWidgetItem()711 QListWidgetItem::~QListWidgetItem()
712 {
713     if (QListModel *model = listModel())
714         model->remove(this);
715     delete d;
716 }
717 
718 /*!
719     Creates an exact copy of the item.
720 */
clone() const721 QListWidgetItem *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 */
setData(int role,const QVariant & value)735 void 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(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(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 */
data(int role) const764 QVariant 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 */
operator <(const QListWidgetItem & other) const777 bool QListWidgetItem::operator<(const QListWidgetItem &other) const
778 {
779     const QVariant v1 = data(Qt::DisplayRole), v2 = other.data(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 */
read(QDataStream & in)790 void 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 */
write(QDataStream & out) const800 void 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 */
QListWidgetItem(const QListWidgetItem & other)816 QListWidgetItem::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 */
operator =(const QListWidgetItem & other)832 QListWidgetItem &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  */
listModel() const843 QListModel *QListWidgetItem::listModel() const
844 {
845     return (view ? qobject_cast<QListModel*>(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 */
operator <<(QDataStream & out,const QListWidgetItem & item)859 QDataStream &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 */
operator >>(QDataStream & in,QListWidgetItem & item)874 QDataStream &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 */
setSelected(bool select)1012 void 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(this);
1021     if (selectionMode == QAbstractItemView::SingleSelection)
1022         view->selectionModel()->select(index, select
1023                                        ? QItemSelectionModel::ClearAndSelect
1024                                        : QItemSelectionModel::Deselect);
1025     else
1026         view->selectionModel()->select(index, 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 */
isSelected() const1039 bool QListWidgetItem::isSelected() const
1040 {
1041     const QListModel *model = listModel();
1042     if (!model || !view->selectionModel())
1043         return false;
1044     const QModelIndex index = model->index(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 */
setFlags(Qt::ItemFlags aflags)1055 void QListWidgetItem::setFlags(Qt::ItemFlags aflags)
1056 {
1057     itemFlags = aflags;
1058     if (QListModel *model = listModel())
1059         model->itemChanged(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 
setup()1166 void QListWidgetPrivate::setup()
1167 {
1168     Q_Q(QListWidget);
1169     q->QListView::setModel(new QListModel(q));
1170     // view signals
1171     QObject::connect(q, SIGNAL(pressed(QModelIndex)), q, SLOT(_q_emitItemPressed(QModelIndex)));
1172     QObject::connect(q, SIGNAL(clicked(QModelIndex)), q, SLOT(_q_emitItemClicked(QModelIndex)));
1173     QObject::connect(q, SIGNAL(doubleClicked(QModelIndex)),
1174                      q, SLOT(_q_emitItemDoubleClicked(QModelIndex)));
1175     QObject::connect(q, SIGNAL(activated(QModelIndex)),
1176                      q, SLOT(_q_emitItemActivated(QModelIndex)));
1177     QObject::connect(q, SIGNAL(entered(QModelIndex)), q, SLOT(_q_emitItemEntered(QModelIndex)));
1178     QObject::connect(model, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
1179                      q, SLOT(_q_emitItemChanged(QModelIndex)));
1180     QObject::connect(model, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
1181                      q, SLOT(_q_dataChanged(QModelIndex,QModelIndex)));
1182     QObject::connect(model, SIGNAL(columnsRemoved(QModelIndex,int,int)), q, SLOT(_q_sort()));
1183 }
1184 
_q_emitItemPressed(const QModelIndex & index)1185 void QListWidgetPrivate::_q_emitItemPressed(const QModelIndex &index)
1186 {
1187     Q_Q(QListWidget);
1188     emit q->itemPressed(listModel()->at(index.row()));
1189 }
1190 
_q_emitItemClicked(const QModelIndex & index)1191 void QListWidgetPrivate::_q_emitItemClicked(const QModelIndex &index)
1192 {
1193     Q_Q(QListWidget);
1194     emit q->itemClicked(listModel()->at(index.row()));
1195 }
1196 
_q_emitItemDoubleClicked(const QModelIndex & index)1197 void QListWidgetPrivate::_q_emitItemDoubleClicked(const QModelIndex &index)
1198 {
1199     Q_Q(QListWidget);
1200     emit q->itemDoubleClicked(listModel()->at(index.row()));
1201 }
1202 
_q_emitItemActivated(const QModelIndex & index)1203 void QListWidgetPrivate::_q_emitItemActivated(const QModelIndex &index)
1204 {
1205     Q_Q(QListWidget);
1206     emit q->itemActivated(listModel()->at(index.row()));
1207 }
1208 
_q_emitItemEntered(const QModelIndex & index)1209 void QListWidgetPrivate::_q_emitItemEntered(const QModelIndex &index)
1210 {
1211     Q_Q(QListWidget);
1212     emit q->itemEntered(listModel()->at(index.row()));
1213 }
1214 
_q_emitItemChanged(const QModelIndex & index)1215 void QListWidgetPrivate::_q_emitItemChanged(const QModelIndex &index)
1216 {
1217     Q_Q(QListWidget);
1218     emit q->itemChanged(listModel()->at(index.row()));
1219 }
1220 
_q_emitCurrentItemChanged(const QModelIndex & current,const QModelIndex & previous)1221 void QListWidgetPrivate::_q_emitCurrentItemChanged(const QModelIndex &current,
1222                                                 const QModelIndex &previous)
1223 {
1224     Q_Q(QListWidget);
1225     QPersistentModelIndex persistentCurrent = current;
1226     QListWidgetItem *currentItem = listModel()->at(persistentCurrent.row());
1227     emit q->currentItemChanged(currentItem, listModel()->at(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(currentItem ? currentItem->text() : QString());
1236     emit q->currentRowChanged(persistentCurrent.row());
1237 }
1238 
_q_sort()1239 void QListWidgetPrivate::_q_sort()
1240 {
1241     if (sortingEnabled)
1242         model->sort(0, sortOrder);
1243 }
1244 
_q_dataChanged(const QModelIndex & topLeft,const QModelIndex & bottomRight)1245 void QListWidgetPrivate::_q_dataChanged(const QModelIndex &topLeft,
1246                                         const QModelIndex &bottomRight)
1247 {
1248     if (sortingEnabled && topLeft.isValid() && bottomRight.isValid())
1249         listModel()->ensureSorted(topLeft.column(), sortOrder,
1250                               topLeft.row(), 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 
QListWidget(QWidget * parent)1439 QListWidget::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 
~QListWidget()1450 QListWidget::~QListWidget()
1451 {
1452 }
1453 
1454 /*!
1455     \reimp
1456 */
1457 
setSelectionModel(QItemSelectionModel * selectionModel)1458 void QListWidget::setSelectionModel(QItemSelectionModel *selectionModel)
1459 {
1460     Q_D(QListWidget);
1461 
1462     if (d->selectionModel) {
1463         QObject::disconnect(d->selectionModel, SIGNAL(currentChanged(QModelIndex,QModelIndex)),
1464                             this, SLOT(_q_emitCurrentItemChanged(QModelIndex,QModelIndex)));
1465         QObject::disconnect(d->selectionModel, SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
1466                             this, SIGNAL(itemSelectionChanged()));
1467     }
1468 
1469     QListView::setSelectionModel(selectionModel);
1470 
1471     if (d->selectionModel) {
1472         QObject::connect(d->selectionModel, SIGNAL(currentChanged(QModelIndex,QModelIndex)),
1473                          this, SLOT(_q_emitCurrentItemChanged(QModelIndex,QModelIndex)));
1474         QObject::connect(d->selectionModel, SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
1475                          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 
item(int row) const1486 QListWidgetItem *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 
row(const QListWidgetItem * item) const1500 int QListWidget::row(const QListWidgetItem *item) const
1501 {
1502     Q_D(const QListWidget);
1503     return d->listModel()->index(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 
insertItem(int row,QListWidgetItem * item)1513 void 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 
insertItem(int row,const QString & label)1527 void QListWidget::insertItem(int row, const QString &label)
1528 {
1529     Q_D(QListWidget);
1530     d->listModel()->insert(row, 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 
insertItems(int row,const QStringList & labels)1540 void 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 
takeItem(int row)1556 QListWidgetItem *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 
count() const1569 int QListWidget::count() const
1570 {
1571     Q_D(const QListWidget);
1572     return d->model->rowCount();
1573 }
1574 
1575 /*!
1576     Returns the current item.
1577 */
currentItem() const1578 QListWidgetItem *QListWidget::currentItem() const
1579 {
1580     Q_D(const QListWidget);
1581     return d->listModel()->at(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 */
setCurrentItem(QListWidgetItem * item)1591 void 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 */
setCurrentItem(QListWidgetItem * item,QItemSelectionModel::SelectionFlags command)1600 void QListWidget::setCurrentItem(QListWidgetItem *item, QItemSelectionModel::SelectionFlags command)
1601 {
1602     setCurrentRow(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 
currentRow() const1612 int QListWidget::currentRow() const
1613 {
1614     return currentIndex().row();
1615 }
1616 
setCurrentRow(int row)1617 void 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, QItemSelectionModel::ClearAndSelect);
1623     else if (d->selectionMode == NoSelection)
1624         selectionModel()->setCurrentIndex(index, QItemSelectionModel::NoUpdate);
1625     else
1626         selectionModel()->setCurrentIndex(index, 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 */
setCurrentRow(int row,QItemSelectionModel::SelectionFlags command)1634 void QListWidget::setCurrentRow(int row, QItemSelectionModel::SelectionFlags command)
1635 {
1636     Q_D(QListWidget);
1637     d->selectionModel->setCurrentIndex(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 */
itemAt(const QPoint & p) const1645 QListWidgetItem *QListWidget::itemAt(const QPoint &p) const
1646 {
1647     Q_D(const QListWidget);
1648     return d->listModel()->at(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 */
visualItemRect(const QListWidgetItem * item) const1666 QRect QListWidget::visualItemRect(const QListWidgetItem *item) const
1667 {
1668     Q_D(const QListWidget);
1669     QModelIndex index = d->listModel()->index(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 */
sortItems(Qt::SortOrder order)1676 void QListWidget::sortItems(Qt::SortOrder order)
1677 {
1678     Q_D(QListWidget);
1679     d->sortOrder = order;
1680     d->listModel()->sort(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 */
setSortingEnabled(bool enable)1693 void QListWidget::setSortingEnabled(bool enable)
1694 {
1695     Q_D(QListWidget);
1696     d->sortingEnabled = enable;
1697 }
1698 
isSortingEnabled() const1699 bool QListWidget::isSortingEnabled() const
1700 {
1701     Q_D(const QListWidget);
1702     return d->sortingEnabled;
1703 }
1704 
1705 /*!
1706     \internal
1707 */
sortOrder() const1708 Qt::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 
editItem(QListWidgetItem * item)1718 void QListWidget::editItem(QListWidgetItem *item)
1719 {
1720     Q_D(QListWidget);
1721     edit(d->listModel()->index(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 */
openPersistentEditor(QListWidgetItem * item)1730 void QListWidget::openPersistentEditor(QListWidgetItem *item)
1731 {
1732     Q_D(QListWidget);
1733     QModelIndex index = d->listModel()->index(item);
1734     QAbstractItemView::openPersistentEditor(index);
1735 }
1736 
1737 /*!
1738     Closes the persistent editor for the given \a item.
1739 
1740     \sa openPersistentEditor(), isPersistentEditorOpen()
1741 */
closePersistentEditor(QListWidgetItem * item)1742 void QListWidget::closePersistentEditor(QListWidgetItem *item)
1743 {
1744     Q_D(QListWidget);
1745     QModelIndex index = d->listModel()->index(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 */
isPersistentEditorOpen(QListWidgetItem * item) const1756 bool QListWidget::isPersistentEditorOpen(QListWidgetItem *item) const
1757 {
1758     Q_D(const QListWidget);
1759     const QModelIndex index = d->listModel()->index(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 */
itemWidget(QListWidgetItem * item) const1770 QWidget *QListWidget::itemWidget(QListWidgetItem *item) const
1771 {
1772     Q_D(const QListWidget);
1773     QModelIndex index = d->listModel()->index(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 */
setItemWidget(QListWidgetItem * item,QWidget * widget)1789 void QListWidget::setItemWidget(QListWidgetItem *item, QWidget *widget)
1790 {
1791     Q_D(QListWidget);
1792     QModelIndex index = d->listModel()->index(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 */
isItemSelected(const QListWidgetItem * item) const1804 bool 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 */
setItemSelected(const QListWidgetItem * item,bool select)1817 void 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 
selectedItems() const1828 QList<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(numIndexes);
1835     for (int i = 0; i < numIndexes; ++i)
1836         items.append(d->listModel()->at(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 
findItems(const QString & text,Qt::MatchFlags flags) const1845 QList<QListWidgetItem*> QListWidget::findItems(const QString &text, Qt::MatchFlags flags) const
1846 {
1847     Q_D(const QListWidget);
1848     QModelIndexList indexes = d->listModel()->match(model()->index(0, 0, QModelIndex()),
1849                                                 Qt::DisplayRole, text, -1, flags);
1850     QList<QListWidgetItem*> items;
1851     const int indexesSize = indexes.size();
1852     items.reserve(indexesSize);
1853     for (int i = 0; i < indexesSize; ++i)
1854         items.append(d->listModel()->at(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 */
isItemHidden(const QListWidgetItem * item) const1866 bool QListWidget::isItemHidden(const QListWidgetItem *item) const
1867 {
1868     return isRowHidden(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 */
setItemHidden(const QListWidgetItem * item,bool hide)1878 void QListWidget::setItemHidden(const QListWidgetItem *item, bool hide)
1879 {
1880     setRowHidden(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 
scrollToItem(const QListWidgetItem * item,QAbstractItemView::ScrollHint hint)1890 void QListWidget::scrollToItem(const QListWidgetItem *item, QAbstractItemView::ScrollHint hint)
1891 {
1892     Q_D(QListWidget);
1893     QModelIndex index = d->listModel()->index(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 */
clear()1902 void 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 */
mimeTypes() const1915 QStringList 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)
mimeData(const QList<QListWidgetItem * > & items) const1929 QMimeData *QListWidget::mimeData(const QList<QListWidgetItem *> &items) const
1930 #else
1931 QMimeData *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(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 */
dropMimeData(int index,const QMimeData * data,Qt::DropAction action)1961 bool 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, idx);
1973 }
1974 
1975 /*! \reimp */
dropEvent(QDropEvent * event)1976 void QListWidget::dropEvent(QDropEvent *event)
1977 {
1978     QListView::dropEvent(event);
1979 }
1980 
1981 /*!
1982     Returns the drop actions supported by this view.
1983 
1984     \sa Qt::DropActions
1985 */
supportedDropActions() const1986 Qt::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 */
items(const QMimeData * data) const1998 QList<QListWidgetItem*> QListWidget::items(const QMimeData *data) const
1999 {
2000     const QListWidgetMimeData *lwd = qobject_cast<const QListWidgetMimeData*>(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 
indexFromItem(const QListWidgetItem * item) const2012 QModelIndex QListWidget::indexFromItem(const QListWidgetItem *item) const
2013 {
2014     Q_D(const QListWidget);
2015     return d->listModel()->index(item);
2016 }
2017 
2018 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
2019 /*!
2020     \internal
2021     \obsolete
2022     \overload
2023 */
indexFromItem(QListWidgetItem * item) const2024 QModelIndex QListWidget::indexFromItem(QListWidgetItem *item) const
2025 {
2026     return indexFromItem(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 
itemFromIndex(const QModelIndex & index) const2034 QListWidgetItem *QListWidget::itemFromIndex(const QModelIndex &index) const
2035 {
2036     Q_D(const QListWidget);
2037     if (d->isIndexValid(index))
2038         return d->listModel()->at(index.row());
2039     return nullptr;
2040 }
2041 
2042 /*!
2043     \internal
2044 */
setModel(QAbstractItemModel *)2045 void 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 */
event(QEvent * e)2053 bool QListWidget::event(QEvent *e)
2054 {
2055     return QListView::event(e);
2056 }
2057 
2058 QT_END_NAMESPACE
2059 
2060 #include "moc_qlistwidget.cpp"
2061 #include "moc_qlistwidget_p.cpp"
2062