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
48QT_BEGIN_NAMESPACE
49
50QTableModel::QTableModel(int rows, int columns, QTableWidget *parent)
51 : QAbstractTableModel(parent),
52 prototype(0),
53 tableItems(rows * columns, 0),
54 verticalHeaderItems(rows, 0),
55 horizontalHeaderItems(columns, 0)
56{}
57
58QTableModel::~QTableModel()
59{
60 clear();
61 delete prototype;
62}
63
64bool 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
81bool 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
99bool 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 = 0;
108 for (int j = i; j < n + i; ++j) {
109 oldItem = tableItems.at(j);
110 if (oldItem)
111 oldItem->view = 0;
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 = 0;
119 delete oldItem;
120 }
121 verticalHeaderItems.remove(row, count);
122 endRemoveRows();
123 return true;
124}
125
126bool 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 = 0;
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 = 0;
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 = 0;
147 delete oldItem;
148 }
149 horizontalHeaderItems.remove(column, count);
150 endRemoveColumns();
151 return true;
152}
153
154void 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 = 0;
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 == 0) {
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
220QTableWidgetItem *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 = 0;
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
234QTableWidgetItem *QTableModel::item(int row, int column) const
235{
236 return item(index(row, column));
237}
238
239QTableWidgetItem *QTableModel::item(const QModelIndex &index) const
240{
241 if (!isValid(index))
242 return 0;
243 return tableItems.at(tableIndex(index.row(), index.column()));
244}
245
246void QTableModel::removeItem(QTableWidgetItem *item)
247{
248 int i = tableItems.indexOf(item);
249 if (i != -1) {
250 tableItems[i] = 0;
251 QModelIndex idx = index(item);
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
271void 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 = 0;
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
293void 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 = 0;
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
315QTableWidgetItem *QTableModel::takeHorizontalHeaderItem(int section)
316{
317 if (section < 0 || section >= horizontalHeaderItems.count())
318 return 0;
319 QTableWidgetItem *itm = horizontalHeaderItems.at(section);
320 if (itm) {
321 itm->view = 0;
322 itm->itemFlags &= ~ItemIsHeaderItem;
323 horizontalHeaderItems[section] = 0;
324 }
325 return itm;
326}
327
328QTableWidgetItem *QTableModel::takeVerticalHeaderItem(int section)
329{
330 if (section < 0 || section >= verticalHeaderItems.count())
331 return 0;
332 QTableWidgetItem *itm = verticalHeaderItems.at(section);
333 if (itm) {
334 itm->view = 0;
335 itm->itemFlags &= ~ItemIsHeaderItem;
336 verticalHeaderItems[section] = 0;
337 }
338 return itm;
339}
340
341QTableWidgetItem *QTableModel::horizontalHeaderItem(int section)
342{
343 return horizontalHeaderItems.value(section);
344}
345
346QTableWidgetItem *QTableModel::verticalHeaderItem(int section)
347{
348 return verticalHeaderItems.value(section);
349}
350
351QModelIndex 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
369void 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
380void 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
391int QTableModel::rowCount(const QModelIndex &parent) const
392{
393 return parent.isValid() ? 0 : verticalHeaderItems.count();
394}
395
396int QTableModel::columnCount(const QModelIndex &parent) const
397{
398 return parent.isValid() ? 0 : horizontalHeaderItems.count();
399}
400
401QVariant 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
409bool 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
434QMap<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
448bool 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)
484bool 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
501Qt::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
515void 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*/
566void 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 == 0) {
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*/
645QVector<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 == 0) {
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*/
669void 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*/
694QVector<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
704bool QTableModel::itemLessThan(const QPair<QTableWidgetItem*,int> &left,
705 const QPair<QTableWidgetItem*,int> &right)
706{
707 return *(left.first) < *(right.first);
708}
709
710bool QTableModel::itemGreaterThan(const QPair<QTableWidgetItem*,int> &left,
711 const QPair<QTableWidgetItem*,int> &right)
712{
713 return (*(right.first) < *(left .first));
714}
715
716QVariant QTableModel::headerData(int section, Qt::Orientation orientation, int role) const
717{
718 if (section < 0)
719 return QVariant();
720
721 QTableWidgetItem *itm = 0;
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
736bool 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 = 0;
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
756bool QTableModel::isValid(const QModelIndex &index) const
757{
758 return (index.isValid()
759 && index.row() < verticalHeaderItems.count()
760 && index.column() < horizontalHeaderItems.count());
761}
762
763void QTableModel::clear()
764{
765 for (int j = 0; j < verticalHeaderItems.count(); ++j) {
766 if (verticalHeaderItems.at(j)) {
767 verticalHeaderItems.at(j)->view = 0;
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 = 0;
775 delete horizontalHeaderItems.at(k);
776 horizontalHeaderItems[k] = 0;
777 }
778 }
779 clearContents();
780}
781
782void QTableModel::clearContents()
783{
784 beginResetModel();
785 for (int i = 0; i < tableItems.count(); ++i) {
786 if (tableItems.at(i)) {
787 tableItems.at(i)->view = 0;
788 delete tableItems.at(i);
789 tableItems[i] = 0;
790 }
791 }
792 endResetModel();
793}
794
795void 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
815QTableWidgetItem* QTableModel::createItem() const
816{
817 return prototype ? prototype->clone() : new QTableWidgetItem;
818}
819
820const QTableWidgetItem *QTableModel::itemPrototype() const
821{
822 return prototype;
823}
824
825void QTableModel::setItemPrototype(const QTableWidgetItem *item)
826{
827 if (prototype != item) {
828 delete prototype;
829 prototype = item;
830 }
831}
832
833QStringList QTableModel::mimeTypes() const
834{
835 const QTableWidget *view = qobject_cast<const QTableWidget*>(QObject::parent());
836 return (view ? view->mimeTypes() : QStringList());
837}
838
839QMimeData *QTableModel::internalMimeData() const
840{
841 return QAbstractTableModel::mimeData(cachedIndexes);
842}
843
844QMimeData *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) : 0);
857 cachedIndexes.clear();
858 return mimeData;
859}
860
861bool 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
876Qt::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*/
906QTableWidgetSelectionRange::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*/
917QTableWidgetSelectionRange::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*/
926QTableWidgetSelectionRange::QTableWidgetSelectionRange(const QTableWidgetSelectionRange &other)
927 : top(other.top), left(other.left), bottom(other.bottom), right(other.right)
928{
929}
930
931/*!
932 Destroys the table selection range.
933*/
934QTableWidgetSelectionRange::~QTableWidgetSelectionRange()
935{
936}
937
938/*!
939 \fn int QTableWidgetSelectionRange::topRow() const
940
941 Returns the top row of the range.
942
943 \sa bottomRow(), leftColumn(), rowCount()
944*/
945
946/*!
947 \fn int QTableWidgetSelectionRange::bottomRow() const
948
949 Returns the bottom row of the range.
950
951 \sa topRow(), rightColumn(), rowCount()
952*/
953
954/*!
955 \fn int QTableWidgetSelectionRange::leftColumn() const
956
957 Returns the left column of the range.
958
959 \sa rightColumn(), topRow(), columnCount()
960*/
961
962/*!
963 \fn int QTableWidgetSelectionRange::rightColumn() const
964
965 Returns the right column of the range.
966
967 \sa leftColumn(), bottomRow(), columnCount()
968*/
969
970/*!
971 \since 4.1
972 \fn int QTableWidgetSelectionRange::rowCount() const
973
974 Returns the number of rows in the range.
975
976 This is equivalent to bottomRow() - topRow() + 1.
977
978 \sa columnCount(), topRow(), bottomRow()
979*/
980
981/*!
982 \since 4.1
983 \fn int QTableWidgetSelectionRange::columnCount() const
984
985 Returns the number of columns in the range.
986
987 This is equivalent to rightColumn() - leftColumn() + 1.
988
989 \sa rowCount(), leftColumn(), rightColumn()
990*/
991
992/*!
993 \class QTableWidgetItem
994 \brief The QTableWidgetItem class provides an item for use with the
995 QTableWidget class.
996
997 \ingroup model-view
998 \inmodule QtWidgets
999
1000 Table items are used to hold pieces of information for table widgets.
1001 Items usually contain text, icons, or checkboxes
1002
1003 The QTableWidgetItem class is a convenience class that replaces the
1004 \c QTableItem class in Qt 3. It provides an item for use with
1005 the QTableWidget class.
1006
1007 Top-level items are constructed without a parent then inserted at the
1008 position specified by a pair of row and column numbers:
1009
1010 \snippet qtablewidget-using/mainwindow.cpp 3
1011
1012 Each item can have its own background brush which is set with
1013 the setBackground() function. The current background brush can be
1014 found with background().
1015 The text label for each item can be rendered with its own font and brush.
1016 These are specified with the setFont() and setForeground() functions,
1017 and read with font() and foreground().
1018
1019 By default, items are enabled, editable, selectable, checkable, and can be
1020 used both as the source of a drag and drop operation and as a drop target.
1021 Each item's flags can be changed by calling setFlags() with the appropriate
1022 value (see \l{Qt::ItemFlags}). Checkable items can be checked and unchecked
1023 with the setCheckState() function. The corresponding checkState() function
1024 indicates whether the item is currently checked.
1025
1026 \section1 Subclassing
1027
1028 When subclassing QTableWidgetItem to provide custom items, it is possible to
1029 define new types for them so that they can be distinguished from standard
1030 items. The constructors for subclasses that require this feature need to
1031 call the base class constructor with a new type value equal to or greater
1032 than \l UserType.
1033
1034 \sa QTableWidget, {Model/View Programming}, QListWidgetItem, QTreeWidgetItem
1035*/
1036
1037/*!
1038 \fn int QTableWidgetItem::row() const
1039 \since 4.2
1040
1041 Returns the row of the item in the table.
1042 If the item is not in a table, this function will return -1.
1043
1044 \sa column()
1045*/
1046
1047/*!
1048 \fn int QTableWidgetItem::column() const
1049 \since 4.2
1050
1051 Returns the column of the item in the table.
1052 If the item is not in a table, this function will return -1.
1053
1054 \sa row()
1055*/
1056
1057/*!
1058 \fn QSize QTableWidgetItem::sizeHint() const
1059 \since 4.1
1060
1061 Returns the size hint set for the table item.
1062*/
1063
1064/*!
1065 \fn void QTableWidgetItem::setSizeHint(const QSize &size)
1066 \since 4.1
1067
1068 Sets the size hint for the table item to be \a size.
1069 If no size hint is set, the item delegate will compute the
1070 size hint based on the item data.
1071*/
1072
1073/*!
1074 \fn Qt::CheckState QTableWidgetItem::checkState() const
1075
1076 Returns the checked state of the table item.
1077
1078 \sa flags()
1079*/
1080
1081/*!
1082 \fn void QTableWidgetItem::setCheckState(Qt::CheckState state)
1083
1084 Sets the check state of the table item to be \a state.
1085*/
1086
1087/*!
1088 \fn QTableWidget *QTableWidgetItem::tableWidget() const
1089
1090 Returns the table widget that contains the item.
1091*/
1092
1093/*!
1094 \fn bool QTableWidgetItem::isSelected() const
1095 \since 4.2
1096
1097 Returns \c true if the item is selected, otherwise returns \c false.
1098
1099 \sa setSelected()
1100*/
1101bool QTableWidgetItem::isSelected() const
1102{
1103 if (!view || !view->selectionModel())
1104 return false;
1105 const QTableModel *model = qobject_cast<const QTableModel*>(view->model());
1106 if (!model)
1107 return false;
1108 const QModelIndex index = model->index(this);
1109 return view->selectionModel()->isSelected(index);
1110}
1111
1112/*!
1113 \fn void QTableWidgetItem::setSelected(bool select)
1114 \since 4.2
1115
1116 Sets the selected state of the item to \a select.
1117
1118 \sa isSelected()
1119*/
1120void QTableWidgetItem::setSelected(bool select)
1121{
1122 if (!view || !view->selectionModel())
1123 return;
1124 const QTableModel *model = qobject_cast<const QTableModel*>(view->model());
1125 if (!model)
1126 return;
1127 const QModelIndex index = model->index(this);
1128 view->selectionModel()->select(index, select ? QItemSelectionModel::Select : QItemSelectionModel::Deselect);
1129}
1130
1131/*!
1132 \fn Qt::ItemFlags QTableWidgetItem::flags() const
1133
1134 Returns the flags used to describe the item. These determine whether
1135 the item can be checked, edited, and selected.
1136
1137 \sa setFlags()
1138*/
1139
1140/*!
1141 \fn void QTableWidgetItem::setFlags(Qt::ItemFlags flags)
1142
1143 Sets the flags for the item to the given \a flags. These determine whether
1144 the item can be selected or modified.
1145
1146 \sa flags()
1147*/
1148void QTableWidgetItem::setFlags(Qt::ItemFlags aflags)
1149{
1150 itemFlags = aflags;
1151 if (QTableModel *model = tableModel())
1152 model->itemChanged(this);
1153}
1154
1155
1156/*!
1157 \fn QString QTableWidgetItem::text() const
1158
1159 Returns the item's text.
1160
1161 \sa setText()
1162*/
1163
1164/*!
1165 \fn void QTableWidgetItem::setText(const QString &text)
1166
1167 Sets the item's text to the \a text specified.
1168
1169 \sa text(), setFont(), setForeground()
1170*/
1171
1172/*!
1173 \fn QIcon QTableWidgetItem::icon() const
1174
1175 Returns the item's icon.
1176
1177 \sa setIcon(), {QAbstractItemView::iconSize}{iconSize}
1178*/
1179
1180/*!
1181 \fn void QTableWidgetItem::setIcon(const QIcon &icon)
1182
1183 Sets the item's icon to the \a icon specified.
1184
1185 \sa icon(), setText(), {QAbstractItemView::iconSize}{iconSize}
1186*/
1187
1188/*!
1189 \fn QString QTableWidgetItem::statusTip() const
1190
1191 Returns the item's status tip.
1192
1193 \sa setStatusTip()
1194*/
1195
1196/*!
1197 \fn void QTableWidgetItem::setStatusTip(const QString &statusTip)
1198
1199 Sets the status tip for the table item to the text specified by
1200 \a statusTip. QTableWidget mouse tracking needs to be enabled for this
1201 feature to work.
1202
1203 \sa statusTip(), setToolTip(), setWhatsThis()
1204*/
1205
1206/*!
1207 \fn QString QTableWidgetItem::toolTip() const
1208
1209 Returns the item's tooltip.
1210
1211 \sa setToolTip()
1212*/
1213
1214/*!
1215 \fn void QTableWidgetItem::setToolTip(const QString &toolTip)
1216
1217 Sets the item's tooltip to the string specified by \a toolTip.
1218
1219 \sa toolTip(), setStatusTip(), setWhatsThis()
1220*/
1221
1222/*!
1223 \fn QString QTableWidgetItem::whatsThis() const
1224
1225 Returns the item's "What's This?" help.
1226
1227 \sa setWhatsThis()
1228*/
1229
1230/*!
1231 \fn void QTableWidgetItem::setWhatsThis(const QString &whatsThis)
1232
1233 Sets the item's "What's This?" help to the string specified by \a whatsThis.
1234
1235 \sa whatsThis(), setStatusTip(), setToolTip()
1236*/
1237
1238/*!
1239 \fn QFont QTableWidgetItem::font() const
1240
1241 Returns the font used to render the item's text.
1242
1243 \sa setFont()
1244*/
1245
1246/*!
1247 \fn void QTableWidgetItem::setFont(const QFont &font)
1248
1249 Sets the font used to display the item's text to the given \a font.
1250
1251 \sa font(), setText(), setForeground()
1252*/
1253
1254/*!
1255 \fn QColor QTableWidgetItem::backgroundColor() const
1256 \obsolete
1257
1258 This function is deprecated. Use background() instead.
1259*/
1260
1261/*!
1262 \fn void QTableWidgetItem::setBackgroundColor(const QColor &color)
1263 \obsolete
1264
1265 This function is deprecated. Use setBackground() instead.
1266*/
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
1283 \sa setForeground()
1284*/
1285
1286/*!
1287 \fn QColor QTableWidgetItem::textColor() const
1288 \obsolete
1289
1290 This function is deprecated. Use foreground() instead.
1291*/
1292
1293/*!
1294 \fn void QTableWidgetItem::setTextColor(const QColor &color)
1295 \obsolete
1296
1297 This function is deprecated. Use setForeground() instead.
1298*/
1299
1300/*!
1301 \fn QBrush QTableWidgetItem::foreground() const
1302 \since 4.2
1303
1304 Returns the brush used to render the item's foreground (e.g. text).
1305
1306 \sa background()
1307*/
1308
1309/*!
1310 \fn void QTableWidgetItem::setForeground(const QBrush &brush)
1311 \since 4.2
1312
1313 Sets the item's foreground brush to the specified \a brush.
1314
1315 \sa setBackground()
1316*/
1317
1318/*!
1319 \fn int QTableWidgetItem::textAlignment() const
1320
1321 Returns the text alignment for the item's text.
1322
1323 \sa Qt::Alignment
1324*/
1325
1326/*!
1327 \fn void QTableWidgetItem::setTextAlignment(int alignment)
1328
1329 Sets the text alignment for the item's text to the \a alignment
1330 specified.
1331
1332 \sa Qt::Alignment
1333*/
1334
1335/*!
1336 Constructs a table item of the specified \a type that does not belong
1337 to any table.
1338
1339 \sa type()
1340*/
1341QTableWidgetItem::QTableWidgetItem(int type)
1342 : rtti(type), view(nullptr), d(new QTableWidgetItemPrivate(this)),
1343 itemFlags(Qt::ItemIsEditable
1344 |Qt::ItemIsSelectable
1345 |Qt::ItemIsUserCheckable
1346 |Qt::ItemIsEnabled
1347 |Qt::ItemIsDragEnabled
1348 |Qt::ItemIsDropEnabled)
1349{
1350}
1351
1352/*!
1353 Constructs a table item with the given \a text.
1354
1355 \sa type()
1356*/
1357QTableWidgetItem::QTableWidgetItem(const QString &text, int type)
1358 : rtti(type), view(nullptr), d(new QTableWidgetItemPrivate(this)),
1359 itemFlags(Qt::ItemIsEditable
1360 |Qt::ItemIsSelectable
1361 |Qt::ItemIsUserCheckable
1362 |Qt::ItemIsEnabled
1363 |Qt::ItemIsDragEnabled
1364 |Qt::ItemIsDropEnabled)
1365{
1366 setData(Qt::DisplayRole, text);
1367}
1368
1369/*!
1370 Constructs a table item with the given \a icon and \a text.
1371
1372 \sa type()
1373*/
1374QTableWidgetItem::QTableWidgetItem(const QIcon &icon, const QString &text, int type)
1375 : rtti(type), view(nullptr), d(new QTableWidgetItemPrivate(this)),
1376 itemFlags(Qt::ItemIsEditable
1377 |Qt::ItemIsSelectable
1378 |Qt::ItemIsUserCheckable
1379 |Qt::ItemIsEnabled
1380 |Qt::ItemIsDragEnabled
1381 |Qt::ItemIsDropEnabled)
1382{
1383 setData(Qt::DecorationRole, icon);
1384 setData(Qt::DisplayRole, text);
1385}
1386
1387/*!
1388 Destroys the table item.
1389*/
1390QTableWidgetItem::~QTableWidgetItem()
1391{
1392 if (QTableModel *model = tableModel())
1393 model->removeItem(this);
1394 delete d;
1395}
1396
1397/*!
1398 Creates a copy of the item.
1399*/
1400QTableWidgetItem *QTableWidgetItem::clone() const
1401{
1402 return new QTableWidgetItem(*this);
1403}
1404
1405/*!
1406 Sets the item's data for the given \a role to the specified \a value.
1407
1408 \note The default implementation treats Qt::EditRole and Qt::DisplayRole as
1409 referring to the same data.
1410
1411 \sa Qt::ItemDataRole, data()
1412*/
1413void QTableWidgetItem::setData(int role, const QVariant &value)
1414{
1415 bool found = false;
1416 role = (role == Qt::EditRole ? Qt::DisplayRole : role);
1417 for (int i = 0; i < values.count(); ++i) {
1418 if (values.at(i).role == role) {
1419 if (values[i].value == value)
1420 return;
1421
1422 values[i].value = value;
1423 found = true;
1424 break;
1425 }
1426 }
1427 if (!found)
1428 values.append(QWidgetItemData(role, value));
1429 if (QTableModel *model = tableModel())
1430 {
1431 const QVector<int> roles((role == Qt::DisplayRole) ?
1432 QVector<int>({Qt::DisplayRole, Qt::EditRole}) :
1433 QVector<int>({role}));
1434 model->itemChanged(this, roles);
1435 }
1436}
1437
1438/*!
1439 Returns the item's data for the given \a role.
1440*/
1441QVariant QTableWidgetItem::data(int role) const
1442{
1443 role = (role == Qt::EditRole ? Qt::DisplayRole : role);
1444 for (const auto &value : values) {
1445 if (value.role == role)
1446 return value.value;
1447 }
1448 return QVariant();
1449}
1450
1451/*!
1452 Returns \c true if the item is less than the \a other item; otherwise returns
1453 false.
1454*/
1455bool QTableWidgetItem::operator<(const QTableWidgetItem &other) const
1456{
1457 const QVariant v1 = data(Qt::DisplayRole), v2 = other.data(Qt::DisplayRole);
1458 return QAbstractItemModelPrivate::variantLessThan(v1, v2);
1459}
1460
1461#ifndef QT_NO_DATASTREAM
1462
1463/*!
1464 Reads the item from stream \a in.
1465
1466 \sa write()
1467*/
1468void QTableWidgetItem::read(QDataStream &in)
1469{
1470 in >> values;
1471}
1472
1473/*!
1474 Writes the item to stream \a out.
1475
1476 \sa read()
1477*/
1478void QTableWidgetItem::write(QDataStream &out) const
1479{
1480 out << values;
1481}
1482
1483/*!
1484 \internal
1485 returns the QTableModel if a view is set
1486*/
1487QTableModel *QTableWidgetItem::tableModel() const
1488{
1489 return (view ? qobject_cast<QTableModel*>(view->model()) : nullptr);
1490}
1491
1492
1493/*!
1494 \relates QTableWidgetItem
1495
1496 Reads a table widget item from stream \a in into \a item.
1497
1498 This operator uses QTableWidgetItem::read().
1499
1500 \sa {Serializing Qt Data Types}
1501*/
1502QDataStream &operator>>(QDataStream &in, QTableWidgetItem &item)
1503{
1504 item.read(in);
1505 return in;
1506}
1507
1508/*!
1509 \relates QTableWidgetItem
1510
1511 Writes the table widget item \a item to stream \a out.
1512
1513 This operator uses QTableWidgetItem::write().
1514
1515 \sa {Serializing Qt Data Types}
1516*/
1517QDataStream &operator<<(QDataStream &out, const QTableWidgetItem &item)
1518{
1519 item.write(out);
1520 return out;
1521}
1522
1523#endif // QT_NO_DATASTREAM
1524
1525/*!
1526 \since 4.1
1527
1528 Constructs a copy of \a other. Note that type() and tableWidget()
1529 are not copied.
1530
1531 This function is useful when reimplementing clone().
1532
1533 \sa data(), flags()
1534*/
1535QTableWidgetItem::QTableWidgetItem(const QTableWidgetItem &other)
1536 : rtti(Type), values(other.values), view(nullptr),
1537 d(new QTableWidgetItemPrivate(this)),
1538 itemFlags(other.itemFlags)
1539{
1540}
1541
1542/*!
1543 Assigns \a other's data and flags to this item. Note that type()
1544 and tableWidget() are not copied.
1545
1546 This function is useful when reimplementing clone().
1547
1548 \sa data(), flags()
1549*/
1550QTableWidgetItem &QTableWidgetItem::operator=(const QTableWidgetItem &other)
1551{
1552 values = other.values;
1553 itemFlags = other.itemFlags;
1554 return *this;
1555}
1556
1557/*!
1558 \class QTableWidget
1559 \brief The QTableWidget class provides an item-based table view with a default model.
1560
1561 \ingroup model-view
1562 \inmodule QtWidgets
1563
1564 \image windows-tableview.png
1565
1566 Table widgets provide standard table display facilities for applications.
1567 The items in a QTableWidget are provided by QTableWidgetItem.
1568
1569 If you want a table that uses your own data model you should
1570 use QTableView rather than this class.
1571
1572 Table widgets can be constructed with the required numbers of rows and
1573 columns:
1574
1575 \snippet qtablewidget-using/mainwindow.cpp 0
1576
1577 Alternatively, tables can be constructed without a given size and resized
1578 later:
1579
1580 \snippet qtablewidget-resizing/mainwindow.cpp 0
1581 \snippet qtablewidget-resizing/mainwindow.cpp 1
1582
1583 Items are created outside the table (with no parent widget) and inserted
1584 into the table with setItem():
1585
1586 \snippet qtablewidget-resizing/mainwindow.cpp 2
1587
1588 If you want to enable sorting in your table widget, do so after you
1589 have populated it with items, otherwise sorting may interfere with
1590 the insertion order (see setItem() for details).
1591
1592 Tables can be given both horizontal and vertical headers. The simplest way
1593 to create the headers is to supply a list of strings to the
1594 setHorizontalHeaderLabels() and setVerticalHeaderLabels() functions. These
1595 will provide simple textual headers for the table's columns and rows.
1596 More sophisticated headers can be created from existing table items
1597 that are usually constructed outside the table. For example, we can
1598 construct a table item with an icon and aligned text, and use it as the
1599 header for a particular column:
1600
1601 \snippet qtablewidget-using/mainwindow.cpp 2
1602
1603 The number of rows in the table can be found with rowCount(), and the
1604 number of columns with columnCount(). The table can be cleared with the
1605 clear() function.
1606
1607 \sa QTableWidgetItem, QTableView, {Model/View Programming}
1608*/
1609
1610/*!
1611 \property QTableWidget::rowCount
1612 \brief the number of rows in the table
1613
1614 By default, for a table constructed without row and column counts,
1615 this property contains a value of 0.
1616*/
1617
1618/*!
1619 \property QTableWidget::columnCount
1620 \brief the number of columns in the table
1621
1622 By default, for a table constructed without row and column counts,
1623 this property contains a value of 0.
1624*/
1625
1626void QTableWidgetPrivate::setup()
1627{
1628 Q_Q(QTableWidget);
1629 // view signals
1630 QObject::connect(q, SIGNAL(pressed(QModelIndex)), q, SLOT(_q_emitItemPressed(QModelIndex)));
1631 QObject::connect(q, SIGNAL(clicked(QModelIndex)), q, SLOT(_q_emitItemClicked(QModelIndex)));
1632 QObject::connect(q, SIGNAL(doubleClicked(QModelIndex)),
1633 q, SLOT(_q_emitItemDoubleClicked(QModelIndex)));
1634 QObject::connect(q, SIGNAL(activated(QModelIndex)), q, SLOT(_q_emitItemActivated(QModelIndex)));
1635 QObject::connect(q, SIGNAL(entered(QModelIndex)), q, SLOT(_q_emitItemEntered(QModelIndex)));
1636 // model signals
1637 QObject::connect(model, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
1638 q, SLOT(_q_emitItemChanged(QModelIndex)));
1639 // selection signals
1640 QObject::connect(q->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)),
1641 q, SLOT(_q_emitCurrentItemChanged(QModelIndex,QModelIndex)));
1642 QObject::connect(q->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
1643 q, SIGNAL(itemSelectionChanged()));
1644 // sorting
1645 QObject::connect(model, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
1646 q, SLOT(_q_dataChanged(QModelIndex,QModelIndex)));
1647 QObject::connect(model, SIGNAL(columnsRemoved(QModelIndex,int,int)), q, SLOT(_q_sort()));
1648}
1649
1650void QTableWidgetPrivate::_q_emitItemPressed(const QModelIndex &index)
1651{
1652 Q_Q(QTableWidget);
1653 if (QTableWidgetItem *item = tableModel()->item(index))
1654 emit q->itemPressed(item);
1655 emit q->cellPressed(index.row(), index.column());
1656}
1657
1658void QTableWidgetPrivate::_q_emitItemClicked(const QModelIndex &index)
1659{
1660 Q_Q(QTableWidget);
1661 if (QTableWidgetItem *item = tableModel()->item(index))
1662 emit q->itemClicked(item);
1663 emit q->cellClicked(index.row(), index.column());
1664}
1665
1666void QTableWidgetPrivate::_q_emitItemDoubleClicked(const QModelIndex &index)
1667{
1668 Q_Q(QTableWidget);
1669 if (QTableWidgetItem *item = tableModel()->item(index))
1670 emit q->itemDoubleClicked(item);
1671 emit q->cellDoubleClicked(index.row(), index.column());
1672}
1673
1674void QTableWidgetPrivate::_q_emitItemActivated(const QModelIndex &index)
1675{
1676 Q_Q(QTableWidget);
1677 if (QTableWidgetItem *item = tableModel()->item(index))
1678 emit q->itemActivated(item);
1679 emit q->cellActivated(index.row(), index.column());
1680}
1681
1682void QTableWidgetPrivate::_q_emitItemEntered(const QModelIndex &index)
1683{
1684 Q_Q(QTableWidget);
1685 if (QTableWidgetItem *item = tableModel()->item(index))
1686 emit q->itemEntered(item);
1687 emit q->cellEntered(index.row(), index.column());
1688}
1689
1690void QTableWidgetPrivate::_q_emitItemChanged(const QModelIndex &index)
1691{
1692 Q_Q(QTableWidget);
1693 if (QTableWidgetItem *item = tableModel()->item(index))
1694 emit q->itemChanged(item);
1695 emit q->cellChanged(index.row(), index.column());
1696}
1697
1698void QTableWidgetPrivate::_q_emitCurrentItemChanged(const QModelIndex &current,
1699 const QModelIndex &previous)
1700{
1701 Q_Q(QTableWidget);
1702 QTableWidgetItem *currentItem = tableModel()->item(current);
1703 QTableWidgetItem *previousItem = tableModel()->item(previous);
1704 if (currentItem || previousItem)
1705 emit q->currentItemChanged(currentItem, previousItem);
1706 emit q->currentCellChanged(current.row(), current.column(), previous.row(), previous.column());
1707}
1708
1709void QTableWidgetPrivate::_q_sort()
1710{
1711 if (sortingEnabled) {
1712 int column = horizontalHeader->sortIndicatorSection();
1713 Qt::SortOrder order = horizontalHeader->sortIndicatorOrder();
1714 model->sort(column, order);
1715 }
1716}
1717
1718void QTableWidgetPrivate::_q_dataChanged(const QModelIndex &topLeft,
1719 const QModelIndex &bottomRight)
1720{
1721 if (sortingEnabled && topLeft.isValid() && bottomRight.isValid()) {
1722 int column = horizontalHeader->sortIndicatorSection();
1723 if (column >= topLeft.column() && column <= bottomRight.column()) {
1724 Qt::SortOrder order = horizontalHeader->sortIndicatorOrder();
1725 tableModel()->ensureSorted(column, order, topLeft.row(), bottomRight.row());
1726 }
1727 }
1728}
1729
1730/*!
1731 \fn void QTableWidget::itemPressed(QTableWidgetItem *item)
1732
1733 This signal is emitted whenever an item in the table is pressed.
1734 The \a item specified is the item that was pressed.
1735*/
1736
1737/*!
1738 \fn void QTableWidget::itemClicked(QTableWidgetItem *item)
1739
1740 This signal is emitted whenever an item in the table is clicked.
1741 The \a item specified is the item that was clicked.
1742*/
1743
1744/*!
1745 \fn void QTableWidget::itemDoubleClicked(QTableWidgetItem *item)
1746
1747 This signal is emitted whenever an item in the table is double
1748 clicked. The \a item specified is the item that was double clicked.
1749*/
1750
1751/*!
1752 \fn void QTableWidget::itemActivated(QTableWidgetItem *item)
1753
1754 This signal is emitted when the specified \a item has been activated
1755*/
1756
1757/*!
1758 \fn void QTableWidget::itemEntered(QTableWidgetItem *item)
1759
1760 This signal is emitted when the mouse cursor enters an item. The
1761 \a item is the item entered.
1762
1763 This signal is only emitted when mouseTracking is turned on, or when a
1764 mouse button is pressed while moving into an item.
1765*/
1766
1767/*!
1768 \fn void QTableWidget::itemChanged(QTableWidgetItem *item)
1769
1770 This signal is emitted whenever the data of \a item has changed.
1771*/
1772
1773/*!
1774 \fn void QTableWidget::currentItemChanged(QTableWidgetItem *current, QTableWidgetItem *previous)
1775
1776 This signal is emitted whenever the current item changes. The \a
1777 previous item is the item that previously had the focus, \a
1778 current is the new current item.
1779*/
1780
1781/*!
1782 \fn void QTableWidget::itemSelectionChanged()
1783
1784 This signal is emitted whenever the selection changes.
1785
1786 \sa selectedItems(), QTableWidgetItem::isSelected()
1787*/
1788
1789
1790/*!
1791 \since 4.1
1792 \fn void QTableWidget::cellPressed(int row, int column)
1793
1794 This signal is emitted whenever a cell in the table is pressed.
1795 The \a row and \a column specified is the cell that was pressed.
1796*/
1797
1798/*!
1799 \since 4.1
1800 \fn void QTableWidget::cellClicked(int row, int column)
1801
1802 This signal is emitted whenever a cell in the table is clicked.
1803 The \a row and \a column specified is the cell that was clicked.
1804*/
1805
1806/*!
1807 \since 4.1
1808 \fn void QTableWidget::cellDoubleClicked(int row, int column)
1809
1810 This signal is emitted whenever a cell in the table is double
1811 clicked. The \a row and \a column specified is the cell that was
1812 double clicked.
1813*/
1814
1815/*!
1816 \since 4.1
1817 \fn void QTableWidget::cellActivated(int row, int column)
1818
1819 This signal is emitted when the cell specified by \a row and \a column
1820 has been activated
1821*/
1822
1823/*!
1824 \since 4.1
1825 \fn void QTableWidget::cellEntered(int row, int column)
1826
1827 This signal is emitted when the mouse cursor enters a cell. The
1828 cell is specified by \a row and \a column.
1829
1830 This signal is only emitted when mouseTracking is turned on, or when a
1831 mouse button is pressed while moving into an item.
1832*/
1833
1834/*!
1835 \since 4.1
1836 \fn void QTableWidget::cellChanged(int row, int column)
1837
1838 This signal is emitted whenever the data of the item in the cell
1839 specified by \a row and \a column has changed.
1840*/
1841
1842/*!
1843 \since 4.1
1844 \fn void QTableWidget::currentCellChanged(int currentRow, int currentColumn, int previousRow, int previousColumn)
1845
1846 This signal is emitted whenever the current cell changes. The cell
1847 specified by \a previousRow and \a previousColumn is the cell that
1848 previously had the focus, the cell specified by \a currentRow and \a
1849 currentColumn is the new current cell.
1850*/
1851
1852/*!
1853 \since 4.3
1854 \fn void QTableWidget::removeCellWidget(int row, int column)
1855
1856 Removes the widget set on the cell indicated by \a row and \a column.
1857*/
1858
1859/*!
1860 \fn QTableWidgetItem *QTableWidget::itemAt(int ax, int ay) const
1861
1862 Returns the item at the position equivalent to QPoint(\a{ax}, \a{ay}) in
1863 the table widget's coordinate system, or returns \nullptr if the specified point
1864 is not covered by an item in the table widget.
1865
1866 \sa item()
1867*/
1868
1869/*!
1870 \enum QTableWidgetItem::ItemType
1871
1872 This enum describes the types that are used to describe table widget items.
1873
1874 \value Type The default type for table widget items.
1875 \value UserType The minimum value for custom types. Values below UserType are
1876 reserved by Qt.
1877
1878 You can define new user types in QTableWidgetItem subclasses to ensure that
1879 custom items are treated specially.
1880
1881 \sa type()
1882*/
1883
1884/*!
1885 \fn int QTableWidgetItem::type() const
1886
1887 Returns the type passed to the QTableWidgetItem constructor.
1888*/
1889
1890/*!
1891 Creates a new table view with the given \a parent.
1892*/
1893QTableWidget::QTableWidget(QWidget *parent)
1894 : QTableView(*new QTableWidgetPrivate, parent)
1895{
1896 Q_D(QTableWidget);
1897 QTableView::setModel(new QTableModel(0, 0, this));
1898 d->setup();
1899}
1900
1901/*!
1902 Creates a new table view with the given \a rows and \a columns, and with the given \a parent.
1903*/
1904QTableWidget::QTableWidget(int rows, int columns, QWidget *parent)
1905 : QTableView(*new QTableWidgetPrivate, parent)
1906{
1907 Q_D(QTableWidget);
1908 QTableView::setModel(new QTableModel(rows, columns, this));
1909 d->setup();
1910}
1911
1912/*!
1913 Destroys this QTableWidget.
1914*/
1915QTableWidget::~QTableWidget()
1916{
1917}
1918
1919/*!
1920 Sets the number of rows in this table's model to \a rows. If
1921 this is less than rowCount(), the data in the unwanted rows
1922 is discarded.
1923
1924 \sa setColumnCount()
1925*/
1926void QTableWidget::setRowCount(int rows)
1927{
1928 Q_D(QTableWidget);
1929 d->tableModel()->setRowCount(rows);
1930}
1931
1932/*!
1933 Returns the number of rows.
1934*/
1935
1936int QTableWidget::rowCount() const
1937{
1938 Q_D(const QTableWidget);
1939 return d->model->rowCount();
1940}
1941
1942/*!
1943 Sets the number of columns in this table's model to \a columns. If
1944 this is less than columnCount(), the data in the unwanted columns
1945 is discarded.
1946
1947 \sa setRowCount()
1948*/
1949void QTableWidget::setColumnCount(int columns)
1950{
1951 Q_D(QTableWidget);
1952 d->tableModel()->setColumnCount(columns);
1953}
1954
1955/*!
1956 Returns the number of columns.
1957*/
1958
1959int QTableWidget::columnCount() const
1960{
1961 Q_D(const QTableWidget);
1962 return d->model->columnCount();
1963}
1964
1965/*!
1966 Returns the row for the \a item.
1967*/
1968int QTableWidget::row(const QTableWidgetItem *item) const
1969{
1970 Q_D(const QTableWidget);
1971 return d->tableModel()->index(item).row();
1972}
1973
1974/*!
1975 Returns the column for the \a item.
1976*/
1977int QTableWidget::column(const QTableWidgetItem *item) const
1978{
1979 Q_D(const QTableWidget);
1980 return d->tableModel()->index(item).column();
1981}
1982
1983
1984/*!
1985 Returns the item for the given \a row and \a column if one has been set; otherwise
1986 returns \nullptr.
1987
1988 \sa setItem()
1989*/
1990QTableWidgetItem *QTableWidget::item(int row, int column) const
1991{
1992 Q_D(const QTableWidget);
1993 return d->tableModel()->item(row, column);
1994}
1995
1996/*!
1997 Sets the item for the given \a row and \a column to \a item.
1998
1999 The table takes ownership of the item.
2000
2001 Note that if sorting is enabled (see
2002 \l{QTableView::sortingEnabled} {sortingEnabled}) and \a column is
2003 the current sort column, the \a row will be moved to the sorted
2004 position determined by \a item.
2005
2006 If you want to set several items of a particular row (say, by
2007 calling setItem() in a loop), you may want to turn off sorting
2008 before doing so, and turn it back on afterwards; this will allow
2009 you to use the same \a row argument for all items in the same row
2010 (i.e. setItem() will not move the row).
2011
2012 \sa item(), takeItem()
2013*/
2014void QTableWidget::setItem(int row, int column, QTableWidgetItem *item)
2015{
2016 Q_D(QTableWidget);
2017 if (item) {
2018 if (Q_UNLIKELY(item->view)) {
2019 qWarning("QTableWidget: cannot insert an item that is already owned by another QTableWidget");
2020 } else {
2021 item->view = this;
2022 d->tableModel()->setItem(row, column, item);
2023 }
2024 } else {
2025 delete takeItem(row, column);
2026 }
2027}
2028
2029/*!
2030 Removes the item at \a row and \a column from the table without deleting it.
2031*/
2032QTableWidgetItem *QTableWidget::takeItem(int row, int column)
2033{
2034 Q_D(QTableWidget);
2035 QTableWidgetItem *item = d->tableModel()->takeItem(row, column);
2036 if (item)
2037 item->view = 0;
2038 return item;
2039}
2040
2041/*!
2042 Returns the vertical header item for row \a row.
2043*/
2044QTableWidgetItem *QTableWidget::verticalHeaderItem(int row) const
2045{
2046 Q_D(const QTableWidget);
2047 return d->tableModel()->verticalHeaderItem(row);
2048}
2049
2050/*!
2051 Sets the vertical header item for row \a row to \a item.
2052*/
2053void QTableWidget::setVerticalHeaderItem(int row, QTableWidgetItem *item)
2054{
2055 Q_D(QTableWidget);
2056 if (item) {
2057 item->view = this;
2058 d->tableModel()->setVerticalHeaderItem(row, item);
2059 } else {
2060 delete takeVerticalHeaderItem(row);
2061 }
2062}
2063
2064/*!
2065 \since 4.1
2066 Removes the vertical header item at \a row from the header without deleting it.
2067*/
2068QTableWidgetItem *QTableWidget::takeVerticalHeaderItem(int row)
2069{
2070 Q_D(QTableWidget);
2071 QTableWidgetItem *itm = d->tableModel()->takeVerticalHeaderItem(row);
2072 if (itm)
2073 itm->view = 0;
2074 return itm;
2075}
2076
2077/*!
2078 Returns the horizontal header item for column, \a column, if one has been
2079 set; otherwise returns \nullptr.
2080*/
2081QTableWidgetItem *QTableWidget::horizontalHeaderItem(int column) const
2082{
2083 Q_D(const QTableWidget);
2084 return d->tableModel()->horizontalHeaderItem(column);
2085}
2086
2087/*!
2088 Sets the horizontal header item for column \a column to \a item.
2089 If necessary, the column count is increased to fit the item.
2090 The previous header item (if there was one) is deleted.
2091*/
2092void QTableWidget::setHorizontalHeaderItem(int column, QTableWidgetItem *item)
2093{
2094 Q_D(QTableWidget);
2095 if (item) {
2096 item->view = this;
2097 d->tableModel()->setHorizontalHeaderItem(column, item);
2098 } else {
2099 delete takeHorizontalHeaderItem(column);
2100 }
2101}
2102
2103/*!
2104 \since 4.1
2105 Removes the horizontal header item at \a column from the header without deleting it.
2106*/
2107QTableWidgetItem *QTableWidget::takeHorizontalHeaderItem(int column)
2108{
2109 Q_D(QTableWidget);
2110 QTableWidgetItem *itm = d->tableModel()->takeHorizontalHeaderItem(column);
2111 if (itm)
2112 itm->view = 0;
2113 return itm;
2114}
2115
2116/*!
2117 Sets the vertical header labels using \a labels.
2118*/
2119void QTableWidget::setVerticalHeaderLabels(const QStringList &labels)
2120{
2121 Q_D(QTableWidget);
2122 QTableModel *model = d->tableModel();
2123 QTableWidgetItem *item = 0;
2124 for (int i = 0; i < model->rowCount() && i < labels.count(); ++i) {
2125 item = model->verticalHeaderItem(i);
2126 if (!item) {
2127 item = model->createItem();
2128 setVerticalHeaderItem(i, item);
2129 }
2130 item->setText(labels.at(i));
2131 }
2132}
2133
2134/*!
2135 Sets the horizontal header labels using \a labels.
2136*/
2137void QTableWidget::setHorizontalHeaderLabels(const QStringList &labels)
2138{
2139 Q_D(QTableWidget);
2140 QTableModel *model = d->tableModel();
2141 QTableWidgetItem *item = 0;
2142 for (int i = 0; i < model->columnCount() && i < labels.count(); ++i) {
2143 item = model->horizontalHeaderItem(i);
2144 if (!item) {
2145 item = model->createItem();
2146 setHorizontalHeaderItem(i, item);
2147 }
2148 item->setText(labels.at(i));
2149 }
2150}
2151
2152/*!
2153 Returns the row of the current item.
2154
2155 \sa currentColumn(), setCurrentCell()
2156*/
2157int QTableWidget::currentRow() const
2158{
2159 return currentIndex().row();
2160}
2161
2162/*!
2163 Returns the column of the current item.
2164
2165 \sa currentRow(), setCurrentCell()
2166*/
2167int QTableWidget::currentColumn() const
2168{
2169 return currentIndex().column();
2170}
2171
2172/*!
2173 Returns the current item.
2174
2175 \sa setCurrentItem()
2176*/
2177QTableWidgetItem *QTableWidget::currentItem() const
2178{
2179 Q_D(const QTableWidget);
2180 return d->tableModel()->item(currentIndex());
2181}
2182
2183/*!
2184 Sets the current item to \a item.
2185
2186 Unless the selection mode is \l{QAbstractItemView::}{NoSelection},
2187 the item is also selected.
2188
2189 \sa currentItem(), setCurrentCell()
2190*/
2191void QTableWidget::setCurrentItem(QTableWidgetItem *item)
2192{
2193 Q_D(QTableWidget);
2194 setCurrentIndex(d->tableModel()->index(item));
2195}
2196
2197/*!
2198 \since 4.4
2199
2200 Sets the current item to be \a item, using the given \a command.
2201
2202 \sa currentItem(), setCurrentCell()
2203*/
2204void QTableWidget::setCurrentItem(QTableWidgetItem *item, QItemSelectionModel::SelectionFlags command)
2205{
2206 Q_D(QTableWidget);
2207 d->selectionModel->setCurrentIndex(d->tableModel()->index(item), command);
2208}
2209
2210/*!
2211 \since 4.1
2212
2213 Sets the current cell to be the cell at position (\a row, \a
2214 column).
2215
2216 Depending on the current \l{QAbstractItemView::SelectionMode}{selection mode},
2217 the cell may also be selected.
2218
2219 \sa setCurrentItem(), currentRow(), currentColumn()
2220*/
2221void QTableWidget::setCurrentCell(int row, int column)
2222{
2223 setCurrentIndex(model()->index(row, column, QModelIndex()));
2224}
2225
2226/*!
2227 \since 4.4
2228
2229 Sets the current cell to be the cell at position (\a row, \a
2230 column), using the given \a command.
2231
2232 \sa setCurrentItem(), currentRow(), currentColumn()
2233*/
2234void QTableWidget::setCurrentCell(int row, int column, QItemSelectionModel::SelectionFlags command)
2235{
2236 Q_D(QTableWidget);
2237 d->selectionModel->setCurrentIndex(model()->index(row, column, QModelIndex()), command);
2238}
2239
2240/*!
2241 Sorts all the rows in the table widget based on \a column and \a order.
2242*/
2243void QTableWidget::sortItems(int column, Qt::SortOrder order)
2244{
2245 Q_D(QTableWidget);
2246 d->model->sort(column, order);
2247 horizontalHeader()->setSortIndicator(column, order);
2248}
2249
2250/*!
2251 \internal
2252*/
2253void QTableWidget::setSortingEnabled(bool enable)
2254{
2255 QTableView::setSortingEnabled(enable);
2256}
2257
2258/*!
2259 \internal
2260*/
2261bool QTableWidget::isSortingEnabled() const
2262{
2263 return QTableView::isSortingEnabled();
2264}
2265
2266/*!
2267 Starts editing the \a item if it is editable.
2268*/
2269
2270void QTableWidget::editItem(QTableWidgetItem *item)
2271{
2272 Q_D(QTableWidget);
2273 if (!item)
2274 return;
2275 edit(d->tableModel()->index(item));
2276}
2277
2278/*!
2279 Opens an editor for the give \a item. The editor remains open after editing.
2280
2281 \sa closePersistentEditor(), isPersistentEditorOpen()
2282*/
2283void QTableWidget::openPersistentEditor(QTableWidgetItem *item)
2284{
2285 Q_D(QTableWidget);
2286 if (!item)
2287 return;
2288 QModelIndex index = d->tableModel()->index(item);
2289 QAbstractItemView::openPersistentEditor(index);
2290}
2291
2292/*!
2293 Closes the persistent editor for \a item.
2294
2295 \sa openPersistentEditor(), isPersistentEditorOpen()
2296*/
2297void QTableWidget::closePersistentEditor(QTableWidgetItem *item)
2298{
2299 Q_D(QTableWidget);
2300 if (!item)
2301 return;
2302 QModelIndex index = d->tableModel()->index(item);
2303 QAbstractItemView::closePersistentEditor(index);
2304}
2305
2306/*!
2307 \since 5.10
2308
2309 Returns whether a persistent editor is open for item \a item.
2310
2311 \sa openPersistentEditor(), closePersistentEditor()
2312*/
2313bool QTableWidget::isPersistentEditorOpen(QTableWidgetItem *item) const
2314{
2315 Q_D(const QTableWidget);
2316 const QModelIndex index = d->tableModel()->index(item);
2317 return QAbstractItemView::isPersistentEditorOpen(index);
2318}
2319
2320/*!
2321 \since 4.1
2322
2323 Returns the widget displayed in the cell in the given \a row and \a column.
2324
2325 \note The table takes ownership of the widget.
2326
2327 \sa setCellWidget()
2328*/
2329QWidget *QTableWidget::cellWidget(int row, int column) const
2330{
2331 QModelIndex index = model()->index(row, column, QModelIndex());
2332 return QAbstractItemView::indexWidget(index);
2333}
2334
2335/*!
2336 \since 4.1
2337
2338 Sets the given \a widget to be displayed in the cell in the given \a row
2339 and \a column, passing the ownership of the widget to the table.
2340
2341 If cell widget A is replaced with cell widget B, cell widget A will be
2342 deleted. For example, in the code snippet below, the QLineEdit object will
2343 be deleted.
2344
2345 \snippet code/src_gui_itemviews_qtablewidget.cpp 0
2346
2347 \sa cellWidget()
2348*/
2349void QTableWidget::setCellWidget(int row, int column, QWidget *widget)
2350{
2351 QModelIndex index = model()->index(row, column, QModelIndex());
2352 QAbstractItemView::setIndexWidget(index, widget);
2353}
2354
2355#if QT_DEPRECATED_SINCE(5, 13)
2356/*!
2357 Returns \c true if the \a item is selected, otherwise returns \c false.
2358
2359 \obsolete
2360
2361 This function is deprecated. Use \l{QTableWidgetItem::isSelected()} instead.
2362*/
2363
2364bool QTableWidget::isItemSelected(const QTableWidgetItem *item) const
2365{
2366 return ((item && item->tableWidget() == this) ? item->isSelected() : false);
2367}
2368
2369/*!
2370 Selects or deselects \a item depending on \a select.
2371
2372 \obsolete
2373
2374 This function is deprecated. Use \l{QTableWidgetItem::setSelected()} instead.
2375*/
2376void QTableWidget::setItemSelected(const QTableWidgetItem *item, bool select)
2377{
2378 if (item && item->tableWidget() == this)
2379 const_cast<QTableWidgetItem*>(item)->setSelected(select);
2380}
2381#endif
2382
2383/*!
2384 Selects or deselects the \a range depending on \a select.
2385*/
2386void QTableWidget::setRangeSelected(const QTableWidgetSelectionRange &range, bool select)
2387{
2388 if (!model()->hasIndex(range.topRow(), range.leftColumn(), rootIndex()) ||
2389 !model()->hasIndex(range.bottomRow(), range.rightColumn(), rootIndex()))
2390 return;
2391
2392 QModelIndex topLeft = model()->index(range.topRow(), range.leftColumn(), rootIndex());
2393 QModelIndex bottomRight = model()->index(range.bottomRow(), range.rightColumn(), rootIndex());
2394
2395 selectionModel()->select(QItemSelection(topLeft, bottomRight),
2396 select ? QItemSelectionModel::Select : QItemSelectionModel::Deselect);
2397}
2398
2399/*!
2400 Returns a list of all selected ranges.
2401
2402 \sa QTableWidgetSelectionRange
2403*/
2404
2405QList<QTableWidgetSelectionRange> QTableWidget::selectedRanges() const
2406{
2407 const QList<QItemSelectionRange> ranges = selectionModel()->selection();
2408 QList<QTableWidgetSelectionRange> result;
2409 const int rangesCount = ranges.count();
2410 result.reserve(rangesCount);
2411 for (int i = 0; i < rangesCount; ++i)
2412 result.append(QTableWidgetSelectionRange(ranges.at(i).top(),
2413 ranges.at(i).left(),
2414 ranges.at(i).bottom(),
2415 ranges.at(i).right()));
2416 return result;
2417}
2418
2419/*!
2420 Returns a list of all selected items.
2421
2422 This function returns a list of pointers to the contents of the
2423 selected cells. Use the selectedIndexes() function to retrieve the
2424 complete selection \e including empty cells.
2425
2426 \sa selectedIndexes()
2427*/
2428
2429QList<QTableWidgetItem*> QTableWidget::selectedItems() const
2430{
2431 Q_D(const QTableWidget);
2432 const QModelIndexList indexes = selectionModel()->selectedIndexes();
2433 QList<QTableWidgetItem*> items;
2434 for (const auto &index : indexes) {
2435 if (isIndexHidden(index))
2436 continue;
2437 QTableWidgetItem *item = d->tableModel()->item(index);
2438 if (item)
2439 items.append(item);
2440 }
2441 return items;
2442}
2443
2444/*!
2445 Finds items that matches the \a text using the given \a flags.
2446*/
2447
2448QList<QTableWidgetItem*> QTableWidget::findItems(const QString &text, Qt::MatchFlags flags) const
2449{
2450 Q_D(const QTableWidget);
2451 QModelIndexList indexes;
2452 for (int column = 0; column < columnCount(); ++column)
2453 indexes += d->model->match(model()->index(0, column, QModelIndex()),
2454 Qt::DisplayRole, text, -1, flags);
2455 QList<QTableWidgetItem*> items;
2456 const int indexCount = indexes.size();
2457 items.reserve(indexCount);
2458 for (int i = 0; i < indexCount; ++i)
2459 items.append(d->tableModel()->item(indexes.at(i)));
2460 return items;
2461}
2462
2463/*!
2464 Returns the visual row of the given \a logicalRow.
2465*/
2466
2467int QTableWidget::visualRow(int logicalRow) const
2468{
2469 return verticalHeader()->visualIndex(logicalRow);
2470}
2471
2472/*!
2473 Returns the visual column of the given \a logicalColumn.
2474*/
2475
2476int QTableWidget::visualColumn(int logicalColumn) const
2477{
2478 return horizontalHeader()->visualIndex(logicalColumn);
2479}
2480
2481/*!
2482 \fn QTableWidgetItem *QTableWidget::itemAt(const QPoint &point) const
2483
2484 Returns a pointer to the item at the given \a point, or returns \nullptr if
2485 \a point is not covered by an item in the table widget.
2486
2487 \sa item()
2488*/
2489
2490QTableWidgetItem *QTableWidget::itemAt(const QPoint &p) const
2491{
2492 Q_D(const QTableWidget);
2493 return d->tableModel()->item(indexAt(p));
2494}
2495
2496/*!
2497 Returns the rectangle on the viewport occupied by the item at \a item.
2498*/
2499QRect QTableWidget::visualItemRect(const QTableWidgetItem *item) const
2500{
2501 Q_D(const QTableWidget);
2502 if (!item)
2503 return QRect();
2504 QModelIndex index = d->tableModel()->index(const_cast<QTableWidgetItem*>(item));
2505 Q_ASSERT(index.isValid());
2506 return visualRect(index);
2507}
2508
2509/*!
2510 Scrolls the view if necessary to ensure that the \a item is visible.
2511 The \a hint parameter specifies more precisely where the
2512 \a item should be located after the operation.
2513*/
2514
2515void QTableWidget::scrollToItem(const QTableWidgetItem *item, QAbstractItemView::ScrollHint hint)
2516{
2517 Q_D(QTableWidget);
2518 if (!item)
2519 return;
2520 QModelIndex index = d->tableModel()->index(const_cast<QTableWidgetItem*>(item));
2521 Q_ASSERT(index.isValid());
2522 QTableView::scrollTo(index, hint);
2523}
2524
2525/*!
2526 Returns the item prototype used by the table.
2527
2528 \sa setItemPrototype()
2529*/
2530const QTableWidgetItem *QTableWidget::itemPrototype() const
2531{
2532 Q_D(const QTableWidget);
2533 return d->tableModel()->itemPrototype();
2534}
2535
2536/*!
2537 Sets the item prototype for the table to the specified \a item.
2538
2539 The table widget will use the item prototype clone function when it needs
2540 to create a new table item. For example when the user is editing
2541 in an empty cell. This is useful when you have a QTableWidgetItem
2542 subclass and want to make sure that QTableWidget creates instances of
2543 your subclass.
2544
2545 The table takes ownership of the prototype.
2546
2547 \sa itemPrototype()
2548*/
2549void QTableWidget::setItemPrototype(const QTableWidgetItem *item)
2550{
2551 Q_D(QTableWidget);
2552 d->tableModel()->setItemPrototype(item);
2553}
2554
2555/*!
2556 Inserts an empty row into the table at \a row.
2557*/
2558void QTableWidget::insertRow(int row)
2559{
2560 Q_D(QTableWidget);
2561 d->tableModel()->insertRows(row);
2562}
2563
2564/*!
2565 Inserts an empty column into the table at \a column.
2566*/
2567void QTableWidget::insertColumn(int column)
2568{
2569 Q_D(QTableWidget);
2570 d->tableModel()->insertColumns(column);
2571}
2572
2573/*!
2574 Removes the row \a row and all its items from the table.
2575*/
2576void QTableWidget::removeRow(int row)
2577{
2578 Q_D(QTableWidget);
2579 d->tableModel()->removeRows(row);
2580}
2581
2582/*!
2583 Removes the column \a column and all its items from the table.
2584*/
2585void QTableWidget::removeColumn(int column)
2586{
2587 Q_D(QTableWidget);
2588 d->tableModel()->removeColumns(column);
2589}
2590
2591/*!
2592 Removes all items in the view.
2593 This will also remove all selections and headers.
2594 If you don't want to remove the headers, use
2595 QTableWidget::clearContents().
2596 The table dimensions stay the same.
2597*/
2598
2599void QTableWidget::clear()
2600{
2601 Q_D(QTableWidget);
2602 selectionModel()->clear();
2603 d->tableModel()->clear();
2604}
2605
2606/*!
2607 \since 4.2
2608
2609 Removes all items not in the headers from the view.
2610 This will also remove all selections.
2611 The table dimensions stay the same.
2612*/
2613void QTableWidget::clearContents()
2614{
2615 Q_D(QTableWidget);
2616 selectionModel()->clear();
2617 d->tableModel()->clearContents();
2618}
2619
2620/*!
2621 Returns a list of MIME types that can be used to describe a list of
2622 tablewidget items.
2623
2624 \sa mimeData()
2625*/
2626QStringList QTableWidget::mimeTypes() const
2627{
2628 return d_func()->tableModel()->QAbstractTableModel::mimeTypes();
2629}
2630
2631/*!
2632 Returns an object that contains a serialized description of the specified
2633 \a items. The format used to describe the items is obtained from the
2634 mimeTypes() function.
2635
2636 If the list of items is empty, \nullptr is returned rather than a
2637 serialized empty list.
2638*/
2639#if QT_VERSION >= QT_VERSION_CHECK(6,0,0)
2640QMimeData *QTableWidget::mimeData(const QList<QTableWidgetItem *> &items) const
2641#else
2642QMimeData *QTableWidget::mimeData(const QList<QTableWidgetItem*> items) const
2643#endif
2644{
2645 Q_D(const QTableWidget);
2646
2647 QModelIndexList &cachedIndexes = d->tableModel()->cachedIndexes;
2648
2649 // if non empty, it's called from the model's own mimeData
2650 if (cachedIndexes.isEmpty()) {
2651 cachedIndexes.reserve(items.count());
2652 for (QTableWidgetItem *item : items)
2653 cachedIndexes << indexFromItem(item);
2654
2655 QMimeData *result = d->tableModel()->internalMimeData();
2656
2657 cachedIndexes.clear();
2658 return result;
2659 }
2660
2661 return d->tableModel()->internalMimeData();
2662}
2663
2664/*!
2665 Handles the \a data supplied by a drag and drop operation that ended with
2666 the given \a action in the given \a row and \a column.
2667 Returns \c true if the data and action can be handled by the model;
2668 otherwise returns \c false.
2669
2670 \sa supportedDropActions()
2671*/
2672bool QTableWidget::dropMimeData(int row, int column, const QMimeData *data, Qt::DropAction action)
2673{
2674 QModelIndex idx;
2675#if QT_CONFIG(draganddrop)
2676 if (dropIndicatorPosition() == QAbstractItemView::OnItem) {
2677 // QAbstractTableModel::dropMimeData will overwrite on the index if row == -1 and column == -1
2678 idx = model()->index(row, column);
2679 row = -1;
2680 column = -1;
2681 }
2682#endif
2683 return d_func()->tableModel()->QAbstractTableModel::dropMimeData(data, action , row, column, idx);
2684}
2685
2686/*!
2687 Returns the drop actions supported by this view.
2688
2689 \sa Qt::DropActions
2690*/
2691Qt::DropActions QTableWidget::supportedDropActions() const
2692{
2693 return d_func()->tableModel()->QAbstractTableModel::supportedDropActions() | Qt::MoveAction;
2694}
2695
2696/*!
2697 Returns a list of pointers to the items contained in the \a data object.
2698 If the object was not created by a QTreeWidget in the same process, the list
2699 is empty.
2700
2701*/
2702QList<QTableWidgetItem*> QTableWidget::items(const QMimeData *data) const
2703{
2704 const QTableWidgetMimeData *twd = qobject_cast<const QTableWidgetMimeData*>(data);
2705 if (twd)
2706 return twd->items;
2707 return QList<QTableWidgetItem*>();
2708}
2709
2710/*!
2711 Returns the QModelIndex associated with the given \a item.
2712
2713 \note In Qt versions prior to 5.10, this function took a non-\c{const} \a item.
2714*/
2715
2716QModelIndex QTableWidget::indexFromItem(const QTableWidgetItem *item) const
2717{
2718 Q_D(const QTableWidget);
2719 return d->tableModel()->index(item);
2720}
2721
2722#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
2723/*!
2724 \internal
2725 \obsolete
2726 \overload
2727*/
2728QModelIndex QTableWidget::indexFromItem(QTableWidgetItem *item) const
2729{
2730 return indexFromItem(const_cast<const QTableWidgetItem *>(item));
2731}
2732#endif
2733
2734/*!
2735 Returns a pointer to the QTableWidgetItem associated with the given \a index.
2736*/
2737
2738QTableWidgetItem *QTableWidget::itemFromIndex(const QModelIndex &index) const
2739{
2740 Q_D(const QTableWidget);
2741 return d->tableModel()->item(index);
2742}
2743
2744/*!
2745 \internal
2746*/
2747void QTableWidget::setModel(QAbstractItemModel * /*model*/)
2748{
2749 Q_ASSERT(!"QTableWidget::setModel() - Changing the model of the QTableWidget is not allowed.");
2750}
2751
2752/*! \reimp */
2753bool QTableWidget::event(QEvent *e)
2754{
2755 return QTableView::event(e);
2756}
2757
2758#if QT_CONFIG(draganddrop)
2759/*! \reimp */
2760void QTableWidget::dropEvent(QDropEvent *event) {
2761 Q_D(QTableWidget);
2762 if (event->source() == this && (event->dropAction() == Qt::MoveAction ||
2763 dragDropMode() == QAbstractItemView::InternalMove)) {
2764 QModelIndex topIndex;
2765 int col = -1;
2766 int row = -1;
2767 if (d->dropOn(event, &row, &col, &topIndex)) {
2768 const QModelIndexList indexes = selectedIndexes();
2769 int top = INT_MAX;
2770 int left = INT_MAX;
2771 for (const auto &index : indexes) {
2772 top = qMin(index.row(), top);
2773 left = qMin(index.column(), left);
2774 }
2775
2776 QList<QTableWidgetItem *> taken;
2777 const int indexesCount = indexes.count();
2778 taken.reserve(indexesCount);
2779 for (const auto &index : indexes)
2780 taken.append(takeItem(index.row(), index.column()));
2781
2782 for (const auto &index : indexes) {
2783 int r = index.row() - top + topIndex.row();
2784 int c = index.column() - left + topIndex.column();
2785 setItem(r, c, taken.takeFirst());
2786 }
2787
2788 event->accept();
2789 // Don't want QAbstractItemView to delete it because it was "moved" we already did it
2790 event->setDropAction(Qt::CopyAction);
2791 }
2792 }
2793
2794 QTableView::dropEvent(event);
2795}
2796#endif
2797
2798QT_END_NAMESPACE
2799
2800#include "moc_qtablewidget.cpp"
2801#include "moc_qtablewidget_p.cpp"
2802