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 \property QTimeEdit::time
1568 \sa QDateTimeEdit::time
1572 \fn void QTimeEdit::userTimeChanged(const QTime &time)
1574 This signal only exists to fully implement the time Q_PROPERTY on the class.
1575 Normally timeChanged should be used instead.
1583 \brief The QDateEdit class provides a widget for editing dates based on
1584 the QDateTimeEdit widget.
1586 \ingroup basicwidgets
1589 Many of the properties and functions provided by QDateEdit are implemented in
1590 QDateTimeEdit. The following properties are most relevant to users of this
1594 \li \l{QDateTimeEdit::date}{date} holds the date displayed by the widget.
1595 \li \l{QDateTimeEdit::minimumDate}{minimumDate} defines the minimum (earliest)
1596 date that can be set by the user.
1597 \li \l{QDateTimeEdit::maximumDate}{maximumDate} defines the maximum (latest) date
1598 that can be set by the user.
1599 \li \l{QDateTimeEdit::displayFormat}{displayFormat} contains a string that is used
1600 to format the date displayed in the widget.
1604 \row \li \inlineimage windowsxp-dateedit.png Screenshot of a Windows XP style date editing widget
1605 \li A date editing widget shown in the \l{Windows XP Style Widget Gallery}{Windows XP widget style}.
1606 \row \li \inlineimage macintosh-dateedit.png Screenshot of a Macintosh style date editing widget
1607 \li A date editing widget shown in the \l{Macintosh Style Widget Gallery}{Macintosh widget style}.
1608 \row \li \inlineimage plastique-dateedit.png Screenshot of a Plastique style date editing widget
1609 \li A date editing widget shown in the \l{Plastique Style Widget Gallery}{Plastique widget style}.
1612 \sa QTimeEdit, QDateTimeEdit
1616 Constructs an empty date editor with a \a parent.
1619 QDateEdit::QDateEdit(QWidget *parent)
1620 : QDateTimeEdit(QDATETIMEEDIT_DATE_INITIAL, QVariant::Date, parent)
1622 connect(this, SIGNAL(dateChanged(QDate)), SIGNAL(userDateChanged(QDate)));
1626 Constructs an empty date editor with a \a parent. The date is set
1630 QDateEdit::QDateEdit(const QDate &date, QWidget *parent)
1631 : QDateTimeEdit(date, QVariant::Date, parent)
1636 \property QDateEdit::date
1638 \sa QDateTimeEdit::date
1642 \fn void QDateEdit::userDateChanged(const QDate &date)
1644 This signal only exists to fully implement the date Q_PROPERTY on the class.
1645 Normally dateChanged should be used instead.
1651 // --- QDateTimeEditPrivate ---
1655 Constructs a QDateTimeEditPrivate object
1659 QDateTimeEditPrivate::QDateTimeEditPrivate()
1660 : QDateTimeParser(QVariant::DateTime, QDateTimeParser::DateTimeEdit)
1662 hasHadFocus = false;
1663 formatExplicitlySet = false;
1666 type = QVariant::DateTime;
1669 currentSectionIndex = FirstSectionIndex;
1671 first.type = FirstSection;
1672 last.type = LastSection;
1673 none.type = NoSection;
1678 calendarPopup = false;
1679 minimum = QDATETIMEEDIT_COMPAT_DATETIME_MIN;
1680 maximum = QDATETIMEEDIT_DATETIME_MAX;
1681 arrowState = QStyle::State_None;
1683 readLocaleSettings();
1685 #ifdef QT_KEYPAD_NAVIGATION
1686 focusOnButton = false;
1690 void QDateTimeEditPrivate::updateTimeSpec()
1692 minimum = minimum.toDateTime().toTimeSpec(spec);
1693 maximum = maximum.toDateTime().toTimeSpec(spec);
1694 value = value.toDateTime().toTimeSpec(spec);
1696 // time zone changes can lead to 00:00:00 becomes 01:00:00 and 23:59:59 becomes 00:59:59 (invalid range)
1697 const bool dateShown = (sections & QDateTimeEdit::DateSections_Mask);
1699 if (minimum.toTime() >= maximum.toTime()){
1700 minimum = QDateTime(value.toDate(), QDATETIMEEDIT_TIME_MIN, spec);
1701 maximum = QDateTime(value.toDate(), QDATETIMEEDIT_TIME_MAX, spec);
1706 void QDateTimeEditPrivate::updateEdit()
1708 const QString newText = (specialValue() ? specialValueText : textFromValue(value));
1709 if (newText == displayText())
1711 int selsize = edit->selectedText().size();
1712 const bool sb = edit->blockSignals(true);
1714 edit->setText(newText);
1717 #ifdef QT_KEYPAD_NAVIGATION
1718 && !(QApplication::keypadNavigationEnabled() && !edit->hasEditFocus())
1721 int cursor = sectionPos(currentSectionIndex);
1722 QDTEDEBUG << "cursor is " << cursor << currentSectionIndex;
1723 cursor = qBound(0, cursor, displayText().size());
1724 QDTEDEBUG << cursor;
1726 edit->setSelection(cursor, selsize);
1727 QDTEDEBUG << cursor << selsize;
1729 edit->setCursorPosition(cursor);
1730 QDTEDEBUG << cursor;
1734 edit->blockSignals(sb);
1741 Selects the section \a s. If \a forward is false selects backwards.
1744 void QDateTimeEditPrivate::setSelected(int sectionIndex, bool forward)
1747 #ifdef QT_KEYPAD_NAVIGATION
1748 || (QApplication::keypadNavigationEnabled() && !edit->hasEditFocus())
1753 const SectionNode &node = sectionNode(sectionIndex);
1754 if (node.type == NoSection || node.type == LastSection || node.type == FirstSection)
1757 updateCache(value, displayText());
1758 const int size = sectionSize(sectionIndex);
1760 edit->setSelection(sectionPos(node), size);
1762 edit->setSelection(sectionPos(node) + size, -size);
1770 Returns the section at index \a index or NoSection if there are no sections there.
1773 int QDateTimeEditPrivate::sectionAt(int pos) const
1775 if (pos < separators.first().size()) {
1776 return (pos == 0 ? FirstSectionIndex : NoSectionIndex);
1777 } else if (displayText().size() - pos < separators.last().size() + 1) {
1778 if (separators.last().size() == 0) {
1779 return sectionNodes.count() - 1;
1781 return (pos == displayText().size() ? LastSectionIndex : NoSectionIndex);
1783 updateCache(value, displayText());
1785 for (int i=0; i<sectionNodes.size(); ++i) {
1786 const int tmp = sectionPos(i);
1787 if (pos < tmp + sectionSize(i)) {
1788 return (pos < tmp ? -1 : i);
1797 Returns the closest section of index \a index. Searches forward
1798 for a section if \a forward is true. Otherwise searches backwards.
1801 int QDateTimeEditPrivate::closestSection(int pos, bool forward) const
1804 if (pos < separators.first().size()) {
1805 return forward ? 0 : FirstSectionIndex;
1806 } else if (displayText().size() - pos < separators.last().size() + 1) {
1807 return forward ? LastSectionIndex : sectionNodes.size() - 1;
1809 updateCache(value, displayText());
1810 for (int i=0; i<sectionNodes.size(); ++i) {
1811 const int tmp = sectionPos(sectionNodes.at(i));
1812 if (pos < tmp + sectionSize(i)) {
1813 if (pos < tmp && !forward) {
1817 } else if (i == sectionNodes.size() - 1 && pos > tmp) {
1821 qWarning("QDateTimeEdit: Internal Error: closestSection returned NoSection");
1822 return NoSectionIndex;
1828 Returns a copy of the section that is before or after \a current, depending on \a forward.
1831 int QDateTimeEditPrivate::nextPrevSection(int current, bool forward) const
1833 Q_Q(const QDateTimeEdit);
1834 if (q->isRightToLeft())
1838 case FirstSectionIndex: return forward ? 0 : FirstSectionIndex;
1839 case LastSectionIndex: return (forward ? LastSectionIndex : sectionNodes.size() - 1);
1840 case NoSectionIndex: return FirstSectionIndex;
1843 Q_ASSERT(current >= 0 && current < sectionNodes.size());
1845 current += (forward ? 1 : -1);
1846 if (current >= sectionNodes.size()) {
1847 return LastSectionIndex;
1848 } else if (current < 0) {
1849 return FirstSectionIndex;
1858 Clears the text of section \a s.
1861 void QDateTimeEditPrivate::clearSection(int index)
1863 const QLatin1Char space(' ');
1864 int cursorPos = edit->cursorPosition();
1865 bool blocked = edit->blockSignals(true);
1866 QString t = edit->text();
1867 const int pos = sectionPos(index);
1869 qWarning("QDateTimeEdit: Internal error (%s:%d)", __FILE__, __LINE__);
1872 const int size = sectionSize(index);
1873 t.replace(pos, size, QString().fill(space, size));
1875 edit->setCursorPosition(cursorPos);
1876 QDTEDEBUG << cursorPos;
1878 edit->blockSignals(blocked);
1885 updates the cached values
1888 void QDateTimeEditPrivate::updateCache(const QVariant &val, const QString &str) const
1890 if (val != cachedValue || str != cachedText || cacheGuard) {
1893 int unused = edit->cursorPosition();
1894 QValidator::State unusedState;
1895 validateAndInterpret(copy, unused, unusedState);
1903 parses and validates \a input
1906 QDateTime QDateTimeEditPrivate::validateAndInterpret(QString &input, int &position,
1907 QValidator::State &state, bool fixup) const
1909 if (input.isEmpty()) {
1910 if (sectionNodes.size() == 1 || !specialValueText.isEmpty()) {
1911 state = QValidator::Intermediate;
1913 state = QValidator::Invalid;
1915 return getZeroVariant().toDateTime();
1916 } else if (cachedText == input && !fixup) {
1917 state = cachedState;
1918 return cachedValue.toDateTime();
1919 } else if (!specialValueText.isEmpty()) {
1920 bool changeCase = false;
1921 const int max = qMin(specialValueText.size(), input.size());
1923 for (i=0; i<max; ++i) {
1924 const QChar ic = input.at(i);
1925 const QChar sc = specialValueText.at(i);
1927 if (sc.toLower() == ic.toLower()) {
1935 state = specialValueText.size() == input.size() ? QValidator::Acceptable : QValidator::Intermediate;
1937 input = specialValueText.left(max);
1939 return minimum.toDateTime();
1942 StateNode tmp = parse(input, position, value.toDateTime(), fixup);
1944 state = QValidator::State(int(tmp.state));
1945 if (state == QValidator::Acceptable) {
1946 if (tmp.conflicts && conflictGuard != tmp.value) {
1947 conflictGuard = tmp.value;
1949 input = textFromValue(tmp.value);
1950 updateCache(tmp.value, input);
1951 conflictGuard.clear();
1954 cachedState = state;
1955 cachedValue = tmp.value;
1960 return (tmp.value.isNull() ? getZeroVariant().toDateTime() : tmp.value);
1968 QString QDateTimeEditPrivate::textFromValue(const QVariant &f) const
1970 Q_Q(const QDateTimeEdit);
1971 return q->textFromDateTime(f.toDateTime());
1977 This function's name is slightly confusing; it is not to be confused
1978 with QAbstractSpinBox::valueFromText().
1981 QVariant QDateTimeEditPrivate::valueFromText(const QString &f) const
1983 Q_Q(const QDateTimeEdit);
1984 return q->dateTimeFromText(f).toTimeSpec(spec);
1991 Internal function called by QDateTimeEdit::stepBy(). Also takes a
1992 Section for which section to step on and a bool \a test for
1993 whether or not to modify the internal cachedDay variable. This is
1994 necessary because the function is called from the const function
1995 QDateTimeEdit::stepEnabled() as well as QDateTimeEdit::stepBy().
1998 QDateTime QDateTimeEditPrivate::stepBy(int sectionIndex, int steps, bool test) const
2000 Q_Q(const QDateTimeEdit);
2001 QDateTime v = value.toDateTime();
2002 QString str = displayText();
2003 int pos = edit->cursorPosition();
2004 const SectionNode sn = sectionNode(sectionIndex);
2007 // to make sure it behaves reasonably when typing something and then stepping in non-tracking mode
2008 if (!test && pendingEmit) {
2009 if (q->validate(str, pos) != QValidator::Acceptable) {
2010 v = value.toDateTime();
2012 v = q->dateTimeFromText(str);
2014 val = getDigit(v, sectionIndex);
2016 val = getDigit(v, sectionIndex);
2021 const int min = absoluteMin(sectionIndex);
2022 const int max = absoluteMax(sectionIndex, value.toDateTime());
2025 val = (wrapping ? max - (min - val) + 1 : min);
2026 } else if (val > max) {
2027 val = (wrapping ? min + val - max - 1 : max);
2031 const int oldDay = v.date().day();
2033 setDigit(v, sectionIndex, val);
2034 // if this sets year or month it will make
2035 // sure that days are lowered if needed.
2037 const QDateTime minimumDateTime = minimum.toDateTime();
2038 const QDateTime maximumDateTime = maximum.toDateTime();
2039 // changing one section should only modify that section, if possible
2040 if (sn.type != AmPmSection && (v < minimumDateTime || v > maximumDateTime)) {
2041 const int localmin = getDigit(minimumDateTime, sectionIndex);
2042 const int localmax = getDigit(maximumDateTime, sectionIndex);
2045 // just because we hit the roof in one direction, it
2046 // doesn't mean that we hit the floor in the other
2048 setDigit(v, sectionIndex, min);
2049 if (!(sn.type & (DaySection|DayOfWeekSectionShort|DayOfWeekSectionLong)) && sections & DateSectionMask) {
2050 const int daysInMonth = v.date().daysInMonth();
2051 if (v.date().day() < oldDay && v.date().day() < daysInMonth) {
2052 const int adds = qMin(oldDay, daysInMonth);
2053 v = v.addDays(adds - v.date().day());
2057 if (v < minimumDateTime) {
2058 setDigit(v, sectionIndex, localmin);
2059 if (v < minimumDateTime)
2060 setDigit(v, sectionIndex, localmin + 1);
2063 setDigit(v, sectionIndex, max);
2064 if (!(sn.type & (DaySection|DayOfWeekSectionShort|DayOfWeekSectionLong)) && sections & DateSectionMask) {
2065 const int daysInMonth = v.date().daysInMonth();
2066 if (v.date().day() < oldDay && v.date().day() < daysInMonth) {
2067 const int adds = qMin(oldDay, daysInMonth);
2068 v = v.addDays(adds - v.date().day());
2072 if (v > maximumDateTime) {
2073 setDigit(v, sectionIndex, localmax);
2074 if (v > maximumDateTime)
2075 setDigit(v, sectionIndex, localmax - 1);
2079 setDigit(v, sectionIndex, (steps > 0 ? localmax : localmin));
2082 if (!test && oldDay != v.date().day() && !(sn.type & (DaySection|DayOfWeekSectionShort|DayOfWeekSectionLong))) {
2083 // this should not happen when called from stepEnabled
2084 cachedDay = qMax<int>(oldDay, cachedDay);
2087 if (v < minimumDateTime) {
2090 setDigit(t, sectionIndex, steps < 0 ? max : min);
2091 bool mincmp = (t >= minimumDateTime);
2092 bool maxcmp = (t <= maximumDateTime);
2093 if (!mincmp || !maxcmp) {
2094 setDigit(t, sectionIndex, getDigit(steps < 0
2096 : minimumDateTime, sectionIndex));
2097 mincmp = (t >= minimumDateTime);
2098 maxcmp = (t <= maximumDateTime);
2100 if (mincmp && maxcmp) {
2104 v = value.toDateTime();
2106 } else if (v > maximumDateTime) {
2109 setDigit(t, sectionIndex, steps > 0 ? min : max);
2110 bool mincmp = (t >= minimumDateTime);
2111 bool maxcmp = (t <= maximumDateTime);
2112 if (!mincmp || !maxcmp) {
2113 setDigit(t, sectionIndex, getDigit(steps > 0 ?
2115 maximumDateTime, sectionIndex));
2116 mincmp = (t >= minimumDateTime);
2117 maxcmp = (t <= maximumDateTime);
2119 if (mincmp && maxcmp) {
2123 v = value.toDateTime();
2127 const QDateTime ret = bound(v, value, steps).toDateTime().toTimeSpec(spec);
2135 void QDateTimeEditPrivate::emitSignals(EmitPolicy ep, const QVariant &old)
2138 if (ep == NeverEmit) {
2141 pendingEmit = false;
2143 const bool dodate = value.toDate().isValid() && (sections & DateSectionMask);
2144 const bool datechanged = (ep == AlwaysEmit || old.toDate() != value.toDate());
2145 const bool dotime = value.toTime().isValid() && (sections & TimeSectionMask);
2146 const bool timechanged = (ep == AlwaysEmit || old.toTime() != value.toTime());
2148 updateCache(value, displayText());
2150 syncCalendarWidget();
2151 if (datechanged || timechanged)
2152 emit q->dateTimeChanged(value.toDateTime());
2153 if (dodate && datechanged)
2154 emit q->dateChanged(value.toDate());
2155 if (dotime && timechanged)
2156 emit q->timeChanged(value.toTime());
2164 void QDateTimeEditPrivate::_q_editorCursorPositionChanged(int oldpos, int newpos)
2166 if (ignoreCursorPositionChanged || specialValue())
2168 const QString oldText = displayText();
2169 updateCache(value, oldText);
2171 const bool allowChange = !edit->hasSelectedText();
2172 const bool forward = oldpos <= newpos;
2173 ignoreCursorPositionChanged = true;
2174 int s = sectionAt(newpos);
2175 if (s == NoSectionIndex && forward && newpos > 0) {
2176 s = sectionAt(newpos - 1);
2181 const int selstart = edit->selectionStart();
2182 const int selSection = sectionAt(selstart);
2183 const int l = selSection != -1 ? sectionSize(selSection) : 0;
2185 if (s == NoSectionIndex) {
2186 if (l > 0 && selstart == sectionPos(selSection) && edit->selectedText().size() == l) {
2189 setSelected(selSection, true);
2192 int closest = closestSection(newpos, forward);
2193 c = sectionPos(closest) + (forward ? 0 : qMax<int>(0, sectionSize(closest)));
2196 edit->setCursorPosition(c);
2203 if (allowChange && currentSectionIndex != s) {
2204 interpret(EmitIfChanged);
2207 setSelected(s, true);
2208 } else if (!edit->hasSelectedText()) {
2209 if (oldpos < newpos) {
2210 edit->setCursorPosition(displayText().size() - (oldText.size() - c));
2212 edit->setCursorPosition(c);
2216 QDTEDEBUG << "currentSectionIndex is set to" << sectionName(sectionType(s))
2218 << "was" << sectionName(sectionType(currentSectionIndex));
2220 currentSectionIndex = s;
2221 Q_ASSERT_X(currentSectionIndex < sectionNodes.size(),
2222 "QDateTimeEditPrivate::_q_editorCursorPositionChanged()",
2223 qPrintable(QString::fromLatin1("Internal error (%1 %2)").
2224 arg(currentSectionIndex).
2225 arg(sectionNodes.size())));
2227 ignoreCursorPositionChanged = false;
2233 Try to get the format from the local settings
2235 void QDateTimeEditPrivate::readLocaleSettings()
2238 defaultTimeFormat = loc.timeFormat(QLocale::ShortFormat);
2239 defaultDateFormat = loc.dateFormat(QLocale::ShortFormat);
2240 defaultDateTimeFormat = loc.dateTimeFormat(QLocale::ShortFormat);
2243 QDateTimeEdit::Section QDateTimeEditPrivate::convertToPublic(QDateTimeParser::Section s)
2245 switch (s & ~Internal) {
2246 case AmPmSection: return QDateTimeEdit::AmPmSection;
2247 case MSecSection: return QDateTimeEdit::MSecSection;
2248 case SecondSection: return QDateTimeEdit::SecondSection;
2249 case MinuteSection: return QDateTimeEdit::MinuteSection;
2250 case DayOfWeekSectionShort:
2251 case DayOfWeekSectionLong:
2252 case DaySection: return QDateTimeEdit::DaySection;
2253 case MonthSection: return QDateTimeEdit::MonthSection;
2254 case YearSection2Digits:
2255 case YearSection: return QDateTimeEdit::YearSection;
2257 case Hour24Section: return QDateTimeEdit::HourSection;
2260 case LastSection: break;
2262 return QDateTimeEdit::NoSection;
2265 QDateTimeEdit::Sections QDateTimeEditPrivate::convertSections(QDateTimeParser::Sections s)
2267 QDateTimeEdit::Sections ret = 0;
2268 if (s & QDateTimeParser::MSecSection)
2269 ret |= QDateTimeEdit::MSecSection;
2270 if (s & QDateTimeParser::SecondSection)
2271 ret |= QDateTimeEdit::SecondSection;
2272 if (s & QDateTimeParser::MinuteSection)
2273 ret |= QDateTimeEdit::MinuteSection;
2274 if (s & (QDateTimeParser::Hour24Section|QDateTimeParser::Hour12Section))
2275 ret |= QDateTimeEdit::HourSection;
2276 if (s & QDateTimeParser::AmPmSection)
2277 ret |= QDateTimeEdit::AmPmSection;
2278 if (s & (QDateTimeParser::DaySection|QDateTimeParser::DayOfWeekSectionShort|QDateTimeParser::DayOfWeekSectionLong))
2279 ret |= QDateTimeEdit::DaySection;
2280 if (s & QDateTimeParser::MonthSection)
2281 ret |= QDateTimeEdit::MonthSection;
2282 if (s & (QDateTimeParser::YearSection|QDateTimeParser::YearSection2Digits))
2283 ret |= QDateTimeEdit::YearSection;
2292 void QDateTimeEdit::paintEvent(QPaintEvent *event)
2295 if (!d->calendarPopupEnabled()) {
2296 QAbstractSpinBox::paintEvent(event);
2300 QStyleOptionSpinBox opt;
2301 initStyleOption(&opt);
2303 QStyleOptionComboBox optCombo;
2305 optCombo.init(this);
2306 optCombo.editable = true;
2307 optCombo.frame = opt.frame;
2308 optCombo.subControls = opt.subControls;
2309 optCombo.activeSubControls = opt.activeSubControls;
2310 optCombo.state = opt.state;
2312 optCombo.state &= ~QStyle::State_Enabled;
2316 style()->drawComplexControl(QStyle::CC_ComboBox, &optCombo, &p, this);
2319 QString QDateTimeEditPrivate::getAmPmText(AmPm ap, Case cs) const
2322 return (cs == UpperCase ? QDateTimeEdit::tr("AM") : QDateTimeEdit::tr("am"));
2324 return (cs == UpperCase ? QDateTimeEdit::tr("PM") : QDateTimeEdit::tr("pm"));
2328 int QDateTimeEditPrivate::absoluteIndex(QDateTimeEdit::Section s, int index) const
2330 for (int i=0; i<sectionNodes.size(); ++i) {
2331 if (convertToPublic(sectionNodes.at(i).type) == s && index-- == 0) {
2335 return NoSectionIndex;
2338 int QDateTimeEditPrivate::absoluteIndex(const SectionNode &s) const
2340 return sectionNodes.indexOf(s);
2343 void QDateTimeEditPrivate::interpret(EmitPolicy ep)
2346 QString tmp = displayText();
2347 int pos = edit->cursorPosition();
2348 const QValidator::State state = q->validate(tmp, pos);
2349 if (state != QValidator::Acceptable
2350 && correctionMode == QAbstractSpinBox::CorrectToPreviousValue
2351 && (state == QValidator::Invalid || !(fieldInfo(currentSectionIndex) & AllowPartial))) {
2352 setValue(value, ep);
2355 QAbstractSpinBoxPrivate::interpret(ep);
2359 void QDateTimeEditPrivate::clearCache() const
2361 QAbstractSpinBoxPrivate::clearCache();
2366 Initialize \a option with the values from this QDataTimeEdit. This method
2367 is useful for subclasses when they need a QStyleOptionSpinBox, but don't want
2368 to fill in all the information themselves.
2370 \sa QStyleOption::initFrom()
2372 void QDateTimeEdit::initStyleOption(QStyleOptionSpinBox *option) const
2377 Q_D(const QDateTimeEdit);
2378 QAbstractSpinBox::initStyleOption(option);
2379 if (d->calendarPopupEnabled()) {
2380 option->subControls = QStyle::SC_ComboBoxFrame | QStyle::SC_ComboBoxEditField
2381 | QStyle::SC_ComboBoxArrow;
2382 if (d->arrowState == QStyle::State_Sunken)
2383 option->state |= QStyle::State_Sunken;
2385 option->state &= ~QStyle::State_Sunken;
2389 void QDateTimeEditPrivate::init(const QVariant &var)
2392 switch (var.type()) {
2393 case QVariant::Date:
2394 value = QDateTime(var.toDate(), QDATETIMEEDIT_TIME_MIN);
2395 q->setDisplayFormat(defaultDateFormat);
2396 if (sectionNodes.isEmpty()) // ### safeguard for broken locale
2397 q->setDisplayFormat(QLatin1String("dd/MM/yyyy"));
2399 case QVariant::DateTime:
2401 q->setDisplayFormat(defaultDateTimeFormat);
2402 if (sectionNodes.isEmpty()) // ### safeguard for broken locale
2403 q->setDisplayFormat(QLatin1String("dd/MM/yyyy hh:mm:ss"));
2405 case QVariant::Time:
2406 value = QDateTime(QDATETIMEEDIT_DATE_INITIAL, var.toTime());
2407 q->setDisplayFormat(defaultTimeFormat);
2408 if (sectionNodes.isEmpty()) // ### safeguard for broken locale
2409 q->setDisplayFormat(QLatin1String("hh:mm:ss"));
2412 Q_ASSERT_X(0, "QDateTimeEditPrivate::init", "Internal error");
2415 #ifdef QT_KEYPAD_NAVIGATION
2416 if (QApplication::keypadNavigationEnabled())
2417 q->setCalendarPopup(true);
2420 q->setInputMethodHints(Qt::ImhPreferNumbers);
2421 setLayoutItemMargins(QStyle::SE_DateTimeEditLayoutItem);
2424 void QDateTimeEditPrivate::_q_resetButton()
2426 updateArrow(QStyle::State_None);
2429 void QDateTimeEditPrivate::updateArrow(QStyle::StateFlag state)
2433 if (arrowState == state)
2436 if (arrowState != QStyle::State_None)
2437 buttonState |= Mouse;
2440 hoverControl = QStyle::SC_ComboBoxFrame;
2447 Returns the hover control at \a pos.
2448 This will update the hoverRect and hoverControl.
2450 QStyle::SubControl QDateTimeEditPrivate::newHoverControl(const QPoint &pos)
2452 if (!calendarPopupEnabled())
2453 return QAbstractSpinBoxPrivate::newHoverControl(pos);
2457 QStyleOptionComboBox optCombo;
2459 optCombo.editable = true;
2460 optCombo.subControls = QStyle::SC_All;
2461 hoverControl = q->style()->hitTestComplexControl(QStyle::CC_ComboBox, &optCombo, pos, q);
2462 return hoverControl;
2465 void QDateTimeEditPrivate::updateEditFieldGeometry()
2467 if (!calendarPopupEnabled()) {
2468 QAbstractSpinBoxPrivate::updateEditFieldGeometry();
2474 QStyleOptionComboBox optCombo;
2476 optCombo.editable = true;
2477 optCombo.subControls = QStyle::SC_ComboBoxEditField;
2478 edit->setGeometry(q->style()->subControlRect(QStyle::CC_ComboBox, &optCombo,
2479 QStyle::SC_ComboBoxEditField, q));
2482 QVariant QDateTimeEditPrivate::getZeroVariant() const
2484 Q_ASSERT(type == QVariant::DateTime);
2485 return QDateTime(QDATETIMEEDIT_DATE_INITIAL, QTime(), spec);
2488 void QDateTimeEditPrivate::setRange(const QVariant &min, const QVariant &max)
2490 QAbstractSpinBoxPrivate::setRange(min, max);
2491 syncCalendarWidget();
2495 bool QDateTimeEditPrivate::isSeparatorKey(const QKeyEvent *ke) const
2497 if (!ke->text().isEmpty() && currentSectionIndex + 1 < sectionNodes.size() && currentSectionIndex >= 0) {
2498 if (fieldInfo(currentSectionIndex) & Numeric) {
2499 if (ke->text().at(0).isNumber())
2501 } else if (ke->text().at(0).isLetterOrNumber()) {
2504 return separators.at(currentSectionIndex + 1).contains(ke->text());
2509 void QDateTimeEditPrivate::initCalendarPopup(QCalendarWidget *cw)
2512 if (!monthCalendar) {
2513 monthCalendar = new QCalendarPopup(q, cw);
2514 monthCalendar->setObjectName(QLatin1String("qt_datetimedit_calendar"));
2515 QObject::connect(monthCalendar, SIGNAL(newDateSelected(QDate)), q, SLOT(setDate(QDate)));
2516 QObject::connect(monthCalendar, SIGNAL(hidingCalendar(QDate)), q, SLOT(setDate(QDate)));
2517 QObject::connect(monthCalendar, SIGNAL(activated(QDate)), q, SLOT(setDate(QDate)));
2518 QObject::connect(monthCalendar, SIGNAL(activated(QDate)), monthCalendar, SLOT(close()));
2519 QObject::connect(monthCalendar, SIGNAL(resetButton()), q, SLOT(_q_resetButton()));
2521 monthCalendar->setCalendarWidget(cw);
2523 syncCalendarWidget();
2526 void QDateTimeEditPrivate::positionCalendarPopup()
2529 QPoint pos = (q->layoutDirection() == Qt::RightToLeft) ? q->rect().bottomRight() : q->rect().bottomLeft();
2530 QPoint pos2 = (q->layoutDirection() == Qt::RightToLeft) ? q->rect().topRight() : q->rect().topLeft();
2531 pos = q->mapToGlobal(pos);
2532 pos2 = q->mapToGlobal(pos2);
2533 QSize size = monthCalendar->sizeHint();
2534 QRect screen = QApplication::desktop()->availableGeometry(pos);
2535 //handle popup falling "off screen"
2536 if (q->layoutDirection() == Qt::RightToLeft) {
2537 pos.setX(pos.x()-size.width());
2538 pos2.setX(pos2.x()-size.width());
2539 if (pos.x() < screen.left())
2540 pos.setX(qMax(pos.x(), screen.left()));
2541 else if (pos.x()+size.width() > screen.right())
2542 pos.setX(qMax(pos.x()-size.width(), screen.right()-size.width()));
2544 if (pos.x()+size.width() > screen.right())
2545 pos.setX(screen.right()-size.width());
2546 pos.setX(qMax(pos.x(), screen.left()));
2548 if (pos.y() + size.height() > screen.bottom())
2549 pos.setY(pos2.y() - size.height());
2550 else if (pos.y() < screen.top())
2551 pos.setY(screen.top());
2552 if (pos.y() < screen.top())
2553 pos.setY(screen.top());
2554 if (pos.y()+size.height() > screen.bottom())
2555 pos.setY(screen.bottom()-size.height());
2556 monthCalendar->move(pos);
2559 bool QDateTimeEditPrivate::calendarPopupEnabled() const
2561 return (calendarPopup && (sections & (DateSectionMask)));
2564 void QDateTimeEditPrivate::syncCalendarWidget()
2567 if (monthCalendar) {
2568 const bool sb = monthCalendar->blockSignals(true);
2569 monthCalendar->setDateRange(q->minimumDate(), q->maximumDate());
2570 monthCalendar->setDate(q->date());
2571 monthCalendar->blockSignals(sb);
2575 QCalendarPopup::QCalendarPopup(QWidget * parent, QCalendarWidget *cw)
2576 : QWidget(parent, Qt::Popup)
2578 setAttribute(Qt::WA_WindowPropagation);
2580 dateChanged = false;
2582 verifyCalendarInstance();
2584 setCalendarWidget(cw);
2588 QCalendarWidget *QCalendarPopup::verifyCalendarInstance()
2590 if (calendar.isNull()) {
2591 QCalendarWidget *cw = new QCalendarWidget(this);
2592 cw->setVerticalHeaderFormat(QCalendarWidget::NoVerticalHeader);
2593 #ifdef QT_KEYPAD_NAVIGATION
2594 if (QApplication::keypadNavigationEnabled())
2595 cw->setHorizontalHeaderFormat(QCalendarWidget::SingleLetterDayNames);
2597 setCalendarWidget(cw);
2600 return calendar.data();
2604 void QCalendarPopup::setCalendarWidget(QCalendarWidget *cw)
2607 QVBoxLayout *widgetLayout = qobject_cast<QVBoxLayout*>(layout());
2608 if (!widgetLayout) {
2609 widgetLayout = new QVBoxLayout(this);
2610 widgetLayout->setMargin(0);
2611 widgetLayout->setSpacing(0);
2613 delete calendar.data();
2614 calendar = QPointer<QCalendarWidget>(cw);
2615 widgetLayout->addWidget(cw);
2617 connect(cw, SIGNAL(activated(QDate)), this, SLOT(dateSelected(QDate)));
2618 connect(cw, SIGNAL(clicked(QDate)), this, SLOT(dateSelected(QDate)));
2619 connect(cw, SIGNAL(selectionChanged()), this, SLOT(dateSelectionChanged()));
2625 void QCalendarPopup::setDate(const QDate &date)
2628 verifyCalendarInstance()->setSelectedDate(date);
2631 void QCalendarPopup::setDateRange(const QDate &min, const QDate &max)
2633 QCalendarWidget *cw = verifyCalendarInstance();
2634 cw->setMinimumDate(min);
2635 cw->setMaximumDate(max);
2638 void QCalendarPopup::mousePressEvent(QMouseEvent *event)
2640 QDateTimeEdit *dateTime = qobject_cast<QDateTimeEdit *>(parentWidget());
2642 QStyleOptionComboBox opt;
2644 QRect arrowRect = dateTime->style()->subControlRect(QStyle::CC_ComboBox, &opt,
2645 QStyle::SC_ComboBoxArrow, dateTime);
2646 arrowRect.moveTo(dateTime->mapToGlobal(arrowRect .topLeft()));
2647 if (arrowRect.contains(event->globalPos()) || rect().contains(event->pos()))
2648 setAttribute(Qt::WA_NoMouseReplay);
2650 QWidget::mousePressEvent(event);
2653 void QCalendarPopup::mouseReleaseEvent(QMouseEvent*)
2658 bool QCalendarPopup::event(QEvent *event)
2660 if (event->type() == QEvent::KeyPress) {
2661 QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
2662 if (keyEvent->key()== Qt::Key_Escape)
2663 dateChanged = false;
2665 return QWidget::event(event);
2668 void QCalendarPopup::dateSelectionChanged()
2671 emit newDateSelected(verifyCalendarInstance()->selectedDate());
2673 void QCalendarPopup::dateSelected(const QDate &date)
2676 emit activated(date);
2680 void QCalendarPopup::hideEvent(QHideEvent *)
2684 emit hidingCalendar(oldDate);
2688 #include "moc_qdatetimeedit.cpp"
2690 #endif // QT_NO_DATETIMEEDIT