Reputation: 1883
I need some general advice to point me in the correct direction of solving this problem: I have a .txt file with table data like the following:
Time Pin
11:00 EIO4
12:55 EIO6
16:40 EIO4
20:10 EIO3
etc......
I need to be able to parse this .txt file. Then I need to display this table in Qt (perhaps in a QTableView
).
I have looked into using QTableView, and it appears I pass a QAbstractItemModel*
to the QTableView
using QTableView::setModel(QAbstractItemModel* model)
, after which my QTableView will display whatever data is in the QAbstractItemModel (right?).
If that last paragraph was logical, then my next question is how do I construct a QAbstractItemModel
using my .txt file? I don't see any functions in the documentation that do this? (Note: someone suggested creating a QStandardItemModel)
(Note, this paragraph is no longer relevant) QModelIndex createIndex(int row, int column, void* ptr)
appears to have something to do with this, maybe? Maybe this creates a QModelIndex
that can be passed to the QAbstractItemModel
using QAbstractItemModel::insertRow(QModelIndex)
? However I still don't know how to make these QModelIndex
objects have anything to do with my .txt data.
QStandardItemModel
documentation says
When you want a list or tree, you typically create an empty
QStandardItemModel
and useappendRow()
to add items to the model, anditem()
to access an item. If your model represents a table, you typically pass the dimensions of the table to theQStandardItemModel
constructor and usesetItem()
to position items into the table. You can also usesetRowCount()
andsetColumnCount()
to alter the dimensions of the model. To insert items, useinsertRow()
orinsertColumn()
, and to remove items, useremoveRow()
orremoveColumn()
.
These functions that "add rows" take QList<QStandardItem*>
's as arguments, so I need to create QLists that each contain pointers QStandardItems that contain each cell's data?
So I will use
void QStandardItemModel::insertRow(int row, const QList<QStandardItem *> & items)
http://doc.qt.io/qt-5/qstandarditemmodel.html#insertRow
Along with an argument QList<QStandardItem*>
generated by repeated calls of "<<
" passing QStandardItem*
pointers to an empty QList
.
I will make QStandardItem
's using the constructor
QStandardItem::QStandardItem(const QString & text)
where I get my QString text
by parsing a QFile into QStrings.
Everything looking good?
Or maybe I should skip creating QLists and go directly from generating QStandardItem
's to passing them into the QStandardItemModel
using void QStandardItemModel::setItem(int row, int column, QStandardItem * item)
Edit: I ended up skipping creating QLists with the following process: QFile file -> QString line -> QStringList peices -> QStandardItem -> QStandardItemModel -> QTableView
Thanks to all who contributed
Upvotes: 0
Views: 1250
Reputation: 5207
For the original question, i.e. how to create a custom model: this is fairly easy because there is a convenience base class for table models, QAbstractTableModel
which implements most of the hairy methods of the general model interface.
The first step for a custom table model is to decide on a data type for a single row, e.g.
struct Data
{
QTime time;
QString pin;
};
The custom model can then operate on a list or vector of that type.
class MyModel : public QAbstractItemModel
{
private:
QVector<Data> m_data;
};
The rowCount()
method can then simply be implemented by returning the size/count of the list/vector, columnCount()
is fixed (2 in this example) and data()
can simply access the n-th entry and switch on requested column:
QVariant MyModel::data(const QModelIndex &index, int role) const
{
const Data &rowData = m_data[index.row()];
switch (index.row()) {
case 0: {
if (role == Qt::DisplayRole) return rowData.time.toString("hh:mm"); // or whatever format you'd like
else if (role == Qt::EditRole) return rowData.time; // return as QTime
break;
}
case 1: if (role == Qt::DisplayRole || role == Qt::EditRole) return rowData.pin;
break;
default: break;
}
return QVariant();
}
Optionally implement headerData()
to to get "Time" and "PIN" as the column headers
Upvotes: 0
Reputation: 1976
Your approach is correct. You can use QStandardItemModel for your data.
QStandardItemModel *model = new QStandardItemModel(2,3,this);
model->setHorizontalHeaderItem(0, new QStandardItem(QString("Column1 Header")));
model->setHorizontalHeaderItem(1, new QStandardItem(QString("Column2 Header")));
model->setHorizontalHeaderItem(2, new QStandardItem(QString("Column3 Header")));
ui->tableView->setModel(model);
Than you can add values:
QStandardItem *firstRow = new QStandardItem(QString("ColumnValue"));
model->setItem(0,0,firstRow);
Upvotes: 0