QTreeView: fix drawing of background for alternate rows

After f4976f86cd we never called the style
to draw the background of rows, unless ShowDecorationSelected was set.
This broke rendering of alternate row backgrounds, as painting that
background for the item's decoration was done by the style function that
was no longer called.

QStyleOptionViewItem::showDecorationSelected should store the value from
the widget's style and be used by the style when rendering. This avoids
that a style sheet is ignored when we are already in the virtual table
of the parent style. However, in that style option we conflate both the
style hint, and whether the entire row should be selected when the
selection behavior is SelectRow (as we then need to draw selection in
the first column all the way to the second column, not just around the
text).

To fix this, override the showDecorationSelected back to the style hint
value while we are only painting the background, and reset it back
before calling the delegate to draw the rest (including the selection).

This reverts f4976f86cd.

Fixes: QTBUG-106227
Pick-to: 6.4 6.2
Change-Id: I5c1ecdf0a0e07b156f35f4e5614593a984754a34
Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@qt.io>
Reviewed-by: Axel Spoerl <axel.spoerl@qt.io>
Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io>
This commit is contained in:
Volker Hilsheimer 2022-10-23 12:40:05 +02:00
parent 94039c9a6a
commit 16e0e7c779
2 changed files with 17 additions and 5 deletions

View File

@ -1659,8 +1659,11 @@ void QTreeView::drawRow(QPainter *painter, const QStyleOptionViewItem &option,
}
}
// ### special case: treeviews with multiple columns draw
// the selections differently than with only one column
// ### special case: if we select entire rows, then we need to draw the
// selection in the first column all the way to the second column, rather
// than just around the item text. We abuse showDecorationSelected to
// indicate this to the style. Below we will reset this value temporarily
// to only respect the styleHint while we are rendering the decoration.
opt.showDecorationSelected = (d->selectionBehavior & SelectRows)
|| option.showDecorationSelected;
@ -1745,8 +1748,16 @@ void QTreeView::drawRow(QPainter *painter, const QStyleOptionViewItem &option,
}
// draw background for the branch (selection + alternate row)
opt.rect = branches;
if (style()->styleHint(QStyle::SH_ItemView_ShowDecorationSelected, &opt, this))
style()->drawPrimitive(QStyle::PE_PanelItemViewRow, &opt, painter, this);
// We use showDecorationSelected both to store the style hint, and to indicate
// that the entire row has to be selected (see overrides of the value if
// selectionBehavior == SelectRow).
// While we are only painting the background we don't care for the
// selectionBehavior factor, so respect only the style value, and reset later.
const bool oldShowDecorationSelected = opt.showDecorationSelected;
opt.showDecorationSelected = style()->styleHint(QStyle::SH_ItemView_ShowDecorationSelected,
&opt, this);
style()->drawPrimitive(QStyle::PE_PanelItemViewRow, &opt, painter, this);
// draw background of the item (only alternate row). rest of the background
// is provided by the delegate
@ -1755,6 +1766,7 @@ void QTreeView::drawRow(QPainter *painter, const QStyleOptionViewItem &option,
opt.rect.setRect(reverse ? position : i + position, y, width - i, height);
style()->drawPrimitive(QStyle::PE_PanelItemViewRow, &opt, painter, this);
opt.state = oldState;
opt.showDecorationSelected = oldShowDecorationSelected;
if (d->indent != 0)
drawBranches(painter, branches, index);

View File

@ -657,7 +657,7 @@ void QCommonStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, Q
if (cg == QPalette::Normal && !(vopt->state & QStyle::State_Active))
cg = QPalette::Inactive;
if ((vopt->state & QStyle::State_Selected) && proxy()->styleHint(QStyle::SH_ItemView_ShowDecorationSelected, opt, widget))
if ((vopt->state & QStyle::State_Selected) && vopt->showDecorationSelected)
p->fillRect(vopt->rect, vopt->palette.brush(cg, QPalette::Highlight));
else if (vopt->features & QStyleOptionViewItem::Alternate)
p->fillRect(vopt->rect, vopt->palette.brush(cg, QPalette::AlternateBase));