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 ¤tValue, 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 ¤tValue, int insert) const; 0217 bool potentialValue(const QString &str, int min, int max, int index, 0218 const QDateTime ¤tValue, 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 ¤tValue, int insert) const; 0225 bool potentialValue(const QString &str, int min, int max, int index, 0226 const QDateTime ¤tValue, 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 §ionNode(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 ¤t, const QStringRef §ionText) const; 0249 bool skipToNextSection(int section, const QDateTime ¤t, const QString §ionText) const 0250 { 0251 return skipToNextSection(section, current, QStringRef(§ionText)); 0252 } 0253 #else 0254 bool skipToNextSection(int section, const QDateTime ¤t, const QStringView §ionText) const; 0255 bool skipToNextSection(int section, const QDateTime ¤t, const QString §ionText) 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