Trolltech Home | Qt-interest Home | Recent Threads | All Threads | Author | Date
All threads index page 1

Qt-interest Archive, February 2008
Add calculated columns to QSqlQueryModel or QSqlTableModel


Message 1 in thread

Hi Everyone, 

Using 4.3.1. 

I would like to fetch records from the database, but need to add some extra columns to the fetched rows with information that is not in the database. In Delphi you can just add extra columns to the dataset. I expect to be able override the QSqlRecord record () const, but its not virtual. Do I have to implement my own model from scratch, or is it easier to create a proxy model, or is there something else I should be looking at? 

Many thanks in advance. 

Tony Rietwyk. 

--
 [ signature omitted ] 

Message 2 in thread

On Feb 5, 2008, at 1:42 PM, Tony Rietwyk wrote:

> Hi Everyone,
>
> Using 4.3.1.
>
> I would like to fetch records from the database, but need to add  
> some extra columns to the fetched rows with information that is not  
> in the database. In Delphi you can just add extra columns to the  
> dataset. I expect to be able override the QSqlRecord record ()  
> const, but its not virtual. Do I have to implement my own model from  
> scratch, or is it easier to create a proxy model, or is there  
> something else I should be looking at?
>
> Many thanks in advance.

I just implemented this in my application, and I don't know if my  
implementation is the most elegant, but it works. Basically, you sub- 
class the exsisting QSqlTableModel, and then just re-implement the  
data() function, like so:

class myQSqlQueryModel:public QSqlQueryModel
	{
		Q_OBJECT
	public:
		QVariant data(const QModelIndex &item, int role) const;
	};

QVariant myQSqlQueryModel::data(const QModelIndex &item, int role) const
{
	if (item.column() == <calculated column #> &&  
role==Qt::DisplayRole) //if the column is the calculated column, and  
it is being requested for the DisplayRole
	{
		//whatever calculation code is needed
		return QVariant(<calculated value>);
	}
	return QSqlQueryModel::data(item, role); //otherwise, just use the  
data function from the base QSqlQueryModel class
}

You then instantiate and use an instance of your inherited class as  
you would a standard QSqlTableModel class, using the insertColumns()  
function to insert blank columns at the positions your new data()  
function expects them. For example, if you wanted column 4 to be the  
sum of columns two and three, your if statement in the data function  
could look something like if (item.column() == 4 &&  
role==Qt::DisplayRole), and then you would need to call  
insertColumns(4,1) on the instance of your class. Course, you would  
probably want to find a better way of determining the column position  
than hard-coding it, but I'll leave that to your imagination :) Hope  
this helps!

-----------------------------------------------
Israel Brewster
Computer Support Technician
Frontier Flying Service Inc.
5245 Airport Industrial Rd
Fairbanks, AK 99709
(907) 450-7250 x293
-----------------------------------------------

>
>
> Tony Rietwyk.
>
> --
> To unsubscribe - send a mail to qt-interest-request@xxxxxxxxxxxxx  
> with "unsubscribe" in the subject or the body.
> List archive and information: http://lists.trolltech.com/qt-interest/
>

--
 [ signature omitted ] 

Message 3 in thread

Hi Israel, 

Thanks for the reply. 

I assumed that I would need to add them to the QSQLRecord, for the sql
model's to work properly. 

Tony.


> -----Original Message-----
> From: Israel Brewster [mailto:israel@xxxxxxxxxxxxxxxxxx] 
> Sent: Wednesday, 6 February 2008 10:10
> To: Tony Rietwyk
> Cc: qt-interest@xxxxxxxxxxxxx
> Subject: Re: Add calculated columns to QSqlQueryModel or 
> QSqlTableModel
> 
> 
> On Feb 5, 2008, at 1:42 PM, Tony Rietwyk wrote:
> 
> > Hi Everyone,
> >
> > Using 4.3.1.
> >
> > I would like to fetch records from the database, but need to add  
> > some extra columns to the fetched rows with information 
> that is not  
> > in the database. In Delphi you can just add extra columns to the  
> > dataset. I expect to be able override the QSqlRecord record ()  
> > const, but its not virtual. Do I have to implement my own 
> model from  
> > scratch, or is it easier to create a proxy model, or is there  
> > something else I should be looking at?
> >
> > Many thanks in advance.
> 
> I just implemented this in my application, and I don't know if my  
> implementation is the most elegant, but it works. Basically, you sub- 
> class the exsisting QSqlTableModel, and then just re-implement the  
> data() function, like so:
> 
> class myQSqlQueryModel:public QSqlQueryModel
> 	{
> 		Q_OBJECT
> 	public:
> 		QVariant data(const QModelIndex &item, int role) const;
> 	};
> 
> QVariant myQSqlQueryModel::data(const QModelIndex &item, int 
> role) const
> {
> 	if (item.column() == <calculated column #> &&  
> role==Qt::DisplayRole) //if the column is the calculated column, and  
> it is being requested for the DisplayRole
> 	{
> 		//whatever calculation code is needed
> 		return QVariant(<calculated value>);
> 	}
> 	return QSqlQueryModel::data(item, role); //otherwise, 
> just use the  
> data function from the base QSqlQueryModel class
> }
> 
> You then instantiate and use an instance of your inherited class as  
> you would a standard QSqlTableModel class, using the insertColumns()  
> function to insert blank columns at the positions your new data()  
> function expects them. For example, if you wanted column 4 to be the  
> sum of columns two and three, your if statement in the data function  
> could look something like if (item.column() == 4 &&  
> role==Qt::DisplayRole), and then you would need to call  
> insertColumns(4,1) on the instance of your class. Course, you would  
> probably want to find a better way of determining the column 
> position  
> than hard-coding it, but I'll leave that to your imagination :) Hope  
> this helps!

--
 [ signature omitted ] 

Message 4 in thread

On Feb 5, 2008, at 3:25 PM, Tony Rietwyk wrote:

> Hi Israel,
>
> Thanks for the reply.
>
> I assumed that I would need to add them to the QSQLRecord, for the sql
> model's to work properly.

Well, the code I sent (I could send you the full file if you want)  
works in my application to create a display-only calculated column, no  
need to mess qith the QSqlRecords- in my case, total number of items  
minus number of items used, with the option to display "inf." for  
items with unlimited availability. Once set up like this, the object  
works as a standard QSqlQueryModel model in all regards, including the  
calculated column. Incidentally, It seems perfectly happy to display a  
mixture of integers and strings, which somewhat surprised me. One  
small potential caviat, however, is that I don't know how it would  
behave if the model was submitted back to the database. In my  
application the model in question is used as read-only (note that it  
is inheriting from QSqlQueryModel, not QSqlTableModel), so I have  
never tried that. YMMV.

-----------------------------------------------
Israel Brewster
Computer Support Technician
Frontier Flying Service Inc.
5245 Airport Industrial Rd
Fairbanks, AK 99709
(907) 450-7250 x293
-----------------------------------------------
>
>
> Tony.
>
>
>> -----Original Message-----
>> From: Israel Brewster [mailto:israel@xxxxxxxxxxxxxxxxxx]
>> Sent: Wednesday, 6 February 2008 10:10
>> To: Tony Rietwyk
>> Cc: qt-interest@xxxxxxxxxxxxx
>> Subject: Re: Add calculated columns to QSqlQueryModel or
>> QSqlTableModel
>>
>>
>> On Feb 5, 2008, at 1:42 PM, Tony Rietwyk wrote:
>>
>>> Hi Everyone,
>>>
>>> Using 4.3.1.
>>>
>>> I would like to fetch records from the database, but need to add
>>> some extra columns to the fetched rows with information
>> that is not
>>> in the database. In Delphi you can just add extra columns to the
>>> dataset. I expect to be able override the QSqlRecord record ()
>>> const, but its not virtual. Do I have to implement my own
>> model from
>>> scratch, or is it easier to create a proxy model, or is there
>>> something else I should be looking at?
>>>
>>> Many thanks in advance.
>>
>> I just implemented this in my application, and I don't know if my
>> implementation is the most elegant, but it works. Basically, you sub-
>> class the exsisting QSqlTableModel, and then just re-implement the
>> data() function, like so:
>>
>> class myQSqlQueryModel:public QSqlQueryModel
>> 	{
>> 		Q_OBJECT
>> 	public:
>> 		QVariant data(const QModelIndex &item, int role) const;
>> 	};
>>
>> QVariant myQSqlQueryModel::data(const QModelIndex &item, int
>> role) const
>> {
>> 	if (item.column() == <calculated column #> &&
>> role==Qt::DisplayRole) //if the column is the calculated column, and
>> it is being requested for the DisplayRole
>> 	{
>> 		//whatever calculation code is needed
>> 		return QVariant(<calculated value>);
>> 	}
>> 	return QSqlQueryModel::data(item, role); //otherwise,
>> just use the
>> data function from the base QSqlQueryModel class
>> }
>>
>> You then instantiate and use an instance of your inherited class as
>> you would a standard QSqlTableModel class, using the insertColumns()
>> function to insert blank columns at the positions your new data()
>> function expects them. For example, if you wanted column 4 to be the
>> sum of columns two and three, your if statement in the data function
>> could look something like if (item.column() == 4 &&
>> role==Qt::DisplayRole), and then you would need to call
>> insertColumns(4,1) on the instance of your class. Course, you would
>> probably want to find a better way of determining the column
>> position
>> than hard-coding it, but I'll leave that to your imagination :) Hope
>> this helps!
>
> --
> To unsubscribe - send a mail to qt-interest-request@xxxxxxxxxxxxx  
> with "unsubscribe" in the subject or the body.
> List archive and information: http://lists.trolltech.com/qt-interest/

--
 [ signature omitted ]