QAbstractSpinBox: fix some ui glitches

Fix some ui glitches for QAbstractSpinBox:
 - update geometry when buttons are toggled on/off
 - calc button size with subControlRect instead hardcoded 20px
 - when buttons are not shown, don't add the button size in
   sizeFromContents for common and macOS style

Fixes: QTBUG-39713
Fixes: QTBUG-75303
Task-number: QTBUG-67126
Change-Id: Ibf330c76deb16358a481bba6bd429fff6a5d57ae
Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@qt.io>
This commit is contained in:
Christian Ehrlicher 2019-04-21 13:09:07 +02:00
parent 12ebdf0281
commit aa8d3f90a4
6 changed files with 40 additions and 25 deletions

View File

@ -6166,8 +6166,9 @@ QSize QMacStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt,
switch (ct) { switch (ct) {
#if QT_CONFIG(spinbox) #if QT_CONFIG(spinbox)
case CT_SpinBox: case CT_SpinBox:
if (qstyleoption_cast<const QStyleOptionSpinBox *>(opt)) { if (const QStyleOptionSpinBox *vopt = qstyleoption_cast<const QStyleOptionSpinBox *>(opt)) {
const int buttonWidth = 20; // FIXME Use subControlRect() const bool hasButtons = (vopt->buttonSymbols != QAbstractSpinBox::NoButtons);
const int buttonWidth = hasButtons ? proxy()->subControlRect(CC_SpinBox, vopt, SC_SpinBoxUp, widget).width() : 0;
sz += QSize(buttonWidth, 0); sz += QSize(buttonWidth, 0);
} }
break; break;

View File

@ -5029,7 +5029,8 @@ QSize QCommonStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt,
case CT_SpinBox: case CT_SpinBox:
if (const QStyleOptionSpinBox *vopt = qstyleoption_cast<const QStyleOptionSpinBox *>(opt)) { if (const QStyleOptionSpinBox *vopt = qstyleoption_cast<const QStyleOptionSpinBox *>(opt)) {
// Add button + frame widths // Add button + frame widths
const int buttonWidth = (vopt->subControls & (QStyle::SC_SpinBoxUp | QStyle::SC_SpinBoxDown)) != 0 ? 20 : 0; const bool hasButtons = (vopt->buttonSymbols != QAbstractSpinBox::NoButtons);
const int buttonWidth = hasButtons ? proxy()->subControlRect(CC_SpinBox, vopt, SC_SpinBoxUp, widget).width() : 0;
const int fw = vopt->frame ? proxy()->pixelMetric(PM_SpinBoxFrameWidth, vopt, widget) : 0; const int fw = vopt->frame ? proxy()->pixelMetric(PM_SpinBoxFrameWidth, vopt, widget) : 0;
sz += QSize(buttonWidth + 2*fw, 2*fw); sz += QSize(buttonWidth + 2*fw, 2*fw);
} }

View File

@ -4987,17 +4987,19 @@ QSize QStyleSheetStyle::sizeFromContents(ContentsType ct, const QStyleOption *op
switch (ct) { switch (ct) {
#if QT_CONFIG(spinbox) #if QT_CONFIG(spinbox)
case CT_SpinBox: // ### hopelessly broken QAbstractSpinBox (part 1) case CT_SpinBox:
if (const QStyleOptionSpinBox *spinbox = qstyleoption_cast<const QStyleOptionSpinBox *>(opt)) { if (const QStyleOptionSpinBox *spinbox = qstyleoption_cast<const QStyleOptionSpinBox *>(opt)) {
// Add some space for the up/down buttons if (spinbox->buttonSymbols != QAbstractSpinBox::NoButtons) {
QRenderRule subRule = renderRule(w, opt, PseudoElement_SpinBoxUpButton); // Add some space for the up/down buttons
if (subRule.hasDrawable()) { QRenderRule subRule = renderRule(w, opt, PseudoElement_SpinBoxUpButton);
QRect r = positionRect(w, rule, subRule, PseudoElement_SpinBoxUpButton, if (subRule.hasDrawable()) {
opt->rect, opt->direction); QRect r = positionRect(w, rule, subRule, PseudoElement_SpinBoxUpButton,
sz += QSize(r.width(), 0); opt->rect, opt->direction);
} else { sz.rwidth() += r.width();
QSize defaultUpSize = defaultSize(w, subRule.size(), spinbox->rect, PseudoElement_SpinBoxUpButton); } else {
sz += QSize(defaultUpSize.width(), 0); QSize defaultUpSize = defaultSize(w, subRule.size(), spinbox->rect, PseudoElement_SpinBoxUpButton);
sz.rwidth() += defaultUpSize.width();
}
} }
if (rule.hasBox() || rule.hasBorder() || !rule.hasNativeBorder()) if (rule.hasBox() || rule.hasBorder() || !rule.hasNativeBorder())
sz = rule.boxSize(sz); sz = rule.boxSize(sz);
@ -5498,8 +5500,12 @@ QRect QStyleSheetStyle::subControlRect(ComplexControl cc, const QStyleOptionComp
: Qt::Alignment(Qt::AlignRight); : Qt::Alignment(Qt::AlignRight);
downAlign = resolveAlignment(opt->direction, downAlign); downAlign = resolveAlignment(opt->direction, downAlign);
int upSize = subControlRect(CC_SpinBox, opt, SC_SpinBoxUp, w).width(); const bool hasButtons = (spin->buttonSymbols != QAbstractSpinBox::NoButtons);
int downSize = subControlRect(CC_SpinBox, opt, SC_SpinBoxDown, w).width(); const int upSize = hasButtons
? subControlRect(CC_SpinBox, opt, SC_SpinBoxUp, w).width() : 0;
const int downSize = hasButtons
? subControlRect(CC_SpinBox, opt, SC_SpinBoxDown, w).width() : 0;
int widestL = qMax((upAlign & Qt::AlignLeft) ? upSize : 0, int widestL = qMax((upAlign & Qt::AlignLeft) ? upSize : 0,
(downAlign & Qt::AlignLeft) ? downSize : 0); (downAlign & Qt::AlignLeft) ? downSize : 0);
int widestR = qMax((upAlign & Qt::AlignRight) ? upSize : 0, int widestR = qMax((upAlign & Qt::AlignRight) ? upSize : 0,

View File

@ -212,6 +212,7 @@ void QAbstractSpinBox::setButtonSymbols(ButtonSymbols buttonSymbols)
if (d->buttonSymbols != buttonSymbols) { if (d->buttonSymbols != buttonSymbols) {
d->buttonSymbols = buttonSymbols; d->buttonSymbols = buttonSymbols;
d->updateEditFieldGeometry(); d->updateEditFieldGeometry();
updateGeometry();
update(); update();
} }
} }

View File

@ -324,7 +324,9 @@ void tst_QDoubleSpinBox::setPrefixSuffix()
QFETCH(QString, expectedCleanText); QFETCH(QString, expectedCleanText);
QFETCH(bool, show); QFETCH(bool, show);
QDoubleSpinBox spin(0); QDoubleSpinBox spin;
if (show)
spin.show();
spin.setDecimals(decimals); spin.setDecimals(decimals);
const QSize size1 = spin.sizeHint(); const QSize size1 = spin.sizeHint();
spin.setPrefix(prefix); spin.setPrefix(prefix);
@ -332,17 +334,17 @@ void tst_QDoubleSpinBox::setPrefixSuffix()
spin.setSuffix(suffix); spin.setSuffix(suffix);
const QSize size3 = spin.sizeHint(); const QSize size3 = spin.sizeHint();
spin.setValue(value); spin.setValue(value);
if (show)
spin.show();
QCOMPARE(spin.text(), expectedText); QCOMPARE(spin.text(), expectedText);
QCOMPARE(spin.cleanText(), expectedCleanText); QCOMPARE(spin.cleanText(), expectedCleanText);
if (!prefix.isEmpty() && !suffix.isEmpty()) { if (!suffix.isEmpty()) {
QVERIFY(size1.width() < size2.width());
QVERIFY(size2.width() < size3.width()); QVERIFY(size2.width() < size3.width());
spin.setSuffix(QString()); spin.setSuffix(QString());
QCOMPARE(spin.sizeHint(), size2); QCOMPARE(spin.sizeHint(), size2);
}
if (!prefix.isEmpty()) {
QVERIFY(size1.width() < size2.width());
spin.setPrefix(QString()); spin.setPrefix(QString());
QCOMPARE(spin.sizeHint(), size1); QCOMPARE(spin.sizeHint(), size1);
} }

View File

@ -461,26 +461,30 @@ void tst_QSpinBox::setPrefixSuffix()
QFETCH(QString, expectedCleanText); QFETCH(QString, expectedCleanText);
QFETCH(bool, show); QFETCH(bool, show);
QSpinBox spin(0); QSpinBox spin;
if (show) {
spin.show();
spin.setPrefix(QString()); // trigger a recalc of sizeHint
}
const QSize size1 = spin.sizeHint(); const QSize size1 = spin.sizeHint();
spin.setPrefix(prefix); spin.setPrefix(prefix);
const QSize size2 = spin.sizeHint(); const QSize size2 = spin.sizeHint();
spin.setSuffix(suffix); spin.setSuffix(suffix);
const QSize size3 = spin.sizeHint(); const QSize size3 = spin.sizeHint();
spin.setValue(value); spin.setValue(value);
if (show)
spin.show();
QCOMPARE(spin.prefix(), prefix); QCOMPARE(spin.prefix(), prefix);
QCOMPARE(spin.suffix(), suffix); QCOMPARE(spin.suffix(), suffix);
QCOMPARE(spin.text(), expectedText); QCOMPARE(spin.text(), expectedText);
QCOMPARE(spin.cleanText(), expectedCleanText); QCOMPARE(spin.cleanText(), expectedCleanText);
if (!prefix.isEmpty() && !suffix.isEmpty()) { if (!suffix.isEmpty()) {
QVERIFY(size1.width() < size2.width());
QVERIFY(size2.width() < size3.width()); QVERIFY(size2.width() < size3.width());
spin.setSuffix(QString()); spin.setSuffix(QString());
QCOMPARE(spin.sizeHint(), size2); QCOMPARE(spin.sizeHint(), size2);
}
if (!prefix.isEmpty()) {
QVERIFY(size1.width() < size2.width());
spin.setPrefix(QString()); spin.setPrefix(QString());
QCOMPARE(spin.sizeHint(), size1); QCOMPARE(spin.sizeHint(), size1);
} }