src/gui/widgets/qdatetimeedit.cpp
changeset 0 1918ee327afb
child 4 3b1da2848fc7
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the QtGui module of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include <math.h>
       
    43 #include <private/qdatetimeedit_p.h>
       
    44 #include <qabstractspinbox.h>
       
    45 #include <qapplication.h>
       
    46 #include <qdatetimeedit.h>
       
    47 #include <qdesktopwidget.h>
       
    48 #include <qdebug.h>
       
    49 #include <qevent.h>
       
    50 #include <qlineedit.h>
       
    51 #include <private/qlineedit_p.h>
       
    52 #include <qlocale.h>
       
    53 #include <qpainter.h>
       
    54 #include <qlayout.h>
       
    55 #include <qset.h>
       
    56 #include <qstyle.h>
       
    57 
       
    58 #ifndef QT_NO_DATETIMEEDIT
       
    59 
       
    60 //#define QDATETIMEEDIT_QDTEDEBUG
       
    61 #ifdef QDATETIMEEDIT_QDTEDEBUG
       
    62 #  define QDTEDEBUG qDebug() << QString::fromLatin1("%1:%2").arg(__FILE__).arg(__LINE__)
       
    63 #  define QDTEDEBUGN qDebug
       
    64 #else
       
    65 #  define QDTEDEBUG if (false) qDebug()
       
    66 #  define QDTEDEBUGN if (false) qDebug
       
    67 #endif
       
    68 
       
    69 QT_BEGIN_NAMESPACE
       
    70 
       
    71 // --- QDateTimeEdit ---
       
    72 
       
    73 /*!
       
    74   \class QDateTimeEdit
       
    75   \brief The QDateTimeEdit class provides a widget for editing dates and times.
       
    76 
       
    77   \ingroup basicwidgets
       
    78 
       
    79 
       
    80   QDateTimeEdit allows the user to edit dates by using the keyboard or
       
    81   the arrow keys to increase and decrease date and time values. The
       
    82   arrow keys can be used to move from section to section within the
       
    83   QDateTimeEdit box. Dates and times appear in accordance with the
       
    84   format set; see setDisplayFormat().
       
    85 
       
    86   \snippet doc/src/snippets/code/src_gui_widgets_qdatetimeedit.cpp 0
       
    87 
       
    88   Here we've created a new QDateTimeEdit object initialized with
       
    89   today's date, and restricted the valid date range to today plus or
       
    90   minus 365 days. We've set the order to month, day, year.
       
    91 
       
    92   The minimum value for QDateTimeEdit is 14 September 1752,
       
    93   and 2 January 4713BC for QDate. You can change this by calling
       
    94   setMinimumDate(), setMaximumDate(),  setMinimumTime(),
       
    95   and setMaximumTime().
       
    96 
       
    97   \section1 Using a Pop-up Calendar Widget
       
    98 
       
    99   QDateTimeEdit can be configured to allow a QCalendarWidget to be used
       
   100   to select dates. This is enabled by setting the calendarPopup property.
       
   101   Additionally, you can supply a custom calendar widget for use as the
       
   102   calendar pop-up by calling the setCalendarWidget() function. The existing
       
   103   calendar widget can be retrieved with calendarWidget().
       
   104 
       
   105   \table 100%
       
   106   \row \o \inlineimage windowsxp-datetimeedit.png Screenshot of a Windows XP style date time editing widget
       
   107        \o A date time editing widget shown in the \l{Windows XP Style Widget Gallery}{Windows XP widget style}.
       
   108   \row \o \inlineimage macintosh-datetimeedit.png Screenshot of a Macintosh style date time editing widget
       
   109        \o A date time editing widget shown in the \l{Macintosh Style Widget Gallery}{Macintosh widget style}.
       
   110   \row \o \inlineimage plastique-datetimeedit.png Screenshot of a Plastique style date time editing widget
       
   111        \o A date time editing widget shown in the \l{Plastique Style Widget Gallery}{Plastique widget style}.
       
   112   \endtable
       
   113 
       
   114   \sa QDateEdit, QTimeEdit, QDate, QTime
       
   115 */
       
   116 
       
   117 /*!
       
   118   \enum QDateTimeEdit::Section
       
   119 
       
   120   \value NoSection
       
   121   \value AmPmSection
       
   122   \value MSecSection
       
   123   \value SecondSection
       
   124   \value MinuteSection
       
   125   \value HourSection
       
   126   \value DaySection
       
   127   \value MonthSection
       
   128   \value YearSection
       
   129   \omitvalue DateSections_Mask
       
   130   \omitvalue TimeSections_Mask
       
   131 */
       
   132 
       
   133 /*!
       
   134   \fn void QDateTimeEdit::dateTimeChanged(const QDateTime &datetime)
       
   135 
       
   136   This signal is emitted whenever the date or time is changed. The
       
   137   new date and time is passed in \a datetime.
       
   138 */
       
   139 
       
   140 /*!
       
   141   \fn void QDateTimeEdit::timeChanged(const QTime &time)
       
   142 
       
   143   This signal is emitted whenever the time is changed. The new time
       
   144   is passed in \a time.
       
   145 */
       
   146 
       
   147 /*!
       
   148   \fn void QDateTimeEdit::dateChanged(const QDate &date)
       
   149 
       
   150   This signal is emitted whenever the date is changed. The new date
       
   151   is passed in \a date.
       
   152 */
       
   153 
       
   154 
       
   155 /*!
       
   156   Constructs an empty date time editor with a \a parent.
       
   157 */
       
   158 
       
   159 QDateTimeEdit::QDateTimeEdit(QWidget *parent)
       
   160     : QAbstractSpinBox(*new QDateTimeEditPrivate, parent)
       
   161 {
       
   162     Q_D(QDateTimeEdit);
       
   163     d->init(QDateTime(QDATETIMEEDIT_DATE_INITIAL, QDATETIMEEDIT_TIME_MIN));
       
   164 }
       
   165 
       
   166 /*!
       
   167   Constructs an empty date time editor with a \a parent. The value
       
   168   is set to \a datetime.
       
   169 */
       
   170 
       
   171 QDateTimeEdit::QDateTimeEdit(const QDateTime &datetime, QWidget *parent)
       
   172     : QAbstractSpinBox(*new QDateTimeEditPrivate, parent)
       
   173 {
       
   174     Q_D(QDateTimeEdit);
       
   175     d->init(datetime.isValid() ? datetime : QDateTime(QDATETIMEEDIT_DATE_INITIAL,
       
   176                                                       QDATETIMEEDIT_TIME_MIN));
       
   177 }
       
   178 
       
   179 /*!
       
   180   \fn QDateTimeEdit::QDateTimeEdit(const QDate &date, QWidget *parent)
       
   181 
       
   182   Constructs an empty date time editor with a \a parent.
       
   183   The value is set to \a date.
       
   184 */
       
   185 
       
   186 QDateTimeEdit::QDateTimeEdit(const QDate &date, QWidget *parent)
       
   187     : QAbstractSpinBox(*new QDateTimeEditPrivate, parent)
       
   188 {
       
   189     Q_D(QDateTimeEdit);
       
   190     d->init(date.isValid() ? date : QDATETIMEEDIT_DATE_INITIAL);
       
   191 }
       
   192 
       
   193 /*!
       
   194   \fn QDateTimeEdit::QDateTimeEdit(const QTime &time, QWidget *parent)
       
   195 
       
   196   Constructs an empty date time editor with a \a parent.
       
   197   The value is set to \a time.
       
   198 */
       
   199 
       
   200 QDateTimeEdit::QDateTimeEdit(const QTime &time, QWidget *parent)
       
   201     : QAbstractSpinBox(*new QDateTimeEditPrivate, parent)
       
   202 {
       
   203     Q_D(QDateTimeEdit);
       
   204     d->init(time.isValid() ? time : QDATETIMEEDIT_TIME_MIN);
       
   205 }
       
   206 
       
   207 /*!
       
   208   \internal
       
   209 */
       
   210 
       
   211 QDateTimeEdit::QDateTimeEdit(const QVariant &var, QVariant::Type parserType, QWidget *parent)
       
   212     : QAbstractSpinBox(*new QDateTimeEditPrivate, parent)
       
   213 {
       
   214     Q_D(QDateTimeEdit);
       
   215     d->parserType = parserType;
       
   216     d->init(var);
       
   217 }
       
   218 
       
   219 /*!
       
   220   \property QDateTimeEdit::dateTime
       
   221   \brief the QDateTime that is set in the QDateTimeEdit
       
   222 
       
   223   When setting this property the timespec of the QDateTimeEdit remains the same
       
   224   and the timespec of the new QDateTime is ignored.
       
   225 
       
   226   By default, this property contains a date that refers to January 1,
       
   227   2000 and a time of 00:00:00 and 0 milliseconds.
       
   228 
       
   229   \sa date, time
       
   230 */
       
   231 
       
   232 QDateTime QDateTimeEdit::dateTime() const
       
   233 {
       
   234     Q_D(const QDateTimeEdit);
       
   235     return d->value.toDateTime();
       
   236 }
       
   237 
       
   238 void QDateTimeEdit::setDateTime(const QDateTime &datetime)
       
   239 {
       
   240     Q_D(QDateTimeEdit);
       
   241     if (datetime.isValid()) {
       
   242         d->clearCache();
       
   243         if (!(d->sections & DateSections_Mask))
       
   244             setDateRange(datetime.date(), datetime.date());
       
   245         d->setValue(QDateTime(datetime.date(), datetime.time(), d->spec), EmitIfChanged);
       
   246     }
       
   247 }
       
   248 
       
   249 /*!
       
   250   \property QDateTimeEdit::date
       
   251   \brief the QDate that is set in the QDateTimeEdit
       
   252 
       
   253   By default, this property contains a date that refers to January 1, 2000.
       
   254 
       
   255   \sa time, dateTime
       
   256 */
       
   257 
       
   258 /*!
       
   259     Returns the date of the date time edit.
       
   260 */
       
   261 QDate QDateTimeEdit::date() const
       
   262 {
       
   263     Q_D(const QDateTimeEdit);
       
   264     return d->value.toDate();
       
   265 }
       
   266 
       
   267 void QDateTimeEdit::setDate(const QDate &date)
       
   268 {
       
   269     Q_D(QDateTimeEdit);
       
   270     if (date.isValid()) {
       
   271         if (!(d->sections & DateSections_Mask))
       
   272             setDateRange(date, date);
       
   273 
       
   274         d->clearCache();
       
   275         d->setValue(QDateTime(date, d->value.toTime(), d->spec), EmitIfChanged);
       
   276         d->updateTimeSpec();
       
   277     }
       
   278 }
       
   279 
       
   280 /*!
       
   281   \property QDateTimeEdit::time
       
   282   \brief the QTime that is set in the QDateTimeEdit
       
   283 
       
   284   By default, this property contains a time of 00:00:00 and 0 milliseconds.
       
   285 
       
   286   \sa date, dateTime
       
   287 */
       
   288 
       
   289 /*!
       
   290     Returns the time of the date time edit.
       
   291 */
       
   292 QTime QDateTimeEdit::time() const
       
   293 {
       
   294     Q_D(const QDateTimeEdit);
       
   295     return d->value.toTime();
       
   296 }
       
   297 
       
   298 void QDateTimeEdit::setTime(const QTime &time)
       
   299 {
       
   300     Q_D(QDateTimeEdit);
       
   301     if (time.isValid()) {
       
   302         d->clearCache();
       
   303         d->setValue(QDateTime(d->value.toDate(), time, d->spec), EmitIfChanged);
       
   304     }
       
   305 }
       
   306 
       
   307 
       
   308 /*!
       
   309   \property QDateTimeEdit::minimumDateTime
       
   310   \since 4.4
       
   311 
       
   312   \brief the minimum datetime of the date time edit
       
   313 
       
   314   When setting this property the \l maximumDateTime() is adjusted if
       
   315   necessary to ensure that the range remains valid. If the datetime is
       
   316   not a valid QDateTime object, this function does nothing.
       
   317 
       
   318   The default minimumDateTime can be restored with
       
   319   clearMinimumDateTime()
       
   320 
       
   321   By default, this property contains a date that refers to September 14,
       
   322   1752 and a time of 00:00:00 and 0 milliseconds.
       
   323 
       
   324   \sa maximumDateTime(), minimumTime(), maximumTime(), minimumDate(),
       
   325   maximumDate(), setDateTimeRange(), setDateRange(), setTimeRange(),
       
   326   clearMaximumDateTime(), clearMinimumDate(),
       
   327   clearMaximumDate(), clearMinimumTime(), clearMaximumTime()
       
   328 */
       
   329 
       
   330 QDateTime QDateTimeEdit::minimumDateTime() const
       
   331 {
       
   332     Q_D(const QDateTimeEdit);
       
   333     return d->minimum.toDateTime();
       
   334 }
       
   335 
       
   336 void QDateTimeEdit::clearMinimumDateTime()
       
   337 {
       
   338     setMinimumDateTime(QDateTime(QDATETIMEEDIT_COMPAT_DATE_MIN, QDATETIMEEDIT_TIME_MIN));
       
   339 }
       
   340 
       
   341 void QDateTimeEdit::setMinimumDateTime(const QDateTime &dt)
       
   342 {
       
   343     Q_D(QDateTimeEdit);
       
   344     if (dt.isValid() && dt.date() >= QDATETIMEEDIT_DATE_MIN) {
       
   345         const QDateTime m = dt.toTimeSpec(d->spec);
       
   346         const QDateTime max = d->maximum.toDateTime();
       
   347         d->setRange(m, (max > m ? max : m));
       
   348     }
       
   349 }
       
   350 
       
   351 /*!
       
   352   \property QDateTimeEdit::maximumDateTime
       
   353   \since 4.4
       
   354 
       
   355   \brief the maximum datetime of the date time edit
       
   356 
       
   357   When setting this property the \l minimumDateTime() is adjusted if
       
   358   necessary to ensure that the range remains valid. If the datetime is
       
   359   not a valid QDateTime object, this function does nothing.
       
   360 
       
   361   The default maximumDateTime can be restored with
       
   362   clearMaximumDateTime().
       
   363 
       
   364   By default, this property contains a date that refers to 31 December,
       
   365   7999 and a time of 23:59:59 and 999 milliseconds.
       
   366 
       
   367   \sa minimumDateTime(), minimumTime(), maximumTime(), minimumDate(),
       
   368   maximumDate(), setDateTimeRange(), setDateRange(), setTimeRange(),
       
   369   clearMinimumDateTime(), clearMinimumDate(),
       
   370   clearMaximumDate(), clearMinimumTime(), clearMaximumTime()
       
   371 */
       
   372 
       
   373 QDateTime QDateTimeEdit::maximumDateTime() const
       
   374 {
       
   375     Q_D(const QDateTimeEdit);
       
   376     return d->maximum.toDateTime();
       
   377 }
       
   378 
       
   379 void QDateTimeEdit::clearMaximumDateTime()
       
   380 {
       
   381     setMaximumDateTime(QDATETIMEEDIT_DATETIME_MAX);
       
   382 }
       
   383 
       
   384 void QDateTimeEdit::setMaximumDateTime(const QDateTime &dt)
       
   385 {
       
   386     Q_D(QDateTimeEdit);
       
   387     if (dt.isValid() && dt.date() <= QDATETIMEEDIT_DATE_MAX) {
       
   388         const QDateTime m = dt.toTimeSpec(d->spec);
       
   389         const QDateTime min = d->minimum.toDateTime();
       
   390         d->setRange((min < m ? min : m), m);
       
   391     }
       
   392 }
       
   393 
       
   394 
       
   395 /*!
       
   396   Convenience function to set minimum and maximum date time with one
       
   397   function call.
       
   398   \since 4.4
       
   399 
       
   400   \snippet doc/src/snippets/code/src_gui_widgets_qdatetimeedit.cpp 1
       
   401 
       
   402   is analogous to:
       
   403 
       
   404   \snippet doc/src/snippets/code/src_gui_widgets_qdatetimeedit.cpp 2
       
   405 
       
   406   If either \a min or \a max are not valid, this function does
       
   407   nothing.
       
   408 
       
   409   \sa setMinimumDate(), maximumDate(), setMaximumDate(),
       
   410   clearMinimumDate(), setMinimumTime(), maximumTime(),
       
   411   setMaximumTime(), clearMinimumTime(), QDateTime::isValid()
       
   412 */
       
   413 
       
   414 void QDateTimeEdit::setDateTimeRange(const QDateTime &min, const QDateTime &max)
       
   415 {
       
   416     Q_D(QDateTimeEdit);
       
   417     const QDateTime minimum = min.toTimeSpec(d->spec);
       
   418     QDateTime maximum = max.toTimeSpec(d->spec);
       
   419     if (min > max)
       
   420         maximum = minimum;
       
   421     d->setRange(minimum, maximum);
       
   422 }
       
   423 
       
   424 /*!
       
   425   \property QDateTimeEdit::minimumDate
       
   426 
       
   427   \brief the minimum date of the date time edit
       
   428 
       
   429   When setting this property the \l maximumDate is adjusted if
       
   430   necessary, to ensure that the range remains valid. If the date is
       
   431   not a valid QDate object, this function does nothing.
       
   432 
       
   433   By default, this property contains a date that refers to September 14, 1752.
       
   434   The minimum date must be at least the first day in year 100, otherwise
       
   435   setMinimumDate() has no effect.
       
   436 
       
   437   \sa minimumTime(), maximumTime(), setDateRange()
       
   438 */
       
   439 
       
   440 QDate QDateTimeEdit::minimumDate() const
       
   441 {
       
   442     Q_D(const QDateTimeEdit);
       
   443     return d->minimum.toDate();
       
   444 }
       
   445 
       
   446 void QDateTimeEdit::setMinimumDate(const QDate &min)
       
   447 {
       
   448     Q_D(QDateTimeEdit);
       
   449     if (min.isValid() && min >= QDATETIMEEDIT_DATE_MIN) {
       
   450         setMinimumDateTime(QDateTime(min, d->minimum.toTime(), d->spec));
       
   451     }
       
   452 }
       
   453 
       
   454 void QDateTimeEdit::clearMinimumDate()
       
   455 {
       
   456     setMinimumDate(QDATETIMEEDIT_COMPAT_DATE_MIN);
       
   457 }
       
   458 
       
   459 /*!
       
   460   \property QDateTimeEdit::maximumDate
       
   461 
       
   462   \brief the maximum date of the date time edit
       
   463 
       
   464   When setting this property the \l minimumDate is adjusted if
       
   465   necessary to ensure that the range remains valid. If the date is
       
   466   not a valid QDate object, this function does nothing.
       
   467 
       
   468   By default, this property contains a date that refers to December 31, 7999.
       
   469 
       
   470   \sa minimumDate, minimumTime, maximumTime, setDateRange()
       
   471 */
       
   472 
       
   473 QDate QDateTimeEdit::maximumDate() const
       
   474 {
       
   475     Q_D(const QDateTimeEdit);
       
   476     return d->maximum.toDate();
       
   477 }
       
   478 
       
   479 void QDateTimeEdit::setMaximumDate(const QDate &max)
       
   480 {
       
   481     Q_D(QDateTimeEdit);
       
   482     if (max.isValid()) {
       
   483         setMaximumDateTime(QDateTime(max, d->maximum.toTime(), d->spec));
       
   484     }
       
   485 }
       
   486 
       
   487 void QDateTimeEdit::clearMaximumDate()
       
   488 {
       
   489     setMaximumDate(QDATETIMEEDIT_DATE_MAX);
       
   490 }
       
   491 
       
   492 /*!
       
   493   \property QDateTimeEdit::minimumTime
       
   494 
       
   495   \brief the minimum time of the date time edit
       
   496 
       
   497   When setting this property the \l maximumTime is adjusted if
       
   498   necessary, to ensure that the range remains valid. If the time is
       
   499   not a valid QTime object, this function does nothing.
       
   500 
       
   501   By default, this property contains a time of 00:00:00 and 0 milliseconds.
       
   502 
       
   503   \sa maximumTime, minimumDate, maximumDate, setTimeRange()
       
   504 */
       
   505 
       
   506 QTime QDateTimeEdit::minimumTime() const
       
   507 {
       
   508     Q_D(const QDateTimeEdit);
       
   509     return d->minimum.toTime();
       
   510 }
       
   511 
       
   512 void QDateTimeEdit::setMinimumTime(const QTime &min)
       
   513 {
       
   514     Q_D(QDateTimeEdit);
       
   515     if (min.isValid()) {
       
   516         const QDateTime m(d->minimum.toDate(), min, d->spec);
       
   517         setMinimumDateTime(m);
       
   518     }
       
   519 }
       
   520 
       
   521 void QDateTimeEdit::clearMinimumTime()
       
   522 {
       
   523     setMinimumTime(QDATETIMEEDIT_TIME_MIN);
       
   524 }
       
   525 
       
   526 /*!
       
   527   \property QDateTimeEdit::maximumTime
       
   528 
       
   529   \brief the maximum time of the date time edit
       
   530 
       
   531   When setting this property, the \l minimumTime is adjusted if
       
   532   necessary to ensure that the range remains valid. If the time is
       
   533   not a valid QTime object, this function does nothing.
       
   534 
       
   535   By default, this property contains a time of 23:59:59 and 999 milliseconds.
       
   536 
       
   537   \sa minimumTime, minimumDate, maximumDate, setTimeRange()
       
   538 */
       
   539 QTime QDateTimeEdit::maximumTime() const
       
   540 {
       
   541     Q_D(const QDateTimeEdit);
       
   542     return d->maximum.toTime();
       
   543 }
       
   544 
       
   545 void QDateTimeEdit::setMaximumTime(const QTime &max)
       
   546 {
       
   547     Q_D(QDateTimeEdit);
       
   548     if (max.isValid()) {
       
   549         const QDateTime m(d->maximum.toDate(), max);
       
   550         setMaximumDateTime(m);
       
   551     }
       
   552 }
       
   553 
       
   554 void QDateTimeEdit::clearMaximumTime()
       
   555 {
       
   556     setMaximumTime(QDATETIMEEDIT_TIME_MAX);
       
   557 }
       
   558 
       
   559 /*!
       
   560   Convenience function to set minimum and maximum date with one
       
   561   function call.
       
   562 
       
   563   \snippet doc/src/snippets/code/src_gui_widgets_qdatetimeedit.cpp 3
       
   564 
       
   565   is analogous to:
       
   566 
       
   567   \snippet doc/src/snippets/code/src_gui_widgets_qdatetimeedit.cpp 4
       
   568 
       
   569   If either \a min or \a max are not valid, this function does
       
   570   nothing.
       
   571 
       
   572   \sa setMinimumDate(), maximumDate(), setMaximumDate(),
       
   573   clearMinimumDate(), setMinimumTime(), maximumTime(),
       
   574   setMaximumTime(), clearMinimumTime(), QDate::isValid()
       
   575 */
       
   576 
       
   577 void QDateTimeEdit::setDateRange(const QDate &min, const QDate &max)
       
   578 {
       
   579     Q_D(QDateTimeEdit);
       
   580     if (min.isValid() && max.isValid()) {
       
   581         setDateTimeRange(QDateTime(min, d->minimum.toTime(), d->spec),
       
   582                          QDateTime(max, d->maximum.toTime(), d->spec));
       
   583     }
       
   584 }
       
   585 
       
   586 /*!
       
   587   Convenience function to set minimum and maximum time with one
       
   588   function call.
       
   589 
       
   590   \snippet doc/src/snippets/code/src_gui_widgets_qdatetimeedit.cpp 5
       
   591 
       
   592   is analogous to:
       
   593 
       
   594   \snippet doc/src/snippets/code/src_gui_widgets_qdatetimeedit.cpp 6
       
   595 
       
   596   If either \a min or \a max are not valid, this function does
       
   597   nothing.
       
   598 
       
   599   \sa setMinimumDate(), maximumDate(), setMaximumDate(),
       
   600   clearMinimumDate(), setMinimumTime(), maximumTime(),
       
   601   setMaximumTime(), clearMinimumTime(), QTime::isValid()
       
   602 */
       
   603 
       
   604 void QDateTimeEdit::setTimeRange(const QTime &min, const QTime &max)
       
   605 {
       
   606     Q_D(QDateTimeEdit);
       
   607     if (min.isValid() && max.isValid()) {
       
   608         setDateTimeRange(QDateTime(d->minimum.toDate(), min, d->spec),
       
   609                          QDateTime(d->maximum.toDate(), max, d->spec));
       
   610     }
       
   611 }
       
   612 
       
   613 /*!
       
   614   \property QDateTimeEdit::displayedSections
       
   615 
       
   616   \brief the currently displayed fields of the date time edit
       
   617 
       
   618   Returns a bit set of the displayed sections for this format.
       
   619   \a setDisplayFormat(), displayFormat()
       
   620 */
       
   621 
       
   622 QDateTimeEdit::Sections QDateTimeEdit::displayedSections() const
       
   623 {
       
   624     Q_D(const QDateTimeEdit);
       
   625     return d->sections;
       
   626 }
       
   627 
       
   628 /*!
       
   629   \property QDateTimeEdit::currentSection
       
   630 
       
   631   \brief the current section of the spinbox
       
   632   \a setCurrentSection()
       
   633 */
       
   634 
       
   635 QDateTimeEdit::Section QDateTimeEdit::currentSection() const
       
   636 {
       
   637     Q_D(const QDateTimeEdit);
       
   638 #ifdef QT_KEYPAD_NAVIGATION
       
   639     if (QApplication::keypadNavigationEnabled() && d->focusOnButton)
       
   640         return NoSection;
       
   641 #endif
       
   642     return d->convertToPublic(d->sectionType(d->currentSectionIndex));
       
   643 }
       
   644 
       
   645 void QDateTimeEdit::setCurrentSection(Section section)
       
   646 {
       
   647     Q_D(QDateTimeEdit);
       
   648     if (section == NoSection || !(section & d->sections))
       
   649         return;
       
   650 
       
   651     d->updateCache(d->value, d->displayText());
       
   652     const int size = d->sectionNodes.size();
       
   653     int index = d->currentSectionIndex + 1;
       
   654     for (int i=0; i<2; ++i) {
       
   655         while (index < size) {
       
   656             if (d->convertToPublic(d->sectionType(index)) == section) {
       
   657                 d->edit->setCursorPosition(d->sectionPos(index));
       
   658                 QDTEDEBUG << d->sectionPos(index);
       
   659                 return;
       
   660             }
       
   661             ++index;
       
   662         }
       
   663         index = 0;
       
   664     }
       
   665 }
       
   666 
       
   667 /*!
       
   668   \since 4.3
       
   669 
       
   670   Returns the Section at \a index.
       
   671 
       
   672   If the format is 'yyyy/MM/dd', sectionAt(0) returns YearSection,
       
   673   sectionAt(1) returns MonthSection, and sectionAt(2) returns
       
   674   YearSection,
       
   675 */
       
   676 
       
   677 QDateTimeEdit::Section QDateTimeEdit::sectionAt(int index) const
       
   678 {
       
   679     Q_D(const QDateTimeEdit);
       
   680     if (index < 0 || index >= d->sectionNodes.size())
       
   681         return NoSection;
       
   682     return d->convertToPublic(d->sectionType(index));
       
   683 }
       
   684 
       
   685 /*!
       
   686   \since 4.3
       
   687 
       
   688   \property QDateTimeEdit::sectionCount
       
   689 
       
   690   \brief the number of sections displayed.
       
   691   If the format is 'yyyy/yy/yyyy', sectionCount returns 3
       
   692 */
       
   693 
       
   694 int QDateTimeEdit::sectionCount() const
       
   695 {
       
   696     Q_D(const QDateTimeEdit);
       
   697     return d->sectionNodes.size();
       
   698 }
       
   699 
       
   700 
       
   701 /*!
       
   702   \since 4.3
       
   703 
       
   704   \property QDateTimeEdit::currentSectionIndex
       
   705 
       
   706   \brief the current section index of the spinbox
       
   707 
       
   708   If the format is 'yyyy/MM/dd', the displayText is '2001/05/21' and
       
   709   the cursorPosition is 5 currentSectionIndex returns 1. If the
       
   710   cursorPosition is 3 currentSectionIndex is 0 etc.
       
   711 
       
   712   \a setCurrentSection()
       
   713   \sa currentSection()
       
   714 */
       
   715 
       
   716 int QDateTimeEdit::currentSectionIndex() const
       
   717 {
       
   718     Q_D(const QDateTimeEdit);
       
   719     return d->currentSectionIndex;
       
   720 }
       
   721 
       
   722 void QDateTimeEdit::setCurrentSectionIndex(int index)
       
   723 {
       
   724     Q_D(QDateTimeEdit);
       
   725     if (index < 0 || index >= d->sectionNodes.size())
       
   726         return;
       
   727     d->edit->setCursorPosition(d->sectionPos(index));
       
   728 }
       
   729 
       
   730 /*!
       
   731   \since 4.4
       
   732 
       
   733   \brief Returns the calendar widget for the editor if calendarPopup is
       
   734   set to true and (sections() & DateSections_Mask) != 0.
       
   735 
       
   736   This function creates and returns a calendar widget if none has been set.
       
   737 */
       
   738 
       
   739 
       
   740 QCalendarWidget *QDateTimeEdit::calendarWidget() const
       
   741 {
       
   742     Q_D(const QDateTimeEdit);
       
   743     if (!d->calendarPopup || !(d->sections & QDateTimeParser::DateSectionMask))
       
   744         return 0;
       
   745     if (!d->monthCalendar) {
       
   746         const_cast<QDateTimeEditPrivate*>(d)->initCalendarPopup();
       
   747     }
       
   748     return d->monthCalendar->calendarWidget();
       
   749 }
       
   750 
       
   751 /*!
       
   752   \since 4.4
       
   753 
       
   754   Sets the given \a calendarWidget as the widget to be used for the calendar
       
   755   pop-up. The editor does not automatically take ownership of the calendar widget.
       
   756 
       
   757   \sa calendarPopup
       
   758 */
       
   759 void QDateTimeEdit::setCalendarWidget(QCalendarWidget *calendarWidget)
       
   760 {
       
   761     Q_D(QDateTimeEdit);
       
   762     if (!calendarWidget) {
       
   763         qWarning("QDateTimeEdit::setCalendarWidget: Cannot set a null calendar widget");
       
   764         return;
       
   765     }
       
   766 
       
   767     if (!d->calendarPopup) {
       
   768         qWarning("QDateTimeEdit::setCalendarWidget: calendarPopup is set to false");
       
   769         return;
       
   770     }
       
   771 
       
   772     if (!(d->display & QDateTimeParser::DateSectionMask)) {
       
   773         qWarning("QDateTimeEdit::setCalendarWidget: no date sections specified");
       
   774         return;
       
   775     }
       
   776     d->initCalendarPopup(calendarWidget);
       
   777 }
       
   778 
       
   779 
       
   780 /*!
       
   781   \since 4.2
       
   782 
       
   783   Selects \a section. If \a section doesn't exist in the currently
       
   784   displayed sections this function does nothing. If \a section is
       
   785   NoSection this function will unselect all text in the editor.
       
   786   Otherwise this function will move the cursor and the current section
       
   787   to the selected section.
       
   788 
       
   789   \sa currentSection()
       
   790 */
       
   791 
       
   792 void QDateTimeEdit::setSelectedSection(Section section)
       
   793 {
       
   794     Q_D(QDateTimeEdit);
       
   795     if (section == NoSection) {
       
   796         d->edit->setSelection(d->edit->cursorPosition(), 0);
       
   797     } else if (section & d->sections) {
       
   798         if (currentSection() != section)
       
   799             setCurrentSection(section);
       
   800         d->setSelected(d->currentSectionIndex);
       
   801     }
       
   802 }
       
   803 
       
   804 
       
   805 
       
   806 /*!
       
   807   \fn QString QDateTimeEdit::sectionText(Section section) const
       
   808 
       
   809   Returns the text from the given \a section.
       
   810 
       
   811   \sa currentSection()
       
   812 */
       
   813 
       
   814 QString QDateTimeEdit::sectionText(Section section) const
       
   815 {
       
   816     Q_D(const QDateTimeEdit);
       
   817     if (section == QDateTimeEdit::NoSection || !(section & d->sections)) {
       
   818         return QString();
       
   819     }
       
   820 
       
   821     d->updateCache(d->value, d->displayText());
       
   822     const int sectionIndex = d->absoluteIndex(section, 0);
       
   823     return d->sectionText(sectionIndex);
       
   824 }
       
   825 
       
   826 /*!
       
   827   \property QDateTimeEdit::displayFormat
       
   828 
       
   829   \brief the format used to display the time/date of the date time edit
       
   830 
       
   831   This format is the same as the one used described in QDateTime::toString()
       
   832   and QDateTime::fromString()
       
   833 
       
   834   Example format strings(assuming that the date is 2nd of July 1969):
       
   835 
       
   836   \table
       
   837   \header \i Format \i Result
       
   838   \row \i dd.MM.yyyy    \i 02.07.1969
       
   839   \row \i MMM d yy \i Jul 2 69
       
   840   \row \i MMMM d yy \i July 2 69
       
   841   \endtable
       
   842 
       
   843   Note that if you specify a two digit year, it will be interpreted
       
   844   to be in the century in which the date time edit was initialized.
       
   845   The default century is the 21 (2000-2099).
       
   846 
       
   847   If you specify an invalid format the format will not be set.
       
   848 
       
   849   \sa QDateTime::toString(), displayedSections()
       
   850 */
       
   851 
       
   852 QString QDateTimeEdit::displayFormat() const
       
   853 {
       
   854     Q_D(const QDateTimeEdit);
       
   855     return isRightToLeft() ? d->unreversedFormat : d->displayFormat;
       
   856 }
       
   857 
       
   858 template<typename C> static inline C reverse(const C &l)
       
   859 {
       
   860     C ret;
       
   861     for (int i=l.size() - 1; i>=0; --i)
       
   862         ret.append(l.at(i));
       
   863     return ret;
       
   864 }
       
   865 
       
   866 void QDateTimeEdit::setDisplayFormat(const QString &format)
       
   867 {
       
   868     Q_D(QDateTimeEdit);
       
   869     if (d->parseFormat(format)) {
       
   870         d->unreversedFormat.clear();
       
   871         if (isRightToLeft()) {
       
   872             d->unreversedFormat = format;
       
   873             d->displayFormat.clear();
       
   874             for (int i=d->sectionNodes.size() - 1; i>=0; --i) {
       
   875                 d->displayFormat += d->separators.at(i + 1);
       
   876                 d->displayFormat += d->sectionFormat(i);
       
   877             }
       
   878             d->displayFormat += d->separators.at(0);
       
   879             d->separators = reverse(d->separators);
       
   880             d->sectionNodes = reverse(d->sectionNodes);
       
   881         }
       
   882 
       
   883         d->formatExplicitlySet = true;
       
   884         d->sections = d->convertSections(d->display);
       
   885         d->clearCache();
       
   886 
       
   887         d->currentSectionIndex = qMin(d->currentSectionIndex, d->sectionNodes.size() - 1);
       
   888         const bool timeShown = (d->sections & TimeSections_Mask);
       
   889         const bool dateShown = (d->sections & DateSections_Mask);
       
   890         Q_ASSERT(dateShown || timeShown);
       
   891         if (timeShown && !dateShown) {
       
   892             setDateRange(d->value.toDate(), d->value.toDate());
       
   893         } else if (dateShown && !timeShown) {
       
   894             setTimeRange(QDATETIMEEDIT_TIME_MIN, QDATETIMEEDIT_TIME_MAX);
       
   895             d->value = QDateTime(d->value.toDate(), QTime(), d->spec);
       
   896         }
       
   897         d->updateEdit();
       
   898         d->_q_editorCursorPositionChanged(-1, 0);
       
   899     }
       
   900 }
       
   901 
       
   902 /*!
       
   903     \property QDateTimeEdit::calendarPopup
       
   904     \brief the current calender pop-up showing mode.
       
   905     \since 4.2
       
   906 
       
   907     The calendar pop-up will be shown upon clicking the arrow button.
       
   908     This property is valid only if there is a valid date display format.
       
   909 
       
   910     \sa setDisplayFormat()
       
   911 */
       
   912 
       
   913 bool QDateTimeEdit::calendarPopup() const
       
   914 {
       
   915     Q_D(const QDateTimeEdit);
       
   916     return d->calendarPopup;
       
   917 }
       
   918 
       
   919 void QDateTimeEdit::setCalendarPopup(bool enable)
       
   920 {
       
   921     Q_D(QDateTimeEdit);
       
   922     if (enable == d->calendarPopup)
       
   923         return;
       
   924     setAttribute(Qt::WA_MacShowFocusRect, !enable);
       
   925     d->calendarPopup = enable;
       
   926 #ifdef QT_KEYPAD_NAVIGATION
       
   927     if (!enable)
       
   928         d->focusOnButton = false;
       
   929 #endif
       
   930     d->updateEditFieldGeometry();
       
   931     update();
       
   932 }
       
   933 
       
   934 /*!
       
   935     \property QDateTimeEdit::timeSpec
       
   936     \brief the current timespec used by the date time edit.
       
   937     \since 4.4
       
   938 */
       
   939 
       
   940 Qt::TimeSpec QDateTimeEdit::timeSpec() const
       
   941 {
       
   942     Q_D(const QDateTimeEdit);
       
   943     return d->spec;
       
   944 }
       
   945 
       
   946 void QDateTimeEdit::setTimeSpec(Qt::TimeSpec spec)
       
   947 {
       
   948     Q_D(QDateTimeEdit);
       
   949     if (spec != d->spec) {
       
   950         d->spec = spec;
       
   951         d->updateTimeSpec();
       
   952     }
       
   953 }
       
   954 
       
   955 /*!
       
   956   \reimp
       
   957 */
       
   958 
       
   959 QSize QDateTimeEdit::sizeHint() const
       
   960 {
       
   961     Q_D(const QDateTimeEdit);
       
   962     if (d->cachedSizeHint.isEmpty()) {
       
   963         ensurePolished();
       
   964 
       
   965         const QFontMetrics fm(fontMetrics());
       
   966         int h = d->edit->sizeHint().height();
       
   967         int w = 0;
       
   968         QString s;
       
   969         s = d->textFromValue(d->minimum) + QLatin1String("   ");
       
   970         w = qMax<int>(w, fm.width(s));
       
   971         s = d->textFromValue(d->maximum) + QLatin1String("   ");
       
   972         w = qMax<int>(w, fm.width(s));
       
   973         if (d->specialValueText.size()) {
       
   974             s = d->specialValueText;
       
   975             w = qMax<int>(w, fm.width(s));
       
   976         }
       
   977         w += 2; // cursor blinking space
       
   978 
       
   979         QSize hint(w, h);
       
   980 
       
   981 #ifdef Q_WS_MAC
       
   982         if (d->calendarPopupEnabled()) {
       
   983             QStyleOptionComboBox opt;
       
   984             d->cachedSizeHint = style()->sizeFromContents(QStyle::CT_ComboBox, &opt, hint, this);
       
   985         } else {
       
   986 #else
       
   987         {
       
   988 #endif
       
   989             QSize extra(35, 6);
       
   990             QStyleOptionSpinBox opt;
       
   991             initStyleOption(&opt);
       
   992             opt.rect.setSize(hint + extra);
       
   993             extra += hint - style()->subControlRect(QStyle::CC_SpinBox, &opt,
       
   994                                                 QStyle::SC_SpinBoxEditField, this).size();
       
   995             // get closer to final result by repeating the calculation
       
   996             opt.rect.setSize(hint + extra);
       
   997             extra += hint - style()->subControlRect(QStyle::CC_SpinBox, &opt,
       
   998                                                 QStyle::SC_SpinBoxEditField, this).size();
       
   999             hint += extra;
       
  1000 
       
  1001             opt.rect = rect();
       
  1002             d->cachedSizeHint = style()->sizeFromContents(QStyle::CT_SpinBox, &opt, hint, this)
       
  1003                                 .expandedTo(QApplication::globalStrut());
       
  1004         }
       
  1005 
       
  1006         d->cachedMinimumSizeHint = d->cachedSizeHint;
       
  1007         // essentially make minimumSizeHint return the same as sizeHint for datetimeedits
       
  1008     }
       
  1009     return d->cachedSizeHint;
       
  1010 }
       
  1011 
       
  1012 /*!
       
  1013   \reimp
       
  1014 */
       
  1015 
       
  1016 bool QDateTimeEdit::event(QEvent *event)
       
  1017 {
       
  1018     Q_D(QDateTimeEdit);
       
  1019     switch (event->type()) {
       
  1020     case QEvent::ApplicationLayoutDirectionChange: {
       
  1021         const bool was = d->formatExplicitlySet;
       
  1022         const QString oldFormat = d->displayFormat;
       
  1023         d->displayFormat.clear();
       
  1024         setDisplayFormat(oldFormat);
       
  1025         d->formatExplicitlySet = was;
       
  1026         break; }
       
  1027     case QEvent::LocaleChange:
       
  1028         d->updateEdit();
       
  1029         break;
       
  1030     case QEvent::StyleChange:
       
  1031 #ifdef Q_WS_MAC
       
  1032     case QEvent::MacSizeChange:
       
  1033 #endif
       
  1034         d->setLayoutItemMargins(QStyle::SE_DateTimeEditLayoutItem);
       
  1035         break;
       
  1036     default:
       
  1037         break;
       
  1038     }
       
  1039     return QAbstractSpinBox::event(event);
       
  1040 }
       
  1041 
       
  1042 /*!
       
  1043   \reimp
       
  1044 */
       
  1045 
       
  1046 void QDateTimeEdit::clear()
       
  1047 {
       
  1048     Q_D(QDateTimeEdit);
       
  1049     d->clearSection(d->currentSectionIndex);
       
  1050 }
       
  1051 /*!
       
  1052   \reimp
       
  1053 */
       
  1054 
       
  1055 void QDateTimeEdit::keyPressEvent(QKeyEvent *event)
       
  1056 {
       
  1057     Q_D(QDateTimeEdit);
       
  1058     int oldCurrent = d->currentSectionIndex;
       
  1059     bool select = true;
       
  1060     bool inserted = false;
       
  1061 
       
  1062     switch (event->key()) {
       
  1063 #ifdef QT_KEYPAD_NAVIGATION
       
  1064     case Qt::Key_NumberSign:    //shortcut to popup calendar
       
  1065         if (QApplication::keypadNavigationEnabled() && d->calendarPopupEnabled()) {
       
  1066             d->initCalendarPopup();
       
  1067             d->positionCalendarPopup();
       
  1068             d->monthCalendar->show();
       
  1069             return;
       
  1070         }
       
  1071         break;
       
  1072     case Qt::Key_Select:
       
  1073         if (QApplication::keypadNavigationEnabled()) {
       
  1074             if (hasEditFocus()) {
       
  1075                 if (d->focusOnButton) {
       
  1076                     d->initCalendarPopup();
       
  1077                     d->positionCalendarPopup();
       
  1078                     d->monthCalendar->show();
       
  1079                     d->focusOnButton = false;
       
  1080                     return;
       
  1081                 }
       
  1082                 setEditFocus(false);
       
  1083                 selectAll();
       
  1084             } else {
       
  1085                 setEditFocus(true);
       
  1086 
       
  1087                 //hide cursor
       
  1088                 d->edit->d_func()->setCursorVisible(false);
       
  1089                 d->edit->d_func()->control->setCursorBlinkPeriod(0);
       
  1090                 d->setSelected(0);
       
  1091             }
       
  1092         }
       
  1093         return;
       
  1094 #endif
       
  1095     case Qt::Key_Enter:
       
  1096     case Qt::Key_Return:
       
  1097         d->interpret(AlwaysEmit);
       
  1098         d->setSelected(d->currentSectionIndex, true);
       
  1099         event->ignore();
       
  1100         emit editingFinished();
       
  1101         return;
       
  1102     default:
       
  1103 #ifdef QT_KEYPAD_NAVIGATION
       
  1104         if (QApplication::keypadNavigationEnabled() && !hasEditFocus()
       
  1105             && !event->text().isEmpty() && event->text().at(0).isLetterOrNumber()) {
       
  1106             setEditFocus(true);
       
  1107 
       
  1108             //hide cursor
       
  1109             d->edit->d_func()->setCursorVisible(false);
       
  1110             d->edit->d_func()->control->setCursorBlinkPeriod(0);
       
  1111             d->setSelected(0);
       
  1112             oldCurrent = 0;
       
  1113         }
       
  1114 #endif
       
  1115         if (!d->isSeparatorKey(event)) {
       
  1116             inserted = select = !event->text().isEmpty() && event->text().at(0).isPrint()
       
  1117                        && !(event->modifiers() & ~(Qt::ShiftModifier|Qt::KeypadModifier));
       
  1118             break;
       
  1119         }
       
  1120     case Qt::Key_Left:
       
  1121     case Qt::Key_Right:
       
  1122         if (event->key() == Qt::Key_Left || event->key() == Qt::Key_Right) {
       
  1123             if (
       
  1124 #ifdef QT_KEYPAD_NAVIGATION
       
  1125                 QApplication::keypadNavigationEnabled() && !hasEditFocus()
       
  1126                 || !QApplication::keypadNavigationEnabled() &&
       
  1127 #endif
       
  1128                 !(event->modifiers() & Qt::ControlModifier)) {
       
  1129                 select = false;
       
  1130                 break;
       
  1131             }
       
  1132 #ifdef Q_WS_MAC
       
  1133             else
       
  1134 #ifdef QT_KEYPAD_NAVIGATION
       
  1135                 if (!QApplication::keypadNavigationEnabled())
       
  1136 #endif
       
  1137             {
       
  1138                 select = (event->modifiers() & Qt::ShiftModifier);
       
  1139                 break;
       
  1140             }
       
  1141 #endif
       
  1142         }
       
  1143         // else fall through
       
  1144     case Qt::Key_Backtab:
       
  1145     case Qt::Key_Tab: {
       
  1146         event->accept();
       
  1147         if (d->specialValue()) {
       
  1148             d->edit->setSelection(d->edit->cursorPosition(), 0);
       
  1149             return;
       
  1150         }
       
  1151         const bool forward = event->key() != Qt::Key_Left && event->key() != Qt::Key_Backtab
       
  1152                              && (event->key() != Qt::Key_Tab || !(event->modifiers() & Qt::ShiftModifier));
       
  1153 #ifdef QT_KEYPAD_NAVIGATION
       
  1154         int newSection = d->nextPrevSection(d->currentSectionIndex, forward);
       
  1155         if (QApplication::keypadNavigationEnabled()) {
       
  1156             if (d->focusOnButton) {
       
  1157                 newSection = forward ? 0 : d->sectionNodes.size() - 1;
       
  1158                 d->focusOnButton = false;
       
  1159                 update();
       
  1160             } else if (newSection < 0 && select && d->calendarPopupEnabled()) {
       
  1161                 setSelectedSection(NoSection);
       
  1162                 d->focusOnButton = true;
       
  1163                 update();
       
  1164                 return;
       
  1165             }
       
  1166         }
       
  1167         // only allow date/time sections to be selected.
       
  1168         if (newSection & ~(QDateTimeParser::TimeSectionMask | QDateTimeParser::DateSectionMask))
       
  1169             return;
       
  1170 #endif
       
  1171         //key tab and backtab will be managed thrgout QWidget::event
       
  1172         if (event->key() != Qt::Key_Backtab && event->key() != Qt::Key_Tab)
       
  1173             focusNextPrevChild(forward);
       
  1174 
       
  1175         return; }
       
  1176     }
       
  1177     QAbstractSpinBox::keyPressEvent(event);
       
  1178     if (select && !(event->modifiers() & Qt::ShiftModifier) && !d->edit->hasSelectedText()) {
       
  1179         if (inserted && d->sectionAt(d->edit->cursorPosition()) == QDateTimeParser::NoSectionIndex) {
       
  1180             QString str = d->displayText();
       
  1181             int pos = d->edit->cursorPosition();
       
  1182             if (validate(str, pos) == QValidator::Acceptable
       
  1183                 && (d->sectionNodes.at(oldCurrent).count != 1
       
  1184                     || d->sectionMaxSize(oldCurrent) == d->sectionSize(oldCurrent)
       
  1185                     || d->skipToNextSection(oldCurrent, d->value.toDateTime(), d->sectionText(oldCurrent)))) {
       
  1186                 QDTEDEBUG << "Setting currentsection to"
       
  1187                           << d->closestSection(d->edit->cursorPosition(), true) << event->key()
       
  1188                           << oldCurrent << str;
       
  1189                 const int tmp = d->closestSection(d->edit->cursorPosition(), true);
       
  1190                 if (tmp >= 0)
       
  1191                     d->currentSectionIndex = tmp;
       
  1192             }
       
  1193         }
       
  1194         if (d->currentSectionIndex != oldCurrent) {
       
  1195             d->setSelected(d->currentSectionIndex);
       
  1196         }
       
  1197     }
       
  1198     if (d->specialValue()) {
       
  1199         d->edit->setSelection(d->edit->cursorPosition(), 0);
       
  1200     }
       
  1201 }
       
  1202 
       
  1203 /*!
       
  1204   \reimp
       
  1205 */
       
  1206 
       
  1207 #ifndef QT_NO_WHEELEVENT
       
  1208 void QDateTimeEdit::wheelEvent(QWheelEvent *event)
       
  1209 {
       
  1210     QAbstractSpinBox::wheelEvent(event);
       
  1211 }
       
  1212 #endif
       
  1213 
       
  1214 /*!
       
  1215   \reimp
       
  1216 */
       
  1217 
       
  1218 void QDateTimeEdit::focusInEvent(QFocusEvent *event)
       
  1219 {
       
  1220     Q_D(QDateTimeEdit);
       
  1221     QAbstractSpinBox::focusInEvent(event);
       
  1222     QString *frm = 0;
       
  1223     const int oldPos = d->edit->cursorPosition();
       
  1224     if (!d->formatExplicitlySet) {
       
  1225         if (d->displayFormat == d->defaultTimeFormat) {
       
  1226             frm = &d->defaultTimeFormat;
       
  1227         } else if (d->displayFormat == d->defaultDateFormat) {
       
  1228             frm = &d->defaultDateFormat;
       
  1229         } else if (d->displayFormat == d->defaultDateTimeFormat) {
       
  1230             frm = &d->defaultDateTimeFormat;
       
  1231         }
       
  1232 
       
  1233         if (frm) {
       
  1234             d->readLocaleSettings();
       
  1235             if (d->displayFormat != *frm) {
       
  1236                 setDisplayFormat(*frm);
       
  1237                 d->formatExplicitlySet = false;
       
  1238                 d->edit->setCursorPosition(oldPos);
       
  1239             }
       
  1240         }
       
  1241     }
       
  1242     const bool oldHasHadFocus = d->hasHadFocus;
       
  1243     d->hasHadFocus = true;
       
  1244     bool first = true;
       
  1245     switch (event->reason()) {
       
  1246     case Qt::BacktabFocusReason:
       
  1247         first = false;
       
  1248         break;
       
  1249     case Qt::MouseFocusReason:
       
  1250     case Qt::PopupFocusReason:
       
  1251         return;
       
  1252     case Qt::ActiveWindowFocusReason:
       
  1253         if (oldHasHadFocus)
       
  1254             return;
       
  1255     case Qt::ShortcutFocusReason:
       
  1256     case Qt::TabFocusReason:
       
  1257     default:
       
  1258         break;
       
  1259     }
       
  1260     if (isRightToLeft())
       
  1261         first = !first;
       
  1262     d->updateEdit(); // needed to make it update specialValueText
       
  1263 
       
  1264     d->setSelected(first ? 0 : d->sectionNodes.size() - 1);
       
  1265 }
       
  1266 
       
  1267 /*!
       
  1268   \reimp
       
  1269 */
       
  1270 
       
  1271 bool QDateTimeEdit::focusNextPrevChild(bool next)
       
  1272 {
       
  1273     Q_D(QDateTimeEdit);
       
  1274     const int newSection = d->nextPrevSection(d->currentSectionIndex, next);
       
  1275     switch (d->sectionType(newSection)) {
       
  1276     case QDateTimeParser::NoSection:
       
  1277     case QDateTimeParser::FirstSection:
       
  1278     case QDateTimeParser::LastSection:
       
  1279         return QAbstractSpinBox::focusNextPrevChild(next);
       
  1280     default:
       
  1281         d->edit->deselect();
       
  1282         d->edit->setCursorPosition(d->sectionPos(newSection));
       
  1283         QDTEDEBUG << d->sectionPos(newSection);
       
  1284         d->setSelected(newSection, true);
       
  1285         return false;
       
  1286     }
       
  1287 }
       
  1288 
       
  1289 /*!
       
  1290   \reimp
       
  1291 */
       
  1292 
       
  1293 void QDateTimeEdit::stepBy(int steps)
       
  1294 {
       
  1295     Q_D(QDateTimeEdit);
       
  1296 #ifdef QT_KEYPAD_NAVIGATION
       
  1297     // with keypad navigation and not editFocus, left right change the date/time by a fixed amount.
       
  1298     if (QApplication::keypadNavigationEnabled() && !hasEditFocus()) {
       
  1299         // if date based, shift by day.  else shift by 15min
       
  1300         if (d->sections & DateSections_Mask) {
       
  1301             setDateTime(dateTime().addDays(steps));
       
  1302         } else {
       
  1303             int minutes = time().hour()*60 + time().minute();
       
  1304             int blocks = minutes/15;
       
  1305             blocks += steps;
       
  1306             /* rounding involved */
       
  1307             if (minutes % 15) {
       
  1308                 if (steps < 0) {
       
  1309                     blocks += 1; // do one less step;
       
  1310                 }
       
  1311             }
       
  1312 
       
  1313             minutes = blocks * 15;
       
  1314 
       
  1315             /* need to take wrapping into account */
       
  1316             if (!d->wrapping) {
       
  1317                 int max_minutes = d->maximum.toTime().hour()*60 + d->maximum.toTime().minute();
       
  1318                 int min_minutes = d->minimum.toTime().hour()*60 + d->minimum.toTime().minute();
       
  1319 
       
  1320                 if (minutes >= max_minutes) {
       
  1321                     setTime(maximumTime());
       
  1322                     return;
       
  1323                 } else if (minutes <= min_minutes) {
       
  1324                     setTime(minimumTime());
       
  1325                     return;
       
  1326                 }
       
  1327             }
       
  1328             setTime(QTime(minutes/60, minutes%60));
       
  1329         }
       
  1330         return;
       
  1331     }
       
  1332 #endif
       
  1333     // don't optimize away steps == 0. This is the only way to select
       
  1334     // the currentSection in Qt 4.1.x
       
  1335     if (d->specialValue() && displayedSections() != AmPmSection) {
       
  1336         for (int i=0; i<d->sectionNodes.size(); ++i) {
       
  1337             if (d->sectionType(i) != QDateTimeParser::AmPmSection) {
       
  1338                 d->currentSectionIndex = i;
       
  1339                 break;
       
  1340             }
       
  1341         }
       
  1342     }
       
  1343     d->setValue(d->stepBy(d->currentSectionIndex, steps, false), EmitIfChanged);
       
  1344     d->updateCache(d->value, d->displayText());
       
  1345 
       
  1346     d->setSelected(d->currentSectionIndex);
       
  1347     d->updateTimeSpec();
       
  1348 }
       
  1349 
       
  1350 /*!
       
  1351   This virtual function is used by the date time edit whenever it
       
  1352   needs to display \a dateTime.
       
  1353 
       
  1354   If you reimplement this, you may also need to reimplement validate().
       
  1355 
       
  1356   \sa dateTimeFromText(), validate()
       
  1357 */
       
  1358 QString QDateTimeEdit::textFromDateTime(const QDateTime &dateTime) const
       
  1359 {
       
  1360     Q_D(const QDateTimeEdit);
       
  1361     return locale().toString(dateTime, d->displayFormat);
       
  1362 }
       
  1363 
       
  1364 
       
  1365 /*!
       
  1366   Returns an appropriate datetime for the given \a text.
       
  1367 
       
  1368   This virtual function is used by the datetime edit whenever it
       
  1369   needs to interpret text entered by the user as a value.
       
  1370 
       
  1371   \sa textFromDateTime(), validate()
       
  1372 */
       
  1373 QDateTime QDateTimeEdit::dateTimeFromText(const QString &text) const
       
  1374 {
       
  1375     Q_D(const QDateTimeEdit);
       
  1376     QString copy = text;
       
  1377     int pos = d->edit->cursorPosition();
       
  1378     QValidator::State state = QValidator::Acceptable;
       
  1379     return d->validateAndInterpret(copy, pos, state);
       
  1380 }
       
  1381 
       
  1382 /*!
       
  1383   \reimp
       
  1384 */
       
  1385 
       
  1386 QValidator::State QDateTimeEdit::validate(QString &text, int &pos) const
       
  1387 {
       
  1388     Q_D(const QDateTimeEdit);
       
  1389     QValidator::State state;
       
  1390     d->validateAndInterpret(text, pos, state);
       
  1391     return state;
       
  1392 }
       
  1393 
       
  1394 /*!
       
  1395   \reimp
       
  1396 */
       
  1397 
       
  1398 
       
  1399 void QDateTimeEdit::fixup(QString &input) const
       
  1400 {
       
  1401     Q_D(const QDateTimeEdit);
       
  1402     QValidator::State state;
       
  1403     int copy = d->edit->cursorPosition();
       
  1404 
       
  1405     d->validateAndInterpret(input, copy, state, true);
       
  1406 }
       
  1407 
       
  1408 
       
  1409 /*!
       
  1410   \reimp
       
  1411 */
       
  1412 
       
  1413 QDateTimeEdit::StepEnabled QDateTimeEdit::stepEnabled() const
       
  1414 {
       
  1415     Q_D(const QDateTimeEdit);
       
  1416     if (d->readOnly)
       
  1417         return StepEnabled(0);
       
  1418     if (d->specialValue()) {
       
  1419         return (d->minimum == d->maximum ? StepEnabled(0) : StepEnabled(StepUpEnabled));
       
  1420     }
       
  1421 
       
  1422     QAbstractSpinBox::StepEnabled ret = 0;
       
  1423 
       
  1424 #ifdef QT_KEYPAD_NAVIGATION
       
  1425     if (QApplication::keypadNavigationEnabled() && !hasEditFocus()) {
       
  1426         if (d->wrapping)
       
  1427             return StepEnabled(StepUpEnabled | StepDownEnabled);
       
  1428         // 3 cases.  date, time, datetime.  each case look
       
  1429         // at just the relavant component.
       
  1430         QVariant max, min, val;
       
  1431         if (!(d->sections & DateSections_Mask)) {
       
  1432             // time only, no date
       
  1433             max = d->maximum.toTime();
       
  1434             min = d->minimum.toTime();
       
  1435             val = d->value.toTime();
       
  1436         } else if (!(d->sections & TimeSections_Mask)) {
       
  1437             // date only, no time
       
  1438             max = d->maximum.toDate();
       
  1439             min = d->minimum.toDate();
       
  1440             val = d->value.toDate();
       
  1441         } else {
       
  1442             // both
       
  1443             max = d->maximum;
       
  1444             min = d->minimum;
       
  1445             val = d->value;
       
  1446         }
       
  1447         if (val != min)
       
  1448             ret |= QAbstractSpinBox::StepDownEnabled;
       
  1449         if (val != max)
       
  1450             ret |= QAbstractSpinBox::StepUpEnabled;
       
  1451         return ret;
       
  1452     }
       
  1453 #endif
       
  1454     switch (d->sectionType(d->currentSectionIndex)) {
       
  1455     case QDateTimeParser::NoSection:
       
  1456     case QDateTimeParser::FirstSection:
       
  1457     case QDateTimeParser::LastSection: return 0;
       
  1458     default: break;
       
  1459     }
       
  1460     if (d->wrapping)
       
  1461         return StepEnabled(StepDownEnabled|StepUpEnabled);
       
  1462 
       
  1463     QVariant v = d->stepBy(d->currentSectionIndex, 1, true);
       
  1464     if (v != d->value) {
       
  1465         ret |= QAbstractSpinBox::StepUpEnabled;
       
  1466     }
       
  1467     v = d->stepBy(d->currentSectionIndex, -1, true);
       
  1468     if (v != d->value) {
       
  1469         ret |= QAbstractSpinBox::StepDownEnabled;
       
  1470     }
       
  1471 
       
  1472     return ret;
       
  1473 }
       
  1474 
       
  1475 
       
  1476 /*!
       
  1477   \reimp
       
  1478 */
       
  1479 
       
  1480 void QDateTimeEdit::mousePressEvent(QMouseEvent *event)
       
  1481 {
       
  1482     Q_D(QDateTimeEdit);
       
  1483     if (!d->calendarPopupEnabled()) {
       
  1484         QAbstractSpinBox::mousePressEvent(event);
       
  1485         return;
       
  1486     }
       
  1487     d->updateHoverControl(event->pos());
       
  1488     if (d->hoverControl == QStyle::SC_ComboBoxArrow) {
       
  1489         event->accept();
       
  1490         if (d->readOnly) {
       
  1491             return;
       
  1492         }
       
  1493         d->updateArrow(QStyle::State_Sunken);
       
  1494         d->initCalendarPopup();
       
  1495         d->positionCalendarPopup();
       
  1496         //Show the calendar
       
  1497         d->monthCalendar->show();
       
  1498     } else {
       
  1499         QAbstractSpinBox::mousePressEvent(event);
       
  1500     }
       
  1501 }
       
  1502 
       
  1503 /*!
       
  1504   \class QTimeEdit
       
  1505   \brief The QTimeEdit class provides a widget for editing times based on
       
  1506   the QDateTimeEdit widget.
       
  1507 
       
  1508   \ingroup basicwidgets
       
  1509 
       
  1510 
       
  1511   Many of the properties and functions provided by QTimeEdit are implemented in
       
  1512   QDateTimeEdit. The following properties are most relevant to users of this
       
  1513   class:
       
  1514 
       
  1515   \list
       
  1516   \o \l{QDateTimeEdit::time}{time} holds the date displayed by the widget.
       
  1517   \o \l{QDateTimeEdit::minimumTime}{minimumTime} defines the minimum (earliest) time
       
  1518      that can be set by the user.
       
  1519   \o \l{QDateTimeEdit::maximumTime}{maximumTime} defines the maximum (latest) time
       
  1520      that can be set by the user.
       
  1521   \o \l{QDateTimeEdit::displayFormat}{displayFormat} contains a string that is used
       
  1522      to format the time displayed in the widget.
       
  1523   \endlist
       
  1524 
       
  1525   \table 100%
       
  1526   \row \o \inlineimage windowsxp-timeedit.png Screenshot of a Windows XP style time editing widget
       
  1527        \o A time editing widget shown in the \l{Windows XP Style Widget Gallery}{Windows XP widget style}.
       
  1528   \row \o \inlineimage macintosh-timeedit.png Screenshot of a Macintosh style time editing widget
       
  1529        \o A time editing widget shown in the \l{Macintosh Style Widget Gallery}{Macintosh widget style}.
       
  1530   \row \o \inlineimage plastique-timeedit.png Screenshot of a Plastique style time editing widget
       
  1531        \o A time editing widget shown in the \l{Plastique Style Widget Gallery}{Plastique widget style}.
       
  1532   \endtable
       
  1533 
       
  1534   \sa QDateEdit, QDateTimeEdit
       
  1535 */
       
  1536 
       
  1537 /*!
       
  1538   Constructs an empty time editor with a \a parent.
       
  1539 */
       
  1540 
       
  1541 
       
  1542 QTimeEdit::QTimeEdit(QWidget *parent)
       
  1543     : QDateTimeEdit(QDATETIMEEDIT_TIME_MIN, QVariant::Time, parent)
       
  1544 {
       
  1545 }
       
  1546 
       
  1547 /*!
       
  1548   Constructs an empty time editor with a \a parent. The time is set
       
  1549   to \a time.
       
  1550 */
       
  1551 
       
  1552 QTimeEdit::QTimeEdit(const QTime &time, QWidget *parent)
       
  1553     : QDateTimeEdit(time, QVariant::Time, parent)
       
  1554 {
       
  1555 }
       
  1556 
       
  1557 /*!
       
  1558     \property QTimeEdit::time
       
  1559     \brief the QTime that is shown in the widget
       
  1560 
       
  1561     By default, this property contains a time of 00:00:00 and 0 milliseconds.
       
  1562 */
       
  1563 
       
  1564 
       
  1565 /*!
       
  1566   \class QDateEdit
       
  1567   \brief The QDateEdit class provides a widget for editing dates based on
       
  1568   the QDateTimeEdit widget.
       
  1569 
       
  1570   \ingroup basicwidgets
       
  1571 
       
  1572 
       
  1573   Many of the properties and functions provided by QDateEdit are implemented in
       
  1574   QDateTimeEdit. The following properties are most relevant to users of this
       
  1575   class:
       
  1576 
       
  1577   \list
       
  1578   \o \l{QDateTimeEdit::date}{date} holds the date displayed by the widget.
       
  1579   \o \l{QDateTimeEdit::minimumDate}{minimumDate} defines the minimum (earliest)
       
  1580      date that can be set by the user.
       
  1581   \o \l{QDateTimeEdit::maximumDate}{maximumDate} defines the maximum (latest) date
       
  1582      that can be set by the user.
       
  1583   \o \l{QDateTimeEdit::displayFormat}{displayFormat} contains a string that is used
       
  1584      to format the date displayed in the widget.
       
  1585   \endlist
       
  1586 
       
  1587   \table 100%
       
  1588   \row \o \inlineimage windowsxp-dateedit.png Screenshot of a Windows XP style date editing widget
       
  1589        \o A date editing widget shown in the \l{Windows XP Style Widget Gallery}{Windows XP widget style}.
       
  1590   \row \o \inlineimage macintosh-dateedit.png Screenshot of a Macintosh style date editing widget
       
  1591        \o A date editing widget shown in the \l{Macintosh Style Widget Gallery}{Macintosh widget style}.
       
  1592   \row \o \inlineimage plastique-dateedit.png Screenshot of a Plastique style date editing widget
       
  1593        \o A date editing widget shown in the \l{Plastique Style Widget Gallery}{Plastique widget style}.
       
  1594   \endtable
       
  1595 
       
  1596   \sa QTimeEdit, QDateTimeEdit
       
  1597 */
       
  1598 
       
  1599 /*!
       
  1600   Constructs an empty date editor with a \a parent.
       
  1601 */
       
  1602 
       
  1603 QDateEdit::QDateEdit(QWidget *parent)
       
  1604     : QDateTimeEdit(QDATETIMEEDIT_DATE_INITIAL, QVariant::Date, parent)
       
  1605 {
       
  1606 }
       
  1607 
       
  1608 /*!
       
  1609   Constructs an empty date editor with a \a parent. The date is set
       
  1610   to \a date.
       
  1611 */
       
  1612 
       
  1613 QDateEdit::QDateEdit(const QDate &date, QWidget *parent)
       
  1614     : QDateTimeEdit(date, QVariant::Date, parent)
       
  1615 {
       
  1616 }
       
  1617 
       
  1618 /*!
       
  1619     \property QDateEdit::date
       
  1620     \brief the QDate that is shown in the widget
       
  1621 
       
  1622     By default, this property contains a date referring to January 1, 2000.
       
  1623 */
       
  1624 
       
  1625 
       
  1626 // --- QDateTimeEditPrivate ---
       
  1627 
       
  1628 /*!
       
  1629   \internal
       
  1630   Constructs a QDateTimeEditPrivate object
       
  1631 */
       
  1632 
       
  1633 
       
  1634 QDateTimeEditPrivate::QDateTimeEditPrivate()
       
  1635     : QDateTimeParser(QVariant::DateTime, QDateTimeParser::DateTimeEdit)
       
  1636 {
       
  1637     hasHadFocus = false;
       
  1638     formatExplicitlySet = false;
       
  1639     cacheGuard = false;
       
  1640     fixday = true;
       
  1641     type = QVariant::DateTime;
       
  1642     sections = 0;
       
  1643     cachedDay = -1;
       
  1644     currentSectionIndex = FirstSectionIndex;
       
  1645 
       
  1646     first.type = FirstSection;
       
  1647     last.type = LastSection;
       
  1648     none.type = NoSection;
       
  1649     first.pos = 0;
       
  1650     last.pos = -1;
       
  1651     none.pos = -1;
       
  1652     sections = 0;
       
  1653     calendarPopup = false;
       
  1654     minimum = QDATETIMEEDIT_COMPAT_DATETIME_MIN;
       
  1655     maximum = QDATETIMEEDIT_DATETIME_MAX;
       
  1656     arrowState = QStyle::State_None;
       
  1657     monthCalendar = 0;
       
  1658     readLocaleSettings();
       
  1659 
       
  1660 #ifdef QT_KEYPAD_NAVIGATION
       
  1661     focusOnButton = false;
       
  1662 #endif
       
  1663 }
       
  1664 
       
  1665 void QDateTimeEditPrivate::updateTimeSpec()
       
  1666 {
       
  1667     minimum = minimum.toDateTime().toTimeSpec(spec);
       
  1668     maximum = maximum.toDateTime().toTimeSpec(spec);
       
  1669     value = value.toDateTime().toTimeSpec(spec);
       
  1670 }
       
  1671 
       
  1672 void QDateTimeEditPrivate::updateEdit()
       
  1673 {
       
  1674     const QString newText = (specialValue() ? specialValueText : textFromValue(value));
       
  1675     if (newText == displayText())
       
  1676         return;
       
  1677     int selsize = edit->selectedText().size();
       
  1678     const bool sb = edit->blockSignals(true);
       
  1679 
       
  1680     edit->setText(newText);
       
  1681 
       
  1682     if (!specialValue()
       
  1683 #ifdef QT_KEYPAD_NAVIGATION
       
  1684         && !(QApplication::keypadNavigationEnabled() && !edit->hasEditFocus())
       
  1685 #endif
       
  1686             ) {
       
  1687         int cursor = sectionPos(currentSectionIndex);
       
  1688         QDTEDEBUG << "cursor is " << cursor << currentSectionIndex;
       
  1689         cursor = qBound(0, cursor, displayText().size());
       
  1690         QDTEDEBUG << cursor;
       
  1691         if (selsize > 0) {
       
  1692             edit->setSelection(cursor, selsize);
       
  1693             QDTEDEBUG << cursor << selsize;
       
  1694         } else {
       
  1695             edit->setCursorPosition(cursor);
       
  1696             QDTEDEBUG << cursor;
       
  1697 
       
  1698         }
       
  1699     }
       
  1700     edit->blockSignals(sb);
       
  1701 }
       
  1702 
       
  1703 
       
  1704 /*!
       
  1705   \internal
       
  1706 
       
  1707   Selects the section \a s. If \a forward is false selects backwards.
       
  1708 */
       
  1709 
       
  1710 void QDateTimeEditPrivate::setSelected(int sectionIndex, bool forward)
       
  1711 {
       
  1712     if (specialValue()
       
  1713 #ifdef QT_KEYPAD_NAVIGATION
       
  1714         || (QApplication::keypadNavigationEnabled() && !edit->hasEditFocus())
       
  1715 #endif
       
  1716         ) {
       
  1717         edit->selectAll();
       
  1718     } else {
       
  1719         const SectionNode &node = sectionNode(sectionIndex);
       
  1720         if (node.type == NoSection || node.type == LastSection || node.type == FirstSection)
       
  1721             return;
       
  1722 
       
  1723         updateCache(value, displayText());
       
  1724         const int size = sectionSize(sectionIndex);
       
  1725         if (forward) {
       
  1726             edit->setSelection(sectionPos(node), size);
       
  1727         } else {
       
  1728             edit->setSelection(sectionPos(node) + size, -size);
       
  1729         }
       
  1730     }
       
  1731 }
       
  1732 
       
  1733 /*!
       
  1734   \internal
       
  1735 
       
  1736   Returns the section at index \a index or NoSection if there are no sections there.
       
  1737 */
       
  1738 
       
  1739 int QDateTimeEditPrivate::sectionAt(int pos) const
       
  1740 {
       
  1741     if (pos < separators.first().size()) {
       
  1742         return (pos == 0 ? FirstSectionIndex : NoSectionIndex);
       
  1743     } else if (displayText().size() - pos < separators.last().size() + 1) {
       
  1744         if (separators.last().size() == 0) {
       
  1745             return sectionNodes.count() - 1;
       
  1746         }
       
  1747         return (pos == displayText().size() ? LastSectionIndex : NoSectionIndex);
       
  1748     }
       
  1749     updateCache(value, displayText());
       
  1750 
       
  1751     for (int i=0; i<sectionNodes.size(); ++i) {
       
  1752         const int tmp = sectionPos(i);
       
  1753         if (pos < tmp + sectionSize(i)) {
       
  1754             return (pos < tmp ? -1 : i);
       
  1755         }
       
  1756     }
       
  1757     return -1;
       
  1758 }
       
  1759 
       
  1760 /*!
       
  1761   \internal
       
  1762 
       
  1763   Returns the closest section of index \a index. Searches forward
       
  1764   for a section if \a forward is true. Otherwise searches backwards.
       
  1765 */
       
  1766 
       
  1767 int QDateTimeEditPrivate::closestSection(int pos, bool forward) const
       
  1768 {
       
  1769     Q_ASSERT(pos >= 0);
       
  1770     if (pos < separators.first().size()) {
       
  1771         return forward ? 0 : FirstSectionIndex;
       
  1772     } else if (displayText().size() - pos < separators.last().size() + 1) {
       
  1773         return forward ? LastSectionIndex : sectionNodes.size() - 1;
       
  1774     }
       
  1775     updateCache(value, displayText());
       
  1776     for (int i=0; i<sectionNodes.size(); ++i) {
       
  1777         const int tmp = sectionPos(sectionNodes.at(i));
       
  1778         if (pos < tmp + sectionSize(i)) {
       
  1779             if (pos < tmp && !forward) {
       
  1780                 return i-1;
       
  1781             }
       
  1782             return i;
       
  1783         } else if (i == sectionNodes.size() - 1 && pos > tmp) {
       
  1784             return i;
       
  1785         }
       
  1786     }
       
  1787     qWarning("QDateTimeEdit: Internal Error: closestSection returned NoSection");
       
  1788     return NoSectionIndex;
       
  1789 }
       
  1790 
       
  1791 /*!
       
  1792   \internal
       
  1793 
       
  1794   Returns a copy of the section that is before or after \a current, depending on \a forward.
       
  1795 */
       
  1796 
       
  1797 int QDateTimeEditPrivate::nextPrevSection(int current, bool forward) const
       
  1798 {
       
  1799     Q_Q(const QDateTimeEdit);
       
  1800     if (q->isRightToLeft())
       
  1801         forward = !forward;
       
  1802 
       
  1803     switch (current) {
       
  1804     case FirstSectionIndex: return forward ? 0 : FirstSectionIndex;
       
  1805     case LastSectionIndex: return (forward ? LastSectionIndex : sectionNodes.size() - 1);
       
  1806     case NoSectionIndex: return FirstSectionIndex;
       
  1807     default: break;
       
  1808     }
       
  1809     Q_ASSERT(current >= 0 && current < sectionNodes.size());
       
  1810 
       
  1811     current += (forward ? 1 : -1);
       
  1812     if (current >= sectionNodes.size()) {
       
  1813         return LastSectionIndex;
       
  1814     } else if (current < 0) {
       
  1815         return FirstSectionIndex;
       
  1816     }
       
  1817 
       
  1818     return current;
       
  1819 }
       
  1820 
       
  1821 /*!
       
  1822   \internal
       
  1823 
       
  1824   Clears the text of section \a s.
       
  1825 */
       
  1826 
       
  1827 void QDateTimeEditPrivate::clearSection(int index)
       
  1828 {
       
  1829     const QLatin1Char space(' ');
       
  1830     int cursorPos = edit->cursorPosition();
       
  1831     bool blocked = edit->blockSignals(true);
       
  1832     QString t = edit->text();
       
  1833     const int pos = sectionPos(index);
       
  1834     if (pos == -1) {
       
  1835         qWarning("QDateTimeEdit: Internal error (%s:%d)", __FILE__, __LINE__);
       
  1836         return;
       
  1837     }
       
  1838     const int size = sectionSize(index);
       
  1839     t.replace(pos, size, QString().fill(space, size));
       
  1840     edit->setText(t);
       
  1841     edit->setCursorPosition(cursorPos);
       
  1842     QDTEDEBUG << cursorPos;
       
  1843 
       
  1844     edit->blockSignals(blocked);
       
  1845 }
       
  1846 
       
  1847 
       
  1848 /*!
       
  1849   \internal
       
  1850 
       
  1851   updates the cached values
       
  1852 */
       
  1853 
       
  1854 void QDateTimeEditPrivate::updateCache(const QVariant &val, const QString &str) const
       
  1855 {
       
  1856     if (val != cachedValue || str != cachedText || cacheGuard) {
       
  1857         cacheGuard = true;
       
  1858         QString copy = str;
       
  1859         int unused = edit->cursorPosition();
       
  1860         QValidator::State unusedState;
       
  1861         validateAndInterpret(copy, unused, unusedState);
       
  1862         cacheGuard = false;
       
  1863     }
       
  1864 }
       
  1865 
       
  1866 /*!
       
  1867   \internal
       
  1868 
       
  1869   parses and validates \a input
       
  1870 */
       
  1871 
       
  1872 QDateTime QDateTimeEditPrivate::validateAndInterpret(QString &input, int &position,
       
  1873                                                      QValidator::State &state, bool fixup) const
       
  1874 {
       
  1875     if (input.isEmpty()) {
       
  1876         if (sectionNodes.size() == 1 || !specialValueText.isEmpty()) {
       
  1877             state = QValidator::Intermediate;
       
  1878         } else {
       
  1879             state = QValidator::Invalid;
       
  1880         }
       
  1881         return getZeroVariant().toDateTime();
       
  1882     } else if (cachedText == input && !fixup) {
       
  1883         state = cachedState;
       
  1884         return cachedValue.toDateTime();
       
  1885     } else if (!specialValueText.isEmpty()) {
       
  1886         bool changeCase = false;
       
  1887         const int max = qMin(specialValueText.size(), input.size());
       
  1888         int i;
       
  1889         for (i=0; i<max; ++i) {
       
  1890             const QChar ic = input.at(i);
       
  1891             const QChar sc = specialValueText.at(i);
       
  1892             if (ic != sc) {
       
  1893                 if (sc.toLower() == ic.toLower()) {
       
  1894                     changeCase = true;
       
  1895                 } else {
       
  1896                     break;
       
  1897                 }
       
  1898             }
       
  1899         }
       
  1900         if (i == max) {
       
  1901             state = specialValueText.size() == input.size() ? QValidator::Acceptable : QValidator::Intermediate;
       
  1902             if (changeCase) {
       
  1903                 input = specialValueText.left(max);
       
  1904             }
       
  1905             return minimum.toDateTime();
       
  1906         }
       
  1907     }
       
  1908     StateNode tmp = parse(input, position, value.toDateTime(), fixup);
       
  1909     input = tmp.input;
       
  1910     state = QValidator::State(int(tmp.state));
       
  1911     if (state == QValidator::Acceptable) {
       
  1912         if (tmp.conflicts && conflictGuard != tmp.value) {
       
  1913             conflictGuard = tmp.value;
       
  1914             clearCache();
       
  1915             input = textFromValue(tmp.value);
       
  1916             updateCache(tmp.value, input);
       
  1917             conflictGuard.clear();
       
  1918         } else {
       
  1919             cachedText = input;
       
  1920             cachedState = state;
       
  1921             cachedValue = tmp.value;
       
  1922         }
       
  1923     } else {
       
  1924         clearCache();
       
  1925     }
       
  1926     return (tmp.value.isNull() ? getZeroVariant().toDateTime() : tmp.value);
       
  1927 }
       
  1928 
       
  1929 
       
  1930 /*!
       
  1931   \internal
       
  1932 */
       
  1933 
       
  1934 QString QDateTimeEditPrivate::textFromValue(const QVariant &f) const
       
  1935 {
       
  1936     Q_Q(const QDateTimeEdit);
       
  1937     return q->textFromDateTime(f.toDateTime());
       
  1938 }
       
  1939 
       
  1940 /*!
       
  1941   \internal
       
  1942 
       
  1943   This function's name is slightly confusing; it is not to be confused
       
  1944   with QAbstractSpinBox::valueFromText().
       
  1945 */
       
  1946 
       
  1947 QVariant QDateTimeEditPrivate::valueFromText(const QString &f) const
       
  1948 {
       
  1949     Q_Q(const QDateTimeEdit);
       
  1950     return q->dateTimeFromText(f).toTimeSpec(spec);
       
  1951 }
       
  1952 
       
  1953 
       
  1954 /*!
       
  1955   \internal
       
  1956 
       
  1957   Internal function called by QDateTimeEdit::stepBy(). Also takes a
       
  1958   Section for which section to step on and a bool \a test for
       
  1959   whether or not to modify the internal cachedDay variable. This is
       
  1960   necessary because the function is called from the const function
       
  1961   QDateTimeEdit::stepEnabled() as well as QDateTimeEdit::stepBy().
       
  1962 */
       
  1963 
       
  1964 QDateTime QDateTimeEditPrivate::stepBy(int sectionIndex, int steps, bool test) const
       
  1965 {
       
  1966     Q_Q(const QDateTimeEdit);
       
  1967     QDateTime v = value.toDateTime();
       
  1968     QString str = displayText();
       
  1969     int pos = edit->cursorPosition();
       
  1970     const SectionNode sn = sectionNode(sectionIndex);
       
  1971 
       
  1972     int val;
       
  1973     // to make sure it behaves reasonably when typing something and then stepping in non-tracking mode
       
  1974     if (!test && pendingEmit) {
       
  1975         if (q->validate(str, pos) != QValidator::Acceptable) {
       
  1976             v = value.toDateTime();
       
  1977         } else {
       
  1978             v = q->dateTimeFromText(str);
       
  1979         }
       
  1980         val = getDigit(v, sectionIndex);
       
  1981     } else {
       
  1982         val = getDigit(v, sectionIndex);
       
  1983     }
       
  1984 
       
  1985     val += steps;
       
  1986 
       
  1987     const int min = absoluteMin(sectionIndex);
       
  1988     const int max = absoluteMax(sectionIndex, value.toDateTime());
       
  1989 
       
  1990     if (val < min) {
       
  1991         val = (wrapping ? max - (min - val) + 1 : min);
       
  1992     } else if (val > max) {
       
  1993         val = (wrapping ? min + val - max - 1 : max);
       
  1994     }
       
  1995 
       
  1996 
       
  1997     const int oldDay = v.date().day();
       
  1998 
       
  1999     setDigit(v, sectionIndex, val);
       
  2000     // if this sets year or month it will make
       
  2001     // sure that days are lowered if needed.
       
  2002 
       
  2003     const QDateTime minimumDateTime = minimum.toDateTime();
       
  2004     const QDateTime maximumDateTime = maximum.toDateTime();
       
  2005     // changing one section should only modify that section, if possible
       
  2006     if (sn.type != AmPmSection && (v < minimumDateTime || v > maximumDateTime)) {
       
  2007         const int localmin = getDigit(minimumDateTime, sectionIndex);
       
  2008         const int localmax = getDigit(maximumDateTime, sectionIndex);
       
  2009 
       
  2010         if (wrapping) {
       
  2011             // just because we hit the roof in one direction, it
       
  2012             // doesn't mean that we hit the floor in the other
       
  2013             if (steps > 0) {
       
  2014                 setDigit(v, sectionIndex, min);
       
  2015                 if (!(sn.type & (DaySection|DayOfWeekSection)) && sections & DateSectionMask) {
       
  2016                     const int daysInMonth = v.date().daysInMonth();
       
  2017                     if (v.date().day() < oldDay && v.date().day() < daysInMonth) {
       
  2018                         const int adds = qMin(oldDay, daysInMonth);
       
  2019                         v = v.addDays(adds - v.date().day());
       
  2020                     }
       
  2021                 }
       
  2022 
       
  2023                 if (v < minimumDateTime) {
       
  2024                     setDigit(v, sectionIndex, localmin);
       
  2025                     if (v < minimumDateTime)
       
  2026                         setDigit(v, sectionIndex, localmin + 1);
       
  2027                 }
       
  2028             } else {
       
  2029                 setDigit(v, sectionIndex, max);
       
  2030                 if (!(sn.type & (DaySection|DayOfWeekSection)) && sections & DateSectionMask) {
       
  2031                     const int daysInMonth = v.date().daysInMonth();
       
  2032                     if (v.date().day() < oldDay && v.date().day() < daysInMonth) {
       
  2033                         const int adds = qMin(oldDay, daysInMonth);
       
  2034                         v = v.addDays(adds - v.date().day());
       
  2035                     }
       
  2036                 }
       
  2037 
       
  2038                 if (v > maximumDateTime) {
       
  2039                     setDigit(v, sectionIndex, localmax);
       
  2040                     if (v > maximumDateTime)
       
  2041                         setDigit(v, sectionIndex, localmax - 1);
       
  2042                 }
       
  2043             }
       
  2044         } else {
       
  2045             setDigit(v, sectionIndex, (steps > 0 ? localmax : localmin));
       
  2046         }
       
  2047     }
       
  2048     if (!test && oldDay != v.date().day() && !(sn.type & (DaySection|DayOfWeekSection))) {
       
  2049         // this should not happen when called from stepEnabled
       
  2050         cachedDay = qMax<int>(oldDay, cachedDay);
       
  2051     }
       
  2052 
       
  2053     if (v < minimumDateTime) {
       
  2054         if (wrapping) {
       
  2055             QDateTime t = v;
       
  2056             setDigit(t, sectionIndex, steps < 0 ? max : min);
       
  2057             bool mincmp = (t >= minimumDateTime);
       
  2058             bool maxcmp = (t <= maximumDateTime);
       
  2059             if (!mincmp || !maxcmp) {
       
  2060                 setDigit(t, sectionIndex, getDigit(steps < 0
       
  2061                                                    ? maximumDateTime
       
  2062                                                    : minimumDateTime, sectionIndex));
       
  2063                 mincmp = (t >= minimumDateTime);
       
  2064                 maxcmp = (t <= maximumDateTime);
       
  2065             }
       
  2066             if (mincmp && maxcmp) {
       
  2067                 v = t;
       
  2068             }
       
  2069         } else {
       
  2070             v = value.toDateTime();
       
  2071         }
       
  2072     } else if (v > maximumDateTime) {
       
  2073         if (wrapping) {
       
  2074             QDateTime t = v;
       
  2075             setDigit(t, sectionIndex, steps > 0 ? min : max);
       
  2076             bool mincmp = (t >= minimumDateTime);
       
  2077             bool maxcmp = (t <= maximumDateTime);
       
  2078             if (!mincmp || !maxcmp) {
       
  2079                 setDigit(t, sectionIndex, getDigit(steps > 0 ?
       
  2080                                                    minimumDateTime :
       
  2081                                                    maximumDateTime, sectionIndex));
       
  2082                 mincmp = (t >= minimumDateTime);
       
  2083                 maxcmp = (t <= maximumDateTime);
       
  2084             }
       
  2085             if (mincmp && maxcmp) {
       
  2086                 v = t;
       
  2087             }
       
  2088         } else {
       
  2089             v = value.toDateTime();
       
  2090         }
       
  2091     }
       
  2092 
       
  2093     const QDateTime ret = bound(v, value, steps).toDateTime().toTimeSpec(spec);
       
  2094     return ret;
       
  2095 }
       
  2096 
       
  2097 /*!
       
  2098   \internal
       
  2099 */
       
  2100 
       
  2101 void QDateTimeEditPrivate::emitSignals(EmitPolicy ep, const QVariant &old)
       
  2102 {
       
  2103     Q_Q(QDateTimeEdit);
       
  2104     if (ep == NeverEmit) {
       
  2105         return;
       
  2106     }
       
  2107     pendingEmit = false;
       
  2108 
       
  2109     const bool dodate = value.toDate().isValid() && (sections & DateSectionMask);
       
  2110     const bool datechanged = (ep == AlwaysEmit || old.toDate() != value.toDate());
       
  2111     const bool dotime = value.toTime().isValid() && (sections & TimeSectionMask);
       
  2112     const bool timechanged = (ep == AlwaysEmit || old.toTime() != value.toTime());
       
  2113 
       
  2114     updateCache(value, displayText());
       
  2115 
       
  2116     syncCalendarWidget();
       
  2117     if (datechanged || timechanged)
       
  2118         emit q->dateTimeChanged(value.toDateTime());
       
  2119     if (dodate && datechanged)
       
  2120         emit q->dateChanged(value.toDate());
       
  2121     if (dotime && timechanged)
       
  2122         emit q->timeChanged(value.toTime());
       
  2123 
       
  2124 }
       
  2125 
       
  2126 /*!
       
  2127   \internal
       
  2128 */
       
  2129 
       
  2130 void QDateTimeEditPrivate::_q_editorCursorPositionChanged(int oldpos, int newpos)
       
  2131 {
       
  2132     if (ignoreCursorPositionChanged || specialValue())
       
  2133         return;
       
  2134     const QString oldText = displayText();
       
  2135     updateCache(value, oldText);
       
  2136 
       
  2137     const bool allowChange = !edit->hasSelectedText();
       
  2138     const bool forward = oldpos <= newpos;
       
  2139     ignoreCursorPositionChanged = true;
       
  2140     int s = sectionAt(newpos);
       
  2141     if (s == NoSectionIndex && forward && newpos > 0) {
       
  2142         s = sectionAt(newpos - 1);
       
  2143     }
       
  2144 
       
  2145     int c = newpos;
       
  2146 
       
  2147     const int selstart = edit->selectionStart();
       
  2148     const int selSection = sectionAt(selstart);
       
  2149     const int l = selSection != -1 ? sectionSize(selSection) : 0;
       
  2150 
       
  2151     if (s == NoSectionIndex) {
       
  2152         if (l > 0 && selstart == sectionPos(selSection) && edit->selectedText().size() == l) {
       
  2153             s = selSection;
       
  2154             if (allowChange)
       
  2155                 setSelected(selSection, true);
       
  2156             c = -1;
       
  2157         } else {
       
  2158             int closest = closestSection(newpos, forward);
       
  2159             c = sectionPos(closest) + (forward ? 0 : qMax<int>(0, sectionSize(closest)));
       
  2160 
       
  2161             if (allowChange) {
       
  2162                 edit->setCursorPosition(c);
       
  2163                 QDTEDEBUG << c;
       
  2164             }
       
  2165             s = closest;
       
  2166         }
       
  2167     }
       
  2168 
       
  2169     if (allowChange && currentSectionIndex != s) {
       
  2170         interpret(EmitIfChanged);
       
  2171     }
       
  2172     if (c == -1) {
       
  2173         setSelected(s, true);
       
  2174     } else if (!edit->hasSelectedText()) {
       
  2175         if (oldpos < newpos) {
       
  2176             edit->setCursorPosition(displayText().size() - (oldText.size() - c));
       
  2177         } else {
       
  2178             edit->setCursorPosition(c);
       
  2179         }
       
  2180     }
       
  2181 
       
  2182     QDTEDEBUG << "currentSectionIndex is set to" << sectionName(sectionType(s))
       
  2183               << oldpos << newpos
       
  2184               << "was" << sectionName(sectionType(currentSectionIndex));
       
  2185 
       
  2186     currentSectionIndex = s;
       
  2187     Q_ASSERT_X(currentSectionIndex < sectionNodes.size(),
       
  2188                "QDateTimeEditPrivate::_q_editorCursorPositionChanged()",
       
  2189                qPrintable(QString::fromAscii("Internal error (%1 %2)").
       
  2190                           arg(currentSectionIndex).
       
  2191                           arg(sectionNodes.size())));
       
  2192 
       
  2193     ignoreCursorPositionChanged = false;
       
  2194 }
       
  2195 
       
  2196 /*!
       
  2197   \internal
       
  2198 
       
  2199   Try to get the format from the local settings
       
  2200 */
       
  2201 void QDateTimeEditPrivate::readLocaleSettings()
       
  2202 {
       
  2203     const QLocale loc;
       
  2204     defaultTimeFormat = loc.timeFormat(QLocale::ShortFormat);
       
  2205     defaultDateFormat = loc.dateFormat(QLocale::ShortFormat);
       
  2206     defaultDateTimeFormat = loc.dateTimeFormat(QLocale::ShortFormat);
       
  2207 }
       
  2208 
       
  2209 QDateTimeEdit::Section QDateTimeEditPrivate::convertToPublic(QDateTimeParser::Section s)
       
  2210 {
       
  2211     switch (s & ~Internal) {
       
  2212     case AmPmSection: return QDateTimeEdit::AmPmSection;
       
  2213     case MSecSection: return QDateTimeEdit::MSecSection;
       
  2214     case SecondSection: return QDateTimeEdit::SecondSection;
       
  2215     case MinuteSection: return QDateTimeEdit::MinuteSection;
       
  2216     case DayOfWeekSection:
       
  2217     case DaySection: return QDateTimeEdit::DaySection;
       
  2218     case MonthSection: return QDateTimeEdit::MonthSection;
       
  2219     case YearSection2Digits:
       
  2220     case YearSection: return QDateTimeEdit::YearSection;
       
  2221     case Hour12Section:
       
  2222     case Hour24Section: return QDateTimeEdit::HourSection;
       
  2223     case FirstSection:
       
  2224     case NoSection:
       
  2225     case LastSection: break;
       
  2226     }
       
  2227     return QDateTimeEdit::NoSection;
       
  2228 }
       
  2229 
       
  2230 QDateTimeEdit::Sections QDateTimeEditPrivate::convertSections(QDateTimeParser::Sections s)
       
  2231 {
       
  2232     QDateTimeEdit::Sections ret = 0;
       
  2233     if (s & QDateTimeParser::MSecSection)
       
  2234         ret |= QDateTimeEdit::MSecSection;
       
  2235     if (s & QDateTimeParser::SecondSection)
       
  2236         ret |= QDateTimeEdit::SecondSection;
       
  2237     if (s & QDateTimeParser::MinuteSection)
       
  2238         ret |= QDateTimeEdit::MinuteSection;
       
  2239     if (s & (QDateTimeParser::Hour24Section|QDateTimeParser::Hour12Section))
       
  2240         ret |= QDateTimeEdit::HourSection;
       
  2241     if (s & QDateTimeParser::AmPmSection)
       
  2242         ret |= QDateTimeEdit::AmPmSection;
       
  2243     if (s & (QDateTimeParser::DaySection|QDateTimeParser::DayOfWeekSection))
       
  2244         ret |= QDateTimeEdit::DaySection;
       
  2245     if (s & QDateTimeParser::MonthSection)
       
  2246         ret |= QDateTimeEdit::MonthSection;
       
  2247     if (s & (QDateTimeParser::YearSection|QDateTimeParser::YearSection2Digits))
       
  2248         ret |= QDateTimeEdit::YearSection;
       
  2249 
       
  2250     return ret;
       
  2251 }
       
  2252 
       
  2253 /*!
       
  2254     \reimp
       
  2255 */
       
  2256 
       
  2257 void QDateTimeEdit::paintEvent(QPaintEvent *event)
       
  2258 {
       
  2259     Q_D(QDateTimeEdit);
       
  2260     if (!d->calendarPopupEnabled()) {
       
  2261         QAbstractSpinBox::paintEvent(event);
       
  2262         return;
       
  2263     }
       
  2264 
       
  2265     QStyleOptionSpinBox opt;
       
  2266     initStyleOption(&opt);
       
  2267 
       
  2268     QStyleOptionComboBox optCombo;
       
  2269 
       
  2270     optCombo.init(this);
       
  2271     optCombo.editable = true;
       
  2272 	optCombo.frame = opt.frame;
       
  2273     optCombo.subControls = opt.subControls;
       
  2274     optCombo.activeSubControls = opt.activeSubControls;
       
  2275     optCombo.state = opt.state;
       
  2276     if (d->readOnly) {
       
  2277         optCombo.state &= ~QStyle::State_Enabled;
       
  2278     }
       
  2279 
       
  2280     QPainter p(this);
       
  2281     style()->drawComplexControl(QStyle::CC_ComboBox, &optCombo, &p, this);
       
  2282 }
       
  2283 
       
  2284 QString QDateTimeEditPrivate::getAmPmText(AmPm ap, Case cs) const
       
  2285 {
       
  2286     if (ap == AmText) {
       
  2287         return (cs == UpperCase ? QDateTimeEdit::tr("AM") : QDateTimeEdit::tr("am"));
       
  2288     } else {
       
  2289         return (cs == UpperCase ? QDateTimeEdit::tr("PM") : QDateTimeEdit::tr("pm"));
       
  2290     }
       
  2291 }
       
  2292 
       
  2293 int QDateTimeEditPrivate::absoluteIndex(QDateTimeEdit::Section s, int index) const
       
  2294 {
       
  2295     for (int i=0; i<sectionNodes.size(); ++i) {
       
  2296         if (convertToPublic(sectionNodes.at(i).type) == s && index-- == 0) {
       
  2297             return i;
       
  2298         }
       
  2299     }
       
  2300     return NoSectionIndex;
       
  2301 }
       
  2302 
       
  2303 int QDateTimeEditPrivate::absoluteIndex(const SectionNode &s) const
       
  2304 {
       
  2305     return sectionNodes.indexOf(s);
       
  2306 }
       
  2307 
       
  2308 void QDateTimeEditPrivate::interpret(EmitPolicy ep)
       
  2309 {
       
  2310     Q_Q(QDateTimeEdit);
       
  2311     QString tmp = displayText();
       
  2312     int pos = edit->cursorPosition();
       
  2313     const QValidator::State state = q->validate(tmp, pos);
       
  2314     if (state != QValidator::Acceptable
       
  2315         && correctionMode == QAbstractSpinBox::CorrectToPreviousValue
       
  2316         && (state == QValidator::Invalid || !(fieldInfo(currentSectionIndex) & AllowPartial))) {
       
  2317         setValue(value, ep);
       
  2318         updateTimeSpec();
       
  2319     } else {
       
  2320         QAbstractSpinBoxPrivate::interpret(ep);
       
  2321     }
       
  2322 }
       
  2323 
       
  2324 void QDateTimeEditPrivate::clearCache() const
       
  2325 {
       
  2326     QAbstractSpinBoxPrivate::clearCache();
       
  2327     cachedDay = -1;
       
  2328 }
       
  2329 
       
  2330 /*!
       
  2331     Initialize \a option with the values from this QDataTimeEdit. This method
       
  2332     is useful for subclasses when they need a QStyleOptionSpinBox, but don't want
       
  2333     to fill in all the information themselves.
       
  2334 
       
  2335     \sa QStyleOption::initFrom()
       
  2336 */
       
  2337 void QDateTimeEdit::initStyleOption(QStyleOptionSpinBox *option) const
       
  2338 {
       
  2339     if (!option)
       
  2340         return;
       
  2341 
       
  2342     Q_D(const QDateTimeEdit);
       
  2343     QAbstractSpinBox::initStyleOption(option);
       
  2344     if (d->calendarPopupEnabled()) {
       
  2345         option->subControls = QStyle::SC_ComboBoxFrame | QStyle::SC_ComboBoxEditField
       
  2346                               | QStyle::SC_ComboBoxArrow;
       
  2347         if (d->arrowState == QStyle::State_Sunken)
       
  2348             option->state |= QStyle::State_Sunken;
       
  2349         else
       
  2350             option->state &= ~QStyle::State_Sunken;
       
  2351     }
       
  2352 }
       
  2353 
       
  2354 void QDateTimeEditPrivate::init(const QVariant &var)
       
  2355 {
       
  2356     Q_Q(QDateTimeEdit);
       
  2357     switch (var.type()) {
       
  2358     case QVariant::Date:
       
  2359         value = QDateTime(var.toDate(), QDATETIMEEDIT_TIME_MIN);
       
  2360         q->setDisplayFormat(defaultDateFormat);
       
  2361         if (sectionNodes.isEmpty()) // ### safeguard for broken locale
       
  2362             q->setDisplayFormat(QLatin1String("dd/MM/yyyy"));
       
  2363         break;
       
  2364     case QVariant::DateTime:
       
  2365         value = var;
       
  2366         q->setDisplayFormat(defaultDateTimeFormat);
       
  2367         if (sectionNodes.isEmpty()) // ### safeguard for broken locale
       
  2368             q->setDisplayFormat(QLatin1String("dd/MM/yyyy hh:mm:ss"));
       
  2369         break;
       
  2370     case QVariant::Time:
       
  2371         value = QDateTime(QDATETIMEEDIT_DATE_INITIAL, var.toTime());
       
  2372         q->setDisplayFormat(defaultTimeFormat);
       
  2373         if (sectionNodes.isEmpty()) // ### safeguard for broken locale
       
  2374             q->setDisplayFormat(QLatin1String("hh:mm:ss"));
       
  2375         break;
       
  2376     default:
       
  2377         Q_ASSERT_X(0, "QDateTimeEditPrivate::init", "Internal error");
       
  2378         break;
       
  2379     }
       
  2380 #ifdef QT_KEYPAD_NAVIGATION
       
  2381     if (QApplication::keypadNavigationEnabled())
       
  2382         q->setCalendarPopup(true);
       
  2383 #endif
       
  2384     updateTimeSpec();
       
  2385     q->setInputMethodHints(Qt::ImhPreferNumbers);
       
  2386     setLayoutItemMargins(QStyle::SE_DateTimeEditLayoutItem);
       
  2387 }
       
  2388 
       
  2389 void QDateTimeEditPrivate::_q_resetButton()
       
  2390 {
       
  2391     updateArrow(QStyle::State_None);
       
  2392 }
       
  2393 
       
  2394 void QDateTimeEditPrivate::updateArrow(QStyle::StateFlag state)
       
  2395 {
       
  2396     Q_Q(QDateTimeEdit);
       
  2397 
       
  2398     if (arrowState == state)
       
  2399         return;
       
  2400     arrowState = state;
       
  2401     if (arrowState != QStyle::State_None)
       
  2402         buttonState |= Mouse;
       
  2403     else {
       
  2404         buttonState = 0;
       
  2405         hoverControl = QStyle::SC_ComboBoxFrame;
       
  2406     }
       
  2407     q->update();
       
  2408 }
       
  2409 
       
  2410 /*!
       
  2411     \internal
       
  2412     Returns the hover control at \a pos.
       
  2413     This will update the hoverRect and hoverControl.
       
  2414 */
       
  2415 QStyle::SubControl QDateTimeEditPrivate::newHoverControl(const QPoint &pos)
       
  2416 {
       
  2417     if (!calendarPopupEnabled())
       
  2418         return QAbstractSpinBoxPrivate::newHoverControl(pos);
       
  2419 
       
  2420     Q_Q(QDateTimeEdit);
       
  2421 
       
  2422     QStyleOptionComboBox optCombo;
       
  2423     optCombo.init(q);
       
  2424     optCombo.editable = true;
       
  2425     optCombo.subControls = QStyle::SC_All;
       
  2426     hoverControl = q->style()->hitTestComplexControl(QStyle::CC_ComboBox, &optCombo, pos, q);
       
  2427     return hoverControl;
       
  2428 }
       
  2429 
       
  2430 void QDateTimeEditPrivate::updateEditFieldGeometry()
       
  2431 {
       
  2432     if (!calendarPopupEnabled()) {
       
  2433         QAbstractSpinBoxPrivate::updateEditFieldGeometry();
       
  2434         return;
       
  2435     }
       
  2436 
       
  2437     Q_Q(QDateTimeEdit);
       
  2438 
       
  2439     QStyleOptionComboBox optCombo;
       
  2440     optCombo.init(q);
       
  2441     optCombo.editable = true;
       
  2442     optCombo.subControls = QStyle::SC_ComboBoxEditField;
       
  2443     edit->setGeometry(q->style()->subControlRect(QStyle::CC_ComboBox, &optCombo,
       
  2444                                                  QStyle::SC_ComboBoxEditField, q));
       
  2445 }
       
  2446 
       
  2447 QVariant QDateTimeEditPrivate::getZeroVariant() const
       
  2448 {
       
  2449     Q_ASSERT(type == QVariant::DateTime);
       
  2450     return QDateTime(QDATETIMEEDIT_DATE_INITIAL, QTime(), spec);
       
  2451 }
       
  2452 
       
  2453 void QDateTimeEditPrivate::setRange(const QVariant &min, const QVariant &max)
       
  2454 {
       
  2455     QAbstractSpinBoxPrivate::setRange(min, max);
       
  2456     syncCalendarWidget();
       
  2457 }
       
  2458 
       
  2459 
       
  2460 bool QDateTimeEditPrivate::isSeparatorKey(const QKeyEvent *ke) const
       
  2461 {
       
  2462     if (!ke->text().isEmpty() && currentSectionIndex + 1 < sectionNodes.size() && currentSectionIndex >= 0) {
       
  2463         if (fieldInfo(currentSectionIndex) & Numeric) {
       
  2464             if (ke->text().at(0).isNumber())
       
  2465                 return false;
       
  2466         } else if (ke->text().at(0).isLetterOrNumber()) {
       
  2467             return false;
       
  2468         }
       
  2469         return separators.at(currentSectionIndex + 1).contains(ke->text());
       
  2470     }
       
  2471     return false;
       
  2472 }
       
  2473 
       
  2474 void QDateTimeEditPrivate::initCalendarPopup(QCalendarWidget *cw)
       
  2475 {
       
  2476     Q_Q(QDateTimeEdit);
       
  2477     if (!monthCalendar) {
       
  2478         monthCalendar = new QCalendarPopup(q, cw);
       
  2479         monthCalendar->setObjectName(QLatin1String("qt_datetimedit_calendar"));
       
  2480         QObject::connect(monthCalendar, SIGNAL(newDateSelected(QDate)), q, SLOT(setDate(QDate)));
       
  2481         QObject::connect(monthCalendar, SIGNAL(hidingCalendar(QDate)), q, SLOT(setDate(QDate)));
       
  2482         QObject::connect(monthCalendar, SIGNAL(activated(QDate)), q, SLOT(setDate(QDate)));
       
  2483         QObject::connect(monthCalendar, SIGNAL(activated(QDate)), monthCalendar, SLOT(close()));
       
  2484         QObject::connect(monthCalendar, SIGNAL(resetButton()), q, SLOT(_q_resetButton()));
       
  2485     } else if (cw) {
       
  2486         monthCalendar->setCalendarWidget(cw);
       
  2487     }
       
  2488     syncCalendarWidget();
       
  2489 }
       
  2490 
       
  2491 void QDateTimeEditPrivate::positionCalendarPopup()
       
  2492 {
       
  2493     Q_Q(QDateTimeEdit);
       
  2494     QPoint pos = (q->layoutDirection() == Qt::RightToLeft) ? q->rect().bottomRight() : q->rect().bottomLeft();
       
  2495     QPoint pos2 = (q->layoutDirection() == Qt::RightToLeft) ? q->rect().topRight() : q->rect().topLeft();
       
  2496     pos = q->mapToGlobal(pos);
       
  2497     pos2 = q->mapToGlobal(pos2);
       
  2498     QSize size = monthCalendar->sizeHint();
       
  2499     QRect screen = QApplication::desktop()->availableGeometry(pos);
       
  2500     //handle popup falling "off screen"
       
  2501     if (q->layoutDirection() == Qt::RightToLeft) {
       
  2502         pos.setX(pos.x()-size.width());
       
  2503         pos2.setX(pos2.x()-size.width());
       
  2504         if (pos.x() < screen.left())
       
  2505             pos.setX(qMax(pos.x(), screen.left()));
       
  2506         else if (pos.x()+size.width() > screen.right())
       
  2507             pos.setX(qMax(pos.x()-size.width(), screen.right()-size.width()));
       
  2508     } else {
       
  2509         if (pos.x()+size.width() > screen.right())
       
  2510             pos.setX(screen.right()-size.width());
       
  2511         pos.setX(qMax(pos.x(), screen.left()));
       
  2512     }
       
  2513     if (pos.y() + size.height() > screen.bottom())
       
  2514         pos.setY(pos2.y() - size.height());
       
  2515     else if (pos.y() < screen.top())
       
  2516         pos.setY(screen.top());
       
  2517     if (pos.y() < screen.top())
       
  2518         pos.setY(screen.top());
       
  2519     if (pos.y()+size.height() > screen.bottom())
       
  2520         pos.setY(screen.bottom()-size.height());
       
  2521     monthCalendar->move(pos);
       
  2522 }
       
  2523 
       
  2524 bool QDateTimeEditPrivate::calendarPopupEnabled() const
       
  2525 {
       
  2526     return (calendarPopup && (sections & (DateSectionMask)));
       
  2527 }
       
  2528 
       
  2529 void QDateTimeEditPrivate::syncCalendarWidget()
       
  2530 {
       
  2531     Q_Q(QDateTimeEdit);
       
  2532     if (monthCalendar) {
       
  2533         monthCalendar->setDateRange(q->minimumDate(), q->maximumDate());
       
  2534         monthCalendar->setDate(q->date());
       
  2535     }
       
  2536 }
       
  2537 
       
  2538 QCalendarPopup::QCalendarPopup(QWidget * parent, QCalendarWidget *cw)
       
  2539     : QWidget(parent, Qt::Popup), calendar(0)
       
  2540 {
       
  2541     setAttribute(Qt::WA_WindowPropagation);
       
  2542 
       
  2543     dateChanged = false;
       
  2544     if (!cw) {
       
  2545         cw = new QCalendarWidget(this);
       
  2546         cw->setVerticalHeaderFormat(QCalendarWidget::NoVerticalHeader);
       
  2547 #ifdef QT_KEYPAD_NAVIGATION
       
  2548         if (QApplication::keypadNavigationEnabled())
       
  2549             cw->setHorizontalHeaderFormat(QCalendarWidget::SingleLetterDayNames);
       
  2550 #endif
       
  2551     }
       
  2552     setCalendarWidget(cw);
       
  2553 }
       
  2554 
       
  2555 void QCalendarPopup::setCalendarWidget(QCalendarWidget *cw)
       
  2556 {
       
  2557     Q_ASSERT(cw);
       
  2558     QVBoxLayout *widgetLayout = qobject_cast<QVBoxLayout*>(layout());
       
  2559     if (!widgetLayout) {
       
  2560         widgetLayout = new QVBoxLayout(this);
       
  2561         widgetLayout->setMargin(0);
       
  2562         widgetLayout->setSpacing(0);
       
  2563     }
       
  2564     delete calendar;
       
  2565     calendar = cw;
       
  2566     widgetLayout->addWidget(calendar);
       
  2567 
       
  2568     connect(calendar, SIGNAL(activated(QDate)), this, SLOT(dateSelected(QDate)));
       
  2569     connect(calendar, SIGNAL(clicked(QDate)), this, SLOT(dateSelected(QDate)));
       
  2570     connect(calendar, SIGNAL(selectionChanged()), this, SLOT(dateSelectionChanged()));
       
  2571 
       
  2572     calendar->setFocus();
       
  2573 }
       
  2574 
       
  2575 
       
  2576 void QCalendarPopup::setDate(const QDate &date)
       
  2577 {
       
  2578     oldDate = date;
       
  2579     calendar->setSelectedDate(date);
       
  2580 }
       
  2581 
       
  2582 void QCalendarPopup::setDateRange(const QDate &min, const QDate &max)
       
  2583 {
       
  2584     calendar->setMinimumDate(min);
       
  2585     calendar->setMaximumDate(max);
       
  2586 }
       
  2587 
       
  2588 void QCalendarPopup::mousePressEvent(QMouseEvent *event)
       
  2589 {
       
  2590     QDateTimeEdit *dateTime = qobject_cast<QDateTimeEdit *>(parentWidget());
       
  2591     if (dateTime) {
       
  2592         QStyleOptionComboBox opt;
       
  2593         opt.init(dateTime);
       
  2594         QRect arrowRect = dateTime->style()->subControlRect(QStyle::CC_ComboBox, &opt,
       
  2595                                                             QStyle::SC_ComboBoxArrow, dateTime);
       
  2596         arrowRect.moveTo(dateTime->mapToGlobal(arrowRect .topLeft()));
       
  2597         if (arrowRect.contains(event->globalPos()) || rect().contains(event->pos()))
       
  2598             setAttribute(Qt::WA_NoMouseReplay);
       
  2599     }
       
  2600     QWidget::mousePressEvent(event);
       
  2601 }
       
  2602 
       
  2603 void QCalendarPopup::mouseReleaseEvent(QMouseEvent*)
       
  2604 {
       
  2605     emit resetButton();
       
  2606 }
       
  2607 
       
  2608 bool QCalendarPopup::event(QEvent *event)
       
  2609 {
       
  2610     if (event->type() == QEvent::KeyPress) {
       
  2611         QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
       
  2612         if (keyEvent->key()== Qt::Key_Escape)
       
  2613             dateChanged = false;
       
  2614     }
       
  2615     return QWidget::event(event);
       
  2616 }
       
  2617 
       
  2618 void QCalendarPopup::dateSelectionChanged()
       
  2619 {
       
  2620     dateChanged = true;
       
  2621     emit newDateSelected(calendar->selectedDate());
       
  2622 }
       
  2623 void QCalendarPopup::dateSelected(const QDate &date)
       
  2624 {
       
  2625     dateChanged = true;
       
  2626     emit activated(date);
       
  2627     close();
       
  2628 }
       
  2629 
       
  2630 void QCalendarPopup::hideEvent(QHideEvent *)
       
  2631 {
       
  2632     emit resetButton();
       
  2633     if (!dateChanged)
       
  2634         emit hidingCalendar(oldDate);
       
  2635 }
       
  2636 
       
  2637 QT_END_NAMESPACE
       
  2638 #include "moc_qdatetimeedit.cpp"
       
  2639 
       
  2640 #endif // QT_NO_DATETIMEEDIT