It can be done, but it's not trivial. It depends on your implementation of QAbstractItemModel
and that's why it hasn't been done in Qt.
Here are steps to implement a model which is a collection of models:
- Create a new class inherited from
QAbstractItemModel
- Add methods to add other models to that
- Process all signals from child models which contains indexes (you'll need to change them, look #10)
- Forward all signals which doesn't contain indexes.
- Implement
rowCount
and provide a sum of all models rows.
- Implement
columnCount
and provide a number of columns in your models.
- Implement
index
, return createIndex(row, column, NULL);
- Implement
parent
, return QModelIndex(); I hope your models are not trees
- Implement
data
,setData
etc. addressing calls to the right model. Use methods from #10 to convert indexes.
- Create methods to convert a child model index to a base model index and back.
Example (indexes):
BaseModel ChildModel1 ChildModel2
0,0 0,0
1,0 1,0
2,0 0,0
3,0 1,0
4,0 2,0
p.s. Think about creating a cache of indexes mapping.
This is an example of a method to convert a base model index to a child model index:
const QModelIndex childModelIndex(const QModelIndex& baseModelIndex) const
{
if (!baseModelIndex.isValid())
{
return QModelIndex();
}
int count = 0;
const int row = baseModelIndex.row();
for (QList<QAbstractTableModel*>::const_iterator it = m_models.begin();
it != m_models.end(); it++)
{
const int currentCount = (*it)->rowCount();
if (row >= count && row < count + currentCount)
{
return (*it)->index(row - count, 0);
}
count += currentCount;
}
ASSERT(false);
return QModelIndex();
}
This is an example of a method to convert a child model index to a base model index:
QModelIndex baseModelIndex(const QModelIndex& childModelIndex) const
{
int row = childModelIndex.row();
for (QList<QAbstractTableModel*>::const_iterator it = m_models.begin();
it != m_models.end(); it++)
{
if (childModelIndex.model() == *it)
{
return index(row, ind.column());
}
row += (*it)->rowCount();
}
return QModelIndex();
}