PDA

View Full Version : Properties, MetaObjects, and Models



EricTheFruitbat
26th January 2007, 07:15
I've been experimenting with the model/view programming methodology and hope soon to fully understand it's implementation in Qt. Suppose that you have a class, say Customer, and that class has Q_PROPERTYs (like firstName, lastName, etc..). Now you want to hold an Address Book, so you make a model.

First Question: do you subclass QAbstractListModel, or QAbstractTableModel?

I chose to subclass the table model, and hold the records in rows (QList<Customer*> m_list), and the properties of each Customer in the columns. In the interests of future extendability, I'd like for the model's implementation of columnCount() to return the number of properties available for the class Customer. So this exercise was to see if I colud write a model that would automatically account for any changes made to class Customer. That is; if I change class Customer by addition or removal of properties, I don't want to have to change the model.



int myModel::columnCount() {
// we have to subtract the properties gained through inheritance
// from the total count
static int ret = Customer::staticMetaObject()->propertyCount()
- Customer::staticMetaObject->propertyOffset();
return ret;
}

int myModel::rowCount() {
return m_list()->size();
}


Now in order to retrieve our data, we have to reimplement the data function. But this is where I ran into a bit of trouble.


QVariant BrushModel::data( const QModelIndex &index, int role ) const {
if ( index.isValid() )
return QVariant();
if ( index.row() < 0 || rowCount() <= index.row() )
return QVariant();
if ( index.column < 0 || columnCount() <= index.column() )
return QVariant();

if ( role == Qt::DisplayRole ) {
int col = index.column() + Customer::staticMetaObject()->propertyOffset();
Customer *c = m_list.at( index.row() );
char *name = ??? // somehow we have to map col into a property name
return c->property( name );
}

return QVariant();
}


Perhaps this is just a flawed design and there are better ways to go about this. I may have overlooked something in the documentation surrounding metaobects but I could not find a way to map from an index to a property name. I did find an indexOfProperty(char *name) function, but nothing which goes the other direction.

e8johan
26th January 2007, 09:00
Can't you use QMetaObject::property (http://doc.trolltech.com/4.2/qmetaobject.html#property)( int )->name() (http://doc.trolltech.com/4.2/qmetaproperty.html#name) for this?

Regarding the design - it looks quite elegant. I did something similar recently to use QObjects to represent a tree structure for a model.

wysota
26th January 2007, 13:48
First Question: do you subclass QAbstractListModel, or QAbstractTableModel?

It doesn't really matter. You can always transform one representation into the other using a simple proxy model. I guess for manipulating the list representation is better (as you have all information about the object in one place) - it's according "to the book", but a table representation might be better if you wanted to display the model and let the user change values of each property/column.

EricTheFruitbat
26th January 2007, 20:51
Can't you use QMetaObject::property (http://doc.trolltech.com/4.2/qmetaobject.html#property)( int )->name() (http://doc.trolltech.com/4.2/qmetaproperty.html#name) for this?

Regarding the design - it looks quite elegant. I did something similar recently to use QObjects to represent a tree structure for a model.

I knew that I must've been overlooking something.

And thank you both for the feedback about the design.