1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the QtGui module of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
43 #include <private/qdatetimeedit_p.h>
44 #include <qabstractspinbox.h>
45 #include <qapplication.h>
46 #include <qdatetimeedit.h>
47 #include <qdesktopwidget.h>
50 #include <qlineedit.h>
51 #include <private/qlineedit_p.h>
58 #ifndef QT_NO_DATETIMEEDIT
60 //#define QDATETIMEEDIT_QDTEDEBUG
61 #ifdef QDATETIMEEDIT_QDTEDEBUG
62 # define QDTEDEBUG qDebug() << QString::fromLatin1("%1:%2").arg(__FILE__).arg(__LINE__)
63 # define QDTEDEBUGN qDebug
65 # define QDTEDEBUG if (false) qDebug()
66 # define QDTEDEBUGN if (false) qDebug
71 // --- QDateTimeEdit ---
75 \brief The QDateTimeEdit class provides a widget for editing dates and times.
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().
86 \snippet code/src_gui_widgets_qdatetimeedit.cpp 0
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.
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(),
97 \section1 Using a Pop-up Calendar Widget
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().
106 \row \li \inlineimage windowsxp-datetimeedit.png Screenshot of a Windows XP style date time editing widget
107 \li A date time editing widget shown in the \l{Windows XP Style Widget Gallery}{Windows XP widget style}.
108 \row \li \inlineimage macintosh-datetimeedit.png Screenshot of a Macintosh style date time editing widget
109 \li A date time editing widget shown in the \l{Macintosh Style Widget Gallery}{Macintosh widget style}.
110 \row \li \inlineimage plastique-datetimeedit.png Screenshot of a Plastique style date time editing widget
111 \li A date time editing widget shown in the \l{Plastique Style Widget Gallery}{Plastique widget style}.
114 \sa QDateEdit, QTimeEdit, QDate, QTime
118 \enum QDateTimeEdit::Section
129 \omitvalue DateSections_Mask
130 \omitvalue TimeSections_Mask
134 \fn void QDateTimeEdit::dateTimeChanged(const QDateTime &datetime)
136 This signal is emitted whenever the date or time is changed. The
137 new date and time is passed in \a datetime.
141 \fn void QDateTimeEdit::timeChanged(const QTime &time)
143 This signal is emitted whenever the time is changed. The new time
144 is passed in \a time.
148 \fn void QDateTimeEdit::dateChanged(const QDate &date)
150 This signal is emitted whenever the date is changed. The new date
151 is passed in \a date.
156 Constructs an empty date time editor with a \a parent.
159 QDateTimeEdit::QDateTimeEdit(QWidget *parent)
160 : QAbstractSpinBox(*new QDateTimeEditPrivate, parent)
163 d->init(QDateTime(QDATETIMEEDIT_DATE_INITIAL, QDATETIMEEDIT_TIME_MIN));
167 Constructs an empty date time editor with a \a parent. The value
168 is set to \a datetime.
171 QDateTimeEdit::QDateTimeEdit(const QDateTime &datetime, QWidget *parent)
172 : QAbstractSpinBox(*new QDateTimeEditPrivate, parent)
175 d->init(datetime.isValid() ? datetime : QDateTime(QDATETIMEEDIT_DATE_INITIAL,
176 QDATETIMEEDIT_TIME_MIN));
180 \fn QDateTimeEdit::QDateTimeEdit(const QDate &date, QWidget *parent)
182 Constructs an empty date time editor with a \a parent.
183 The value is set to \a date.
186 QDateTimeEdit::QDateTimeEdit(const QDate &date, QWidget *parent)
187 : QAbstractSpinBox(*new QDateTimeEditPrivate, parent)
190 d->init(date.isValid() ? date : QDATETIMEEDIT_DATE_INITIAL);
194 \fn QDateTimeEdit::QDateTimeEdit(const QTime &time, QWidget *parent)
196 Constructs an empty date time editor with a \a parent.
197 The value is set to \a time.
200 QDateTimeEdit::QDateTimeEdit(const QTime &time, QWidget *parent)
201 : QAbstractSpinBox(*new QDateTimeEditPrivate, parent)
204 d->init(time.isValid() ? time : QDATETIMEEDIT_TIME_MIN);
211 QDateTimeEdit::QDateTimeEdit(const QVariant &var, QVariant::Type parserType, QWidget *parent)
212 : QAbstractSpinBox(*new QDateTimeEditPrivate, parent)
215 d->parserType = parserType;
220 \property QDateTimeEdit::dateTime
221 \brief the QDateTime that is set in the QDateTimeEdit
223 When setting this property the timespec of the QDateTimeEdit remains the same
224 and the timespec of the new QDateTime is ignored.
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.
232 QDateTime QDateTimeEdit::dateTime() const
234 Q_D(const QDateTimeEdit);
235 return d->value.toDateTime();
238 void QDateTimeEdit::setDateTime(const QDateTime &datetime)
241 if (datetime.isValid()) {
243 if (!(d->sections & DateSections_Mask))
244 setDateRange(datetime.date(), datetime.date());
245 d->setValue(QDateTime(datetime.date(), datetime.time(), d->spec), EmitIfChanged);
250 \property QDateTimeEdit::date
251 \brief the QDate that is set in the widget
253 By default, this property contains a date that refers to January 1, 2000.
259 Returns the date of the date time edit.
261 QDate QDateTimeEdit::date() const
263 Q_D(const QDateTimeEdit);
264 return d->value.toDate();
267 void QDateTimeEdit::setDate(const QDate &date)
270 if (date.isValid()) {
271 if (!(d->sections & DateSections_Mask))
272 setDateRange(date, date);
275 d->setValue(QDateTime(date, d->value.toTime(), d->spec), EmitIfChanged);
281 \property QDateTimeEdit::time
282 \brief the QTime that is set in the widget
284 By default, this property contains a time of 00:00:00 and 0 milliseconds.
290 Returns the time of the date time edit.
292 QTime QDateTimeEdit::time() const
294 Q_D(const QDateTimeEdit);
295 return d->value.toTime();
298 void QDateTimeEdit::setTime(const QTime &time)
301 if (time.isValid()) {
303 d->setValue(QDateTime(d->value.toDate(), time, d->spec), EmitIfChanged);
309 \property QDateTimeEdit::minimumDateTime
312 \brief the minimum datetime of the date time edit
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.
318 The default minimumDateTime can be restored with
319 clearMinimumDateTime()
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.
324 \sa maximumDateTime(), minimumTime(), maximumTime(), minimumDate(),
325 maximumDate(), setDateTimeRange(), setDateRange(), setTimeRange(),
326 clearMaximumDateTime(), clearMinimumDate(),
327 clearMaximumDate(), clearMinimumTime(), clearMaximumTime()
330 QDateTime QDateTimeEdit::minimumDateTime() const
332 Q_D(const QDateTimeEdit);
333 return d->minimum.toDateTime();
336 void QDateTimeEdit::clearMinimumDateTime()
338 setMinimumDateTime(QDateTime(QDATETIMEEDIT_COMPAT_DATE_MIN, QDATETIMEEDIT_TIME_MIN));
341 void QDateTimeEdit::setMinimumDateTime(const QDateTime &dt)
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));
352 \property QDateTimeEdit::maximumDateTime
355 \brief the maximum datetime of the date time edit
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.
361 The default maximumDateTime can be restored with
362 clearMaximumDateTime().
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.
367 \sa minimumDateTime(), minimumTime(), maximumTime(), minimumDate(),
368 maximumDate(), setDateTimeRange(), setDateRange(), setTimeRange(),
369 clearMinimumDateTime(), clearMinimumDate(),
370 clearMaximumDate(), clearMinimumTime(), clearMaximumTime()
373 QDateTime QDateTimeEdit::maximumDateTime() const
375 Q_D(const QDateTimeEdit);
376 return d->maximum.toDateTime();
379 void QDateTimeEdit::clearMaximumDateTime()
381 setMaximumDateTime(QDATETIMEEDIT_DATETIME_MAX);
384 void QDateTimeEdit::setMaximumDateTime(const QDateTime &dt)
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);
396 Convenience function to set minimum and maximum date time with one
400 \snippet code/src_gui_widgets_qdatetimeedit.cpp 1
404 \snippet code/src_gui_widgets_qdatetimeedit.cpp 2
406 If either \a min or \a max are not valid, this function does
409 \sa setMinimumDate(), maximumDate(), setMaximumDate(),
410 clearMinimumDate(), setMinimumTime(), maximumTime(),
411 setMaximumTime(), clearMinimumTime(), QDateTime::isValid()
414 void QDateTimeEdit::setDateTimeRange(const QDateTime &min, const QDateTime &max)
417 const QDateTime minimum = min.toTimeSpec(d->spec);
418 QDateTime maximum = max.toTimeSpec(d->spec);
421 d->setRange(minimum, maximum);
425 \property QDateTimeEdit::minimumDate
427 \brief the minimum date of the date time edit
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.
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.
437 \sa minimumTime(), maximumTime(), setDateRange()
440 QDate QDateTimeEdit::minimumDate() const
442 Q_D(const QDateTimeEdit);
443 return d->minimum.toDate();
446 void QDateTimeEdit::setMinimumDate(const QDate &min)
449 if (min.isValid() && min >= QDATETIMEEDIT_DATE_MIN) {
450 setMinimumDateTime(QDateTime(min, d->minimum.toTime(), d->spec));
454 void QDateTimeEdit::clearMinimumDate()
456 setMinimumDate(QDATETIMEEDIT_COMPAT_DATE_MIN);
460 \property QDateTimeEdit::maximumDate
462 \brief the maximum date of the date time edit
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.
468 By default, this property contains a date that refers to December 31, 7999.
470 \sa minimumDate, minimumTime, maximumTime, setDateRange()
473 QDate QDateTimeEdit::maximumDate() const
475 Q_D(const QDateTimeEdit);
476 return d->maximum.toDate();
479 void QDateTimeEdit::setMaximumDate(const QDate &max)
483 setMaximumDateTime(QDateTime(max, d->maximum.toTime(), d->spec));
487 void QDateTimeEdit::clearMaximumDate()
489 setMaximumDate(QDATETIMEEDIT_DATE_MAX);
493 \property QDateTimeEdit::minimumTime
495 \brief the minimum time of the date time edit
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.
501 By default, this property contains a time of 00:00:00 and 0 milliseconds.
503 \sa maximumTime, minimumDate, maximumDate, setTimeRange()
506 QTime QDateTimeEdit::minimumTime() const
508 Q_D(const QDateTimeEdit);
509 return d->minimum.toTime();
512 void QDateTimeEdit::setMinimumTime(const QTime &min)
516 const QDateTime m(d->minimum.toDate(), min, d->spec);
517 setMinimumDateTime(m);
521 void QDateTimeEdit::clearMinimumTime()
523 setMinimumTime(QDATETIMEEDIT_TIME_MIN);
527 \property QDateTimeEdit::maximumTime
529 \brief the maximum time of the date time edit
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.
535 By default, this property contains a time of 23:59:59 and 999 milliseconds.
537 \sa minimumTime, minimumDate, maximumDate, setTimeRange()
539 QTime QDateTimeEdit::maximumTime() const
541 Q_D(const QDateTimeEdit);
542 return d->maximum.toTime();
545 void QDateTimeEdit::setMaximumTime(const QTime &max)
549 const QDateTime m(d->maximum.toDate(), max);
550 setMaximumDateTime(m);
554 void QDateTimeEdit::clearMaximumTime()
556 setMaximumTime(QDATETIMEEDIT_TIME_MAX);
560 Convenience function to set minimum and maximum date with one
563 \snippet code/src_gui_widgets_qdatetimeedit.cpp 3
567 \snippet code/src_gui_widgets_qdatetimeedit.cpp 4
569 If either \a min or \a max are not valid, this function does
572 \sa setMinimumDate(), maximumDate(), setMaximumDate(),
573 clearMinimumDate(), setMinimumTime(), maximumTime(),
574 setMaximumTime(), clearMinimumTime(), QDate::isValid()
577 void QDateTimeEdit::setDateRange(const QDate &min, const QDate &max)
580 if (min.isValid() && max.isValid()) {
581 setDateTimeRange(QDateTime(min, d->minimum.toTime(), d->spec),
582 QDateTime(max, d->maximum.toTime(), d->spec));
587 Convenience function to set minimum and maximum time with one
590 \snippet code/src_gui_widgets_qdatetimeedit.cpp 5
594 \snippet code/src_gui_widgets_qdatetimeedit.cpp 6
596 If either \a min or \a max are not valid, this function does
599 \sa setMinimumDate(), maximumDate(), setMaximumDate(),
600 clearMinimumDate(), setMinimumTime(), maximumTime(),
601 setMaximumTime(), clearMinimumTime(), QTime::isValid()
604 void QDateTimeEdit::setTimeRange(const QTime &min, const QTime &max)
607 if (min.isValid() && max.isValid()) {
608 setDateTimeRange(QDateTime(d->minimum.toDate(), min, d->spec),
609 QDateTime(d->maximum.toDate(), max, d->spec));
614 \property QDateTimeEdit::displayedSections
616 \brief the currently displayed fields of the date time edit
618 Returns a bit set of the displayed sections for this format.
619 \a setDisplayFormat(), displayFormat()
622 QDateTimeEdit::Sections QDateTimeEdit::displayedSections() const
624 Q_D(const QDateTimeEdit);
629 \property QDateTimeEdit::currentSection
631 \brief the current section of the spinbox
632 \a setCurrentSection()
635 QDateTimeEdit::Section QDateTimeEdit::currentSection() const
637 Q_D(const QDateTimeEdit);
638 #ifdef QT_KEYPAD_NAVIGATION
639 if (QApplication::keypadNavigationEnabled() && d->focusOnButton)
642 return d->convertToPublic(d->sectionType(d->currentSectionIndex));
645 void QDateTimeEdit::setCurrentSection(Section section)
648 if (section == NoSection || !(section & d->sections))
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);
670 Returns the Section at \a index.
672 If the format is 'yyyy/MM/dd', sectionAt(0) returns YearSection,
673 sectionAt(1) returns MonthSection, and sectionAt(2) returns
677 QDateTimeEdit::Section QDateTimeEdit::sectionAt(int index) const
679 Q_D(const QDateTimeEdit);
680 if (index < 0 || index >= d->sectionNodes.size())
682 return d->convertToPublic(d->sectionType(index));
688 \property QDateTimeEdit::sectionCount
690 \brief the number of sections displayed.
691 If the format is 'yyyy/yy/yyyy', sectionCount returns 3
694 int QDateTimeEdit::sectionCount() const
696 Q_D(const QDateTimeEdit);
697 return d->sectionNodes.size();
704 \property QDateTimeEdit::currentSectionIndex
706 \brief the current section index of the spinbox
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.
712 \a setCurrentSection()
716 int QDateTimeEdit::currentSectionIndex() const
718 Q_D(const QDateTimeEdit);
719 return d->currentSectionIndex;
722 void QDateTimeEdit::setCurrentSectionIndex(int index)
725 if (index < 0 || index >= d->sectionNodes.size())
727 d->edit->setCursorPosition(d->sectionPos(index));
733 \brief Returns the calendar widget for the editor if calendarPopup is
734 set to true and (sections() & DateSections_Mask) != 0.
736 This function creates and returns a calendar widget if none has been set.
740 QCalendarWidget *QDateTimeEdit::calendarWidget() const
742 Q_D(const QDateTimeEdit);
743 if (!d->calendarPopup || !(d->sections & QDateTimeParser::DateSectionMask))
745 if (!d->monthCalendar) {
746 const_cast<QDateTimeEditPrivate*>(d)->initCalendarPopup();
748 return d->monthCalendar->calendarWidget();
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.
757 \note calendarPopup must be set to true before setting the calendar widget.
760 void QDateTimeEdit::setCalendarWidget(QCalendarWidget *calendarWidget)
763 if (!calendarWidget) {
764 qWarning("QDateTimeEdit::setCalendarWidget: Cannot set a null calendar widget");
768 if (!d->calendarPopup) {
769 qWarning("QDateTimeEdit::setCalendarWidget: calendarPopup is set to false");
773 if (!(d->display & QDateTimeParser::DateSectionMask)) {
774 qWarning("QDateTimeEdit::setCalendarWidget: no date sections specified");
777 d->initCalendarPopup(calendarWidget);
784 Selects \a section. If \a section doesn't exist in the currently
785 displayed sections this function does nothing. If \a section is
786 NoSection this function will unselect all text in the editor.
787 Otherwise this function will move the cursor and the current section
788 to the selected section.
793 void QDateTimeEdit::setSelectedSection(Section section)
796 if (section == NoSection) {
797 d->edit->setSelection(d->edit->cursorPosition(), 0);
798 } else if (section & d->sections) {
799 if (currentSection() != section)
800 setCurrentSection(section);
801 d->setSelected(d->currentSectionIndex);
808 \fn QString QDateTimeEdit::sectionText(Section section) const
810 Returns the text from the given \a section.
815 QString QDateTimeEdit::sectionText(Section section) const
817 Q_D(const QDateTimeEdit);
818 if (section == QDateTimeEdit::NoSection || !(section & d->sections)) {
822 d->updateCache(d->value, d->displayText());
823 const int sectionIndex = d->absoluteIndex(section, 0);
824 return d->sectionText(sectionIndex);
828 \property QDateTimeEdit::displayFormat
830 \brief the format used to display the time/date of the date time edit
832 This format is the same as the one used described in QDateTime::toString()
833 and QDateTime::fromString()
835 Example format strings (assuming that the date is 2nd of July 1969):
838 \header \li Format \li Result
839 \row \li dd.MM.yyyy \li 02.07.1969
840 \row \li MMM d yy \li Jul 2 69
841 \row \li MMMM d yy \li July 2 69
844 Note that if you specify a two digit year, it will be interpreted
845 to be in the century in which the date time edit was initialized.
846 The default century is the 21 (2000-2099).
848 If you specify an invalid format the format will not be set.
850 \sa QDateTime::toString(), displayedSections()
853 QString QDateTimeEdit::displayFormat() const
855 Q_D(const QDateTimeEdit);
856 return isRightToLeft() ? d->unreversedFormat : d->displayFormat;
859 template<typename C> static inline C reverse(const C &l)
862 for (int i=l.size() - 1; i>=0; --i)
867 void QDateTimeEdit::setDisplayFormat(const QString &format)
870 if (d->parseFormat(format)) {
871 d->unreversedFormat.clear();
872 if (isRightToLeft()) {
873 d->unreversedFormat = format;
874 d->displayFormat.clear();
875 for (int i=d->sectionNodes.size() - 1; i>=0; --i) {
876 d->displayFormat += d->separators.at(i + 1);
877 d->displayFormat += d->sectionFormat(i);
879 d->displayFormat += d->separators.at(0);
880 d->separators = reverse(d->separators);
881 d->sectionNodes = reverse(d->sectionNodes);
884 d->formatExplicitlySet = true;
885 d->sections = d->convertSections(d->display);
888 d->currentSectionIndex = qMin(d->currentSectionIndex, d->sectionNodes.size() - 1);
889 const bool timeShown = (d->sections & TimeSections_Mask);
890 const bool dateShown = (d->sections & DateSections_Mask);
891 Q_ASSERT(dateShown || timeShown);
892 if (timeShown && !dateShown) {
893 QTime time = d->value.toTime();
894 setDateRange(d->value.toDate(), d->value.toDate());
895 if (d->minimum.toTime() >= d->maximum.toTime()) {
896 setTimeRange(QDATETIMEEDIT_TIME_MIN, QDATETIMEEDIT_TIME_MAX);
897 // if the time range became invalid during the adjustment, the time would have been reset
900 } else if (dateShown && !timeShown) {
901 setTimeRange(QDATETIMEEDIT_TIME_MIN, QDATETIMEEDIT_TIME_MAX);
902 d->value = QDateTime(d->value.toDate(), QTime(), d->spec);
905 d->_q_editorCursorPositionChanged(-1, 0);
910 \property QDateTimeEdit::calendarPopup
911 \brief the current calendar pop-up showing mode.
914 The calendar pop-up will be shown upon clicking the arrow button.
915 This property is valid only if there is a valid date display format.
917 \sa setDisplayFormat()
920 bool QDateTimeEdit::calendarPopup() const
922 Q_D(const QDateTimeEdit);
923 return d->calendarPopup;
926 void QDateTimeEdit::setCalendarPopup(bool enable)
929 if (enable == d->calendarPopup)
931 setAttribute(Qt::WA_MacShowFocusRect, !enable);
932 d->calendarPopup = enable;
933 #ifdef QT_KEYPAD_NAVIGATION
935 d->focusOnButton = false;
937 d->updateEditFieldGeometry();
942 \property QDateTimeEdit::timeSpec
943 \brief the current timespec used by the date time edit.
947 Qt::TimeSpec QDateTimeEdit::timeSpec() const
949 Q_D(const QDateTimeEdit);
953 void QDateTimeEdit::setTimeSpec(Qt::TimeSpec spec)
956 if (spec != d->spec) {
966 QSize QDateTimeEdit::sizeHint() const
968 Q_D(const QDateTimeEdit);
969 if (d->cachedSizeHint.isEmpty()) {
972 const QFontMetrics fm(fontMetrics());
973 int h = d->edit->sizeHint().height();
976 s = d->textFromValue(d->minimum) + QLatin1String(" ");
977 w = qMax<int>(w, fm.width(s));
978 s = d->textFromValue(d->maximum) + QLatin1String(" ");
979 w = qMax<int>(w, fm.width(s));
980 if (d->specialValueText.size()) {
981 s = d->specialValueText;
982 w = qMax<int>(w, fm.width(s));
984 w += 2; // cursor blinking space
989 if (d->calendarPopupEnabled()) {
990 QStyleOptionComboBox opt;
991 d->cachedSizeHint = style()->sizeFromContents(QStyle::CT_ComboBox, &opt, hint, this);
997 QStyleOptionSpinBox opt;
998 initStyleOption(&opt);
999 opt.rect.setSize(hint + extra);
1000 extra += hint - style()->subControlRect(QStyle::CC_SpinBox, &opt,
1001 QStyle::SC_SpinBoxEditField, this).size();
1002 // get closer to final result by repeating the calculation
1003 opt.rect.setSize(hint + extra);
1004 extra += hint - style()->subControlRect(QStyle::CC_SpinBox, &opt,
1005 QStyle::SC_SpinBoxEditField, this).size();
1009 d->cachedSizeHint = style()->sizeFromContents(QStyle::CT_SpinBox, &opt, hint, this)
1010 .expandedTo(QApplication::globalStrut());
1013 d->cachedMinimumSizeHint = d->cachedSizeHint;
1014 // essentially make minimumSizeHint return the same as sizeHint for datetimeedits
1016 return d->cachedSizeHint;
1023 bool QDateTimeEdit::event(QEvent *event)
1026 switch (event->type()) {
1027 case QEvent::ApplicationLayoutDirectionChange: {
1028 const bool was = d->formatExplicitlySet;
1029 const QString oldFormat = d->displayFormat;
1030 d->displayFormat.clear();
1031 setDisplayFormat(oldFormat);
1032 d->formatExplicitlySet = was;
1034 case QEvent::LocaleChange:
1037 case QEvent::StyleChange:
1039 case QEvent::MacSizeChange:
1041 d->setLayoutItemMargins(QStyle::SE_DateTimeEditLayoutItem);
1046 return QAbstractSpinBox::event(event);
1053 void QDateTimeEdit::clear()
1056 d->clearSection(d->currentSectionIndex);
1062 void QDateTimeEdit::keyPressEvent(QKeyEvent *event)
1065 int oldCurrent = d->currentSectionIndex;
1067 bool inserted = false;
1069 switch (event->key()) {
1070 #ifdef QT_KEYPAD_NAVIGATION
1071 case Qt::Key_NumberSign: //shortcut to popup calendar
1072 if (QApplication::keypadNavigationEnabled() && d->calendarPopupEnabled()) {
1073 d->initCalendarPopup();
1074 d->positionCalendarPopup();
1075 d->monthCalendar->show();
1079 case Qt::Key_Select:
1080 if (QApplication::keypadNavigationEnabled()) {
1081 if (hasEditFocus()) {
1082 if (d->focusOnButton) {
1083 d->initCalendarPopup();
1084 d->positionCalendarPopup();
1085 d->monthCalendar->show();
1086 d->focusOnButton = false;
1089 setEditFocus(false);
1095 d->edit->d_func()->setCursorVisible(false);
1096 d->edit->d_func()->control->setCursorBlinkPeriod(0);
1103 case Qt::Key_Return:
1104 d->interpret(AlwaysEmit);
1105 d->setSelected(d->currentSectionIndex, true);
1107 emit editingFinished();
1110 #ifdef QT_KEYPAD_NAVIGATION
1111 if (QApplication::keypadNavigationEnabled() && !hasEditFocus()
1112 && !event->text().isEmpty() && event->text().at(0).isLetterOrNumber()) {
1116 d->edit->d_func()->setCursorVisible(false);
1117 d->edit->d_func()->control->setCursorBlinkPeriod(0);
1122 if (!d->isSeparatorKey(event)) {
1123 inserted = select = !event->text().isEmpty() && event->text().at(0).isPrint()
1124 && !(event->modifiers() & ~(Qt::ShiftModifier|Qt::KeypadModifier));
1129 if (event->key() == Qt::Key_Left || event->key() == Qt::Key_Right) {
1131 #ifdef QT_KEYPAD_NAVIGATION
1132 QApplication::keypadNavigationEnabled() && !hasEditFocus()
1133 || !QApplication::keypadNavigationEnabled() &&
1135 !(event->modifiers() & Qt::ControlModifier)) {
1141 #ifdef QT_KEYPAD_NAVIGATION
1142 if (!QApplication::keypadNavigationEnabled())
1145 select = (event->modifiers() & Qt::ShiftModifier);
1150 // else fall through
1151 case Qt::Key_Backtab:
1154 if (d->specialValue()) {
1155 d->edit->setSelection(d->edit->cursorPosition(), 0);
1158 const bool forward = event->key() != Qt::Key_Left && event->key() != Qt::Key_Backtab
1159 && (event->key() != Qt::Key_Tab || !(event->modifiers() & Qt::ShiftModifier));
1160 #ifdef QT_KEYPAD_NAVIGATION
1161 int newSection = d->nextPrevSection(d->currentSectionIndex, forward);
1162 if (QApplication::keypadNavigationEnabled()) {
1163 if (d->focusOnButton) {
1164 newSection = forward ? 0 : d->sectionNodes.size() - 1;
1165 d->focusOnButton = false;
1167 } else if (newSection < 0 && select && d->calendarPopupEnabled()) {
1168 setSelectedSection(NoSection);
1169 d->focusOnButton = true;
1174 // only allow date/time sections to be selected.
1175 if (newSection & ~(QDateTimeParser::TimeSectionMask | QDateTimeParser::DateSectionMask))
1178 //key tab and backtab will be managed thrgout QWidget::event
1179 if (event->key() != Qt::Key_Backtab && event->key() != Qt::Key_Tab)
1180 focusNextPrevChild(forward);
1184 QAbstractSpinBox::keyPressEvent(event);
1185 if (select && !d->edit->hasSelectedText()) {
1186 if (inserted && d->sectionAt(d->edit->cursorPosition()) == QDateTimeParser::NoSectionIndex) {
1187 QString str = d->displayText();
1188 int pos = d->edit->cursorPosition();
1189 if (validate(str, pos) == QValidator::Acceptable
1190 && (d->sectionNodes.at(oldCurrent).count != 1
1191 || d->sectionMaxSize(oldCurrent) == d->sectionSize(oldCurrent)
1192 || d->skipToNextSection(oldCurrent, d->value.toDateTime(), d->sectionText(oldCurrent)))) {
1193 QDTEDEBUG << "Setting currentsection to"
1194 << d->closestSection(d->edit->cursorPosition(), true) << event->key()
1195 << oldCurrent << str;
1196 const int tmp = d->closestSection(d->edit->cursorPosition(), true);
1198 d->currentSectionIndex = tmp;
1201 if (d->currentSectionIndex != oldCurrent) {
1202 d->setSelected(d->currentSectionIndex);
1205 if (d->specialValue()) {
1206 d->edit->setSelection(d->edit->cursorPosition(), 0);
1214 #ifndef QT_NO_WHEELEVENT
1215 void QDateTimeEdit::wheelEvent(QWheelEvent *event)
1217 QAbstractSpinBox::wheelEvent(event);
1225 void QDateTimeEdit::focusInEvent(QFocusEvent *event)
1228 QAbstractSpinBox::focusInEvent(event);
1230 const int oldPos = d->edit->cursorPosition();
1231 if (!d->formatExplicitlySet) {
1232 if (d->displayFormat == d->defaultTimeFormat) {
1233 frm = &d->defaultTimeFormat;
1234 } else if (d->displayFormat == d->defaultDateFormat) {
1235 frm = &d->defaultDateFormat;
1236 } else if (d->displayFormat == d->defaultDateTimeFormat) {
1237 frm = &d->defaultDateTimeFormat;
1241 d->readLocaleSettings();
1242 if (d->displayFormat != *frm) {
1243 setDisplayFormat(*frm);
1244 d->formatExplicitlySet = false;
1245 d->edit->setCursorPosition(oldPos);
1249 const bool oldHasHadFocus = d->hasHadFocus;
1250 d->hasHadFocus = true;
1252 switch (event->reason()) {
1253 case Qt::BacktabFocusReason:
1256 case Qt::MouseFocusReason:
1257 case Qt::PopupFocusReason:
1259 case Qt::ActiveWindowFocusReason:
1262 case Qt::ShortcutFocusReason:
1263 case Qt::TabFocusReason:
1267 if (isRightToLeft())
1269 d->updateEdit(); // needed to make it update specialValueText
1271 d->setSelected(first ? 0 : d->sectionNodes.size() - 1);
1278 bool QDateTimeEdit::focusNextPrevChild(bool next)
1281 const int newSection = d->nextPrevSection(d->currentSectionIndex, next);
1282 switch (d->sectionType(newSection)) {
1283 case QDateTimeParser::NoSection:
1284 case QDateTimeParser::FirstSection:
1285 case QDateTimeParser::LastSection:
1286 return QAbstractSpinBox::focusNextPrevChild(next);
1288 d->edit->deselect();
1289 d->edit->setCursorPosition(d->sectionPos(newSection));
1290 QDTEDEBUG << d->sectionPos(newSection);
1291 d->setSelected(newSection, true);
1300 void QDateTimeEdit::stepBy(int steps)
1303 #ifdef QT_KEYPAD_NAVIGATION
1304 // with keypad navigation and not editFocus, left right change the date/time by a fixed amount.
1305 if (QApplication::keypadNavigationEnabled() && !hasEditFocus()) {
1306 // if date based, shift by day. else shift by 15min
1307 if (d->sections & DateSections_Mask) {
1308 setDateTime(dateTime().addDays(steps));
1310 int minutes = time().hour()*60 + time().minute();
1311 int blocks = minutes/15;
1313 /* rounding involved */
1316 blocks += 1; // do one less step;
1320 minutes = blocks * 15;
1322 /* need to take wrapping into account */
1324 int max_minutes = d->maximum.toTime().hour()*60 + d->maximum.toTime().minute();
1325 int min_minutes = d->minimum.toTime().hour()*60 + d->minimum.toTime().minute();
1327 if (minutes >= max_minutes) {
1328 setTime(maximumTime());
1330 } else if (minutes <= min_minutes) {
1331 setTime(minimumTime());
1335 setTime(QTime(minutes/60, minutes%60));
1340 // don't optimize away steps == 0. This is the only way to select
1341 // the currentSection in Qt 4.1.x
1342 if (d->specialValue() && displayedSections() != AmPmSection) {
1343 for (int i=0; i<d->sectionNodes.size(); ++i) {
1344 if (d->sectionType(i) != QDateTimeParser::AmPmSection) {
1345 d->currentSectionIndex = i;
1350 d->setValue(d->stepBy(d->currentSectionIndex, steps, false), EmitIfChanged);
1351 d->updateCache(d->value, d->displayText());
1353 d->setSelected(d->currentSectionIndex);
1354 d->updateTimeSpec();
1358 This virtual function is used by the date time edit whenever it
1359 needs to display \a dateTime.
1361 If you reimplement this, you may also need to reimplement validate().
1363 \sa dateTimeFromText(), validate()
1365 QString QDateTimeEdit::textFromDateTime(const QDateTime &dateTime) const
1367 Q_D(const QDateTimeEdit);
1368 return locale().toString(dateTime, d->displayFormat);
1373 Returns an appropriate datetime for the given \a text.
1375 This virtual function is used by the datetime edit whenever it
1376 needs to interpret text entered by the user as a value.
1378 \sa textFromDateTime(), validate()
1380 QDateTime QDateTimeEdit::dateTimeFromText(const QString &text) const
1382 Q_D(const QDateTimeEdit);
1383 QString copy = text;
1384 int pos = d->edit->cursorPosition();
1385 QValidator::State state = QValidator::Acceptable;
1386 return d->validateAndInterpret(copy, pos, state);
1393 QValidator::State QDateTimeEdit::validate(QString &text, int &pos) const
1395 Q_D(const QDateTimeEdit);
1396 QValidator::State state;
1397 d->validateAndInterpret(text, pos, state);
1406 void QDateTimeEdit::fixup(QString &input) const
1408 Q_D(const QDateTimeEdit);
1409 QValidator::State state;
1410 int copy = d->edit->cursorPosition();
1412 d->validateAndInterpret(input, copy, state, true);
1420 QDateTimeEdit::StepEnabled QDateTimeEdit::stepEnabled() const
1422 Q_D(const QDateTimeEdit);
1424 return StepEnabled(0);
1425 if (d->specialValue()) {
1426 return (d->minimum == d->maximum ? StepEnabled(0) : StepEnabled(StepUpEnabled));
1429 QAbstractSpinBox::StepEnabled ret = 0;
1431 #ifdef QT_KEYPAD_NAVIGATION
1432 if (QApplication::keypadNavigationEnabled() && !hasEditFocus()) {
1434 return StepEnabled(StepUpEnabled | StepDownEnabled);
1435 // 3 cases. date, time, datetime. each case look
1436 // at just the relavant component.
1437 QVariant max, min, val;
1438 if (!(d->sections & DateSections_Mask)) {
1439 // time only, no date
1440 max = d->maximum.toTime();
1441 min = d->minimum.toTime();
1442 val = d->value.toTime();
1443 } else if (!(d->sections & TimeSections_Mask)) {
1444 // date only, no time
1445 max = d->maximum.toDate();
1446 min = d->minimum.toDate();
1447 val = d->value.toDate();
1455 ret |= QAbstractSpinBox::StepDownEnabled;
1457 ret |= QAbstractSpinBox::StepUpEnabled;
1461 switch (d->sectionType(d->currentSectionIndex)) {
1462 case QDateTimeParser::NoSection:
1463 case QDateTimeParser::FirstSection:
1464 case QDateTimeParser::LastSection: return 0;
1468 return StepEnabled(StepDownEnabled|StepUpEnabled);
1470 QVariant v = d->stepBy(d->currentSectionIndex, 1, true);
1471 if (v != d->value) {
1472 ret |= QAbstractSpinBox::StepUpEnabled;
1474 v = d->stepBy(d->currentSectionIndex, -1, true);
1475 if (v != d->value) {
1476 ret |= QAbstractSpinBox::StepDownEnabled;
1487 void QDateTimeEdit::mousePressEvent(QMouseEvent *event)
1490 if (!d->calendarPopupEnabled()) {
1491 QAbstractSpinBox::mousePressEvent(event);
1494 d->updateHoverControl(event->pos());
1495 if (d->hoverControl == QStyle::SC_ComboBoxArrow) {
1500 d->updateArrow(QStyle::State_Sunken);
1501 d->initCalendarPopup();
1502 d->positionCalendarPopup();
1504 d->monthCalendar->show();
1506 QAbstractSpinBox::mousePressEvent(event);
1512 \brief The QTimeEdit class provides a widget for editing times based on
1513 the QDateTimeEdit widget.
1515 \ingroup basicwidgets
1518 Many of the properties and functions provided by QTimeEdit are implemented in
1519 QDateTimeEdit. The following properties are most relevant to users of this
1523 \li \l{QDateTimeEdit::time}{time} holds the date displayed by the widget.
1524 \li \l{QDateTimeEdit::minimumTime}{minimumTime} defines the minimum (earliest) time
1525 that can be set by the user.
1526 \li \l{QDateTimeEdit::maximumTime}{maximumTime} defines the maximum (latest) time
1527 that can be set by the user.
1528 \li \l{QDateTimeEdit::displayFormat}{displayFormat} contains a string that is used
1529 to format the time displayed in the widget.
1533 \row \li \inlineimage windowsxp-timeedit.png Screenshot of a Windows XP style time editing widget
1534 \li A time editing widget shown in the \l{Windows XP Style Widget Gallery}{Windows XP widget style}.
1535 \row \li \inlineimage macintosh-timeedit.png Screenshot of a Macintosh style time editing widget
1536 \li A time editing widget shown in the \l{Macintosh Style Widget Gallery}{Macintosh widget style}.
1537 \row \li \inlineimage plastique-timeedit.png Screenshot of a Plastique style time editing widget
1538 \li A time editing widget shown in the \l{Plastique Style Widget Gallery}{Plastique widget style}.
1541 \sa QDateEdit, QDateTimeEdit
1545 Constructs an empty time editor with a \a parent.
1549 QTimeEdit::QTimeEdit(QWidget *parent)
1550 : QDateTimeEdit(QDATETIMEEDIT_TIME_MIN, QVariant::Time, parent)
1552 connect(this, SIGNAL(timeChanged(QTime)), SIGNAL(userTimeChanged(QTime)));
1556 Constructs an empty time editor with a \a parent. The time is set
1560 QTimeEdit::QTimeEdit(const QTime &time, QWidget *parent)
1561 : QDateTimeEdit(time, QVariant::Time, parent)
1566 \fn void QTimeEdit::userTimeChanged(const QTime &time)
1568 This signal only exists to fully implement the time Q_PROPERTY on the class.
1569 Normally timeChanged should be used instead.
1577 \brief The QDateEdit class provides a widget for editing dates based on
1578 the QDateTimeEdit widget.
1580 \ingroup basicwidgets
1583 Many of the properties and functions provided by QDateEdit are implemented in
1584 QDateTimeEdit. The following properties are most relevant to users of this
1588 \li \l{QDateTimeEdit::date}{date} holds the date displayed by the widget.
1589 \li \l{QDateTimeEdit::minimumDate}{minimumDate} defines the minimum (earliest)
1590 date that can be set by the user.
1591 \li \l{QDateTimeEdit::maximumDate}{maximumDate} defines the maximum (latest) date
1592 that can be set by the user.
1593 \li \l{QDateTimeEdit::displayFormat}{displayFormat} contains a string that is used
1594 to format the date displayed in the widget.
1598 \row \li \inlineimage windowsxp-dateedit.png Screenshot of a Windows XP style date editing widget
1599 \li A date editing widget shown in the \l{Windows XP Style Widget Gallery}{Windows XP widget style}.
1600 \row \li \inlineimage macintosh-dateedit.png Screenshot of a Macintosh style date editing widget
1601 \li A date editing widget shown in the \l{Macintosh Style Widget Gallery}{Macintosh widget style}.
1602 \row \li \inlineimage plastique-dateedit.png Screenshot of a Plastique style date editing widget
1603 \li A date editing widget shown in the \l{Plastique Style Widget Gallery}{Plastique widget style}.
1606 \sa QTimeEdit, QDateTimeEdit
1610 Constructs an empty date editor with a \a parent.
1613 QDateEdit::QDateEdit(QWidget *parent)
1614 : QDateTimeEdit(QDATETIMEEDIT_DATE_INITIAL, QVariant::Date, parent)
1616 connect(this, SIGNAL(dateChanged(QDate)), SIGNAL(userDateChanged(QDate)));
1620 Constructs an empty date editor with a \a parent. The date is set
1624 QDateEdit::QDateEdit(const QDate &date, QWidget *parent)
1625 : QDateTimeEdit(date, QVariant::Date, parent)
1630 \fn void QDateEdit::userDateChanged(const QDate &date)
1632 This signal only exists to fully implement the date Q_PROPERTY on the class.
1633 Normally dateChanged should be used instead.
1639 // --- QDateTimeEditPrivate ---
1643 Constructs a QDateTimeEditPrivate object
1647 QDateTimeEditPrivate::QDateTimeEditPrivate()
1648 : QDateTimeParser(QVariant::DateTime, QDateTimeParser::DateTimeEdit)
1650 hasHadFocus = false;
1651 formatExplicitlySet = false;
1654 type = QVariant::DateTime;
1657 currentSectionIndex = FirstSectionIndex;
1659 first.type = FirstSection;
1660 last.type = LastSection;
1661 none.type = NoSection;
1666 calendarPopup = false;
1667 minimum = QDATETIMEEDIT_COMPAT_DATETIME_MIN;
1668 maximum = QDATETIMEEDIT_DATETIME_MAX;
1669 arrowState = QStyle::State_None;
1671 readLocaleSettings();
1673 #ifdef QT_KEYPAD_NAVIGATION
1674 focusOnButton = false;
1678 void QDateTimeEditPrivate::updateTimeSpec()
1680 minimum = minimum.toDateTime().toTimeSpec(spec);
1681 maximum = maximum.toDateTime().toTimeSpec(spec);
1682 value = value.toDateTime().toTimeSpec(spec);
1684 // time zone changes can lead to 00:00:00 becomes 01:00:00 and 23:59:59 becomes 00:59:59 (invalid range)
1685 const bool dateShown = (sections & QDateTimeEdit::DateSections_Mask);
1687 if (minimum.toTime() >= maximum.toTime()){
1688 minimum = QDateTime(value.toDate(), QDATETIMEEDIT_TIME_MIN, spec);
1689 maximum = QDateTime(value.toDate(), QDATETIMEEDIT_TIME_MAX, spec);
1694 void QDateTimeEditPrivate::updateEdit()
1696 const QString newText = (specialValue() ? specialValueText : textFromValue(value));
1697 if (newText == displayText())
1699 int selsize = edit->selectedText().size();
1700 const bool sb = edit->blockSignals(true);
1702 edit->setText(newText);
1705 #ifdef QT_KEYPAD_NAVIGATION
1706 && !(QApplication::keypadNavigationEnabled() && !edit->hasEditFocus())
1709 int cursor = sectionPos(currentSectionIndex);
1710 QDTEDEBUG << "cursor is " << cursor << currentSectionIndex;
1711 cursor = qBound(0, cursor, displayText().size());
1712 QDTEDEBUG << cursor;
1714 edit->setSelection(cursor, selsize);
1715 QDTEDEBUG << cursor << selsize;
1717 edit->setCursorPosition(cursor);
1718 QDTEDEBUG << cursor;
1722 edit->blockSignals(sb);
1729 Selects the section \a s. If \a forward is false selects backwards.
1732 void QDateTimeEditPrivate::setSelected(int sectionIndex, bool forward)
1735 #ifdef QT_KEYPAD_NAVIGATION
1736 || (QApplication::keypadNavigationEnabled() && !edit->hasEditFocus())
1741 const SectionNode &node = sectionNode(sectionIndex);
1742 if (node.type == NoSection || node.type == LastSection || node.type == FirstSection)
1745 updateCache(value, displayText());
1746 const int size = sectionSize(sectionIndex);
1748 edit->setSelection(sectionPos(node), size);
1750 edit->setSelection(sectionPos(node) + size, -size);
1758 Returns the section at index \a index or NoSection if there are no sections there.
1761 int QDateTimeEditPrivate::sectionAt(int pos) const
1763 if (pos < separators.first().size()) {
1764 return (pos == 0 ? FirstSectionIndex : NoSectionIndex);
1765 } else if (displayText().size() - pos < separators.last().size() + 1) {
1766 if (separators.last().size() == 0) {
1767 return sectionNodes.count() - 1;
1769 return (pos == displayText().size() ? LastSectionIndex : NoSectionIndex);
1771 updateCache(value, displayText());
1773 for (int i=0; i<sectionNodes.size(); ++i) {
1774 const int tmp = sectionPos(i);
1775 if (pos < tmp + sectionSize(i)) {
1776 return (pos < tmp ? -1 : i);
1785 Returns the closest section of index \a index. Searches forward
1786 for a section if \a forward is true. Otherwise searches backwards.
1789 int QDateTimeEditPrivate::closestSection(int pos, bool forward) const
1792 if (pos < separators.first().size()) {
1793 return forward ? 0 : FirstSectionIndex;
1794 } else if (displayText().size() - pos < separators.last().size() + 1) {
1795 return forward ? LastSectionIndex : sectionNodes.size() - 1;
1797 updateCache(value, displayText());
1798 for (int i=0; i<sectionNodes.size(); ++i) {
1799 const int tmp = sectionPos(sectionNodes.at(i));
1800 if (pos < tmp + sectionSize(i)) {
1801 if (pos < tmp && !forward) {
1805 } else if (i == sectionNodes.size() - 1 && pos > tmp) {
1809 qWarning("QDateTimeEdit: Internal Error: closestSection returned NoSection");
1810 return NoSectionIndex;
1816 Returns a copy of the section that is before or after \a current, depending on \a forward.
1819 int QDateTimeEditPrivate::nextPrevSection(int current, bool forward) const
1821 Q_Q(const QDateTimeEdit);
1822 if (q->isRightToLeft())
1826 case FirstSectionIndex: return forward ? 0 : FirstSectionIndex;
1827 case LastSectionIndex: return (forward ? LastSectionIndex : sectionNodes.size() - 1);
1828 case NoSectionIndex: return FirstSectionIndex;
1831 Q_ASSERT(current >= 0 && current < sectionNodes.size());
1833 current += (forward ? 1 : -1);
1834 if (current >= sectionNodes.size()) {
1835 return LastSectionIndex;
1836 } else if (current < 0) {
1837 return FirstSectionIndex;
1846 Clears the text of section \a s.
1849 void QDateTimeEditPrivate::clearSection(int index)
1851 const QLatin1Char space(' ');
1852 int cursorPos = edit->cursorPosition();
1853 bool blocked = edit->blockSignals(true);
1854 QString t = edit->text();
1855 const int pos = sectionPos(index);
1857 qWarning("QDateTimeEdit: Internal error (%s:%d)", __FILE__, __LINE__);
1860 const int size = sectionSize(index);
1861 t.replace(pos, size, QString().fill(space, size));
1863 edit->setCursorPosition(cursorPos);
1864 QDTEDEBUG << cursorPos;
1866 edit->blockSignals(blocked);
1873 updates the cached values
1876 void QDateTimeEditPrivate::updateCache(const QVariant &val, const QString &str) const
1878 if (val != cachedValue || str != cachedText || cacheGuard) {
1881 int unused = edit->cursorPosition();
1882 QValidator::State unusedState;
1883 validateAndInterpret(copy, unused, unusedState);
1891 parses and validates \a input
1894 QDateTime QDateTimeEditPrivate::validateAndInterpret(QString &input, int &position,
1895 QValidator::State &state, bool fixup) const
1897 if (input.isEmpty()) {
1898 if (sectionNodes.size() == 1 || !specialValueText.isEmpty()) {
1899 state = QValidator::Intermediate;
1901 state = QValidator::Invalid;
1903 return getZeroVariant().toDateTime();
1904 } else if (cachedText == input && !fixup) {
1905 state = cachedState;
1906 return cachedValue.toDateTime();
1907 } else if (!specialValueText.isEmpty()) {
1908 bool changeCase = false;
1909 const int max = qMin(specialValueText.size(), input.size());
1911 for (i=0; i<max; ++i) {
1912 const QChar ic = input.at(i);
1913 const QChar sc = specialValueText.at(i);
1915 if (sc.toLower() == ic.toLower()) {
1923 state = specialValueText.size() == input.size() ? QValidator::Acceptable : QValidator::Intermediate;
1925 input = specialValueText.left(max);
1927 return minimum.toDateTime();
1930 StateNode tmp = parse(input, position, value.toDateTime(), fixup);
1932 state = QValidator::State(int(tmp.state));
1933 if (state == QValidator::Acceptable) {
1934 if (tmp.conflicts && conflictGuard != tmp.value) {
1935 conflictGuard = tmp.value;
1937 input = textFromValue(tmp.value);
1938 updateCache(tmp.value, input);
1939 conflictGuard.clear();
1942 cachedState = state;
1943 cachedValue = tmp.value;
1948 return (tmp.value.isNull() ? getZeroVariant().toDateTime() : tmp.value);
1956 QString QDateTimeEditPrivate::textFromValue(const QVariant &f) const
1958 Q_Q(const QDateTimeEdit);
1959 return q->textFromDateTime(f.toDateTime());
1965 This function's name is slightly confusing; it is not to be confused
1966 with QAbstractSpinBox::valueFromText().
1969 QVariant QDateTimeEditPrivate::valueFromText(const QString &f) const
1971 Q_Q(const QDateTimeEdit);
1972 return q->dateTimeFromText(f).toTimeSpec(spec);
1979 Internal function called by QDateTimeEdit::stepBy(). Also takes a
1980 Section for which section to step on and a bool \a test for
1981 whether or not to modify the internal cachedDay variable. This is
1982 necessary because the function is called from the const function
1983 QDateTimeEdit::stepEnabled() as well as QDateTimeEdit::stepBy().
1986 QDateTime QDateTimeEditPrivate::stepBy(int sectionIndex, int steps, bool test) const
1988 Q_Q(const QDateTimeEdit);
1989 QDateTime v = value.toDateTime();
1990 QString str = displayText();
1991 int pos = edit->cursorPosition();
1992 const SectionNode sn = sectionNode(sectionIndex);
1995 // to make sure it behaves reasonably when typing something and then stepping in non-tracking mode
1996 if (!test && pendingEmit) {
1997 if (q->validate(str, pos) != QValidator::Acceptable) {
1998 v = value.toDateTime();
2000 v = q->dateTimeFromText(str);
2002 val = getDigit(v, sectionIndex);
2004 val = getDigit(v, sectionIndex);
2009 const int min = absoluteMin(sectionIndex);
2010 const int max = absoluteMax(sectionIndex, value.toDateTime());
2013 val = (wrapping ? max - (min - val) + 1 : min);
2014 } else if (val > max) {
2015 val = (wrapping ? min + val - max - 1 : max);
2019 const int oldDay = v.date().day();
2021 setDigit(v, sectionIndex, val);
2022 // if this sets year or month it will make
2023 // sure that days are lowered if needed.
2025 const QDateTime minimumDateTime = minimum.toDateTime();
2026 const QDateTime maximumDateTime = maximum.toDateTime();
2027 // changing one section should only modify that section, if possible
2028 if (sn.type != AmPmSection && (v < minimumDateTime || v > maximumDateTime)) {
2029 const int localmin = getDigit(minimumDateTime, sectionIndex);
2030 const int localmax = getDigit(maximumDateTime, sectionIndex);
2033 // just because we hit the roof in one direction, it
2034 // doesn't mean that we hit the floor in the other
2036 setDigit(v, sectionIndex, min);
2037 if (!(sn.type & (DaySection|DayOfWeekSection)) && sections & DateSectionMask) {
2038 const int daysInMonth = v.date().daysInMonth();
2039 if (v.date().day() < oldDay && v.date().day() < daysInMonth) {
2040 const int adds = qMin(oldDay, daysInMonth);
2041 v = v.addDays(adds - v.date().day());
2045 if (v < minimumDateTime) {
2046 setDigit(v, sectionIndex, localmin);
2047 if (v < minimumDateTime)
2048 setDigit(v, sectionIndex, localmin + 1);
2051 setDigit(v, sectionIndex, max);
2052 if (!(sn.type & (DaySection|DayOfWeekSection)) && sections & DateSectionMask) {
2053 const int daysInMonth = v.date().daysInMonth();
2054 if (v.date().day() < oldDay && v.date().day() < daysInMonth) {
2055 const int adds = qMin(oldDay, daysInMonth);
2056 v = v.addDays(adds - v.date().day());
2060 if (v > maximumDateTime) {
2061 setDigit(v, sectionIndex, localmax);
2062 if (v > maximumDateTime)
2063 setDigit(v, sectionIndex, localmax - 1);
2067 setDigit(v, sectionIndex, (steps > 0 ? localmax : localmin));
2070 if (!test && oldDay != v.date().day() && !(sn.type & (DaySection|DayOfWeekSection))) {
2071 // this should not happen when called from stepEnabled
2072 cachedDay = qMax<int>(oldDay, cachedDay);
2075 if (v < minimumDateTime) {
2078 setDigit(t, sectionIndex, steps < 0 ? max : min);
2079 bool mincmp = (t >= minimumDateTime);
2080 bool maxcmp = (t <= maximumDateTime);
2081 if (!mincmp || !maxcmp) {
2082 setDigit(t, sectionIndex, getDigit(steps < 0
2084 : minimumDateTime, sectionIndex));
2085 mincmp = (t >= minimumDateTime);
2086 maxcmp = (t <= maximumDateTime);
2088 if (mincmp && maxcmp) {
2092 v = value.toDateTime();
2094 } else if (v > maximumDateTime) {
2097 setDigit(t, sectionIndex, steps > 0 ? min : max);
2098 bool mincmp = (t >= minimumDateTime);
2099 bool maxcmp = (t <= maximumDateTime);
2100 if (!mincmp || !maxcmp) {
2101 setDigit(t, sectionIndex, getDigit(steps > 0 ?
2103 maximumDateTime, sectionIndex));
2104 mincmp = (t >= minimumDateTime);
2105 maxcmp = (t <= maximumDateTime);
2107 if (mincmp && maxcmp) {
2111 v = value.toDateTime();
2115 const QDateTime ret = bound(v, value, steps).toDateTime().toTimeSpec(spec);
2123 void QDateTimeEditPrivate::emitSignals(EmitPolicy ep, const QVariant &old)
2126 if (ep == NeverEmit) {
2129 pendingEmit = false;
2131 const bool dodate = value.toDate().isValid() && (sections & DateSectionMask);
2132 const bool datechanged = (ep == AlwaysEmit || old.toDate() != value.toDate());
2133 const bool dotime = value.toTime().isValid() && (sections & TimeSectionMask);
2134 const bool timechanged = (ep == AlwaysEmit || old.toTime() != value.toTime());
2136 updateCache(value, displayText());
2138 syncCalendarWidget();
2139 if (datechanged || timechanged)
2140 emit q->dateTimeChanged(value.toDateTime());
2141 if (dodate && datechanged)
2142 emit q->dateChanged(value.toDate());
2143 if (dotime && timechanged)
2144 emit q->timeChanged(value.toTime());
2152 void QDateTimeEditPrivate::_q_editorCursorPositionChanged(int oldpos, int newpos)
2154 if (ignoreCursorPositionChanged || specialValue())
2156 const QString oldText = displayText();
2157 updateCache(value, oldText);
2159 const bool allowChange = !edit->hasSelectedText();
2160 const bool forward = oldpos <= newpos;
2161 ignoreCursorPositionChanged = true;
2162 int s = sectionAt(newpos);
2163 if (s == NoSectionIndex && forward && newpos > 0) {
2164 s = sectionAt(newpos - 1);
2169 const int selstart = edit->selectionStart();
2170 const int selSection = sectionAt(selstart);
2171 const int l = selSection != -1 ? sectionSize(selSection) : 0;
2173 if (s == NoSectionIndex) {
2174 if (l > 0 && selstart == sectionPos(selSection) && edit->selectedText().size() == l) {
2177 setSelected(selSection, true);
2180 int closest = closestSection(newpos, forward);
2181 c = sectionPos(closest) + (forward ? 0 : qMax<int>(0, sectionSize(closest)));
2184 edit->setCursorPosition(c);
2191 if (allowChange && currentSectionIndex != s) {
2192 interpret(EmitIfChanged);
2195 setSelected(s, true);
2196 } else if (!edit->hasSelectedText()) {
2197 if (oldpos < newpos) {
2198 edit->setCursorPosition(displayText().size() - (oldText.size() - c));
2200 edit->setCursorPosition(c);
2204 QDTEDEBUG << "currentSectionIndex is set to" << sectionName(sectionType(s))
2206 << "was" << sectionName(sectionType(currentSectionIndex));
2208 currentSectionIndex = s;
2209 Q_ASSERT_X(currentSectionIndex < sectionNodes.size(),
2210 "QDateTimeEditPrivate::_q_editorCursorPositionChanged()",
2211 qPrintable(QString::fromLatin1("Internal error (%1 %2)").
2212 arg(currentSectionIndex).
2213 arg(sectionNodes.size())));
2215 ignoreCursorPositionChanged = false;
2221 Try to get the format from the local settings
2223 void QDateTimeEditPrivate::readLocaleSettings()
2226 defaultTimeFormat = loc.timeFormat(QLocale::ShortFormat);
2227 defaultDateFormat = loc.dateFormat(QLocale::ShortFormat);
2228 defaultDateTimeFormat = loc.dateTimeFormat(QLocale::ShortFormat);
2231 QDateTimeEdit::Section QDateTimeEditPrivate::convertToPublic(QDateTimeParser::Section s)
2233 switch (s & ~Internal) {
2234 case AmPmSection: return QDateTimeEdit::AmPmSection;
2235 case MSecSection: return QDateTimeEdit::MSecSection;
2236 case SecondSection: return QDateTimeEdit::SecondSection;
2237 case MinuteSection: return QDateTimeEdit::MinuteSection;
2238 case DayOfWeekSection:
2239 case DaySection: return QDateTimeEdit::DaySection;
2240 case MonthSection: return QDateTimeEdit::MonthSection;
2241 case YearSection2Digits:
2242 case YearSection: return QDateTimeEdit::YearSection;
2244 case Hour24Section: return QDateTimeEdit::HourSection;
2247 case LastSection: break;
2249 return QDateTimeEdit::NoSection;
2252 QDateTimeEdit::Sections QDateTimeEditPrivate::convertSections(QDateTimeParser::Sections s)
2254 QDateTimeEdit::Sections ret = 0;
2255 if (s & QDateTimeParser::MSecSection)
2256 ret |= QDateTimeEdit::MSecSection;
2257 if (s & QDateTimeParser::SecondSection)
2258 ret |= QDateTimeEdit::SecondSection;
2259 if (s & QDateTimeParser::MinuteSection)
2260 ret |= QDateTimeEdit::MinuteSection;
2261 if (s & (QDateTimeParser::Hour24Section|QDateTimeParser::Hour12Section))
2262 ret |= QDateTimeEdit::HourSection;
2263 if (s & QDateTimeParser::AmPmSection)
2264 ret |= QDateTimeEdit::AmPmSection;
2265 if (s & (QDateTimeParser::DaySection|QDateTimeParser::DayOfWeekSection))
2266 ret |= QDateTimeEdit::DaySection;
2267 if (s & QDateTimeParser::MonthSection)
2268 ret |= QDateTimeEdit::MonthSection;
2269 if (s & (QDateTimeParser::YearSection|QDateTimeParser::YearSection2Digits))
2270 ret |= QDateTimeEdit::YearSection;
2279 void QDateTimeEdit::paintEvent(QPaintEvent *event)
2282 if (!d->calendarPopupEnabled()) {
2283 QAbstractSpinBox::paintEvent(event);
2287 QStyleOptionSpinBox opt;
2288 initStyleOption(&opt);
2290 QStyleOptionComboBox optCombo;
2292 optCombo.init(this);
2293 optCombo.editable = true;
2294 optCombo.frame = opt.frame;
2295 optCombo.subControls = opt.subControls;
2296 optCombo.activeSubControls = opt.activeSubControls;
2297 optCombo.state = opt.state;
2299 optCombo.state &= ~QStyle::State_Enabled;
2303 style()->drawComplexControl(QStyle::CC_ComboBox, &optCombo, &p, this);
2306 QString QDateTimeEditPrivate::getAmPmText(AmPm ap, Case cs) const
2309 return (cs == UpperCase ? QDateTimeEdit::tr("AM") : QDateTimeEdit::tr("am"));
2311 return (cs == UpperCase ? QDateTimeEdit::tr("PM") : QDateTimeEdit::tr("pm"));
2315 int QDateTimeEditPrivate::absoluteIndex(QDateTimeEdit::Section s, int index) const
2317 for (int i=0; i<sectionNodes.size(); ++i) {
2318 if (convertToPublic(sectionNodes.at(i).type) == s && index-- == 0) {
2322 return NoSectionIndex;
2325 int QDateTimeEditPrivate::absoluteIndex(const SectionNode &s) const
2327 return sectionNodes.indexOf(s);
2330 void QDateTimeEditPrivate::interpret(EmitPolicy ep)
2333 QString tmp = displayText();
2334 int pos = edit->cursorPosition();
2335 const QValidator::State state = q->validate(tmp, pos);
2336 if (state != QValidator::Acceptable
2337 && correctionMode == QAbstractSpinBox::CorrectToPreviousValue
2338 && (state == QValidator::Invalid || !(fieldInfo(currentSectionIndex) & AllowPartial))) {
2339 setValue(value, ep);
2342 QAbstractSpinBoxPrivate::interpret(ep);
2346 void QDateTimeEditPrivate::clearCache() const
2348 QAbstractSpinBoxPrivate::clearCache();
2353 Initialize \a option with the values from this QDataTimeEdit. This method
2354 is useful for subclasses when they need a QStyleOptionSpinBox, but don't want
2355 to fill in all the information themselves.
2357 \sa QStyleOption::initFrom()
2359 void QDateTimeEdit::initStyleOption(QStyleOptionSpinBox *option) const
2364 Q_D(const QDateTimeEdit);
2365 QAbstractSpinBox::initStyleOption(option);
2366 if (d->calendarPopupEnabled()) {
2367 option->subControls = QStyle::SC_ComboBoxFrame | QStyle::SC_ComboBoxEditField
2368 | QStyle::SC_ComboBoxArrow;
2369 if (d->arrowState == QStyle::State_Sunken)
2370 option->state |= QStyle::State_Sunken;
2372 option->state &= ~QStyle::State_Sunken;
2376 void QDateTimeEditPrivate::init(const QVariant &var)
2379 switch (var.type()) {
2380 case QVariant::Date:
2381 value = QDateTime(var.toDate(), QDATETIMEEDIT_TIME_MIN);
2382 q->setDisplayFormat(defaultDateFormat);
2383 if (sectionNodes.isEmpty()) // ### safeguard for broken locale
2384 q->setDisplayFormat(QLatin1String("dd/MM/yyyy"));
2386 case QVariant::DateTime:
2388 q->setDisplayFormat(defaultDateTimeFormat);
2389 if (sectionNodes.isEmpty()) // ### safeguard for broken locale
2390 q->setDisplayFormat(QLatin1String("dd/MM/yyyy hh:mm:ss"));
2392 case QVariant::Time:
2393 value = QDateTime(QDATETIMEEDIT_DATE_INITIAL, var.toTime());
2394 q->setDisplayFormat(defaultTimeFormat);
2395 if (sectionNodes.isEmpty()) // ### safeguard for broken locale
2396 q->setDisplayFormat(QLatin1String("hh:mm:ss"));
2399 Q_ASSERT_X(0, "QDateTimeEditPrivate::init", "Internal error");
2402 #ifdef QT_KEYPAD_NAVIGATION
2403 if (QApplication::keypadNavigationEnabled())
2404 q->setCalendarPopup(true);
2407 q->setInputMethodHints(Qt::ImhPreferNumbers);
2408 setLayoutItemMargins(QStyle::SE_DateTimeEditLayoutItem);
2411 void QDateTimeEditPrivate::_q_resetButton()
2413 updateArrow(QStyle::State_None);
2416 void QDateTimeEditPrivate::updateArrow(QStyle::StateFlag state)
2420 if (arrowState == state)
2423 if (arrowState != QStyle::State_None)
2424 buttonState |= Mouse;
2427 hoverControl = QStyle::SC_ComboBoxFrame;
2434 Returns the hover control at \a pos.
2435 This will update the hoverRect and hoverControl.
2437 QStyle::SubControl QDateTimeEditPrivate::newHoverControl(const QPoint &pos)
2439 if (!calendarPopupEnabled())
2440 return QAbstractSpinBoxPrivate::newHoverControl(pos);
2444 QStyleOptionComboBox optCombo;
2446 optCombo.editable = true;
2447 optCombo.subControls = QStyle::SC_All;
2448 hoverControl = q->style()->hitTestComplexControl(QStyle::CC_ComboBox, &optCombo, pos, q);
2449 return hoverControl;
2452 void QDateTimeEditPrivate::updateEditFieldGeometry()
2454 if (!calendarPopupEnabled()) {
2455 QAbstractSpinBoxPrivate::updateEditFieldGeometry();
2461 QStyleOptionComboBox optCombo;
2463 optCombo.editable = true;
2464 optCombo.subControls = QStyle::SC_ComboBoxEditField;
2465 edit->setGeometry(q->style()->subControlRect(QStyle::CC_ComboBox, &optCombo,
2466 QStyle::SC_ComboBoxEditField, q));
2469 QVariant QDateTimeEditPrivate::getZeroVariant() const
2471 Q_ASSERT(type == QVariant::DateTime);
2472 return QDateTime(QDATETIMEEDIT_DATE_INITIAL, QTime(), spec);
2475 void QDateTimeEditPrivate::setRange(const QVariant &min, const QVariant &max)
2477 QAbstractSpinBoxPrivate::setRange(min, max);
2478 syncCalendarWidget();
2482 bool QDateTimeEditPrivate::isSeparatorKey(const QKeyEvent *ke) const
2484 if (!ke->text().isEmpty() && currentSectionIndex + 1 < sectionNodes.size() && currentSectionIndex >= 0) {
2485 if (fieldInfo(currentSectionIndex) & Numeric) {
2486 if (ke->text().at(0).isNumber())
2488 } else if (ke->text().at(0).isLetterOrNumber()) {
2491 return separators.at(currentSectionIndex + 1).contains(ke->text());
2496 void QDateTimeEditPrivate::initCalendarPopup(QCalendarWidget *cw)
2499 if (!monthCalendar) {
2500 monthCalendar = new QCalendarPopup(q, cw);
2501 monthCalendar->setObjectName(QLatin1String("qt_datetimedit_calendar"));
2502 QObject::connect(monthCalendar, SIGNAL(newDateSelected(QDate)), q, SLOT(setDate(QDate)));
2503 QObject::connect(monthCalendar, SIGNAL(hidingCalendar(QDate)), q, SLOT(setDate(QDate)));
2504 QObject::connect(monthCalendar, SIGNAL(activated(QDate)), q, SLOT(setDate(QDate)));
2505 QObject::connect(monthCalendar, SIGNAL(activated(QDate)), monthCalendar, SLOT(close()));
2506 QObject::connect(monthCalendar, SIGNAL(resetButton()), q, SLOT(_q_resetButton()));
2508 monthCalendar->setCalendarWidget(cw);
2510 syncCalendarWidget();
2513 void QDateTimeEditPrivate::positionCalendarPopup()
2516 QPoint pos = (q->layoutDirection() == Qt::RightToLeft) ? q->rect().bottomRight() : q->rect().bottomLeft();
2517 QPoint pos2 = (q->layoutDirection() == Qt::RightToLeft) ? q->rect().topRight() : q->rect().topLeft();
2518 pos = q->mapToGlobal(pos);
2519 pos2 = q->mapToGlobal(pos2);
2520 QSize size = monthCalendar->sizeHint();
2521 QRect screen = QApplication::desktop()->availableGeometry(pos);
2522 //handle popup falling "off screen"
2523 if (q->layoutDirection() == Qt::RightToLeft) {
2524 pos.setX(pos.x()-size.width());
2525 pos2.setX(pos2.x()-size.width());
2526 if (pos.x() < screen.left())
2527 pos.setX(qMax(pos.x(), screen.left()));
2528 else if (pos.x()+size.width() > screen.right())
2529 pos.setX(qMax(pos.x()-size.width(), screen.right()-size.width()));
2531 if (pos.x()+size.width() > screen.right())
2532 pos.setX(screen.right()-size.width());
2533 pos.setX(qMax(pos.x(), screen.left()));
2535 if (pos.y() + size.height() > screen.bottom())
2536 pos.setY(pos2.y() - size.height());
2537 else if (pos.y() < screen.top())
2538 pos.setY(screen.top());
2539 if (pos.y() < screen.top())
2540 pos.setY(screen.top());
2541 if (pos.y()+size.height() > screen.bottom())
2542 pos.setY(screen.bottom()-size.height());
2543 monthCalendar->move(pos);
2546 bool QDateTimeEditPrivate::calendarPopupEnabled() const
2548 return (calendarPopup && (sections & (DateSectionMask)));
2551 void QDateTimeEditPrivate::syncCalendarWidget()
2554 if (monthCalendar) {
2555 const bool sb = monthCalendar->blockSignals(true);
2556 monthCalendar->setDateRange(q->minimumDate(), q->maximumDate());
2557 monthCalendar->setDate(q->date());
2558 monthCalendar->blockSignals(sb);
2562 QCalendarPopup::QCalendarPopup(QWidget * parent, QCalendarWidget *cw)
2563 : QWidget(parent, Qt::Popup)
2565 setAttribute(Qt::WA_WindowPropagation);
2567 dateChanged = false;
2569 verifyCalendarInstance();
2571 setCalendarWidget(cw);
2575 QCalendarWidget *QCalendarPopup::verifyCalendarInstance()
2577 if (calendar.isNull()) {
2578 QCalendarWidget *cw = new QCalendarWidget(this);
2579 cw->setVerticalHeaderFormat(QCalendarWidget::NoVerticalHeader);
2580 #ifdef QT_KEYPAD_NAVIGATION
2581 if (QApplication::keypadNavigationEnabled())
2582 cw->setHorizontalHeaderFormat(QCalendarWidget::SingleLetterDayNames);
2584 setCalendarWidget(cw);
2587 return calendar.data();
2591 void QCalendarPopup::setCalendarWidget(QCalendarWidget *cw)
2594 QVBoxLayout *widgetLayout = qobject_cast<QVBoxLayout*>(layout());
2595 if (!widgetLayout) {
2596 widgetLayout = new QVBoxLayout(this);
2597 widgetLayout->setMargin(0);
2598 widgetLayout->setSpacing(0);
2600 delete calendar.data();
2601 calendar = QWeakPointer<QCalendarWidget>(cw);
2602 widgetLayout->addWidget(cw);
2604 connect(cw, SIGNAL(activated(QDate)), this, SLOT(dateSelected(QDate)));
2605 connect(cw, SIGNAL(clicked(QDate)), this, SLOT(dateSelected(QDate)));
2606 connect(cw, SIGNAL(selectionChanged()), this, SLOT(dateSelectionChanged()));
2612 void QCalendarPopup::setDate(const QDate &date)
2615 verifyCalendarInstance()->setSelectedDate(date);
2618 void QCalendarPopup::setDateRange(const QDate &min, const QDate &max)
2620 QCalendarWidget *cw = verifyCalendarInstance();
2621 cw->setMinimumDate(min);
2622 cw->setMaximumDate(max);
2625 void QCalendarPopup::mousePressEvent(QMouseEvent *event)
2627 QDateTimeEdit *dateTime = qobject_cast<QDateTimeEdit *>(parentWidget());
2629 QStyleOptionComboBox opt;
2631 QRect arrowRect = dateTime->style()->subControlRect(QStyle::CC_ComboBox, &opt,
2632 QStyle::SC_ComboBoxArrow, dateTime);
2633 arrowRect.moveTo(dateTime->mapToGlobal(arrowRect .topLeft()));
2634 if (arrowRect.contains(event->globalPos()) || rect().contains(event->pos()))
2635 setAttribute(Qt::WA_NoMouseReplay);
2637 QWidget::mousePressEvent(event);
2640 void QCalendarPopup::mouseReleaseEvent(QMouseEvent*)
2645 bool QCalendarPopup::event(QEvent *event)
2647 if (event->type() == QEvent::KeyPress) {
2648 QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
2649 if (keyEvent->key()== Qt::Key_Escape)
2650 dateChanged = false;
2652 return QWidget::event(event);
2655 void QCalendarPopup::dateSelectionChanged()
2658 emit newDateSelected(verifyCalendarInstance()->selectedDate());
2660 void QCalendarPopup::dateSelected(const QDate &date)
2663 emit activated(date);
2667 void QCalendarPopup::hideEvent(QHideEvent *)
2671 emit hidingCalendar(oldDate);
2675 #include "moc_qdatetimeedit.cpp"
2677 #endif // QT_NO_DATETIMEEDIT