PDA

View Full Version : Trouble coloring table view rows



waynew
28th August 2010, 23:49
I have a QTableView which is created on the heap in the main window.
Need to selectively color rows, so a db query gets a list of rows to be colored.
From that, I get an index list of the rows. Checked the index list and the indexes are all valid. Created a delegate to use painter( just a stub yet).
The problem comes in trying to assign the delegate to the selected rows.
Here is the offending line of code:


view-->QAbstractItemView::setItemDelegateForRow(rowList[i], new SentDelegate);

Gives compile error complaining it can't call the function without an object.


#ifndef SENTDELEGATE_H
#define SENTDELEGATE_H

#include <QObject>
#include <QItemDelegate>
#include <QModelIndex>

class SentDelegate : public QItemDelegate
{
Q_OBJECT
public:
explicit SentDelegate(QObject *parent = 0);

signals:

public slots:

};

#endif // SENTDELEGATE_H



#include "sentdelegate.h"
#include <QtGui>

SentDelegate::SentDelegate(QObject *parent) :
QItemDelegate(parent)
{
}

And in mainwindow.h


#include "sentdelegate.h"

I used the same approach with a different form and delegate and it works fine.
Where am I going wrong here?

wysota
29th August 2010, 14:57
The correct approach would be different. Create a custom delegate and assign it for the whole table. Make the delegate paint the cell based on a piece of data from the model (using a custom role). To colour some item simply set this piece of data on specific indexes. If you don't want to place such data in your model because of any reason (i.e. when having more than one table assigned to the model), place a proxy model between the view and the base model.

waynew
29th August 2010, 17:37
Ok, that makes sense. I changed the design, but still getting the same compile error.
I subclassed QItemDelegate as QslDelegate to use the paint function.
Here is the relevant code:
mainwindow.h


#include "qsldelegate.h"

And part of MainWindow


// before the ctor
QslDelegate* delegate;
//in the function that creates the view
view-->QAbstractItemView::setItemDelegate(delegate);

Compile error is trying to call the function without an object.
Must be something but I can't find anything wrong with the code.

wysota
29th August 2010, 18:21
Should be:

view->setItemDelegate(delegate);

waynew
29th August 2010, 18:52
Now the error is "setItemDelegate was not declared in this scope"
I have the set delegate line in the code right after where the view was created.

wysota
29th August 2010, 19:31
Please show us a complete piece of code generating the error.

waynew
29th August 2010, 20:34
Thanks Wysota - I included QAbstractItemView in the mainwindow.h and now it compiles ok.
Now to work on the paint part....

waynew
30th August 2010, 00:07
I got it working, mostly. After some experimenting, I went back to my original method of using view->setItemDelegateForRow(rowList[i], delegate); for the index list that needs coloring. It works ok and colors the correct rows, but when the user changes the sort order, the wrong rows are colored, so I call the function again via a signal/slot on the header when the user changes the sort order.

The only problem is, I need to reset the row coloring to the default before re-coloring to the correct rows and I don't see how to do this.

norobro
30th August 2010, 02:07
Is your query criteria simple enough that you can perform a test in the delegate painter? If it is you could use the QModelIndex::sibling() method we recently learned about.

void Delegate::paint( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const
{
if(index.sibling(index.row(), columnToTest).data() == "your criteria"){
painter->fillRect(option.rect,QBrush(someColor));
}
painter->drawText(option.rect,Qt::AlignCenter |Qt::AlignCenter,index.data().toString());
}
And then, as Wysota says above, set the delegate on the entire table.

wysota
30th August 2010, 07:54
I got it working, mostly. After some experimenting, I went back to my original method of using view->setItemDelegateForRow(rowList[i], delegate); for the index list that needs coloring. It works ok and colors the correct rows, but when the user changes the sort order, the wrong rows are colored, so I call the function again via a signal/slot on the header when the user changes the sort order.

The only problem is, I need to reset the row coloring to the default before re-coloring to the correct rows and I don't see how to do this.

If you want to have more work then that's your problem :) My approach needs approximately 10 lines of code in total :)

waynew
30th August 2010, 13:08
Then I have a question Wysota - using your method, which is definitely more elegant, how would one uncolor the row when the data in that row changes such that one no longer wants it colored?

wysota
30th August 2010, 14:38
Clear the flag you previously set for the row to be coloured in the first place.