Add style hint for preventing spin box selection on up/down

On a mobile device, selecting text in a line edit brings up the text
action popup for select/copy/cut. In a spinbox where the user changes the
value using the buttons, this can be very irritating, without providing
any usability - the user is unlikely to start typing, at least not
without first transferring focus into the lineedit first to bring up the
keyboard.

This style hint allows styles to override the default behavior of
QAbstractSpinBox. Implement the customization for the Android style, and
add a test case for QSpinBox.

[ChangeLog][QtWidgets][QStyle] A new style hint, SH_SpinBox_SelectOnStep,
specifies whether pressing the up/down buttons or keys in a spinbox will
automatically select the text.

Fixes: QTBUG-93366
Change-Id: If06365a7c62087a2213145e13119f56544ac33b5
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@qt.io>
bb10
Volker Hilsheimer 2021-10-05 15:47:06 +02:00
parent e4a09b0194
commit e0b6b27d39
6 changed files with 76 additions and 1 deletions

View File

@ -677,6 +677,9 @@ int QAndroidStyle::styleHint(QStyle::StyleHint hint, const QStyleOption *option,
case SH_RequestSoftwareInputPanel:
return RSIP_OnMouseClick;
case SH_SpinBox_SelectOnStep:
return 0;
default:
return QFusionStyle::styleHint(hint, option, widget, returnData);
}

View File

@ -5393,6 +5393,9 @@ int QCommonStyle::styleHint(StyleHint sh, const QStyleOption *opt, const QWidget
case SH_TabBar_AllowWheelScrolling:
ret = true;
break;
case SH_SpinBox_SelectOnStep:
ret = true;
break;
default:
ret = 0;
break;

View File

@ -1853,6 +1853,10 @@ void QStyle::drawItemPixmap(QPainter *painter, const QRect &rect, int alignment,
spinbox mouse clicks.
\value SH_SpinBox_ClickAutoRepeatThreshold Auto-repeat threshold for
spinbox mouse clicks.
\value SH_SpinBox_SelectOnStep Whether changing the value using
the buttons or up/down keys automatically selects the text. This enum
value has been introduced in Qt 6.3.
\value SH_ToolTipLabel_Opacity An integer indicating the opacity for
the tip label, 0 is completely transparent, 255 is completely
opaque.

View File

@ -737,6 +737,7 @@ public:
SH_SpinBox_StepModifier,
SH_TabBar_AllowWheelScrolling,
SH_Table_AlwaysDrawLeftTopGridLines,
SH_SpinBox_SelectOnStep,
// Add new style hint values here
SH_CustomBase = 0xf0000000

View File

@ -671,7 +671,8 @@ void QAbstractSpinBox::stepBy(int steps)
} else if (e == AlwaysEmit) {
d->emitSignals(e, old);
}
selectAll();
if (style()->styleHint(QStyle::SH_SpinBox_SelectOnStep, nullptr, this, nullptr))
selectAll();
}
/*!

View File

@ -130,6 +130,28 @@ public:
Qt::KeyboardModifier stepModifier = Qt::ControlModifier;
};
class SelectAllOnStepStyle : public QProxyStyle
{
public:
SelectAllOnStepStyle(bool selectAll)
: selectAll(selectAll)
{}
int styleHint(QStyle::StyleHint hint, const QStyleOption *option,
const QWidget *widget, QStyleHintReturn *returnData = nullptr) const override
{
switch (hint) {
case QStyle::SH_SpinBox_SelectOnStep:
return selectAll;
default:
return QProxyStyle::styleHint(hint, option, widget, returnData);
}
}
private:
const bool selectAll;
};
class tst_QSpinBox : public QObject
{
Q_OBJECT
@ -210,6 +232,10 @@ private slots:
void stepModifierPressAndHold_data();
void stepModifierPressAndHold();
void stepSelectAll_data();
void stepSelectAll();
public slots:
void textChangedHelper(const QString &);
void valueChangedHelper(int);
@ -1855,5 +1881,42 @@ void tst_QSpinBox::stepModifierPressAndHold()
QCOMPARE(value.toInt(), spy.length() * expectedStepModifier);
}
void tst_QSpinBox::stepSelectAll_data()
{
QTest::addColumn<bool>("stepShouldSelectAll");
QTest::addColumn<QStringList>("selectedText");
QTest::addRow("select all") << true << QStringList{"1", "0", "5", "4", "9"};
QTest::addRow("don't select all") << false << QStringList{{}, {}, {}, {}, "94"};
}
void tst_QSpinBox::stepSelectAll()
{
QFETCH(bool, stepShouldSelectAll);
QFETCH(QStringList, selectedText);
SelectAllOnStepStyle style(stepShouldSelectAll);
SpinBox spinBox;
spinBox.setStyle(&style);
QCOMPARE(spinBox.lineEdit()->selectedText(), QString());
auto it = selectedText.cbegin();
spinBox.stepUp();
QCOMPARE(spinBox.lineEdit()->selectedText(), *(it++));
spinBox.lineEdit()->deselect();
spinBox.stepDown();
QCOMPARE(spinBox.lineEdit()->selectedText(), *(it++));
spinBox.lineEdit()->deselect();
spinBox.stepBy(5);
QCOMPARE(spinBox.lineEdit()->selectedText(), *(it++));
spinBox.lineEdit()->deselect();
QTest::keyClick(&spinBox, Qt::Key_Down);
QCOMPARE(spinBox.lineEdit()->selectedText(), *(it++));
QTest::keyClicks(&spinBox, "9");
QCOMPARE(spinBox.lineEdit()->selectedText(), QString());
QCOMPARE(spinBox.lineEdit()->text(), *(it++));
}
QTEST_MAIN(tst_QSpinBox)
#include "tst_qspinbox.moc"