PDA

View Full Version : Set the color of a row in a qtreeview



slv1
26th February 2015, 08:12
Is it possible to change the color of a row in a QTreeView based on an index at runtime?

atomic
26th February 2015, 10:15
Something like this?



void MainWindow::changeTreeViewRowColor(QModelIndex index)
{
for( int i = 0; i < model.columnCount(); ++i ) {
model.item( index.row(), i )->setBackground( Qt::red );
}
}

west
26th February 2015, 10:41
Inherit QStyledItemDelegate.

slv1
26th February 2015, 11:22
Something like this?



void MainWindow::changeTreeViewRowColor(QModelIndex index)
{
for( int i = 0; i < model.columnCount(); ++i ) {
model.item( index.row(), i )->setBackground( Qt::red );
}
}


exactly like that, except QDirModel and QFileSystemModel don't have an "item()" method...

atomic
26th February 2015, 12:20
Try reimplement this virtual function:



bool QFileSystemModel::setData(const QModelIndex & idx, const QVariant & value, int role = Qt::EditRole)


http://doc.qt.io/qt-5/qfilesystemmodel.html#setData
http://doc.qt.io/qt-5/qabstractitemmodel.html#setData

slv1
27th February 2015, 07:26
reimplement it how?

from this post here : http://www.cplusplusdevelop.com/855_3935440/


QFileSystemModel rejects all calls to setData that is not of the role "Qt::EditRole".

I tried using setData() and Qt::BackgroundRole with QSortFilterProxyModel instead, it still doesn't do anything. I am not sure what exactly I should reimplement setData to do.

wysota
27th February 2015, 09:22
reimplement it how?

from this post here : http://www.cplusplusdevelop.com/855_3935440/



I tried using setData() and Qt::BackgroundRole with QSortFilterProxyModel instead, it still doesn't do anything. I am not sure what exactly I should reimplement setData to do.

Implement a custom delegate or a proxy model that will do the colouring. Reimplementing setData() for QDirModel or QFileSystemModel makes little sense.

slv1
27th February 2015, 13:46
I implemented a custom QStyledItemDelegate() but :

When I iterate through the items in my model, I decide which delegate method should be used for each item, but then the actual drawing takes place after the loop is over, so the last call of "view->setItemDelegate()" will be considered.

How do I force a repaint of a specific item after setting the right itemDelegate for the view?

Update:
Tried using setItemDelegateForRow(), that doesn't work properly because I'm using a QTreeView and that doesn't have unique rows. What would work is a setItemDelegateForIndex() method......

wysota
27th February 2015, 15:18
You should set one delegate for the whole view and teach it to decide about colour of each row it renders.

d_stranz
27th February 2015, 16:07
You should set one delegate for the whole view and teach it to decide about colour of each row it renders.

Can you please explain the pros and cons of doing it this way vs. implementing a proxy that would change the colour via the data() method and the Qt::BackgroundRole. In both cases, it would seem that "teach it to decide" would require inside knowledge about the model.

wysota
27th February 2015, 16:48
Can you please explain the pros and cons of doing it this way vs. implementing a proxy that would change the colour via the data() method and the Qt::BackgroundRole. In both cases, it would seem that "teach it to decide" would require inside knowledge about the model.

They are more or less equivalent. Using a custom delegate is a bit faster performance-wise.

slv1
3rd March 2015, 07:45
You should set one delegate for the whole view and teach it to decide about colour of each row it renders.

I solved this by writing a "QStyledItemDelegate" that takes a list of indexes as arguments. It checks if the current index is in the list and paints accordingly.

Here's the code:


class RedRowDelegate : public QStyledItemDelegate
{
public:
QDirModel *pModel;
QList<QModelIndex> *pRedIndexes;

RedRowDelegate::RedRowDelegate(QDirModel *model, QList<QModelIndex> *redIndexes){
pModel = model;
pRedIndexes = redIndexes;
}

void RedRowDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
int row = index.row();

if(pRedIndexes->contains(index)){
painter->fillRect(option.rect, QColor(Qt::red));
}

QStyledItemDelegate::paint(painter, option, index);
}
};

After setting it for the QTreeView like this:
tree1->setItemDelegate(new RedRowDelegate(model, redIndexes));, the delegate will be called iteratively for all the items in the tree, instead of the default one.

wysota
3rd March 2015, 08:14
You should be using QPersistentModelIndex instead of QModelIndex.