Это старая версия документа!
Содержатся такие свойства как index(), ItemDataRole(), flags(), match()
DataRole- содержит много разных вариантов ролей данных
ListModel- простой, одномерный список
StandartItemModel- гораздо более сложная структура, каждая запись является отдельным итемом, с возможностью его настройки со-но.
Для использования, абстрактные классы необходимо наследовать, для работы необходимо определить как минимум три функции: rowCount(), ColumnCount() и data().
Для хранения данных, внутри собственного класса, похоже нужно создавать собственные структуры данных, контейнеры и т.д. и сосбна обрабатывать их.
Используется в качестве индекса в моделях, используется представлениями, делегатами, моделям выбора и поиска элементов.
Новые объекты создаются с помощью функции QAbstractItemModel::createIndex(), недействительный может быть построен с помощью конструктора QModelIndex(), недействительные часто используются в качестве родительских индексов, верхнего уровня.
Индексы относятся к элементам и содержат всю информацию, необходимую для определения их местоположения.
QAbstractItemModel::index()- возвращает индекс на существующий элемент.
bool isValid() | true если индекс принадлежит модели и имеет неотрицательные номера столбцов/строк |
QModelIndex sibling() | возвращает «родственника» в указанной позиции оО |
QVariant data() | возвращает данные для указанной роли |
class myTableModel; class MWin : public QMainWindow { Q_OBJECT myTableModel *VModelTab; QTableView *VViewTab; QLineEdit *editDataForWrite; QPushButton *butAddRecord, *butAddColumn, *butDelRecord, *butDelColumn; public: MWin(QWidget *parent = nullptr); public slots: void slotInsertNewRecord(); void slotInsertNewColumn(); void slotDeleteSelectedRecord(); void slotDeleteSelectedColumn(); }; class myTableModel: public QAbstractTableModel { Q_OBJECT QList<QList<QString> *> myDataInCell; // Независимый список столбцов плох тем что при удалении, // содержимое таблицы ведь не удаляется QList<QString *> ListHeaders; public: myTableModel(QObject *parent= nullptr); // Минимальные ф-ии QVariant data(const QModelIndex &index, int role= Qt::DisplayRole) const; int rowCount(const QModelIndex &parent= QModelIndex()) const; int columnCount(const QModelIndex &parent= QModelIndex()) const; // Переопределенные QVariant headerData(int section, Qt::Orientation orientation, int role) const; bool setData(const QModelIndex &index, const QVariant &value, int role); // Собственные void addDataRow(const QList<QString> &vValues); void addColumn(const QString&); void delRow(qint32 NumberRow); void delColumn(qint32 NumberCol); };
#include "mwin.h" MWin::MWin(QWidget *parent): QMainWindow(parent) { VModelTab= new myTableModel(this); VViewTab= new QTableView(this); VViewTab->setModel(VModelTab); VViewTab->setSelectionBehavior(QAbstractItemView::SelectionBehavior::SelectRows); editDataForWrite= new QLineEdit(this); butAddRecord= new QPushButton("Новая запись", this); butAddColumn= new QPushButton("Новый столбец", this); QHBoxLayout *layCtrls= new QHBoxLayout(); layCtrls->addWidget(editDataForWrite, 1); layCtrls->addWidget(butAddRecord, 0); layCtrls->addWidget(butAddColumn, 0); butDelRecord= new QPushButton("Удалить строку", this); butDelColumn= new QPushButton("Удалить столбец", this); QHBoxLayout *laySecondCtrls= new QHBoxLayout(); laySecondCtrls->addWidget(butDelRecord); laySecondCtrls->addWidget(butDelColumn); QVBoxLayout *layMain= new QVBoxLayout(); layMain->addWidget(VViewTab, 2); layMain->addLayout(layCtrls); layMain->addLayout(laySecondCtrls); QWidget *myWindow= new QWidget(); myWindow->setLayout(layMain); setCentralWidget(myWindow); connect(butAddRecord, &QPushButton::clicked, this, &MWin::slotInsertNewRecord); connect(butAddColumn, &QPushButton::clicked, this, &MWin::slotInsertNewColumn); connect(butDelRecord, &QPushButton::clicked, this, &MWin::slotDeleteSelectedRecord); connect(butDelColumn, &QPushButton::clicked, this, &MWin::slotDeleteSelectedColumn); } void MWin::slotInsertNewRecord() { if(editDataForWrite->text().isEmpty()) { QMessageBox::information(this, "Text", "Please input text"); return; } VModelTab->addDataRow(editDataForWrite->text().split(";", Qt::SkipEmptyParts)); editDataForWrite->clear(); editDataForWrite->setFocus(); } void MWin::slotInsertNewColumn() { if(editDataForWrite->text().isEmpty()) { QMessageBox::information(this, "Text", "Please input text"); return; } VModelTab->addColumn(editDataForWrite->text()); editDataForWrite->clear(); editDataForWrite->setFocus(); } void MWin::slotDeleteSelectedRecord() { VModelTab->delRow(VViewTab->currentIndex().row()); } void MWin::slotDeleteSelectedColumn() { VModelTab->delColumn(VViewTab->currentIndex().column()); } //*********************************************************************| //*********************************************************************| myTableModel::myTableModel(QObject *parent): QAbstractTableModel(parent) { } // QList->value()- проверяет границы; ->at()- быстрее но не проверяет границы // []- создает копию списка, если он является общим во время обращения, полезно для редактирования QVariant myTableModel::data(const QModelIndex &index, int role) const { if(role== Qt::DisplayRole) // || (==Qt::EditRole)|| (==Qt::BackgroundRole) return myDataInCell.value(index.row())->value(index.column()); return QVariant(); } int myTableModel::columnCount(const QModelIndex &parent) const { Q_UNUSED(parent); // Просто чтобы не было варнинга о неиспользуемой переменной return ListHeaders.count(); } int myTableModel::rowCount(const QModelIndex &parent) const { Q_UNUSED(parent); return myDataInCell.count(); } void myTableModel::addDataRow(const QList<QString> &vValues) { // Единственное только с цифрами тут: вообще это координаты новых строк, // вставляем мы тут по одной, хз, с нолями работает, с некоторыми значениями не работает this->beginInsertRows(QModelIndex(), 0, 0); myDataInCell.append(new QList<QString>(vValues)); this->endInsertRows(); } QVariant myTableModel::headerData(int section, Qt::Orientation orientation, int role) const { if(role != Qt::DisplayRole) return QVariant(); if(orientation == Qt::Horizontal) return *ListHeaders.value(section); else return QString::number(section +1); // номера строк } void myTableModel::addColumn(const QString &vNameNewCol) { this->beginInsertColumns(QModelIndex(), 0, 0); ListHeaders.append(new QString(vNameNewCol)); this->endInsertColumns(); } void myTableModel::delRow(qint32 NumberRow) { this->beginRemoveRows(QModelIndex(), 0,0); delete myDataInCell.value(NumberRow); // Освобождение ячейки памяти myDataInCell.removeAt(NumberRow); // Удаление ссылки на нее из списка this->endRemoveRows(); } void myTableModel::delColumn(qint32 NumberCol) { this->beginRemoveColumns(QModelIndex(), 0,0); delete ListHeaders.value(NumberCol); ListHeaders.removeAt(NumberCol); this->endRemoveColumns(); } // Еще не используется, нужна для редактирования записей bool myTableModel::setData(const QModelIndex &index, const QVariant &value, int role) { if(index.isValid() && role== Qt::EditRole) { // ??? Проверка границ списка ??? myDataInCell[index.row()]->replace(index.column(), value.toString()); emit dataChanged(index, index); return true; } return false; }