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