Kef
Kef

Reputation: 440

QTreeView custom item display delegate and CSS

I have a QTreeView displaying my data and I have installed a custom delegate to one of the columns to display a colored progress bar, which appearance depends on the content. I was able to emulate the default delegate behavior using the color information provided by option.palette:

class ProgressBarDelegate : public QStyledItemDelegate
{
public:
    ProgressBarDelegate(QObject *parent = 0) {}
    ~ProgressBarDelegate() {}
    void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
    {
        // QStyledItemDelegate::paint(painter, option, index); // default implementation

        painter->save();

        // progressbar construction and drawing

        painter->restore();
    }
};

Now, I want to highlight a row on mouse hover event. I set a custom CSS to the tree view:

ui->treeView->setStyleSheet("QTreeView::item:hover{background-color:#D0E0F0;}");

The hover highlighting works, but, expectedly, my custom delegate implementation ignores the CSS setting:

Without defaulte delegate

(Darkblue line is the selected item, lightblue-ish line is the CSS hover-highlighted line)

Enabling the default implementation allows the CSS setting to affect my delegate, but it messes up the picture:

With default delegate

The question is:

I have tried reading the QTreeView property as descried here:

qDebug() << treeView()->property("background");

but the console shows QVariant(Invalid)

I also tried reading the Qt source code for drawControl() and drawPrimitive() methods, which are used in the default delegate implementation, but I managed to find only widget palette references and no connections to the CSS overrides.

Upvotes: 1

Views: 2476

Answers (2)

Kef
Kef

Reputation: 440

After reading the source I found out that apparently, there's no way to access the CSS data from within the delegate by default as the CSS parsing and calculations are being handled by a private QStyleSheetStyle object an application doesn't have direct access to. This object simply modifies respective option.palette fields to be used by drawing routines.

However, there is a way to force the delegate to draw some of the elements with desired settings without manually parsing the option.palette fields by calling the style's drawPrimitive() method:

// drawing background with desired colors:
option.widget->style()->drawPrimitive(QStyle::PE_PanelItemViewItem, &opt, painter);

This method will draw the background with respective settings:

somewhat acceptable

I think there should be a similar way to force the CSS-modified setting to be used, something in the lines of:

option.widget->style()->proxy()->drawPrimitive(QStyle::PE_PanelItemViewItem, &opt, painter);

however, due to lack of understanding of inner workings of Qt's style framework I wasn't able to find it yet.

Upvotes: 1

frbaresi
frbaresi

Reputation: 96

As you're drawing the component in the paint method, you can draw the "hover" effect

You can use something like this:

// detect the hover
QStyleOptionViewItemV4 styleOption(option);
bool mouseOver = (styleOption.state & QStyle::State_MouseOver);
// draw if hovered    
if(mouseOver) {
...
}

Upvotes: 0

Related Questions