Fix QDateEdit displaying day as a number for short and long day formats
[profile/ivi/qtbase.git] / src / corelib / tools / qdatetime_p.h
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the QtCore module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
16 **
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
20 **
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
28 **
29 ** Other Usage
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #ifndef QDATETIME_P_H
43 #define QDATETIME_P_H
44
45 //
46 //  W A R N I N G
47 //  -------------
48 //
49 // This file is not part of the Qt API.  It exists purely as an
50 // implementation detail.  This header file may change from version to
51 // version without notice, or even be removed.
52 //
53 // We mean it.
54 //
55
56 #include "qplatformdefs.h"
57 #include "QtCore/qatomic.h"
58 #include "QtCore/qdatetime.h"
59 #include "QtCore/qstringlist.h"
60 #include "QtCore/qlocale.h"
61 #ifndef QT_BOOTSTRAPPED
62 # include "QtCore/qvariant.h"
63 #endif
64 #include "QtCore/qvector.h"
65
66
67 #define QDATETIMEEDIT_TIME_MIN QTime(0, 0, 0, 0)
68 #define QDATETIMEEDIT_TIME_MAX QTime(23, 59, 59, 999)
69 #define QDATETIMEEDIT_DATE_MIN QDate(100, 1, 1)
70 #define QDATETIMEEDIT_COMPAT_DATE_MIN QDate(1752, 9, 14)
71 #define QDATETIMEEDIT_DATE_MAX QDate(7999, 12, 31)
72 #define QDATETIMEEDIT_DATETIME_MIN QDateTime(QDATETIMEEDIT_DATE_MIN, QDATETIMEEDIT_TIME_MIN)
73 #define QDATETIMEEDIT_COMPAT_DATETIME_MIN QDateTime(QDATETIMEEDIT_COMPAT_DATE_MIN, QDATETIMEEDIT_TIME_MIN)
74 #define QDATETIMEEDIT_DATETIME_MAX QDateTime(QDATETIMEEDIT_DATE_MAX, QDATETIMEEDIT_TIME_MAX)
75 #define QDATETIMEEDIT_DATE_INITIAL QDate(2000, 1, 1)
76
77 QT_BEGIN_NAMESPACE
78
79 class QDateTimePrivate : public QSharedData
80 {
81 public:
82     enum Spec { LocalUnknown = -1, LocalStandard = 0, LocalDST = 1, UTC = 2, OffsetFromUTC = 3};
83
84     QDateTimePrivate() : spec(LocalUnknown), utcOffset(0) {}
85     QDateTimePrivate(const QDateTimePrivate &other)
86         : QSharedData(other), date(other.date), time(other.time), spec(other.spec), utcOffset(other.utcOffset)
87     {}
88
89     QDate date;
90     QTime time;
91     Spec spec;
92     /*!
93       \internal
94       \since 4.4
95
96       The offset in seconds. Applies only when timeSpec() is OffsetFromUTC.
97      */
98     int utcOffset;
99
100     Spec getLocal(QDate &outDate, QTime &outTime) const;
101     void getUTC(QDate &outDate, QTime &outTime) const;
102     static QDateTime addMSecs(const QDateTime &dt, qint64 msecs);
103     static void addMSecs(QDate &utcDate, QTime &utcTime, qint64 msecs);
104 };
105
106 #ifndef QT_BOOTSTRAPPED
107
108 class Q_CORE_EXPORT QDateTimeParser
109 {
110 public:
111     enum Context {
112         FromString,
113         DateTimeEdit
114     };
115     QDateTimeParser(QVariant::Type t, Context ctx)
116         : currentSectionIndex(-1), display(0), cachedDay(-1), parserType(t),
117         fixday(false), spec(Qt::LocalTime), context(ctx)
118     {
119         defaultLocale = QLocale::system();
120         first.type = FirstSection;
121         first.pos = -1;
122         first.count = -1;
123         first.zeroesAdded = 0;
124         last.type = FirstSection;
125         last.pos = -1;
126         last.count = -1;
127         last.zeroesAdded = 0;
128         none.type = NoSection;
129         none.pos = -1;
130         none.count = -1;
131         none.zeroesAdded = 0;
132     }
133     virtual ~QDateTimeParser() {}
134     enum {
135         Neither = -1,
136         AM = 0,
137         PM = 1,
138         PossibleAM = 2,
139         PossiblePM = 3,
140         PossibleBoth = 4
141     };
142
143     enum Section {
144         NoSection = 0x00000,
145         AmPmSection = 0x00001,
146         MSecSection = 0x00002,
147         SecondSection = 0x00004,
148         MinuteSection = 0x00008,
149         Hour12Section   = 0x00010,
150         Hour24Section   = 0x00020,
151         TimeSectionMask = (AmPmSection|MSecSection|SecondSection|MinuteSection|Hour12Section|Hour24Section),
152         Internal = 0x10000,
153         DaySection = 0x00100,
154         MonthSection = 0x00200,
155         YearSection = 0x00400,
156         YearSection2Digits = 0x00800,
157         DayOfWeekSectionShort = 0x01000,
158         DayOfWeekSectionLong = 0x20000,
159         DateSectionMask = (DaySection|MonthSection|YearSection|YearSection2Digits|DayOfWeekSectionShort|DayOfWeekSectionLong),
160         FirstSection = 0x02000|Internal,
161         LastSection = 0x04000|Internal,
162         CalendarPopupSection = 0x08000|Internal,
163
164         NoSectionIndex = -1,
165         FirstSectionIndex = -2,
166         LastSectionIndex = -3,
167         CalendarPopupIndex = -4
168     }; // duplicated from qdatetimeedit.h
169     Q_DECLARE_FLAGS(Sections, Section)
170
171     struct SectionNode {
172         Section type;
173         mutable int pos;
174         int count;
175         int zeroesAdded;
176     };
177
178     enum State { // duplicated from QValidator
179         Invalid,
180         Intermediate,
181         Acceptable
182     };
183
184     struct StateNode {
185         StateNode() : state(Invalid), conflicts(false) {}
186         QString input;
187         State state;
188         bool conflicts;
189         QDateTime value;
190     };
191
192     enum AmPm {
193         AmText,
194         PmText
195     };
196
197     enum Case {
198         UpperCase,
199         LowerCase
200     };
201
202 #ifndef QT_NO_DATESTRING
203     StateNode parse(QString &input, int &cursorPosition, const QDateTime &currentValue, bool fixup) const;
204 #endif
205     int sectionMaxSize(int index) const;
206     int sectionSize(int index) const;
207     int sectionMaxSize(Section s, int count) const;
208     int sectionPos(int index) const;
209     int sectionPos(const SectionNode &sn) const;
210
211     const SectionNode &sectionNode(int index) const;
212     Section sectionType(int index) const;
213     QString sectionText(int sectionIndex) const;
214     QString sectionText(const QString &text, int sectionIndex, int index) const;
215     int getDigit(const QDateTime &dt, int index) const;
216     bool setDigit(QDateTime &t, int index, int newval) const;
217     int parseSection(const QDateTime &currentValue, int sectionIndex, QString &txt, int &cursorPosition,
218                      int index, QDateTimeParser::State &state, int *used = 0) const;
219     int absoluteMax(int index, const QDateTime &value = QDateTime()) const;
220     int absoluteMin(int index) const;
221     bool parseFormat(const QString &format);
222 #ifndef QT_NO_DATESTRING
223     bool fromString(const QString &text, QDate *date, QTime *time) const;
224 #endif
225
226 #ifndef QT_NO_TEXTDATE
227     int findMonth(const QString &str1, int monthstart, int sectionIndex,
228                   QString *monthName = 0, int *used = 0) const;
229     int findDay(const QString &str1, int intDaystart, int sectionIndex,
230                 QString *dayName = 0, int *used = 0) const;
231 #endif
232     int findAmPm(QString &str1, int index, int *used = 0) const;
233     int maxChange(int s) const;
234     bool potentialValue(const QString &str, int min, int max, int index,
235                         const QDateTime &currentValue, int insert) const;
236     bool skipToNextSection(int section, const QDateTime &current, const QString &sectionText) const;
237     QString sectionName(int s) const;
238     QString stateName(int s) const;
239
240     QString sectionFormat(int index) const;
241     QString sectionFormat(Section s, int count) const;
242
243     enum FieldInfoFlag {
244         Numeric = 0x01,
245         FixedWidth = 0x02,
246         AllowPartial = 0x04,
247         Fraction = 0x08
248     };
249     Q_DECLARE_FLAGS(FieldInfo, FieldInfoFlag)
250
251     FieldInfo fieldInfo(int index) const;
252
253     virtual QDateTime getMinimum() const;
254     virtual QDateTime getMaximum() const;
255     virtual int cursorPosition() const { return -1; }
256     virtual QString displayText() const { return text; }
257     virtual QString getAmPmText(AmPm ap, Case cs) const;
258     virtual QLocale locale() const { return defaultLocale; }
259
260     mutable int currentSectionIndex;
261     Sections display;
262     /*
263         This stores the stores the most recently selected day.
264         It is useful when considering the following scenario:
265
266         1. Date is: 31/01/2000
267         2. User increments month: 29/02/2000
268         3. User increments month: 31/03/2000
269
270         At step 1, cachedDay stores 31. At step 2, the 31 is invalid for February, so the cachedDay is not updated.
271         At step 3, the the month is changed to March, for which 31 is a valid day. Since 29 < 31, the day is set to cachedDay.
272         This is good for when users have selected their desired day and are scrolling up or down in the month or year section
273         and do not want smaller months (or non-leap years) to alter the day that they chose.
274     */
275     mutable int cachedDay;
276     mutable QString text;
277     QVector<SectionNode> sectionNodes;
278     SectionNode first, last, none, popup;
279     QStringList separators;
280     QString displayFormat;
281     QLocale defaultLocale;
282     QVariant::Type parserType;
283
284     bool fixday;
285
286     Qt::TimeSpec spec; // spec if used by QDateTimeEdit
287     Context context;
288 };
289
290 Q_CORE_EXPORT bool operator==(const QDateTimeParser::SectionNode &s1, const QDateTimeParser::SectionNode &s2);
291
292 Q_DECLARE_OPERATORS_FOR_FLAGS(QDateTimeParser::Sections)
293 Q_DECLARE_OPERATORS_FOR_FLAGS(QDateTimeParser::FieldInfo)
294
295 #endif // QT_BOOTSTRAPPED
296
297 QT_END_NAMESPACE
298
299 #endif // QDATETIME_P_H