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