Fix editing of QDateTimeEdit in 12-hour locales that don't use AM/PM
The code made two incorrect assumptions: that the strings used are "AM" or "PM", or would be translated. Instead, the locale provides the correct strings, and there is no need to translate. However, in order not to break existing translations, we give those preference. And that the AM/PM string is not longer than 4 characters, while in e.g Spanish/Columbia locale the strings are "A. M." and "P. M.", ie 5 characters long. Also, the use of qMin in a function that is asked to provide the maximum section length is wrong. [ChangeLog][QWidgets][QDateTimeEdit] Use the information provided by the locale to determine the AM/PM strings, unless they are already translated. Change-Id: I6d1b05376e5ac62fc58da2cdea2e6cb732ec6747 Fixes: QTBUG-72833 Reviewed-by: Andy Shaw <andy.shaw@qt.io> Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
This commit is contained in:
parent
11569f7071
commit
5aaade8c93
@ -622,11 +622,11 @@ int QDateTimeParser::sectionMaxSize(Section s, int count) const
|
||||
case LastSection: return 0;
|
||||
|
||||
case AmPmSection: {
|
||||
const int lowerMax = qMin(getAmPmText(AmText, LowerCase).size(),
|
||||
const int lowerMax = qMax(getAmPmText(AmText, LowerCase).size(),
|
||||
getAmPmText(PmText, LowerCase).size());
|
||||
const int upperMax = qMin(getAmPmText(AmText, UpperCase).size(),
|
||||
const int upperMax = qMax(getAmPmText(AmText, UpperCase).size(),
|
||||
getAmPmText(PmText, UpperCase).size());
|
||||
return qMin(4, qMin(lowerMax, upperMax));
|
||||
return qMax(lowerMax, upperMax);
|
||||
}
|
||||
|
||||
case Hour24Section:
|
||||
@ -1665,13 +1665,16 @@ QDateTimeParser::findTimeZone(QStringRef str, const QDateTime &when,
|
||||
/*!
|
||||
\internal
|
||||
|
||||
Returns
|
||||
AM if str == tr("AM")
|
||||
PM if str == tr("PM")
|
||||
PossibleAM if str can become tr("AM")
|
||||
PossiblePM if str can become tr("PM")
|
||||
PossibleBoth if str can become tr("PM") and can become tr("AM")
|
||||
Neither if str can't become anything sensible
|
||||
Compares str to the am/pm texts returned by getAmPmText().
|
||||
Returns AM or PM if str is one of those texts. Failing that, it looks to see
|
||||
whether, ignoring spaces and case, each character of str appears in one of
|
||||
the am/pm texts.
|
||||
If neither text can be the result of the user typing more into str, returns
|
||||
Neither. If both texts are possible results of further typing, returns
|
||||
PossibleBoth. Otherwise, only one of them is a possible completion, so this
|
||||
returns PossibleAM or PossiblePM to indicate which.
|
||||
|
||||
\sa getAmPmText()
|
||||
*/
|
||||
QDateTimeParser::AmPmFinder QDateTimeParser::findAmPm(QString &str, int sectionIndex, int *used) const
|
||||
{
|
||||
@ -1700,10 +1703,10 @@ QDateTimeParser::AmPmFinder QDateTimeParser::findAmPm(QString &str, int sectionI
|
||||
|
||||
QDTPDEBUG << "findAmPm" << str << ampm[0] << ampm[1];
|
||||
|
||||
if (str.indexOf(ampm[amindex], 0, Qt::CaseInsensitive) == 0) {
|
||||
if (str.startsWith(ampm[amindex], Qt::CaseInsensitive)) {
|
||||
str = ampm[amindex];
|
||||
return AM;
|
||||
} else if (str.indexOf(ampm[pmindex], 0, Qt::CaseInsensitive) == 0) {
|
||||
} else if (str.startsWith(ampm[pmindex], Qt::CaseInsensitive)) {
|
||||
str = ampm[pmindex];
|
||||
return PM;
|
||||
} else if (context == FromString || (str.count(space) == 0 && str.size() >= size)) {
|
||||
|
@ -2307,13 +2307,31 @@ void QDateTimeEdit::paintEvent(QPaintEvent *event)
|
||||
style()->drawComplexControl(QStyle::CC_ComboBox, &optCombo, &p, this);
|
||||
}
|
||||
|
||||
/*
|
||||
Returns the string for AM and PM markers.
|
||||
|
||||
If a translation for "AM" and "PM" is installed, then use that.
|
||||
Otherwise, use the default implementation, which uses the locale.
|
||||
*/
|
||||
QString QDateTimeEditPrivate::getAmPmText(AmPm ap, Case cs) const
|
||||
{
|
||||
QString original;
|
||||
QString translated;
|
||||
if (ap == AmText) {
|
||||
return (cs == UpperCase ? QDateTimeParser::tr("AM") : QDateTimeParser::tr("am"));
|
||||
original = QLatin1String(cs == UpperCase ? "AM" : "am");
|
||||
translated = (cs == UpperCase ? QDateTimeParser::tr("AM") : QDateTimeParser::tr("am"));
|
||||
} else {
|
||||
return (cs == UpperCase ? QDateTimeParser::tr("PM") : QDateTimeParser::tr("pm"));
|
||||
original = QLatin1String(cs == UpperCase ? "PM" : "pm");
|
||||
translated = (cs == UpperCase ? QDateTimeParser::tr("PM") : QDateTimeParser::tr("pm"));
|
||||
}
|
||||
|
||||
// This logic fails if a translation exists but doesn't change the string,
|
||||
// which we can accept as a corner-case for which a locale-derived answer
|
||||
// will be acceptable.
|
||||
if (original != translated)
|
||||
return translated;
|
||||
|
||||
return QDateTimeParser::getAmPmText(ap, cs);
|
||||
}
|
||||
|
||||
int QDateTimeEditPrivate::absoluteIndex(QDateTimeEdit::Section s, int index) const
|
||||
|
@ -2490,17 +2490,20 @@ void tst_QDateTime::fromString_LOCALE_ILDATE()
|
||||
|
||||
void tst_QDateTime::fromStringToStringLocale_data()
|
||||
{
|
||||
QTest::addColumn<QLocale>("locale");
|
||||
QTest::addColumn<QDateTime>("dateTime");
|
||||
|
||||
QTest::newRow("data0") << QDateTime(QDate(1999, 1, 18), QTime(11, 49, 00));
|
||||
QTest::newRow("frFR") << QLocale(QLocale::French, QLocale::France) << QDateTime(QDate(1999, 1, 18), QTime(11, 49, 00));
|
||||
QTest::newRow("spCO") << QLocale(QLocale::Spanish, QLocale::Colombia) << QDateTime(QDate(1999, 1, 18), QTime(11, 49, 00));
|
||||
}
|
||||
|
||||
void tst_QDateTime::fromStringToStringLocale()
|
||||
{
|
||||
QFETCH(QLocale, locale);
|
||||
QFETCH(QDateTime, dateTime);
|
||||
|
||||
QLocale def;
|
||||
QLocale::setDefault(QLocale(QLocale::French, QLocale::France));
|
||||
QLocale::setDefault(locale);
|
||||
#define ROUNDTRIP(format) \
|
||||
QCOMPARE(QDateTime::fromString(dateTime.toString(format), format), dateTime)
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user