Add QStyle::SH_SpinBox_StepModifier style hint

This patch allows the developer to pick which keyboard modifier
increases the number of steps a QAbstractSpinBox takes when the user
interacts with it.

The modifier can be either Qt::ControlModifier (default),
Qt::ShiftModifier or Qt::NoModifier. Qt::NoModifier disables the step
modifier. Note that on macOS, Control corresponds to the Command key.

Holding the modifier increases the step rate when:
- scrolling;
- pressing the up/down keys;
- pressing the spin box up/down buttons.

[ChangeLog][QtWidgets][QStyle] QStyle::SH_SpinBox_StepModifier allows
the developer to pick which keyboard modifier increases the number of
steps a QAbstractSpinBox takes for the following interactions:
scrolling, up/down keyboard keys and the spin box buttons. The
Qt::ShiftModifier can now be used, or the feature can be disabled
using Qt::NoModifier. Previously, only Qt::ControlModifier could be
used as the modifier.

Change-Id: Ib5518127e86a8f67798a9a1d6e860c6e35896e6f
Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@qt.io>
This commit is contained in:
Nathan Collins 2018-05-18 16:27:43 +01:00 committed by Mitch Curtis
parent 21291d78c5
commit e40f23f098
7 changed files with 626 additions and 272 deletions

View File

@ -5306,6 +5306,9 @@ int QCommonStyle::styleHint(StyleHint sh, const QStyleOption *opt, const QWidget
case SH_SpinBox_ButtonsInsideFrame: case SH_SpinBox_ButtonsInsideFrame:
ret = true; ret = true;
break; break;
case SH_SpinBox_StepModifier:
ret = Qt::ControlModifier;
break;
default: default:
ret = 0; ret = 0;
break; break;

View File

@ -2001,6 +2001,13 @@ void QStyle::drawItemPixmap(QPainter *painter, const QRect &rect, int alignment,
Determnines if the spin box buttons are inside the line edit frame. Determnines if the spin box buttons are inside the line edit frame.
This enum value has been introduced in Qt 5.11. This enum value has been introduced in Qt 5.11.
\value SH_SpinBox_StepModifier
Determines which Qt::KeyboardModifier increases the step rate of
QAbstractSpinBox. Possible values are Qt::NoModifier,
Qt::ControlModifier (default) or Qt::ShiftModifier. Qt::NoModifier
disables this feature.
This enum value has been introduced in Qt 5.12.
\sa styleHint() \sa styleHint()
*/ */

View File

@ -741,6 +741,7 @@ public:
SH_Widget_Animation_Duration, SH_Widget_Animation_Duration,
SH_ComboBox_AllowWheelScrolling, SH_ComboBox_AllowWheelScrolling,
SH_SpinBox_ButtonsInsideFrame, SH_SpinBox_ButtonsInsideFrame,
SH_SpinBox_StepModifier,
// Add new style hint values here // Add new style hint values here
SH_CustomBase = 0xf0000000 SH_CustomBase = 0xf0000000

View File

@ -106,6 +106,10 @@ QT_BEGIN_NAMESPACE
the spinbox buttons. Note that on macOS, Control corresponds to the the spinbox buttons. Note that on macOS, Control corresponds to the
Command key. Command key.
Since Qt 5.12, QStyle::SH_SpinBox_StepModifier can be used to select
which Qt::KeyboardModifier increases the step rate. Qt::NoModifier
disables this feature.
QAbstractSpinBox also provide a virtual function stepEnabled() to QAbstractSpinBox also provide a virtual function stepEnabled() to
determine whether stepping up/down is allowed at any point. This determine whether stepping up/down is allowed at any point. This
function returns a bitset of StepEnabled. function returns a bitset of StepEnabled.
@ -840,6 +844,7 @@ void QAbstractSpinBox::changeEvent(QEvent *event)
style()->styleHint(QStyle::SH_SpinBox_ClickAutoRepeatThreshold, 0, this); style()->styleHint(QStyle::SH_SpinBox_ClickAutoRepeatThreshold, 0, this);
if (d->edit) if (d->edit)
d->edit->setFrame(!style()->styleHint(QStyle::SH_SpinBox_ButtonsInsideFrame, nullptr, this)); d->edit->setFrame(!style()->styleHint(QStyle::SH_SpinBox_ButtonsInsideFrame, nullptr, this));
d->stepModifier = static_cast<Qt::KeyboardModifier>(style()->styleHint(QStyle::SH_SpinBox_StepModifier, nullptr, this));
d->reset(); d->reset();
d->updateEditFieldGeometry(); d->updateEditFieldGeometry();
break; break;

View File

@ -114,6 +114,26 @@ public:
} }
}; };
class StepModifierStyle : public QProxyStyle
{
Q_OBJECT
public:
using QProxyStyle::QProxyStyle;
int styleHint(QStyle::StyleHint hint, const QStyleOption *option = nullptr,
const QWidget *widget = nullptr, QStyleHintReturn *returnData = nullptr) const override
{
switch (hint) {
case QStyle::SH_SpinBox_StepModifier:
return stepModifier;
default:
return QProxyStyle::styleHint(hint, option, widget, returnData);
}
}
Qt::KeyboardModifier stepModifier = Qt::ControlModifier;
};
class tst_QDateTimeEdit : public QObject class tst_QDateTimeEdit : public QObject
{ {
Q_OBJECT Q_OBJECT
@ -295,6 +315,12 @@ static QLatin1String modifierToName(Qt::KeyboardModifier modifier)
case Qt::ShiftModifier: case Qt::ShiftModifier:
return QLatin1Literal("Shift"); return QLatin1Literal("Shift");
break; break;
case Qt::AltModifier:
return QLatin1Literal("Alt");
break;
case Qt::MetaModifier:
return QLatin1Literal("Meta");
break;
default: default:
qFatal("Unexpected keyboard modifier"); qFatal("Unexpected keyboard modifier");
return QLatin1String(); return QLatin1String();
@ -3110,6 +3136,7 @@ void tst_QDateTimeEdit::wheelEvent_data()
#if QT_CONFIG(wheelevent) #if QT_CONFIG(wheelevent)
QTest::addColumn<QPoint>("angleDelta"); QTest::addColumn<QPoint>("angleDelta");
QTest::addColumn<int>("qt4Delta"); QTest::addColumn<int>("qt4Delta");
QTest::addColumn<int>("stepModifier");
QTest::addColumn<Qt::KeyboardModifiers>("modifiers"); QTest::addColumn<Qt::KeyboardModifiers>("modifiers");
QTest::addColumn<Qt::MouseEventSource>("source"); QTest::addColumn<Qt::MouseEventSource>("source");
QTest::addColumn<QDateTimeEdit::Section>("section"); QTest::addColumn<QDateTimeEdit::Section>("section");
@ -3121,6 +3148,12 @@ void tst_QDateTimeEdit::wheelEvent_data()
const auto directions = {true, false}; const auto directions = {true, false};
const auto modifierList = {Qt::NoModifier, const auto modifierList = {Qt::NoModifier,
Qt::ShiftModifier,
Qt::ControlModifier,
Qt::AltModifier,
Qt::MetaModifier};
const auto validStepModifierList = {Qt::NoModifier,
Qt::ControlModifier, Qt::ControlModifier,
Qt::ShiftModifier}; Qt::ShiftModifier};
@ -3148,7 +3181,13 @@ void tst_QDateTimeEdit::wheelEvent_data()
if (modifierName.isEmpty()) if (modifierName.isEmpty())
continue; continue;
const int steps = (modifier & Qt::ControlModifier ? 10 : 1) for (auto stepModifier : validStepModifierList) {
const auto stepModifierName = modifierToName(stepModifier);
if (stepModifierName.isEmpty())
continue;
const int steps = (modifier & stepModifier ? 10 : 1)
* (up ? 1 : -1); * (up ? 1 : -1);
for (auto source : sources) { for (auto source : sources) {
@ -3202,14 +3241,16 @@ void tst_QDateTimeEdit::wheelEvent_data()
const QLatin1String sectionName = sectionToName(section); const QLatin1String sectionName = sectionToName(section);
QTest::addRow("%s%s%sWith%sKeyboardModifier%s", QTest::addRow("%s%s%s%sWith%sKeyboardModifier%s",
fraction ? "half" : "full", fraction ? "half" : "full",
up ? "Up" : "Down", up ? "Up" : "Down",
stepModifierName.latin1(),
sectionName.latin1(), sectionName.latin1(),
modifierName.latin1(), modifierName.latin1(),
sourceName.latin1()) sourceName.latin1())
<< angleDelta << angleDelta
<< units << units
<< static_cast<int>(stepModifier)
<< modifiers << modifiers
<< source << source
<< section << section
@ -3220,6 +3261,7 @@ void tst_QDateTimeEdit::wheelEvent_data()
} }
} }
} }
}
#else #else
QSKIP("Built with --no-feature-wheelevent"); QSKIP("Built with --no-feature-wheelevent");
#endif #endif
@ -3230,6 +3272,7 @@ void tst_QDateTimeEdit::wheelEvent()
#if QT_CONFIG(wheelevent) #if QT_CONFIG(wheelevent)
QFETCH(QPoint, angleDelta); QFETCH(QPoint, angleDelta);
QFETCH(int, qt4Delta); QFETCH(int, qt4Delta);
QFETCH(int, stepModifier);
QFETCH(Qt::KeyboardModifiers, modifiers); QFETCH(Qt::KeyboardModifiers, modifiers);
QFETCH(Qt::MouseEventSource, source); QFETCH(Qt::MouseEventSource, source);
QFETCH(QDateTimeEdit::Section, section); QFETCH(QDateTimeEdit::Section, section);
@ -3240,6 +3283,11 @@ void tst_QDateTimeEdit::wheelEvent()
edit.setDate(startDate); edit.setDate(startDate);
edit.setCurrentSection(section); edit.setCurrentSection(section);
QScopedPointer<StepModifierStyle, QScopedPointerDeleteLater> style(
new StepModifierStyle);
style->stepModifier = static_cast<Qt::KeyboardModifier>(stepModifier);
edit.setStyle(style.data());
QWheelEvent event(QPointF(), QPointF(), QPoint(), angleDelta, qt4Delta, QWheelEvent event(QPointF(), QPointF(), QPoint(), angleDelta, qt4Delta,
Qt::Vertical, Qt::NoButton, modifiers, Qt::NoScrollPhase, Qt::Vertical, Qt::NoButton, modifiers, Qt::NoScrollPhase,
source); source);
@ -3977,6 +4025,7 @@ void tst_QDateTimeEdit::dateEditCorrectSectionSize()
void tst_QDateTimeEdit::stepModifierKeys_data() void tst_QDateTimeEdit::stepModifierKeys_data()
{ {
QTest::addColumn<QDate>("startDate"); QTest::addColumn<QDate>("startDate");
QTest::addColumn<int>("stepModifier");
QTest::addColumn<QDateTimeEdit::Section>("section"); QTest::addColumn<QDateTimeEdit::Section>("section");
QTest::addColumn<QTestEventList>("keys"); QTest::addColumn<QTestEventList>("keys");
QTest::addColumn<QDate>("expectedDate"); QTest::addColumn<QDate>("expectedDate");
@ -3984,6 +4033,12 @@ void tst_QDateTimeEdit::stepModifierKeys_data()
const auto keyList = {Qt::Key_Up, Qt::Key_Down}; const auto keyList = {Qt::Key_Up, Qt::Key_Down};
const auto modifierList = {Qt::NoModifier, const auto modifierList = {Qt::NoModifier,
Qt::ShiftModifier,
Qt::ControlModifier,
Qt::AltModifier,
Qt::MetaModifier};
const auto validStepModifierList = {Qt::NoModifier,
Qt::ControlModifier, Qt::ControlModifier,
Qt::ShiftModifier}; Qt::ShiftModifier};
@ -4007,7 +4062,13 @@ void tst_QDateTimeEdit::stepModifierKeys_data()
if (modifierName.isEmpty()) if (modifierName.isEmpty())
continue; continue;
const int steps = (modifier & Qt::ControlModifier ? 10 : 1) for (auto stepModifier : validStepModifierList) {
const auto stepModifierName = modifierToName(stepModifier);
if (stepModifierName.isEmpty())
continue;
const int steps = (modifier & stepModifier ? 10 : 1)
* (up ? 1 : -1); * (up ? 1 : -1);
for (const auto section : sections) { for (const auto section : sections) {
@ -4018,11 +4079,13 @@ void tst_QDateTimeEdit::stepModifierKeys_data()
const auto sectionName = sectionToName(section); const auto sectionName = sectionToName(section);
QTest::addRow("%s%sWith%sKeyboardModifier", QTest::addRow("%s%s%sWith%sKeyboardModifier",
up ? "up" : "down", up ? "up" : "down",
stepModifierName.latin1(),
sectionName.latin1(), sectionName.latin1(),
modifierName.latin1()) modifierName.latin1())
<< startDate << startDate
<< static_cast<int>(stepModifier)
<< section << section
<< keys << keys
<< expectedDate; << expectedDate;
@ -4030,10 +4093,12 @@ void tst_QDateTimeEdit::stepModifierKeys_data()
} }
} }
} }
}
void tst_QDateTimeEdit::stepModifierKeys() void tst_QDateTimeEdit::stepModifierKeys()
{ {
QFETCH(QDate, startDate); QFETCH(QDate, startDate);
QFETCH(int, stepModifier);
QFETCH(QDateTimeEdit::Section, section); QFETCH(QDateTimeEdit::Section, section);
QFETCH(QTestEventList, keys); QFETCH(QTestEventList, keys);
QFETCH(QDate, expectedDate); QFETCH(QDate, expectedDate);
@ -4044,6 +4109,11 @@ void tst_QDateTimeEdit::stepModifierKeys()
QVERIFY(QTest::qWaitForWindowActive(&edit)); QVERIFY(QTest::qWaitForWindowActive(&edit));
edit.setCurrentSection(section); edit.setCurrentSection(section);
QScopedPointer<StepModifierStyle, QScopedPointerDeleteLater> style(
new StepModifierStyle);
style->stepModifier = static_cast<Qt::KeyboardModifier>(stepModifier);
edit.setStyle(style.data());
QCOMPARE(edit.date(), startDate); QCOMPARE(edit.date(), startDate);
keys.simulate(&edit); keys.simulate(&edit);
QCOMPARE(edit.date(), expectedDate); QCOMPARE(edit.date(), expectedDate);
@ -4052,6 +4122,7 @@ void tst_QDateTimeEdit::stepModifierKeys()
void tst_QDateTimeEdit::stepModifierButtons_data() void tst_QDateTimeEdit::stepModifierButtons_data()
{ {
QTest::addColumn<QStyle::SubControl>("subControl"); QTest::addColumn<QStyle::SubControl>("subControl");
QTest::addColumn<int>("stepModifier");
QTest::addColumn<Qt::KeyboardModifiers>("modifiers"); QTest::addColumn<Qt::KeyboardModifiers>("modifiers");
QTest::addColumn<QDateTimeEdit::Section>("section"); QTest::addColumn<QDateTimeEdit::Section>("section");
QTest::addColumn<QTime>("startTime"); QTest::addColumn<QTime>("startTime");
@ -4060,6 +4131,12 @@ void tst_QDateTimeEdit::stepModifierButtons_data()
const auto subControls = {QStyle::SC_SpinBoxUp, QStyle::SC_SpinBoxDown}; const auto subControls = {QStyle::SC_SpinBoxUp, QStyle::SC_SpinBoxDown};
const auto modifierList = {Qt::NoModifier, const auto modifierList = {Qt::NoModifier,
Qt::ShiftModifier,
Qt::ControlModifier,
Qt::AltModifier,
Qt::MetaModifier};
const auto validStepModifierList = {Qt::NoModifier,
Qt::ControlModifier, Qt::ControlModifier,
Qt::ShiftModifier}; Qt::ShiftModifier};
@ -4082,7 +4159,13 @@ void tst_QDateTimeEdit::stepModifierButtons_data()
if (modifierName.isEmpty()) if (modifierName.isEmpty())
continue; continue;
const int steps = (modifier & Qt::ControlModifier ? 10 : 1) for (auto stepModifier : validStepModifierList) {
const auto stepModifierName = modifierToName(stepModifier);
if (stepModifierName.isEmpty())
continue;
const int steps = (modifier & stepModifier ? 10 : 1)
* (up ? 1 : -1); * (up ? 1 : -1);
for (const auto section : sections) { for (const auto section : sections) {
@ -4093,11 +4176,13 @@ void tst_QDateTimeEdit::stepModifierButtons_data()
const auto sectionName = sectionToName(section); const auto sectionName = sectionToName(section);
QTest::addRow("%s%sWith%sKeyboardModifier", QTest::addRow("%s%s%sWith%sKeyboardModifier",
up ? "up" : "down", up ? "up" : "down",
stepModifierName.latin1(),
sectionName.latin1(), sectionName.latin1(),
modifierName.latin1()) modifierName.latin1())
<< subControl << subControl
<< static_cast<int>(stepModifier)
<< modifiers << modifiers
<< section << section
<< startTime << startTime
@ -4106,10 +4191,12 @@ void tst_QDateTimeEdit::stepModifierButtons_data()
} }
} }
} }
}
void tst_QDateTimeEdit::stepModifierButtons() void tst_QDateTimeEdit::stepModifierButtons()
{ {
QFETCH(QStyle::SubControl, subControl); QFETCH(QStyle::SubControl, subControl);
QFETCH(int, stepModifier);
QFETCH(Qt::KeyboardModifiers, modifiers); QFETCH(Qt::KeyboardModifiers, modifiers);
QFETCH(QDateTimeEdit::Section, section); QFETCH(QDateTimeEdit::Section, section);
QFETCH(QTime, startTime); QFETCH(QTime, startTime);
@ -4121,6 +4208,11 @@ void tst_QDateTimeEdit::stepModifierButtons()
QVERIFY(QTest::qWaitForWindowActive(&edit)); QVERIFY(QTest::qWaitForWindowActive(&edit));
edit.setCurrentSection(section); edit.setCurrentSection(section);
QScopedPointer<StepModifierStyle, QScopedPointerDeleteLater> style(
new StepModifierStyle);
style->stepModifier = static_cast<Qt::KeyboardModifier>(stepModifier);
edit.setStyle(style.data());
QStyleOptionSpinBox spinBoxStyleOption; QStyleOptionSpinBox spinBoxStyleOption;
edit.initStyleOption(&spinBoxStyleOption); edit.initStyleOption(&spinBoxStyleOption);
@ -4135,12 +4227,19 @@ void tst_QDateTimeEdit::stepModifierButtons()
void tst_QDateTimeEdit::stepModifierPressAndHold_data() void tst_QDateTimeEdit::stepModifierPressAndHold_data()
{ {
QTest::addColumn<QStyle::SubControl>("subControl"); QTest::addColumn<QStyle::SubControl>("subControl");
QTest::addColumn<int>("stepModifier");
QTest::addColumn<Qt::KeyboardModifiers>("modifiers"); QTest::addColumn<Qt::KeyboardModifiers>("modifiers");
QTest::addColumn<int>("expectedStepModifier"); QTest::addColumn<int>("expectedStepModifier");
const auto subControls = {QStyle::SC_SpinBoxUp, QStyle::SC_SpinBoxDown}; const auto subControls = {QStyle::SC_SpinBoxUp, QStyle::SC_SpinBoxDown};
const auto modifierList = {Qt::NoModifier, const auto modifierList = {Qt::NoModifier,
Qt::ShiftModifier,
Qt::ControlModifier,
Qt::AltModifier,
Qt::MetaModifier};
const auto validStepModifierList = {Qt::NoModifier,
Qt::ControlModifier, Qt::ControlModifier,
Qt::ShiftModifier}; Qt::ShiftModifier};
@ -4157,33 +4256,45 @@ void tst_QDateTimeEdit::stepModifierPressAndHold_data()
if (modifierName.isEmpty()) if (modifierName.isEmpty())
continue; continue;
const int steps = (modifier & Qt::ControlModifier ? 10 : 1) for (auto stepModifier : validStepModifierList) {
const auto stepModifierName = modifierToName(stepModifier);
if (stepModifierName.isEmpty())
continue;
const int steps = (modifier & stepModifier ? 10 : 1)
* (up ? 1 : -1); * (up ? 1 : -1);
QTest::addRow("%sWith%sKeyboardModifier", QTest::addRow("%s%sWith%sKeyboardModifier",
up ? "up" : "down", up ? "up" : "down",
stepModifierName.latin1(),
modifierName.latin1()) modifierName.latin1())
<< subControl << subControl
<< static_cast<int>(stepModifier)
<< modifiers << modifiers
<< steps; << steps;
} }
} }
} }
}
void tst_QDateTimeEdit::stepModifierPressAndHold() void tst_QDateTimeEdit::stepModifierPressAndHold()
{ {
QFETCH(QStyle::SubControl, subControl); QFETCH(QStyle::SubControl, subControl);
QFETCH(int, stepModifier);
QFETCH(Qt::KeyboardModifiers, modifiers); QFETCH(Qt::KeyboardModifiers, modifiers);
QFETCH(int, expectedStepModifier); QFETCH(int, expectedStepModifier);
const QDate startDate(2000, 1, 1); const QDate startDate(2000, 1, 1);
EditorDateEdit edit(0); EditorDateEdit edit(0);
QScopedPointer<PressAndHoldStyle, QScopedPointerDeleteLater> pressAndHoldStyle(
new PressAndHoldStyle);
edit.setStyle(pressAndHoldStyle.data());
edit.setDate(startDate); edit.setDate(startDate);
QScopedPointer<StepModifierStyle, QScopedPointerDeleteLater> stepModifierStyle(
new StepModifierStyle(new PressAndHoldStyle));
stepModifierStyle->stepModifier = static_cast<Qt::KeyboardModifier>(stepModifier);
edit.setStyle(stepModifierStyle.data());
QSignalSpy spy(&edit, &EditorDateEdit::dateChanged); QSignalSpy spy(&edit, &EditorDateEdit::dateChanged);
edit.show(); edit.show();

View File

@ -103,6 +103,26 @@ public:
} }
}; };
class StepModifierStyle : public QProxyStyle
{
Q_OBJECT
public:
using QProxyStyle::QProxyStyle;
int styleHint(QStyle::StyleHint hint, const QStyleOption *option = nullptr,
const QWidget *widget = nullptr, QStyleHintReturn *returnData = nullptr) const override
{
switch (hint) {
case QStyle::SH_SpinBox_StepModifier:
return stepModifier;
default:
return QProxyStyle::styleHint(hint, option, widget, returnData);
}
}
Qt::KeyboardModifier stepModifier = Qt::ControlModifier;
};
class tst_QDoubleSpinBox : public QObject class tst_QDoubleSpinBox : public QObject
{ {
@ -209,6 +229,12 @@ static QLatin1String modifierToName(Qt::KeyboardModifier modifier)
case Qt::ShiftModifier: case Qt::ShiftModifier:
return QLatin1Literal("Shift"); return QLatin1Literal("Shift");
break; break;
case Qt::AltModifier:
return QLatin1Literal("Alt");
break;
case Qt::MetaModifier:
return QLatin1Literal("Meta");
break;
default: default:
qFatal("Unexpected keyboard modifier"); qFatal("Unexpected keyboard modifier");
return QLatin1String(); return QLatin1String();
@ -1338,6 +1364,7 @@ void tst_QDoubleSpinBox::wheelEvents_data()
#if QT_CONFIG(wheelevent) #if QT_CONFIG(wheelevent)
QTest::addColumn<QPoint>("angleDelta"); QTest::addColumn<QPoint>("angleDelta");
QTest::addColumn<int>("qt4Delta"); QTest::addColumn<int>("qt4Delta");
QTest::addColumn<int>("stepModifier");
QTest::addColumn<Qt::KeyboardModifiers>("modifier"); QTest::addColumn<Qt::KeyboardModifiers>("modifier");
QTest::addColumn<Qt::MouseEventSource>("source"); QTest::addColumn<Qt::MouseEventSource>("source");
QTest::addColumn<double>("start"); QTest::addColumn<double>("start");
@ -1348,6 +1375,12 @@ void tst_QDoubleSpinBox::wheelEvents_data()
const auto directions = {true, false}; const auto directions = {true, false};
const auto modifierList = {Qt::NoModifier, const auto modifierList = {Qt::NoModifier,
Qt::ShiftModifier,
Qt::ControlModifier,
Qt::AltModifier,
Qt::MetaModifier};
const auto validStepModifierList = {Qt::NoModifier,
Qt::ControlModifier, Qt::ControlModifier,
Qt::ShiftModifier}; Qt::ShiftModifier};
@ -1371,7 +1404,13 @@ void tst_QDoubleSpinBox::wheelEvents_data()
if (modifierName.isEmpty()) if (modifierName.isEmpty())
continue; continue;
const int steps = (modifier & Qt::ControlModifier ? 10 : 1) for (auto stepModifier : validStepModifierList) {
const auto stepModifierName = modifierToName(stepModifier);
if (stepModifierName.isEmpty())
continue;
const int steps = (modifier & stepModifier ? 10 : 1)
* (up ? 1 : -1); * (up ? 1 : -1);
for (auto source : sources) { for (auto source : sources) {
@ -1416,13 +1455,15 @@ void tst_QDoubleSpinBox::wheelEvents_data()
expectedValues << startValue; expectedValues << startValue;
expectedValues << startValue + steps; expectedValues << startValue + steps;
QTest::addRow("%s%sWith%sKeyboardModifier%s", QTest::addRow("%s%s%sWith%sKeyboardModifier%s",
fraction ? "half" : "full", fraction ? "half" : "full",
up ? "Up" : "Down", up ? "Up" : "Down",
stepModifierName.latin1(),
modifierName.latin1(), modifierName.latin1(),
sourceName.latin1()) sourceName.latin1())
<< angleDelta << angleDelta
<< units << units
<< static_cast<int>(stepModifier)
<< modifiers << modifiers
<< source << source
<< startValue << startValue
@ -1431,6 +1472,7 @@ void tst_QDoubleSpinBox::wheelEvents_data()
} }
} }
} }
}
#else #else
QSKIP("Built with --no-feature-wheelevent"); QSKIP("Built with --no-feature-wheelevent");
#endif #endif
@ -1441,6 +1483,7 @@ void tst_QDoubleSpinBox::wheelEvents()
#if QT_CONFIG(wheelevent) #if QT_CONFIG(wheelevent)
QFETCH(QPoint, angleDelta); QFETCH(QPoint, angleDelta);
QFETCH(int, qt4Delta); QFETCH(int, qt4Delta);
QFETCH(int, stepModifier);
QFETCH(Qt::KeyboardModifiers, modifier); QFETCH(Qt::KeyboardModifiers, modifier);
QFETCH(Qt::MouseEventSource, source); QFETCH(Qt::MouseEventSource, source);
QFETCH(double, start); QFETCH(double, start);
@ -1450,6 +1493,11 @@ void tst_QDoubleSpinBox::wheelEvents()
spinBox.setRange(-20, 20); spinBox.setRange(-20, 20);
spinBox.setValue(start); spinBox.setValue(start);
QScopedPointer<StepModifierStyle, QScopedPointerDeleteLater> style(
new StepModifierStyle);
style->stepModifier = static_cast<Qt::KeyboardModifier>(stepModifier);
spinBox.setStyle(style.data());
QWheelEvent event(QPointF(), QPointF(), QPoint(), angleDelta, qt4Delta, QWheelEvent event(QPointF(), QPointF(), QPoint(), angleDelta, qt4Delta,
Qt::Vertical, Qt::NoButton, modifier, Qt::NoScrollPhase, Qt::Vertical, Qt::NoButton, modifier, Qt::NoScrollPhase,
source); source);
@ -1465,15 +1513,23 @@ void tst_QDoubleSpinBox::wheelEvents()
void tst_QDoubleSpinBox::stepModifierKeys_data() void tst_QDoubleSpinBox::stepModifierKeys_data()
{ {
QTest::addColumn<double>("startValue"); QTest::addColumn<double>("startValue");
QTest::addColumn<int>("stepModifier");
QTest::addColumn<QTestEventList>("keys"); QTest::addColumn<QTestEventList>("keys");
QTest::addColumn<double>("expectedValue"); QTest::addColumn<double>("expectedValue");
const auto keyList = {Qt::Key_Up, Qt::Key_Down}; const auto keyList = {Qt::Key_Up, Qt::Key_Down};
const auto modifierList = {Qt::NoModifier, const auto modifierList = {Qt::NoModifier,
Qt::ShiftModifier,
Qt::ControlModifier,
Qt::AltModifier,
Qt::MetaModifier};
const auto validStepModifierList = {Qt::NoModifier,
Qt::ControlModifier, Qt::ControlModifier,
Qt::ShiftModifier}; Qt::ShiftModifier};
for (auto key : keyList) { for (auto key : keyList) {
const bool up = key == Qt::Key_Up; const bool up = key == Qt::Key_Up;
@ -1490,29 +1546,45 @@ void tst_QDoubleSpinBox::stepModifierKeys_data()
if (modifierName.isEmpty()) if (modifierName.isEmpty())
continue; continue;
const int steps = (modifier & Qt::ControlModifier ? 10 : 1) for (auto stepModifier : validStepModifierList) {
const auto stepModifierName = modifierToName(stepModifier);
if (stepModifierName.isEmpty())
continue;
const int steps = (modifier & stepModifier ? 10 : 1)
* (up ? 1 : -1); * (up ? 1 : -1);
const double expectedValue = startValue + steps; const double expectedValue = startValue + steps;
QTest::addRow("%sWith%sKeyboardModifier", QTest::addRow("%s%sWith%sKeyboardModifier",
up ? "up" : "down", up ? "up" : "down",
stepModifierName.latin1(),
modifierName.latin1()) modifierName.latin1())
<< startValue << startValue
<< static_cast<int>(stepModifier)
<< keys << keys
<< expectedValue; << expectedValue;
} }
} }
} }
}
void tst_QDoubleSpinBox::stepModifierKeys() void tst_QDoubleSpinBox::stepModifierKeys()
{ {
QFETCH(double, startValue); QFETCH(double, startValue);
QFETCH(int, stepModifier);
QFETCH(QTestEventList, keys); QFETCH(QTestEventList, keys);
QFETCH(double, expectedValue); QFETCH(double, expectedValue);
QDoubleSpinBox spin(0); QDoubleSpinBox spin(0);
spin.setValue(startValue); spin.setValue(startValue);
QScopedPointer<StepModifierStyle, QScopedPointerDeleteLater> style(
new StepModifierStyle);
style->stepModifier = static_cast<Qt::KeyboardModifier>(stepModifier);
spin.setStyle(style.data());
spin.show(); spin.show();
QVERIFY(QTest::qWaitForWindowActive(&spin)); QVERIFY(QTest::qWaitForWindowActive(&spin));
@ -1524,6 +1596,7 @@ void tst_QDoubleSpinBox::stepModifierKeys()
void tst_QDoubleSpinBox::stepModifierButtons_data() void tst_QDoubleSpinBox::stepModifierButtons_data()
{ {
QTest::addColumn<QStyle::SubControl>("subControl"); QTest::addColumn<QStyle::SubControl>("subControl");
QTest::addColumn<int>("stepModifier");
QTest::addColumn<Qt::KeyboardModifiers>("modifiers"); QTest::addColumn<Qt::KeyboardModifiers>("modifiers");
QTest::addColumn<double>("startValue"); QTest::addColumn<double>("startValue");
QTest::addColumn<double>("expectedValue"); QTest::addColumn<double>("expectedValue");
@ -1531,6 +1604,12 @@ void tst_QDoubleSpinBox::stepModifierButtons_data()
const auto subControls = {QStyle::SC_SpinBoxUp, QStyle::SC_SpinBoxDown}; const auto subControls = {QStyle::SC_SpinBoxUp, QStyle::SC_SpinBoxDown};
const auto modifierList = {Qt::NoModifier, const auto modifierList = {Qt::NoModifier,
Qt::ShiftModifier,
Qt::ControlModifier,
Qt::AltModifier,
Qt::MetaModifier};
const auto validStepModifierList = {Qt::NoModifier,
Qt::ControlModifier, Qt::ControlModifier,
Qt::ShiftModifier}; Qt::ShiftModifier};
@ -1549,25 +1628,35 @@ void tst_QDoubleSpinBox::stepModifierButtons_data()
if (modifierName.isEmpty()) if (modifierName.isEmpty())
continue; continue;
const int steps = (modifier & Qt::ControlModifier ? 10 : 1) for (auto stepModifier : validStepModifierList) {
const auto stepModifierName = modifierToName(stepModifier);
if (stepModifierName.isEmpty())
continue;
const int steps = (modifier & stepModifier ? 10 : 1)
* (up ? 1 : -1); * (up ? 1 : -1);
const double expectedValue = startValue + steps; const double expectedValue = startValue + steps;
QTest::addRow("%sWith%sKeyboardModifier", QTest::addRow("%s%sWith%sKeyboardModifier",
up ? "up" : "down", up ? "up" : "down",
stepModifierName.latin1(),
modifierName.latin1()) modifierName.latin1())
<< subControl << subControl
<< static_cast<int>(stepModifier)
<< modifiers << modifiers
<< startValue << startValue
<< expectedValue; << expectedValue;
} }
} }
} }
}
void tst_QDoubleSpinBox::stepModifierButtons() void tst_QDoubleSpinBox::stepModifierButtons()
{ {
QFETCH(QStyle::SubControl, subControl); QFETCH(QStyle::SubControl, subControl);
QFETCH(int, stepModifier);
QFETCH(Qt::KeyboardModifiers, modifiers); QFETCH(Qt::KeyboardModifiers, modifiers);
QFETCH(double, startValue); QFETCH(double, startValue);
QFETCH(double, expectedValue); QFETCH(double, expectedValue);
@ -1575,6 +1664,12 @@ void tst_QDoubleSpinBox::stepModifierButtons()
DoubleSpinBox spin(0); DoubleSpinBox spin(0);
spin.setRange(-20, 20); spin.setRange(-20, 20);
spin.setValue(startValue); spin.setValue(startValue);
QScopedPointer<StepModifierStyle, QScopedPointerDeleteLater> style(
new StepModifierStyle);
style->stepModifier = static_cast<Qt::KeyboardModifier>(stepModifier);
spin.setStyle(style.data());
spin.show(); spin.show();
QVERIFY(QTest::qWaitForWindowActive(&spin)); QVERIFY(QTest::qWaitForWindowActive(&spin));
@ -1592,12 +1687,19 @@ void tst_QDoubleSpinBox::stepModifierButtons()
void tst_QDoubleSpinBox::stepModifierPressAndHold_data() void tst_QDoubleSpinBox::stepModifierPressAndHold_data()
{ {
QTest::addColumn<QStyle::SubControl>("subControl"); QTest::addColumn<QStyle::SubControl>("subControl");
QTest::addColumn<int>("stepModifier");
QTest::addColumn<Qt::KeyboardModifiers>("modifiers"); QTest::addColumn<Qt::KeyboardModifiers>("modifiers");
QTest::addColumn<int>("expectedStepModifier"); QTest::addColumn<int>("expectedStepModifier");
const auto subControls = {QStyle::SC_SpinBoxUp, QStyle::SC_SpinBoxDown}; const auto subControls = {QStyle::SC_SpinBoxUp, QStyle::SC_SpinBoxDown};
const auto modifierList = {Qt::NoModifier, const auto modifierList = {Qt::NoModifier,
Qt::ShiftModifier,
Qt::ControlModifier,
Qt::AltModifier,
Qt::MetaModifier};
const auto validStepModifierList = {Qt::NoModifier,
Qt::ControlModifier, Qt::ControlModifier,
Qt::ShiftModifier}; Qt::ShiftModifier};
@ -1614,32 +1716,44 @@ void tst_QDoubleSpinBox::stepModifierPressAndHold_data()
if (modifierName.isEmpty()) if (modifierName.isEmpty())
continue; continue;
const int steps = (modifier & Qt::ControlModifier ? 10 : 1) for (auto stepModifier : validStepModifierList) {
const auto stepModifierName = modifierToName(stepModifier);
if (stepModifierName.isEmpty())
continue;
const int steps = (modifier & stepModifier ? 10 : 1)
* (up ? 1 : -1); * (up ? 1 : -1);
QTest::addRow("%sWith%sKeyboardModifier", QTest::addRow("%s%sWith%sKeyboardModifier",
up ? "up" : "down", up ? "up" : "down",
stepModifierName.latin1(),
modifierName.latin1()) modifierName.latin1())
<< subControl << subControl
<< static_cast<int>(stepModifier)
<< modifiers << modifiers
<< steps; << steps;
} }
} }
} }
}
void tst_QDoubleSpinBox::stepModifierPressAndHold() void tst_QDoubleSpinBox::stepModifierPressAndHold()
{ {
QFETCH(QStyle::SubControl, subControl); QFETCH(QStyle::SubControl, subControl);
QFETCH(int, stepModifier);
QFETCH(Qt::KeyboardModifiers, modifiers); QFETCH(Qt::KeyboardModifiers, modifiers);
QFETCH(int, expectedStepModifier); QFETCH(int, expectedStepModifier);
DoubleSpinBox spin(0); DoubleSpinBox spin(0);
QScopedPointer<PressAndHoldStyle, QScopedPointerDeleteLater> pressAndHoldStyle(
new PressAndHoldStyle);
spin.setStyle(pressAndHoldStyle.data());
spin.setRange(-100.0, 100.0); spin.setRange(-100.0, 100.0);
spin.setValue(0.0); spin.setValue(0.0);
QScopedPointer<StepModifierStyle, QScopedPointerDeleteLater> stepModifierStyle(
new StepModifierStyle(new PressAndHoldStyle));
stepModifierStyle->stepModifier = static_cast<Qt::KeyboardModifier>(stepModifier);
spin.setStyle(stepModifierStyle.data());
QSignalSpy spy(&spin, QOverload<double>::of(&DoubleSpinBox::valueChanged)); QSignalSpy spy(&spin, QOverload<double>::of(&DoubleSpinBox::valueChanged));
spin.show(); spin.show();

View File

@ -106,6 +106,26 @@ public:
} }
}; };
class StepModifierStyle : public QProxyStyle
{
Q_OBJECT
public:
using QProxyStyle::QProxyStyle;
int styleHint(QStyle::StyleHint hint, const QStyleOption *option = nullptr,
const QWidget *widget = nullptr, QStyleHintReturn *returnData = nullptr) const override
{
switch (hint) {
case QStyle::SH_SpinBox_StepModifier:
return stepModifier;
default:
return QProxyStyle::styleHint(hint, option, widget, returnData);
}
}
Qt::KeyboardModifier stepModifier = Qt::ControlModifier;
};
class tst_QSpinBox : public QObject class tst_QSpinBox : public QObject
{ {
Q_OBJECT Q_OBJECT
@ -208,6 +228,12 @@ static QLatin1String modifierToName(Qt::KeyboardModifier modifier)
case Qt::ShiftModifier: case Qt::ShiftModifier:
return QLatin1Literal("Shift"); return QLatin1Literal("Shift");
break; break;
case Qt::AltModifier:
return QLatin1Literal("Alt");
break;
case Qt::MetaModifier:
return QLatin1Literal("Meta");
break;
default: default:
qFatal("Unexpected keyboard modifier"); qFatal("Unexpected keyboard modifier");
return QLatin1String(); return QLatin1String();
@ -1280,6 +1306,7 @@ void tst_QSpinBox::wheelEvents_data()
#if QT_CONFIG(wheelevent) #if QT_CONFIG(wheelevent)
QTest::addColumn<QPoint>("angleDelta"); QTest::addColumn<QPoint>("angleDelta");
QTest::addColumn<int>("qt4Delta"); QTest::addColumn<int>("qt4Delta");
QTest::addColumn<int>("stepModifier");
QTest::addColumn<Qt::KeyboardModifiers>("modifier"); QTest::addColumn<Qt::KeyboardModifiers>("modifier");
QTest::addColumn<Qt::MouseEventSource>("source"); QTest::addColumn<Qt::MouseEventSource>("source");
QTest::addColumn<int>("start"); QTest::addColumn<int>("start");
@ -1290,6 +1317,12 @@ void tst_QSpinBox::wheelEvents_data()
const auto directions = {true, false}; const auto directions = {true, false};
const auto modifierList = {Qt::NoModifier, const auto modifierList = {Qt::NoModifier,
Qt::ShiftModifier,
Qt::ControlModifier,
Qt::AltModifier,
Qt::MetaModifier};
const auto validStepModifierList = {Qt::NoModifier,
Qt::ControlModifier, Qt::ControlModifier,
Qt::ShiftModifier}; Qt::ShiftModifier};
@ -1313,7 +1346,13 @@ void tst_QSpinBox::wheelEvents_data()
if (modifierName.isEmpty()) if (modifierName.isEmpty())
continue; continue;
const int steps = (modifier & Qt::ControlModifier ? 10 : 1) for (auto stepModifier : validStepModifierList) {
const auto stepModifierName = modifierToName(stepModifier);
if (stepModifierName.isEmpty())
continue;
const int steps = (modifier & stepModifier ? 10 : 1)
* (up ? 1 : -1); * (up ? 1 : -1);
for (auto source : sources) { for (auto source : sources) {
@ -1358,13 +1397,15 @@ void tst_QSpinBox::wheelEvents_data()
expectedValues << startValue; expectedValues << startValue;
expectedValues << startValue + steps; expectedValues << startValue + steps;
QTest::addRow("%s%sWith%sKeyboardModifier%s", QTest::addRow("%s%s%sWith%sKeyboardModifier%s",
fraction ? "half" : "full", fraction ? "half" : "full",
up ? "Up" : "Down", up ? "Up" : "Down",
stepModifierName.latin1(),
modifierName.latin1(), modifierName.latin1(),
sourceName.latin1()) sourceName.latin1())
<< angleDelta << angleDelta
<< units << units
<< static_cast<int>(stepModifier)
<< modifiers << modifiers
<< source << source
<< startValue << startValue
@ -1373,6 +1414,7 @@ void tst_QSpinBox::wheelEvents_data()
} }
} }
} }
}
#else #else
QSKIP("Built with --no-feature-wheelevent"); QSKIP("Built with --no-feature-wheelevent");
#endif #endif
@ -1383,6 +1425,7 @@ void tst_QSpinBox::wheelEvents()
#if QT_CONFIG(wheelevent) #if QT_CONFIG(wheelevent)
QFETCH(QPoint, angleDelta); QFETCH(QPoint, angleDelta);
QFETCH(int, qt4Delta); QFETCH(int, qt4Delta);
QFETCH(int, stepModifier);
QFETCH(Qt::KeyboardModifiers, modifier); QFETCH(Qt::KeyboardModifiers, modifier);
QFETCH(Qt::MouseEventSource, source); QFETCH(Qt::MouseEventSource, source);
QFETCH(int, start); QFETCH(int, start);
@ -1392,6 +1435,11 @@ void tst_QSpinBox::wheelEvents()
spinBox.setRange(-20, 20); spinBox.setRange(-20, 20);
spinBox.setValue(start); spinBox.setValue(start);
QScopedPointer<StepModifierStyle, QScopedPointerDeleteLater> style(
new StepModifierStyle);
style->stepModifier = static_cast<Qt::KeyboardModifier>(stepModifier);
spinBox.setStyle(style.data());
QWheelEvent event(QPointF(), QPointF(), QPoint(), angleDelta, qt4Delta, QWheelEvent event(QPointF(), QPointF(), QPoint(), angleDelta, qt4Delta,
Qt::Vertical, Qt::NoButton, modifier, Qt::NoScrollPhase, Qt::Vertical, Qt::NoButton, modifier, Qt::NoScrollPhase,
source); source);
@ -1486,12 +1534,19 @@ void tst_QSpinBox::adaptiveDecimalStep()
void tst_QSpinBox::stepModifierKeys_data() void tst_QSpinBox::stepModifierKeys_data()
{ {
QTest::addColumn<int>("startValue"); QTest::addColumn<int>("startValue");
QTest::addColumn<int>("stepModifier");
QTest::addColumn<QTestEventList>("keys"); QTest::addColumn<QTestEventList>("keys");
QTest::addColumn<int>("expectedValue"); QTest::addColumn<int>("expectedValue");
const auto keyList = {Qt::Key_Up, Qt::Key_Down}; const auto keyList = {Qt::Key_Up, Qt::Key_Down};
const auto modifierList = {Qt::NoModifier, const auto modifierList = {Qt::NoModifier,
Qt::ShiftModifier,
Qt::ControlModifier,
Qt::AltModifier,
Qt::MetaModifier};
const auto validStepModifierList = {Qt::NoModifier,
Qt::ControlModifier, Qt::ControlModifier,
Qt::ShiftModifier}; Qt::ShiftModifier};
@ -1511,29 +1566,45 @@ void tst_QSpinBox::stepModifierKeys_data()
if (modifierName.isEmpty()) if (modifierName.isEmpty())
continue; continue;
const int steps = (modifier & Qt::ControlModifier ? 10 : 1) for (auto stepModifier : validStepModifierList) {
const auto stepModifierName = modifierToName(stepModifier);
if (stepModifierName.isEmpty())
continue;
const int steps = (modifier & stepModifier ? 10 : 1)
* (up ? 1 : -1); * (up ? 1 : -1);
const int expectedValue = startValue + steps; const int expectedValue = startValue + steps;
QTest::addRow("%sWith%sKeyboardModifier", QTest::addRow("%s%sWith%sKeyboardModifier",
up ? "up" : "down", up ? "up" : "down",
stepModifierName.latin1(),
modifierName.latin1()) modifierName.latin1())
<< startValue << startValue
<< static_cast<int>(stepModifier)
<< keys << keys
<< expectedValue; << expectedValue;
} }
} }
} }
}
void tst_QSpinBox::stepModifierKeys() void tst_QSpinBox::stepModifierKeys()
{ {
QFETCH(int, startValue); QFETCH(int, startValue);
QFETCH(int, stepModifier);
QFETCH(QTestEventList, keys); QFETCH(QTestEventList, keys);
QFETCH(int, expectedValue); QFETCH(int, expectedValue);
QSpinBox spin(0); QSpinBox spin(0);
spin.setValue(startValue); spin.setValue(startValue);
QScopedPointer<StepModifierStyle, QScopedPointerDeleteLater> style(
new StepModifierStyle);
style->stepModifier = static_cast<Qt::KeyboardModifier>(stepModifier);
spin.setStyle(style.data());
spin.show(); spin.show();
QVERIFY(QTest::qWaitForWindowActive(&spin)); QVERIFY(QTest::qWaitForWindowActive(&spin));
@ -1545,6 +1616,7 @@ void tst_QSpinBox::stepModifierKeys()
void tst_QSpinBox::stepModifierButtons_data() void tst_QSpinBox::stepModifierButtons_data()
{ {
QTest::addColumn<QStyle::SubControl>("subControl"); QTest::addColumn<QStyle::SubControl>("subControl");
QTest::addColumn<int>("stepModifier");
QTest::addColumn<Qt::KeyboardModifiers>("modifiers"); QTest::addColumn<Qt::KeyboardModifiers>("modifiers");
QTest::addColumn<int>("startValue"); QTest::addColumn<int>("startValue");
QTest::addColumn<int>("expectedValue"); QTest::addColumn<int>("expectedValue");
@ -1552,6 +1624,12 @@ void tst_QSpinBox::stepModifierButtons_data()
const auto subControls = {QStyle::SC_SpinBoxUp, QStyle::SC_SpinBoxDown}; const auto subControls = {QStyle::SC_SpinBoxUp, QStyle::SC_SpinBoxDown};
const auto modifierList = {Qt::NoModifier, const auto modifierList = {Qt::NoModifier,
Qt::ShiftModifier,
Qt::ControlModifier,
Qt::AltModifier,
Qt::MetaModifier};
const auto validStepModifierList = {Qt::NoModifier,
Qt::ControlModifier, Qt::ControlModifier,
Qt::ShiftModifier}; Qt::ShiftModifier};
@ -1570,25 +1648,35 @@ void tst_QSpinBox::stepModifierButtons_data()
if (modifierName.isEmpty()) if (modifierName.isEmpty())
continue; continue;
const int steps = (modifier & Qt::ControlModifier ? 10 : 1) for (auto stepModifier : validStepModifierList) {
const auto stepModifierName = modifierToName(stepModifier);
if (stepModifierName.isEmpty())
continue;
const int steps = (modifier & stepModifier ? 10 : 1)
* (up ? 1 : -1); * (up ? 1 : -1);
const int expectedValue = startValue + steps; const int expectedValue = startValue + steps;
QTest::addRow("%sWith%sKeyboardModifier", QTest::addRow("%s%sWith%sKeyboardModifier",
up ? "up" : "down", up ? "up" : "down",
stepModifierName.latin1(),
modifierName.latin1()) modifierName.latin1())
<< subControl << subControl
<< static_cast<int>(stepModifier)
<< modifiers << modifiers
<< startValue << startValue
<< expectedValue; << expectedValue;
} }
} }
} }
}
void tst_QSpinBox::stepModifierButtons() void tst_QSpinBox::stepModifierButtons()
{ {
QFETCH(QStyle::SubControl, subControl); QFETCH(QStyle::SubControl, subControl);
QFETCH(int, stepModifier);
QFETCH(Qt::KeyboardModifiers, modifiers); QFETCH(Qt::KeyboardModifiers, modifiers);
QFETCH(int, startValue); QFETCH(int, startValue);
QFETCH(int, expectedValue); QFETCH(int, expectedValue);
@ -1596,6 +1684,12 @@ void tst_QSpinBox::stepModifierButtons()
SpinBox spin(0); SpinBox spin(0);
spin.setRange(-20, 20); spin.setRange(-20, 20);
spin.setValue(startValue); spin.setValue(startValue);
QScopedPointer<StepModifierStyle, QScopedPointerDeleteLater> style(
new StepModifierStyle);
style->stepModifier = static_cast<Qt::KeyboardModifier>(stepModifier);
spin.setStyle(style.data());
spin.show(); spin.show();
QVERIFY(QTest::qWaitForWindowActive(&spin)); QVERIFY(QTest::qWaitForWindowActive(&spin));
@ -1613,12 +1707,19 @@ void tst_QSpinBox::stepModifierButtons()
void tst_QSpinBox::stepModifierPressAndHold_data() void tst_QSpinBox::stepModifierPressAndHold_data()
{ {
QTest::addColumn<QStyle::SubControl>("subControl"); QTest::addColumn<QStyle::SubControl>("subControl");
QTest::addColumn<int>("stepModifier");
QTest::addColumn<Qt::KeyboardModifiers>("modifiers"); QTest::addColumn<Qt::KeyboardModifiers>("modifiers");
QTest::addColumn<int>("expectedStepModifier"); QTest::addColumn<int>("expectedStepModifier");
const auto subControls = {QStyle::SC_SpinBoxUp, QStyle::SC_SpinBoxDown}; const auto subControls = {QStyle::SC_SpinBoxUp, QStyle::SC_SpinBoxDown};
const auto modifierList = {Qt::NoModifier, const auto modifierList = {Qt::NoModifier,
Qt::ShiftModifier,
Qt::ControlModifier,
Qt::AltModifier,
Qt::MetaModifier};
const auto validStepModifierList = {Qt::NoModifier,
Qt::ControlModifier, Qt::ControlModifier,
Qt::ShiftModifier}; Qt::ShiftModifier};
@ -1635,32 +1736,44 @@ void tst_QSpinBox::stepModifierPressAndHold_data()
if (modifierName.isEmpty()) if (modifierName.isEmpty())
continue; continue;
const int steps = (modifier & Qt::ControlModifier ? 10 : 1) for (auto stepModifier : validStepModifierList) {
const auto stepModifierName = modifierToName(stepModifier);
if (stepModifierName.isEmpty())
continue;
const int steps = (modifier & stepModifier ? 10 : 1)
* (up ? 1 : -1); * (up ? 1 : -1);
QTest::addRow("%sWith%sKeyboardModifier", QTest::addRow("%s%sWith%sKeyboardModifier",
up ? "up" : "down", up ? "up" : "down",
stepModifierName.latin1(),
modifierName.latin1()) modifierName.latin1())
<< subControl << subControl
<< static_cast<int>(stepModifier)
<< modifiers << modifiers
<< steps; << steps;
} }
} }
} }
}
void tst_QSpinBox::stepModifierPressAndHold() void tst_QSpinBox::stepModifierPressAndHold()
{ {
QFETCH(QStyle::SubControl, subControl); QFETCH(QStyle::SubControl, subControl);
QFETCH(int, stepModifier);
QFETCH(Qt::KeyboardModifiers, modifiers); QFETCH(Qt::KeyboardModifiers, modifiers);
QFETCH(int, expectedStepModifier); QFETCH(int, expectedStepModifier);
SpinBox spin(0); SpinBox spin(0);
QScopedPointer<PressAndHoldStyle, QScopedPointerDeleteLater> pressAndHoldStyle(
new PressAndHoldStyle);
spin.setStyle(pressAndHoldStyle.data());
spin.setRange(-100, 100); spin.setRange(-100, 100);
spin.setValue(0); spin.setValue(0);
QScopedPointer<StepModifierStyle, QScopedPointerDeleteLater> stepModifierStyle(
new StepModifierStyle(new PressAndHoldStyle));
stepModifierStyle->stepModifier = static_cast<Qt::KeyboardModifier>(stepModifier);
spin.setStyle(stepModifierStyle.data());
QSignalSpy spy(&spin, QOverload<int>::of(&SpinBox::valueChanged)); QSignalSpy spy(&spin, QOverload<int>::of(&SpinBox::valueChanged));
spin.show(); spin.show();