source: trunk/src/gui/itemviews/qtablewidget.cpp@ 1147

Last change on this file since 1147 was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

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