/****************************************************************************
**
** 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(0),
      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 = 0;
    for (int j = i; j < n + i; ++j) {
        oldItem = tableItems.at(j);
        if (oldItem)
            oldItem->view = 0;
        delete oldItem;
    }
    tableItems.remove(qMax(i, 0), n);
    for (int v = row; v < row + count; ++v) {
        oldItem = verticalHeaderItems.at(v);
        if (oldItem)
            oldItem->view = 0;
        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 = 0;
    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 = 0;
            delete oldItem;
        }
        tableItems.remove(i, count);
    }
    for (int h=column; h<column+count; ++h) {
        oldItem = horizontalHeaderItems.at(h);
        if (oldItem)
            oldItem->view = 0;
        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 = 0;
    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 == 0) {
            // 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 = 0;
        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 0;
    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 = 0;
    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 = 0;
    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 0;
    QTableWidgetItem *itm = horizontalHeaderItems.at(section);
    if (itm) {
        itm->view = 0;
        itm->itemFlags &= ~ItemIsHeaderItem;
        horizontalHeaderItems[section] = 0;
    }
    return itm;
}

QTableWidgetItem *QTableModel::takeVerticalHeaderItem(int section)
{
    if (section < 0 || section >= verticalHeaderItems.count())
        return 0;
    QTableWidgetItem *itm = verticalHeaderItems.at(section);
    if (itm) {
        itm->view = 0;
        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 == 0) {
            // 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 == 0) {
            // 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 = 0;
    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 = 0;
    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 = 0;
            delete verticalHeaderItems.at(j);
            verticalHeaderItems[j] = 0;
        }
    }
    for (int k = 0; k < horizontalHeaderItems.count(); ++k) {
        if (horizontalHeaderItems.at(k)) {
            horizontalHeaderItems.at(k)->view = 0;
            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 = 0;
            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) : 0);
    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 &other) = default;
QTableWidgetSelectionRange &QTableWidgetSelectionRange::operator=(const QTableWidgetSelectionRange &other) = 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, 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.

    \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.

    \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 &current,
                                                 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 = 0;
    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 = 0;
    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 = 0;
    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 = 0;
    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 = 0;
    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"
