Fusion style/QProgressBar: fix High-DPI issues

Fix some issues for QProgressBar with fusion style:
 - no progress text was shown in vertical mode
 - the color change for the text was not correct in rtl mode
 - the two rounded rects were not drawn correctly in some modes
Also simplify the code by also using a QTransform for rtl mode and not
only for the vertical mode.

Fixes: QTBUG-117904
Change-Id: I1dd89daf34e8808417750f2ca714252afdab1416
Reviewed-by: Eirik Aavitsland <eirik.aavitsland@qt.io>
This commit is contained in:
Christian Ehrlicher 2023-10-06 22:18:58 +02:00
parent fe653b70ae
commit 262031d364

View File

@ -1318,36 +1318,39 @@ void QFusionStyle::drawControl(ControlElement element, const QStyleOption *optio
case CE_ProgressBarContents:
painter->save();
painter->setRenderHint(QPainter::Antialiasing, true);
painter->translate(0.5, 0.5);
if (const QStyleOptionProgressBar *bar = qstyleoption_cast<const QStyleOptionProgressBar *>(option)) {
bool vertical = false;
bool inverted = false;
bool indeterminate = (bar->minimum == 0 && bar->maximum == 0);
bool complete = bar->progress == bar->maximum;
vertical = !(bar->state & QStyle::State_Horizontal);
inverted = bar->invertedAppearance;
const auto indeterminate = (bar->minimum == 0 && bar->maximum == 0);
const auto complete = bar->progress == bar->maximum;
const auto vertical = !(bar->state & QStyle::State_Horizontal);
const auto inverted = bar->invertedAppearance;
const auto reverse = (bar->direction == Qt::RightToLeft) ^ inverted;
// If the orientation is vertical, we use a transform to rotate
// the progress bar 90 degrees clockwise. This way we can use the
// the progress bar 90 degrees (counter)clockwise. This way we can use the
// same rendering code for both orientations.
if (vertical) {
rect = QRect(rect.left(), rect.top(), rect.height(), rect.width()); // flip width and height
QTransform m = QTransform::fromTranslate(rect.height()-1, -1.0);
m.rotate(90.0);
QTransform m;
if (inverted) {
m.rotate(90);
m.translate(0, -rect.height());
} else {
m.rotate(-90);
m.translate(-rect.width(), 0);
}
painter->setTransform(m, true);
} else if (reverse) {
QTransform m = QTransform::fromScale(-1, 1);
m.translate(-rect.width(), 0);
painter->setTransform(m, true);
}
painter->translate(0.5, 0.5);
int maxWidth = rect.width();
const auto progress = qMax(bar->progress, bar->minimum); // workaround for bug in QProgressBar
const auto totalSteps = qMax(Q_INT64_C(1), qint64(bar->maximum) - bar->minimum);
const auto progressSteps = qint64(progress) - bar->minimum;
const auto progressBarWidth = progressSteps * maxWidth / totalSteps;
int width = indeterminate ? maxWidth : progressBarWidth;
bool reverse = (!vertical && (bar->direction == Qt::RightToLeft)) || vertical;
if (inverted)
reverse = !reverse;
const auto progressBarWidth = progressSteps * rect.width() / totalSteps;
int width = indeterminate ? rect.width() : progressBarWidth;
int step = 0;
QRect progressBar;
@ -1356,28 +1359,10 @@ void QFusionStyle::drawControl(ControlElement element, const QStyleOption *optio
if (qGray(outline.rgb()) > qGray(highlightedoutline.rgb()))
outline = highlightedoutline;
if (!indeterminate) {
QColor innerShadow(Qt::black);
innerShadow.setAlpha(35);
painter->setPen(innerShadow);
if (!reverse) {
if (!indeterminate)
progressBar.setRect(rect.left(), rect.top(), width - 1, rect.height() - 1);
if (!complete) {
painter->drawLine(progressBar.topRight() + QPoint(2, 1), progressBar.bottomRight() + QPoint(2, 0));
painter->setPen(QPen(highlight.darker(140)));
painter->drawLine(progressBar.topRight() + QPoint(1, 1), progressBar.bottomRight() + QPoint(1, 0));
}
} else {
progressBar.setRect(rect.right() - width - 1, rect.top(), width + 2, rect.height() - 1);
if (!complete) {
painter->drawLine(progressBar.topLeft() + QPoint(-2, 1), progressBar.bottomLeft() + QPoint(-2, 0));
painter->setPen(QPen(highlight.darker(140)));
painter->drawLine(progressBar.topLeft() + QPoint(-1, 1), progressBar.bottomLeft() + QPoint(-1, 0));
}
}
} else {
else
progressBar.setRect(rect.left(), rect.top(), rect.width() - 1, rect.height() - 1);
}
if (indeterminate || bar->progress > bar->minimum) {
@ -1392,10 +1377,13 @@ void QFusionStyle::drawControl(ControlElement element, const QStyleOption *optio
painter->setBrush(gradient);
painter->save();
// 0.5 - half the width of a cosmetic pen (for vertical line below)
if (!complete && !indeterminate)
painter->setClipRect(progressBar.adjusted(-1, -1, -1, 1));
QRect fillRect = progressBar.adjusted( !indeterminate && !complete && reverse ? -2 : 0, 0,
indeterminate || complete || reverse ? 0 : 2, 0);
painter->setClipRect(QRectF(progressBar).adjusted(-1, -1, 0.5, 1));
QRect fillRect = progressBar;
if (!indeterminate && !complete)
fillRect.setWidth(std::min(fillRect.width() + 2, rect.width() - 1)); // avoid round borders at the right end
painter->drawRoundedRect(fillRect, 2, 2);
painter->restore();
@ -1422,43 +1410,63 @@ void QFusionStyle::drawControl(ControlElement element, const QStyleOption *optio
x + rect.height() + step, progressBar.top() - 2);
}
}
if (!indeterminate && !complete) {
QColor innerShadow(Qt::black);
innerShadow.setAlpha(35);
painter->setPen(innerShadow);
painter->drawLine(progressBar.topRight() + QPoint(2, 1), progressBar.bottomRight() + QPoint(2, 0));
painter->setPen(QPen(highlight.darker(140)));
painter->drawLine(progressBar.topRight() + QPoint(1, 1), progressBar.bottomRight() + QPoint(1, 0));
}
}
painter->restore();
break;
case CE_ProgressBarLabel:
if (const QStyleOptionProgressBar *bar = qstyleoption_cast<const QStyleOptionProgressBar *>(option)) {
QRect leftRect;
QRect rect = bar->rect;
QRect leftRect = rect;
QRect rightRect = rect;
QColor textColor = option->palette.text().color();
QColor alternateTextColor = d->highlightedText(option->palette);
painter->save();
bool vertical = false, inverted = false;
vertical = !(bar->state & QStyle::State_Horizontal);
inverted = bar->invertedAppearance;
if (vertical)
rect = QRect(rect.left(), rect.top(), rect.height(), rect.width()); // flip width and height
const auto vertical = !(bar->state & QStyle::State_Horizontal);
const auto inverted = bar->invertedAppearance;
const auto reverse = (bar->direction == Qt::RightToLeft) ^ inverted;
const auto totalSteps = qMax(Q_INT64_C(1), qint64(bar->maximum) - bar->minimum);
const auto progressSteps = qint64(bar->progress) - bar->minimum;
const auto progressIndicatorPos = progressSteps * rect.width() / totalSteps;
if (progressIndicatorPos >= 0 && progressIndicatorPos <= rect.width())
leftRect = QRect(rect.left(), rect.top(), progressIndicatorPos, rect.height());
if (vertical)
leftRect.translate(rect.width() - progressIndicatorPos, 0);
const auto progressIndicatorPos = progressSteps * (vertical ? rect.height() : rect.width()) / totalSteps;
bool flip = (!vertical && (((bar->direction == Qt::RightToLeft) && !inverted) ||
((bar->direction == Qt::LeftToRight) && inverted)));
if (vertical) {
if (progressIndicatorPos >= 0 && progressIndicatorPos <= rect.height()) {
if (inverted) {
leftRect.setHeight(progressIndicatorPos);
rightRect.setY(progressIndicatorPos);
} else {
leftRect.setHeight(rect.height() - progressIndicatorPos);
rightRect.setY(rect.height() - progressIndicatorPos);
}
}
} else {
if (progressIndicatorPos >= 0 && progressIndicatorPos <= rect.width()) {
if (reverse) {
leftRect.setWidth(rect.width() - progressIndicatorPos);
rightRect.setX(rect.width() - progressIndicatorPos);
} else {
leftRect.setWidth(progressIndicatorPos);
rightRect.setX(progressIndicatorPos);
}
}
}
QRegion rightRect = rect;
rightRect = rightRect.subtracted(leftRect);
painter->setClipRegion(rightRect);
painter->setPen(flip ? alternateTextColor : textColor);
const auto firstIsAlternateColor = (vertical && !inverted) || (!vertical && reverse);
painter->setClipRect(rightRect);
painter->setPen(firstIsAlternateColor ? alternateTextColor : textColor);
painter->drawText(rect, bar->text, QTextOption(Qt::AlignAbsolute | Qt::AlignHCenter | Qt::AlignVCenter));
if (!leftRect.isNull()) {
painter->setPen(flip ? textColor : alternateTextColor);
painter->setPen(firstIsAlternateColor ? textColor : alternateTextColor);
painter->setClipRect(leftRect);
painter->drawText(rect, bar->text, QTextOption(Qt::AlignAbsolute | Qt::AlignHCenter | Qt::AlignVCenter));
}
painter->restore();
}
break;