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 "qtablewidget.h"
41 
42 #include <qitemdelegate.h>
43 #include <qpainter.h>
44 #include <private/qtablewidget_p.h>
45 
46 #include <algorithm>
47 
48 QT_BEGIN_NAMESPACE
49 
QTableModel(int rows,int columns,QTableWidget * parent)50 QTableModel::QTableModel(int rows, int columns, QTableWidget *parent)
51     : QAbstractTableModel(parent),
52       prototype(nullptr),
53       tableItems(rows * columns, 0),
54       verticalHeaderItems(rows, 0),
55       horizontalHeaderItems(columns, 0)
56 {}
57 
~QTableModel()58 QTableModel::~QTableModel()
59 {
60     clear();
61     delete prototype;
62 }
63 
insertRows(int row,int count,const QModelIndex &)64 bool QTableModel::insertRows(int row, int count, const QModelIndex &)
65 {
66     if (count < 1 || row < 0 || row > verticalHeaderItems.count())
67         return false;
68 
69     beginInsertRows(QModelIndex(), row, row + count - 1);
70     int rc = verticalHeaderItems.count();
71     int cc = horizontalHeaderItems.count();
72     verticalHeaderItems.insert(row, count, 0);
73     if (rc == 0)
74         tableItems.resize(cc * count);
75     else
76         tableItems.insert(tableIndex(row, 0), cc * count, 0);
77     endInsertRows();
78     return true;
79 }
80 
insertColumns(int column,int count,const QModelIndex &)81 bool QTableModel::insertColumns(int column, int count, const QModelIndex &)
82 {
83     if (count < 1 || column < 0 || column > horizontalHeaderItems.count())
84         return false;
85 
86     beginInsertColumns(QModelIndex(), column, column + count - 1);
87     int rc = verticalHeaderItems.count();
88     int cc = horizontalHeaderItems.count();
89     horizontalHeaderItems.insert(column, count, 0);
90     if (cc == 0)
91         tableItems.resize(rc * count);
92     else
93         for (int row = 0; row < rc; ++row)
94             tableItems.insert(tableIndex(row, column), count, 0);
95     endInsertColumns();
96     return true;
97 }
98 
removeRows(int row,int count,const QModelIndex &)99 bool QTableModel::removeRows(int row, int count, const QModelIndex &)
100 {
101     if (count < 1 || row < 0 || row + count > verticalHeaderItems.count())
102         return false;
103 
104     beginRemoveRows(QModelIndex(), row, row + count - 1);
105     int i = tableIndex(row, 0);
106     int n = count * columnCount();
107     QTableWidgetItem *oldItem = nullptr;
108     for (int j = i; j < n + i; ++j) {
109         oldItem = tableItems.at(j);
110         if (oldItem)
111             oldItem->view = nullptr;
112         delete oldItem;
113     }
114     tableItems.remove(qMax(i, 0), n);
115     for (int v = row; v < row + count; ++v) {
116         oldItem = verticalHeaderItems.at(v);
117         if (oldItem)
118             oldItem->view = nullptr;
119         delete oldItem;
120     }
121     verticalHeaderItems.remove(row, count);
122     endRemoveRows();
123     return true;
124 }
125 
removeColumns(int column,int count,const QModelIndex &)126 bool QTableModel::removeColumns(int column, int count, const QModelIndex &)
127 {
128     if (count < 1 || column < 0 || column + count >  horizontalHeaderItems.count())
129         return false;
130 
131     beginRemoveColumns(QModelIndex(), column, column + count - 1);
132     QTableWidgetItem *oldItem = nullptr;
133     for (int row = rowCount() - 1; row >= 0; --row) {
134         int i = tableIndex(row, column);
135         for (int j = i; j < i + count; ++j) {
136             oldItem = tableItems.at(j);
137             if (oldItem)
138                 oldItem->view = nullptr;
139             delete oldItem;
140         }
141         tableItems.remove(i, count);
142     }
143     for (int h=column; h<column+count; ++h) {
144         oldItem = horizontalHeaderItems.at(h);
145         if (oldItem)
146             oldItem->view = nullptr;
147         delete oldItem;
148     }
149     horizontalHeaderItems.remove(column, count);
150     endRemoveColumns();
151     return true;
152 }
153 
setItem(int row,int column,QTableWidgetItem * item)154 void QTableModel::setItem(int row, int column, QTableWidgetItem *item)
155 {
156     int i = tableIndex(row, column);
157     if (i < 0 || i >= tableItems.count())
158         return;
159     QTableWidgetItem *oldItem = tableItems.at(i);
160     if (item == oldItem)
161         return;
162 
163     // remove old
164     if (oldItem)
165         oldItem->view = nullptr;
166     delete tableItems.at(i);
167 
168     QTableWidget *view = qobject_cast<QTableWidget*>(QObject::parent());
169 
170     // set new
171     if (item)
172         item->d->id = i;
173     tableItems[i] = item;
174 
175     if (view && view->isSortingEnabled()
176         && view->horizontalHeader()->sortIndicatorSection() == column) {
177         // sorted insertion
178         Qt::SortOrder order = view->horizontalHeader()->sortIndicatorOrder();
179         QVector<QTableWidgetItem*> colItems = columnItems(column);
180         if (row < colItems.count())
181             colItems.remove(row);
182         int sortedRow;
183         if (item == nullptr) {
184             // move to after all non-0 (sortable) items
185             sortedRow = colItems.count();
186         } else {
187             QVector<QTableWidgetItem*>::iterator it;
188             it = sortedInsertionIterator(colItems.begin(), colItems.end(), order, item);
189             sortedRow = qMax((int)(it - colItems.begin()), 0);
190         }
191         if (sortedRow != row) {
192             emit layoutAboutToBeChanged({}, QAbstractItemModel::VerticalSortHint);
193             // move the items @ row to sortedRow
194             int cc = columnCount();
195             QVector<QTableWidgetItem*> rowItems(cc);
196             for (int j = 0; j < cc; ++j)
197                 rowItems[j] = tableItems.at(tableIndex(row, j));
198             tableItems.remove(tableIndex(row, 0), cc);
199             tableItems.insert(tableIndex(sortedRow, 0), cc, 0);
200             for (int j = 0; j < cc; ++j)
201                 tableItems[tableIndex(sortedRow, j)] = rowItems.at(j);
202             QTableWidgetItem *header = verticalHeaderItems.at(row);
203             verticalHeaderItems.remove(row);
204             verticalHeaderItems.insert(sortedRow, header);
205             // update persistent indexes
206             QModelIndexList oldPersistentIndexes = persistentIndexList();
207             QModelIndexList newPersistentIndexes = oldPersistentIndexes;
208             updateRowIndexes(newPersistentIndexes, row, sortedRow);
209             changePersistentIndexList(oldPersistentIndexes,
210                                       newPersistentIndexes);
211 
212             emit layoutChanged({}, QAbstractItemModel::VerticalSortHint);
213             return;
214         }
215     }
216     QModelIndex idx = QAbstractTableModel::index(row, column);
217     emit dataChanged(idx, idx);
218 }
219 
takeItem(int row,int column)220 QTableWidgetItem *QTableModel::takeItem(int row, int column)
221 {
222     long i = tableIndex(row, column);
223     QTableWidgetItem *itm = tableItems.value(i);
224     if (itm) {
225         itm->view = nullptr;
226         itm->d->id = -1;
227         tableItems[i] = 0;
228         const QModelIndex ind = index(row, column);
229         emit dataChanged(ind, ind);
230     }
231     return itm;
232 }
233 
item(int row,int column) const234 QTableWidgetItem *QTableModel::item(int row, int column) const
235 {
236     return item(index(row, column));
237 }
238 
item(const QModelIndex & index) const239 QTableWidgetItem *QTableModel::item(const QModelIndex &index) const
240 {
241     if (!isValid(index))
242         return nullptr;
243     return tableItems.at(tableIndex(index.row(), index.column()));
244 }
245 
removeItem(QTableWidgetItem * item)246 void QTableModel::removeItem(QTableWidgetItem *item)
247 {
248     int i = tableItems.indexOf(item);
249     if (i != -1) {
250         QModelIndex idx = index(item);
251         tableItems[i] = nullptr;
252         emit dataChanged(idx, idx);
253         return;
254     }
255 
256     i = verticalHeaderItems.indexOf(item);
257 
258     if (i != -1) {
259         verticalHeaderItems[i] = 0;
260         emit headerDataChanged(Qt::Vertical, i, i);
261         return;
262     }
263     i = horizontalHeaderItems.indexOf(item);
264     if (i != -1) {
265         horizontalHeaderItems[i] = 0;
266         emit headerDataChanged(Qt::Horizontal, i, i);
267         return;
268     }
269 }
270 
setHorizontalHeaderItem(int section,QTableWidgetItem * item)271 void QTableModel::setHorizontalHeaderItem(int section, QTableWidgetItem *item)
272 {
273     if (section < 0 || section >= horizontalHeaderItems.count())
274         return;
275     QTableWidgetItem *oldItem = horizontalHeaderItems.at(section);
276     if (item == oldItem)
277         return;
278 
279     if (oldItem)
280         oldItem->view = nullptr;
281     delete oldItem;
282 
283     QTableWidget *view = qobject_cast<QTableWidget*>(QObject::parent());
284 
285     if (item) {
286         item->view = view;
287         item->itemFlags = Qt::ItemFlags(int(item->itemFlags)|ItemIsHeaderItem);
288     }
289     horizontalHeaderItems[section] = item;
290     emit headerDataChanged(Qt::Horizontal, section, section);
291 }
292 
setVerticalHeaderItem(int section,QTableWidgetItem * item)293 void QTableModel::setVerticalHeaderItem(int section, QTableWidgetItem *item)
294 {
295     if (section < 0 || section >= verticalHeaderItems.count())
296         return;
297     QTableWidgetItem *oldItem = verticalHeaderItems.at(section);
298     if (item == oldItem)
299         return;
300 
301     if (oldItem)
302         oldItem->view = nullptr;
303     delete oldItem;
304 
305     QTableWidget *view = qobject_cast<QTableWidget*>(QObject::parent());
306 
307     if (item) {
308         item->view = view;
309         item->itemFlags = Qt::ItemFlags(int(item->itemFlags)|ItemIsHeaderItem);
310     }
311     verticalHeaderItems[section] = item;
312     emit headerDataChanged(Qt::Vertical, section, section);
313 }
314 
takeHorizontalHeaderItem(int section)315 QTableWidgetItem *QTableModel::takeHorizontalHeaderItem(int section)
316 {
317     if (section < 0 || section >= horizontalHeaderItems.count())
318         return nullptr;
319     QTableWidgetItem *itm = horizontalHeaderItems.at(section);
320     if (itm) {
321         itm->view = nullptr;
322         itm->itemFlags &= ~ItemIsHeaderItem;
323         horizontalHeaderItems[section] = 0;
324     }
325     return itm;
326 }
327 
takeVerticalHeaderItem(int section)328 QTableWidgetItem *QTableModel::takeVerticalHeaderItem(int section)
329 {
330     if (section < 0 || section >= verticalHeaderItems.count())
331         return nullptr;
332     QTableWidgetItem *itm = verticalHeaderItems.at(section);
333     if (itm) {
334         itm->view = nullptr;
335         itm->itemFlags &= ~ItemIsHeaderItem;
336         verticalHeaderItems[section] = 0;
337     }
338     return itm;
339 }
340 
horizontalHeaderItem(int section)341 QTableWidgetItem *QTableModel::horizontalHeaderItem(int section)
342 {
343     return horizontalHeaderItems.value(section);
344 }
345 
verticalHeaderItem(int section)346 QTableWidgetItem *QTableModel::verticalHeaderItem(int section)
347 {
348     return verticalHeaderItems.value(section);
349 }
350 
index(const QTableWidgetItem * item) const351 QModelIndex QTableModel::index(const QTableWidgetItem *item) const
352 {
353     if (!item)
354         return QModelIndex();
355     int i = -1;
356     const int id = item->d->id;
357     if (id >= 0 && id < tableItems.count() && tableItems.at(id) == item) {
358         i = id;
359     } else { // we need to search for the item
360         i = tableItems.indexOf(const_cast<QTableWidgetItem*>(item));
361         if (i == -1) // not found
362             return QModelIndex();
363     }
364     int row = i / columnCount();
365     int col = i % columnCount();
366     return QAbstractTableModel::index(row, col);
367 }
368 
setRowCount(int rows)369 void QTableModel::setRowCount(int rows)
370 {
371     int rc = verticalHeaderItems.count();
372     if (rows < 0 || rc == rows)
373         return;
374     if (rc < rows)
375         insertRows(qMax(rc, 0), rows - rc);
376     else
377         removeRows(qMax(rows, 0), rc - rows);
378 }
379 
setColumnCount(int columns)380 void QTableModel::setColumnCount(int columns)
381 {
382     int cc = horizontalHeaderItems.count();
383     if (columns < 0 || cc == columns)
384         return;
385     if (cc < columns)
386         insertColumns(qMax(cc, 0), columns - cc);
387     else
388         removeColumns(qMax(columns, 0), cc - columns);
389 }
390 
rowCount(const QModelIndex & parent) const391 int QTableModel::rowCount(const QModelIndex &parent) const
392 {
393     return parent.isValid() ? 0 : verticalHeaderItems.count();
394 }
395 
columnCount(const QModelIndex & parent) const396 int QTableModel::columnCount(const QModelIndex &parent) const
397 {
398     return parent.isValid() ? 0 : horizontalHeaderItems.count();
399 }
400 
data(const QModelIndex & index,int role) const401 QVariant QTableModel::data(const QModelIndex &index, int role) const
402 {
403     QTableWidgetItem *itm = item(index);
404     if (itm)
405         return itm->data(role);
406     return QVariant();
407 }
408 
setData(const QModelIndex & index,const QVariant & value,int role)409 bool QTableModel::setData(const QModelIndex &index, const QVariant &value, int role)
410 {
411     if (!index.isValid())
412         return false;
413 
414     QTableWidgetItem *itm = item(index);
415     if (itm) {
416         itm->setData(role, value);
417         return true;
418     }
419 
420     // don't create dummy table items for empty values
421     if (!value.isValid())
422         return false;
423 
424     QTableWidget *view = qobject_cast<QTableWidget*>(QObject::parent());
425     if (!view)
426         return false;
427 
428     itm = createItem();
429     itm->setData(role, value);
430     view->setItem(index.row(), index.column(), itm);
431     return true;
432 }
433 
itemData(const QModelIndex & index) const434 QMap<int, QVariant> QTableModel::itemData(const QModelIndex &index) const
435 {
436     QMap<int, QVariant> roles;
437     QTableWidgetItem *itm = item(index);
438     if (itm) {
439         for (int i = 0; i < itm->values.count(); ++i) {
440             roles.insert(itm->values.at(i).role,
441                          itm->values.at(i).value);
442         }
443     }
444     return roles;
445 }
446 
447 // reimplemented to ensure that only one dataChanged() signal is emitted
setItemData(const QModelIndex & index,const QMap<int,QVariant> & roles)448 bool QTableModel::setItemData(const QModelIndex &index, const QMap<int, QVariant> &roles)
449 {
450     if (!index.isValid())
451         return false;
452 
453     QTableWidget *view = qobject_cast<QTableWidget*>(QObject::parent());
454     QTableWidgetItem *itm = item(index);
455     if (itm) {
456         itm->view = nullptr; // prohibits item from calling itemChanged()
457         QVector<int> rolesVec;
458         for (QMap<int, QVariant>::ConstIterator it = roles.constBegin(); it != roles.constEnd(); ++it) {
459             const int role = (it.key() == Qt::EditRole ? Qt::DisplayRole : it.key());
460             if (itm->data(role) != it.value()) {
461                 itm->setData(role, it.value());
462                 rolesVec += role;
463                 if (role == Qt::DisplayRole)
464                     rolesVec += Qt::EditRole;
465             }
466         }
467         itm->view = view;
468         if (!rolesVec.isEmpty())
469             itemChanged(itm, rolesVec);
470         return true;
471     }
472 
473     if (!view)
474         return false;
475 
476     itm = createItem();
477     for (QMap<int, QVariant>::ConstIterator it = roles.constBegin(); it != roles.constEnd(); ++it)
478         itm->setData(it.key(), it.value());
479     view->setItem(index.row(), index.column(), itm);
480     return true;
481 }
482 
483 #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
clearItemData(const QModelIndex & index)484 bool QTableModel::clearItemData(const QModelIndex &index)
485 {
486     if (!checkIndex(index, CheckIndexOption::IndexIsValid))
487         return false;
488     QTableWidgetItem *itm = item(index);
489     if (!itm)
490         return false;
491     const auto beginIter = itm->values.cbegin();
492     const auto endIter = itm->values.cend();
493     if (std::all_of(beginIter, endIter, [](const QWidgetItemData& data) -> bool { return !data.value.isValid(); }))
494         return true; //it's already cleared
495     itm->values.clear();
496     emit dataChanged(index, index, QVector<int>{});
497     return true;
498 }
499 #endif
500 
flags(const QModelIndex & index) const501 Qt::ItemFlags QTableModel::flags(const QModelIndex &index) const
502 {
503     if (!index.isValid())
504         return Qt::ItemIsDropEnabled;
505     if (QTableWidgetItem *itm = item(index))
506         return itm->flags();
507     return (Qt::ItemIsEditable
508             |Qt::ItemIsSelectable
509             |Qt::ItemIsUserCheckable
510             |Qt::ItemIsEnabled
511             |Qt::ItemIsDragEnabled
512             |Qt::ItemIsDropEnabled);
513 }
514 
sort(int column,Qt::SortOrder order)515 void QTableModel::sort(int column, Qt::SortOrder order)
516 {
517     QVector<QPair<QTableWidgetItem*, int> > sortable;
518     QVector<int> unsortable;
519 
520     sortable.reserve(rowCount());
521     unsortable.reserve(rowCount());
522 
523     for (int row = 0; row < rowCount(); ++row) {
524         if (QTableWidgetItem *itm = item(row, column))
525             sortable.append(QPair<QTableWidgetItem*,int>(itm, row));
526         else
527             unsortable.append(row);
528     }
529 
530     const auto compare = (order == Qt::AscendingOrder ? &itemLessThan : &itemGreaterThan);
531     std::stable_sort(sortable.begin(), sortable.end(), compare);
532 
533     QVector<QTableWidgetItem*> sorted_table(tableItems.count());
534     QModelIndexList from;
535     QModelIndexList to;
536     const int numRows = rowCount();
537     const int numColumns = columnCount();
538     from.reserve(numRows * numColumns);
539     to.reserve(numRows * numColumns);
540     for (int i = 0; i < numRows; ++i) {
541         int r = (i < sortable.count()
542                  ? sortable.at(i).second
543                  : unsortable.at(i - sortable.count()));
544         for (int c = 0; c < numColumns; ++c) {
545             sorted_table[tableIndex(i, c)] = item(r, c);
546             from.append(createIndex(r, c));
547             to.append(createIndex(i, c));
548         }
549     }
550 
551     emit layoutAboutToBeChanged({}, QAbstractItemModel::VerticalSortHint);
552 
553     tableItems = sorted_table;
554     changePersistentIndexList(from, to); // ### slow
555 
556     emit layoutChanged({}, QAbstractItemModel::VerticalSortHint);
557 }
558 
559 /*
560   \internal
561 
562   Ensures that rows in the interval [start, end] are
563   sorted according to the contents of column \a column
564   and the given sort \a order.
565 */
ensureSorted(int column,Qt::SortOrder order,int start,int end)566 void QTableModel::ensureSorted(int column, Qt::SortOrder order,
567                                int start, int end)
568 {
569     int count = end - start + 1;
570     QVector < QPair<QTableWidgetItem*,int> > sorting;
571     sorting.reserve(count);
572     for (int row = start; row <= end; ++row) {
573         QTableWidgetItem *itm = item(row, column);
574         if (itm == nullptr) {
575             // no more sortable items (all 0-items are
576             // at the end of the table when it is sorted)
577             break;
578         }
579         sorting.append(QPair<QTableWidgetItem*,int>(itm, row));
580     }
581 
582     const auto compare = (order == Qt::AscendingOrder ? &itemLessThan : &itemGreaterThan);
583     std::stable_sort(sorting.begin(), sorting.end(), compare);
584     QModelIndexList oldPersistentIndexes, newPersistentIndexes;
585     QVector<QTableWidgetItem*> newTable = tableItems;
586     QVector<QTableWidgetItem*> newVertical = verticalHeaderItems;
587     QVector<QTableWidgetItem*> colItems = columnItems(column);
588     QVector<QTableWidgetItem*>::iterator vit = colItems.begin();
589     bool changed = false;
590     for (int i = 0; i < sorting.count(); ++i) {
591         int oldRow = sorting.at(i).second;
592         QTableWidgetItem *item = colItems.at(oldRow);
593         colItems.remove(oldRow);
594         vit = sortedInsertionIterator(vit, colItems.end(), order, item);
595         int newRow = qMax((int)(vit - colItems.begin()), 0);
596         if ((newRow < oldRow) && !(*item < *colItems.at(oldRow - 1)) && !(*colItems.at(oldRow - 1) < *item))
597             newRow = oldRow;
598         vit = colItems.insert(vit, item);
599         if (newRow != oldRow) {
600             if (!changed) {
601                 emit layoutAboutToBeChanged({}, QAbstractItemModel::VerticalSortHint);
602                 oldPersistentIndexes = persistentIndexList();
603                 newPersistentIndexes = oldPersistentIndexes;
604                 changed = true;
605             }
606             // move the items @ oldRow to newRow
607             int cc = columnCount();
608             QVector<QTableWidgetItem*> rowItems(cc);
609             for (int j = 0; j < cc; ++j)
610                 rowItems[j] = newTable.at(tableIndex(oldRow, j));
611             newTable.remove(tableIndex(oldRow, 0), cc);
612             newTable.insert(tableIndex(newRow, 0), cc, 0);
613             for (int j = 0; j < cc; ++j)
614                 newTable[tableIndex(newRow, j)] = rowItems.at(j);
615             QTableWidgetItem *header = newVertical.at(oldRow);
616             newVertical.remove(oldRow);
617             newVertical.insert(newRow, header);
618             // update persistent indexes
619             updateRowIndexes(newPersistentIndexes, oldRow, newRow);
620             // the index of the remaining rows may have changed
621             for (int j = i + 1; j < sorting.count(); ++j) {
622                 int otherRow = sorting.at(j).second;
623                 if (oldRow < otherRow && newRow >= otherRow)
624                     --sorting[j].second;
625                 else if (oldRow > otherRow && newRow <= otherRow)
626                     ++sorting[j].second;
627             }
628         }
629     }
630 
631     if (changed) {
632         tableItems = newTable;
633         verticalHeaderItems = newVertical;
634         changePersistentIndexList(oldPersistentIndexes,
635                                   newPersistentIndexes);
636         emit layoutChanged({}, QAbstractItemModel::VerticalSortHint);
637     }
638 }
639 
640 /*
641   \internal
642 
643   Returns the non-0 items in column \a column.
644 */
columnItems(int column) const645 QVector<QTableWidgetItem*> QTableModel::columnItems(int column) const
646 {
647     QVector<QTableWidgetItem*> items;
648     int rc = rowCount();
649     items.reserve(rc);
650     for (int row = 0; row < rc; ++row) {
651         QTableWidgetItem *itm = item(row, column);
652         if (itm == nullptr) {
653             // no more sortable items (all 0-items are
654             // at the end of the table when it is sorted)
655             break;
656         }
657         items.append(itm);
658     }
659     return items;
660 }
661 
662 /*
663   \internal
664 
665   Adjusts the row of each index in \a indexes if necessary, given
666   that a row of items has been moved from row \a movedFrom to row
667   \a movedTo.
668 */
updateRowIndexes(QModelIndexList & indexes,int movedFromRow,int movedToRow)669 void QTableModel::updateRowIndexes(QModelIndexList &indexes,
670                                    int movedFromRow, int movedToRow)
671 {
672     QModelIndexList::iterator it;
673     for (it = indexes.begin(); it != indexes.end(); ++it) {
674         int oldRow = (*it).row();
675         int newRow = oldRow;
676         if (oldRow == movedFromRow)
677             newRow = movedToRow;
678         else if (movedFromRow < oldRow && movedToRow >= oldRow)
679             newRow = oldRow - 1;
680         else if (movedFromRow > oldRow && movedToRow <= oldRow)
681             newRow = oldRow + 1;
682         if (newRow != oldRow)
683             *it = index(newRow, (*it).column(), (*it).parent());
684     }
685 }
686 
687 /*
688   \internal
689 
690   Returns an iterator to the item where \a item should be
691   inserted in the interval (\a begin, \a end) according to
692   the given sort \a order.
693 */
sortedInsertionIterator(const QVector<QTableWidgetItem * >::iterator & begin,const QVector<QTableWidgetItem * >::iterator & end,Qt::SortOrder order,QTableWidgetItem * item)694 QVector<QTableWidgetItem*>::iterator QTableModel::sortedInsertionIterator(
695     const QVector<QTableWidgetItem*>::iterator &begin,
696     const QVector<QTableWidgetItem*>::iterator &end,
697     Qt::SortOrder order, QTableWidgetItem *item)
698 {
699     if (order == Qt::AscendingOrder)
700         return std::lower_bound(begin, end, item, QTableModelLessThan());
701     return std::lower_bound(begin, end, item, QTableModelGreaterThan());
702 }
703 
itemLessThan(const QPair<QTableWidgetItem *,int> & left,const QPair<QTableWidgetItem *,int> & right)704 bool QTableModel::itemLessThan(const QPair<QTableWidgetItem*,int> &left,
705                                const QPair<QTableWidgetItem*,int> &right)
706 {
707     return *(left.first) < *(right.first);
708 }
709 
itemGreaterThan(const QPair<QTableWidgetItem *,int> & left,const QPair<QTableWidgetItem *,int> & right)710 bool QTableModel::itemGreaterThan(const QPair<QTableWidgetItem*,int> &left,
711                                   const QPair<QTableWidgetItem*,int> &right)
712 {
713     return (*(right.first) < *(left .first));
714 }
715 
headerData(int section,Qt::Orientation orientation,int role) const716 QVariant QTableModel::headerData(int section, Qt::Orientation orientation, int role) const
717 {
718     if (section < 0)
719         return QVariant();
720 
721     QTableWidgetItem *itm = nullptr;
722     if (orientation == Qt::Horizontal && section < horizontalHeaderItems.count())
723         itm = horizontalHeaderItems.at(section);
724     else if (orientation == Qt::Vertical && section < verticalHeaderItems.count())
725         itm = verticalHeaderItems.at(section);
726     else
727         return QVariant(); // section is out of bounds
728 
729     if (itm)
730         return itm->data(role);
731     if (role == Qt::DisplayRole)
732         return section + 1;
733     return QVariant();
734 }
735 
setHeaderData(int section,Qt::Orientation orientation,const QVariant & value,int role)736 bool QTableModel::setHeaderData(int section, Qt::Orientation orientation,
737                                 const QVariant &value, int role)
738 {
739     if (section < 0 ||
740        (orientation == Qt::Horizontal && horizontalHeaderItems.size() <= section) ||
741        (orientation == Qt::Vertical && verticalHeaderItems.size() <= section))
742     return false;
743 
744     QTableWidgetItem *itm = nullptr;
745     if (orientation == Qt::Horizontal)
746         itm = horizontalHeaderItems.at(section);
747     else
748         itm = verticalHeaderItems.at(section);
749     if (itm) {
750         itm->setData(role, value);
751         return true;
752     }
753     return false;
754 }
755 
isValid(const QModelIndex & index) const756 bool QTableModel::isValid(const QModelIndex &index) const
757 {
758     return (index.isValid()
759             && index.row() < verticalHeaderItems.count()
760             && index.column() < horizontalHeaderItems.count());
761 }
762 
clear()763 void QTableModel::clear()
764 {
765     for (int j = 0; j < verticalHeaderItems.count(); ++j) {
766         if (verticalHeaderItems.at(j)) {
767             verticalHeaderItems.at(j)->view = nullptr;
768             delete verticalHeaderItems.at(j);
769             verticalHeaderItems[j] = 0;
770         }
771     }
772     for (int k = 0; k < horizontalHeaderItems.count(); ++k) {
773         if (horizontalHeaderItems.at(k)) {
774             horizontalHeaderItems.at(k)->view = nullptr;
775             delete horizontalHeaderItems.at(k);
776             horizontalHeaderItems[k] = 0;
777         }
778     }
779     clearContents();
780 }
781 
clearContents()782 void QTableModel::clearContents()
783 {
784     beginResetModel();
785     for (int i = 0; i < tableItems.count(); ++i) {
786         if (tableItems.at(i)) {
787             tableItems.at(i)->view = nullptr;
788             delete tableItems.at(i);
789             tableItems[i] = 0;
790         }
791     }
792     endResetModel();
793 }
794 
itemChanged(QTableWidgetItem * item,const QVector<int> & roles)795 void QTableModel::itemChanged(QTableWidgetItem *item, const QVector<int> &roles)
796 {
797     if (!item)
798         return;
799     if (item->flags() & ItemIsHeaderItem) {
800         int row = verticalHeaderItems.indexOf(item);
801         if (row >= 0) {
802             emit headerDataChanged(Qt::Vertical, row, row);
803         } else {
804             int column = horizontalHeaderItems.indexOf(item);
805             if (column >= 0)
806                 emit headerDataChanged(Qt::Horizontal, column, column);
807         }
808     } else {
809         QModelIndex idx = index(item);
810         if (idx.isValid())
811             emit dataChanged(idx, idx, roles);
812     }
813 }
814 
createItem() const815 QTableWidgetItem* QTableModel::createItem() const
816 {
817     return prototype ? prototype->clone() : new QTableWidgetItem;
818 }
819 
itemPrototype() const820 const QTableWidgetItem *QTableModel::itemPrototype() const
821 {
822     return prototype;
823 }
824 
setItemPrototype(const QTableWidgetItem * item)825 void QTableModel::setItemPrototype(const QTableWidgetItem *item)
826 {
827     if (prototype != item) {
828         delete prototype;
829         prototype = item;
830     }
831 }
832 
mimeTypes() const833 QStringList QTableModel::mimeTypes() const
834 {
835     const QTableWidget *view = qobject_cast<const QTableWidget*>(QObject::parent());
836     return (view ? view->mimeTypes() : QStringList());
837 }
838 
internalMimeData() const839 QMimeData *QTableModel::internalMimeData()  const
840 {
841     return QAbstractTableModel::mimeData(cachedIndexes);
842 }
843 
mimeData(const QModelIndexList & indexes) const844 QMimeData *QTableModel::mimeData(const QModelIndexList &indexes) const
845 {
846     QList<QTableWidgetItem*> items;
847     const int indexesCount = indexes.count();
848     items.reserve(indexesCount);
849     for (int i = 0; i < indexesCount; ++i)
850         items << item(indexes.at(i));
851     const QTableWidget *view = qobject_cast<const QTableWidget*>(QObject::parent());
852 
853     // cachedIndexes is a little hack to avoid copying from QModelIndexList to
854     // QList<QTreeWidgetItem*> and back again in the view
855     cachedIndexes = indexes;
856     QMimeData *mimeData = (view ? view->mimeData(items) : nullptr);
857     cachedIndexes.clear();
858     return mimeData;
859 }
860 
dropMimeData(const QMimeData * data,Qt::DropAction action,int row,int column,const QModelIndex & index)861 bool QTableModel::dropMimeData(const QMimeData *data, Qt::DropAction action,
862                               int row , int column, const QModelIndex &index)
863 {
864     if (index.isValid()) {
865         row = index.row();
866         column = index.column();
867     }else if (row == -1 || column == -1) {  // The user dropped outside the table.
868         row = rowCount();
869         column = 0;
870     }
871 
872     QTableWidget *view = qobject_cast<QTableWidget*>(QObject::parent());
873     return (view ? view->dropMimeData(row, column, data, action) : false);
874 }
875 
supportedDropActions() const876 Qt::DropActions QTableModel::supportedDropActions() const
877 {
878     const QTableWidget *view = qobject_cast<const QTableWidget*>(QObject::parent());
879     return (view ? view->supportedDropActions() : Qt::DropActions(Qt::IgnoreAction));
880 }
881 
882 /*!
883     \class QTableWidgetSelectionRange
884 
885     \brief The QTableWidgetSelectionRange class provides a way to interact with
886     selection in a model without using model indexes and a selection model.
887 
888     \ingroup model-view
889     \inmodule QtWidgets
890 
891     The QTableWidgetSelectionRange class stores the top left and bottom
892     right rows and columns of a selection range in a table. The
893     selections in the table may consist of several selection ranges.
894 
895     \note If the item within the selection range is marked as not selectable,
896     e.g., \c{itemFlags() & Qt::ItemIsSelectable == 0} then it will not appear
897     in the selection range.
898 
899     \sa QTableWidget
900 */
901 
902 /*!
903     Constructs an table selection range, i.e. a range
904     whose rowCount() and columnCount() are 0.
905 */
QTableWidgetSelectionRange()906 QTableWidgetSelectionRange::QTableWidgetSelectionRange()
907     : top(-1), left(-1), bottom(-2), right(-2)
908 {
909 }
910 
911 /*!
912     Constructs the table selection range from the given \a top, \a
913     left, \a bottom and \a right table rows and columns.
914 
915     \sa topRow(), leftColumn(), bottomRow(), rightColumn()
916 */
QTableWidgetSelectionRange(int top,int left,int bottom,int right)917 QTableWidgetSelectionRange::QTableWidgetSelectionRange(int top, int left, int bottom, int right)
918     : top(top), left(left), bottom(bottom), right(right)
919 {
920 }
921 
922 /*!
923     Constructs a the table selection range by copying the given \a
924     other table selection range.
925 */
926 QTableWidgetSelectionRange::QTableWidgetSelectionRange(const QTableWidgetSelectionRange &) = default;
927 QTableWidgetSelectionRange &QTableWidgetSelectionRange::operator=(const QTableWidgetSelectionRange &) = default;
928 
929 /*!
930     Destroys the table selection range.
931 */
~QTableWidgetSelectionRange()932 QTableWidgetSelectionRange::~QTableWidgetSelectionRange()
933 {
934 }
935 
936 /*!
937     \fn int QTableWidgetSelectionRange::topRow() const
938 
939     Returns the top row of the range.
940 
941     \sa bottomRow(), leftColumn(), rowCount()
942 */
943 
944 /*!
945     \fn int QTableWidgetSelectionRange::bottomRow() const
946 
947     Returns the bottom row of the range.
948 
949     \sa topRow(), rightColumn(), rowCount()
950 */
951 
952 /*!
953     \fn int QTableWidgetSelectionRange::leftColumn() const
954 
955     Returns the left column of the range.
956 
957     \sa rightColumn(), topRow(), columnCount()
958 */
959 
960 /*!
961     \fn int QTableWidgetSelectionRange::rightColumn() const
962 
963     Returns the right column of the range.
964 
965     \sa leftColumn(), bottomRow(), columnCount()
966 */
967 
968 /*!
969     \since 4.1
970     \fn int QTableWidgetSelectionRange::rowCount() const
971 
972     Returns the number of rows in the range.
973 
974     This is equivalent to bottomRow() - topRow() + 1.
975 
976     \sa columnCount(), topRow(), bottomRow()
977 */
978 
979 /*!
980     \since 4.1
981     \fn int QTableWidgetSelectionRange::columnCount() const
982 
983     Returns the number of columns in the range.
984 
985     This is equivalent to rightColumn() - leftColumn() + 1.
986 
987     \sa rowCount(), leftColumn(), rightColumn()
988 */
989 
990 /*!
991     \class QTableWidgetItem
992     \brief The QTableWidgetItem class provides an item for use with the
993     QTableWidget class.
994 
995     \ingroup model-view
996     \inmodule QtWidgets
997 
998     Table items are used to hold pieces of information for table widgets.
999     Items usually contain text, icons, or checkboxes
1000 
1001     The QTableWidgetItem class is a convenience class that replaces the
1002     \c QTableItem class in Qt 3. It provides an item for use with
1003     the QTableWidget class.
1004 
1005     Top-level items are constructed without a parent then inserted at the
1006     position specified by a pair of row and column numbers:
1007 
1008     \snippet qtablewidget-using/mainwindow.cpp 3
1009 
1010     Each item can have its own background brush which is set with
1011     the setBackground() function. The current background brush can be
1012     found with background().
1013     The text label for each item can be rendered with its own font and brush.
1014     These are specified with the setFont() and setForeground() functions,
1015     and read with font() and foreground().
1016 
1017     By default, items are enabled, editable, selectable, checkable, and can be
1018     used both as the source of a drag and drop operation and as a drop target.
1019     Each item's flags can be changed by calling setFlags() with the appropriate
1020     value (see \l{Qt::ItemFlags}). Checkable items can be checked and unchecked
1021     with the setCheckState() function. The corresponding checkState() function
1022     indicates whether the item is currently checked.
1023 
1024     \section1 Subclassing
1025 
1026     When subclassing QTableWidgetItem to provide custom items, it is possible to
1027     define new types for them so that they can be distinguished from standard
1028     items. The constructors for subclasses that require this feature need to
1029     call the base class constructor with a new type value equal to or greater
1030     than \l UserType.
1031 
1032     \sa QTableWidget, {Model/View Programming}, QListWidgetItem, QTreeWidgetItem
1033 */
1034 
1035 /*!
1036   \fn int QTableWidgetItem::row() const
1037   \since 4.2
1038 
1039   Returns the row of the item in the table.
1040   If the item is not in a table, this function will return -1.
1041 
1042   \sa column()
1043 */
1044 
1045 /*!
1046   \fn int QTableWidgetItem::column() const
1047   \since 4.2
1048 
1049   Returns the column of the item in the table.
1050   If the item is not in a table, this function will return -1.
1051 
1052   \sa row()
1053 */
1054 
1055 /*!
1056   \fn QSize QTableWidgetItem::sizeHint() const
1057   \since 4.1
1058 
1059   Returns the size hint set for the table item.
1060 */
1061 
1062 /*!
1063   \fn void QTableWidgetItem::setSizeHint(const QSize &size)
1064   \since 4.1
1065 
1066   Sets the size hint for the table item to be \a size.
1067   If no size hint is set or \a size is invalid, the item
1068   delegate will compute the size hint based on the item data.
1069 */
1070 
1071 /*!
1072     \fn Qt::CheckState QTableWidgetItem::checkState() const
1073 
1074     Returns the checked state of the table item.
1075 
1076     \sa flags()
1077 */
1078 
1079 /*!
1080     \fn void QTableWidgetItem::setCheckState(Qt::CheckState state)
1081 
1082     Sets the check state of the table item to be \a state.
1083 */
1084 
1085 /*!
1086     \fn QTableWidget *QTableWidgetItem::tableWidget() const
1087 
1088     Returns the table widget that contains the item.
1089 */
1090 
1091 /*!
1092   \fn bool QTableWidgetItem::isSelected() const
1093   \since 4.2
1094 
1095   Returns \c true if the item is selected, otherwise returns \c false.
1096 
1097   \sa setSelected()
1098 */
isSelected() const1099 bool QTableWidgetItem::isSelected() const
1100 {
1101     if (!view || !view->selectionModel())
1102         return false;
1103     const QTableModel *model = qobject_cast<const QTableModel*>(view->model());
1104     if (!model)
1105         return false;
1106     const QModelIndex index = model->index(this);
1107     return view->selectionModel()->isSelected(index);
1108 }
1109 
1110 /*!
1111   \fn void QTableWidgetItem::setSelected(bool select)
1112   \since 4.2
1113 
1114   Sets the selected state of the item to \a select.
1115 
1116   \sa isSelected()
1117 */
setSelected(bool select)1118 void QTableWidgetItem::setSelected(bool select)
1119 {
1120     if (!view || !view->selectionModel())
1121         return;
1122     const QTableModel *model = qobject_cast<const QTableModel*>(view->model());
1123     if (!model)
1124         return;
1125     const QModelIndex index = model->index(this);
1126     view->selectionModel()->select(index, select ? QItemSelectionModel::Select : QItemSelectionModel::Deselect);
1127 }
1128 
1129 /*!
1130     \fn Qt::ItemFlags QTableWidgetItem::flags() const
1131 
1132     Returns the flags used to describe the item. These determine whether
1133     the item can be checked, edited, and selected.
1134 
1135     \sa setFlags()
1136 */
1137 
1138 /*!
1139     \fn void QTableWidgetItem::setFlags(Qt::ItemFlags flags)
1140 
1141     Sets the flags for the item to the given \a flags. These determine whether
1142     the item can be selected or modified.
1143 
1144     \sa flags()
1145 */
setFlags(Qt::ItemFlags aflags)1146 void QTableWidgetItem::setFlags(Qt::ItemFlags aflags)
1147 {
1148     itemFlags = aflags;
1149     if (QTableModel *model = tableModel())
1150         model->itemChanged(this);
1151 }
1152 
1153 
1154 /*!
1155     \fn QString QTableWidgetItem::text() const
1156 
1157     Returns the item's text.
1158 
1159     \sa setText()
1160 */
1161 
1162 /*!
1163     \fn void QTableWidgetItem::setText(const QString &text)
1164 
1165     Sets the item's text to the \a text specified.
1166 
1167     \sa text(), setFont(), setForeground()
1168 */
1169 
1170 /*!
1171     \fn QIcon QTableWidgetItem::icon() const
1172 
1173     Returns the item's icon.
1174 
1175     \sa setIcon(), {QAbstractItemView::iconSize}{iconSize}
1176 */
1177 
1178 /*!
1179     \fn void QTableWidgetItem::setIcon(const QIcon &icon)
1180 
1181     Sets the item's icon to the \a icon specified.
1182 
1183     \sa icon(), setText(), {QAbstractItemView::iconSize}{iconSize}
1184 */
1185 
1186 /*!
1187     \fn QString QTableWidgetItem::statusTip() const
1188 
1189     Returns the item's status tip.
1190 
1191     \sa setStatusTip()
1192 */
1193 
1194 /*!
1195     \fn void QTableWidgetItem::setStatusTip(const QString &statusTip)
1196 
1197     Sets the status tip for the table item to the text specified by
1198     \a statusTip. QTableWidget mouse tracking needs to be enabled for this
1199     feature to work.
1200 
1201     \sa statusTip(), setToolTip(), setWhatsThis()
1202 */
1203 
1204 /*!
1205     \fn QString QTableWidgetItem::toolTip() const
1206 
1207     Returns the item's tooltip.
1208 
1209     \sa setToolTip()
1210 */
1211 
1212 /*!
1213     \fn void QTableWidgetItem::setToolTip(const QString &toolTip)
1214 
1215     Sets the item's tooltip to the string specified by \a toolTip.
1216 
1217     \sa toolTip(), setStatusTip(), setWhatsThis()
1218 */
1219 
1220 /*!
1221     \fn QString QTableWidgetItem::whatsThis() const
1222 
1223     Returns the item's "What's This?" help.
1224 
1225     \sa setWhatsThis()
1226 */
1227 
1228 /*!
1229     \fn void QTableWidgetItem::setWhatsThis(const QString &whatsThis)
1230 
1231     Sets the item's "What's This?" help to the string specified by \a whatsThis.
1232 
1233     \sa whatsThis(), setStatusTip(), setToolTip()
1234 */
1235 
1236 /*!
1237     \fn QFont QTableWidgetItem::font() const
1238 
1239     Returns the font used to render the item's text.
1240 
1241     \sa setFont()
1242 */
1243 
1244 /*!
1245     \fn void QTableWidgetItem::setFont(const QFont &font)
1246 
1247     Sets the font used to display the item's text to the given \a font.
1248 
1249     \sa font(), setText(), setForeground()
1250 */
1251 
1252 #if QT_DEPRECATED_SINCE(5, 13)
1253 /*!
1254     \fn QColor QTableWidgetItem::backgroundColor() const
1255     \obsolete
1256 
1257     This function is deprecated. Use background() instead.
1258 */
1259 
1260 /*!
1261     \fn void QTableWidgetItem::setBackgroundColor(const QColor &color)
1262     \obsolete
1263 
1264     This function is deprecated. Use setBackground() instead.
1265 */
1266 #endif
1267 
1268 /*!
1269     \fn QBrush QTableWidgetItem::background() const
1270     \since 4.2
1271 
1272     Returns the brush used to render the item's background.
1273 
1274     \sa foreground()
1275 */
1276 
1277 /*!
1278     \fn void QTableWidgetItem::setBackground(const QBrush &brush)
1279     \since 4.2
1280 
1281     Sets the item's background brush to the specified \a brush.
1282     Setting a default-constructed brush will let the view use the
1283     default color from the style.
1284 
1285     \sa setForeground()
1286 */
1287 
1288 #if QT_DEPRECATED_SINCE(5, 13)
1289 /*!
1290     \fn QColor QTableWidgetItem::textColor() const
1291     \obsolete
1292 
1293     This function is deprecated. Use foreground() instead.
1294 */
1295 
1296 /*!
1297     \fn void QTableWidgetItem::setTextColor(const QColor &color)
1298     \obsolete
1299 
1300     This function is deprecated. Use setForeground() instead.
1301 */
1302 #endif
1303 
1304 /*!
1305     \fn QBrush QTableWidgetItem::foreground() const
1306     \since 4.2
1307 
1308     Returns the brush used to render the item's foreground (e.g. text).
1309 
1310     \sa background()
1311 */
1312 
1313 /*!
1314     \fn void QTableWidgetItem::setForeground(const QBrush &brush)
1315     \since 4.2
1316 
1317     Sets the item's foreground brush to the specified \a brush.
1318     Setting a default-constructed brush will let the view use the
1319     default color from the style.
1320 
1321     \sa setBackground()
1322 */
1323 
1324 /*!
1325     \fn int QTableWidgetItem::textAlignment() const
1326 
1327     Returns the text alignment for the item's text.
1328 
1329     \sa Qt::Alignment
1330 */
1331 
1332 /*!
1333     \fn void QTableWidgetItem::setTextAlignment(int alignment)
1334 
1335     Sets the text alignment for the item's text to the \a alignment
1336     specified.
1337 
1338     \sa Qt::Alignment
1339 */
1340 
1341 /*!
1342     Constructs a table item of the specified \a type that does not belong
1343     to any table.
1344 
1345     \sa type()
1346 */
QTableWidgetItem(int type)1347 QTableWidgetItem::QTableWidgetItem(int type)
1348     :  rtti(type), view(nullptr), d(new QTableWidgetItemPrivate(this)),
1349       itemFlags(Qt::ItemIsEditable
1350                 |Qt::ItemIsSelectable
1351                 |Qt::ItemIsUserCheckable
1352                 |Qt::ItemIsEnabled
1353                 |Qt::ItemIsDragEnabled
1354                 |Qt::ItemIsDropEnabled)
1355 {
1356 }
1357 
1358 /*!
1359     Constructs a table item with the given \a text.
1360 
1361     \sa type()
1362 */
QTableWidgetItem(const QString & text,int type)1363 QTableWidgetItem::QTableWidgetItem(const QString &text, int type)
1364     :  rtti(type), view(nullptr), d(new QTableWidgetItemPrivate(this)),
1365       itemFlags(Qt::ItemIsEditable
1366                 |Qt::ItemIsSelectable
1367                 |Qt::ItemIsUserCheckable
1368                 |Qt::ItemIsEnabled
1369                 |Qt::ItemIsDragEnabled
1370                 |Qt::ItemIsDropEnabled)
1371 {
1372     setData(Qt::DisplayRole, text);
1373 }
1374 
1375 /*!
1376     Constructs a table item with the given \a icon and \a text.
1377 
1378     \sa type()
1379 */
QTableWidgetItem(const QIcon & icon,const QString & text,int type)1380 QTableWidgetItem::QTableWidgetItem(const QIcon &icon, const QString &text, int type)
1381     :  rtti(type), view(nullptr), d(new QTableWidgetItemPrivate(this)),
1382        itemFlags(Qt::ItemIsEditable
1383                 |Qt::ItemIsSelectable
1384                 |Qt::ItemIsUserCheckable
1385                 |Qt::ItemIsEnabled
1386                 |Qt::ItemIsDragEnabled
1387                 |Qt::ItemIsDropEnabled)
1388 {
1389     setData(Qt::DecorationRole, icon);
1390     setData(Qt::DisplayRole, text);
1391 }
1392 
1393 /*!
1394     Destroys the table item.
1395 */
~QTableWidgetItem()1396 QTableWidgetItem::~QTableWidgetItem()
1397 {
1398     if (QTableModel *model = tableModel())
1399         model->removeItem(this);
1400     delete d;
1401 }
1402 
1403 /*!
1404     Creates a copy of the item.
1405 */
clone() const1406 QTableWidgetItem *QTableWidgetItem::clone() const
1407 {
1408     return new QTableWidgetItem(*this);
1409 }
1410 
1411 /*!
1412     Sets the item's data for the given \a role to the specified \a value.
1413 
1414     \note The default implementation treats Qt::EditRole and Qt::DisplayRole as
1415     referring to the same data.
1416 
1417     \sa Qt::ItemDataRole, data()
1418 */
setData(int role,const QVariant & value)1419 void QTableWidgetItem::setData(int role, const QVariant &value)
1420 {
1421     bool found = false;
1422     role = (role == Qt::EditRole ? Qt::DisplayRole : role);
1423     for (int i = 0; i < values.count(); ++i) {
1424         if (values.at(i).role == role) {
1425             if (values[i].value == value)
1426                 return;
1427 
1428             values[i].value = value;
1429             found = true;
1430             break;
1431         }
1432     }
1433     if (!found)
1434         values.append(QWidgetItemData(role, value));
1435     if (QTableModel *model = tableModel())
1436     {
1437         const QVector<int> roles((role == Qt::DisplayRole) ?
1438                                     QVector<int>({Qt::DisplayRole, Qt::EditRole}) :
1439                                     QVector<int>({role}));
1440         model->itemChanged(this, roles);
1441     }
1442 }
1443 
1444 /*!
1445     Returns the item's data for the given \a role.
1446 */
data(int role) const1447 QVariant QTableWidgetItem::data(int role) const
1448 {
1449     role = (role == Qt::EditRole ? Qt::DisplayRole : role);
1450     for (const auto &value : values) {
1451         if (value.role == role)
1452             return value.value;
1453     }
1454     return QVariant();
1455 }
1456 
1457 /*!
1458     Returns \c true if the item is less than the \a other item; otherwise returns
1459     false.
1460 */
operator <(const QTableWidgetItem & other) const1461 bool QTableWidgetItem::operator<(const QTableWidgetItem &other) const
1462 {
1463     const QVariant v1 = data(Qt::DisplayRole), v2 = other.data(Qt::DisplayRole);
1464     return QAbstractItemModelPrivate::variantLessThan(v1, v2);
1465 }
1466 
1467 #ifndef QT_NO_DATASTREAM
1468 
1469 /*!
1470     Reads the item from stream \a in.
1471 
1472     \sa write()
1473 */
read(QDataStream & in)1474 void QTableWidgetItem::read(QDataStream &in)
1475 {
1476     in >> values;
1477 }
1478 
1479 /*!
1480     Writes the item to stream \a out.
1481 
1482     \sa read()
1483 */
write(QDataStream & out) const1484 void QTableWidgetItem::write(QDataStream &out) const
1485 {
1486     out << values;
1487 }
1488 
1489 /*!
1490   \internal
1491   returns the QTableModel if a view is set
1492 */
tableModel() const1493 QTableModel *QTableWidgetItem::tableModel() const
1494 {
1495     return (view ? qobject_cast<QTableModel*>(view->model()) : nullptr);
1496 }
1497 
1498 
1499 /*!
1500     \relates QTableWidgetItem
1501 
1502     Reads a table widget item from stream \a in into \a item.
1503 
1504     This operator uses QTableWidgetItem::read().
1505 
1506     \sa {Serializing Qt Data Types}
1507 */
operator >>(QDataStream & in,QTableWidgetItem & item)1508 QDataStream &operator>>(QDataStream &in, QTableWidgetItem &item)
1509 {
1510     item.read(in);
1511     return in;
1512 }
1513 
1514 /*!
1515     \relates QTableWidgetItem
1516 
1517     Writes the table widget item \a item to stream \a out.
1518 
1519     This operator uses QTableWidgetItem::write().
1520 
1521     \sa {Serializing Qt Data Types}
1522 */
operator <<(QDataStream & out,const QTableWidgetItem & item)1523 QDataStream &operator<<(QDataStream &out, const QTableWidgetItem &item)
1524 {
1525     item.write(out);
1526     return out;
1527 }
1528 
1529 #endif // QT_NO_DATASTREAM
1530 
1531 /*!
1532     \since 4.1
1533 
1534     Constructs a copy of \a other. Note that type() and tableWidget()
1535     are not copied.
1536 
1537     This function is useful when reimplementing clone().
1538 
1539     \sa data(), flags()
1540 */
QTableWidgetItem(const QTableWidgetItem & other)1541 QTableWidgetItem::QTableWidgetItem(const QTableWidgetItem &other)
1542     : rtti(Type), values(other.values), view(nullptr),
1543       d(new QTableWidgetItemPrivate(this)),
1544       itemFlags(other.itemFlags)
1545 {
1546 }
1547 
1548 /*!
1549     Assigns \a other's data and flags to this item. Note that type()
1550     and tableWidget() are not copied.
1551 
1552     This function is useful when reimplementing clone().
1553 
1554     \sa data(), flags()
1555 */
operator =(const QTableWidgetItem & other)1556 QTableWidgetItem &QTableWidgetItem::operator=(const QTableWidgetItem &other)
1557 {
1558     values = other.values;
1559     itemFlags = other.itemFlags;
1560     return *this;
1561 }
1562 
1563 /*!
1564     \class QTableWidget
1565     \brief The QTableWidget class provides an item-based table view with a default model.
1566 
1567     \ingroup model-view
1568     \inmodule QtWidgets
1569 
1570     \image windows-tableview.png
1571 
1572     Table widgets provide standard table display facilities for applications.
1573     The items in a QTableWidget are provided by QTableWidgetItem.
1574 
1575     If you want a table that uses your own data model you should
1576     use QTableView rather than this class.
1577 
1578     Table widgets can be constructed with the required numbers of rows and
1579     columns:
1580 
1581     \snippet qtablewidget-using/mainwindow.cpp 0
1582 
1583     Alternatively, tables can be constructed without a given size and resized
1584     later:
1585 
1586     \snippet qtablewidget-resizing/mainwindow.cpp 0
1587     \snippet qtablewidget-resizing/mainwindow.cpp 1
1588 
1589     Items are created outside the table (with no parent widget) and inserted
1590     into the table with setItem():
1591 
1592     \snippet qtablewidget-resizing/mainwindow.cpp 2
1593 
1594     If you want to enable sorting in your table widget, do so after you
1595     have populated it with items, otherwise sorting may interfere with
1596     the insertion order (see setItem() for details).
1597 
1598     Tables can be given both horizontal and vertical headers. The simplest way
1599     to create the headers is to supply a list of strings to the
1600     setHorizontalHeaderLabels() and setVerticalHeaderLabels() functions. These
1601     will provide simple textual headers for the table's columns and rows.
1602     More sophisticated headers can be created from existing table items
1603     that are usually constructed outside the table. For example, we can
1604     construct a table item with an icon and aligned text, and use it as the
1605     header for a particular column:
1606 
1607     \snippet qtablewidget-using/mainwindow.cpp 2
1608 
1609     The number of rows in the table can be found with rowCount(), and the
1610     number of columns with columnCount(). The table can be cleared with the
1611     clear() function.
1612 
1613     \sa QTableWidgetItem, QTableView, {Model/View Programming}
1614 */
1615 
1616 /*!
1617     \property QTableWidget::rowCount
1618     \brief the number of rows in the table
1619 
1620     By default, for a table constructed without row and column counts,
1621     this property contains a value of 0.
1622 */
1623 
1624 /*!
1625     \property QTableWidget::columnCount
1626     \brief the number of columns in the table
1627 
1628     By default, for a table constructed without row and column counts,
1629     this property contains a value of 0.
1630 */
1631 
setup()1632 void QTableWidgetPrivate::setup()
1633 {
1634     Q_Q(QTableWidget);
1635     // view signals
1636     QObject::connect(q, SIGNAL(pressed(QModelIndex)), q, SLOT(_q_emitItemPressed(QModelIndex)));
1637     QObject::connect(q, SIGNAL(clicked(QModelIndex)), q, SLOT(_q_emitItemClicked(QModelIndex)));
1638     QObject::connect(q, SIGNAL(doubleClicked(QModelIndex)),
1639                      q, SLOT(_q_emitItemDoubleClicked(QModelIndex)));
1640     QObject::connect(q, SIGNAL(activated(QModelIndex)), q, SLOT(_q_emitItemActivated(QModelIndex)));
1641     QObject::connect(q, SIGNAL(entered(QModelIndex)), q, SLOT(_q_emitItemEntered(QModelIndex)));
1642     // model signals
1643     QObject::connect(model, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
1644                      q, SLOT(_q_emitItemChanged(QModelIndex)));
1645     // selection signals
1646     QObject::connect(q->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)),
1647                      q, SLOT(_q_emitCurrentItemChanged(QModelIndex,QModelIndex)));
1648     QObject::connect(q->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
1649                      q, SIGNAL(itemSelectionChanged()));
1650     // sorting
1651     QObject::connect(model, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
1652                      q, SLOT(_q_dataChanged(QModelIndex,QModelIndex)));
1653     QObject::connect(model, SIGNAL(columnsRemoved(QModelIndex,int,int)), q, SLOT(_q_sort()));
1654 }
1655 
_q_emitItemPressed(const QModelIndex & index)1656 void QTableWidgetPrivate::_q_emitItemPressed(const QModelIndex &index)
1657 {
1658     Q_Q(QTableWidget);
1659     if (QTableWidgetItem *item = tableModel()->item(index))
1660         emit q->itemPressed(item);
1661     emit q->cellPressed(index.row(), index.column());
1662 }
1663 
_q_emitItemClicked(const QModelIndex & index)1664 void QTableWidgetPrivate::_q_emitItemClicked(const QModelIndex &index)
1665 {
1666     Q_Q(QTableWidget);
1667     if (QTableWidgetItem *item = tableModel()->item(index))
1668         emit q->itemClicked(item);
1669     emit q->cellClicked(index.row(), index.column());
1670 }
1671 
_q_emitItemDoubleClicked(const QModelIndex & index)1672 void QTableWidgetPrivate::_q_emitItemDoubleClicked(const QModelIndex &index)
1673 {
1674     Q_Q(QTableWidget);
1675     if (QTableWidgetItem *item = tableModel()->item(index))
1676         emit q->itemDoubleClicked(item);
1677     emit q->cellDoubleClicked(index.row(), index.column());
1678 }
1679 
_q_emitItemActivated(const QModelIndex & index)1680 void QTableWidgetPrivate::_q_emitItemActivated(const QModelIndex &index)
1681 {
1682     Q_Q(QTableWidget);
1683     if (QTableWidgetItem *item = tableModel()->item(index))
1684         emit q->itemActivated(item);
1685     emit q->cellActivated(index.row(), index.column());
1686 }
1687 
_q_emitItemEntered(const QModelIndex & index)1688 void QTableWidgetPrivate::_q_emitItemEntered(const QModelIndex &index)
1689 {
1690     Q_Q(QTableWidget);
1691     if (QTableWidgetItem *item = tableModel()->item(index))
1692         emit q->itemEntered(item);
1693     emit q->cellEntered(index.row(), index.column());
1694 }
1695 
_q_emitItemChanged(const QModelIndex & index)1696 void QTableWidgetPrivate::_q_emitItemChanged(const QModelIndex &index)
1697 {
1698     Q_Q(QTableWidget);
1699     if (QTableWidgetItem *item = tableModel()->item(index))
1700         emit q->itemChanged(item);
1701     emit q->cellChanged(index.row(), index.column());
1702 }
1703 
_q_emitCurrentItemChanged(const QModelIndex & current,const QModelIndex & previous)1704 void QTableWidgetPrivate::_q_emitCurrentItemChanged(const QModelIndex &current,
1705                                                  const QModelIndex &previous)
1706 {
1707     Q_Q(QTableWidget);
1708     QTableWidgetItem *currentItem = tableModel()->item(current);
1709     QTableWidgetItem *previousItem = tableModel()->item(previous);
1710     if (currentItem || previousItem)
1711         emit q->currentItemChanged(currentItem, previousItem);
1712     emit q->currentCellChanged(current.row(), current.column(), previous.row(), previous.column());
1713 }
1714 
_q_sort()1715 void QTableWidgetPrivate::_q_sort()
1716 {
1717     if (sortingEnabled) {
1718         int column = horizontalHeader->sortIndicatorSection();
1719         Qt::SortOrder order = horizontalHeader->sortIndicatorOrder();
1720         model->sort(column, order);
1721     }
1722 }
1723 
_q_dataChanged(const QModelIndex & topLeft,const QModelIndex & bottomRight)1724 void QTableWidgetPrivate::_q_dataChanged(const QModelIndex &topLeft,
1725                                          const QModelIndex &bottomRight)
1726 {
1727     if (sortingEnabled && topLeft.isValid() && bottomRight.isValid()) {
1728         int column = horizontalHeader->sortIndicatorSection();
1729         if (column >= topLeft.column() && column <= bottomRight.column()) {
1730             Qt::SortOrder order = horizontalHeader->sortIndicatorOrder();
1731             tableModel()->ensureSorted(column, order, topLeft.row(), bottomRight.row());
1732         }
1733     }
1734 }
1735 
1736 /*!
1737     \fn void QTableWidget::itemPressed(QTableWidgetItem *item)
1738 
1739     This signal is emitted whenever an item in the table is pressed.
1740     The \a item specified is the item that was pressed.
1741 */
1742 
1743 /*!
1744     \fn void QTableWidget::itemClicked(QTableWidgetItem *item)
1745 
1746     This signal is emitted whenever an item in the table is clicked.
1747     The \a item specified is the item that was clicked.
1748 */
1749 
1750 /*!
1751     \fn void QTableWidget::itemDoubleClicked(QTableWidgetItem *item)
1752 
1753     This signal is emitted whenever an item in the table is double
1754     clicked. The \a item specified is the item that was double clicked.
1755 */
1756 
1757 /*!
1758     \fn void QTableWidget::itemActivated(QTableWidgetItem *item)
1759 
1760     This signal is emitted when the specified \a item has been activated
1761 */
1762 
1763 /*!
1764     \fn void QTableWidget::itemEntered(QTableWidgetItem *item)
1765 
1766     This signal is emitted when the mouse cursor enters an item. The
1767     \a item is the item entered.
1768 
1769     This signal is only emitted when mouseTracking is turned on, or when a
1770     mouse button is pressed while moving into an item.
1771 */
1772 
1773 /*!
1774     \fn void QTableWidget::itemChanged(QTableWidgetItem *item)
1775 
1776     This signal is emitted whenever the data of \a item has changed.
1777 */
1778 
1779 /*!
1780     \fn void QTableWidget::currentItemChanged(QTableWidgetItem *current, QTableWidgetItem *previous)
1781 
1782     This signal is emitted whenever the current item changes. The \a
1783     previous item is the item that previously had the focus, \a
1784     current is the new current item.
1785 */
1786 
1787 /*!
1788     \fn void QTableWidget::itemSelectionChanged()
1789 
1790     This signal is emitted whenever the selection changes.
1791 
1792     \sa selectedItems(), QTableWidgetItem::isSelected()
1793 */
1794 
1795 
1796 /*!
1797   \since 4.1
1798   \fn void QTableWidget::cellPressed(int row, int column)
1799 
1800   This signal is emitted whenever a cell in the table is pressed.
1801   The \a row and \a column specified is the cell that was pressed.
1802 */
1803 
1804 /*!
1805   \since 4.1
1806   \fn void QTableWidget::cellClicked(int row, int column)
1807 
1808   This signal is emitted whenever a cell in the table is clicked.
1809   The \a row and \a column specified is the cell that was clicked.
1810 */
1811 
1812 /*!
1813   \since 4.1
1814   \fn void QTableWidget::cellDoubleClicked(int row, int column)
1815 
1816   This signal is emitted whenever a cell in the table is double
1817   clicked. The \a row and \a column specified is the cell that was
1818   double clicked.
1819 */
1820 
1821 /*!
1822   \since 4.1
1823   \fn void QTableWidget::cellActivated(int row, int column)
1824 
1825   This signal is emitted when the cell specified  by \a row and \a column
1826   has been activated
1827 */
1828 
1829 /*!
1830   \since 4.1
1831   \fn void QTableWidget::cellEntered(int row, int column)
1832 
1833   This signal is emitted when the mouse cursor enters a cell. The
1834   cell is specified by \a row and \a column.
1835 
1836   This signal is only emitted when mouseTracking is turned on, or when a
1837   mouse button is pressed while moving into an item.
1838 */
1839 
1840 /*!
1841   \since 4.1
1842   \fn void QTableWidget::cellChanged(int row, int column)
1843 
1844   This signal is emitted whenever the data of the item in the cell
1845   specified by \a row and \a column has changed.
1846 */
1847 
1848 /*!
1849   \since 4.1
1850   \fn void QTableWidget::currentCellChanged(int currentRow, int currentColumn, int previousRow, int previousColumn)
1851 
1852   This signal is emitted whenever the current cell changes. The cell
1853   specified by \a previousRow and \a previousColumn is the cell that
1854   previously had the focus, the cell specified by \a currentRow and \a
1855   currentColumn is the new current cell.
1856 */
1857 
1858 /*!
1859   \since 4.3
1860   \fn void QTableWidget::removeCellWidget(int row, int column)
1861 
1862   Removes the widget set on the cell indicated by \a row and \a column.
1863 */
1864 
1865 /*!
1866     \fn QTableWidgetItem *QTableWidget::itemAt(int ax, int ay) const
1867 
1868     Returns the item at the position equivalent to QPoint(\a{ax}, \a{ay}) in
1869     the table widget's coordinate system, or returns \nullptr if the specified point
1870     is not covered by an item in the table widget.
1871 
1872     \sa item()
1873 */
1874 
1875 /*!
1876     \enum QTableWidgetItem::ItemType
1877 
1878     This enum describes the types that are used to describe table widget items.
1879 
1880     \value Type     The default type for table widget items.
1881     \value UserType The minimum value for custom types. Values below UserType are
1882                     reserved by Qt.
1883 
1884     You can define new user types in QTableWidgetItem subclasses to ensure that
1885     custom items are treated specially.
1886 
1887     \sa type()
1888 */
1889 
1890 /*!
1891     \fn int QTableWidgetItem::type() const
1892 
1893     Returns the type passed to the QTableWidgetItem constructor.
1894 */
1895 
1896 /*!
1897     Creates a new table view with the given \a parent.
1898 */
QTableWidget(QWidget * parent)1899 QTableWidget::QTableWidget(QWidget *parent)
1900     : QTableView(*new QTableWidgetPrivate, parent)
1901 {
1902     Q_D(QTableWidget);
1903     QTableView::setModel(new QTableModel(0, 0, this));
1904     d->setup();
1905 }
1906 
1907 /*!
1908     Creates a new table view with the given \a rows and \a columns, and with the given \a parent.
1909 */
QTableWidget(int rows,int columns,QWidget * parent)1910 QTableWidget::QTableWidget(int rows, int columns, QWidget *parent)
1911     : QTableView(*new QTableWidgetPrivate, parent)
1912 {
1913     Q_D(QTableWidget);
1914     QTableView::setModel(new QTableModel(rows, columns, this));
1915     d->setup();
1916 }
1917 
1918 /*!
1919     Destroys this QTableWidget.
1920 */
~QTableWidget()1921 QTableWidget::~QTableWidget()
1922 {
1923 }
1924 
1925 /*!
1926     Sets the number of rows in this table's model to \a rows. If
1927     this is less than rowCount(), the data in the unwanted rows
1928     is discarded.
1929 
1930     \sa setColumnCount()
1931 */
setRowCount(int rows)1932 void QTableWidget::setRowCount(int rows)
1933 {
1934     Q_D(QTableWidget);
1935     d->tableModel()->setRowCount(rows);
1936 }
1937 
1938 /*!
1939   Returns the number of rows.
1940 */
1941 
rowCount() const1942 int QTableWidget::rowCount() const
1943 {
1944     Q_D(const QTableWidget);
1945     return d->model->rowCount();
1946 }
1947 
1948 /*!
1949     Sets the number of columns in this table's model to \a columns. If
1950     this is less than columnCount(), the data in the unwanted columns
1951     is discarded.
1952 
1953     \sa setRowCount()
1954 */
setColumnCount(int columns)1955 void QTableWidget::setColumnCount(int columns)
1956 {
1957     Q_D(QTableWidget);
1958     d->tableModel()->setColumnCount(columns);
1959 }
1960 
1961 /*!
1962   Returns the number of columns.
1963 */
1964 
columnCount() const1965 int QTableWidget::columnCount() const
1966 {
1967     Q_D(const QTableWidget);
1968     return d->model->columnCount();
1969 }
1970 
1971 /*!
1972   Returns the row for the \a item.
1973 */
row(const QTableWidgetItem * item) const1974 int QTableWidget::row(const QTableWidgetItem *item) const
1975 {
1976     Q_D(const QTableWidget);
1977     return d->tableModel()->index(item).row();
1978 }
1979 
1980 /*!
1981   Returns the column for the \a item.
1982 */
column(const QTableWidgetItem * item) const1983 int QTableWidget::column(const QTableWidgetItem *item) const
1984 {
1985     Q_D(const QTableWidget);
1986     return d->tableModel()->index(item).column();
1987 }
1988 
1989 
1990 /*!
1991     Returns the item for the given \a row and \a column if one has been set; otherwise
1992     returns \nullptr.
1993 
1994     \sa setItem()
1995 */
item(int row,int column) const1996 QTableWidgetItem *QTableWidget::item(int row, int column) const
1997 {
1998     Q_D(const QTableWidget);
1999     return d->tableModel()->item(row, column);
2000 }
2001 
2002 /*!
2003     Sets the item for the given \a row and \a column to \a item.
2004 
2005     The table takes ownership of the item.
2006 
2007     Note that if sorting is enabled (see
2008     \l{QTableView::sortingEnabled} {sortingEnabled}) and \a column is
2009     the current sort column, the \a row will be moved to the sorted
2010     position determined by \a item.
2011 
2012     If you want to set several items of a particular row (say, by
2013     calling setItem() in a loop), you may want to turn off sorting
2014     before doing so, and turn it back on afterwards; this will allow
2015     you to use the same \a row argument for all items in the same row
2016     (i.e. setItem() will not move the row).
2017 
2018     \sa item(), takeItem()
2019 */
setItem(int row,int column,QTableWidgetItem * item)2020 void QTableWidget::setItem(int row, int column, QTableWidgetItem *item)
2021 {
2022     Q_D(QTableWidget);
2023     if (item) {
2024         if (Q_UNLIKELY(item->view)) {
2025             qWarning("QTableWidget: cannot insert an item that is already owned by another QTableWidget");
2026         } else {
2027             item->view = this;
2028             d->tableModel()->setItem(row, column, item);
2029         }
2030     } else {
2031         delete takeItem(row, column);
2032     }
2033 }
2034 
2035 /*!
2036     Removes the item at \a row and \a column from the table without deleting it.
2037 */
takeItem(int row,int column)2038 QTableWidgetItem *QTableWidget::takeItem(int row, int column)
2039 {
2040     Q_D(QTableWidget);
2041     QTableWidgetItem *item = d->tableModel()->takeItem(row, column);
2042     if (item)
2043         item->view = nullptr;
2044     return item;
2045 }
2046 
2047 /*!
2048   Returns the vertical header item for row \a row.
2049 */
verticalHeaderItem(int row) const2050 QTableWidgetItem *QTableWidget::verticalHeaderItem(int row) const
2051 {
2052     Q_D(const QTableWidget);
2053     return d->tableModel()->verticalHeaderItem(row);
2054 }
2055 
2056 /*!
2057   Sets the vertical header item for row \a row to \a item.
2058 */
setVerticalHeaderItem(int row,QTableWidgetItem * item)2059 void QTableWidget::setVerticalHeaderItem(int row, QTableWidgetItem *item)
2060 {
2061     Q_D(QTableWidget);
2062     if (item) {
2063         item->view = this;
2064         d->tableModel()->setVerticalHeaderItem(row, item);
2065     } else {
2066         delete takeVerticalHeaderItem(row);
2067     }
2068 }
2069 
2070 /*!
2071   \since 4.1
2072     Removes the vertical header item at \a row from the header without deleting it.
2073 */
takeVerticalHeaderItem(int row)2074 QTableWidgetItem *QTableWidget::takeVerticalHeaderItem(int row)
2075 {
2076     Q_D(QTableWidget);
2077     QTableWidgetItem *itm = d->tableModel()->takeVerticalHeaderItem(row);
2078     if (itm)
2079         itm->view = nullptr;
2080     return itm;
2081 }
2082 
2083 /*!
2084     Returns the horizontal header item for column, \a column, if one has been
2085     set; otherwise returns \nullptr.
2086 */
horizontalHeaderItem(int column) const2087 QTableWidgetItem *QTableWidget::horizontalHeaderItem(int column) const
2088 {
2089     Q_D(const QTableWidget);
2090     return d->tableModel()->horizontalHeaderItem(column);
2091 }
2092 
2093 /*!
2094   Sets the horizontal header item for column \a column to \a item.
2095   If necessary, the column count is increased to fit the item.
2096   The previous header item (if there was one) is deleted.
2097 */
setHorizontalHeaderItem(int column,QTableWidgetItem * item)2098 void QTableWidget::setHorizontalHeaderItem(int column, QTableWidgetItem *item)
2099 {
2100     Q_D(QTableWidget);
2101     if (item) {
2102         item->view = this;
2103         d->tableModel()->setHorizontalHeaderItem(column, item);
2104     } else {
2105         delete takeHorizontalHeaderItem(column);
2106     }
2107 }
2108 
2109 /*!
2110   \since 4.1
2111     Removes the horizontal header item at \a column from the header without deleting it.
2112 */
takeHorizontalHeaderItem(int column)2113 QTableWidgetItem *QTableWidget::takeHorizontalHeaderItem(int column)
2114 {
2115     Q_D(QTableWidget);
2116     QTableWidgetItem *itm = d->tableModel()->takeHorizontalHeaderItem(column);
2117     if (itm)
2118         itm->view = nullptr;
2119     return itm;
2120 }
2121 
2122 /*!
2123   Sets the vertical header labels using \a labels.
2124 */
setVerticalHeaderLabels(const QStringList & labels)2125 void QTableWidget::setVerticalHeaderLabels(const QStringList &labels)
2126 {
2127     Q_D(QTableWidget);
2128     QTableModel *model = d->tableModel();
2129     QTableWidgetItem *item = nullptr;
2130     for (int i = 0; i < model->rowCount() && i < labels.count(); ++i) {
2131         item = model->verticalHeaderItem(i);
2132         if (!item) {
2133             item = model->createItem();
2134             setVerticalHeaderItem(i, item);
2135         }
2136         item->setText(labels.at(i));
2137     }
2138 }
2139 
2140 /*!
2141   Sets the horizontal header labels using \a labels.
2142 */
setHorizontalHeaderLabels(const QStringList & labels)2143 void QTableWidget::setHorizontalHeaderLabels(const QStringList &labels)
2144 {
2145     Q_D(QTableWidget);
2146     QTableModel *model = d->tableModel();
2147     QTableWidgetItem *item = nullptr;
2148     for (int i = 0; i < model->columnCount() && i < labels.count(); ++i) {
2149         item = model->horizontalHeaderItem(i);
2150         if (!item) {
2151             item = model->createItem();
2152             setHorizontalHeaderItem(i, item);
2153         }
2154         item->setText(labels.at(i));
2155     }
2156 }
2157 
2158 /*!
2159     Returns the row of the current item.
2160 
2161     \sa currentColumn(), setCurrentCell()
2162 */
currentRow() const2163 int QTableWidget::currentRow() const
2164 {
2165     return currentIndex().row();
2166 }
2167 
2168 /*!
2169     Returns the column of the current item.
2170 
2171     \sa currentRow(), setCurrentCell()
2172 */
currentColumn() const2173 int QTableWidget::currentColumn() const
2174 {
2175     return currentIndex().column();
2176 }
2177 
2178 /*!
2179     Returns the current item.
2180 
2181     \sa setCurrentItem()
2182 */
currentItem() const2183 QTableWidgetItem *QTableWidget::currentItem() const
2184 {
2185     Q_D(const QTableWidget);
2186     return d->tableModel()->item(currentIndex());
2187 }
2188 
2189 /*!
2190     Sets the current item to \a item.
2191 
2192     Unless the selection mode is \l{QAbstractItemView::}{NoSelection},
2193     the item is also selected.
2194 
2195     \sa currentItem(), setCurrentCell()
2196 */
setCurrentItem(QTableWidgetItem * item)2197 void QTableWidget::setCurrentItem(QTableWidgetItem *item)
2198 {
2199     Q_D(QTableWidget);
2200     setCurrentIndex(d->tableModel()->index(item));
2201 }
2202 
2203 /*!
2204   \since 4.4
2205 
2206   Sets the current item to be \a item, using the given \a command.
2207 
2208   \sa currentItem(), setCurrentCell()
2209 */
setCurrentItem(QTableWidgetItem * item,QItemSelectionModel::SelectionFlags command)2210 void QTableWidget::setCurrentItem(QTableWidgetItem *item, QItemSelectionModel::SelectionFlags command)
2211 {
2212     Q_D(QTableWidget);
2213     d->selectionModel->setCurrentIndex(d->tableModel()->index(item), command);
2214 }
2215 
2216 /*!
2217     \since 4.1
2218 
2219     Sets the current cell to be the cell at position (\a row, \a
2220     column).
2221 
2222     Depending on the current \l{QAbstractItemView::SelectionMode}{selection mode},
2223     the cell may also be selected.
2224 
2225     \sa setCurrentItem(), currentRow(), currentColumn()
2226 */
setCurrentCell(int row,int column)2227 void QTableWidget::setCurrentCell(int row, int column)
2228 {
2229     setCurrentIndex(model()->index(row, column, QModelIndex()));
2230 }
2231 
2232 /*!
2233   \since 4.4
2234 
2235   Sets the current cell to be the cell at position (\a row, \a
2236   column), using the given \a command.
2237 
2238   \sa setCurrentItem(), currentRow(), currentColumn()
2239 */
setCurrentCell(int row,int column,QItemSelectionModel::SelectionFlags command)2240 void QTableWidget::setCurrentCell(int row, int column, QItemSelectionModel::SelectionFlags command)
2241 {
2242     Q_D(QTableWidget);
2243     d->selectionModel->setCurrentIndex(model()->index(row, column, QModelIndex()), command);
2244 }
2245 
2246 /*!
2247   Sorts all the rows in the table widget based on \a column and \a order.
2248 */
sortItems(int column,Qt::SortOrder order)2249 void QTableWidget::sortItems(int column, Qt::SortOrder order)
2250 {
2251     Q_D(QTableWidget);
2252     d->model->sort(column, order);
2253     horizontalHeader()->setSortIndicator(column, order);
2254 }
2255 
2256 /*!
2257     \internal
2258 */
setSortingEnabled(bool enable)2259 void QTableWidget::setSortingEnabled(bool enable)
2260 {
2261     QTableView::setSortingEnabled(enable);
2262 }
2263 
2264 /*!
2265     \internal
2266 */
isSortingEnabled() const2267 bool QTableWidget::isSortingEnabled() const
2268 {
2269     return QTableView::isSortingEnabled();
2270 }
2271 
2272 /*!
2273   Starts editing the \a item if it is editable.
2274 */
2275 
editItem(QTableWidgetItem * item)2276 void QTableWidget::editItem(QTableWidgetItem *item)
2277 {
2278     Q_D(QTableWidget);
2279     if (!item)
2280         return;
2281     edit(d->tableModel()->index(item));
2282 }
2283 
2284 /*!
2285   Opens an editor for the give \a item. The editor remains open after editing.
2286 
2287   \sa closePersistentEditor(), isPersistentEditorOpen()
2288 */
openPersistentEditor(QTableWidgetItem * item)2289 void QTableWidget::openPersistentEditor(QTableWidgetItem *item)
2290 {
2291     Q_D(QTableWidget);
2292     if (!item)
2293         return;
2294     QModelIndex index = d->tableModel()->index(item);
2295     QAbstractItemView::openPersistentEditor(index);
2296 }
2297 
2298 /*!
2299   Closes the persistent editor for \a item.
2300 
2301   \sa openPersistentEditor(), isPersistentEditorOpen()
2302 */
closePersistentEditor(QTableWidgetItem * item)2303 void QTableWidget::closePersistentEditor(QTableWidgetItem *item)
2304 {
2305     Q_D(QTableWidget);
2306     if (!item)
2307         return;
2308     QModelIndex index = d->tableModel()->index(item);
2309     QAbstractItemView::closePersistentEditor(index);
2310 }
2311 
2312 /*!
2313     \since 5.10
2314 
2315     Returns whether a persistent editor is open for item \a item.
2316 
2317     \sa openPersistentEditor(), closePersistentEditor()
2318 */
isPersistentEditorOpen(QTableWidgetItem * item) const2319 bool QTableWidget::isPersistentEditorOpen(QTableWidgetItem *item) const
2320 {
2321     Q_D(const QTableWidget);
2322     const QModelIndex index = d->tableModel()->index(item);
2323     return QAbstractItemView::isPersistentEditorOpen(index);
2324 }
2325 
2326 /*!
2327     \since 4.1
2328 
2329     Returns the widget displayed in the cell in the given \a row and \a column.
2330 
2331     \note The table takes ownership of the widget.
2332 
2333     \sa setCellWidget()
2334 */
cellWidget(int row,int column) const2335 QWidget *QTableWidget::cellWidget(int row, int column) const
2336 {
2337     QModelIndex index = model()->index(row, column, QModelIndex());
2338     return QAbstractItemView::indexWidget(index);
2339 }
2340 
2341 /*!
2342     \since 4.1
2343 
2344     Sets the given \a widget to be displayed in the cell in the given \a row
2345     and \a column, passing the ownership of the widget to the table.
2346 
2347     If cell widget A is replaced with cell widget B, cell widget A will be
2348     deleted. For example, in the code snippet below, the QLineEdit object will
2349     be deleted.
2350 
2351     \snippet code/src_gui_itemviews_qtablewidget.cpp 0
2352 
2353     \sa cellWidget()
2354 */
setCellWidget(int row,int column,QWidget * widget)2355 void QTableWidget::setCellWidget(int row, int column, QWidget *widget)
2356 {
2357     QModelIndex index = model()->index(row, column, QModelIndex());
2358     QAbstractItemView::setIndexWidget(index, widget);
2359 }
2360 
2361 #if QT_DEPRECATED_SINCE(5, 13)
2362 /*!
2363   Returns \c true if the \a item is selected, otherwise returns \c false.
2364 
2365   \obsolete
2366 
2367   This function is deprecated. Use \l{QTableWidgetItem::isSelected()} instead.
2368 */
2369 
isItemSelected(const QTableWidgetItem * item) const2370 bool QTableWidget::isItemSelected(const QTableWidgetItem *item) const
2371 {
2372     return ((item && item->tableWidget() == this) ? item->isSelected() : false);
2373 }
2374 
2375 /*!
2376   Selects or deselects \a item depending on \a select.
2377 
2378   \obsolete
2379 
2380   This function is deprecated. Use \l{QTableWidgetItem::setSelected()} instead.
2381 */
setItemSelected(const QTableWidgetItem * item,bool select)2382 void QTableWidget::setItemSelected(const QTableWidgetItem *item, bool select)
2383 {
2384     if (item && item->tableWidget() == this)
2385         const_cast<QTableWidgetItem*>(item)->setSelected(select);
2386 }
2387 #endif
2388 
2389 /*!
2390   Selects or deselects the \a range depending on \a select.
2391 */
setRangeSelected(const QTableWidgetSelectionRange & range,bool select)2392 void QTableWidget::setRangeSelected(const QTableWidgetSelectionRange &range, bool select)
2393 {
2394     if (!model()->hasIndex(range.topRow(), range.leftColumn(), rootIndex()) ||
2395         !model()->hasIndex(range.bottomRow(), range.rightColumn(), rootIndex()))
2396         return;
2397 
2398     QModelIndex topLeft = model()->index(range.topRow(), range.leftColumn(), rootIndex());
2399     QModelIndex bottomRight = model()->index(range.bottomRow(), range.rightColumn(), rootIndex());
2400 
2401     selectionModel()->select(QItemSelection(topLeft, bottomRight),
2402                              select ? QItemSelectionModel::Select : QItemSelectionModel::Deselect);
2403 }
2404 
2405 /*!
2406   Returns a list of all selected ranges.
2407 
2408   \sa QTableWidgetSelectionRange
2409 */
2410 
selectedRanges() const2411 QList<QTableWidgetSelectionRange> QTableWidget::selectedRanges() const
2412 {
2413     const QList<QItemSelectionRange> ranges = selectionModel()->selection();
2414     QList<QTableWidgetSelectionRange> result;
2415     const int rangesCount = ranges.count();
2416     result.reserve(rangesCount);
2417     for (int i = 0; i < rangesCount; ++i)
2418         result.append(QTableWidgetSelectionRange(ranges.at(i).top(),
2419                                                  ranges.at(i).left(),
2420                                                  ranges.at(i).bottom(),
2421                                                  ranges.at(i).right()));
2422     return result;
2423 }
2424 
2425 /*!
2426   Returns a list of all selected items.
2427 
2428   This function returns a list of pointers to the contents of the
2429   selected cells. Use the selectedIndexes() function to retrieve the
2430   complete selection \e including empty cells.
2431 
2432   \sa selectedIndexes()
2433 */
2434 
selectedItems() const2435 QList<QTableWidgetItem*> QTableWidget::selectedItems() const
2436 {
2437     Q_D(const QTableWidget);
2438     const QModelIndexList indexes = selectionModel()->selectedIndexes();
2439     QList<QTableWidgetItem*> items;
2440     for (const auto &index : indexes) {
2441         if (isIndexHidden(index))
2442             continue;
2443         QTableWidgetItem *item = d->tableModel()->item(index);
2444         if (item)
2445             items.append(item);
2446     }
2447     return items;
2448 }
2449 
2450 /*!
2451   Finds items that matches the \a text using the given \a flags.
2452 */
2453 
findItems(const QString & text,Qt::MatchFlags flags) const2454 QList<QTableWidgetItem*> QTableWidget::findItems(const QString &text, Qt::MatchFlags flags) const
2455 {
2456     Q_D(const QTableWidget);
2457     QModelIndexList indexes;
2458     for (int column = 0; column < columnCount(); ++column)
2459         indexes += d->model->match(model()->index(0, column, QModelIndex()),
2460                                      Qt::DisplayRole, text, -1, flags);
2461     QList<QTableWidgetItem*> items;
2462     const int indexCount = indexes.size();
2463     items.reserve(indexCount);
2464     for (int i = 0; i < indexCount; ++i)
2465         items.append(d->tableModel()->item(indexes.at(i)));
2466     return items;
2467 }
2468 
2469 /*!
2470   Returns the visual row of the given \a logicalRow.
2471 */
2472 
visualRow(int logicalRow) const2473 int QTableWidget::visualRow(int logicalRow) const
2474 {
2475     return verticalHeader()->visualIndex(logicalRow);
2476 }
2477 
2478 /*!
2479   Returns the visual column of the given \a logicalColumn.
2480 */
2481 
visualColumn(int logicalColumn) const2482 int QTableWidget::visualColumn(int logicalColumn) const
2483 {
2484     return horizontalHeader()->visualIndex(logicalColumn);
2485 }
2486 
2487 /*!
2488   \fn QTableWidgetItem *QTableWidget::itemAt(const QPoint &point) const
2489 
2490   Returns a pointer to the item at the given \a point, or returns \nullptr if
2491   \a point is not covered by an item in the table widget.
2492 
2493   \sa item()
2494 */
2495 
itemAt(const QPoint & p) const2496 QTableWidgetItem *QTableWidget::itemAt(const QPoint &p) const
2497 {
2498     Q_D(const QTableWidget);
2499     return d->tableModel()->item(indexAt(p));
2500 }
2501 
2502 /*!
2503   Returns the rectangle on the viewport occupied by the item at \a item.
2504 */
visualItemRect(const QTableWidgetItem * item) const2505 QRect QTableWidget::visualItemRect(const QTableWidgetItem *item) const
2506 {
2507     Q_D(const QTableWidget);
2508     if (!item)
2509         return QRect();
2510     QModelIndex index = d->tableModel()->index(const_cast<QTableWidgetItem*>(item));
2511     Q_ASSERT(index.isValid());
2512     return visualRect(index);
2513 }
2514 
2515 /*!
2516     Scrolls the view if necessary to ensure that the \a item is visible.
2517     The \a hint parameter specifies more precisely where the
2518     \a item should be located after the operation.
2519 */
2520 
scrollToItem(const QTableWidgetItem * item,QAbstractItemView::ScrollHint hint)2521 void QTableWidget::scrollToItem(const QTableWidgetItem *item, QAbstractItemView::ScrollHint hint)
2522 {
2523     Q_D(QTableWidget);
2524     if (!item)
2525         return;
2526     QModelIndex index = d->tableModel()->index(const_cast<QTableWidgetItem*>(item));
2527     Q_ASSERT(index.isValid());
2528     QTableView::scrollTo(index, hint);
2529 }
2530 
2531 /*!
2532     Returns the item prototype used by the table.
2533 
2534     \sa setItemPrototype()
2535 */
itemPrototype() const2536 const QTableWidgetItem *QTableWidget::itemPrototype() const
2537 {
2538     Q_D(const QTableWidget);
2539     return d->tableModel()->itemPrototype();
2540 }
2541 
2542 /*!
2543     Sets the item prototype for the table to the specified \a item.
2544 
2545     The table widget will use the item prototype clone function when it needs
2546     to create a new table item.  For example when the user is editing
2547     in an empty cell.  This is useful when you have a QTableWidgetItem
2548     subclass and want to make sure that QTableWidget creates instances of
2549     your subclass.
2550 
2551     The table takes ownership of the prototype.
2552 
2553     \sa itemPrototype()
2554 */
setItemPrototype(const QTableWidgetItem * item)2555 void QTableWidget::setItemPrototype(const QTableWidgetItem *item)
2556 {
2557     Q_D(QTableWidget);
2558     d->tableModel()->setItemPrototype(item);
2559 }
2560 
2561 /*!
2562   Inserts an empty row into the table at \a row.
2563 */
insertRow(int row)2564 void QTableWidget::insertRow(int row)
2565 {
2566     Q_D(QTableWidget);
2567     d->tableModel()->insertRows(row);
2568 }
2569 
2570 /*!
2571   Inserts an empty column into the table at \a column.
2572 */
insertColumn(int column)2573 void QTableWidget::insertColumn(int column)
2574 {
2575     Q_D(QTableWidget);
2576     d->tableModel()->insertColumns(column);
2577 }
2578 
2579 /*!
2580   Removes the row \a row and all its items from the table.
2581 */
removeRow(int row)2582 void QTableWidget::removeRow(int row)
2583 {
2584     Q_D(QTableWidget);
2585     d->tableModel()->removeRows(row);
2586 }
2587 
2588 /*!
2589   Removes the column \a column and all its items from the table.
2590 */
removeColumn(int column)2591 void QTableWidget::removeColumn(int column)
2592 {
2593     Q_D(QTableWidget);
2594     d->tableModel()->removeColumns(column);
2595 }
2596 
2597 /*!
2598    Removes all items in the view.
2599    This will also remove all selections and headers.
2600    If you don't want to remove the headers, use
2601    QTableWidget::clearContents().
2602    The table dimensions stay the same.
2603 */
2604 
clear()2605 void QTableWidget::clear()
2606 {
2607     Q_D(QTableWidget);
2608     selectionModel()->clear();
2609     d->tableModel()->clear();
2610 }
2611 
2612 /*!
2613     \since 4.2
2614 
2615     Removes all items not in the headers from the view.
2616     This will also remove all selections.
2617     The table dimensions stay the same.
2618 */
clearContents()2619 void QTableWidget::clearContents()
2620 {
2621     Q_D(QTableWidget);
2622     selectionModel()->clear();
2623     d->tableModel()->clearContents();
2624 }
2625 
2626 /*!
2627     Returns a list of MIME types that can be used to describe a list of
2628     tablewidget items.
2629 
2630     \sa mimeData()
2631 */
mimeTypes() const2632 QStringList QTableWidget::mimeTypes() const
2633 {
2634     return d_func()->tableModel()->QAbstractTableModel::mimeTypes();
2635 }
2636 
2637 /*!
2638     Returns an object that contains a serialized description of the specified
2639     \a items. The format used to describe the items is obtained from the
2640     mimeTypes() function.
2641 
2642     If the list of items is empty, \nullptr is returned rather than a
2643     serialized empty list.
2644 */
2645 #if QT_VERSION >= QT_VERSION_CHECK(6,0,0)
mimeData(const QList<QTableWidgetItem * > & items) const2646 QMimeData *QTableWidget::mimeData(const QList<QTableWidgetItem *> &items) const
2647 #else
2648 QMimeData *QTableWidget::mimeData(const QList<QTableWidgetItem*> items) const
2649 #endif
2650 {
2651     Q_D(const QTableWidget);
2652 
2653     QModelIndexList &cachedIndexes = d->tableModel()->cachedIndexes;
2654 
2655     // if non empty, it's called from the model's own mimeData
2656     if (cachedIndexes.isEmpty()) {
2657         cachedIndexes.reserve(items.count());
2658         for (QTableWidgetItem *item : items)
2659             cachedIndexes << indexFromItem(item);
2660 
2661         QMimeData *result = d->tableModel()->internalMimeData();
2662 
2663         cachedIndexes.clear();
2664         return result;
2665     }
2666 
2667     return d->tableModel()->internalMimeData();
2668 }
2669 
2670 /*!
2671     Handles the \a data supplied by a drag and drop operation that ended with
2672     the given \a action in the given \a row and \a column.
2673     Returns \c true if the data and action can be handled by the model;
2674     otherwise returns \c false.
2675 
2676     \sa supportedDropActions()
2677 */
dropMimeData(int row,int column,const QMimeData * data,Qt::DropAction action)2678 bool QTableWidget::dropMimeData(int row, int column, const QMimeData *data, Qt::DropAction action)
2679 {
2680     QModelIndex idx;
2681 #if QT_CONFIG(draganddrop)
2682     if (dropIndicatorPosition() == QAbstractItemView::OnItem) {
2683         // QAbstractTableModel::dropMimeData will overwrite on the index if row == -1 and column == -1
2684         idx = model()->index(row, column);
2685         row = -1;
2686         column = -1;
2687     }
2688 #endif
2689     return d_func()->tableModel()->QAbstractTableModel::dropMimeData(data, action , row, column, idx);
2690 }
2691 
2692 /*!
2693   Returns the drop actions supported by this view.
2694 
2695   \sa Qt::DropActions
2696 */
supportedDropActions() const2697 Qt::DropActions QTableWidget::supportedDropActions() const
2698 {
2699     return d_func()->tableModel()->QAbstractTableModel::supportedDropActions() | Qt::MoveAction;
2700 }
2701 
2702 /*!
2703   Returns a list of pointers to the items contained in the \a data object.
2704   If the object was not created by a QTreeWidget in the same process, the list
2705   is empty.
2706 
2707 */
items(const QMimeData * data) const2708 QList<QTableWidgetItem*> QTableWidget::items(const QMimeData *data) const
2709 {
2710     const QTableWidgetMimeData *twd = qobject_cast<const QTableWidgetMimeData*>(data);
2711     if (twd)
2712         return twd->items;
2713     return QList<QTableWidgetItem*>();
2714 }
2715 
2716 /*!
2717   Returns the QModelIndex associated with the given \a item.
2718 
2719   \note In Qt versions prior to 5.10, this function took a non-\c{const} \a item.
2720 */
2721 
indexFromItem(const QTableWidgetItem * item) const2722 QModelIndex QTableWidget::indexFromItem(const QTableWidgetItem *item) const
2723 {
2724     Q_D(const QTableWidget);
2725     return d->tableModel()->index(item);
2726 }
2727 
2728 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
2729 /*!
2730   \internal
2731   \obsolete
2732   \overload
2733 */
indexFromItem(QTableWidgetItem * item) const2734 QModelIndex QTableWidget::indexFromItem(QTableWidgetItem *item) const
2735 {
2736     return indexFromItem(const_cast<const QTableWidgetItem *>(item));
2737 }
2738 #endif
2739 
2740 /*!
2741   Returns a pointer to the QTableWidgetItem associated with the given \a index.
2742 */
2743 
itemFromIndex(const QModelIndex & index) const2744 QTableWidgetItem *QTableWidget::itemFromIndex(const QModelIndex &index) const
2745 {
2746     Q_D(const QTableWidget);
2747     return d->tableModel()->item(index);
2748 }
2749 
2750 /*!
2751     \internal
2752 */
setModel(QAbstractItemModel *)2753 void QTableWidget::setModel(QAbstractItemModel * /*model*/)
2754 {
2755     Q_ASSERT(!"QTableWidget::setModel() - Changing the model of the QTableWidget is not allowed.");
2756 }
2757 
2758 /*! \reimp */
event(QEvent * e)2759 bool QTableWidget::event(QEvent *e)
2760 {
2761     return QTableView::event(e);
2762 }
2763 
2764 #if QT_CONFIG(draganddrop)
2765 /*! \reimp */
dropEvent(QDropEvent * event)2766 void QTableWidget::dropEvent(QDropEvent *event) {
2767     Q_D(QTableWidget);
2768     if (event->source() == this && (event->dropAction() == Qt::MoveAction ||
2769                                     dragDropMode() == QAbstractItemView::InternalMove)) {
2770         QModelIndex topIndex;
2771         int col = -1;
2772         int row = -1;
2773         if (d->dropOn(event, &row, &col, &topIndex)) {
2774             const QModelIndexList indexes = selectedIndexes();
2775             int top = INT_MAX;
2776             int left = INT_MAX;
2777             for (const auto &index : indexes) {
2778                 top = qMin(index.row(), top);
2779                 left = qMin(index.column(), left);
2780             }
2781 
2782             QList<QTableWidgetItem *> taken;
2783             const int indexesCount = indexes.count();
2784             taken.reserve(indexesCount);
2785             for (const auto &index : indexes)
2786                 taken.append(takeItem(index.row(), index.column()));
2787 
2788             for (const auto &index : indexes) {
2789                 int r = index.row() - top + topIndex.row();
2790                 int c = index.column() - left + topIndex.column();
2791                 setItem(r, c, taken.takeFirst());
2792             }
2793 
2794             event->accept();
2795             // Don't want QAbstractItemView to delete it because it was "moved" we already did it
2796             d->dropEventMoved = true;
2797         }
2798     }
2799 
2800     QTableView::dropEvent(event);
2801 }
2802 #endif
2803 
2804 QT_END_NAMESPACE
2805 
2806 #include "moc_qtablewidget.cpp"
2807 #include "moc_qtablewidget_p.cpp"
2808