2808 lines
78 KiB
C++
2808 lines
78 KiB
C++
/****************************************************************************
|
|
**
|
|
** Copyright (C) 2016 The Qt Company Ltd.
|
|
** Contact: https://www.qt.io/licensing/
|
|
**
|
|
** This file is part of the QtWidgets module of the Qt Toolkit.
|
|
**
|
|
** $QT_BEGIN_LICENSE:LGPL$
|
|
** Commercial License Usage
|
|
** Licensees holding valid commercial Qt licenses may use this file in
|
|
** accordance with the commercial license agreement provided with the
|
|
** Software or, alternatively, in accordance with the terms contained in
|
|
** a written agreement between you and The Qt Company. For licensing terms
|
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
|
** information use the contact form at https://www.qt.io/contact-us.
|
|
**
|
|
** GNU Lesser General Public License Usage
|
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
|
** General Public License version 3 as published by the Free Software
|
|
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
|
** packaging of this file. Please review the following information to
|
|
** ensure the GNU Lesser General Public License version 3 requirements
|
|
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
|
**
|
|
** GNU General Public License Usage
|
|
** Alternatively, this file may be used under the terms of the GNU
|
|
** General Public License version 2.0 or (at your option) the GNU General
|
|
** Public license version 3 or any later version approved by the KDE Free
|
|
** Qt Foundation. The licenses are as published by the Free Software
|
|
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
|
|
** included in the packaging of this file. Please review the following
|
|
** information to ensure the GNU General Public License requirements will
|
|
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
|
|
** https://www.gnu.org/licenses/gpl-3.0.html.
|
|
**
|
|
** $QT_END_LICENSE$
|
|
**
|
|
****************************************************************************/
|
|
|
|
#include "qtablewidget.h"
|
|
|
|
#include <qitemdelegate.h>
|
|
#include <qpainter.h>
|
|
#include <private/qtablewidget_p.h>
|
|
|
|
#include <algorithm>
|
|
|
|
QT_BEGIN_NAMESPACE
|
|
|
|
QTableModel::QTableModel(int rows, int columns, QTableWidget *parent)
|
|
: QAbstractTableModel(parent),
|
|
prototype(nullptr),
|
|
tableItems(rows * columns, 0),
|
|
verticalHeaderItems(rows, 0),
|
|
horizontalHeaderItems(columns, 0)
|
|
{}
|
|
|
|
QTableModel::~QTableModel()
|
|
{
|
|
clear();
|
|
delete prototype;
|
|
}
|
|
|
|
bool QTableModel::insertRows(int row, int count, const QModelIndex &)
|
|
{
|
|
if (count < 1 || row < 0 || row > verticalHeaderItems.count())
|
|
return false;
|
|
|
|
beginInsertRows(QModelIndex(), row, row + count - 1);
|
|
int rc = verticalHeaderItems.count();
|
|
int cc = horizontalHeaderItems.count();
|
|
verticalHeaderItems.insert(row, count, 0);
|
|
if (rc == 0)
|
|
tableItems.resize(cc * count);
|
|
else
|
|
tableItems.insert(tableIndex(row, 0), cc * count, 0);
|
|
endInsertRows();
|
|
return true;
|
|
}
|
|
|
|
bool QTableModel::insertColumns(int column, int count, const QModelIndex &)
|
|
{
|
|
if (count < 1 || column < 0 || column > horizontalHeaderItems.count())
|
|
return false;
|
|
|
|
beginInsertColumns(QModelIndex(), column, column + count - 1);
|
|
int rc = verticalHeaderItems.count();
|
|
int cc = horizontalHeaderItems.count();
|
|
horizontalHeaderItems.insert(column, count, 0);
|
|
if (cc == 0)
|
|
tableItems.resize(rc * count);
|
|
else
|
|
for (int row = 0; row < rc; ++row)
|
|
tableItems.insert(tableIndex(row, column), count, 0);
|
|
endInsertColumns();
|
|
return true;
|
|
}
|
|
|
|
bool QTableModel::removeRows(int row, int count, const QModelIndex &)
|
|
{
|
|
if (count < 1 || row < 0 || row + count > verticalHeaderItems.count())
|
|
return false;
|
|
|
|
beginRemoveRows(QModelIndex(), row, row + count - 1);
|
|
int i = tableIndex(row, 0);
|
|
int n = count * columnCount();
|
|
QTableWidgetItem *oldItem = nullptr;
|
|
for (int j = i; j < n + i; ++j) {
|
|
oldItem = tableItems.at(j);
|
|
if (oldItem)
|
|
oldItem->view = nullptr;
|
|
delete oldItem;
|
|
}
|
|
tableItems.remove(qMax(i, 0), n);
|
|
for (int v = row; v < row + count; ++v) {
|
|
oldItem = verticalHeaderItems.at(v);
|
|
if (oldItem)
|
|
oldItem->view = nullptr;
|
|
delete oldItem;
|
|
}
|
|
verticalHeaderItems.remove(row, count);
|
|
endRemoveRows();
|
|
return true;
|
|
}
|
|
|
|
bool QTableModel::removeColumns(int column, int count, const QModelIndex &)
|
|
{
|
|
if (count < 1 || column < 0 || column + count > horizontalHeaderItems.count())
|
|
return false;
|
|
|
|
beginRemoveColumns(QModelIndex(), column, column + count - 1);
|
|
QTableWidgetItem *oldItem = nullptr;
|
|
for (int row = rowCount() - 1; row >= 0; --row) {
|
|
int i = tableIndex(row, column);
|
|
for (int j = i; j < i + count; ++j) {
|
|
oldItem = tableItems.at(j);
|
|
if (oldItem)
|
|
oldItem->view = nullptr;
|
|
delete oldItem;
|
|
}
|
|
tableItems.remove(i, count);
|
|
}
|
|
for (int h=column; h<column+count; ++h) {
|
|
oldItem = horizontalHeaderItems.at(h);
|
|
if (oldItem)
|
|
oldItem->view = nullptr;
|
|
delete oldItem;
|
|
}
|
|
horizontalHeaderItems.remove(column, count);
|
|
endRemoveColumns();
|
|
return true;
|
|
}
|
|
|
|
void QTableModel::setItem(int row, int column, QTableWidgetItem *item)
|
|
{
|
|
int i = tableIndex(row, column);
|
|
if (i < 0 || i >= tableItems.count())
|
|
return;
|
|
QTableWidgetItem *oldItem = tableItems.at(i);
|
|
if (item == oldItem)
|
|
return;
|
|
|
|
// remove old
|
|
if (oldItem)
|
|
oldItem->view = nullptr;
|
|
delete tableItems.at(i);
|
|
|
|
QTableWidget *view = qobject_cast<QTableWidget*>(QObject::parent());
|
|
|
|
// set new
|
|
if (item)
|
|
item->d->id = i;
|
|
tableItems[i] = item;
|
|
|
|
if (view && view->isSortingEnabled()
|
|
&& view->horizontalHeader()->sortIndicatorSection() == column) {
|
|
// sorted insertion
|
|
Qt::SortOrder order = view->horizontalHeader()->sortIndicatorOrder();
|
|
QVector<QTableWidgetItem*> colItems = columnItems(column);
|
|
if (row < colItems.count())
|
|
colItems.remove(row);
|
|
int sortedRow;
|
|
if (item == nullptr) {
|
|
// move to after all non-0 (sortable) items
|
|
sortedRow = colItems.count();
|
|
} else {
|
|
QVector<QTableWidgetItem*>::iterator it;
|
|
it = sortedInsertionIterator(colItems.begin(), colItems.end(), order, item);
|
|
sortedRow = qMax((int)(it - colItems.begin()), 0);
|
|
}
|
|
if (sortedRow != row) {
|
|
emit layoutAboutToBeChanged({}, QAbstractItemModel::VerticalSortHint);
|
|
// move the items @ row to sortedRow
|
|
int cc = columnCount();
|
|
QVector<QTableWidgetItem*> rowItems(cc);
|
|
for (int j = 0; j < cc; ++j)
|
|
rowItems[j] = tableItems.at(tableIndex(row, j));
|
|
tableItems.remove(tableIndex(row, 0), cc);
|
|
tableItems.insert(tableIndex(sortedRow, 0), cc, 0);
|
|
for (int j = 0; j < cc; ++j)
|
|
tableItems[tableIndex(sortedRow, j)] = rowItems.at(j);
|
|
QTableWidgetItem *header = verticalHeaderItems.at(row);
|
|
verticalHeaderItems.remove(row);
|
|
verticalHeaderItems.insert(sortedRow, header);
|
|
// update persistent indexes
|
|
QModelIndexList oldPersistentIndexes = persistentIndexList();
|
|
QModelIndexList newPersistentIndexes = oldPersistentIndexes;
|
|
updateRowIndexes(newPersistentIndexes, row, sortedRow);
|
|
changePersistentIndexList(oldPersistentIndexes,
|
|
newPersistentIndexes);
|
|
|
|
emit layoutChanged({}, QAbstractItemModel::VerticalSortHint);
|
|
return;
|
|
}
|
|
}
|
|
QModelIndex idx = QAbstractTableModel::index(row, column);
|
|
emit dataChanged(idx, idx);
|
|
}
|
|
|
|
QTableWidgetItem *QTableModel::takeItem(int row, int column)
|
|
{
|
|
long i = tableIndex(row, column);
|
|
QTableWidgetItem *itm = tableItems.value(i);
|
|
if (itm) {
|
|
itm->view = nullptr;
|
|
itm->d->id = -1;
|
|
tableItems[i] = 0;
|
|
const QModelIndex ind = index(row, column);
|
|
emit dataChanged(ind, ind);
|
|
}
|
|
return itm;
|
|
}
|
|
|
|
QTableWidgetItem *QTableModel::item(int row, int column) const
|
|
{
|
|
return item(index(row, column));
|
|
}
|
|
|
|
QTableWidgetItem *QTableModel::item(const QModelIndex &index) const
|
|
{
|
|
if (!isValid(index))
|
|
return nullptr;
|
|
return tableItems.at(tableIndex(index.row(), index.column()));
|
|
}
|
|
|
|
void QTableModel::removeItem(QTableWidgetItem *item)
|
|
{
|
|
int i = tableItems.indexOf(item);
|
|
if (i != -1) {
|
|
tableItems[i] = 0;
|
|
QModelIndex idx = index(item);
|
|
emit dataChanged(idx, idx);
|
|
return;
|
|
}
|
|
|
|
i = verticalHeaderItems.indexOf(item);
|
|
|
|
if (i != -1) {
|
|
verticalHeaderItems[i] = 0;
|
|
emit headerDataChanged(Qt::Vertical, i, i);
|
|
return;
|
|
}
|
|
i = horizontalHeaderItems.indexOf(item);
|
|
if (i != -1) {
|
|
horizontalHeaderItems[i] = 0;
|
|
emit headerDataChanged(Qt::Horizontal, i, i);
|
|
return;
|
|
}
|
|
}
|
|
|
|
void QTableModel::setHorizontalHeaderItem(int section, QTableWidgetItem *item)
|
|
{
|
|
if (section < 0 || section >= horizontalHeaderItems.count())
|
|
return;
|
|
QTableWidgetItem *oldItem = horizontalHeaderItems.at(section);
|
|
if (item == oldItem)
|
|
return;
|
|
|
|
if (oldItem)
|
|
oldItem->view = nullptr;
|
|
delete oldItem;
|
|
|
|
QTableWidget *view = qobject_cast<QTableWidget*>(QObject::parent());
|
|
|
|
if (item) {
|
|
item->view = view;
|
|
item->itemFlags = Qt::ItemFlags(int(item->itemFlags)|ItemIsHeaderItem);
|
|
}
|
|
horizontalHeaderItems[section] = item;
|
|
emit headerDataChanged(Qt::Horizontal, section, section);
|
|
}
|
|
|
|
void QTableModel::setVerticalHeaderItem(int section, QTableWidgetItem *item)
|
|
{
|
|
if (section < 0 || section >= verticalHeaderItems.count())
|
|
return;
|
|
QTableWidgetItem *oldItem = verticalHeaderItems.at(section);
|
|
if (item == oldItem)
|
|
return;
|
|
|
|
if (oldItem)
|
|
oldItem->view = nullptr;
|
|
delete oldItem;
|
|
|
|
QTableWidget *view = qobject_cast<QTableWidget*>(QObject::parent());
|
|
|
|
if (item) {
|
|
item->view = view;
|
|
item->itemFlags = Qt::ItemFlags(int(item->itemFlags)|ItemIsHeaderItem);
|
|
}
|
|
verticalHeaderItems[section] = item;
|
|
emit headerDataChanged(Qt::Vertical, section, section);
|
|
}
|
|
|
|
QTableWidgetItem *QTableModel::takeHorizontalHeaderItem(int section)
|
|
{
|
|
if (section < 0 || section >= horizontalHeaderItems.count())
|
|
return nullptr;
|
|
QTableWidgetItem *itm = horizontalHeaderItems.at(section);
|
|
if (itm) {
|
|
itm->view = nullptr;
|
|
itm->itemFlags &= ~ItemIsHeaderItem;
|
|
horizontalHeaderItems[section] = 0;
|
|
}
|
|
return itm;
|
|
}
|
|
|
|
QTableWidgetItem *QTableModel::takeVerticalHeaderItem(int section)
|
|
{
|
|
if (section < 0 || section >= verticalHeaderItems.count())
|
|
return nullptr;
|
|
QTableWidgetItem *itm = verticalHeaderItems.at(section);
|
|
if (itm) {
|
|
itm->view = nullptr;
|
|
itm->itemFlags &= ~ItemIsHeaderItem;
|
|
verticalHeaderItems[section] = 0;
|
|
}
|
|
return itm;
|
|
}
|
|
|
|
QTableWidgetItem *QTableModel::horizontalHeaderItem(int section)
|
|
{
|
|
return horizontalHeaderItems.value(section);
|
|
}
|
|
|
|
QTableWidgetItem *QTableModel::verticalHeaderItem(int section)
|
|
{
|
|
return verticalHeaderItems.value(section);
|
|
}
|
|
|
|
QModelIndex QTableModel::index(const QTableWidgetItem *item) const
|
|
{
|
|
if (!item)
|
|
return QModelIndex();
|
|
int i = -1;
|
|
const int id = item->d->id;
|
|
if (id >= 0 && id < tableItems.count() && tableItems.at(id) == item) {
|
|
i = id;
|
|
} else { // we need to search for the item
|
|
i = tableItems.indexOf(const_cast<QTableWidgetItem*>(item));
|
|
if (i == -1) // not found
|
|
return QModelIndex();
|
|
}
|
|
int row = i / columnCount();
|
|
int col = i % columnCount();
|
|
return QAbstractTableModel::index(row, col);
|
|
}
|
|
|
|
void QTableModel::setRowCount(int rows)
|
|
{
|
|
int rc = verticalHeaderItems.count();
|
|
if (rows < 0 || rc == rows)
|
|
return;
|
|
if (rc < rows)
|
|
insertRows(qMax(rc, 0), rows - rc);
|
|
else
|
|
removeRows(qMax(rows, 0), rc - rows);
|
|
}
|
|
|
|
void QTableModel::setColumnCount(int columns)
|
|
{
|
|
int cc = horizontalHeaderItems.count();
|
|
if (columns < 0 || cc == columns)
|
|
return;
|
|
if (cc < columns)
|
|
insertColumns(qMax(cc, 0), columns - cc);
|
|
else
|
|
removeColumns(qMax(columns, 0), cc - columns);
|
|
}
|
|
|
|
int QTableModel::rowCount(const QModelIndex &parent) const
|
|
{
|
|
return parent.isValid() ? 0 : verticalHeaderItems.count();
|
|
}
|
|
|
|
int QTableModel::columnCount(const QModelIndex &parent) const
|
|
{
|
|
return parent.isValid() ? 0 : horizontalHeaderItems.count();
|
|
}
|
|
|
|
QVariant QTableModel::data(const QModelIndex &index, int role) const
|
|
{
|
|
QTableWidgetItem *itm = item(index);
|
|
if (itm)
|
|
return itm->data(role);
|
|
return QVariant();
|
|
}
|
|
|
|
bool QTableModel::setData(const QModelIndex &index, const QVariant &value, int role)
|
|
{
|
|
if (!index.isValid())
|
|
return false;
|
|
|
|
QTableWidgetItem *itm = item(index);
|
|
if (itm) {
|
|
itm->setData(role, value);
|
|
return true;
|
|
}
|
|
|
|
// don't create dummy table items for empty values
|
|
if (!value.isValid())
|
|
return false;
|
|
|
|
QTableWidget *view = qobject_cast<QTableWidget*>(QObject::parent());
|
|
if (!view)
|
|
return false;
|
|
|
|
itm = createItem();
|
|
itm->setData(role, value);
|
|
view->setItem(index.row(), index.column(), itm);
|
|
return true;
|
|
}
|
|
|
|
QMap<int, QVariant> QTableModel::itemData(const QModelIndex &index) const
|
|
{
|
|
QMap<int, QVariant> roles;
|
|
QTableWidgetItem *itm = item(index);
|
|
if (itm) {
|
|
for (int i = 0; i < itm->values.count(); ++i) {
|
|
roles.insert(itm->values.at(i).role,
|
|
itm->values.at(i).value);
|
|
}
|
|
}
|
|
return roles;
|
|
}
|
|
|
|
// reimplemented to ensure that only one dataChanged() signal is emitted
|
|
bool QTableModel::setItemData(const QModelIndex &index, const QMap<int, QVariant> &roles)
|
|
{
|
|
if (!index.isValid())
|
|
return false;
|
|
|
|
QTableWidget *view = qobject_cast<QTableWidget*>(QObject::parent());
|
|
QTableWidgetItem *itm = item(index);
|
|
if (itm) {
|
|
itm->view = nullptr; // prohibits item from calling itemChanged()
|
|
QVector<int> rolesVec;
|
|
for (QMap<int, QVariant>::ConstIterator it = roles.constBegin(); it != roles.constEnd(); ++it) {
|
|
const int role = (it.key() == Qt::EditRole ? Qt::DisplayRole : it.key());
|
|
if (itm->data(role) != it.value()) {
|
|
itm->setData(role, it.value());
|
|
rolesVec += role;
|
|
if (role == Qt::DisplayRole)
|
|
rolesVec += Qt::EditRole;
|
|
}
|
|
}
|
|
itm->view = view;
|
|
if (!rolesVec.isEmpty())
|
|
itemChanged(itm, rolesVec);
|
|
return true;
|
|
}
|
|
|
|
if (!view)
|
|
return false;
|
|
|
|
itm = createItem();
|
|
for (QMap<int, QVariant>::ConstIterator it = roles.constBegin(); it != roles.constEnd(); ++it)
|
|
itm->setData(it.key(), it.value());
|
|
view->setItem(index.row(), index.column(), itm);
|
|
return true;
|
|
}
|
|
|
|
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
|
bool QTableModel::clearItemData(const QModelIndex &index)
|
|
{
|
|
if (!checkIndex(index, CheckIndexOption::IndexIsValid))
|
|
return false;
|
|
QTableWidgetItem *itm = item(index);
|
|
if (!itm)
|
|
return false;
|
|
const auto beginIter = itm->values.cbegin();
|
|
const auto endIter = itm->values.cend();
|
|
if (std::all_of(beginIter, endIter, [](const QWidgetItemData& data) -> bool { return !data.value.isValid(); }))
|
|
return true; //it's already cleared
|
|
itm->values.clear();
|
|
emit dataChanged(index, index, QVector<int>{});
|
|
return true;
|
|
}
|
|
#endif
|
|
|
|
Qt::ItemFlags QTableModel::flags(const QModelIndex &index) const
|
|
{
|
|
if (!index.isValid())
|
|
return Qt::ItemIsDropEnabled;
|
|
if (QTableWidgetItem *itm = item(index))
|
|
return itm->flags();
|
|
return (Qt::ItemIsEditable
|
|
|Qt::ItemIsSelectable
|
|
|Qt::ItemIsUserCheckable
|
|
|Qt::ItemIsEnabled
|
|
|Qt::ItemIsDragEnabled
|
|
|Qt::ItemIsDropEnabled);
|
|
}
|
|
|
|
void QTableModel::sort(int column, Qt::SortOrder order)
|
|
{
|
|
QVector<QPair<QTableWidgetItem*, int> > sortable;
|
|
QVector<int> unsortable;
|
|
|
|
sortable.reserve(rowCount());
|
|
unsortable.reserve(rowCount());
|
|
|
|
for (int row = 0; row < rowCount(); ++row) {
|
|
if (QTableWidgetItem *itm = item(row, column))
|
|
sortable.append(QPair<QTableWidgetItem*,int>(itm, row));
|
|
else
|
|
unsortable.append(row);
|
|
}
|
|
|
|
const auto compare = (order == Qt::AscendingOrder ? &itemLessThan : &itemGreaterThan);
|
|
std::stable_sort(sortable.begin(), sortable.end(), compare);
|
|
|
|
QVector<QTableWidgetItem*> sorted_table(tableItems.count());
|
|
QModelIndexList from;
|
|
QModelIndexList to;
|
|
const int numRows = rowCount();
|
|
const int numColumns = columnCount();
|
|
from.reserve(numRows * numColumns);
|
|
to.reserve(numRows * numColumns);
|
|
for (int i = 0; i < numRows; ++i) {
|
|
int r = (i < sortable.count()
|
|
? sortable.at(i).second
|
|
: unsortable.at(i - sortable.count()));
|
|
for (int c = 0; c < numColumns; ++c) {
|
|
sorted_table[tableIndex(i, c)] = item(r, c);
|
|
from.append(createIndex(r, c));
|
|
to.append(createIndex(i, c));
|
|
}
|
|
}
|
|
|
|
emit layoutAboutToBeChanged({}, QAbstractItemModel::VerticalSortHint);
|
|
|
|
tableItems = sorted_table;
|
|
changePersistentIndexList(from, to); // ### slow
|
|
|
|
emit layoutChanged({}, QAbstractItemModel::VerticalSortHint);
|
|
}
|
|
|
|
/*
|
|
\internal
|
|
|
|
Ensures that rows in the interval [start, end] are
|
|
sorted according to the contents of column \a column
|
|
and the given sort \a order.
|
|
*/
|
|
void QTableModel::ensureSorted(int column, Qt::SortOrder order,
|
|
int start, int end)
|
|
{
|
|
int count = end - start + 1;
|
|
QVector < QPair<QTableWidgetItem*,int> > sorting;
|
|
sorting.reserve(count);
|
|
for (int row = start; row <= end; ++row) {
|
|
QTableWidgetItem *itm = item(row, column);
|
|
if (itm == nullptr) {
|
|
// no more sortable items (all 0-items are
|
|
// at the end of the table when it is sorted)
|
|
break;
|
|
}
|
|
sorting.append(QPair<QTableWidgetItem*,int>(itm, row));
|
|
}
|
|
|
|
const auto compare = (order == Qt::AscendingOrder ? &itemLessThan : &itemGreaterThan);
|
|
std::stable_sort(sorting.begin(), sorting.end(), compare);
|
|
QModelIndexList oldPersistentIndexes, newPersistentIndexes;
|
|
QVector<QTableWidgetItem*> newTable = tableItems;
|
|
QVector<QTableWidgetItem*> newVertical = verticalHeaderItems;
|
|
QVector<QTableWidgetItem*> colItems = columnItems(column);
|
|
QVector<QTableWidgetItem*>::iterator vit = colItems.begin();
|
|
bool changed = false;
|
|
for (int i = 0; i < sorting.count(); ++i) {
|
|
int oldRow = sorting.at(i).second;
|
|
QTableWidgetItem *item = colItems.at(oldRow);
|
|
colItems.remove(oldRow);
|
|
vit = sortedInsertionIterator(vit, colItems.end(), order, item);
|
|
int newRow = qMax((int)(vit - colItems.begin()), 0);
|
|
if ((newRow < oldRow) && !(*item < *colItems.at(oldRow - 1)) && !(*colItems.at(oldRow - 1) < *item))
|
|
newRow = oldRow;
|
|
vit = colItems.insert(vit, item);
|
|
if (newRow != oldRow) {
|
|
if (!changed) {
|
|
emit layoutAboutToBeChanged({}, QAbstractItemModel::VerticalSortHint);
|
|
oldPersistentIndexes = persistentIndexList();
|
|
newPersistentIndexes = oldPersistentIndexes;
|
|
changed = true;
|
|
}
|
|
// move the items @ oldRow to newRow
|
|
int cc = columnCount();
|
|
QVector<QTableWidgetItem*> rowItems(cc);
|
|
for (int j = 0; j < cc; ++j)
|
|
rowItems[j] = newTable.at(tableIndex(oldRow, j));
|
|
newTable.remove(tableIndex(oldRow, 0), cc);
|
|
newTable.insert(tableIndex(newRow, 0), cc, 0);
|
|
for (int j = 0; j < cc; ++j)
|
|
newTable[tableIndex(newRow, j)] = rowItems.at(j);
|
|
QTableWidgetItem *header = newVertical.at(oldRow);
|
|
newVertical.remove(oldRow);
|
|
newVertical.insert(newRow, header);
|
|
// update persistent indexes
|
|
updateRowIndexes(newPersistentIndexes, oldRow, newRow);
|
|
// the index of the remaining rows may have changed
|
|
for (int j = i + 1; j < sorting.count(); ++j) {
|
|
int otherRow = sorting.at(j).second;
|
|
if (oldRow < otherRow && newRow >= otherRow)
|
|
--sorting[j].second;
|
|
else if (oldRow > otherRow && newRow <= otherRow)
|
|
++sorting[j].second;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (changed) {
|
|
tableItems = newTable;
|
|
verticalHeaderItems = newVertical;
|
|
changePersistentIndexList(oldPersistentIndexes,
|
|
newPersistentIndexes);
|
|
emit layoutChanged({}, QAbstractItemModel::VerticalSortHint);
|
|
}
|
|
}
|
|
|
|
/*
|
|
\internal
|
|
|
|
Returns the non-0 items in column \a column.
|
|
*/
|
|
QVector<QTableWidgetItem*> QTableModel::columnItems(int column) const
|
|
{
|
|
QVector<QTableWidgetItem*> items;
|
|
int rc = rowCount();
|
|
items.reserve(rc);
|
|
for (int row = 0; row < rc; ++row) {
|
|
QTableWidgetItem *itm = item(row, column);
|
|
if (itm == nullptr) {
|
|
// no more sortable items (all 0-items are
|
|
// at the end of the table when it is sorted)
|
|
break;
|
|
}
|
|
items.append(itm);
|
|
}
|
|
return items;
|
|
}
|
|
|
|
/*
|
|
\internal
|
|
|
|
Adjusts the row of each index in \a indexes if necessary, given
|
|
that a row of items has been moved from row \a movedFrom to row
|
|
\a movedTo.
|
|
*/
|
|
void QTableModel::updateRowIndexes(QModelIndexList &indexes,
|
|
int movedFromRow, int movedToRow)
|
|
{
|
|
QModelIndexList::iterator it;
|
|
for (it = indexes.begin(); it != indexes.end(); ++it) {
|
|
int oldRow = (*it).row();
|
|
int newRow = oldRow;
|
|
if (oldRow == movedFromRow)
|
|
newRow = movedToRow;
|
|
else if (movedFromRow < oldRow && movedToRow >= oldRow)
|
|
newRow = oldRow - 1;
|
|
else if (movedFromRow > oldRow && movedToRow <= oldRow)
|
|
newRow = oldRow + 1;
|
|
if (newRow != oldRow)
|
|
*it = index(newRow, (*it).column(), (*it).parent());
|
|
}
|
|
}
|
|
|
|
/*
|
|
\internal
|
|
|
|
Returns an iterator to the item where \a item should be
|
|
inserted in the interval (\a begin, \a end) according to
|
|
the given sort \a order.
|
|
*/
|
|
QVector<QTableWidgetItem*>::iterator QTableModel::sortedInsertionIterator(
|
|
const QVector<QTableWidgetItem*>::iterator &begin,
|
|
const QVector<QTableWidgetItem*>::iterator &end,
|
|
Qt::SortOrder order, QTableWidgetItem *item)
|
|
{
|
|
if (order == Qt::AscendingOrder)
|
|
return std::lower_bound(begin, end, item, QTableModelLessThan());
|
|
return std::lower_bound(begin, end, item, QTableModelGreaterThan());
|
|
}
|
|
|
|
bool QTableModel::itemLessThan(const QPair<QTableWidgetItem*,int> &left,
|
|
const QPair<QTableWidgetItem*,int> &right)
|
|
{
|
|
return *(left.first) < *(right.first);
|
|
}
|
|
|
|
bool QTableModel::itemGreaterThan(const QPair<QTableWidgetItem*,int> &left,
|
|
const QPair<QTableWidgetItem*,int> &right)
|
|
{
|
|
return (*(right.first) < *(left .first));
|
|
}
|
|
|
|
QVariant QTableModel::headerData(int section, Qt::Orientation orientation, int role) const
|
|
{
|
|
if (section < 0)
|
|
return QVariant();
|
|
|
|
QTableWidgetItem *itm = nullptr;
|
|
if (orientation == Qt::Horizontal && section < horizontalHeaderItems.count())
|
|
itm = horizontalHeaderItems.at(section);
|
|
else if (orientation == Qt::Vertical && section < verticalHeaderItems.count())
|
|
itm = verticalHeaderItems.at(section);
|
|
else
|
|
return QVariant(); // section is out of bounds
|
|
|
|
if (itm)
|
|
return itm->data(role);
|
|
if (role == Qt::DisplayRole)
|
|
return section + 1;
|
|
return QVariant();
|
|
}
|
|
|
|
bool QTableModel::setHeaderData(int section, Qt::Orientation orientation,
|
|
const QVariant &value, int role)
|
|
{
|
|
if (section < 0 ||
|
|
(orientation == Qt::Horizontal && horizontalHeaderItems.size() <= section) ||
|
|
(orientation == Qt::Vertical && verticalHeaderItems.size() <= section))
|
|
return false;
|
|
|
|
QTableWidgetItem *itm = nullptr;
|
|
if (orientation == Qt::Horizontal)
|
|
itm = horizontalHeaderItems.at(section);
|
|
else
|
|
itm = verticalHeaderItems.at(section);
|
|
if (itm) {
|
|
itm->setData(role, value);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool QTableModel::isValid(const QModelIndex &index) const
|
|
{
|
|
return (index.isValid()
|
|
&& index.row() < verticalHeaderItems.count()
|
|
&& index.column() < horizontalHeaderItems.count());
|
|
}
|
|
|
|
void QTableModel::clear()
|
|
{
|
|
for (int j = 0; j < verticalHeaderItems.count(); ++j) {
|
|
if (verticalHeaderItems.at(j)) {
|
|
verticalHeaderItems.at(j)->view = nullptr;
|
|
delete verticalHeaderItems.at(j);
|
|
verticalHeaderItems[j] = 0;
|
|
}
|
|
}
|
|
for (int k = 0; k < horizontalHeaderItems.count(); ++k) {
|
|
if (horizontalHeaderItems.at(k)) {
|
|
horizontalHeaderItems.at(k)->view = nullptr;
|
|
delete horizontalHeaderItems.at(k);
|
|
horizontalHeaderItems[k] = 0;
|
|
}
|
|
}
|
|
clearContents();
|
|
}
|
|
|
|
void QTableModel::clearContents()
|
|
{
|
|
beginResetModel();
|
|
for (int i = 0; i < tableItems.count(); ++i) {
|
|
if (tableItems.at(i)) {
|
|
tableItems.at(i)->view = nullptr;
|
|
delete tableItems.at(i);
|
|
tableItems[i] = 0;
|
|
}
|
|
}
|
|
endResetModel();
|
|
}
|
|
|
|
void QTableModel::itemChanged(QTableWidgetItem *item, const QVector<int> &roles)
|
|
{
|
|
if (!item)
|
|
return;
|
|
if (item->flags() & ItemIsHeaderItem) {
|
|
int row = verticalHeaderItems.indexOf(item);
|
|
if (row >= 0) {
|
|
emit headerDataChanged(Qt::Vertical, row, row);
|
|
} else {
|
|
int column = horizontalHeaderItems.indexOf(item);
|
|
if (column >= 0)
|
|
emit headerDataChanged(Qt::Horizontal, column, column);
|
|
}
|
|
} else {
|
|
QModelIndex idx = index(item);
|
|
if (idx.isValid())
|
|
emit dataChanged(idx, idx, roles);
|
|
}
|
|
}
|
|
|
|
QTableWidgetItem* QTableModel::createItem() const
|
|
{
|
|
return prototype ? prototype->clone() : new QTableWidgetItem;
|
|
}
|
|
|
|
const QTableWidgetItem *QTableModel::itemPrototype() const
|
|
{
|
|
return prototype;
|
|
}
|
|
|
|
void QTableModel::setItemPrototype(const QTableWidgetItem *item)
|
|
{
|
|
if (prototype != item) {
|
|
delete prototype;
|
|
prototype = item;
|
|
}
|
|
}
|
|
|
|
QStringList QTableModel::mimeTypes() const
|
|
{
|
|
const QTableWidget *view = qobject_cast<const QTableWidget*>(QObject::parent());
|
|
return (view ? view->mimeTypes() : QStringList());
|
|
}
|
|
|
|
QMimeData *QTableModel::internalMimeData() const
|
|
{
|
|
return QAbstractTableModel::mimeData(cachedIndexes);
|
|
}
|
|
|
|
QMimeData *QTableModel::mimeData(const QModelIndexList &indexes) const
|
|
{
|
|
QList<QTableWidgetItem*> items;
|
|
const int indexesCount = indexes.count();
|
|
items.reserve(indexesCount);
|
|
for (int i = 0; i < indexesCount; ++i)
|
|
items << item(indexes.at(i));
|
|
const QTableWidget *view = qobject_cast<const QTableWidget*>(QObject::parent());
|
|
|
|
// cachedIndexes is a little hack to avoid copying from QModelIndexList to
|
|
// QList<QTreeWidgetItem*> and back again in the view
|
|
cachedIndexes = indexes;
|
|
QMimeData *mimeData = (view ? view->mimeData(items) : nullptr);
|
|
cachedIndexes.clear();
|
|
return mimeData;
|
|
}
|
|
|
|
bool QTableModel::dropMimeData(const QMimeData *data, Qt::DropAction action,
|
|
int row , int column, const QModelIndex &index)
|
|
{
|
|
if (index.isValid()) {
|
|
row = index.row();
|
|
column = index.column();
|
|
}else if (row == -1 || column == -1) { // The user dropped outside the table.
|
|
row = rowCount();
|
|
column = 0;
|
|
}
|
|
|
|
QTableWidget *view = qobject_cast<QTableWidget*>(QObject::parent());
|
|
return (view ? view->dropMimeData(row, column, data, action) : false);
|
|
}
|
|
|
|
Qt::DropActions QTableModel::supportedDropActions() const
|
|
{
|
|
const QTableWidget *view = qobject_cast<const QTableWidget*>(QObject::parent());
|
|
return (view ? view->supportedDropActions() : Qt::DropActions(Qt::IgnoreAction));
|
|
}
|
|
|
|
/*!
|
|
\class QTableWidgetSelectionRange
|
|
|
|
\brief The QTableWidgetSelectionRange class provides a way to interact with
|
|
selection in a model without using model indexes and a selection model.
|
|
|
|
\ingroup model-view
|
|
\inmodule QtWidgets
|
|
|
|
The QTableWidgetSelectionRange class stores the top left and bottom
|
|
right rows and columns of a selection range in a table. The
|
|
selections in the table may consist of several selection ranges.
|
|
|
|
\note If the item within the selection range is marked as not selectable,
|
|
e.g., \c{itemFlags() & Qt::ItemIsSelectable == 0} then it will not appear
|
|
in the selection range.
|
|
|
|
\sa QTableWidget
|
|
*/
|
|
|
|
/*!
|
|
Constructs an table selection range, i.e. a range
|
|
whose rowCount() and columnCount() are 0.
|
|
*/
|
|
QTableWidgetSelectionRange::QTableWidgetSelectionRange()
|
|
: top(-1), left(-1), bottom(-2), right(-2)
|
|
{
|
|
}
|
|
|
|
/*!
|
|
Constructs the table selection range from the given \a top, \a
|
|
left, \a bottom and \a right table rows and columns.
|
|
|
|
\sa topRow(), leftColumn(), bottomRow(), rightColumn()
|
|
*/
|
|
QTableWidgetSelectionRange::QTableWidgetSelectionRange(int top, int left, int bottom, int right)
|
|
: top(top), left(left), bottom(bottom), right(right)
|
|
{
|
|
}
|
|
|
|
/*!
|
|
Constructs a the table selection range by copying the given \a
|
|
other table selection range.
|
|
*/
|
|
QTableWidgetSelectionRange::QTableWidgetSelectionRange(const QTableWidgetSelectionRange &) = default;
|
|
QTableWidgetSelectionRange &QTableWidgetSelectionRange::operator=(const QTableWidgetSelectionRange &) = default;
|
|
|
|
/*!
|
|
Destroys the table selection range.
|
|
*/
|
|
QTableWidgetSelectionRange::~QTableWidgetSelectionRange()
|
|
{
|
|
}
|
|
|
|
/*!
|
|
\fn int QTableWidgetSelectionRange::topRow() const
|
|
|
|
Returns the top row of the range.
|
|
|
|
\sa bottomRow(), leftColumn(), rowCount()
|
|
*/
|
|
|
|
/*!
|
|
\fn int QTableWidgetSelectionRange::bottomRow() const
|
|
|
|
Returns the bottom row of the range.
|
|
|
|
\sa topRow(), rightColumn(), rowCount()
|
|
*/
|
|
|
|
/*!
|
|
\fn int QTableWidgetSelectionRange::leftColumn() const
|
|
|
|
Returns the left column of the range.
|
|
|
|
\sa rightColumn(), topRow(), columnCount()
|
|
*/
|
|
|
|
/*!
|
|
\fn int QTableWidgetSelectionRange::rightColumn() const
|
|
|
|
Returns the right column of the range.
|
|
|
|
\sa leftColumn(), bottomRow(), columnCount()
|
|
*/
|
|
|
|
/*!
|
|
\since 4.1
|
|
\fn int QTableWidgetSelectionRange::rowCount() const
|
|
|
|
Returns the number of rows in the range.
|
|
|
|
This is equivalent to bottomRow() - topRow() + 1.
|
|
|
|
\sa columnCount(), topRow(), bottomRow()
|
|
*/
|
|
|
|
/*!
|
|
\since 4.1
|
|
\fn int QTableWidgetSelectionRange::columnCount() const
|
|
|
|
Returns the number of columns in the range.
|
|
|
|
This is equivalent to rightColumn() - leftColumn() + 1.
|
|
|
|
\sa rowCount(), leftColumn(), rightColumn()
|
|
*/
|
|
|
|
/*!
|
|
\class QTableWidgetItem
|
|
\brief The QTableWidgetItem class provides an item for use with the
|
|
QTableWidget class.
|
|
|
|
\ingroup model-view
|
|
\inmodule QtWidgets
|
|
|
|
Table items are used to hold pieces of information for table widgets.
|
|
Items usually contain text, icons, or checkboxes
|
|
|
|
The QTableWidgetItem class is a convenience class that replaces the
|
|
\c QTableItem class in Qt 3. It provides an item for use with
|
|
the QTableWidget class.
|
|
|
|
Top-level items are constructed without a parent then inserted at the
|
|
position specified by a pair of row and column numbers:
|
|
|
|
\snippet qtablewidget-using/mainwindow.cpp 3
|
|
|
|
Each item can have its own background brush which is set with
|
|
the setBackground() function. The current background brush can be
|
|
found with background().
|
|
The text label for each item can be rendered with its own font and brush.
|
|
These are specified with the setFont() and setForeground() functions,
|
|
and read with font() and foreground().
|
|
|
|
By default, items are enabled, editable, selectable, checkable, and can be
|
|
used both as the source of a drag and drop operation and as a drop target.
|
|
Each item's flags can be changed by calling setFlags() with the appropriate
|
|
value (see \l{Qt::ItemFlags}). Checkable items can be checked and unchecked
|
|
with the setCheckState() function. The corresponding checkState() function
|
|
indicates whether the item is currently checked.
|
|
|
|
\section1 Subclassing
|
|
|
|
When subclassing QTableWidgetItem to provide custom items, it is possible to
|
|
define new types for them so that they can be distinguished from standard
|
|
items. The constructors for subclasses that require this feature need to
|
|
call the base class constructor with a new type value equal to or greater
|
|
than \l UserType.
|
|
|
|
\sa QTableWidget, {Model/View Programming}, QListWidgetItem, QTreeWidgetItem
|
|
*/
|
|
|
|
/*!
|
|
\fn int QTableWidgetItem::row() const
|
|
\since 4.2
|
|
|
|
Returns the row of the item in the table.
|
|
If the item is not in a table, this function will return -1.
|
|
|
|
\sa column()
|
|
*/
|
|
|
|
/*!
|
|
\fn int QTableWidgetItem::column() const
|
|
\since 4.2
|
|
|
|
Returns the column of the item in the table.
|
|
If the item is not in a table, this function will return -1.
|
|
|
|
\sa row()
|
|
*/
|
|
|
|
/*!
|
|
\fn QSize QTableWidgetItem::sizeHint() const
|
|
\since 4.1
|
|
|
|
Returns the size hint set for the table item.
|
|
*/
|
|
|
|
/*!
|
|
\fn void QTableWidgetItem::setSizeHint(const QSize &size)
|
|
\since 4.1
|
|
|
|
Sets the size hint for the table item to be \a size.
|
|
If no size hint is set or \a size is invalid, the item
|
|
delegate will compute the size hint based on the item data.
|
|
*/
|
|
|
|
/*!
|
|
\fn Qt::CheckState QTableWidgetItem::checkState() const
|
|
|
|
Returns the checked state of the table item.
|
|
|
|
\sa flags()
|
|
*/
|
|
|
|
/*!
|
|
\fn void QTableWidgetItem::setCheckState(Qt::CheckState state)
|
|
|
|
Sets the check state of the table item to be \a state.
|
|
*/
|
|
|
|
/*!
|
|
\fn QTableWidget *QTableWidgetItem::tableWidget() const
|
|
|
|
Returns the table widget that contains the item.
|
|
*/
|
|
|
|
/*!
|
|
\fn bool QTableWidgetItem::isSelected() const
|
|
\since 4.2
|
|
|
|
Returns \c true if the item is selected, otherwise returns \c false.
|
|
|
|
\sa setSelected()
|
|
*/
|
|
bool QTableWidgetItem::isSelected() const
|
|
{
|
|
if (!view || !view->selectionModel())
|
|
return false;
|
|
const QTableModel *model = qobject_cast<const QTableModel*>(view->model());
|
|
if (!model)
|
|
return false;
|
|
const QModelIndex index = model->index(this);
|
|
return view->selectionModel()->isSelected(index);
|
|
}
|
|
|
|
/*!
|
|
\fn void QTableWidgetItem::setSelected(bool select)
|
|
\since 4.2
|
|
|
|
Sets the selected state of the item to \a select.
|
|
|
|
\sa isSelected()
|
|
*/
|
|
void QTableWidgetItem::setSelected(bool select)
|
|
{
|
|
if (!view || !view->selectionModel())
|
|
return;
|
|
const QTableModel *model = qobject_cast<const QTableModel*>(view->model());
|
|
if (!model)
|
|
return;
|
|
const QModelIndex index = model->index(this);
|
|
view->selectionModel()->select(index, select ? QItemSelectionModel::Select : QItemSelectionModel::Deselect);
|
|
}
|
|
|
|
/*!
|
|
\fn Qt::ItemFlags QTableWidgetItem::flags() const
|
|
|
|
Returns the flags used to describe the item. These determine whether
|
|
the item can be checked, edited, and selected.
|
|
|
|
\sa setFlags()
|
|
*/
|
|
|
|
/*!
|
|
\fn void QTableWidgetItem::setFlags(Qt::ItemFlags flags)
|
|
|
|
Sets the flags for the item to the given \a flags. These determine whether
|
|
the item can be selected or modified.
|
|
|
|
\sa flags()
|
|
*/
|
|
void QTableWidgetItem::setFlags(Qt::ItemFlags aflags)
|
|
{
|
|
itemFlags = aflags;
|
|
if (QTableModel *model = tableModel())
|
|
model->itemChanged(this);
|
|
}
|
|
|
|
|
|
/*!
|
|
\fn QString QTableWidgetItem::text() const
|
|
|
|
Returns the item's text.
|
|
|
|
\sa setText()
|
|
*/
|
|
|
|
/*!
|
|
\fn void QTableWidgetItem::setText(const QString &text)
|
|
|
|
Sets the item's text to the \a text specified.
|
|
|
|
\sa text(), setFont(), setForeground()
|
|
*/
|
|
|
|
/*!
|
|
\fn QIcon QTableWidgetItem::icon() const
|
|
|
|
Returns the item's icon.
|
|
|
|
\sa setIcon(), {QAbstractItemView::iconSize}{iconSize}
|
|
*/
|
|
|
|
/*!
|
|
\fn void QTableWidgetItem::setIcon(const QIcon &icon)
|
|
|
|
Sets the item's icon to the \a icon specified.
|
|
|
|
\sa icon(), setText(), {QAbstractItemView::iconSize}{iconSize}
|
|
*/
|
|
|
|
/*!
|
|
\fn QString QTableWidgetItem::statusTip() const
|
|
|
|
Returns the item's status tip.
|
|
|
|
\sa setStatusTip()
|
|
*/
|
|
|
|
/*!
|
|
\fn void QTableWidgetItem::setStatusTip(const QString &statusTip)
|
|
|
|
Sets the status tip for the table item to the text specified by
|
|
\a statusTip. QTableWidget mouse tracking needs to be enabled for this
|
|
feature to work.
|
|
|
|
\sa statusTip(), setToolTip(), setWhatsThis()
|
|
*/
|
|
|
|
/*!
|
|
\fn QString QTableWidgetItem::toolTip() const
|
|
|
|
Returns the item's tooltip.
|
|
|
|
\sa setToolTip()
|
|
*/
|
|
|
|
/*!
|
|
\fn void QTableWidgetItem::setToolTip(const QString &toolTip)
|
|
|
|
Sets the item's tooltip to the string specified by \a toolTip.
|
|
|
|
\sa toolTip(), setStatusTip(), setWhatsThis()
|
|
*/
|
|
|
|
/*!
|
|
\fn QString QTableWidgetItem::whatsThis() const
|
|
|
|
Returns the item's "What's This?" help.
|
|
|
|
\sa setWhatsThis()
|
|
*/
|
|
|
|
/*!
|
|
\fn void QTableWidgetItem::setWhatsThis(const QString &whatsThis)
|
|
|
|
Sets the item's "What's This?" help to the string specified by \a whatsThis.
|
|
|
|
\sa whatsThis(), setStatusTip(), setToolTip()
|
|
*/
|
|
|
|
/*!
|
|
\fn QFont QTableWidgetItem::font() const
|
|
|
|
Returns the font used to render the item's text.
|
|
|
|
\sa setFont()
|
|
*/
|
|
|
|
/*!
|
|
\fn void QTableWidgetItem::setFont(const QFont &font)
|
|
|
|
Sets the font used to display the item's text to the given \a font.
|
|
|
|
\sa font(), setText(), setForeground()
|
|
*/
|
|
|
|
#if QT_DEPRECATED_SINCE(5, 13)
|
|
/*!
|
|
\fn QColor QTableWidgetItem::backgroundColor() const
|
|
\obsolete
|
|
|
|
This function is deprecated. Use background() instead.
|
|
*/
|
|
|
|
/*!
|
|
\fn void QTableWidgetItem::setBackgroundColor(const QColor &color)
|
|
\obsolete
|
|
|
|
This function is deprecated. Use setBackground() instead.
|
|
*/
|
|
#endif
|
|
|
|
/*!
|
|
\fn QBrush QTableWidgetItem::background() const
|
|
\since 4.2
|
|
|
|
Returns the brush used to render the item's background.
|
|
|
|
\sa foreground()
|
|
*/
|
|
|
|
/*!
|
|
\fn void QTableWidgetItem::setBackground(const QBrush &brush)
|
|
\since 4.2
|
|
|
|
Sets the item's background brush to the specified \a brush.
|
|
Setting a default-constructed brush will let the view use the
|
|
default color from the style.
|
|
|
|
\sa setForeground()
|
|
*/
|
|
|
|
#if QT_DEPRECATED_SINCE(5, 13)
|
|
/*!
|
|
\fn QColor QTableWidgetItem::textColor() const
|
|
\obsolete
|
|
|
|
This function is deprecated. Use foreground() instead.
|
|
*/
|
|
|
|
/*!
|
|
\fn void QTableWidgetItem::setTextColor(const QColor &color)
|
|
\obsolete
|
|
|
|
This function is deprecated. Use setForeground() instead.
|
|
*/
|
|
#endif
|
|
|
|
/*!
|
|
\fn QBrush QTableWidgetItem::foreground() const
|
|
\since 4.2
|
|
|
|
Returns the brush used to render the item's foreground (e.g. text).
|
|
|
|
\sa background()
|
|
*/
|
|
|
|
/*!
|
|
\fn void QTableWidgetItem::setForeground(const QBrush &brush)
|
|
\since 4.2
|
|
|
|
Sets the item's foreground brush to the specified \a brush.
|
|
Setting a default-constructed brush will let the view use the
|
|
default color from the style.
|
|
|
|
\sa setBackground()
|
|
*/
|
|
|
|
/*!
|
|
\fn int QTableWidgetItem::textAlignment() const
|
|
|
|
Returns the text alignment for the item's text.
|
|
|
|
\sa Qt::Alignment
|
|
*/
|
|
|
|
/*!
|
|
\fn void QTableWidgetItem::setTextAlignment(int alignment)
|
|
|
|
Sets the text alignment for the item's text to the \a alignment
|
|
specified.
|
|
|
|
\sa Qt::Alignment
|
|
*/
|
|
|
|
/*!
|
|
Constructs a table item of the specified \a type that does not belong
|
|
to any table.
|
|
|
|
\sa type()
|
|
*/
|
|
QTableWidgetItem::QTableWidgetItem(int type)
|
|
: rtti(type), view(nullptr), d(new QTableWidgetItemPrivate(this)),
|
|
itemFlags(Qt::ItemIsEditable
|
|
|Qt::ItemIsSelectable
|
|
|Qt::ItemIsUserCheckable
|
|
|Qt::ItemIsEnabled
|
|
|Qt::ItemIsDragEnabled
|
|
|Qt::ItemIsDropEnabled)
|
|
{
|
|
}
|
|
|
|
/*!
|
|
Constructs a table item with the given \a text.
|
|
|
|
\sa type()
|
|
*/
|
|
QTableWidgetItem::QTableWidgetItem(const QString &text, int type)
|
|
: rtti(type), view(nullptr), d(new QTableWidgetItemPrivate(this)),
|
|
itemFlags(Qt::ItemIsEditable
|
|
|Qt::ItemIsSelectable
|
|
|Qt::ItemIsUserCheckable
|
|
|Qt::ItemIsEnabled
|
|
|Qt::ItemIsDragEnabled
|
|
|Qt::ItemIsDropEnabled)
|
|
{
|
|
setData(Qt::DisplayRole, text);
|
|
}
|
|
|
|
/*!
|
|
Constructs a table item with the given \a icon and \a text.
|
|
|
|
\sa type()
|
|
*/
|
|
QTableWidgetItem::QTableWidgetItem(const QIcon &icon, const QString &text, int type)
|
|
: rtti(type), view(nullptr), d(new QTableWidgetItemPrivate(this)),
|
|
itemFlags(Qt::ItemIsEditable
|
|
|Qt::ItemIsSelectable
|
|
|Qt::ItemIsUserCheckable
|
|
|Qt::ItemIsEnabled
|
|
|Qt::ItemIsDragEnabled
|
|
|Qt::ItemIsDropEnabled)
|
|
{
|
|
setData(Qt::DecorationRole, icon);
|
|
setData(Qt::DisplayRole, text);
|
|
}
|
|
|
|
/*!
|
|
Destroys the table item.
|
|
*/
|
|
QTableWidgetItem::~QTableWidgetItem()
|
|
{
|
|
if (QTableModel *model = tableModel())
|
|
model->removeItem(this);
|
|
delete d;
|
|
}
|
|
|
|
/*!
|
|
Creates a copy of the item.
|
|
*/
|
|
QTableWidgetItem *QTableWidgetItem::clone() const
|
|
{
|
|
return new QTableWidgetItem(*this);
|
|
}
|
|
|
|
/*!
|
|
Sets the item's data for the given \a role to the specified \a value.
|
|
|
|
\note The default implementation treats Qt::EditRole and Qt::DisplayRole as
|
|
referring to the same data.
|
|
|
|
\sa Qt::ItemDataRole, data()
|
|
*/
|
|
void QTableWidgetItem::setData(int role, const QVariant &value)
|
|
{
|
|
bool found = false;
|
|
role = (role == Qt::EditRole ? Qt::DisplayRole : role);
|
|
for (int i = 0; i < values.count(); ++i) {
|
|
if (values.at(i).role == role) {
|
|
if (values[i].value == value)
|
|
return;
|
|
|
|
values[i].value = value;
|
|
found = true;
|
|
break;
|
|
}
|
|
}
|
|
if (!found)
|
|
values.append(QWidgetItemData(role, value));
|
|
if (QTableModel *model = tableModel())
|
|
{
|
|
const QVector<int> roles((role == Qt::DisplayRole) ?
|
|
QVector<int>({Qt::DisplayRole, Qt::EditRole}) :
|
|
QVector<int>({role}));
|
|
model->itemChanged(this, roles);
|
|
}
|
|
}
|
|
|
|
/*!
|
|
Returns the item's data for the given \a role.
|
|
*/
|
|
QVariant QTableWidgetItem::data(int role) const
|
|
{
|
|
role = (role == Qt::EditRole ? Qt::DisplayRole : role);
|
|
for (const auto &value : values) {
|
|
if (value.role == role)
|
|
return value.value;
|
|
}
|
|
return QVariant();
|
|
}
|
|
|
|
/*!
|
|
Returns \c true if the item is less than the \a other item; otherwise returns
|
|
false.
|
|
*/
|
|
bool QTableWidgetItem::operator<(const QTableWidgetItem &other) const
|
|
{
|
|
const QVariant v1 = data(Qt::DisplayRole), v2 = other.data(Qt::DisplayRole);
|
|
return QAbstractItemModelPrivate::variantLessThan(v1, v2);
|
|
}
|
|
|
|
#ifndef QT_NO_DATASTREAM
|
|
|
|
/*!
|
|
Reads the item from stream \a in.
|
|
|
|
\sa write()
|
|
*/
|
|
void QTableWidgetItem::read(QDataStream &in)
|
|
{
|
|
in >> values;
|
|
}
|
|
|
|
/*!
|
|
Writes the item to stream \a out.
|
|
|
|
\sa read()
|
|
*/
|
|
void QTableWidgetItem::write(QDataStream &out) const
|
|
{
|
|
out << values;
|
|
}
|
|
|
|
/*!
|
|
\internal
|
|
returns the QTableModel if a view is set
|
|
*/
|
|
QTableModel *QTableWidgetItem::tableModel() const
|
|
{
|
|
return (view ? qobject_cast<QTableModel*>(view->model()) : nullptr);
|
|
}
|
|
|
|
|
|
/*!
|
|
\relates QTableWidgetItem
|
|
|
|
Reads a table widget item from stream \a in into \a item.
|
|
|
|
This operator uses QTableWidgetItem::read().
|
|
|
|
\sa {Serializing Qt Data Types}
|
|
*/
|
|
QDataStream &operator>>(QDataStream &in, QTableWidgetItem &item)
|
|
{
|
|
item.read(in);
|
|
return in;
|
|
}
|
|
|
|
/*!
|
|
\relates QTableWidgetItem
|
|
|
|
Writes the table widget item \a item to stream \a out.
|
|
|
|
This operator uses QTableWidgetItem::write().
|
|
|
|
\sa {Serializing Qt Data Types}
|
|
*/
|
|
QDataStream &operator<<(QDataStream &out, const QTableWidgetItem &item)
|
|
{
|
|
item.write(out);
|
|
return out;
|
|
}
|
|
|
|
#endif // QT_NO_DATASTREAM
|
|
|
|
/*!
|
|
\since 4.1
|
|
|
|
Constructs a copy of \a other. Note that type() and tableWidget()
|
|
are not copied.
|
|
|
|
This function is useful when reimplementing clone().
|
|
|
|
\sa data(), flags()
|
|
*/
|
|
QTableWidgetItem::QTableWidgetItem(const QTableWidgetItem &other)
|
|
: rtti(Type), values(other.values), view(nullptr),
|
|
d(new QTableWidgetItemPrivate(this)),
|
|
itemFlags(other.itemFlags)
|
|
{
|
|
}
|
|
|
|
/*!
|
|
Assigns \a other's data and flags to this item. Note that type()
|
|
and tableWidget() are not copied.
|
|
|
|
This function is useful when reimplementing clone().
|
|
|
|
\sa data(), flags()
|
|
*/
|
|
QTableWidgetItem &QTableWidgetItem::operator=(const QTableWidgetItem &other)
|
|
{
|
|
values = other.values;
|
|
itemFlags = other.itemFlags;
|
|
return *this;
|
|
}
|
|
|
|
/*!
|
|
\class QTableWidget
|
|
\brief The QTableWidget class provides an item-based table view with a default model.
|
|
|
|
\ingroup model-view
|
|
\inmodule QtWidgets
|
|
|
|
\image windows-tableview.png
|
|
|
|
Table widgets provide standard table display facilities for applications.
|
|
The items in a QTableWidget are provided by QTableWidgetItem.
|
|
|
|
If you want a table that uses your own data model you should
|
|
use QTableView rather than this class.
|
|
|
|
Table widgets can be constructed with the required numbers of rows and
|
|
columns:
|
|
|
|
\snippet qtablewidget-using/mainwindow.cpp 0
|
|
|
|
Alternatively, tables can be constructed without a given size and resized
|
|
later:
|
|
|
|
\snippet qtablewidget-resizing/mainwindow.cpp 0
|
|
\snippet qtablewidget-resizing/mainwindow.cpp 1
|
|
|
|
Items are created outside the table (with no parent widget) and inserted
|
|
into the table with setItem():
|
|
|
|
\snippet qtablewidget-resizing/mainwindow.cpp 2
|
|
|
|
If you want to enable sorting in your table widget, do so after you
|
|
have populated it with items, otherwise sorting may interfere with
|
|
the insertion order (see setItem() for details).
|
|
|
|
Tables can be given both horizontal and vertical headers. The simplest way
|
|
to create the headers is to supply a list of strings to the
|
|
setHorizontalHeaderLabels() and setVerticalHeaderLabels() functions. These
|
|
will provide simple textual headers for the table's columns and rows.
|
|
More sophisticated headers can be created from existing table items
|
|
that are usually constructed outside the table. For example, we can
|
|
construct a table item with an icon and aligned text, and use it as the
|
|
header for a particular column:
|
|
|
|
\snippet qtablewidget-using/mainwindow.cpp 2
|
|
|
|
The number of rows in the table can be found with rowCount(), and the
|
|
number of columns with columnCount(). The table can be cleared with the
|
|
clear() function.
|
|
|
|
\sa QTableWidgetItem, QTableView, {Model/View Programming}
|
|
*/
|
|
|
|
/*!
|
|
\property QTableWidget::rowCount
|
|
\brief the number of rows in the table
|
|
|
|
By default, for a table constructed without row and column counts,
|
|
this property contains a value of 0.
|
|
*/
|
|
|
|
/*!
|
|
\property QTableWidget::columnCount
|
|
\brief the number of columns in the table
|
|
|
|
By default, for a table constructed without row and column counts,
|
|
this property contains a value of 0.
|
|
*/
|
|
|
|
void QTableWidgetPrivate::setup()
|
|
{
|
|
Q_Q(QTableWidget);
|
|
// view signals
|
|
QObject::connect(q, SIGNAL(pressed(QModelIndex)), q, SLOT(_q_emitItemPressed(QModelIndex)));
|
|
QObject::connect(q, SIGNAL(clicked(QModelIndex)), q, SLOT(_q_emitItemClicked(QModelIndex)));
|
|
QObject::connect(q, SIGNAL(doubleClicked(QModelIndex)),
|
|
q, SLOT(_q_emitItemDoubleClicked(QModelIndex)));
|
|
QObject::connect(q, SIGNAL(activated(QModelIndex)), q, SLOT(_q_emitItemActivated(QModelIndex)));
|
|
QObject::connect(q, SIGNAL(entered(QModelIndex)), q, SLOT(_q_emitItemEntered(QModelIndex)));
|
|
// model signals
|
|
QObject::connect(model, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
|
|
q, SLOT(_q_emitItemChanged(QModelIndex)));
|
|
// selection signals
|
|
QObject::connect(q->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)),
|
|
q, SLOT(_q_emitCurrentItemChanged(QModelIndex,QModelIndex)));
|
|
QObject::connect(q->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
|
|
q, SIGNAL(itemSelectionChanged()));
|
|
// sorting
|
|
QObject::connect(model, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
|
|
q, SLOT(_q_dataChanged(QModelIndex,QModelIndex)));
|
|
QObject::connect(model, SIGNAL(columnsRemoved(QModelIndex,int,int)), q, SLOT(_q_sort()));
|
|
}
|
|
|
|
void QTableWidgetPrivate::_q_emitItemPressed(const QModelIndex &index)
|
|
{
|
|
Q_Q(QTableWidget);
|
|
if (QTableWidgetItem *item = tableModel()->item(index))
|
|
emit q->itemPressed(item);
|
|
emit q->cellPressed(index.row(), index.column());
|
|
}
|
|
|
|
void QTableWidgetPrivate::_q_emitItemClicked(const QModelIndex &index)
|
|
{
|
|
Q_Q(QTableWidget);
|
|
if (QTableWidgetItem *item = tableModel()->item(index))
|
|
emit q->itemClicked(item);
|
|
emit q->cellClicked(index.row(), index.column());
|
|
}
|
|
|
|
void QTableWidgetPrivate::_q_emitItemDoubleClicked(const QModelIndex &index)
|
|
{
|
|
Q_Q(QTableWidget);
|
|
if (QTableWidgetItem *item = tableModel()->item(index))
|
|
emit q->itemDoubleClicked(item);
|
|
emit q->cellDoubleClicked(index.row(), index.column());
|
|
}
|
|
|
|
void QTableWidgetPrivate::_q_emitItemActivated(const QModelIndex &index)
|
|
{
|
|
Q_Q(QTableWidget);
|
|
if (QTableWidgetItem *item = tableModel()->item(index))
|
|
emit q->itemActivated(item);
|
|
emit q->cellActivated(index.row(), index.column());
|
|
}
|
|
|
|
void QTableWidgetPrivate::_q_emitItemEntered(const QModelIndex &index)
|
|
{
|
|
Q_Q(QTableWidget);
|
|
if (QTableWidgetItem *item = tableModel()->item(index))
|
|
emit q->itemEntered(item);
|
|
emit q->cellEntered(index.row(), index.column());
|
|
}
|
|
|
|
void QTableWidgetPrivate::_q_emitItemChanged(const QModelIndex &index)
|
|
{
|
|
Q_Q(QTableWidget);
|
|
if (QTableWidgetItem *item = tableModel()->item(index))
|
|
emit q->itemChanged(item);
|
|
emit q->cellChanged(index.row(), index.column());
|
|
}
|
|
|
|
void QTableWidgetPrivate::_q_emitCurrentItemChanged(const QModelIndex ¤t,
|
|
const QModelIndex &previous)
|
|
{
|
|
Q_Q(QTableWidget);
|
|
QTableWidgetItem *currentItem = tableModel()->item(current);
|
|
QTableWidgetItem *previousItem = tableModel()->item(previous);
|
|
if (currentItem || previousItem)
|
|
emit q->currentItemChanged(currentItem, previousItem);
|
|
emit q->currentCellChanged(current.row(), current.column(), previous.row(), previous.column());
|
|
}
|
|
|
|
void QTableWidgetPrivate::_q_sort()
|
|
{
|
|
if (sortingEnabled) {
|
|
int column = horizontalHeader->sortIndicatorSection();
|
|
Qt::SortOrder order = horizontalHeader->sortIndicatorOrder();
|
|
model->sort(column, order);
|
|
}
|
|
}
|
|
|
|
void QTableWidgetPrivate::_q_dataChanged(const QModelIndex &topLeft,
|
|
const QModelIndex &bottomRight)
|
|
{
|
|
if (sortingEnabled && topLeft.isValid() && bottomRight.isValid()) {
|
|
int column = horizontalHeader->sortIndicatorSection();
|
|
if (column >= topLeft.column() && column <= bottomRight.column()) {
|
|
Qt::SortOrder order = horizontalHeader->sortIndicatorOrder();
|
|
tableModel()->ensureSorted(column, order, topLeft.row(), bottomRight.row());
|
|
}
|
|
}
|
|
}
|
|
|
|
/*!
|
|
\fn void QTableWidget::itemPressed(QTableWidgetItem *item)
|
|
|
|
This signal is emitted whenever an item in the table is pressed.
|
|
The \a item specified is the item that was pressed.
|
|
*/
|
|
|
|
/*!
|
|
\fn void QTableWidget::itemClicked(QTableWidgetItem *item)
|
|
|
|
This signal is emitted whenever an item in the table is clicked.
|
|
The \a item specified is the item that was clicked.
|
|
*/
|
|
|
|
/*!
|
|
\fn void QTableWidget::itemDoubleClicked(QTableWidgetItem *item)
|
|
|
|
This signal is emitted whenever an item in the table is double
|
|
clicked. The \a item specified is the item that was double clicked.
|
|
*/
|
|
|
|
/*!
|
|
\fn void QTableWidget::itemActivated(QTableWidgetItem *item)
|
|
|
|
This signal is emitted when the specified \a item has been activated
|
|
*/
|
|
|
|
/*!
|
|
\fn void QTableWidget::itemEntered(QTableWidgetItem *item)
|
|
|
|
This signal is emitted when the mouse cursor enters an item. The
|
|
\a item is the item entered.
|
|
|
|
This signal is only emitted when mouseTracking is turned on, or when a
|
|
mouse button is pressed while moving into an item.
|
|
*/
|
|
|
|
/*!
|
|
\fn void QTableWidget::itemChanged(QTableWidgetItem *item)
|
|
|
|
This signal is emitted whenever the data of \a item has changed.
|
|
*/
|
|
|
|
/*!
|
|
\fn void QTableWidget::currentItemChanged(QTableWidgetItem *current, QTableWidgetItem *previous)
|
|
|
|
This signal is emitted whenever the current item changes. The \a
|
|
previous item is the item that previously had the focus, \a
|
|
current is the new current item.
|
|
*/
|
|
|
|
/*!
|
|
\fn void QTableWidget::itemSelectionChanged()
|
|
|
|
This signal is emitted whenever the selection changes.
|
|
|
|
\sa selectedItems(), QTableWidgetItem::isSelected()
|
|
*/
|
|
|
|
|
|
/*!
|
|
\since 4.1
|
|
\fn void QTableWidget::cellPressed(int row, int column)
|
|
|
|
This signal is emitted whenever a cell in the table is pressed.
|
|
The \a row and \a column specified is the cell that was pressed.
|
|
*/
|
|
|
|
/*!
|
|
\since 4.1
|
|
\fn void QTableWidget::cellClicked(int row, int column)
|
|
|
|
This signal is emitted whenever a cell in the table is clicked.
|
|
The \a row and \a column specified is the cell that was clicked.
|
|
*/
|
|
|
|
/*!
|
|
\since 4.1
|
|
\fn void QTableWidget::cellDoubleClicked(int row, int column)
|
|
|
|
This signal is emitted whenever a cell in the table is double
|
|
clicked. The \a row and \a column specified is the cell that was
|
|
double clicked.
|
|
*/
|
|
|
|
/*!
|
|
\since 4.1
|
|
\fn void QTableWidget::cellActivated(int row, int column)
|
|
|
|
This signal is emitted when the cell specified by \a row and \a column
|
|
has been activated
|
|
*/
|
|
|
|
/*!
|
|
\since 4.1
|
|
\fn void QTableWidget::cellEntered(int row, int column)
|
|
|
|
This signal is emitted when the mouse cursor enters a cell. The
|
|
cell is specified by \a row and \a column.
|
|
|
|
This signal is only emitted when mouseTracking is turned on, or when a
|
|
mouse button is pressed while moving into an item.
|
|
*/
|
|
|
|
/*!
|
|
\since 4.1
|
|
\fn void QTableWidget::cellChanged(int row, int column)
|
|
|
|
This signal is emitted whenever the data of the item in the cell
|
|
specified by \a row and \a column has changed.
|
|
*/
|
|
|
|
/*!
|
|
\since 4.1
|
|
\fn void QTableWidget::currentCellChanged(int currentRow, int currentColumn, int previousRow, int previousColumn)
|
|
|
|
This signal is emitted whenever the current cell changes. The cell
|
|
specified by \a previousRow and \a previousColumn is the cell that
|
|
previously had the focus, the cell specified by \a currentRow and \a
|
|
currentColumn is the new current cell.
|
|
*/
|
|
|
|
/*!
|
|
\since 4.3
|
|
\fn void QTableWidget::removeCellWidget(int row, int column)
|
|
|
|
Removes the widget set on the cell indicated by \a row and \a column.
|
|
*/
|
|
|
|
/*!
|
|
\fn QTableWidgetItem *QTableWidget::itemAt(int ax, int ay) const
|
|
|
|
Returns the item at the position equivalent to QPoint(\a{ax}, \a{ay}) in
|
|
the table widget's coordinate system, or returns \nullptr if the specified point
|
|
is not covered by an item in the table widget.
|
|
|
|
\sa item()
|
|
*/
|
|
|
|
/*!
|
|
\enum QTableWidgetItem::ItemType
|
|
|
|
This enum describes the types that are used to describe table widget items.
|
|
|
|
\value Type The default type for table widget items.
|
|
\value UserType The minimum value for custom types. Values below UserType are
|
|
reserved by Qt.
|
|
|
|
You can define new user types in QTableWidgetItem subclasses to ensure that
|
|
custom items are treated specially.
|
|
|
|
\sa type()
|
|
*/
|
|
|
|
/*!
|
|
\fn int QTableWidgetItem::type() const
|
|
|
|
Returns the type passed to the QTableWidgetItem constructor.
|
|
*/
|
|
|
|
/*!
|
|
Creates a new table view with the given \a parent.
|
|
*/
|
|
QTableWidget::QTableWidget(QWidget *parent)
|
|
: QTableView(*new QTableWidgetPrivate, parent)
|
|
{
|
|
Q_D(QTableWidget);
|
|
QTableView::setModel(new QTableModel(0, 0, this));
|
|
d->setup();
|
|
}
|
|
|
|
/*!
|
|
Creates a new table view with the given \a rows and \a columns, and with the given \a parent.
|
|
*/
|
|
QTableWidget::QTableWidget(int rows, int columns, QWidget *parent)
|
|
: QTableView(*new QTableWidgetPrivate, parent)
|
|
{
|
|
Q_D(QTableWidget);
|
|
QTableView::setModel(new QTableModel(rows, columns, this));
|
|
d->setup();
|
|
}
|
|
|
|
/*!
|
|
Destroys this QTableWidget.
|
|
*/
|
|
QTableWidget::~QTableWidget()
|
|
{
|
|
}
|
|
|
|
/*!
|
|
Sets the number of rows in this table's model to \a rows. If
|
|
this is less than rowCount(), the data in the unwanted rows
|
|
is discarded.
|
|
|
|
\sa setColumnCount()
|
|
*/
|
|
void QTableWidget::setRowCount(int rows)
|
|
{
|
|
Q_D(QTableWidget);
|
|
d->tableModel()->setRowCount(rows);
|
|
}
|
|
|
|
/*!
|
|
Returns the number of rows.
|
|
*/
|
|
|
|
int QTableWidget::rowCount() const
|
|
{
|
|
Q_D(const QTableWidget);
|
|
return d->model->rowCount();
|
|
}
|
|
|
|
/*!
|
|
Sets the number of columns in this table's model to \a columns. If
|
|
this is less than columnCount(), the data in the unwanted columns
|
|
is discarded.
|
|
|
|
\sa setRowCount()
|
|
*/
|
|
void QTableWidget::setColumnCount(int columns)
|
|
{
|
|
Q_D(QTableWidget);
|
|
d->tableModel()->setColumnCount(columns);
|
|
}
|
|
|
|
/*!
|
|
Returns the number of columns.
|
|
*/
|
|
|
|
int QTableWidget::columnCount() const
|
|
{
|
|
Q_D(const QTableWidget);
|
|
return d->model->columnCount();
|
|
}
|
|
|
|
/*!
|
|
Returns the row for the \a item.
|
|
*/
|
|
int QTableWidget::row(const QTableWidgetItem *item) const
|
|
{
|
|
Q_D(const QTableWidget);
|
|
return d->tableModel()->index(item).row();
|
|
}
|
|
|
|
/*!
|
|
Returns the column for the \a item.
|
|
*/
|
|
int QTableWidget::column(const QTableWidgetItem *item) const
|
|
{
|
|
Q_D(const QTableWidget);
|
|
return d->tableModel()->index(item).column();
|
|
}
|
|
|
|
|
|
/*!
|
|
Returns the item for the given \a row and \a column if one has been set; otherwise
|
|
returns \nullptr.
|
|
|
|
\sa setItem()
|
|
*/
|
|
QTableWidgetItem *QTableWidget::item(int row, int column) const
|
|
{
|
|
Q_D(const QTableWidget);
|
|
return d->tableModel()->item(row, column);
|
|
}
|
|
|
|
/*!
|
|
Sets the item for the given \a row and \a column to \a item.
|
|
|
|
The table takes ownership of the item.
|
|
|
|
Note that if sorting is enabled (see
|
|
\l{QTableView::sortingEnabled} {sortingEnabled}) and \a column is
|
|
the current sort column, the \a row will be moved to the sorted
|
|
position determined by \a item.
|
|
|
|
If you want to set several items of a particular row (say, by
|
|
calling setItem() in a loop), you may want to turn off sorting
|
|
before doing so, and turn it back on afterwards; this will allow
|
|
you to use the same \a row argument for all items in the same row
|
|
(i.e. setItem() will not move the row).
|
|
|
|
\sa item(), takeItem()
|
|
*/
|
|
void QTableWidget::setItem(int row, int column, QTableWidgetItem *item)
|
|
{
|
|
Q_D(QTableWidget);
|
|
if (item) {
|
|
if (Q_UNLIKELY(item->view)) {
|
|
qWarning("QTableWidget: cannot insert an item that is already owned by another QTableWidget");
|
|
} else {
|
|
item->view = this;
|
|
d->tableModel()->setItem(row, column, item);
|
|
}
|
|
} else {
|
|
delete takeItem(row, column);
|
|
}
|
|
}
|
|
|
|
/*!
|
|
Removes the item at \a row and \a column from the table without deleting it.
|
|
*/
|
|
QTableWidgetItem *QTableWidget::takeItem(int row, int column)
|
|
{
|
|
Q_D(QTableWidget);
|
|
QTableWidgetItem *item = d->tableModel()->takeItem(row, column);
|
|
if (item)
|
|
item->view = nullptr;
|
|
return item;
|
|
}
|
|
|
|
/*!
|
|
Returns the vertical header item for row \a row.
|
|
*/
|
|
QTableWidgetItem *QTableWidget::verticalHeaderItem(int row) const
|
|
{
|
|
Q_D(const QTableWidget);
|
|
return d->tableModel()->verticalHeaderItem(row);
|
|
}
|
|
|
|
/*!
|
|
Sets the vertical header item for row \a row to \a item.
|
|
*/
|
|
void QTableWidget::setVerticalHeaderItem(int row, QTableWidgetItem *item)
|
|
{
|
|
Q_D(QTableWidget);
|
|
if (item) {
|
|
item->view = this;
|
|
d->tableModel()->setVerticalHeaderItem(row, item);
|
|
} else {
|
|
delete takeVerticalHeaderItem(row);
|
|
}
|
|
}
|
|
|
|
/*!
|
|
\since 4.1
|
|
Removes the vertical header item at \a row from the header without deleting it.
|
|
*/
|
|
QTableWidgetItem *QTableWidget::takeVerticalHeaderItem(int row)
|
|
{
|
|
Q_D(QTableWidget);
|
|
QTableWidgetItem *itm = d->tableModel()->takeVerticalHeaderItem(row);
|
|
if (itm)
|
|
itm->view = nullptr;
|
|
return itm;
|
|
}
|
|
|
|
/*!
|
|
Returns the horizontal header item for column, \a column, if one has been
|
|
set; otherwise returns \nullptr.
|
|
*/
|
|
QTableWidgetItem *QTableWidget::horizontalHeaderItem(int column) const
|
|
{
|
|
Q_D(const QTableWidget);
|
|
return d->tableModel()->horizontalHeaderItem(column);
|
|
}
|
|
|
|
/*!
|
|
Sets the horizontal header item for column \a column to \a item.
|
|
If necessary, the column count is increased to fit the item.
|
|
The previous header item (if there was one) is deleted.
|
|
*/
|
|
void QTableWidget::setHorizontalHeaderItem(int column, QTableWidgetItem *item)
|
|
{
|
|
Q_D(QTableWidget);
|
|
if (item) {
|
|
item->view = this;
|
|
d->tableModel()->setHorizontalHeaderItem(column, item);
|
|
} else {
|
|
delete takeHorizontalHeaderItem(column);
|
|
}
|
|
}
|
|
|
|
/*!
|
|
\since 4.1
|
|
Removes the horizontal header item at \a column from the header without deleting it.
|
|
*/
|
|
QTableWidgetItem *QTableWidget::takeHorizontalHeaderItem(int column)
|
|
{
|
|
Q_D(QTableWidget);
|
|
QTableWidgetItem *itm = d->tableModel()->takeHorizontalHeaderItem(column);
|
|
if (itm)
|
|
itm->view = nullptr;
|
|
return itm;
|
|
}
|
|
|
|
/*!
|
|
Sets the vertical header labels using \a labels.
|
|
*/
|
|
void QTableWidget::setVerticalHeaderLabels(const QStringList &labels)
|
|
{
|
|
Q_D(QTableWidget);
|
|
QTableModel *model = d->tableModel();
|
|
QTableWidgetItem *item = nullptr;
|
|
for (int i = 0; i < model->rowCount() && i < labels.count(); ++i) {
|
|
item = model->verticalHeaderItem(i);
|
|
if (!item) {
|
|
item = model->createItem();
|
|
setVerticalHeaderItem(i, item);
|
|
}
|
|
item->setText(labels.at(i));
|
|
}
|
|
}
|
|
|
|
/*!
|
|
Sets the horizontal header labels using \a labels.
|
|
*/
|
|
void QTableWidget::setHorizontalHeaderLabels(const QStringList &labels)
|
|
{
|
|
Q_D(QTableWidget);
|
|
QTableModel *model = d->tableModel();
|
|
QTableWidgetItem *item = nullptr;
|
|
for (int i = 0; i < model->columnCount() && i < labels.count(); ++i) {
|
|
item = model->horizontalHeaderItem(i);
|
|
if (!item) {
|
|
item = model->createItem();
|
|
setHorizontalHeaderItem(i, item);
|
|
}
|
|
item->setText(labels.at(i));
|
|
}
|
|
}
|
|
|
|
/*!
|
|
Returns the row of the current item.
|
|
|
|
\sa currentColumn(), setCurrentCell()
|
|
*/
|
|
int QTableWidget::currentRow() const
|
|
{
|
|
return currentIndex().row();
|
|
}
|
|
|
|
/*!
|
|
Returns the column of the current item.
|
|
|
|
\sa currentRow(), setCurrentCell()
|
|
*/
|
|
int QTableWidget::currentColumn() const
|
|
{
|
|
return currentIndex().column();
|
|
}
|
|
|
|
/*!
|
|
Returns the current item.
|
|
|
|
\sa setCurrentItem()
|
|
*/
|
|
QTableWidgetItem *QTableWidget::currentItem() const
|
|
{
|
|
Q_D(const QTableWidget);
|
|
return d->tableModel()->item(currentIndex());
|
|
}
|
|
|
|
/*!
|
|
Sets the current item to \a item.
|
|
|
|
Unless the selection mode is \l{QAbstractItemView::}{NoSelection},
|
|
the item is also selected.
|
|
|
|
\sa currentItem(), setCurrentCell()
|
|
*/
|
|
void QTableWidget::setCurrentItem(QTableWidgetItem *item)
|
|
{
|
|
Q_D(QTableWidget);
|
|
setCurrentIndex(d->tableModel()->index(item));
|
|
}
|
|
|
|
/*!
|
|
\since 4.4
|
|
|
|
Sets the current item to be \a item, using the given \a command.
|
|
|
|
\sa currentItem(), setCurrentCell()
|
|
*/
|
|
void QTableWidget::setCurrentItem(QTableWidgetItem *item, QItemSelectionModel::SelectionFlags command)
|
|
{
|
|
Q_D(QTableWidget);
|
|
d->selectionModel->setCurrentIndex(d->tableModel()->index(item), command);
|
|
}
|
|
|
|
/*!
|
|
\since 4.1
|
|
|
|
Sets the current cell to be the cell at position (\a row, \a
|
|
column).
|
|
|
|
Depending on the current \l{QAbstractItemView::SelectionMode}{selection mode},
|
|
the cell may also be selected.
|
|
|
|
\sa setCurrentItem(), currentRow(), currentColumn()
|
|
*/
|
|
void QTableWidget::setCurrentCell(int row, int column)
|
|
{
|
|
setCurrentIndex(model()->index(row, column, QModelIndex()));
|
|
}
|
|
|
|
/*!
|
|
\since 4.4
|
|
|
|
Sets the current cell to be the cell at position (\a row, \a
|
|
column), using the given \a command.
|
|
|
|
\sa setCurrentItem(), currentRow(), currentColumn()
|
|
*/
|
|
void QTableWidget::setCurrentCell(int row, int column, QItemSelectionModel::SelectionFlags command)
|
|
{
|
|
Q_D(QTableWidget);
|
|
d->selectionModel->setCurrentIndex(model()->index(row, column, QModelIndex()), command);
|
|
}
|
|
|
|
/*!
|
|
Sorts all the rows in the table widget based on \a column and \a order.
|
|
*/
|
|
void QTableWidget::sortItems(int column, Qt::SortOrder order)
|
|
{
|
|
Q_D(QTableWidget);
|
|
d->model->sort(column, order);
|
|
horizontalHeader()->setSortIndicator(column, order);
|
|
}
|
|
|
|
/*!
|
|
\internal
|
|
*/
|
|
void QTableWidget::setSortingEnabled(bool enable)
|
|
{
|
|
QTableView::setSortingEnabled(enable);
|
|
}
|
|
|
|
/*!
|
|
\internal
|
|
*/
|
|
bool QTableWidget::isSortingEnabled() const
|
|
{
|
|
return QTableView::isSortingEnabled();
|
|
}
|
|
|
|
/*!
|
|
Starts editing the \a item if it is editable.
|
|
*/
|
|
|
|
void QTableWidget::editItem(QTableWidgetItem *item)
|
|
{
|
|
Q_D(QTableWidget);
|
|
if (!item)
|
|
return;
|
|
edit(d->tableModel()->index(item));
|
|
}
|
|
|
|
/*!
|
|
Opens an editor for the give \a item. The editor remains open after editing.
|
|
|
|
\sa closePersistentEditor(), isPersistentEditorOpen()
|
|
*/
|
|
void QTableWidget::openPersistentEditor(QTableWidgetItem *item)
|
|
{
|
|
Q_D(QTableWidget);
|
|
if (!item)
|
|
return;
|
|
QModelIndex index = d->tableModel()->index(item);
|
|
QAbstractItemView::openPersistentEditor(index);
|
|
}
|
|
|
|
/*!
|
|
Closes the persistent editor for \a item.
|
|
|
|
\sa openPersistentEditor(), isPersistentEditorOpen()
|
|
*/
|
|
void QTableWidget::closePersistentEditor(QTableWidgetItem *item)
|
|
{
|
|
Q_D(QTableWidget);
|
|
if (!item)
|
|
return;
|
|
QModelIndex index = d->tableModel()->index(item);
|
|
QAbstractItemView::closePersistentEditor(index);
|
|
}
|
|
|
|
/*!
|
|
\since 5.10
|
|
|
|
Returns whether a persistent editor is open for item \a item.
|
|
|
|
\sa openPersistentEditor(), closePersistentEditor()
|
|
*/
|
|
bool QTableWidget::isPersistentEditorOpen(QTableWidgetItem *item) const
|
|
{
|
|
Q_D(const QTableWidget);
|
|
const QModelIndex index = d->tableModel()->index(item);
|
|
return QAbstractItemView::isPersistentEditorOpen(index);
|
|
}
|
|
|
|
/*!
|
|
\since 4.1
|
|
|
|
Returns the widget displayed in the cell in the given \a row and \a column.
|
|
|
|
\note The table takes ownership of the widget.
|
|
|
|
\sa setCellWidget()
|
|
*/
|
|
QWidget *QTableWidget::cellWidget(int row, int column) const
|
|
{
|
|
QModelIndex index = model()->index(row, column, QModelIndex());
|
|
return QAbstractItemView::indexWidget(index);
|
|
}
|
|
|
|
/*!
|
|
\since 4.1
|
|
|
|
Sets the given \a widget to be displayed in the cell in the given \a row
|
|
and \a column, passing the ownership of the widget to the table.
|
|
|
|
If cell widget A is replaced with cell widget B, cell widget A will be
|
|
deleted. For example, in the code snippet below, the QLineEdit object will
|
|
be deleted.
|
|
|
|
\snippet code/src_gui_itemviews_qtablewidget.cpp 0
|
|
|
|
\sa cellWidget()
|
|
*/
|
|
void QTableWidget::setCellWidget(int row, int column, QWidget *widget)
|
|
{
|
|
QModelIndex index = model()->index(row, column, QModelIndex());
|
|
QAbstractItemView::setIndexWidget(index, widget);
|
|
}
|
|
|
|
#if QT_DEPRECATED_SINCE(5, 13)
|
|
/*!
|
|
Returns \c true if the \a item is selected, otherwise returns \c false.
|
|
|
|
\obsolete
|
|
|
|
This function is deprecated. Use \l{QTableWidgetItem::isSelected()} instead.
|
|
*/
|
|
|
|
bool QTableWidget::isItemSelected(const QTableWidgetItem *item) const
|
|
{
|
|
return ((item && item->tableWidget() == this) ? item->isSelected() : false);
|
|
}
|
|
|
|
/*!
|
|
Selects or deselects \a item depending on \a select.
|
|
|
|
\obsolete
|
|
|
|
This function is deprecated. Use \l{QTableWidgetItem::setSelected()} instead.
|
|
*/
|
|
void QTableWidget::setItemSelected(const QTableWidgetItem *item, bool select)
|
|
{
|
|
if (item && item->tableWidget() == this)
|
|
const_cast<QTableWidgetItem*>(item)->setSelected(select);
|
|
}
|
|
#endif
|
|
|
|
/*!
|
|
Selects or deselects the \a range depending on \a select.
|
|
*/
|
|
void QTableWidget::setRangeSelected(const QTableWidgetSelectionRange &range, bool select)
|
|
{
|
|
if (!model()->hasIndex(range.topRow(), range.leftColumn(), rootIndex()) ||
|
|
!model()->hasIndex(range.bottomRow(), range.rightColumn(), rootIndex()))
|
|
return;
|
|
|
|
QModelIndex topLeft = model()->index(range.topRow(), range.leftColumn(), rootIndex());
|
|
QModelIndex bottomRight = model()->index(range.bottomRow(), range.rightColumn(), rootIndex());
|
|
|
|
selectionModel()->select(QItemSelection(topLeft, bottomRight),
|
|
select ? QItemSelectionModel::Select : QItemSelectionModel::Deselect);
|
|
}
|
|
|
|
/*!
|
|
Returns a list of all selected ranges.
|
|
|
|
\sa QTableWidgetSelectionRange
|
|
*/
|
|
|
|
QList<QTableWidgetSelectionRange> QTableWidget::selectedRanges() const
|
|
{
|
|
const QList<QItemSelectionRange> ranges = selectionModel()->selection();
|
|
QList<QTableWidgetSelectionRange> result;
|
|
const int rangesCount = ranges.count();
|
|
result.reserve(rangesCount);
|
|
for (int i = 0; i < rangesCount; ++i)
|
|
result.append(QTableWidgetSelectionRange(ranges.at(i).top(),
|
|
ranges.at(i).left(),
|
|
ranges.at(i).bottom(),
|
|
ranges.at(i).right()));
|
|
return result;
|
|
}
|
|
|
|
/*!
|
|
Returns a list of all selected items.
|
|
|
|
This function returns a list of pointers to the contents of the
|
|
selected cells. Use the selectedIndexes() function to retrieve the
|
|
complete selection \e including empty cells.
|
|
|
|
\sa selectedIndexes()
|
|
*/
|
|
|
|
QList<QTableWidgetItem*> QTableWidget::selectedItems() const
|
|
{
|
|
Q_D(const QTableWidget);
|
|
const QModelIndexList indexes = selectionModel()->selectedIndexes();
|
|
QList<QTableWidgetItem*> items;
|
|
for (const auto &index : indexes) {
|
|
if (isIndexHidden(index))
|
|
continue;
|
|
QTableWidgetItem *item = d->tableModel()->item(index);
|
|
if (item)
|
|
items.append(item);
|
|
}
|
|
return items;
|
|
}
|
|
|
|
/*!
|
|
Finds items that matches the \a text using the given \a flags.
|
|
*/
|
|
|
|
QList<QTableWidgetItem*> QTableWidget::findItems(const QString &text, Qt::MatchFlags flags) const
|
|
{
|
|
Q_D(const QTableWidget);
|
|
QModelIndexList indexes;
|
|
for (int column = 0; column < columnCount(); ++column)
|
|
indexes += d->model->match(model()->index(0, column, QModelIndex()),
|
|
Qt::DisplayRole, text, -1, flags);
|
|
QList<QTableWidgetItem*> items;
|
|
const int indexCount = indexes.size();
|
|
items.reserve(indexCount);
|
|
for (int i = 0; i < indexCount; ++i)
|
|
items.append(d->tableModel()->item(indexes.at(i)));
|
|
return items;
|
|
}
|
|
|
|
/*!
|
|
Returns the visual row of the given \a logicalRow.
|
|
*/
|
|
|
|
int QTableWidget::visualRow(int logicalRow) const
|
|
{
|
|
return verticalHeader()->visualIndex(logicalRow);
|
|
}
|
|
|
|
/*!
|
|
Returns the visual column of the given \a logicalColumn.
|
|
*/
|
|
|
|
int QTableWidget::visualColumn(int logicalColumn) const
|
|
{
|
|
return horizontalHeader()->visualIndex(logicalColumn);
|
|
}
|
|
|
|
/*!
|
|
\fn QTableWidgetItem *QTableWidget::itemAt(const QPoint &point) const
|
|
|
|
Returns a pointer to the item at the given \a point, or returns \nullptr if
|
|
\a point is not covered by an item in the table widget.
|
|
|
|
\sa item()
|
|
*/
|
|
|
|
QTableWidgetItem *QTableWidget::itemAt(const QPoint &p) const
|
|
{
|
|
Q_D(const QTableWidget);
|
|
return d->tableModel()->item(indexAt(p));
|
|
}
|
|
|
|
/*!
|
|
Returns the rectangle on the viewport occupied by the item at \a item.
|
|
*/
|
|
QRect QTableWidget::visualItemRect(const QTableWidgetItem *item) const
|
|
{
|
|
Q_D(const QTableWidget);
|
|
if (!item)
|
|
return QRect();
|
|
QModelIndex index = d->tableModel()->index(const_cast<QTableWidgetItem*>(item));
|
|
Q_ASSERT(index.isValid());
|
|
return visualRect(index);
|
|
}
|
|
|
|
/*!
|
|
Scrolls the view if necessary to ensure that the \a item is visible.
|
|
The \a hint parameter specifies more precisely where the
|
|
\a item should be located after the operation.
|
|
*/
|
|
|
|
void QTableWidget::scrollToItem(const QTableWidgetItem *item, QAbstractItemView::ScrollHint hint)
|
|
{
|
|
Q_D(QTableWidget);
|
|
if (!item)
|
|
return;
|
|
QModelIndex index = d->tableModel()->index(const_cast<QTableWidgetItem*>(item));
|
|
Q_ASSERT(index.isValid());
|
|
QTableView::scrollTo(index, hint);
|
|
}
|
|
|
|
/*!
|
|
Returns the item prototype used by the table.
|
|
|
|
\sa setItemPrototype()
|
|
*/
|
|
const QTableWidgetItem *QTableWidget::itemPrototype() const
|
|
{
|
|
Q_D(const QTableWidget);
|
|
return d->tableModel()->itemPrototype();
|
|
}
|
|
|
|
/*!
|
|
Sets the item prototype for the table to the specified \a item.
|
|
|
|
The table widget will use the item prototype clone function when it needs
|
|
to create a new table item. For example when the user is editing
|
|
in an empty cell. This is useful when you have a QTableWidgetItem
|
|
subclass and want to make sure that QTableWidget creates instances of
|
|
your subclass.
|
|
|
|
The table takes ownership of the prototype.
|
|
|
|
\sa itemPrototype()
|
|
*/
|
|
void QTableWidget::setItemPrototype(const QTableWidgetItem *item)
|
|
{
|
|
Q_D(QTableWidget);
|
|
d->tableModel()->setItemPrototype(item);
|
|
}
|
|
|
|
/*!
|
|
Inserts an empty row into the table at \a row.
|
|
*/
|
|
void QTableWidget::insertRow(int row)
|
|
{
|
|
Q_D(QTableWidget);
|
|
d->tableModel()->insertRows(row);
|
|
}
|
|
|
|
/*!
|
|
Inserts an empty column into the table at \a column.
|
|
*/
|
|
void QTableWidget::insertColumn(int column)
|
|
{
|
|
Q_D(QTableWidget);
|
|
d->tableModel()->insertColumns(column);
|
|
}
|
|
|
|
/*!
|
|
Removes the row \a row and all its items from the table.
|
|
*/
|
|
void QTableWidget::removeRow(int row)
|
|
{
|
|
Q_D(QTableWidget);
|
|
d->tableModel()->removeRows(row);
|
|
}
|
|
|
|
/*!
|
|
Removes the column \a column and all its items from the table.
|
|
*/
|
|
void QTableWidget::removeColumn(int column)
|
|
{
|
|
Q_D(QTableWidget);
|
|
d->tableModel()->removeColumns(column);
|
|
}
|
|
|
|
/*!
|
|
Removes all items in the view.
|
|
This will also remove all selections and headers.
|
|
If you don't want to remove the headers, use
|
|
QTableWidget::clearContents().
|
|
The table dimensions stay the same.
|
|
*/
|
|
|
|
void QTableWidget::clear()
|
|
{
|
|
Q_D(QTableWidget);
|
|
selectionModel()->clear();
|
|
d->tableModel()->clear();
|
|
}
|
|
|
|
/*!
|
|
\since 4.2
|
|
|
|
Removes all items not in the headers from the view.
|
|
This will also remove all selections.
|
|
The table dimensions stay the same.
|
|
*/
|
|
void QTableWidget::clearContents()
|
|
{
|
|
Q_D(QTableWidget);
|
|
selectionModel()->clear();
|
|
d->tableModel()->clearContents();
|
|
}
|
|
|
|
/*!
|
|
Returns a list of MIME types that can be used to describe a list of
|
|
tablewidget items.
|
|
|
|
\sa mimeData()
|
|
*/
|
|
QStringList QTableWidget::mimeTypes() const
|
|
{
|
|
return d_func()->tableModel()->QAbstractTableModel::mimeTypes();
|
|
}
|
|
|
|
/*!
|
|
Returns an object that contains a serialized description of the specified
|
|
\a items. The format used to describe the items is obtained from the
|
|
mimeTypes() function.
|
|
|
|
If the list of items is empty, \nullptr is returned rather than a
|
|
serialized empty list.
|
|
*/
|
|
#if QT_VERSION >= QT_VERSION_CHECK(6,0,0)
|
|
QMimeData *QTableWidget::mimeData(const QList<QTableWidgetItem *> &items) const
|
|
#else
|
|
QMimeData *QTableWidget::mimeData(const QList<QTableWidgetItem*> items) const
|
|
#endif
|
|
{
|
|
Q_D(const QTableWidget);
|
|
|
|
QModelIndexList &cachedIndexes = d->tableModel()->cachedIndexes;
|
|
|
|
// if non empty, it's called from the model's own mimeData
|
|
if (cachedIndexes.isEmpty()) {
|
|
cachedIndexes.reserve(items.count());
|
|
for (QTableWidgetItem *item : items)
|
|
cachedIndexes << indexFromItem(item);
|
|
|
|
QMimeData *result = d->tableModel()->internalMimeData();
|
|
|
|
cachedIndexes.clear();
|
|
return result;
|
|
}
|
|
|
|
return d->tableModel()->internalMimeData();
|
|
}
|
|
|
|
/*!
|
|
Handles the \a data supplied by a drag and drop operation that ended with
|
|
the given \a action in the given \a row and \a column.
|
|
Returns \c true if the data and action can be handled by the model;
|
|
otherwise returns \c false.
|
|
|
|
\sa supportedDropActions()
|
|
*/
|
|
bool QTableWidget::dropMimeData(int row, int column, const QMimeData *data, Qt::DropAction action)
|
|
{
|
|
QModelIndex idx;
|
|
#if QT_CONFIG(draganddrop)
|
|
if (dropIndicatorPosition() == QAbstractItemView::OnItem) {
|
|
// QAbstractTableModel::dropMimeData will overwrite on the index if row == -1 and column == -1
|
|
idx = model()->index(row, column);
|
|
row = -1;
|
|
column = -1;
|
|
}
|
|
#endif
|
|
return d_func()->tableModel()->QAbstractTableModel::dropMimeData(data, action , row, column, idx);
|
|
}
|
|
|
|
/*!
|
|
Returns the drop actions supported by this view.
|
|
|
|
\sa Qt::DropActions
|
|
*/
|
|
Qt::DropActions QTableWidget::supportedDropActions() const
|
|
{
|
|
return d_func()->tableModel()->QAbstractTableModel::supportedDropActions() | Qt::MoveAction;
|
|
}
|
|
|
|
/*!
|
|
Returns a list of pointers to the items contained in the \a data object.
|
|
If the object was not created by a QTreeWidget in the same process, the list
|
|
is empty.
|
|
|
|
*/
|
|
QList<QTableWidgetItem*> QTableWidget::items(const QMimeData *data) const
|
|
{
|
|
const QTableWidgetMimeData *twd = qobject_cast<const QTableWidgetMimeData*>(data);
|
|
if (twd)
|
|
return twd->items;
|
|
return QList<QTableWidgetItem*>();
|
|
}
|
|
|
|
/*!
|
|
Returns the QModelIndex associated with the given \a item.
|
|
|
|
\note In Qt versions prior to 5.10, this function took a non-\c{const} \a item.
|
|
*/
|
|
|
|
QModelIndex QTableWidget::indexFromItem(const QTableWidgetItem *item) const
|
|
{
|
|
Q_D(const QTableWidget);
|
|
return d->tableModel()->index(item);
|
|
}
|
|
|
|
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
|
|
/*!
|
|
\internal
|
|
\obsolete
|
|
\overload
|
|
*/
|
|
QModelIndex QTableWidget::indexFromItem(QTableWidgetItem *item) const
|
|
{
|
|
return indexFromItem(const_cast<const QTableWidgetItem *>(item));
|
|
}
|
|
#endif
|
|
|
|
/*!
|
|
Returns a pointer to the QTableWidgetItem associated with the given \a index.
|
|
*/
|
|
|
|
QTableWidgetItem *QTableWidget::itemFromIndex(const QModelIndex &index) const
|
|
{
|
|
Q_D(const QTableWidget);
|
|
return d->tableModel()->item(index);
|
|
}
|
|
|
|
/*!
|
|
\internal
|
|
*/
|
|
void QTableWidget::setModel(QAbstractItemModel * /*model*/)
|
|
{
|
|
Q_ASSERT(!"QTableWidget::setModel() - Changing the model of the QTableWidget is not allowed.");
|
|
}
|
|
|
|
/*! \reimp */
|
|
bool QTableWidget::event(QEvent *e)
|
|
{
|
|
return QTableView::event(e);
|
|
}
|
|
|
|
#if QT_CONFIG(draganddrop)
|
|
/*! \reimp */
|
|
void QTableWidget::dropEvent(QDropEvent *event) {
|
|
Q_D(QTableWidget);
|
|
if (event->source() == this && (event->dropAction() == Qt::MoveAction ||
|
|
dragDropMode() == QAbstractItemView::InternalMove)) {
|
|
QModelIndex topIndex;
|
|
int col = -1;
|
|
int row = -1;
|
|
if (d->dropOn(event, &row, &col, &topIndex)) {
|
|
const QModelIndexList indexes = selectedIndexes();
|
|
int top = INT_MAX;
|
|
int left = INT_MAX;
|
|
for (const auto &index : indexes) {
|
|
top = qMin(index.row(), top);
|
|
left = qMin(index.column(), left);
|
|
}
|
|
|
|
QList<QTableWidgetItem *> taken;
|
|
const int indexesCount = indexes.count();
|
|
taken.reserve(indexesCount);
|
|
for (const auto &index : indexes)
|
|
taken.append(takeItem(index.row(), index.column()));
|
|
|
|
for (const auto &index : indexes) {
|
|
int r = index.row() - top + topIndex.row();
|
|
int c = index.column() - left + topIndex.column();
|
|
setItem(r, c, taken.takeFirst());
|
|
}
|
|
|
|
event->accept();
|
|
// Don't want QAbstractItemView to delete it because it was "moved" we already did it
|
|
event->setDropAction(Qt::CopyAction);
|
|
}
|
|
}
|
|
|
|
QTableView::dropEvent(event);
|
|
}
|
|
#endif
|
|
|
|
QT_END_NAMESPACE
|
|
|
|
#include "moc_qtablewidget.cpp"
|
|
#include "moc_qtablewidget_p.cpp"
|