Содержатся такие свойства как index(), ItemDataRole(), flags(), match()
DataRole- содержит много разных вариантов ролей данных
ListModel- простой, одномерный список
StandartItemModel- гораздо более сложная структура, каждая запись является отдельным итемом, с возможностью его настройки со-но.
Для использования, абстрактные классы необходимо наследовать, для работы необходимо определить как минимум три функции: rowCount(), ColumnCount() и data().
Для хранения данных, внутри собственного класса, похоже нужно создавать собственные структуры данных, контейнеры и т.д. и сосбна обрабатывать их.
Используется в качестве индекса в моделях, используется представлениями, делегатами, моделям выбора и поиска элементов.
Новые объекты создаются с помощью функции QAbstractItemModel::createIndex(), недействительный может быть построен с помощью конструктора QModelIndex(), недействительные часто используются в качестве родительских индексов, верхнего уровня.
Индексы относятся к элементам и содержат всю информацию, необходимую для определения их местоположения.
QAbstractItemModel::index()- возвращает индекс на существующий элемент.
bool isValid() | true если индекс принадлежит модели и имеет неотрицательные номера столбцов/строк |
QModelIndex sibling() | возвращает «родственника» в указанной позиции оО |
QVariant data() | возвращает данные для указанной роли |
В ф-ции beginInsertColumn/beginInsertRow, нужно передавать корректные индексы, если передавать нули, то происходит вставка только одной записи, если не корректные цифры то все вообще по п*зде идет.
Вставлять элементы можно как сразу в объект хранения (вектор/лист) так и ф-ями insertColumn/insertRow.
class VectorTableModel; class MWin : public QMainWindow { Q_OBJECT VectorTableModel *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 VectorTableModel: public QAbstractTableModel { Q_OBJECT QVector<QVector<QString> *> *LisIsData; QVector<QString> *HeadersList; public: VectorTableModel(QObject *parent= nullptr); ~VectorTableModel(); // Минимальные 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 addRow(const QVector<QString> &vValues); void addColumn(qint32 vCount); void delRow(const qint32 &vNumberRow); void delColumn(const qint32 &vNumberCol); };
#include "mwin.h" MWin::MWin(QWidget *parent): QMainWindow(parent) { VModelTab= new VectorTableModel(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 count"); return; } VModelTab->addColumn(editDataForWrite->text().toInt()); editDataForWrite->clear(); editDataForWrite->setFocus(); } void MWin::slotDeleteSelectedRecord() { VModelTab->delRow(VViewTab->currentIndex().row()); } void MWin::slotDeleteSelectedColumn() { VModelTab->delColumn(VViewTab->currentIndex().column()); } //*********************************************************************| //*********************************************************************| VectorTableModel::VectorTableModel(QObject *parent): QAbstractTableModel(parent) { LisIsData= new QVector<QVector<QString>* >; HeadersList= new QVector<QString>; } VectorTableModel::~VectorTableModel() { while(!LisIsData->isEmpty()) delete LisIsData->takeFirst(); delete LisIsData; delete HeadersList; } QVariant VectorTableModel::data(const QModelIndex &index, int role) const { if(role== Qt::DisplayRole) return LisIsData->at(index.row())->at(index.column()); return QVariant(); } int VectorTableModel::rowCount(const QModelIndex &parent) const { Q_UNUSED(parent); return LisIsData->count(); } int VectorTableModel::columnCount(const QModelIndex &parent) const { Q_UNUSED(parent); return LisIsData->isEmpty() ? 0:LisIsData->at(0)->count(); } QVariant VectorTableModel::headerData(int section, Qt::Orientation orientation, int role) const { if(role!= Qt::DisplayRole) return QVariant(); if(orientation== Qt::Horizontal) return HeadersList->count() > section ? HeadersList->at(section):""; else return QString::number(section +1); } bool VectorTableModel::setData(const QModelIndex &index, const QVariant &value, int role) { if(index.isValid() && role== Qt::EditRole) { LisIsData->at(index.row())->replace(index.column(), value.toString()); emit dataChanged(index, index); return true; } return false; } void VectorTableModel::addRow(const QVector<QString> &vValues) { beginInsertRows(QModelIndex(), rowCount(), rowCount()); QVector<QString> *vNewRow= new QVector<QString>(vValues); // Подгоняем кол-во столбцов, к большему, либо в гриде (векторе) либо в новой строке if(columnCount() > vNewRow->count()) vNewRow->resize(this->columnCount()); else if(columnCount() < vNewRow->count()) { beginInsertColumns(QModelIndex(), columnCount(), columnCount()+ (vNewRow->count()- columnCount()) -1); for(qint32 i= 0; i < LisIsData->count(); i++) LisIsData->at(i)->resize(vNewRow->count()); endInsertColumns(); } LisIsData->append(vNewRow); endInsertRows(); } void VectorTableModel::addColumn(qint32 vCount) { beginInsertColumns(QModelIndex(), columnCount(), columnCount()+ vCount -1); while(vCount--) this->insertColumn(columnCount()); endInsertColumns(); } void VectorTableModel::delRow(const qint32 &vNumberRow) { beginInsertRows(QModelIndex(), vNumberRow, vNumberRow); if(LisIsData->count() > vNumberRow) LisIsData->remove(vNumberRow); endInsertRows(); } void VectorTableModel::delColumn(const qint32 &vNumberCol) { beginInsertColumns(QModelIndex(), vNumberCol, vNumberCol); if(HeadersList->count() > vNumberCol) HeadersList->remove(vNumberCol); for(qint32 i= 0; i < LisIsData->count(); i++) LisIsData->at(i)->remove(vNumberCol); endInsertColumns(); }