📄 qtablewidget.cpp
字号:
/******************************************************************************** Copyright (C) 1992-2006 Trolltech ASA. All rights reserved.**** This file is part of the QtGui module of the Qt Toolkit.**** This file may be used under the terms of the GNU General Public** License version 2.0 as published by the Free Software Foundation** and appearing in the file LICENSE.GPL included in the packaging of** this file. Please review the following information to ensure GNU** General Public Licensing requirements will be met:** http://www.trolltech.com/products/qt/opensource.html**** If you are unsure which license is appropriate for your use, please** review the following information:** http://www.trolltech.com/products/qt/licensing.html or contact the** sales department at sales@trolltech.com.**** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.******************************************************************************/#include "qtablewidget.h"#ifndef QT_NO_TABLEWIDGET#include <qheaderview.h>#include <qitemdelegate.h>#include <qpainter.h>#include <qabstractitemmodel.h>#include <private/qabstractitemmodel_p.h>#include <private/qtableview_p.h>#include <private/qwidgetitemdata_p.h>// workaround for VC++ 6.0 linker bugtypedef bool(*LessThan)(const QPair<QTableWidgetItem*,int>&,const QPair<QTableWidgetItem*,int>&);class QTableWidgetMimeData : public QMimeData{ Q_OBJECTpublic: QList<QTableWidgetItem*> items;};class QTableModel : public QAbstractTableModel{ Q_OBJECTpublic: enum ItemFlagsExtension { ItemIsVerticalHeaderItem = Qt::ItemIsTristate * 2, ItemIsHorizontalHeaderItem = Qt::ItemIsTristate * 4 }; // we need this to separate header items from other items QTableModel(int rows, int columns, QTableWidget *parent); ~QTableModel(); bool insertRows(int row, int count = 1, const QModelIndex &parent = QModelIndex()); bool insertColumns(int column, int count = 1, const QModelIndex &parent = QModelIndex()); bool removeRows(int row, int count = 1, const QModelIndex &parent = QModelIndex()); bool removeColumns(int column, int count = 1, const QModelIndex &parent = QModelIndex()); void setItem(int row, int column, QTableWidgetItem *item); QTableWidgetItem *takeItem(int row, int column); QTableWidgetItem *item(int row, int column) const; QTableWidgetItem *item(const QModelIndex &index) const; void removeItem(QTableWidgetItem *item); void setHorizontalHeaderItem(int section, QTableWidgetItem *item); QTableWidgetItem *takeHorizontalHeaderItem(int section); void setVerticalHeaderItem(int section, QTableWidgetItem *item); QTableWidgetItem *takeVerticalHeaderItem(int section); QTableWidgetItem *horizontalHeaderItem(int section); QTableWidgetItem *verticalHeaderItem(int section); QModelIndex index(const QTableWidgetItem *item) const; void setRowCount(int rows); void setColumnCount(int columns); int rowCount(const QModelIndex &parent = QModelIndex()) const; int columnCount(const QModelIndex &parent = QModelIndex()) const; QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; bool setData(const QModelIndex &index, const QVariant &value, int role); QVariant headerData(int section, Qt::Orientation orientation, int role) const; bool setHeaderData(int section, Qt::Orientation orientation, const QVariant &value, int role); Qt::ItemFlags flags(const QModelIndex &index) const; void sort(int column, Qt::SortOrder order); static bool itemLessThan(const QPair<QTableWidgetItem*,int> &left, const QPair<QTableWidgetItem*,int> &right); static bool itemGreaterThan(const QPair<QTableWidgetItem*,int> &left, const QPair<QTableWidgetItem*,int> &right); bool isValid(const QModelIndex &index) const; inline long tableIndex(int row, int column) const { return (row * horizontal.count()) + column; } void clear(); void itemChanged(QTableWidgetItem *item); inline QTableWidgetItem *createItem() const { return prototype ? prototype->clone() : new QTableWidgetItem; } inline const QTableWidgetItem *itemPrototype() const { return prototype; } inline void setItemPrototype(const QTableWidgetItem *item) { prototype = item; } // dnd QStringList mimeTypes() const; QMimeData *mimeData(const QModelIndexList &indexes) const; bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent); Qt::DropActions supportedDropActions() const; QMimeData *internalMimeData() const;private: const QTableWidgetItem *prototype; QVector<QTableWidgetItem*> table; QVector<QTableWidgetItem*> vertical; QVector<QTableWidgetItem*> horizontal; // A cache must be mutable if get-functions should have const modifiers mutable QModelIndexList cachedIndexes;};#include "qtablewidget.moc"QTableModel::QTableModel(int rows, int columns, QTableWidget *parent) : QAbstractTableModel(parent), prototype(0), table(rows * columns, 0), vertical(rows, 0), horizontal(columns, 0){}QTableModel::~QTableModel(){ clear();}bool QTableModel::insertRows(int row, int count, const QModelIndex &){ if (count < 1 || row < 0 || row > vertical.count()) return false; beginInsertRows(QModelIndex(), row, row + count - 1); int rc = vertical.count(); int cc = horizontal.count(); vertical.insert(row, count, 0); if (rc == 0) table.resize(cc * count); else table.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 > horizontal.count()) return false; beginInsertColumns(QModelIndex(), column, column + count - 1); int rc = vertical.count(); int cc = horizontal.count(); horizontal.insert(column, count, 0); if (cc == 0) table.resize(rc * count); else for (int row = 0; row < rc; ++row) table.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 > vertical.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 = table.at(j); if (oldItem) oldItem->model = 0; delete oldItem; } table.remove(qMax(i, 0), n); for (int v=row; v<row+count; ++v) { oldItem = vertical.at(v); if (oldItem) oldItem->model = 0; delete oldItem; } vertical.remove(row, count); endRemoveRows(); return true;}bool QTableModel::removeColumns(int column, int count, const QModelIndex &){ if (count < 1 || column < 0 || column + count > horizontal.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 = table.at(j); if (oldItem) oldItem->model = 0; delete oldItem; } table.remove(i, count); } for (int h=column; h<column+count; ++h) { oldItem = horizontal.at(h); if (oldItem) oldItem->model = 0; delete oldItem; } horizontal.remove(column, count); endRemoveColumns(); return true;}void QTableModel::setItem(int row, int column, QTableWidgetItem *item){ int i = tableIndex(row, column); if (i < 0 || i >= table.count()) return; QTableWidgetItem *oldItem = table.at(i); if (item == oldItem) return; // remove old if (oldItem) oldItem->model = 0; delete table.at(i); // set new if (item) item->model = this; table[i] = item; QModelIndex idx = QAbstractTableModel::index(row, column); emit dataChanged(idx, idx);}QTableWidgetItem *QTableModel::takeItem(int row, int column){ long i = tableIndex(row, column); QTableWidgetItem *itm = table.value(i); if (itm) { itm->model = 0; table[i] = 0; } return itm;}QTableWidgetItem *QTableModel::item(int row, int column) const{ return table.value(tableIndex(row, column));}QTableWidgetItem *QTableModel::item(const QModelIndex &index) const{ if (!isValid(index)) return 0; return table.at(tableIndex(index.row(), index.column()));}void QTableModel::removeItem(QTableWidgetItem *item){ int i = table.indexOf(item); if (i != -1) { table[i] = 0; QModelIndex idx = index(item); emit dataChanged(idx, idx); return; } i = vertical.indexOf(item); if (i != -1) { vertical[i] = 0; emit headerDataChanged(Qt::Vertical, i, i); return; } i = horizontal.indexOf(item); if (i != -1) { horizontal[i] = 0; emit headerDataChanged(Qt::Horizontal, i, i); return; }}void QTableModel::setHorizontalHeaderItem(int section, QTableWidgetItem *item){ if (section < 0 || section >= horizontal.count()) return; QTableWidgetItem *oldItem = horizontal.at(section); if (item == oldItem) return; if (oldItem) oldItem->model = 0; delete oldItem; if (item) item->model = this; horizontal[section] = item; emit headerDataChanged(Qt::Horizontal, section, section);}QTableWidgetItem *QTableModel::takeHorizontalHeaderItem(int section){ if (section < 0 || section >= horizontal.count()) return 0; QTableWidgetItem *itm = horizontal.at(section); if (itm) { itm->model = 0; horizontal[section] = 0; } return itm;}void QTableModel::setVerticalHeaderItem(int section, QTableWidgetItem *item){ if (section < 0 || section >= vertical.count()) return; QTableWidgetItem *oldItem = vertical.at(section); if (item == oldItem) return; if (oldItem) oldItem->model = 0; delete oldItem; if (item) item->model = this; vertical[section] = item; emit headerDataChanged(Qt::Vertical, section, section);}QTableWidgetItem *QTableModel::takeVerticalHeaderItem(int section){ if (section < 0 || section >= vertical.count()) return 0; QTableWidgetItem *itm = vertical.at(section); if (itm) { itm->model = 0; vertical[section] = 0; } return itm;}QTableWidgetItem *QTableModel::horizontalHeaderItem(int section){ return horizontal.value(section);}QTableWidgetItem *QTableModel::verticalHeaderItem(int section){ return vertical.value(section);}QModelIndex QTableModel::index(const QTableWidgetItem *item) const{ int i = table.indexOf(const_cast<QTableWidgetItem*>(item)); int row = i / columnCount(); int col = i % columnCount(); return QAbstractTableModel::index(row, col);}void QTableModel::setRowCount(int rows){ int rc = vertical.count(); if (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 = horizontal.count(); if (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 : vertical.count();}int QTableModel::columnCount(const QModelIndex &parent) const{ return parent.isValid() ? 0 : horizontal.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;}Qt::ItemFlags QTableModel::flags(const QModelIndex &index) const{ if (!index.isValid()) return Qt::ItemIsDropEnabled; QTableWidgetItem *itm = item(index); if (itm) return itm->flags(); return (Qt::ItemIsEditable |Qt::ItemIsSelectable |Qt::ItemIsUserCheckable |Qt::ItemIsEnabled);}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) { QTableWidgetItem *itm = item(row, column); if (itm) sortable.append(QPair<QTableWidgetItem*,int>(itm, row)); else unsortable.append(row); } LessThan compare = (order == Qt::AscendingOrder ? &itemLessThan : &itemGreaterThan); qSort(sortable.begin(), sortable.end(), compare); QVector<QTableWidgetItem*> sorted_table(table.count()); QModelIndexList from; QModelIndexList to; for (int i = 0; i < rowCount(); ++i) { int r = (i < sortable.count() ? sortable.at(i).second : unsortable.at(i - sortable.count())); for (int c = 0; c < columnCount(); ++c) { QTableWidgetItem *itm = item(r, c); sorted_table[tableIndex(i, c)] = itm; from << createIndex(r, c, 0); to << createIndex(i, c, 0); } } table = sorted_table; changePersistentIndexList(from, to); // ### slow emit layoutChanged();}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 !(*(left .first) < *(right.first));}QVariant QTableModel::headerData(int section, Qt::Orientation orientation, int role) const{ QTableWidgetItem *itm = 0; if (section < 0) return QVariant(); if (orientation == Qt::Horizontal && section < horizontal.count()) itm = horizontal.at(section); else if (section < vertical.count()) itm = vertical.at(section); 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 && horizontal.size() <= section) || (orientation == Qt::Vertical && vertical.size() <= section)) return false; QTableWidgetItem *itm = 0; if (orientation == Qt::Horizontal) itm = horizontal.at(section); else itm = vertical.at(section); if (itm) { itm->setData(role, value); return true; } return false;}bool QTableModel::isValid(const QModelIndex &index) const{ return index.isValid() && index.row() < vertical.count() && index.column() < horizontal.count();}void QTableModel::clear(){ for (int i = 0; i < table.count(); ++i) { if (table.at(i)) { table.at(i)->model = 0; delete table.at(i); table[i] = 0; } } for (int j = 0; j < vertical.count(); ++j) { if (vertical.at(j)) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -