[Qt-interest] custom model question, cells depending on other cell

Andre Somers andre at familiesomers.nl
Mon Dec 21 10:09:11 CET 2009


Hi,

franki wrote:
> Thanks for clarification, I'll try this one for the sake of practice. 
> Programming in C is a bit different than script language like php, so I 
> haven't been dealing with structures so far.
>   
Auch... I'm sorry, but that is basic C++ programming. Perhaps your own 
struct in a QList would be sufficient for you?
>> * Replace QAbstractItemModel by one of the (abstract) models based on it
>> if they are more convenient.
>>
>>     
>>> I haven't read very much about proxy models, will they allow me to
>>> iterate throught data and calculate data and change values in role?
>>>       
>> Proxies are used mainly for filtering, but they can be used for other
>> things like modifying data. Note that a proxy model is also a
>> QAbstractItemModel subclass... That is: nothing prevents you to
>> re-implement the data() method and return whatever you like there. You
>> can even change the data structure (flatten trees for instance) if you
>> want, but that kind of thing is non-trivial to say the least.
>> So sure, if you want to change values in a proxy model, you can. But,
>> I'd be cautious with this. Changing the colour role for a row based on
>> the value of one of it's columns and then hiding that column is one
>> thing, but iterating over the whole dataset to calculate some value is
>> quite another IMHO. Still, if you would be able to cache critical data
>> for such calculations, it may be a viable solution.
>>
>> For instance, say you have a table with numbers of items in each row,
>> and you'd like to add a column that displays the proportion of the total
>> numbers of items in the set. You'd only have to calculate the total once
>> (assuming the data behind it not too volitile), so this could be done
>> quite easily in a proxy model. You could have the proxy model get the
>> data by iterating, or you could supply the proxy with the sum yourself
>> based on a perhaps more efficient SQL query with a SUM () statement in
>> it. However, I'd only use a proxy model solution if I'd be reasonably
>> sure I can use the created solution again on a different source model,
>> either in the same or in a different application. That is: it has to be
>> reasonably generic. Otherwise it's not worth the trouble, IMHO.
>>
>>     
>>> Second solution seems to be easy, column order is always the same,
>>> besides I can search for data using QSqlRecord::indexOf but then data in
>>> model remains unchanged, and customModel::data() will have to calculate
>>> roles and data each time view request the data.
>>>
>>> So if I want to change values that comes from sql, inside model, and then
>>> when I connect a view, it gets always previously calculated data from
>>> model, should I opt for solution 3 - proxy model?
>>>       
>> I'm sorry, I don't get what you're trying to say here. Is the data in
>> your database volitile? That is: does it change (frequently) while your
>> application is running, by other means than your application itself?
>>
>>     
>>> And is it ever possible (in read-only model) to change values fetched
>>> from sql, values like DisplayRole, and others, and then let the view to
>>> operate on modified data without implementing proxy model, or maybe those
>>> data in model are read-only?
>>>       
>> The read-onlyness has only to do with if changes in the data can be
>> written back, not if the data you pass along for the view can be
>> modified in the process. Do you plan to write back data to your database
>> from your model?
>>     
>
> My data isn't volatile, it is changed only by my application,
> and I don't plan to write back data to database from this model.
>   
Ok, good. That will simplify things a little.
> So I'm still unsure, Is it possible to change data in model QSqlQueryModel 
> fetched from sql? Or not?
> Because when I was trying to use a few times setData function it always 
> returns FAILED, and in documentation about setData there is: "The base class 
> implementation returns false."
> Even if I subclassed QSqlQueryModel inside my own setData function I think I 
> still have to use QSqlQueryModel::setData to change my data from sql, right?
>
> But maybe there is something else that cause that setData returns FAILED in my 
> app.
>   
Ah!
I see the confusion here...
Your QSqlQueryModel is read only. They all are, by default. But... to 
change what data is being provided by the model, you do not actually 
need to change the data in the underlying model at all! You don't need 
to use setData, you only need to reimplement the data() function to 
return whatever you like.

For instance; say you want to return half of the original value in one 
of your columns (you would normally do that in SQL, but that is not the 
point of the example.) You would simply reimplement the data function of 
your subclassed model like this (pseudo-code):

QVariant MyModel::data(const QModelIndex & item, int role ) const
{
    if (!item.isValid())
       return QVariant();

    QVariant result (QSqlQueryModel::data(item, role));
    //return half of column two
    if (item.column() == 1 && role == Qt::DisplayRole) { //columns start 
at index 0
       result = QVariant(result.toDouble() / 2);
    }

    return result;
}

You see? You don't actually change the data in the underlying structure, 
but you just tell the user of your class something else than what is in 
your underlying data source.
In exactly the same way you can make a row color red depending on the 
value of another cell in the row...

André


  



More information about the Qt-interest-old mailing list