View Full Version : How to store data in a tablemodel
rubikon
9th August 2012, 08:25
Hello.
I'm new to model view programming but I've successfully implemented a model inherited from QAbstractListModel:
class PaletteListModel : public QAbstractListModel
{
Q_OBJECT
public:
explicit PaletteListModel(QList<QColor> colors, QObject *parent);
int rowCount(const QModelIndex &parent = QModelIndex()) const;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
...
...
...
private:
QList<QColor> m_colors;
};
PaletteListModel::PaletteListModel(QList<QColor> colors, QObject *parent) :
QAbstractListModel(parent)
{
m_colors = colors;
}
int PaletteListModel::rowCount(const QModelIndex & ) const
{
return m_colors.count();
}
...
...
So I can pass a list which can have a dynamic length to the constructor which will be stored in a private field. With this I can determine the row count...
But how can I pass and store the data for a table model? I guess it has to be some kind of nested list. But I can't figure out how exactly to do this:
class PaletteTableModel : public QAbstractTableModel
{
Q_OBJECT
public:
explicit PaletteTableModel(??????? colors, QObject *parent);
int rowCount(const QModelIndex &parent = QModelIndex()) const;
int columnCount(const QModelIndex &parent = QModelIndex())) const;
private:
???????? m_colors;
};
PaletteTableModel::PaletteTableModel(??????? colors, QObject *parent) :
QAbstractTableModel(parent)
{
m_colors = colors;
}
int PaletteTableModel::rowCount(const QModelIndex & ) const
{
return ?????
}
int PaletteTableModel::columnCount(const QModelIndex &) const
{
return ?????
}
...
...
...
How do I have to implement this?
spirit
9th August 2012, 08:48
Not sure what you need. Can you clarify your thoughts?
rubikon
9th August 2012, 10:02
I want to have a model which stores a table of colors.
So basically: What do I have to write for the question marks in the second Qt Code of my first post?
spirit
9th August 2012, 10:06
Well, you already have the list of private colors -- it is the storage of the model.
You need to implement QAbstractItemModel::data (to display your colors), QAbstractItemModel::setData (to change existing colors), QAbstractItemModel::insertRows (to insert new colors), QAbstractItemModel::removeRows (to remove colors).
This is good stuff for reading (http://qt-project.org/doc/qt-4.8/model-view-programming.html#model-subclassing-reference).
rubikon
9th August 2012, 10:27
Well, you already have the list of private colors -- it is the storage of the model.
As I have written, implementing a list works fine. Now I want to implement a table not a list.
And I don't know how to store and pass the the two dimensional data through the constructor. For the one dimensional data I used QList<QColor> as I have written in the first Qt Code of my first posting.
But what 'datatype' or 'datastructure' do I have to use for an two dimensional data? Marked with question marks in the second Qt Code of my first post.
You need to implement QAbstractItemModel::data (to display your colors), QAbstractItemModel::setData (to change existing colors), QAbstractItemModel::insertRows (to insert new colors), QAbstractItemModel::removeRows (to remove colors).
This is good stuff for reading (http://qt-project.org/doc/qt-4.8/model-view-programming.html#model-subclassing-reference).
I'm aware of that and already know how to do that. What I don't know is how to pass two dimensional data through the constructor, store the two dimensional data and determine the range of my two dimensional data in rowCount(const QModelIndex & ) and columnCount(const QModelIndex &) const.
spirit
9th August 2012, 10:33
Okay, got it.
Yes, you should use nested lists or vectors in this case.
rubikon
9th August 2012, 11:27
Okay, thank you. But how do I have to do it? Could you complete the second Qt code for my first post, so I can see how to do it?
spirit
9th August 2012, 12:31
class PaletteTableModel : public QAbstractTableModel
{
Q_OBJECT
public:
explicit PaletteTableModel(const QList<QList<QColor> > &colors, QObject *parent);
int rowCount(const QModelIndex &parent = QModelIndex()) const;
int columnCount(const QModelIndex &parent = QModelIndex())) const;
private:
QList<QList<QColor> > m_colors; //suppose the first list keeps rows, the second -- columns
};
PaletteTableModel::PaletteTableModel(const QList<QList<QColor> > &colors, QObject *parent) :
QAbstractTableModel(parent), m_colors(colors)
{
}
int PaletteTableModel::rowCount(const QModelIndex &) const
{
return m_colors.count();
}
int PaletteTableModel::columnCount(const QModelIndex &index) const
{
//TODO: add an index checks and boundary checks
return m_colors.at(index.row()).count();
}
...
...
...
rubikon
13th August 2012, 13:21
Thank you for your completion. I have tried to complete the code:
PaletteTableModel::PaletteTableModel(QList< QList<QColor> > colors, QObject *parent) :
QAbstractTableModel(parent)
{
m_colors = colors;
}
int PaletteTableModel::rowCount(const QModelIndex & ) const
{
return m_colors.count();
}
int PaletteTableModel::columnCount(const QModelIndex &index) const
{
return m_colors.at(index.row()).count();
}
For the first try I passed an empty list to the constructor:
private:
PaletteTableModel *m_model;
QList< QList<QColor> > m_list;
...
...
m_model = new PaletteTableModel(m_list, this);
ui->tableView->setModel(m_model);
But setModel fails with
---------------------------
Microsoft Visual C++ Runtime Library
---------------------------
This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.
---------------------------
OK
---------------------------
Where is the problem?
spirit
13th August 2012, 13:25
I think the problem is here
int PaletteTableModel::columnCount(const QModelIndex &index) const
{
return m_colors.at(index.row()).count();
}
You are not checking the index. That leads to error in QList::at -- wrong range.
I specially added TODO in this method definition.
rubikon
13th August 2012, 14:15
I'm not able to implement a check...
The first thing I've tried is this
int PaletteTableModel::columnCount(const QModelIndex &index) const
{
if(index.row() > (m_colors.count() - 1))
return 0;
if(index.column() > (m_colors.at(index.row()).count()) - 1)
return 0;
return m_colors.at(index.row()).count();
}
But the function is getting called with index.row() = -1. Why gets the function called with index.row() = -1?
So I extended the function
int PaletteTableModel::columnCount(const QModelIndex &index) const
{
if(index.row() < 0)
return 0;
if(index.row() > (m_colors.count() - 1))
return 0;
if(index.column() > (m_colors.at(index.row()).count()) - 1)
return 0;
return m_colors.at(index.row()).count();
}
Now it works with an empty list.
But when I try to fill the two dimensional list and pass it like this
QList<QColor> list;
list << QColor(Qt::red) << QColor(Qt::green) << QColor(Qt::blue);
m_list << list << list << list;
m_model = new PaletteTableModel(m_list, this);
I still get the same error. What am I doing wrong?
spirit
13th August 2012, 14:18
But the function is getting called with index.row() = -1. Why gets the function called with index.row() = -1?
I still get the same error. What am I doing wrong?
Because an index can be invalid see QModelIndex::isValid.
So, you should at first check the index validity
...
if (!index.isValid())
return 0;
...
Powered by vBulletin® Version 4.2.5 Copyright © 2024 vBulletin Solutions Inc. All rights reserved.