summaryrefslogtreecommitdiffstats
path: root/tests/auto/widgets/widgets/qdatetimeedit
diff options
context:
space:
mode:
authorNathan Collins <nathan.collins@kdab.com>2018-05-14 19:22:22 +0100
committerNathan Collins <nathan.collins@kdab.com>2018-05-24 09:44:16 +0000
commit2d1e1f569b6de3edacd828c5e2452cfe1040192c (patch)
tree386323de4f021d9601925504ff06520bd5048529 /tests/auto/widgets/widgets/qdatetimeedit
parentcb3e85fc9a4992ee2af4e4c2bfa9f76bcdf7955c (diff)
Apply Qt::ControlModifier to all spin box interactions
A step modifier already existed when scrolling with the Qt::ControlModifier held. This patch applies this functionality to other methods of stepping a spin box. Holding the modifier increases the step rate when: - scrolling; - pressing the up/down keys; - pressing the spin box up/down buttons. [ChangeLog][QtWidgets][QAbstractSpinBox] The Qt::ControlModifier increases the number of steps a QAbstractSpinBox takes for the following interactions: scrolling, up/down keyboard keys and the spin box buttons. Previously, Qt::ControlModifier only affected scrolling. Task-number: QTBUG-67380 Change-Id: Icc8754d5c007da0771bfaef113603a2f334dd494 Reviewed-by: Mitch Curtis <mitch.curtis@qt.io>
Diffstat (limited to 'tests/auto/widgets/widgets/qdatetimeedit')
-rw-r--r--tests/auto/widgets/widgets/qdatetimeedit/tst_qdatetimeedit.cpp496
1 files changed, 484 insertions, 12 deletions
diff --git a/tests/auto/widgets/widgets/qdatetimeedit/tst_qdatetimeedit.cpp b/tests/auto/widgets/widgets/qdatetimeedit/tst_qdatetimeedit.cpp
index fa28ec2575..0fe5b48341 100644
--- a/tests/auto/widgets/widgets/qdatetimeedit/tst_qdatetimeedit.cpp
+++ b/tests/auto/widgets/widgets/qdatetimeedit/tst_qdatetimeedit.cpp
@@ -70,6 +70,7 @@
#include <QSignalSpy>
#include <QTestEventList>
#include <QDateEdit>
+#include <QProxyStyle>
#include <private/qdatetimeedit_p.h>
@@ -93,6 +94,26 @@ public:
friend class tst_QDateTimeEdit;
};
+class PressAndHoldStyle : 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_ClickAutoRepeatRate:
+ return 5;
+ case QStyle::SH_SpinBox_ClickAutoRepeatThreshold:
+ return 10;
+ default:
+ return QProxyStyle::styleHint(hint, option, widget, returnData);
+ }
+ }
+};
+
class tst_QDateTimeEdit : public QObject
{
Q_OBJECT
@@ -205,9 +226,8 @@ private slots:
void reverseTest();
void ddMMMMyyyy();
-#if QT_CONFIG(wheelevent)
+ void wheelEvent_data();
void wheelEvent();
-#endif
void specialValueCornerCase();
void cursorPositionOnInit();
@@ -245,14 +265,99 @@ private slots:
void dateEditCorrectSectionSize_data();
void dateEditCorrectSectionSize();
#endif
+
+ void stepModifierKeys_data();
+ void stepModifierKeys();
+
+ void stepModifierButtons_data();
+ void stepModifierButtons();
+
+ void stepModifierPressAndHold_data();
+ void stepModifierPressAndHold();
private:
EditorDateEdit* testWidget;
QWidget *testFocusWidget;
};
+typedef QList<QDate> DateList;
typedef QList<QTime> TimeList;
typedef QList<Qt::Key> KeyList;
+static QLatin1String modifierToName(Qt::KeyboardModifier modifier)
+{
+ switch (modifier) {
+ case Qt::NoModifier:
+ return QLatin1Literal("No");
+ break;
+ case Qt::ControlModifier:
+ return QLatin1Literal("Ctrl");
+ break;
+ case Qt::ShiftModifier:
+ return QLatin1Literal("Shift");
+ break;
+ default:
+ qFatal("Unexpected keyboard modifier");
+ return QLatin1String();
+ }
+}
+
+static QLatin1String sectionToName(const QDateTimeEdit::Section section)
+{
+ switch (section) {
+ case QDateTimeEdit::SecondSection:
+ return QLatin1Literal("Second");
+ case QDateTimeEdit::MinuteSection:
+ return QLatin1Literal("Minute");
+ case QDateTimeEdit::HourSection:
+ return QLatin1Literal("Hours");
+ case QDateTimeEdit::DaySection:
+ return QLatin1Literal("Day");
+ case QDateTimeEdit::MonthSection:
+ return QLatin1Literal("Month");
+ case QDateTimeEdit::YearSection:
+ return QLatin1Literal("Year");
+ default:
+ qFatal("Unexpected section");
+ return QLatin1String();
+ }
+}
+
+static QDate stepDate(const QDate& startDate, const QDateTimeEdit::Section section,
+ const int steps)
+{
+ switch (section) {
+ case QDateTimeEdit::DaySection:
+ return startDate.addDays(steps);
+ case QDateTimeEdit::MonthSection:
+ return startDate.addMonths(steps);
+ case QDateTimeEdit::YearSection:
+ return startDate.addYears(steps);
+ default:
+ qFatal("Unexpected section");
+ return QDate();
+ }
+}
+
+static QTime stepTime(const QTime& startTime, const QDateTimeEdit::Section section,
+ const int steps)
+{
+ switch (section) {
+ case QDateTimeEdit::SecondSection:
+ return startTime.addSecs(steps);
+ case QDateTimeEdit::MinuteSection:
+ return QTime(startTime.hour(),
+ startTime.minute() + steps,
+ startTime.second());
+ case QDateTimeEdit::HourSection:
+ return QTime(startTime.hour() + steps,
+ startTime.minute(),
+ startTime.second());
+ default:
+ qFatal("Unexpected section");
+ return QTime();
+ }
+}
+
// Testing get/set functions
void tst_QDateTimeEdit::getSetCheck()
{
@@ -3000,20 +3105,154 @@ void tst_QDateTimeEdit::ddMMMMyyyy()
QCOMPARE(testWidget->lineEdit()->text(), "01." + QDate::longMonthName(1) + ".200");
}
+void tst_QDateTimeEdit::wheelEvent_data()
+{
#if QT_CONFIG(wheelevent)
+ QTest::addColumn<QPoint>("angleDelta");
+ QTest::addColumn<int>("qt4Delta");
+ QTest::addColumn<Qt::KeyboardModifiers>("modifiers");
+ QTest::addColumn<Qt::MouseEventSource>("source");
+ QTest::addColumn<QDateTimeEdit::Section>("section");
+ QTest::addColumn<QDate>("startDate");
+ QTest::addColumn<DateList>("expectedDates");
+
+ const auto fractions = {false, true};
+
+ const auto directions = {true, false};
+
+ const auto modifierList = {Qt::NoModifier,
+ Qt::ControlModifier,
+ Qt::ShiftModifier};
+
+ const auto sources = {Qt::MouseEventNotSynthesized,
+ Qt::MouseEventSynthesizedBySystem,
+ Qt::MouseEventSynthesizedByQt,
+ Qt::MouseEventSynthesizedByApplication};
+
+ const auto sections = {QDateTimeEdit::DaySection,
+ QDateTimeEdit::MonthSection,
+ QDateTimeEdit::YearSection};
+
+ for (auto fraction : fractions) {
+ for (auto up : directions) {
+
+ const QDate startDate(2000, up ? 2 : 12, 17);
+
+ const int units = (fraction ? 60 : 120) * (up ? 1 : -1);
+
+ for (auto modifier : modifierList) {
+
+ const Qt::KeyboardModifiers modifiers(modifier);
+
+ const auto modifierName = modifierToName(modifier);
+ if (modifierName.isEmpty())
+ continue;
+
+ const int steps = (modifier & Qt::ControlModifier ? 10 : 1)
+ * (up ? 1 : -1);
+
+ for (auto source : sources) {
+
+#ifdef Q_OS_MACOS
+ QPoint angleDelta;
+ if ((modifier & Qt::ShiftModifier) &&
+ source == Qt::MouseEventNotSynthesized) {
+ // On macOS the Shift modifier converts vertical
+ // mouse wheel events to horizontal.
+ angleDelta = { units, 0 };
+ } else {
+ // However, this is not the case for trackpad scroll
+ // events.
+ angleDelta = { 0, units };
+ }
+#else
+ const QPoint angleDelta(0, units);
+#endif
+
+ QLatin1String sourceName;
+ switch (source) {
+ case Qt::MouseEventNotSynthesized:
+ sourceName = QLatin1Literal("NotSynthesized");
+ break;
+ case Qt::MouseEventSynthesizedBySystem:
+ sourceName = QLatin1Literal("SynthesizedBySystem");
+ break;
+ case Qt::MouseEventSynthesizedByQt:
+ sourceName = QLatin1Literal("SynthesizedByQt");
+ break;
+ case Qt::MouseEventSynthesizedByApplication:
+ sourceName = QLatin1Literal("SynthesizedByApplication");
+ break;
+ default:
+ qFatal("Unexpected wheel event source");
+ continue;
+ }
+
+ for (const auto section : sections) {
+
+ DateList expectedDates;
+ if (fraction)
+ expectedDates << startDate;
+
+ const auto expectedDate = stepDate(startDate, section, steps);
+ if (!expectedDate.isValid())
+ continue;
+
+ expectedDates << expectedDate;
+
+ const QLatin1String sectionName = sectionToName(section);
+
+ QTest::addRow("%s%s%sWith%sKeyboardModifier%s",
+ fraction ? "half" : "full",
+ up ? "Up" : "Down",
+ sectionName.latin1(),
+ modifierName.latin1(),
+ sourceName.latin1())
+ << angleDelta
+ << units
+ << modifiers
+ << source
+ << section
+ << startDate
+ << expectedDates;
+ }
+ }
+ }
+ }
+ }
+#else
+ QSKIP("Built with --no-feature-wheelevent");
+#endif
+}
+
void tst_QDateTimeEdit::wheelEvent()
{
- testWidget->setDisplayFormat("dddd/MM");
- testWidget->setDate(QDate(2000, 2, 21));
- testWidget->setCurrentSection(QDateTimeEdit::DaySection);
- QWheelEvent w(testWidget->lineEdit()->geometry().center(), 120, 0, 0);
- qApp->sendEvent(testWidget, &w);
- QCOMPARE(testWidget->date(), QDate(2000, 2, 22));
- testWidget->setCurrentSection(QDateTimeEdit::MonthSection);
- qApp->sendEvent(testWidget, &w);
- QCOMPARE(testWidget->date(), QDate(2000, 3, 22));
-}
+#if QT_CONFIG(wheelevent)
+ QFETCH(QPoint, angleDelta);
+ QFETCH(int, qt4Delta);
+ QFETCH(Qt::KeyboardModifiers, modifiers);
+ QFETCH(Qt::MouseEventSource, source);
+ QFETCH(QDateTimeEdit::Section, section);
+ QFETCH(QDate, startDate);
+ QFETCH(DateList, expectedDates);
+
+ EditorDateEdit edit(0);
+ edit.setDate(startDate);
+ edit.setCurrentSection(section);
+
+ QWheelEvent event(QPointF(), QPointF(), QPoint(), angleDelta, qt4Delta,
+ Qt::Vertical, Qt::NoButton, modifiers, Qt::NoScrollPhase,
+ source);
+
+ QCOMPARE(edit.date(), startDate);
+ for (QDate expected : expectedDates) {
+ qApp->sendEvent(&edit, &event);
+ QCOMPARE(edit.date(), expected);
+ }
+#else
+ QSKIP("Built with --no-feature-wheelevent");
#endif // QT_CONFIG(wheelevent)
+}
void tst_QDateTimeEdit::specialValueCornerCase()
{
@@ -3735,5 +3974,238 @@ void tst_QDateTimeEdit::dateEditCorrectSectionSize()
}
#endif
+void tst_QDateTimeEdit::stepModifierKeys_data()
+{
+ QTest::addColumn<QDate>("startDate");
+ QTest::addColumn<QDateTimeEdit::Section>("section");
+ QTest::addColumn<QTestEventList>("keys");
+ QTest::addColumn<QDate>("expectedDate");
+
+ const auto keyList = {Qt::Key_Up, Qt::Key_Down};
+
+ const auto modifierList = {Qt::NoModifier,
+ Qt::ControlModifier,
+ Qt::ShiftModifier};
+
+ const auto sections = {QDateTimeEdit::DaySection,
+ QDateTimeEdit::MonthSection,
+ QDateTimeEdit::YearSection};
+
+ for (auto key : keyList) {
+
+ const bool up = key == Qt::Key_Up;
+ Q_ASSERT(up || key == Qt::Key_Down);
+
+ const QDate startDate(2000, up ? 2 : 12, 17);
+
+ for (auto modifier : modifierList) {
+
+ QTestEventList keys;
+ keys.addKeyClick(key, modifier);
+
+ const auto modifierName = modifierToName(modifier);
+ if (modifierName.isEmpty())
+ continue;
+
+ const int steps = (modifier & Qt::ControlModifier ? 10 : 1)
+ * (up ? 1 : -1);
+
+ for (const auto section : sections) {
+
+ const auto expectedDate = stepDate(startDate, section, steps);
+ if (!expectedDate.isValid())
+ continue;
+
+ const auto sectionName = sectionToName(section);
+
+ QTest::addRow("%s%sWith%sKeyboardModifier",
+ up ? "up" : "down",
+ sectionName.latin1(),
+ modifierName.latin1())
+ << startDate
+ << section
+ << keys
+ << expectedDate;
+ }
+ }
+ }
+}
+
+void tst_QDateTimeEdit::stepModifierKeys()
+{
+ QFETCH(QDate, startDate);
+ QFETCH(QDateTimeEdit::Section, section);
+ QFETCH(QTestEventList, keys);
+ QFETCH(QDate, expectedDate);
+
+ QDateTimeEdit edit(0);
+ edit.setDate(startDate);
+ edit.show();
+ QVERIFY(QTest::qWaitForWindowActive(&edit));
+ edit.setCurrentSection(section);
+
+ QCOMPARE(edit.date(), startDate);
+ keys.simulate(&edit);
+ QCOMPARE(edit.date(), expectedDate);
+}
+
+void tst_QDateTimeEdit::stepModifierButtons_data()
+{
+ QTest::addColumn<QStyle::SubControl>("subControl");
+ QTest::addColumn<Qt::KeyboardModifiers>("modifiers");
+ QTest::addColumn<QDateTimeEdit::Section>("section");
+ QTest::addColumn<QTime>("startTime");
+ QTest::addColumn<QTime>("expectedTime");
+
+ const auto subControls = {QStyle::SC_SpinBoxUp, QStyle::SC_SpinBoxDown};
+
+ const auto modifierList = {Qt::NoModifier,
+ Qt::ControlModifier,
+ Qt::ShiftModifier};
+
+ const auto sections = {QDateTimeEdit::SecondSection,
+ QDateTimeEdit::MinuteSection,
+ QDateTimeEdit::HourSection};
+
+ const QTime startTime(12, 36, 24);
+
+ for (auto subControl : subControls) {
+
+ const bool up = subControl == QStyle::SC_SpinBoxUp;
+ Q_ASSERT(up || subControl == QStyle::SC_SpinBoxDown);
+
+ for (auto modifier : modifierList) {
+
+ const Qt::KeyboardModifiers modifiers(modifier);
+
+ const auto modifierName = modifierToName(modifier);
+ if (modifierName.isEmpty())
+ continue;
+
+ const int steps = (modifier & Qt::ControlModifier ? 10 : 1)
+ * (up ? 1 : -1);
+
+ for (const auto section : sections) {
+
+ const auto expectedTime = stepTime(startTime, section, steps);
+ if (!expectedTime.isValid())
+ continue;
+
+ const auto sectionName = sectionToName(section);
+
+ QTest::addRow("%s%sWith%sKeyboardModifier",
+ up ? "up" : "down",
+ sectionName.latin1(),
+ modifierName.latin1())
+ << subControl
+ << modifiers
+ << section
+ << startTime
+ << expectedTime;
+ }
+ }
+ }
+}
+
+void tst_QDateTimeEdit::stepModifierButtons()
+{
+ QFETCH(QStyle::SubControl, subControl);
+ QFETCH(Qt::KeyboardModifiers, modifiers);
+ QFETCH(QDateTimeEdit::Section, section);
+ QFETCH(QTime, startTime);
+ QFETCH(QTime, expectedTime);
+
+ EditorDateEdit edit(0);
+ edit.setTime(startTime);
+ edit.show();
+ QVERIFY(QTest::qWaitForWindowActive(&edit));
+ edit.setCurrentSection(section);
+
+ QStyleOptionSpinBox spinBoxStyleOption;
+ edit.initStyleOption(&spinBoxStyleOption);
+
+ const QRect buttonRect = edit.style()->subControlRect(
+ QStyle::CC_SpinBox, &spinBoxStyleOption, subControl, &edit);
+
+ QCOMPARE(edit.time(), startTime);
+ QTest::mouseClick(&edit, Qt::LeftButton, modifiers, buttonRect.center());
+ QCOMPARE(edit.time(), expectedTime);
+}
+
+void tst_QDateTimeEdit::stepModifierPressAndHold_data()
+{
+ QTest::addColumn<QStyle::SubControl>("subControl");
+ QTest::addColumn<Qt::KeyboardModifiers>("modifiers");
+ QTest::addColumn<int>("expectedStepModifier");
+
+ const auto subControls = {QStyle::SC_SpinBoxUp, QStyle::SC_SpinBoxDown};
+
+ const auto modifierList = {Qt::NoModifier,
+ Qt::ControlModifier,
+ Qt::ShiftModifier};
+
+ for (auto subControl : subControls) {
+
+ const bool up = subControl == QStyle::SC_SpinBoxUp;
+ Q_ASSERT(up || subControl == QStyle::SC_SpinBoxDown);
+
+ for (auto modifier : modifierList) {
+
+ const Qt::KeyboardModifiers modifiers(modifier);
+
+ const auto modifierName = modifierToName(modifier);
+ if (modifierName.isEmpty())
+ continue;
+
+ const int steps = (modifier & Qt::ControlModifier ? 10 : 1)
+ * (up ? 1 : -1);
+
+ QTest::addRow("%sWith%sKeyboardModifier",
+ up ? "up" : "down",
+ modifierName.latin1())
+ << subControl
+ << modifiers
+ << steps;
+ }
+ }
+}
+
+void tst_QDateTimeEdit::stepModifierPressAndHold()
+{
+ QFETCH(QStyle::SubControl, subControl);
+ QFETCH(Qt::KeyboardModifiers, modifiers);
+ QFETCH(int, expectedStepModifier);
+
+ const QDate startDate(2000, 1, 1);
+
+ EditorDateEdit edit(0);
+ QScopedPointer<PressAndHoldStyle, QScopedPointerDeleteLater> pressAndHoldStyle(
+ new PressAndHoldStyle);
+ edit.setStyle(pressAndHoldStyle.data());
+ edit.setDate(startDate);
+
+ QSignalSpy spy(&edit, &EditorDateEdit::dateChanged);
+
+ edit.show();
+ QVERIFY(QTest::qWaitForWindowActive(&edit));
+ edit.setCurrentSection(QDateTimeEdit::YearSection);
+
+ QStyleOptionSpinBox spinBoxStyleOption;
+ edit.initStyleOption(&spinBoxStyleOption);
+
+ const QRect buttonRect = edit.style()->subControlRect(
+ QStyle::CC_SpinBox, &spinBoxStyleOption, subControl, &edit);
+
+ QTest::mousePress(&edit, Qt::LeftButton, modifiers, buttonRect.center());
+ QTRY_VERIFY(spy.length() >= 3);
+ QTest::mouseRelease(&edit, Qt::LeftButton, modifiers, buttonRect.center());
+
+ const auto value = spy.last().at(0);
+ QVERIFY(value.type() == QVariant::Date);
+ const QDate expectedDate = startDate.addYears(spy.length() *
+ expectedStepModifier);
+ QCOMPARE(value.toDate(), expectedDate);
+}
+
QTEST_MAIN(tst_QDateTimeEdit)
#include "tst_qdatetimeedit.moc"