File indexing completed on 2024-05-12 16:14:34

0001 /****************************************************************************
0002 **
0003 ** SPDX-FileCopyrightText: 2016 The Qt Company Ltd.
0004 ** Contact: https://www.qt.io/licensing/
0005 **
0006 ** This file is part of the QtCore module of the Qt Toolkit.
0007 **
0008 ** SPDX-License-Identifier: LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KFQF-Accepted-GPL OR LicenseRef-Qt-Commercial
0009 **
0010 ****************************************************************************/
0011 
0012 #ifndef QDATETIMEPARSER_P_H
0013 #define QDATETIMEPARSER_P_H
0014 
0015 //
0016 //  W A R N I N G
0017 //  -------------
0018 //
0019 // This file is not part of the Qt API.  It exists purely as an
0020 // implementation detail.  This header file may change from version to
0021 // version without notice, or even be removed.
0022 //
0023 // We mean it.
0024 //
0025 
0026 #include <QtGlobal>
0027 // #include "qplatformdefs.h"
0028 #include <QDateTime>
0029 #include <QStringList>
0030 #include <QLocale>
0031 #include <QVariant>
0032 #include <QVector>
0033 #include <QCoreApplication>
0034 
0035 #define QDATETIMEEDIT_TIME_MIN QTime(0, 0, 0, 0)
0036 #define QDATETIMEEDIT_TIME_MAX QTime(23, 59, 59, 999)
0037 #define QDATETIMEEDIT_DATE_MIN QDate(100, 1, 1)
0038 #define QDATETIMEEDIT_COMPAT_DATE_MIN QDate(1752, 9, 14)
0039 #define QDATETIMEEDIT_DATE_MAX QDate(9999, 12, 31)
0040 #define QDATETIMEEDIT_DATETIME_MIN QDateTime(QDATETIMEEDIT_DATE_MIN, QDATETIMEEDIT_TIME_MIN)
0041 #define QDATETIMEEDIT_COMPAT_DATETIME_MIN QDateTime(QDATETIMEEDIT_COMPAT_DATE_MIN, QDATETIMEEDIT_TIME_MIN)
0042 #define QDATETIMEEDIT_DATETIME_MAX QDateTime(QDATETIMEEDIT_DATE_MAX, QDATETIMEEDIT_TIME_MAX)
0043 #define QDATETIMEEDIT_DATE_INITIAL QDate(2000, 1, 1)
0044 
0045 class QDateTimeParser
0046 {
0047     Q_DECLARE_TR_FUNCTIONS(QDateTimeParser)
0048 public:
0049     enum Context {
0050         FromString,
0051         DateTimeEdit
0052     };
0053     QDateTimeParser(QMetaType::Type t, Context ctx)
0054         : currentSectionIndex(-1), display(NoSection), cachedDay(-1), parserType(t),
0055         fixday(false), spec(Qt::LocalTime), context(ctx)
0056     {
0057         defaultLocale = QLocale::system();
0058         first.type = FirstSection;
0059         first.pos = -1;
0060         first.count = -1;
0061         first.zeroesAdded = 0;
0062         last.type = LastSection;
0063         last.pos = -1;
0064         last.count = -1;
0065         last.zeroesAdded = 0;
0066         none.type = NoSection;
0067         none.pos = -1;
0068         none.count = -1;
0069         none.zeroesAdded = 0;
0070     }
0071     virtual ~QDateTimeParser();
0072 
0073     enum Section {
0074         NoSection     = 0x00000,
0075         AmPmSection   = 0x00001,
0076         MSecSection   = 0x00002,
0077         SecondSection = 0x00004,
0078         MinuteSection = 0x00008,
0079         Hour12Section   = 0x00010,
0080         Hour24Section   = 0x00020,
0081         TimeZoneSection = 0x00040,
0082         HourSectionMask = (Hour12Section | Hour24Section),
0083         TimeSectionMask = (MSecSection | SecondSection | MinuteSection |
0084                            HourSectionMask | AmPmSection | TimeZoneSection),
0085 
0086         DaySection         = 0x00100,
0087         MonthSection       = 0x00200,
0088         YearSection        = 0x00400,
0089         YearSection2Digits = 0x00800,
0090         YearSectionMask = YearSection | YearSection2Digits,
0091         DayOfWeekSectionShort = 0x01000,
0092         DayOfWeekSectionLong  = 0x02000,
0093         DayOfWeekSectionMask = DayOfWeekSectionShort | DayOfWeekSectionLong,
0094         DaySectionMask = DaySection | DayOfWeekSectionMask,
0095         DateSectionMask = DaySectionMask | MonthSection | YearSectionMask,
0096 
0097         Internal             = 0x10000,
0098         FirstSection         = 0x20000 | Internal,
0099         LastSection          = 0x40000 | Internal,
0100         CalendarPopupSection = 0x80000 | Internal,
0101 
0102         NoSectionIndex = -1,
0103         FirstSectionIndex = -2,
0104         LastSectionIndex = -3,
0105         CalendarPopupIndex = -4
0106     }; // extending qdatetimeedit.h's equivalent
0107     Q_DECLARE_FLAGS(Sections, Section)
0108 
0109     struct Q_CORE_EXPORT SectionNode {
0110         Section type;
0111         mutable int pos;
0112         int count;
0113         int zeroesAdded;
0114 
0115         static QString name(Section s);
0116         QString name() const { return name(type); }
0117         QString format() const;
0118         int maxChange() const;
0119     };
0120 
0121     enum State { // duplicated from QValidator
0122         Invalid,
0123         Intermediate,
0124         Acceptable
0125     };
0126 
0127     struct StateNode {
0128         StateNode() : state(Invalid), padded(0), conflicts(false) {}
0129         StateNode(const QDateTime &val, State ok=Acceptable, int pad=0, bool bad=false)
0130             : value(val), state(ok), padded(pad), conflicts(bad) {}
0131         QString input;
0132         QDateTime value;
0133         State state;
0134         int padded;
0135         bool conflicts;
0136     };
0137 
0138     enum AmPm {
0139         AmText,
0140         PmText
0141     };
0142 
0143     enum Case {
0144         UpperCase,
0145         LowerCase
0146     };
0147 
0148 #if QT_CONFIG(datestring)
0149     StateNode parse(QString input, int position, const QDateTime &defaultValue, bool fixup) const;
0150     bool fromString(const QString &text, QDate *date, QTime *time) const;
0151 #endif
0152     bool parseFormat(const QString &format);
0153 
0154     enum FieldInfoFlag {
0155         Numeric = 0x01,
0156         FixedWidth = 0x02,
0157         AllowPartial = 0x04,
0158         Fraction = 0x08
0159     };
0160     Q_DECLARE_FLAGS(FieldInfo, FieldInfoFlag)
0161 
0162     FieldInfo fieldInfo(int index) const;
0163 
0164     void setDefaultLocale(const QLocale &loc) { defaultLocale = loc; }
0165     virtual QString displayText() const { return text; }
0166 
0167 private:
0168     int sectionMaxSize(Section s, int count) const;
0169     QString sectionText(const QString &text, int sectionIndex, int index) const;
0170 #if QT_CONFIG(datestring)
0171     StateNode scanString(const QDateTime &defaultValue,
0172                          bool fixup, QString *input) const;
0173     struct ParsedSection {
0174         int value;
0175         int used;
0176         int zeroes;
0177         State state;
0178         Q_DECL_CONSTEXPR ParsedSection(State ok = Invalid,
0179                                        int val = 0, int read = 0, int zs = 0)
0180             : value(ok == Invalid ? -1 : val), used(read), zeroes(zs), state(ok)
0181             {}
0182     };
0183     ParsedSection parseSection(const QDateTime &currentValue, int sectionIndex,
0184                                int offset, QString *text) const;
0185     int findMonth(const QString &str1, int monthstart, int sectionIndex,
0186                   QString *monthName = nullptr, int *used = nullptr) const;
0187     int findDay(const QString &str1, int intDaystart, int sectionIndex,
0188                 QString *dayName = nullptr, int *used = nullptr) const;
0189 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
0190     ParsedSection findTimeZone(QStringRef str, const QDateTime &when,
0191                                int maxVal, int minVal) const;
0192 #else
0193     ParsedSection findTimeZone(QStringView str, const QDateTime &when,
0194                                int maxVal, int minVal) const;
0195 #endif
0196 #if QT_CONFIG(timezone)
0197 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
0198     static int startsWithLocalTimeZone(const QStringRef name);
0199 #else
0200     static int startsWithLocalTimeZone(const QStringView name, const QDateTime &when);
0201 #endif
0202 #endif
0203 
0204     enum AmPmFinder {
0205         Neither = -1,
0206         AM = 0,
0207         PM = 1,
0208         PossibleAM = 2,
0209         PossiblePM = 3,
0210         PossibleBoth = 4
0211     };
0212     AmPmFinder findAmPm(QString &str, int index, int *used = nullptr) const;
0213 #endif // datestring
0214 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
0215     bool potentialValue(const QStringRef &str, int min, int max, int index,
0216                         const QDateTime &currentValue, int insert) const;
0217     bool potentialValue(const QString &str, int min, int max, int index,
0218                         const QDateTime &currentValue, int insert) const
0219     {
0220         return potentialValue(QStringRef(&str), min, max, index, currentValue, insert);
0221     }
0222 #else
0223     bool potentialValue(const QStringView &str, int min, int max, int index,
0224                         const QDateTime &currentValue, int insert) const;
0225     bool potentialValue(const QString &str, int min, int max, int index,
0226                         const QDateTime &currentValue, int insert) const
0227     {
0228         return potentialValue(QStringView(str), min, max, index, currentValue, insert);
0229     }
0230 
0231 #endif
0232 
0233 protected: // for the benefit of QDateTimeEditPrivate
0234     int sectionSize(int index) const;
0235     int sectionMaxSize(int index) const;
0236     int sectionPos(int index) const;
0237     int sectionPos(const SectionNode &sn) const;
0238 
0239     const SectionNode &sectionNode(int index) const;
0240     Section sectionType(int index) const;
0241     QString sectionText(int sectionIndex) const;
0242     int getDigit(const QDateTime &dt, int index) const;
0243     bool setDigit(QDateTime &t, int index, int newval) const;
0244 
0245     int absoluteMax(int index, const QDateTime &value = QDateTime()) const;
0246     int absoluteMin(int index) const;
0247 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
0248     bool skipToNextSection(int section, const QDateTime &current, const QStringRef &sectionText) const;
0249     bool skipToNextSection(int section, const QDateTime &current, const QString &sectionText) const
0250     {
0251         return skipToNextSection(section, current, QStringRef(&sectionText));
0252     }
0253 #else
0254     bool skipToNextSection(int section, const QDateTime &current, const QStringView &sectionText) const;
0255     bool skipToNextSection(int section, const QDateTime &current, const QString &sectionText) const
0256     {
0257         return skipToNextSection(section, current, QStringView(sectionText));
0258     }
0259 
0260 #endif
0261     QString stateName(State s) const;
0262     virtual QDateTime getMinimum() const;
0263     virtual QDateTime getMaximum() const;
0264     virtual int cursorPosition() const { return -1; }
0265     virtual QString getAmPmText(AmPm ap, Case cs) const;
0266     virtual QLocale locale() const { return defaultLocale; }
0267 
0268     mutable int currentSectionIndex;
0269     Sections display;
0270     /*
0271         This stores the most recently selected day.
0272         It is useful when considering the following scenario:
0273 
0274         1. Date is: 31/01/2000
0275         2. User increments month: 29/02/2000
0276         3. User increments month: 31/03/2000
0277 
0278         At step 1, cachedDay stores 31. At step 2, the 31 is invalid for February, so the cachedDay is not updated.
0279         At step 3, the month is changed to March, for which 31 is a valid day. Since 29 < 31, the day is set to cachedDay.
0280         This is good for when users have selected their desired day and are scrolling up or down in the month or year section
0281         and do not want smaller months (or non-leap years) to alter the day that they chose.
0282     */
0283     mutable int cachedDay;
0284     mutable QString text;
0285     QVector<SectionNode> sectionNodes;
0286     SectionNode first, last, none, popup;
0287     QStringList separators;
0288     QString displayFormat;
0289     QLocale defaultLocale;
0290     QMetaType::Type parserType;
0291     bool fixday;
0292     Qt::TimeSpec spec; // spec if used by QDateTimeEdit
0293     Context context;
0294 };
0295 Q_DECLARE_TYPEINFO(QDateTimeParser::SectionNode, Q_PRIMITIVE_TYPE);
0296 
0297 Q_CORE_EXPORT bool operator==(const QDateTimeParser::SectionNode &s1, const QDateTimeParser::SectionNode &s2);
0298 
0299 Q_DECLARE_OPERATORS_FOR_FLAGS(QDateTimeParser::Sections)
0300 Q_DECLARE_OPERATORS_FOR_FLAGS(QDateTimeParser::FieldInfo)
0301 
0302 QT_END_NAMESPACE
0303 
0304 #endif // QDATETIME_P_H