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

Last change on this file since 123 was 2, checked in by Dmitry A. Kuminov, 16 years ago

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

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