Windows11Style: fix drawing rounded corners in itemviews

When drawing an itemview item, the rounded corners (for current and
hovered item) were not properly drawn - the rounded corners of the
windows11 style were sometimes also visible where they should not be.
Fix it by using a clip rect and move the rounded corners out of the clip
rect on the appropriate places.

Pick-to: 6.9
Task-nubmer: QTBUG-131585
Change-Id: I4eccc1e65768306a5511cda6e18db8f56fe1eff6
Reviewed-by: Axel Spoerl <axel.spoerl@qt.io>
This commit is contained in:
Christian Ehrlicher 2024-12-02 17:00:00 +01:00
parent 39564261b2
commit ed18ad9543

View File

@ -1006,28 +1006,54 @@ void QWindows11Style::drawPrimitive(PrimitiveElement element, const QStyleOption
} }
case PE_PanelItemViewRow: case PE_PanelItemViewRow:
if (const QStyleOptionViewItem *vopt = qstyleoption_cast<const QStyleOptionViewItem *>(option)) { if (const QStyleOptionViewItem *vopt = qstyleoption_cast<const QStyleOptionViewItem *>(option)) {
// this is only called from a QTreeView to paint
// - the tree branch decoration (incl. selected/hovered or not)
// - the (alternate) background of the item in always unselected state
const QRect &rect = vopt->rect; const QRect &rect = vopt->rect;
const bool isRtl = option->direction == Qt::RightToLeft; const bool isRtl = option->direction == Qt::RightToLeft;
if (rect.width() <= 0)
break;
painter->setPen(Qt::NoPen); painter->setPen(Qt::NoPen);
if (vopt->features & QStyleOptionViewItem::Alternate) if (vopt->features & QStyleOptionViewItem::Alternate)
painter->setBrush(vopt->palette.alternateBase()); painter->setBrush(vopt->palette.alternateBase());
else else
painter->setBrush(vopt->palette.base()); painter->setBrush(vopt->palette.base());
int markerOffset = 2; painter->drawRect(rect);
painter->drawRect(vopt->rect.marginsRemoved(QMargins(markerOffset, 0, -markerOffset, 0)));
if ((vopt->state & State_Selected || vopt->state & State_MouseOver) && vopt->showDecorationSelected) { const bool isTreeDecoration = vopt->features.testFlag(
QStyleOptionViewItem::IsDecorationForRootColumn);
if (isTreeDecoration && vopt->state.testAnyFlags(State_Selected | State_MouseOver) &&
vopt->showDecorationSelected) {
const bool onlyOne = vopt->viewItemPosition == QStyleOptionViewItem::OnlyOne ||
vopt->viewItemPosition == QStyleOptionViewItem::Invalid;
bool isFirst = vopt->viewItemPosition == QStyleOptionViewItem::Beginning;
bool isLast = vopt->viewItemPosition == QStyleOptionViewItem::End;
if (onlyOne)
isFirst = true;
if (isRtl) {
isFirst = !isFirst;
isLast = !isLast;
}
painter->setBrush(WINUI3Colors[colorSchemeIndex][subtleHighlightColor]); painter->setBrush(WINUI3Colors[colorSchemeIndex][subtleHighlightColor]);
painter->setPen(Qt::NoPen); painter->setPen(Qt::NoPen);
painter->drawRoundedRect(vopt->rect.marginsRemoved(QMargins(0,2,-2,2)),2,2); if (isFirst) {
if (vopt->viewItemPosition == QStyleOptionViewItem::Beginning && option->state & State_Selected) { painter->save();
painter->setPen(QPen(option->palette.accent().color())); painter->setClipRect(rect);
const auto xPos = isRtl ? rect.right() - 1 : rect.left(); painter->drawRoundedRect(rect.marginsRemoved(QMargins(2, 2, -secondLevelRoundingRadius, 2)),
const QLineF lines[2] = { secondLevelRoundingRadius, secondLevelRoundingRadius);
QLineF(xPos, rect.y() + 2, xPos, rect.y() + rect.height() - 2), painter->restore();
QLineF(xPos + 1, rect.y() + 2, xPos + 1, rect.y() + rect.height() - 2), } else if (isLast) {
}; painter->save();
painter->drawLines(lines, 2); painter->setClipRect(rect);
painter->drawRoundedRect(rect.marginsRemoved(QMargins(-secondLevelRoundingRadius, 2, 2, 2)),
secondLevelRoundingRadius, secondLevelRoundingRadius);
painter->restore();
} else {
painter->drawRect(vopt->rect.marginsRemoved(QMargins(0, 2, 0, 2)));
} }
} }
} }
@ -1674,26 +1700,27 @@ void QWindows11Style::drawControl(ControlElement element, const QStyleOption *op
bool isFirst = vopt->viewItemPosition == QStyleOptionViewItem::Beginning; bool isFirst = vopt->viewItemPosition == QStyleOptionViewItem::Beginning;
bool isLast = vopt->viewItemPosition == QStyleOptionViewItem::End; bool isLast = vopt->viewItemPosition == QStyleOptionViewItem::End;
painter->setPen(highContrastTheme == true ? vopt->palette.buttonText().color() : WINUI3Colors[colorSchemeIndex][frameColorLight]); // the tree decoration already painted the left side of the rounded rect
if (isFirst) { if (vopt->features.testFlag(QStyleOptionViewItem::IsDecoratedRootColumn) &&
painter->drawLine(rect.topRight() + QPointF(0.5, 0.0), vopt->showDecorationSelected) {
rect.bottomRight() + QPointF(0.5, 0.0)); isFirst = false;
} else if (isLast) { if (onlyOne) {
painter->drawLine(rect.topLeft() - QPointF(0.5, 0.0), onlyOne = false;
rect.bottomLeft() - QPointF(0.5, 0.0)); isLast = true;
} else { }
const QLineF lines[2] = {
QLineF(rect.topRight() + QPointF(0.5, 0.0),
rect.bottomRight() + QPointF(0.5, 0.0)),
QLineF(rect.topLeft() - QPointF(0.5, 0.0),
rect.bottomLeft() - QPointF(0.5, 0.0)),
};
painter->drawLines(lines, 2);
} }
const bool isTreeView = qobject_cast<const QTreeView *>(widget); if (isRtl) {
if (isFirst) {
isFirst = false;
isLast = true;
} else if (isLast) {
isFirst = true;
isLast = false;
}
}
if ((vopt->state & State_Selected || vopt->state & State_MouseOver) && !(isTreeView && vopt->state & State_MouseOver) && vopt->showDecorationSelected) { if (vopt->state.testAnyFlags(State_Selected | State_MouseOver)) {
painter->setBrush(WINUI3Colors[colorSchemeIndex][subtleHighlightColor]); painter->setBrush(WINUI3Colors[colorSchemeIndex][subtleHighlightColor]);
QWidget *editorWidget = view ? view->indexWidget(view->currentIndex()) : nullptr; QWidget *editorWidget = view ? view->indexWidget(view->currentIndex()) : nullptr;
if (editorWidget) { if (editorWidget) {
@ -1712,11 +1739,17 @@ void QWindows11Style::drawControl(ControlElement element, const QStyleOption *op
painter->drawRoundedRect(rect.marginsRemoved(QMargins(2, 2, 2, 2)), painter->drawRoundedRect(rect.marginsRemoved(QMargins(2, 2, 2, 2)),
secondLevelRoundingRadius, secondLevelRoundingRadius); secondLevelRoundingRadius, secondLevelRoundingRadius);
} else if (isFirst) { } else if (isFirst) {
painter->drawRoundedRect(rect.marginsRemoved(QMargins(2, 2, 0, 2)), painter->save();
painter->setClipRect(rect);
painter->drawRoundedRect(rect.marginsRemoved(QMargins(2, 2, -secondLevelRoundingRadius, 2)),
secondLevelRoundingRadius, secondLevelRoundingRadius); secondLevelRoundingRadius, secondLevelRoundingRadius);
painter->restore();
} else if (isLast) { } else if (isLast) {
painter->drawRoundedRect(rect.marginsRemoved(QMargins(0, 2, 2, 2)), painter->save();
painter->setClipRect(rect);
painter->drawRoundedRect(rect.marginsRemoved(QMargins(-secondLevelRoundingRadius, 2, 2, 2)),
secondLevelRoundingRadius, secondLevelRoundingRadius); secondLevelRoundingRadius, secondLevelRoundingRadius);
painter->restore();
} else { } else {
painter->drawRect(rect.marginsRemoved(QMargins(0, 2, 0, 2))); painter->drawRect(rect.marginsRemoved(QMargins(0, 2, 0, 2)));
} }
@ -1754,7 +1787,8 @@ void QWindows11Style::drawControl(ControlElement element, const QStyleOption *op
painter->setPen(QPen(option->palette.text().color())); painter->setPen(QPen(option->palette.text().color()));
d->viewItemDrawText(painter, vopt, textRect); d->viewItemDrawText(painter, vopt, textRect);
} }
if (vopt->state & State_Selected && (isFirst || onlyOne)) { // paint a vertical marker for QListView
if (vopt->state & State_Selected) {
if (const QListView *lv = qobject_cast<const QListView *>(widget); if (const QListView *lv = qobject_cast<const QListView *>(widget);
lv && lv->viewMode() != QListView::IconMode) { lv && lv->viewMode() != QListView::IconMode) {
painter->setPen(QPen(vopt->palette.accent().color())); painter->setPen(QPen(vopt->palette.accent().color()));