Add a QDateTimeEdit::timeZone property

This shall ultimately replace its timeSpec property, which had already
been turned into a derived property of an internal timezone.

[ChangeLog][QWidget][QDateTimeEdit] Added timeZone property to enable
a datetime edit widget to control the timezone used. This makes the
timeSpec property redundant; this old property shall be deprecated
from 6.10.

Fixes: QTBUG-80417
Change-Id: I3cdb686bd2dada0e5067f5b4c1828b73892e424a
Reviewed-by: Axel Spoerl <axel.spoerl@qt.io>
This commit is contained in:
Edward Welbourne 2023-09-08 17:14:15 +02:00
parent b7e0f45a85
commit 51cfc973b3
3 changed files with 74 additions and 31 deletions

View File

@ -219,7 +219,7 @@ QDateTimeEdit::~QDateTimeEdit()
widget's date-range to start and end on the date of the new value of this
property.
\sa date, time, minimumDateTime, maximumDateTime
\sa date, time, minimumDateTime, maximumDateTime, timeZone
*/
QDateTime QDateTimeEdit::dateTime() const
@ -984,10 +984,16 @@ void QDateTimeEdit::setCalendarPopup(bool enable)
update();
}
#if QT_DEPRECATED_SINCE(6, 10)
/*!
\property QDateTimeEdit::timeSpec
\brief The current timespec used by the date time edit.
\since 4.4
\deprecated[6.10] Use QDateTimeEdit::timeZone instead.
\brief The current timespec used by the date time edit.
Since Qt 6.7 this is an indirect accessor for the timeZone property.
\sa QDateTimeEdit::timeZone
*/
Qt::TimeSpec QDateTimeEdit::timeSpec() const
@ -1002,17 +1008,45 @@ void QDateTimeEdit::setTimeSpec(Qt::TimeSpec spec)
if (spec != d->timeZone.timeSpec()) {
switch (spec) {
case Qt::UTC:
d->timeZone = QTimeZone::UTC;
setTimeZone(QTimeZone::UTC);
break;
case Qt::LocalTime:
d->timeZone = QTimeZone::LocalTime;
setTimeZone(QTimeZone::LocalTime);
break;
default:
qWarning() << "Ignoring attempt to set time-spec" << spec
<< "which is not yet supported by QDateTimeEdit";
// TODO: fix that QTBUG-80417.
<< "which needs ancillary data: see setTimeZone()";
return;
}
}
}
#endif // 6.10 deprecation
// TODO: enable user input to control timeZone, when the format includes it.
/*!
\property QDateTimeEdit::timeZone
\since 6.7
\brief The current timezone used by the datetime editing widget
If the datetime format in use includes a timezone indicator - that is, a
\c{t}, \c{tt}, \c{ttt} or \c{tttt} format specifier - the user's input is
re-expressed in this timezone whenever it is parsed, overriding any timezone
the user may have specified.
\sa QDateTimeEdit::displayFormat
*/
QTimeZone QDateTimeEdit::timeZone() const
{
Q_D(const QDateTimeEdit);
return d->timeZone;
}
void QDateTimeEdit::setTimeZone(const QTimeZone &zone)
{
Q_D(QDateTimeEdit);
if (zone != d->timeZone) {
d->timeZone = zone;
d->updateTimeZone();
}
}
@ -1421,8 +1455,6 @@ QDateTime QDateTimeEdit::dateTimeFromText(const QString &text) const
QString copy = text;
int pos = d->edit->cursorPosition();
QValidator::State state = QValidator::Acceptable;
// TODO: if the format specifies time-zone, d->timeZone should change as
// determined by the parsed text.
return d->validateAndInterpret(copy, pos, state);
}
@ -2004,6 +2036,8 @@ QDateTime QDateTimeEditPrivate::validateAndInterpret(QString &input, int &positi
StateNode tmp = parse(input, position, value.toDateTime(), fixup);
// Take note of any corrections imposed during parsing:
input = m_text;
// TODO: if the format specifies time-zone, update timeZone to match the
// parsed text; but we're in const context, so can't - QTBUG-118393.
// Impose this widget's time system:
tmp.value = tmp.value.toTimeZone(timeZone);
// ... but that might turn a valid datetime into an invalid one:

View File

@ -5,7 +5,7 @@
#define QDATETIMEEDIT_H
#include <QtWidgets/qtwidgetsglobal.h>
#include <QtCore/qdatetime.h>
#include <QtCore/qtimezone.h>
#include <QtCore/qcalendar.h>
#include <QtCore/qvariant.h>
#include <QtWidgets/qabstractspinbox.h>
@ -39,7 +39,10 @@ class Q_WIDGETS_EXPORT QDateTimeEdit : public QAbstractSpinBox
Q_PROPERTY(bool calendarPopup READ calendarPopup WRITE setCalendarPopup)
Q_PROPERTY(int currentSectionIndex READ currentSectionIndex WRITE setCurrentSectionIndex)
Q_PROPERTY(int sectionCount READ sectionCount)
#if QT_DEPRECATED_SINCE(6, 10)
Q_PROPERTY(Qt::TimeSpec timeSpec READ timeSpec WRITE setTimeSpec)
#endif
Q_PROPERTY(QTimeZone timeZone READ timeZone WRITE setTimeZone)
public:
enum Section { // a sub-type of QDateTimeParser's like-named enum.
NoSection = 0x0000,
@ -125,8 +128,14 @@ public:
bool calendarPopup() const;
void setCalendarPopup(bool enable);
#if QT_DEPRECATED_SINCE(6, 10)
QT_DEPRECATED_VERSION_X_6_10("Use timeZone() instead")
Qt::TimeSpec timeSpec() const;
QT_DEPRECATED_VERSION_X_6_10("Use setTimeZone() instead")
void setTimeSpec(Qt::TimeSpec spec);
#endif
QTimeZone timeZone() const;
void setTimeZone(const QTimeZone &zone);
QSize sizeHint() const override;

View File

@ -233,10 +233,12 @@ private slots:
void nextPrevSection();
void dateEditTimeEditFormats();
#if QT_DEPRECATED_SINCE(6, 10)
void timeSpec_data();
void timeSpec();
void timeSpecBug();
void timeSpecInit();
#endif
void timeZoneBug();
void timeZoneInit();
void setDateTime_data();
void setDateTime();
@ -252,7 +254,7 @@ private slots:
void task196924();
void focusNextPrevChild();
void taskQTBUG_12384_timeSpecShowTimeOnly();
void taskQTBUG_12384_timeZoneShowTimeOnly();
void deleteCalendarWidget();
@ -436,7 +438,7 @@ void tst_QDateTimeEdit::cleanup()
{
testWidget->clearMinimumDateTime();
testWidget->clearMaximumDateTime();
testWidget->setTimeSpec(Qt::LocalTime);
testWidget->setTimeZone(QTimeZone::LocalTime);
testWidget->setSpecialValueText(QString());
testWidget->setWrapping(false);
// Restore the default.
@ -3491,6 +3493,7 @@ void tst_QDateTimeEdit::dateEditTimeEditFormats()
QCOMPARE(d.displayedSections(), QDateTimeEdit::YearSection);
}
#if QT_DEPRECATED_SINCE(6, 10)
void tst_QDateTimeEdit::timeSpec_data()
{
QTest::addColumn<bool>("useSetProperty");
@ -3538,10 +3541,11 @@ void tst_QDateTimeEdit::timeSpec()
QSKIP("Not tested in the GMT timezone");
}
}
#endif // test deprecated timeSpec property
void tst_QDateTimeEdit::timeSpecBug()
void tst_QDateTimeEdit::timeZoneBug()
{
testWidget->setTimeSpec(Qt::UTC);
testWidget->setTimeZone(QTimeZone::UTC);
testWidget->setDisplayFormat("hh:mm");
testWidget->setTime(QTime(2, 2));
const QString oldText = testWidget->text();
@ -3551,7 +3555,7 @@ void tst_QDateTimeEdit::timeSpecBug()
QCOMPARE(oldText, testWidget->text());
}
void tst_QDateTimeEdit::timeSpecInit()
void tst_QDateTimeEdit::timeZoneInit()
{
QDateTime utc(QDate(2000, 1, 1), QTime(12, 0), QTimeZone::UTC);
QDateTimeEdit widget(utc);
@ -3560,28 +3564,24 @@ void tst_QDateTimeEdit::timeSpecInit()
void tst_QDateTimeEdit::setDateTime_data()
{
QDateTime localNoon(QDate(2019, 12, 24), QTime(12, 0));
// TODO QTBUG-80417: port away from spec, to use QTimeZone instead.
QTest::addColumn<Qt::TimeSpec>("spec");
const QDateTime localNoon(QDate(2019, 12, 24), QTime(12, 0));
const QTimeZone UTC(QTimeZone::UTC), local(QTimeZone::LocalTime);
QTest::addColumn<QTimeZone>("zone");
QTest::addColumn<QDateTime>("store");
QTest::addColumn<QDateTime>("expect");
QTest::newRow("LocalTime/LocalTime")
<< Qt::LocalTime << localNoon << localNoon;
QTest::newRow("LocalTime/UTC")
<< Qt::LocalTime << localNoon.toUTC() << localNoon;
QTest::newRow("UTC/LocalTime")
<< Qt::UTC << localNoon << localNoon.toUTC();
QTest::newRow("UTC/UTC")
<< Qt::UTC << localNoon.toUTC() << localNoon.toUTC();
QTest::newRow("LocalTime/LocalTime") << local << localNoon << localNoon;
QTest::newRow("LocalTime/UTC") << local << localNoon.toUTC() << localNoon;
QTest::newRow("UTC/LocalTime") << UTC << localNoon << localNoon.toUTC();
QTest::newRow("UTC/UTC") << UTC << localNoon.toUTC() << localNoon.toUTC();
}
void tst_QDateTimeEdit::setDateTime()
{
QFETCH(const Qt::TimeSpec, spec);
QFETCH(const QTimeZone, zone);
QFETCH(const QDateTime, store);
QFETCH(const QDateTime, expect);
QDateTimeEdit editor;
editor.setTimeSpec(spec);
editor.setTimeZone(zone);
editor.setDateTime(store);
QCOMPARE(editor.dateTime(), expect);
}
@ -3775,14 +3775,14 @@ void tst_QDateTimeEdit::focusNextPrevChild()
QCOMPARE(edit.currentSection(), QDateTimeEdit::MonthSection);
}
void tst_QDateTimeEdit::taskQTBUG_12384_timeSpecShowTimeOnly()
void tst_QDateTimeEdit::taskQTBUG_12384_timeZoneShowTimeOnly()
{
QDateTime time = QDateTime::fromString("20100723 04:02:40", "yyyyMMdd hh:mm:ss");
time.setTimeZone(QTimeZone::UTC);
EditorDateEdit edit;
edit.setDisplayFormat("hh:mm:ss");
edit.setTimeSpec(Qt::UTC);
edit.setTimeZone(QTimeZone::UTC);
edit.setDateTime(time);
QCOMPARE(edit.minimumTime(), QTime(0, 0, 0, 0));