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