Ok, I somehow came to a conclusion that I may not able to explain you further without help of a working example.
So here we look at an example, which should be very similar to what you explained. Please make a BIG NOTE that this is just an example, and shows one of the ways to implement a model.
The key feature here is to relate the Person to the Job, and at run-time able to refer them from one another. In the example below i use a simple row & and type encoding which make it easy to relate job to a person. One could use any type of technique to relate Job & Person, simple pointers / run time type determination / holding pointer to each others etc.
//PersonJobModel.h
#ifndef PERSONJOBMODEL_H
#define PERSONJOBMODEL_H
#include <QList>
#include <QDate>
#include <QAbstractItemModel>
struct Job {
};
struct Person {
QList<Job*> employmentHistory;
};
{
Q_OBJECT
public:
explicit PersonJobModel
(QObject *parent
= 0);
~PersonJobModel();
signals:
private:
enum RowType {
TypePerson = 0x00000000,
TypeJob = 0x01000000,
TypeMask = 0xFF000000
};
QList<Person*> persons;
inline quint32 encodeTypeRow(RowType type, int row) const
{ return type | ( ~TypeMask & row); }
inline int decodeRow(const QModelIndex& index) const
{ return static_cast<quint32>(index.internalId()) & ~TypeMask; }
inline RowType decodeType(const QModelIndex& index) const
{ return static_cast<RowType>(index.internalId() & TypeMask); }
inline bool isPerson(const QModelIndex& index) const
{ return decodeType(index) == TypePerson; }
inline bool isJob(const QModelIndex& index) const
{ return decodeType(index) == TypeJob; }
};
//PersonJobModel.h
#ifndef PERSONJOBMODEL_H
#define PERSONJOBMODEL_H
#include <QList>
#include <QDate>
#include <QAbstractItemModel>
struct Job {
QString name;
QDate startDate;
};
struct Person {
QString name;
QString address;
QList<Job*> employmentHistory;
};
class PersonJobModel : public QAbstractItemModel
{
Q_OBJECT
public:
explicit PersonJobModel(QObject *parent = 0);
~PersonJobModel();
QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const;
QModelIndex parent(const QModelIndex &child) const ;
int rowCount(const QModelIndex &parent = QModelIndex()) const;
int columnCount(const QModelIndex &parent = QModelIndex()) const;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
signals:
private:
enum RowType {
TypePerson = 0x00000000,
TypeJob = 0x01000000,
TypeMask = 0xFF000000
};
QList<Person*> persons;
inline quint32 encodeTypeRow(RowType type, int row) const
{ return type | ( ~TypeMask & row); }
inline int decodeRow(const QModelIndex& index) const
{ return static_cast<quint32>(index.internalId()) & ~TypeMask; }
inline RowType decodeType(const QModelIndex& index) const
{ return static_cast<RowType>(index.internalId() & TypeMask); }
inline bool isPerson(const QModelIndex& index) const
{ return decodeType(index) == TypePerson; }
inline bool isJob(const QModelIndex& index) const
{ return decodeType(index) == TypeJob; }
};
To copy to clipboard, switch view to plain text mode
//PersonJobModel.cpp
#include "PersonJobModel.h"
PersonJobModel
::PersonJobModel(QObject *parent
){
//Create some sample data, 4 Persons, 5 Jobs per person
for(int i = 0; i < 4; i++)
{
Person* person = new Person;
person
->name
= QString("Person %1").
arg(i
+1);
person
->address
= QString("Address of Person %1").
arg(i
+1);
for(int j = 0; j < 5; j++)
{
Job* job = new Job;
job
->name
= QString("Person %1, Job %2").
arg(i
+1).
arg((i
+1)*(j
+1));
job
->startDate
= QDate(i
+1, j
+1,
(i
+1)*(j
+1));
person->employmentHistory.append(job);
}
persons.append(person);
}
}
PersonJobModel::~PersonJobModel()
{
while(persons.count())
{
while(persons.at(0)->employmentHistory.count())
delete persons.at(0)->employmentHistory.takeFirst();
delete persons.takeFirst();
}
}
{
if(!parent.isValid())
return createIndex(row, column, encodeTypeRow(TypePerson, 0));
else if(isPerson(parent))
return createIndex(row, column, encodeTypeRow(TypeJob, parent.row()));
}
QModelIndex PersonJobModel
::parent(const QModelIndex
& child
) const {
if(child.isValid())
if(isJob(child))
return createIndex(decodeRow(child), 0, encodeTypeRow(TypePerson, 0));
}
int PersonJobModel::rowCount(const QModelIndex& parent) const
{
if(!parent.isValid())
return persons.count();
else if(isPerson(parent))
return persons.at(parent.row())->employmentHistory.count();
return 0;
}
int PersonJobModel::columnCount(const QModelIndex& parent) const
{
return 2;
}
QVariant PersonJobModel
::data(const QModelIndex
& index,
int role
) const {
if(role == Qt::DisplayRole)
{
if(isPerson(index))
{
if(index.column() == 0)
return persons.at(index.row())->name;
else if(index.column() == 1)
return persons.at(index.row())->address;
}
else if(isJob(index))
{
if(index.column() == 0)
return persons.at(decodeRow(index))->employmentHistory.at(index.row())->name;
else if(index.column() == 1)
return persons.at(decodeRow(index))->employmentHistory.at(index.row())->startDate.toString();
}
}
}
#endif // PERSONJOBMODEL_H
//PersonJobModel.cpp
#include "PersonJobModel.h"
PersonJobModel::PersonJobModel(QObject *parent)
: QAbstractItemModel(parent)
{
//Create some sample data, 4 Persons, 5 Jobs per person
for(int i = 0; i < 4; i++)
{
Person* person = new Person;
person->name = QString("Person %1").arg(i+1);
person->address = QString("Address of Person %1").arg(i+1);
for(int j = 0; j < 5; j++)
{
Job* job = new Job;
job->name = QString("Person %1, Job %2").arg(i+1).arg((i+1)*(j+1));
job->startDate = QDate(i+1, j+1, (i+1)*(j+1));
person->employmentHistory.append(job);
}
persons.append(person);
}
}
PersonJobModel::~PersonJobModel()
{
while(persons.count())
{
while(persons.at(0)->employmentHistory.count())
delete persons.at(0)->employmentHistory.takeFirst();
delete persons.takeFirst();
}
}
QModelIndex PersonJobModel::index(int row, int column, const QModelIndex &parent) const
{
if(!parent.isValid())
return createIndex(row, column, encodeTypeRow(TypePerson, 0));
else if(isPerson(parent))
return createIndex(row, column, encodeTypeRow(TypeJob, parent.row()));
return QModelIndex();
}
QModelIndex PersonJobModel::parent(const QModelIndex& child) const
{
if(child.isValid())
if(isJob(child))
return createIndex(decodeRow(child), 0, encodeTypeRow(TypePerson, 0));
return QModelIndex();
}
int PersonJobModel::rowCount(const QModelIndex& parent) const
{
if(!parent.isValid())
return persons.count();
else if(isPerson(parent))
return persons.at(parent.row())->employmentHistory.count();
return 0;
}
int PersonJobModel::columnCount(const QModelIndex& parent) const
{
return 2;
}
QVariant PersonJobModel::data(const QModelIndex& index, int role) const
{
if(role == Qt::DisplayRole)
{
if(isPerson(index))
{
if(index.column() == 0)
return persons.at(index.row())->name;
else if(index.column() == 1)
return persons.at(index.row())->address;
}
else if(isJob(index))
{
if(index.column() == 0)
return persons.at(decodeRow(index))->employmentHistory.at(index.row())->name;
else if(index.column() == 1)
return persons.at(decodeRow(index))->employmentHistory.at(index.row())->startDate.toString();
}
}
return QVariant();
}
#endif // PERSONJOBMODEL_H
To copy to clipboard, switch view to plain text mode
and here is the output view
Bookmarks