PDA

View Full Version : Color table row with ItemDelegate



dexjam
28th June 2006, 03:21
Hello, i want to color a whole row using a custom delegate when a specific column contains a date bigger then a set date. What i can actually accomplish is just setting the background color of the cell ...


Atm the code looks like this:


void Delegate::paint(QPainter *painter,
const QStyleOptionViewItem &option,
const QModelIndex &index) const
{
if ( index.column() == 11 )
{
QDateTime compareDate = QDateTime::fromString("2010-01-01T23:59:59", Qt::ISODate);

QVariant date = index.model()->data(index, Qt::DisplayRole);
QDateTime dt = date.toDateTime();
if ( dt > compareDate )
{
if (option.state & QStyle::State_Enabled)
painter->fillRect(option.rect, Qt::green);
QItemDelegate::paint(painter, option, index);
}
}
QItemDelegate::paint(painter, option, index);
}

can anybody help with row coloring?

jpn
28th June 2006, 06:49
You don't need a delegate to do that. Model items have a specific data role for setting the background color used for items rendered with the default delegate.

You could do the same for example in model's setData():


bool YourModel::setData(const QModelIndex& index, const QVariant& value, int role)
{
if (index.column() == 11 && role == Qt::EditRole)
{
// ...
if (dt > compareDate)
{
// set the background color to all siblings (includes the index itself..)
for (int col = 0; col < columnCount(index.parent()); ++col)
{
QModelIndex sibling = index.sibling(index.row(), col);
setData(sibling, QColor(Qt::green), Qt::BackgroundColorRole);
}
}
}
return BaseClassModel::setData(index, value, role);
}

wysota
28th June 2006, 08:29
I would simplify it even more:


QVariant YourModel::data(const QModelIndex& ind, int role){
//...
if(role==Qt::BackgroundColorRole){
QModelIndex testindex = index(ind.row(), 7, ind.parent()); // get index of "watched" column
if(ind.column()==7 || data(testindex, Qt::DisplayRole).toDate() > ...)
return QColor(255,0,0);
}
//...
}

dexjam
28th June 2006, 10:13
Thank you for all the hints, but the actual problem is that i don't have a custom data model. I am atm. using a QSqlTableModel ... and i am accessing the model with SQL queries, not directly wit setData().

Is there a possibility to do the row coloring in the delegate anyway? Or can i set the BackgroundRole using the delegate?

dexjam
28th June 2006, 17:24
Is the fup question i asked so damn silly, that no one will answer it? Maybe the solution to this problem is so simple that i cannot extract it from your answers?

The problem is that i cannot set data within the model from the paint() method in the delegate (which is against MVC anyway i guess) but coloring of a row is a view thing, and maybe you want your row colored in a QTableView (like i do) and not in some other representation (perhaps QListView).

As of my point of view, there has to be a way in which i can manipulate the row color (which is a simple task, i think, and will be used by others too) but i just don't get it.

Perhaps anyone can tell me how that is possible ...

wysota
28th June 2006, 20:56
You can do it from the delegate. The core of the functionality will be exactly the same as the one I posted above, you just need to place it in the delegate. Subclass QItemDelegate and reimplement its paint function. You should then insert the already mentioned code there (of course you need to change it slightly but the general idea remains) so that it changes the palette of the "option" param and then call the base class implementation to handle the rest.

It's possible that this will not work (depends if the default delegate looks at the palette to render the background -- I'm not sure of that). In that case just fill the background yourself using QPainter::fillRect() before calling the base implementation of the paint method.

jacek
28th June 2006, 20:58
Note that the second solution doesn't use setData() --- only data(), so you can easily subclass QSqlTableModel.

As for the delegate, maybe something like:

void Delegate::paint( QPainter *painter,
const QStyleOptionViewItem& option,
const QModelIndex& index ) const
{
QStyleOptionViewItem modOption( option );
if( rowShouldBeHighlighted( index ) ) {
modOption.palette.setColor( QPalette::Base, Qt::green );
modOption.palette.setColor( QPalette::AlternateBase, Qt::green );
}
QItemDelegate::paint( painter, modOption, index );
}

dexjam
29th June 2006, 01:06
@wysota: You're my man :) using your "watched column" approach i got it working .... if anybody is interested in the code on how to change the row color of a QTableView using a delegate that inherits from QItemDelegate it's printed below ...

@jacek: your approach seemed not to work ... or maybe i did something wrong ... i did not follow that thing any further ...

Thanks again for your help ...


void Delegate::paint(QPainter *painter,
const QStyleOptionViewItem &option,
const QModelIndex &index) const
{

QDateTime compareDate = QDateTime::currentDateTime();
//QDateTime::fromString(dateString, Qt::ISODate);
//compareDate = compareDate.addYears(30);
//qDebug("Date is: %s", qPrintable(compareDate.toString()));

QModelIndex testindex = index.model()->index(index.row(), 11, index.parent()); // get index of "watched" column
if( index.model()->data(testindex, Qt::DisplayRole).toDateTime() > compareDate)
{
painter->fillRect(option.rect, Qt::green);
}

QItemDelegate::paint( painter, option, index );

}

jacek
29th June 2006, 12:56
your approach seemed not to work ...
I've just checked the sources and QItemDelegate::paint() just ignores option.palette if the item is not selected, so it had no chance to work.