1 /****************************************************************************
3 ** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
6 ** This file is part of the QtGui module of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
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. You can
93 change this by calling setMinimumDate(), taking into account that
94 the minimum value for QDate is 2 January 4713BC.
96 Other useful functions are setMaximumDate(), setMinimumTime()
99 \section1 Using a Pop-up Calendar Widget
101 QDateTimeEdit can be configured to allow a QCalendarWidget to be used
102 to select dates. This is enabled by setting the calendarPopup property.
103 Additionally, you can supply a custom calendar widget for use as the
104 calendar pop-up by calling the setCalendarWidget() function. The existing
105 calendar widget can be retrieved with calendarWidget().
108 \row \li \inlineimage windowsvista-datetimeedit.png Screenshot of a Windows Vista style date time editing widget
109 \li A date time editing widget shown in the \l{Windows Vista Style Widget Gallery}{Windows Vista widget style}.
110 \row \li \inlineimage macintosh-datetimeedit.png Screenshot of a Macintosh style date time editing widget
111 \li A date time editing widget shown in the \l{Macintosh Style Widget Gallery}{Macintosh widget style}.
112 \row \li \inlineimage fusion-datetimeedit.png Screenshot of a Fusion style date time editing widget
113 \li A date time editing widget shown in the \l{Fusion Style Widget Gallery}{Fusion widget style}.
116 \sa QDateEdit, QTimeEdit, QDate, QTime
120 \enum QDateTimeEdit::Section
131 \omitvalue DateSections_Mask
132 \omitvalue TimeSections_Mask
136 \fn void QDateTimeEdit::dateTimeChanged(const QDateTime &datetime)
138 This signal is emitted whenever the date or time is changed. The
139 new date and time is passed in \a datetime.
143 \fn void QDateTimeEdit::timeChanged(const QTime &time)
145 This signal is emitted whenever the time is changed. The new time
146 is passed in \a time.
150 \fn void QDateTimeEdit::dateChanged(const QDate &date)
152 This signal is emitted whenever the date is changed. The new date
153 is passed in \a date.
158 Constructs an empty date time editor with a \a parent.
161 QDateTimeEdit::QDateTimeEdit(QWidget *parent)
162 : QAbstractSpinBox(*new QDateTimeEditPrivate, parent)
165 d->init(QDateTime(QDATETIMEEDIT_DATE_INITIAL, QDATETIMEEDIT_TIME_MIN));
169 Constructs an empty date time editor with a \a parent. The value
170 is set to \a datetime.
173 QDateTimeEdit::QDateTimeEdit(const QDateTime &datetime, QWidget *parent)
174 : QAbstractSpinBox(*new QDateTimeEditPrivate, parent)
177 d->init(datetime.isValid() ? datetime : QDateTime(QDATETIMEEDIT_DATE_INITIAL,
178 QDATETIMEEDIT_TIME_MIN));
182 \fn QDateTimeEdit::QDateTimeEdit(const QDate &date, QWidget *parent)
184 Constructs an empty date time editor with a \a parent.
185 The value is set to \a date.
188 QDateTimeEdit::QDateTimeEdit(const QDate &date, QWidget *parent)
189 : QAbstractSpinBox(*new QDateTimeEditPrivate, parent)
192 d->init(date.isValid() ? date : QDATETIMEEDIT_DATE_INITIAL);
196 \fn QDateTimeEdit::QDateTimeEdit(const QTime &time, QWidget *parent)
198 Constructs an empty date time editor with a \a parent.
199 The value is set to \a time.
202 QDateTimeEdit::QDateTimeEdit(const QTime &time, QWidget *parent)
203 : QAbstractSpinBox(*new QDateTimeEditPrivate, parent)
206 d->init(time.isValid() ? time : QDATETIMEEDIT_TIME_MIN);
213 QDateTimeEdit::QDateTimeEdit(const QVariant &var, QVariant::Type parserType, QWidget *parent)
214 : QAbstractSpinBox(*new QDateTimeEditPrivate, parent)
217 d->parserType = parserType;
224 QDateTimeEdit::~QDateTimeEdit()
229 \property QDateTimeEdit::dateTime
230 \brief the QDateTime that is set in the QDateTimeEdit
232 When setting this property the timespec of the QDateTimeEdit remains the same
233 and the timespec of the new QDateTime is ignored.
235 By default, this property contains a date that refers to January 1,
236 2000 and a time of 00:00:00 and 0 milliseconds.
241 QDateTime QDateTimeEdit::dateTime() const
243 Q_D(const QDateTimeEdit);
244 return d->value.toDateTime();
247 void QDateTimeEdit::setDateTime(const QDateTime &datetime)
250 if (datetime.isValid()) {
252 if (!(d->sections & DateSections_Mask))
253 setDateRange(datetime.date(), datetime.date());
254 d->setValue(QDateTime(datetime.date(), datetime.time(), d->spec), EmitIfChanged);
259 \property QDateTimeEdit::date
260 \brief the QDate that is set in the widget
262 By default, this property contains a date that refers to January 1, 2000.
268 Returns the date of the date time edit.
270 QDate QDateTimeEdit::date() const
272 Q_D(const QDateTimeEdit);
273 return d->value.toDate();
276 void QDateTimeEdit::setDate(const QDate &date)
279 if (date.isValid()) {
280 if (!(d->sections & DateSections_Mask))
281 setDateRange(date, date);
284 d->setValue(QDateTime(date, d->value.toTime(), d->spec), EmitIfChanged);
290 \property QDateTimeEdit::time
291 \brief the QTime that is set in the widget
293 By default, this property contains a time of 00:00:00 and 0 milliseconds.
299 Returns the time of the date time edit.
301 QTime QDateTimeEdit::time() const
303 Q_D(const QDateTimeEdit);
304 return d->value.toTime();
307 void QDateTimeEdit::setTime(const QTime &time)
310 if (time.isValid()) {
312 d->setValue(QDateTime(d->value.toDate(), time, d->spec), EmitIfChanged);
318 \property QDateTimeEdit::minimumDateTime
321 \brief the minimum datetime of the date time edit
323 When setting this property the \l maximumDateTime() is adjusted if
324 necessary to ensure that the range remains valid. If the datetime is
325 not a valid QDateTime object, this function does nothing.
327 The default minimumDateTime can be restored with
328 clearMinimumDateTime()
330 By default, this property contains a date that refers to September 14,
331 1752 and a time of 00:00:00 and 0 milliseconds.
333 \sa maximumDateTime(), minimumTime(), maximumTime(), minimumDate(),
334 maximumDate(), setDateTimeRange(), setDateRange(), setTimeRange(),
335 clearMaximumDateTime(), clearMinimumDate(),
336 clearMaximumDate(), clearMinimumTime(), clearMaximumTime()
339 QDateTime QDateTimeEdit::minimumDateTime() const
341 Q_D(const QDateTimeEdit);
342 return d->minimum.toDateTime();
345 void QDateTimeEdit::clearMinimumDateTime()
347 setMinimumDateTime(QDateTime(QDATETIMEEDIT_COMPAT_DATE_MIN, QDATETIMEEDIT_TIME_MIN));
350 void QDateTimeEdit::setMinimumDateTime(const QDateTime &dt)
353 if (dt.isValid() && dt.date() >= QDATETIMEEDIT_DATE_MIN) {
354 const QDateTime m = dt.toTimeSpec(d->spec);
355 const QDateTime max = d->maximum.toDateTime();
356 d->setRange(m, (max > m ? max : m));
361 \property QDateTimeEdit::maximumDateTime
364 \brief the maximum datetime of the date time edit
366 When setting this property the \l minimumDateTime() is adjusted if
367 necessary to ensure that the range remains valid. If the datetime is
368 not a valid QDateTime object, this function does nothing.
370 The default maximumDateTime can be restored with
371 clearMaximumDateTime().
373 By default, this property contains a date that refers to 31 December,
374 7999 and a time of 23:59:59 and 999 milliseconds.
376 \sa minimumDateTime(), minimumTime(), maximumTime(), minimumDate(),
377 maximumDate(), setDateTimeRange(), setDateRange(), setTimeRange(),
378 clearMinimumDateTime(), clearMinimumDate(),
379 clearMaximumDate(), clearMinimumTime(), clearMaximumTime()
382 QDateTime QDateTimeEdit::maximumDateTime() const
384 Q_D(const QDateTimeEdit);
385 return d->maximum.toDateTime();
388 void QDateTimeEdit::clearMaximumDateTime()
390 setMaximumDateTime(QDATETIMEEDIT_DATETIME_MAX);
393 void QDateTimeEdit::setMaximumDateTime(const QDateTime &dt)
396 if (dt.isValid() && dt.date() <= QDATETIMEEDIT_DATE_MAX) {
397 const QDateTime m = dt.toTimeSpec(d->spec);
398 const QDateTime min = d->minimum.toDateTime();
399 d->setRange((min < m ? min : m), m);
405 Convenience function to set minimum and maximum date time with one
409 \snippet code/src_gui_widgets_qdatetimeedit.cpp 1
413 \snippet code/src_gui_widgets_qdatetimeedit.cpp 2
415 If either \a min or \a max are not valid, this function does
418 \sa setMinimumDate(), maximumDate(), setMaximumDate(),
419 clearMinimumDate(), setMinimumTime(), maximumTime(),
420 setMaximumTime(), clearMinimumTime(), QDateTime::isValid()
423 void QDateTimeEdit::setDateTimeRange(const QDateTime &min, const QDateTime &max)
426 const QDateTime minimum = min.toTimeSpec(d->spec);
427 QDateTime maximum = max.toTimeSpec(d->spec);
430 d->setRange(minimum, maximum);
434 \property QDateTimeEdit::minimumDate
436 \brief the minimum date of the date time edit
438 When setting this property the \l maximumDate is adjusted if
439 necessary, to ensure that the range remains valid. If the date is
440 not a valid QDate object, this function does nothing.
442 By default, this property contains a date that refers to September 14, 1752.
443 The minimum date must be at least the first day in year 100, otherwise
444 setMinimumDate() has no effect.
446 \sa minimumTime(), maximumTime(), setDateRange()
449 QDate QDateTimeEdit::minimumDate() const
451 Q_D(const QDateTimeEdit);
452 return d->minimum.toDate();
455 void QDateTimeEdit::setMinimumDate(const QDate &min)
458 if (min.isValid() && min >= QDATETIMEEDIT_DATE_MIN) {
459 setMinimumDateTime(QDateTime(min, d->minimum.toTime(), d->spec));
463 void QDateTimeEdit::clearMinimumDate()
465 setMinimumDate(QDATETIMEEDIT_COMPAT_DATE_MIN);
469 \property QDateTimeEdit::maximumDate
471 \brief the maximum date of the date time edit
473 When setting this property the \l minimumDate is adjusted if
474 necessary to ensure that the range remains valid. If the date is
475 not a valid QDate object, this function does nothing.
477 By default, this property contains a date that refers to December 31, 7999.
479 \sa minimumDate, minimumTime, maximumTime, setDateRange()
482 QDate QDateTimeEdit::maximumDate() const
484 Q_D(const QDateTimeEdit);
485 return d->maximum.toDate();
488 void QDateTimeEdit::setMaximumDate(const QDate &max)
492 setMaximumDateTime(QDateTime(max, d->maximum.toTime(), d->spec));
496 void QDateTimeEdit::clearMaximumDate()
498 setMaximumDate(QDATETIMEEDIT_DATE_MAX);
502 \property QDateTimeEdit::minimumTime
504 \brief the minimum time of the date time edit
506 When setting this property the \l maximumTime is adjusted if
507 necessary, to ensure that the range remains valid. If the time is
508 not a valid QTime object, this function does nothing.
510 By default, this property contains a time of 00:00:00 and 0 milliseconds.
512 \sa maximumTime, minimumDate, maximumDate, setTimeRange()
515 QTime QDateTimeEdit::minimumTime() const
517 Q_D(const QDateTimeEdit);
518 return d->minimum.toTime();
521 void QDateTimeEdit::setMinimumTime(const QTime &min)
525 const QDateTime m(d->minimum.toDate(), min, d->spec);
526 setMinimumDateTime(m);
530 void QDateTimeEdit::clearMinimumTime()
532 setMinimumTime(QDATETIMEEDIT_TIME_MIN);
536 \property QDateTimeEdit::maximumTime
538 \brief the maximum time of the date time edit
540 When setting this property, the \l minimumTime is adjusted if
541 necessary to ensure that the range remains valid. If the time is
542 not a valid QTime object, this function does nothing.
544 By default, this property contains a time of 23:59:59 and 999 milliseconds.
546 \sa minimumTime, minimumDate, maximumDate, setTimeRange()
548 QTime QDateTimeEdit::maximumTime() const
550 Q_D(const QDateTimeEdit);
551 return d->maximum.toTime();
554 void QDateTimeEdit::setMaximumTime(const QTime &max)
558 const QDateTime m(d->maximum.toDate(), max);
559 setMaximumDateTime(m);
563 void QDateTimeEdit::clearMaximumTime()
565 setMaximumTime(QDATETIMEEDIT_TIME_MAX);
569 Convenience function to set minimum and maximum date with one
572 \snippet code/src_gui_widgets_qdatetimeedit.cpp 3
576 \snippet code/src_gui_widgets_qdatetimeedit.cpp 4
578 If either \a min or \a max are not valid, this function does
581 \sa setMinimumDate(), maximumDate(), setMaximumDate(),
582 clearMinimumDate(), setMinimumTime(), maximumTime(),
583 setMaximumTime(), clearMinimumTime(), QDate::isValid()
586 void QDateTimeEdit::setDateRange(const QDate &min, const QDate &max)
589 if (min.isValid() && max.isValid()) {
590 setDateTimeRange(QDateTime(min, d->minimum.toTime(), d->spec),
591 QDateTime(max, d->maximum.toTime(), d->spec));
596 Convenience function to set minimum and maximum time with one
599 \snippet code/src_gui_widgets_qdatetimeedit.cpp 5
603 \snippet code/src_gui_widgets_qdatetimeedit.cpp 6
605 If either \a min or \a max are not valid, this function does
608 \sa setMinimumDate(), maximumDate(), setMaximumDate(),
609 clearMinimumDate(), setMinimumTime(), maximumTime(),
610 setMaximumTime(), clearMinimumTime(), QTime::isValid()
613 void QDateTimeEdit::setTimeRange(const QTime &min, const QTime &max)
616 if (min.isValid() && max.isValid()) {
617 setDateTimeRange(QDateTime(d->minimum.toDate(), min, d->spec),
618 QDateTime(d->maximum.toDate(), max, d->spec));
623 \property QDateTimeEdit::displayedSections
625 \brief the currently displayed fields of the date time edit
627 Returns a bit set of the displayed sections for this format.
628 \a setDisplayFormat(), displayFormat()
631 QDateTimeEdit::Sections QDateTimeEdit::displayedSections() const
633 Q_D(const QDateTimeEdit);
638 \property QDateTimeEdit::currentSection
640 \brief the current section of the spinbox
641 \a setCurrentSection()
644 QDateTimeEdit::Section QDateTimeEdit::currentSection() const
646 Q_D(const QDateTimeEdit);
647 #ifdef QT_KEYPAD_NAVIGATION
648 if (QApplication::keypadNavigationEnabled() && d->focusOnButton)
651 return d->convertToPublic(d->sectionType(d->currentSectionIndex));
654 void QDateTimeEdit::setCurrentSection(Section section)
657 if (section == NoSection || !(section & d->sections))
660 d->updateCache(d->value, d->displayText());
661 const int size = d->sectionNodes.size();
662 int index = d->currentSectionIndex + 1;
663 for (int i=0; i<2; ++i) {
664 while (index < size) {
665 if (d->convertToPublic(d->sectionType(index)) == section) {
666 d->edit->setCursorPosition(d->sectionPos(index));
667 QDTEDEBUG << d->sectionPos(index);
679 Returns the Section at \a index.
681 If the format is 'yyyy/MM/dd', sectionAt(0) returns YearSection,
682 sectionAt(1) returns MonthSection, and sectionAt(2) returns
686 QDateTimeEdit::Section QDateTimeEdit::sectionAt(int index) const
688 Q_D(const QDateTimeEdit);
689 if (index < 0 || index >= d->sectionNodes.size())
691 return d->convertToPublic(d->sectionType(index));
697 \property QDateTimeEdit::sectionCount
699 \brief the number of sections displayed.
700 If the format is 'yyyy/yy/yyyy', sectionCount returns 3
703 int QDateTimeEdit::sectionCount() const
705 Q_D(const QDateTimeEdit);
706 return d->sectionNodes.size();
713 \property QDateTimeEdit::currentSectionIndex
715 \brief the current section index of the spinbox
717 If the format is 'yyyy/MM/dd', the displayText is '2001/05/21', and
718 the cursorPosition is 5, currentSectionIndex returns 1. If the
719 cursorPosition is 3, currentSectionIndex is 0, and so on.
721 \a setCurrentSection()
725 int QDateTimeEdit::currentSectionIndex() const
727 Q_D(const QDateTimeEdit);
728 return d->currentSectionIndex;
731 void QDateTimeEdit::setCurrentSectionIndex(int index)
734 if (index < 0 || index >= d->sectionNodes.size())
736 d->edit->setCursorPosition(d->sectionPos(index));
742 \brief Returns the calendar widget for the editor if calendarPopup is
743 set to true and (sections() & DateSections_Mask) != 0.
745 This function creates and returns a calendar widget if none has been set.
749 QCalendarWidget *QDateTimeEdit::calendarWidget() const
751 Q_D(const QDateTimeEdit);
752 if (!d->calendarPopup || !(d->sections & QDateTimeParser::DateSectionMask))
754 if (!d->monthCalendar) {
755 const_cast<QDateTimeEditPrivate*>(d)->initCalendarPopup();
757 return d->monthCalendar->calendarWidget();
763 Sets the given \a calendarWidget as the widget to be used for the calendar
764 pop-up. The editor does not automatically take ownership of the calendar widget.
766 \note calendarPopup must be set to true before setting the calendar widget.
769 void QDateTimeEdit::setCalendarWidget(QCalendarWidget *calendarWidget)
772 if (!calendarWidget) {
773 qWarning("QDateTimeEdit::setCalendarWidget: Cannot set a null calendar widget");
777 if (!d->calendarPopup) {
778 qWarning("QDateTimeEdit::setCalendarWidget: calendarPopup is set to false");
782 if (!(d->display & QDateTimeParser::DateSectionMask)) {
783 qWarning("QDateTimeEdit::setCalendarWidget: no date sections specified");
786 d->initCalendarPopup(calendarWidget);
793 Selects \a section. If \a section doesn't exist in the currently
794 displayed sections, this function does nothing. If \a section is
795 NoSection, this function will unselect all text in the editor.
796 Otherwise, this function will move the cursor and the current section
797 to the selected section.
802 void QDateTimeEdit::setSelectedSection(Section section)
805 if (section == NoSection) {
806 d->edit->setSelection(d->edit->cursorPosition(), 0);
807 } else if (section & d->sections) {
808 if (currentSection() != section)
809 setCurrentSection(section);
810 d->setSelected(d->currentSectionIndex);
817 \fn QString QDateTimeEdit::sectionText(Section section) const
819 Returns the text from the given \a section.
824 QString QDateTimeEdit::sectionText(Section section) const
826 Q_D(const QDateTimeEdit);
827 if (section == QDateTimeEdit::NoSection || !(section & d->sections)) {
831 d->updateCache(d->value, d->displayText());
832 const int sectionIndex = d->absoluteIndex(section, 0);
833 return d->sectionText(sectionIndex);
837 \property QDateTimeEdit::displayFormat
839 \brief the format used to display the time/date of the date time edit
841 This format is described in QDateTime::toString() and QDateTime::fromString()
843 Example format strings (assuming that the date is 2nd of July 1969):
846 \header \li Format \li Result
847 \row \li dd.MM.yyyy \li 02.07.1969
848 \row \li MMM d yy \li Jul 2 69
849 \row \li MMMM d yy \li July 2 69
852 Note that if you specify a two digit year, it will be interpreted
853 to be in the century in which the date time edit was initialized.
854 The default century is the 21 (2000-2099).
856 If you specify an invalid format the format will not be set.
858 \sa QDateTime::toString(), displayedSections()
861 QString QDateTimeEdit::displayFormat() const
863 Q_D(const QDateTimeEdit);
864 return isRightToLeft() ? d->unreversedFormat : d->displayFormat;
867 template<typename C> static inline C reverse(const C &l)
870 for (int i=l.size() - 1; i>=0; --i)
875 void QDateTimeEdit::setDisplayFormat(const QString &format)
878 if (d->parseFormat(format)) {
879 d->unreversedFormat.clear();
880 if (isRightToLeft()) {
881 d->unreversedFormat = format;
882 d->displayFormat.clear();
883 for (int i=d->sectionNodes.size() - 1; i>=0; --i) {
884 d->displayFormat += d->separators.at(i + 1);
885 d->displayFormat += d->sectionFormat(i);
887 d->displayFormat += d->separators.at(0);
888 d->separators = reverse(d->separators);
889 d->sectionNodes = reverse(d->sectionNodes);
892 d->formatExplicitlySet = true;
893 d->sections = d->convertSections(d->display);
896 d->currentSectionIndex = qMin(d->currentSectionIndex, d->sectionNodes.size() - 1);
897 const bool timeShown = (d->sections & TimeSections_Mask);
898 const bool dateShown = (d->sections & DateSections_Mask);
899 Q_ASSERT(dateShown || timeShown);
900 if (timeShown && !dateShown) {
901 QTime time = d->value.toTime();
902 setDateRange(d->value.toDate(), d->value.toDate());
903 if (d->minimum.toTime() >= d->maximum.toTime()) {
904 setTimeRange(QDATETIMEEDIT_TIME_MIN, QDATETIMEEDIT_TIME_MAX);
905 // if the time range became invalid during the adjustment, the time would have been reset
908 } else if (dateShown && !timeShown) {
909 setTimeRange(QDATETIMEEDIT_TIME_MIN, QDATETIMEEDIT_TIME_MAX);
910 d->value = QDateTime(d->value.toDate(), QTime(), d->spec);
913 d->_q_editorCursorPositionChanged(-1, 0);
918 \property QDateTimeEdit::calendarPopup
919 \brief the current calendar pop-up show mode.
922 The calendar pop-up will be shown upon clicking the arrow button.
923 This property is valid only if there is a valid date display format.
925 \sa setDisplayFormat()
928 bool QDateTimeEdit::calendarPopup() const
930 Q_D(const QDateTimeEdit);
931 return d->calendarPopup;
934 void QDateTimeEdit::setCalendarPopup(bool enable)
937 if (enable == d->calendarPopup)
939 setAttribute(Qt::WA_MacShowFocusRect, !enable);
940 d->calendarPopup = enable;
941 #ifdef QT_KEYPAD_NAVIGATION
943 d->focusOnButton = false;
945 d->updateEditFieldGeometry();
950 \property QDateTimeEdit::timeSpec
951 \brief the current timespec used by the date time edit.
955 Qt::TimeSpec QDateTimeEdit::timeSpec() const
957 Q_D(const QDateTimeEdit);
961 void QDateTimeEdit::setTimeSpec(Qt::TimeSpec spec)
964 if (spec != d->spec) {
974 QSize QDateTimeEdit::sizeHint() const
976 Q_D(const QDateTimeEdit);
977 if (d->cachedSizeHint.isEmpty()) {
980 const QFontMetrics fm(fontMetrics());
981 int h = d->edit->sizeHint().height();
984 s = d->textFromValue(d->minimum) + QLatin1String(" ");
985 w = qMax<int>(w, fm.width(s));
986 s = d->textFromValue(d->maximum) + QLatin1String(" ");
987 w = qMax<int>(w, fm.width(s));
988 if (d->specialValueText.size()) {
989 s = d->specialValueText;
990 w = qMax<int>(w, fm.width(s));
992 w += 2; // cursor blinking space
997 if (d->calendarPopupEnabled()) {
998 QStyleOptionComboBox opt;
999 d->cachedSizeHint = style()->sizeFromContents(QStyle::CT_ComboBox, &opt, hint, this);
1004 QStyleOptionSpinBox opt;
1005 initStyleOption(&opt);
1006 opt.rect.setSize(hint + extra);
1007 extra += hint - style()->subControlRect(QStyle::CC_SpinBox, &opt,
1008 QStyle::SC_SpinBoxEditField, this).size();
1009 // get closer to final result by repeating the calculation
1010 opt.rect.setSize(hint + extra);
1011 extra += hint - style()->subControlRect(QStyle::CC_SpinBox, &opt,
1012 QStyle::SC_SpinBoxEditField, this).size();
1016 d->cachedSizeHint = style()->sizeFromContents(QStyle::CT_SpinBox, &opt, hint, this)
1017 .expandedTo(QApplication::globalStrut());
1020 d->cachedMinimumSizeHint = d->cachedSizeHint;
1021 // essentially make minimumSizeHint return the same as sizeHint for datetimeedits
1023 return d->cachedSizeHint;
1030 bool QDateTimeEdit::event(QEvent *event)
1033 switch (event->type()) {
1034 case QEvent::ApplicationLayoutDirectionChange: {
1035 const bool was = d->formatExplicitlySet;
1036 const QString oldFormat = d->displayFormat;
1037 d->displayFormat.clear();
1038 setDisplayFormat(oldFormat);
1039 d->formatExplicitlySet = was;
1041 case QEvent::LocaleChange:
1044 case QEvent::StyleChange:
1046 case QEvent::MacSizeChange:
1048 d->setLayoutItemMargins(QStyle::SE_DateTimeEditLayoutItem);
1053 return QAbstractSpinBox::event(event);
1060 void QDateTimeEdit::clear()
1063 d->clearSection(d->currentSectionIndex);
1069 void QDateTimeEdit::keyPressEvent(QKeyEvent *event)
1072 int oldCurrent = d->currentSectionIndex;
1074 bool inserted = false;
1076 switch (event->key()) {
1077 #ifdef QT_KEYPAD_NAVIGATION
1078 case Qt::Key_NumberSign: //shortcut to popup calendar
1079 if (QApplication::keypadNavigationEnabled() && d->calendarPopupEnabled()) {
1080 d->initCalendarPopup();
1081 d->positionCalendarPopup();
1082 d->monthCalendar->show();
1086 case Qt::Key_Select:
1087 if (QApplication::keypadNavigationEnabled()) {
1088 if (hasEditFocus()) {
1089 if (d->focusOnButton) {
1090 d->initCalendarPopup();
1091 d->positionCalendarPopup();
1092 d->monthCalendar->show();
1093 d->focusOnButton = false;
1096 setEditFocus(false);
1102 d->edit->d_func()->setCursorVisible(false);
1103 d->edit->d_func()->control->setCursorBlinkPeriod(0);
1110 case Qt::Key_Return:
1111 d->interpret(AlwaysEmit);
1112 d->setSelected(d->currentSectionIndex, true);
1114 emit editingFinished();
1117 #ifdef QT_KEYPAD_NAVIGATION
1118 if (QApplication::keypadNavigationEnabled() && !hasEditFocus()
1119 && !event->text().isEmpty() && event->text().at(0).isLetterOrNumber()) {
1123 d->edit->d_func()->setCursorVisible(false);
1124 d->edit->d_func()->control->setCursorBlinkPeriod(0);
1129 if (!d->isSeparatorKey(event)) {
1130 inserted = select = !event->text().isEmpty() && event->text().at(0).isPrint()
1131 && !(event->modifiers() & ~(Qt::ShiftModifier|Qt::KeypadModifier));
1136 if (event->key() == Qt::Key_Left || event->key() == Qt::Key_Right) {
1138 #ifdef QT_KEYPAD_NAVIGATION
1139 QApplication::keypadNavigationEnabled() && !hasEditFocus()
1140 || !QApplication::keypadNavigationEnabled() &&
1142 !(event->modifiers() & Qt::ControlModifier)) {
1148 #ifdef QT_KEYPAD_NAVIGATION
1149 if (!QApplication::keypadNavigationEnabled())
1152 select = (event->modifiers() & Qt::ShiftModifier);
1157 // else fall through
1158 case Qt::Key_Backtab:
1161 if (d->specialValue()) {
1162 d->edit->setSelection(d->edit->cursorPosition(), 0);
1165 const bool forward = event->key() != Qt::Key_Left && event->key() != Qt::Key_Backtab
1166 && (event->key() != Qt::Key_Tab || !(event->modifiers() & Qt::ShiftModifier));
1167 #ifdef QT_KEYPAD_NAVIGATION
1168 int newSection = d->nextPrevSection(d->currentSectionIndex, forward);
1169 if (QApplication::keypadNavigationEnabled()) {
1170 if (d->focusOnButton) {
1171 newSection = forward ? 0 : d->sectionNodes.size() - 1;
1172 d->focusOnButton = false;
1174 } else if (newSection < 0 && select && d->calendarPopupEnabled()) {
1175 setSelectedSection(NoSection);
1176 d->focusOnButton = true;
1181 // only allow date/time sections to be selected.
1182 if (newSection & ~(QDateTimeParser::TimeSectionMask | QDateTimeParser::DateSectionMask))
1185 //key tab and backtab will be managed thrgout QWidget::event
1186 if (event->key() != Qt::Key_Backtab && event->key() != Qt::Key_Tab)
1187 focusNextPrevChild(forward);
1191 QAbstractSpinBox::keyPressEvent(event);
1192 if (select && !d->edit->hasSelectedText()) {
1193 if (inserted && d->sectionAt(d->edit->cursorPosition()) == QDateTimeParser::NoSectionIndex) {
1194 QString str = d->displayText();
1195 int pos = d->edit->cursorPosition();
1196 if (validate(str, pos) == QValidator::Acceptable
1197 && (d->sectionNodes.at(oldCurrent).count != 1
1198 || d->sectionMaxSize(oldCurrent) == d->sectionSize(oldCurrent)
1199 || d->skipToNextSection(oldCurrent, d->value.toDateTime(), d->sectionText(oldCurrent)))) {
1200 QDTEDEBUG << "Setting currentsection to"
1201 << d->closestSection(d->edit->cursorPosition(), true) << event->key()
1202 << oldCurrent << str;
1203 const int tmp = d->closestSection(d->edit->cursorPosition(), true);
1205 d->currentSectionIndex = tmp;
1208 if (d->currentSectionIndex != oldCurrent) {
1209 d->setSelected(d->currentSectionIndex);
1212 if (d->specialValue()) {
1213 d->edit->setSelection(d->edit->cursorPosition(), 0);
1221 #ifndef QT_NO_WHEELEVENT
1222 void QDateTimeEdit::wheelEvent(QWheelEvent *event)
1224 QAbstractSpinBox::wheelEvent(event);
1232 void QDateTimeEdit::focusInEvent(QFocusEvent *event)
1235 QAbstractSpinBox::focusInEvent(event);
1237 const int oldPos = d->edit->cursorPosition();
1238 if (!d->formatExplicitlySet) {
1239 if (d->displayFormat == d->defaultTimeFormat) {
1240 frm = &d->defaultTimeFormat;
1241 } else if (d->displayFormat == d->defaultDateFormat) {
1242 frm = &d->defaultDateFormat;
1243 } else if (d->displayFormat == d->defaultDateTimeFormat) {
1244 frm = &d->defaultDateTimeFormat;
1248 d->readLocaleSettings();
1249 if (d->displayFormat != *frm) {
1250 setDisplayFormat(*frm);
1251 d->formatExplicitlySet = false;
1252 d->edit->setCursorPosition(oldPos);
1256 const bool oldHasHadFocus = d->hasHadFocus;
1257 d->hasHadFocus = true;
1259 switch (event->reason()) {
1260 case Qt::BacktabFocusReason:
1263 case Qt::MouseFocusReason:
1264 case Qt::PopupFocusReason:
1266 case Qt::ActiveWindowFocusReason:
1269 case Qt::ShortcutFocusReason:
1270 case Qt::TabFocusReason:
1274 if (isRightToLeft())
1276 d->updateEdit(); // needed to make it update specialValueText
1278 d->setSelected(first ? 0 : d->sectionNodes.size() - 1);
1285 bool QDateTimeEdit::focusNextPrevChild(bool next)
1288 const int newSection = d->nextPrevSection(d->currentSectionIndex, next);
1289 switch (d->sectionType(newSection)) {
1290 case QDateTimeParser::NoSection:
1291 case QDateTimeParser::FirstSection:
1292 case QDateTimeParser::LastSection:
1293 return QAbstractSpinBox::focusNextPrevChild(next);
1295 d->edit->deselect();
1296 d->edit->setCursorPosition(d->sectionPos(newSection));
1297 QDTEDEBUG << d->sectionPos(newSection);
1298 d->setSelected(newSection, true);
1307 void QDateTimeEdit::stepBy(int steps)
1310 #ifdef QT_KEYPAD_NAVIGATION
1311 // with keypad navigation and not editFocus, left right change the date/time by a fixed amount.
1312 if (QApplication::keypadNavigationEnabled() && !hasEditFocus()) {
1313 // if date based, shift by day. else shift by 15min
1314 if (d->sections & DateSections_Mask) {
1315 setDateTime(dateTime().addDays(steps));
1317 int minutes = time().hour()*60 + time().minute();
1318 int blocks = minutes/15;
1320 /* rounding involved */
1323 blocks += 1; // do one less step;
1327 minutes = blocks * 15;
1329 /* need to take wrapping into account */
1331 int max_minutes = d->maximum.toTime().hour()*60 + d->maximum.toTime().minute();
1332 int min_minutes = d->minimum.toTime().hour()*60 + d->minimum.toTime().minute();
1334 if (minutes >= max_minutes) {
1335 setTime(maximumTime());
1337 } else if (minutes <= min_minutes) {
1338 setTime(minimumTime());
1342 setTime(QTime(minutes/60, minutes%60));
1347 // don't optimize away steps == 0. This is the only way to select
1348 // the currentSection in Qt 4.1.x
1349 if (d->specialValue() && displayedSections() != AmPmSection) {
1350 for (int i=0; i<d->sectionNodes.size(); ++i) {
1351 if (d->sectionType(i) != QDateTimeParser::AmPmSection) {
1352 d->currentSectionIndex = i;
1357 d->setValue(d->stepBy(d->currentSectionIndex, steps, false), EmitIfChanged);
1358 d->updateCache(d->value, d->displayText());
1360 d->setSelected(d->currentSectionIndex);
1361 d->updateTimeSpec();
1365 This virtual function is used by the date time edit whenever it
1366 needs to display \a dateTime.
1368 If you reimplement this, you may also need to reimplement validate().
1370 \sa dateTimeFromText(), validate()
1372 QString QDateTimeEdit::textFromDateTime(const QDateTime &dateTime) const
1374 Q_D(const QDateTimeEdit);
1375 return locale().toString(dateTime, d->displayFormat);
1380 Returns an appropriate datetime for the given \a text.
1382 This virtual function is used by the datetime edit whenever it
1383 needs to interpret text entered by the user as a value.
1385 \sa textFromDateTime(), validate()
1387 QDateTime QDateTimeEdit::dateTimeFromText(const QString &text) const
1389 Q_D(const QDateTimeEdit);
1390 QString copy = text;
1391 int pos = d->edit->cursorPosition();
1392 QValidator::State state = QValidator::Acceptable;
1393 return d->validateAndInterpret(copy, pos, state);
1400 QValidator::State QDateTimeEdit::validate(QString &text, int &pos) const
1402 Q_D(const QDateTimeEdit);
1403 QValidator::State state;
1404 d->validateAndInterpret(text, pos, state);
1413 void QDateTimeEdit::fixup(QString &input) const
1415 Q_D(const QDateTimeEdit);
1416 QValidator::State state;
1417 int copy = d->edit->cursorPosition();
1419 d->validateAndInterpret(input, copy, state, true);
1427 QDateTimeEdit::StepEnabled QDateTimeEdit::stepEnabled() const
1429 Q_D(const QDateTimeEdit);
1431 return StepEnabled(0);
1432 if (d->specialValue()) {
1433 return (d->minimum == d->maximum ? StepEnabled(0) : StepEnabled(StepUpEnabled));
1436 QAbstractSpinBox::StepEnabled ret = 0;
1438 #ifdef QT_KEYPAD_NAVIGATION
1439 if (QApplication::keypadNavigationEnabled() && !hasEditFocus()) {
1441 return StepEnabled(StepUpEnabled | StepDownEnabled);
1442 // 3 cases. date, time, datetime. each case look
1443 // at just the relavant component.
1444 QVariant max, min, val;
1445 if (!(d->sections & DateSections_Mask)) {
1446 // time only, no date
1447 max = d->maximum.toTime();
1448 min = d->minimum.toTime();
1449 val = d->value.toTime();
1450 } else if (!(d->sections & TimeSections_Mask)) {
1451 // date only, no time
1452 max = d->maximum.toDate();
1453 min = d->minimum.toDate();
1454 val = d->value.toDate();
1462 ret |= QAbstractSpinBox::StepDownEnabled;
1464 ret |= QAbstractSpinBox::StepUpEnabled;
1468 switch (d->sectionType(d->currentSectionIndex)) {
1469 case QDateTimeParser::NoSection:
1470 case QDateTimeParser::FirstSection:
1471 case QDateTimeParser::LastSection: return 0;
1475 return StepEnabled(StepDownEnabled|StepUpEnabled);
1477 QVariant v = d->stepBy(d->currentSectionIndex, 1, true);
1478 if (v != d->value) {
1479 ret |= QAbstractSpinBox::StepUpEnabled;
1481 v = d->stepBy(d->currentSectionIndex, -1, true);
1482 if (v != d->value) {
1483 ret |= QAbstractSpinBox::StepDownEnabled;
1494 void QDateTimeEdit::mousePressEvent(QMouseEvent *event)
1497 if (!d->calendarPopupEnabled()) {
1498 QAbstractSpinBox::mousePressEvent(event);
1501 d->updateHoverControl(event->pos());
1502 if (d->hoverControl == QStyle::SC_ComboBoxArrow) {
1507 d->updateArrow(QStyle::State_Sunken);
1508 d->initCalendarPopup();
1509 d->positionCalendarPopup();
1511 d->monthCalendar->show();
1513 QAbstractSpinBox::mousePressEvent(event);
1519 \brief The QTimeEdit class provides a widget for editing times based on
1520 the QDateTimeEdit widget.
1522 \ingroup basicwidgets
1525 Many of the properties and functions provided by QTimeEdit are implemented in
1526 QDateTimeEdit. These are the relevant properties of this class:
1529 \li \l{QDateTimeEdit::time}{time} holds the time displayed by the widget.
1530 \li \l{QDateTimeEdit::minimumTime}{minimumTime} defines the minimum (earliest) time
1531 that can be set by the user.
1532 \li \l{QDateTimeEdit::maximumTime}{maximumTime} defines the maximum (latest) time
1533 that can be set by the user.
1534 \li \l{QDateTimeEdit::displayFormat}{displayFormat} contains a string that is used
1535 to format the time displayed in the widget.
1539 \row \li \inlineimage windowsvista-timeedit.png Screenshot of a Windows Vista style time editing widget
1540 \li A time editing widget shown in the \l{Windows Vista Style Widget Gallery}{Windows Vista widget style}.
1541 \row \li \inlineimage macintosh-timeedit.png Screenshot of a Macintosh style time editing widget
1542 \li A time editing widget shown in the \l{Macintosh Style Widget Gallery}{Macintosh widget style}.
1543 \row \li \inlineimage fusion-timeedit.png Screenshot of a Fusion style time editing widget
1544 \li A time editing widget shown in the \l{Fusion Style Widget Gallery}{Fusion widget style}.
1547 \sa QDateEdit, QDateTimeEdit
1551 Constructs an empty time editor with a \a parent.
1555 QTimeEdit::QTimeEdit(QWidget *parent)
1556 : QDateTimeEdit(QDATETIMEEDIT_TIME_MIN, QVariant::Time, parent)
1558 connect(this, SIGNAL(timeChanged(QTime)), SIGNAL(userTimeChanged(QTime)));
1562 Constructs an empty time editor with a \a parent. The time is set
1566 QTimeEdit::QTimeEdit(const QTime &time, QWidget *parent)
1567 : QDateTimeEdit(time, QVariant::Time, parent)
1574 QTimeEdit::~QTimeEdit()
1579 \property QTimeEdit::time
1581 \sa QDateTimeEdit::time
1585 \fn void QTimeEdit::userTimeChanged(const QTime &time)
1587 This signal only exists to fully implement the time Q_PROPERTY on the class.
1588 Normally timeChanged should be used instead.
1596 \brief The QDateEdit class provides a widget for editing dates based on
1597 the QDateTimeEdit widget.
1599 \ingroup basicwidgets
1602 Many of the properties and functions provided by QDateEdit are implemented in
1603 QDateTimeEdit. These are the relevant properties of this class:
1606 \li \l{QDateTimeEdit::date}{date} holds the date displayed by the widget.
1607 \li \l{QDateTimeEdit::minimumDate}{minimumDate} defines the minimum (earliest)
1608 date that can be set by the user.
1609 \li \l{QDateTimeEdit::maximumDate}{maximumDate} defines the maximum (latest) date
1610 that can be set by the user.
1611 \li \l{QDateTimeEdit::displayFormat}{displayFormat} contains a string that is used
1612 to format the date displayed in the widget.
1616 \row \li \inlineimage windowsvista-dateedit.png Screenshot of a Windows Vista style date editing widget
1617 \li A date editing widget shown in the \l{Windows Vista Style Widget Gallery}{Windows Vista widget style}.
1618 \row \li \inlineimage macintosh-dateedit.png Screenshot of a Macintosh style date editing widget
1619 \li A date editing widget shown in the \l{Macintosh Style Widget Gallery}{Macintosh widget style}.
1620 \row \li \inlineimage fusion-dateedit.png Screenshot of a Fusion style date editing widget
1621 \li A date editing widget shown in the \l{Fusion Style Widget Gallery}{Fusion widget style}.
1624 \sa QTimeEdit, QDateTimeEdit
1628 Constructs an empty date editor with a \a parent.
1631 QDateEdit::QDateEdit(QWidget *parent)
1632 : QDateTimeEdit(QDATETIMEEDIT_DATE_INITIAL, QVariant::Date, parent)
1634 connect(this, SIGNAL(dateChanged(QDate)), SIGNAL(userDateChanged(QDate)));
1638 Constructs an empty date editor with a \a parent. The date is set
1642 QDateEdit::QDateEdit(const QDate &date, QWidget *parent)
1643 : QDateTimeEdit(date, QVariant::Date, parent)
1650 QDateEdit::~QDateEdit()
1655 \property QDateEdit::date
1657 \sa QDateTimeEdit::date
1661 \fn void QDateEdit::userDateChanged(const QDate &date)
1663 This signal only exists to fully implement the date Q_PROPERTY on the class.
1664 Normally dateChanged should be used instead.
1670 // --- QDateTimeEditPrivate ---
1674 Constructs a QDateTimeEditPrivate object
1678 QDateTimeEditPrivate::QDateTimeEditPrivate()
1679 : QDateTimeParser(QVariant::DateTime, QDateTimeParser::DateTimeEdit)
1681 hasHadFocus = false;
1682 formatExplicitlySet = false;
1685 type = QVariant::DateTime;
1688 currentSectionIndex = FirstSectionIndex;
1690 first.type = FirstSection;
1691 last.type = LastSection;
1692 none.type = NoSection;
1697 calendarPopup = false;
1698 minimum = QDATETIMEEDIT_COMPAT_DATETIME_MIN;
1699 maximum = QDATETIMEEDIT_DATETIME_MAX;
1700 arrowState = QStyle::State_None;
1702 readLocaleSettings();
1704 #ifdef QT_KEYPAD_NAVIGATION
1705 focusOnButton = false;
1709 void QDateTimeEditPrivate::updateTimeSpec()
1711 minimum = minimum.toDateTime().toTimeSpec(spec);
1712 maximum = maximum.toDateTime().toTimeSpec(spec);
1713 value = value.toDateTime().toTimeSpec(spec);
1715 // time zone changes can lead to 00:00:00 becomes 01:00:00 and 23:59:59 becomes 00:59:59 (invalid range)
1716 const bool dateShown = (sections & QDateTimeEdit::DateSections_Mask);
1718 if (minimum.toTime() >= maximum.toTime()){
1719 minimum = QDateTime(value.toDate(), QDATETIMEEDIT_TIME_MIN, spec);
1720 maximum = QDateTime(value.toDate(), QDATETIMEEDIT_TIME_MAX, spec);
1725 void QDateTimeEditPrivate::updateEdit()
1727 const QString newText = (specialValue() ? specialValueText : textFromValue(value));
1728 if (newText == displayText())
1730 int selsize = edit->selectedText().size();
1731 const bool sb = edit->blockSignals(true);
1733 edit->setText(newText);
1736 #ifdef QT_KEYPAD_NAVIGATION
1737 && !(QApplication::keypadNavigationEnabled() && !edit->hasEditFocus())
1740 int cursor = sectionPos(currentSectionIndex);
1741 QDTEDEBUG << "cursor is " << cursor << currentSectionIndex;
1742 cursor = qBound(0, cursor, displayText().size());
1743 QDTEDEBUG << cursor;
1745 edit->setSelection(cursor, selsize);
1746 QDTEDEBUG << cursor << selsize;
1748 edit->setCursorPosition(cursor);
1749 QDTEDEBUG << cursor;
1753 edit->blockSignals(sb);
1760 Selects the section \a s. If \a forward is false selects backwards.
1763 void QDateTimeEditPrivate::setSelected(int sectionIndex, bool forward)
1766 #ifdef QT_KEYPAD_NAVIGATION
1767 || (QApplication::keypadNavigationEnabled() && !edit->hasEditFocus())
1772 const SectionNode &node = sectionNode(sectionIndex);
1773 if (node.type == NoSection || node.type == LastSection || node.type == FirstSection)
1776 updateCache(value, displayText());
1777 const int size = sectionSize(sectionIndex);
1779 edit->setSelection(sectionPos(node), size);
1781 edit->setSelection(sectionPos(node) + size, -size);
1789 Returns the section at index \a index or NoSection if there are no sections there.
1792 int QDateTimeEditPrivate::sectionAt(int pos) const
1794 if (pos < separators.first().size()) {
1795 return (pos == 0 ? FirstSectionIndex : NoSectionIndex);
1796 } else if (displayText().size() - pos < separators.last().size() + 1) {
1797 if (separators.last().size() == 0) {
1798 return sectionNodes.count() - 1;
1800 return (pos == displayText().size() ? LastSectionIndex : NoSectionIndex);
1802 updateCache(value, displayText());
1804 for (int i=0; i<sectionNodes.size(); ++i) {
1805 const int tmp = sectionPos(i);
1806 if (pos < tmp + sectionSize(i)) {
1807 return (pos < tmp ? -1 : i);
1816 Returns the closest section of index \a index. Searches forward
1817 for a section if \a forward is true. Otherwise searches backwards.
1820 int QDateTimeEditPrivate::closestSection(int pos, bool forward) const
1823 if (pos < separators.first().size()) {
1824 return forward ? 0 : FirstSectionIndex;
1825 } else if (displayText().size() - pos < separators.last().size() + 1) {
1826 return forward ? LastSectionIndex : sectionNodes.size() - 1;
1828 updateCache(value, displayText());
1829 for (int i=0; i<sectionNodes.size(); ++i) {
1830 const int tmp = sectionPos(sectionNodes.at(i));
1831 if (pos < tmp + sectionSize(i)) {
1832 if (pos < tmp && !forward) {
1836 } else if (i == sectionNodes.size() - 1 && pos > tmp) {
1840 qWarning("QDateTimeEdit: Internal Error: closestSection returned NoSection");
1841 return NoSectionIndex;
1847 Returns a copy of the section that is before or after \a current, depending on \a forward.
1850 int QDateTimeEditPrivate::nextPrevSection(int current, bool forward) const
1852 Q_Q(const QDateTimeEdit);
1853 if (q->isRightToLeft())
1857 case FirstSectionIndex: return forward ? 0 : FirstSectionIndex;
1858 case LastSectionIndex: return (forward ? LastSectionIndex : sectionNodes.size() - 1);
1859 case NoSectionIndex: return FirstSectionIndex;
1862 Q_ASSERT(current >= 0 && current < sectionNodes.size());
1864 current += (forward ? 1 : -1);
1865 if (current >= sectionNodes.size()) {
1866 return LastSectionIndex;
1867 } else if (current < 0) {
1868 return FirstSectionIndex;
1877 Clears the text of section \a s.
1880 void QDateTimeEditPrivate::clearSection(int index)
1882 const QLatin1Char space(' ');
1883 int cursorPos = edit->cursorPosition();
1884 bool blocked = edit->blockSignals(true);
1885 QString t = edit->text();
1886 const int pos = sectionPos(index);
1888 qWarning("QDateTimeEdit: Internal error (%s:%d)", __FILE__, __LINE__);
1891 const int size = sectionSize(index);
1892 t.replace(pos, size, QString().fill(space, size));
1894 edit->setCursorPosition(cursorPos);
1895 QDTEDEBUG << cursorPos;
1897 edit->blockSignals(blocked);
1904 updates the cached values
1907 void QDateTimeEditPrivate::updateCache(const QVariant &val, const QString &str) const
1909 if (val != cachedValue || str != cachedText || cacheGuard) {
1912 int unused = edit->cursorPosition();
1913 QValidator::State unusedState;
1914 validateAndInterpret(copy, unused, unusedState);
1922 parses and validates \a input
1925 QDateTime QDateTimeEditPrivate::validateAndInterpret(QString &input, int &position,
1926 QValidator::State &state, bool fixup) const
1928 if (input.isEmpty()) {
1929 if (sectionNodes.size() == 1 || !specialValueText.isEmpty()) {
1930 state = QValidator::Intermediate;
1932 state = QValidator::Invalid;
1934 return getZeroVariant().toDateTime();
1935 } else if (cachedText == input && !fixup) {
1936 state = cachedState;
1937 return cachedValue.toDateTime();
1938 } else if (!specialValueText.isEmpty()) {
1939 bool changeCase = false;
1940 const int max = qMin(specialValueText.size(), input.size());
1942 for (i=0; i<max; ++i) {
1943 const QChar ic = input.at(i);
1944 const QChar sc = specialValueText.at(i);
1946 if (sc.toLower() == ic.toLower()) {
1954 state = specialValueText.size() == input.size() ? QValidator::Acceptable : QValidator::Intermediate;
1956 input = specialValueText.left(max);
1958 return minimum.toDateTime();
1961 StateNode tmp = parse(input, position, value.toDateTime(), fixup);
1963 state = QValidator::State(int(tmp.state));
1964 if (state == QValidator::Acceptable) {
1965 if (tmp.conflicts && conflictGuard != tmp.value) {
1966 conflictGuard = tmp.value;
1968 input = textFromValue(tmp.value);
1969 updateCache(tmp.value, input);
1970 conflictGuard.clear();
1973 cachedState = state;
1974 cachedValue = tmp.value;
1979 return (tmp.value.isNull() ? getZeroVariant().toDateTime() : tmp.value);
1987 QString QDateTimeEditPrivate::textFromValue(const QVariant &f) const
1989 Q_Q(const QDateTimeEdit);
1990 return q->textFromDateTime(f.toDateTime());
1996 This function's name is slightly confusing; it is not to be confused
1997 with QAbstractSpinBox::valueFromText().
2000 QVariant QDateTimeEditPrivate::valueFromText(const QString &f) const
2002 Q_Q(const QDateTimeEdit);
2003 return q->dateTimeFromText(f).toTimeSpec(spec);
2010 Internal function called by QDateTimeEdit::stepBy(). Also takes a
2011 Section for which section to step on and a bool \a test for
2012 whether or not to modify the internal cachedDay variable. This is
2013 necessary because the function is called from the const function
2014 QDateTimeEdit::stepEnabled() as well as QDateTimeEdit::stepBy().
2017 QDateTime QDateTimeEditPrivate::stepBy(int sectionIndex, int steps, bool test) const
2019 Q_Q(const QDateTimeEdit);
2020 QDateTime v = value.toDateTime();
2021 QString str = displayText();
2022 int pos = edit->cursorPosition();
2023 const SectionNode sn = sectionNode(sectionIndex);
2026 // to make sure it behaves reasonably when typing something and then stepping in non-tracking mode
2027 if (!test && pendingEmit) {
2028 if (q->validate(str, pos) != QValidator::Acceptable) {
2029 v = value.toDateTime();
2031 v = q->dateTimeFromText(str);
2033 val = getDigit(v, sectionIndex);
2035 val = getDigit(v, sectionIndex);
2040 const int min = absoluteMin(sectionIndex);
2041 const int max = absoluteMax(sectionIndex, value.toDateTime());
2044 val = (wrapping ? max - (min - val) + 1 : min);
2045 } else if (val > max) {
2046 val = (wrapping ? min + val - max - 1 : max);
2050 const int oldDay = v.date().day();
2052 setDigit(v, sectionIndex, val);
2053 // if this sets year or month it will make
2054 // sure that days are lowered if needed.
2056 const QDateTime minimumDateTime = minimum.toDateTime();
2057 const QDateTime maximumDateTime = maximum.toDateTime();
2058 // changing one section should only modify that section, if possible
2059 if (sn.type != AmPmSection && (v < minimumDateTime || v > maximumDateTime)) {
2060 const int localmin = getDigit(minimumDateTime, sectionIndex);
2061 const int localmax = getDigit(maximumDateTime, sectionIndex);
2064 // just because we hit the roof in one direction, it
2065 // doesn't mean that we hit the floor in the other
2067 setDigit(v, sectionIndex, min);
2068 if (!(sn.type & (DaySection|DayOfWeekSectionShort|DayOfWeekSectionLong)) && sections & DateSectionMask) {
2069 const int daysInMonth = v.date().daysInMonth();
2070 if (v.date().day() < oldDay && v.date().day() < daysInMonth) {
2071 const int adds = qMin(oldDay, daysInMonth);
2072 v = v.addDays(adds - v.date().day());
2076 if (v < minimumDateTime) {
2077 setDigit(v, sectionIndex, localmin);
2078 if (v < minimumDateTime)
2079 setDigit(v, sectionIndex, localmin + 1);
2082 setDigit(v, sectionIndex, max);
2083 if (!(sn.type & (DaySection|DayOfWeekSectionShort|DayOfWeekSectionLong)) && sections & DateSectionMask) {
2084 const int daysInMonth = v.date().daysInMonth();
2085 if (v.date().day() < oldDay && v.date().day() < daysInMonth) {
2086 const int adds = qMin(oldDay, daysInMonth);
2087 v = v.addDays(adds - v.date().day());
2091 if (v > maximumDateTime) {
2092 setDigit(v, sectionIndex, localmax);
2093 if (v > maximumDateTime)
2094 setDigit(v, sectionIndex, localmax - 1);
2098 setDigit(v, sectionIndex, (steps > 0 ? localmax : localmin));
2101 if (!test && oldDay != v.date().day() && !(sn.type & (DaySection|DayOfWeekSectionShort|DayOfWeekSectionLong))) {
2102 // this should not happen when called from stepEnabled
2103 cachedDay = qMax<int>(oldDay, cachedDay);
2106 if (v < minimumDateTime) {
2109 setDigit(t, sectionIndex, steps < 0 ? max : min);
2110 bool mincmp = (t >= minimumDateTime);
2111 bool maxcmp = (t <= maximumDateTime);
2112 if (!mincmp || !maxcmp) {
2113 setDigit(t, sectionIndex, getDigit(steps < 0
2115 : minimumDateTime, sectionIndex));
2116 mincmp = (t >= minimumDateTime);
2117 maxcmp = (t <= maximumDateTime);
2119 if (mincmp && maxcmp) {
2123 v = value.toDateTime();
2125 } else if (v > maximumDateTime) {
2128 setDigit(t, sectionIndex, steps > 0 ? min : max);
2129 bool mincmp = (t >= minimumDateTime);
2130 bool maxcmp = (t <= maximumDateTime);
2131 if (!mincmp || !maxcmp) {
2132 setDigit(t, sectionIndex, getDigit(steps > 0 ?
2134 maximumDateTime, sectionIndex));
2135 mincmp = (t >= minimumDateTime);
2136 maxcmp = (t <= maximumDateTime);
2138 if (mincmp && maxcmp) {
2142 v = value.toDateTime();
2146 const QDateTime ret = bound(v, value, steps).toDateTime().toTimeSpec(spec);
2154 void QDateTimeEditPrivate::emitSignals(EmitPolicy ep, const QVariant &old)
2157 if (ep == NeverEmit) {
2160 pendingEmit = false;
2162 const bool dodate = value.toDate().isValid() && (sections & DateSectionMask);
2163 const bool datechanged = (ep == AlwaysEmit || old.toDate() != value.toDate());
2164 const bool dotime = value.toTime().isValid() && (sections & TimeSectionMask);
2165 const bool timechanged = (ep == AlwaysEmit || old.toTime() != value.toTime());
2167 updateCache(value, displayText());
2169 syncCalendarWidget();
2170 if (datechanged || timechanged)
2171 emit q->dateTimeChanged(value.toDateTime());
2172 if (dodate && datechanged)
2173 emit q->dateChanged(value.toDate());
2174 if (dotime && timechanged)
2175 emit q->timeChanged(value.toTime());
2183 void QDateTimeEditPrivate::_q_editorCursorPositionChanged(int oldpos, int newpos)
2185 if (ignoreCursorPositionChanged || specialValue())
2187 const QString oldText = displayText();
2188 updateCache(value, oldText);
2190 const bool allowChange = !edit->hasSelectedText();
2191 const bool forward = oldpos <= newpos;
2192 ignoreCursorPositionChanged = true;
2193 int s = sectionAt(newpos);
2194 if (s == NoSectionIndex && forward && newpos > 0) {
2195 s = sectionAt(newpos - 1);
2200 const int selstart = edit->selectionStart();
2201 const int selSection = sectionAt(selstart);
2202 const int l = selSection != -1 ? sectionSize(selSection) : 0;
2204 if (s == NoSectionIndex) {
2205 if (l > 0 && selstart == sectionPos(selSection) && edit->selectedText().size() == l) {
2208 setSelected(selSection, true);
2211 int closest = closestSection(newpos, forward);
2212 c = sectionPos(closest) + (forward ? 0 : qMax<int>(0, sectionSize(closest)));
2215 edit->setCursorPosition(c);
2222 if (allowChange && currentSectionIndex != s) {
2223 interpret(EmitIfChanged);
2226 setSelected(s, true);
2227 } else if (!edit->hasSelectedText()) {
2228 if (oldpos < newpos) {
2229 edit->setCursorPosition(displayText().size() - (oldText.size() - c));
2231 edit->setCursorPosition(c);
2235 QDTEDEBUG << "currentSectionIndex is set to" << sectionName(sectionType(s))
2237 << "was" << sectionName(sectionType(currentSectionIndex));
2239 currentSectionIndex = s;
2240 Q_ASSERT_X(currentSectionIndex < sectionNodes.size(),
2241 "QDateTimeEditPrivate::_q_editorCursorPositionChanged()",
2242 qPrintable(QString::fromLatin1("Internal error (%1 %2)").
2243 arg(currentSectionIndex).
2244 arg(sectionNodes.size())));
2246 ignoreCursorPositionChanged = false;
2252 Try to get the format from the local settings
2254 void QDateTimeEditPrivate::readLocaleSettings()
2257 defaultTimeFormat = loc.timeFormat(QLocale::ShortFormat);
2258 defaultDateFormat = loc.dateFormat(QLocale::ShortFormat);
2259 defaultDateTimeFormat = loc.dateTimeFormat(QLocale::ShortFormat);
2262 QDateTimeEdit::Section QDateTimeEditPrivate::convertToPublic(QDateTimeParser::Section s)
2264 switch (s & ~Internal) {
2265 case AmPmSection: return QDateTimeEdit::AmPmSection;
2266 case MSecSection: return QDateTimeEdit::MSecSection;
2267 case SecondSection: return QDateTimeEdit::SecondSection;
2268 case MinuteSection: return QDateTimeEdit::MinuteSection;
2269 case DayOfWeekSectionShort:
2270 case DayOfWeekSectionLong:
2271 case DaySection: return QDateTimeEdit::DaySection;
2272 case MonthSection: return QDateTimeEdit::MonthSection;
2273 case YearSection2Digits:
2274 case YearSection: return QDateTimeEdit::YearSection;
2276 case Hour24Section: return QDateTimeEdit::HourSection;
2279 case LastSection: break;
2281 return QDateTimeEdit::NoSection;
2284 QDateTimeEdit::Sections QDateTimeEditPrivate::convertSections(QDateTimeParser::Sections s)
2286 QDateTimeEdit::Sections ret = 0;
2287 if (s & QDateTimeParser::MSecSection)
2288 ret |= QDateTimeEdit::MSecSection;
2289 if (s & QDateTimeParser::SecondSection)
2290 ret |= QDateTimeEdit::SecondSection;
2291 if (s & QDateTimeParser::MinuteSection)
2292 ret |= QDateTimeEdit::MinuteSection;
2293 if (s & (QDateTimeParser::Hour24Section|QDateTimeParser::Hour12Section))
2294 ret |= QDateTimeEdit::HourSection;
2295 if (s & QDateTimeParser::AmPmSection)
2296 ret |= QDateTimeEdit::AmPmSection;
2297 if (s & (QDateTimeParser::DaySection|QDateTimeParser::DayOfWeekSectionShort|QDateTimeParser::DayOfWeekSectionLong))
2298 ret |= QDateTimeEdit::DaySection;
2299 if (s & QDateTimeParser::MonthSection)
2300 ret |= QDateTimeEdit::MonthSection;
2301 if (s & (QDateTimeParser::YearSection|QDateTimeParser::YearSection2Digits))
2302 ret |= QDateTimeEdit::YearSection;
2311 void QDateTimeEdit::paintEvent(QPaintEvent *event)
2314 if (!d->calendarPopupEnabled()) {
2315 QAbstractSpinBox::paintEvent(event);
2319 QStyleOptionSpinBox opt;
2320 initStyleOption(&opt);
2322 QStyleOptionComboBox optCombo;
2324 optCombo.init(this);
2325 optCombo.editable = true;
2326 optCombo.frame = opt.frame;
2327 optCombo.subControls = opt.subControls;
2328 optCombo.activeSubControls = opt.activeSubControls;
2329 optCombo.state = opt.state;
2331 optCombo.state &= ~QStyle::State_Enabled;
2335 style()->drawComplexControl(QStyle::CC_ComboBox, &optCombo, &p, this);
2338 QString QDateTimeEditPrivate::getAmPmText(AmPm ap, Case cs) const
2341 return (cs == UpperCase ? QDateTimeEdit::tr("AM") : QDateTimeEdit::tr("am"));
2343 return (cs == UpperCase ? QDateTimeEdit::tr("PM") : QDateTimeEdit::tr("pm"));
2347 int QDateTimeEditPrivate::absoluteIndex(QDateTimeEdit::Section s, int index) const
2349 for (int i=0; i<sectionNodes.size(); ++i) {
2350 if (convertToPublic(sectionNodes.at(i).type) == s && index-- == 0) {
2354 return NoSectionIndex;
2357 int QDateTimeEditPrivate::absoluteIndex(const SectionNode &s) const
2359 return sectionNodes.indexOf(s);
2362 void QDateTimeEditPrivate::interpret(EmitPolicy ep)
2365 QString tmp = displayText();
2366 int pos = edit->cursorPosition();
2367 const QValidator::State state = q->validate(tmp, pos);
2368 if (state != QValidator::Acceptable
2369 && correctionMode == QAbstractSpinBox::CorrectToPreviousValue
2370 && (state == QValidator::Invalid || !(fieldInfo(currentSectionIndex) & AllowPartial))) {
2371 setValue(value, ep);
2374 QAbstractSpinBoxPrivate::interpret(ep);
2378 void QDateTimeEditPrivate::clearCache() const
2380 QAbstractSpinBoxPrivate::clearCache();
2385 Initialize \a option with the values from this QDataTimeEdit. This method
2386 is useful for subclasses when they need a QStyleOptionSpinBox, but don't want
2387 to fill in all the information themselves.
2389 \sa QStyleOption::initFrom()
2391 void QDateTimeEdit::initStyleOption(QStyleOptionSpinBox *option) const
2396 Q_D(const QDateTimeEdit);
2397 QAbstractSpinBox::initStyleOption(option);
2398 if (d->calendarPopupEnabled()) {
2399 option->subControls = QStyle::SC_ComboBoxFrame | QStyle::SC_ComboBoxEditField
2400 | QStyle::SC_ComboBoxArrow;
2401 if (d->arrowState == QStyle::State_Sunken)
2402 option->state |= QStyle::State_Sunken;
2404 option->state &= ~QStyle::State_Sunken;
2408 void QDateTimeEditPrivate::init(const QVariant &var)
2411 switch (var.type()) {
2412 case QVariant::Date:
2413 value = QDateTime(var.toDate(), QDATETIMEEDIT_TIME_MIN);
2414 q->setDisplayFormat(defaultDateFormat);
2415 if (sectionNodes.isEmpty()) // ### safeguard for broken locale
2416 q->setDisplayFormat(QLatin1String("dd/MM/yyyy"));
2418 case QVariant::DateTime:
2420 q->setDisplayFormat(defaultDateTimeFormat);
2421 if (sectionNodes.isEmpty()) // ### safeguard for broken locale
2422 q->setDisplayFormat(QLatin1String("dd/MM/yyyy hh:mm:ss"));
2424 case QVariant::Time:
2425 value = QDateTime(QDATETIMEEDIT_DATE_INITIAL, var.toTime());
2426 q->setDisplayFormat(defaultTimeFormat);
2427 if (sectionNodes.isEmpty()) // ### safeguard for broken locale
2428 q->setDisplayFormat(QLatin1String("hh:mm:ss"));
2431 Q_ASSERT_X(0, "QDateTimeEditPrivate::init", "Internal error");
2434 #ifdef QT_KEYPAD_NAVIGATION
2435 if (QApplication::keypadNavigationEnabled())
2436 q->setCalendarPopup(true);
2439 q->setInputMethodHints(Qt::ImhPreferNumbers);
2440 setLayoutItemMargins(QStyle::SE_DateTimeEditLayoutItem);
2443 void QDateTimeEditPrivate::_q_resetButton()
2445 updateArrow(QStyle::State_None);
2448 void QDateTimeEditPrivate::updateArrow(QStyle::StateFlag state)
2452 if (arrowState == state)
2455 if (arrowState != QStyle::State_None)
2456 buttonState |= Mouse;
2459 hoverControl = QStyle::SC_ComboBoxFrame;
2466 Returns the hover control at \a pos.
2467 This will update the hoverRect and hoverControl.
2469 QStyle::SubControl QDateTimeEditPrivate::newHoverControl(const QPoint &pos)
2471 if (!calendarPopupEnabled())
2472 return QAbstractSpinBoxPrivate::newHoverControl(pos);
2476 QStyleOptionComboBox optCombo;
2478 optCombo.editable = true;
2479 optCombo.subControls = QStyle::SC_All;
2480 hoverControl = q->style()->hitTestComplexControl(QStyle::CC_ComboBox, &optCombo, pos, q);
2481 return hoverControl;
2484 void QDateTimeEditPrivate::updateEditFieldGeometry()
2486 if (!calendarPopupEnabled()) {
2487 QAbstractSpinBoxPrivate::updateEditFieldGeometry();
2493 QStyleOptionComboBox optCombo;
2495 optCombo.editable = true;
2496 optCombo.subControls = QStyle::SC_ComboBoxEditField;
2497 edit->setGeometry(q->style()->subControlRect(QStyle::CC_ComboBox, &optCombo,
2498 QStyle::SC_ComboBoxEditField, q));
2501 QVariant QDateTimeEditPrivate::getZeroVariant() const
2503 Q_ASSERT(type == QVariant::DateTime);
2504 return QDateTime(QDATETIMEEDIT_DATE_INITIAL, QTime(), spec);
2507 void QDateTimeEditPrivate::setRange(const QVariant &min, const QVariant &max)
2509 QAbstractSpinBoxPrivate::setRange(min, max);
2510 syncCalendarWidget();
2514 bool QDateTimeEditPrivate::isSeparatorKey(const QKeyEvent *ke) const
2516 if (!ke->text().isEmpty() && currentSectionIndex + 1 < sectionNodes.size() && currentSectionIndex >= 0) {
2517 if (fieldInfo(currentSectionIndex) & Numeric) {
2518 if (ke->text().at(0).isNumber())
2520 } else if (ke->text().at(0).isLetterOrNumber()) {
2523 return separators.at(currentSectionIndex + 1).contains(ke->text());
2528 void QDateTimeEditPrivate::initCalendarPopup(QCalendarWidget *cw)
2531 if (!monthCalendar) {
2532 monthCalendar = new QCalendarPopup(q, cw);
2533 monthCalendar->setObjectName(QLatin1String("qt_datetimedit_calendar"));
2534 QObject::connect(monthCalendar, SIGNAL(newDateSelected(QDate)), q, SLOT(setDate(QDate)));
2535 QObject::connect(monthCalendar, SIGNAL(hidingCalendar(QDate)), q, SLOT(setDate(QDate)));
2536 QObject::connect(monthCalendar, SIGNAL(activated(QDate)), q, SLOT(setDate(QDate)));
2537 QObject::connect(monthCalendar, SIGNAL(activated(QDate)), monthCalendar, SLOT(close()));
2538 QObject::connect(monthCalendar, SIGNAL(resetButton()), q, SLOT(_q_resetButton()));
2540 monthCalendar->setCalendarWidget(cw);
2542 syncCalendarWidget();
2545 void QDateTimeEditPrivate::positionCalendarPopup()
2548 QPoint pos = (q->layoutDirection() == Qt::RightToLeft) ? q->rect().bottomRight() : q->rect().bottomLeft();
2549 QPoint pos2 = (q->layoutDirection() == Qt::RightToLeft) ? q->rect().topRight() : q->rect().topLeft();
2550 pos = q->mapToGlobal(pos);
2551 pos2 = q->mapToGlobal(pos2);
2552 QSize size = monthCalendar->sizeHint();
2553 QRect screen = QApplication::desktop()->availableGeometry(pos);
2554 //handle popup falling "off screen"
2555 if (q->layoutDirection() == Qt::RightToLeft) {
2556 pos.setX(pos.x()-size.width());
2557 pos2.setX(pos2.x()-size.width());
2558 if (pos.x() < screen.left())
2559 pos.setX(qMax(pos.x(), screen.left()));
2560 else if (pos.x()+size.width() > screen.right())
2561 pos.setX(qMax(pos.x()-size.width(), screen.right()-size.width()));
2563 if (pos.x()+size.width() > screen.right())
2564 pos.setX(screen.right()-size.width());
2565 pos.setX(qMax(pos.x(), screen.left()));
2567 if (pos.y() + size.height() > screen.bottom())
2568 pos.setY(pos2.y() - size.height());
2569 else if (pos.y() < screen.top())
2570 pos.setY(screen.top());
2571 if (pos.y() < screen.top())
2572 pos.setY(screen.top());
2573 if (pos.y()+size.height() > screen.bottom())
2574 pos.setY(screen.bottom()-size.height());
2575 monthCalendar->move(pos);
2578 bool QDateTimeEditPrivate::calendarPopupEnabled() const
2580 return (calendarPopup && (sections & (DateSectionMask)));
2583 void QDateTimeEditPrivate::syncCalendarWidget()
2586 if (monthCalendar) {
2587 const bool sb = monthCalendar->blockSignals(true);
2588 monthCalendar->setDateRange(q->minimumDate(), q->maximumDate());
2589 monthCalendar->setDate(q->date());
2590 monthCalendar->blockSignals(sb);
2594 QCalendarPopup::QCalendarPopup(QWidget * parent, QCalendarWidget *cw)
2595 : QWidget(parent, Qt::Popup)
2597 setAttribute(Qt::WA_WindowPropagation);
2599 dateChanged = false;
2601 verifyCalendarInstance();
2603 setCalendarWidget(cw);
2607 QCalendarWidget *QCalendarPopup::verifyCalendarInstance()
2609 if (calendar.isNull()) {
2610 QCalendarWidget *cw = new QCalendarWidget(this);
2611 cw->setVerticalHeaderFormat(QCalendarWidget::NoVerticalHeader);
2612 #ifdef QT_KEYPAD_NAVIGATION
2613 if (QApplication::keypadNavigationEnabled())
2614 cw->setHorizontalHeaderFormat(QCalendarWidget::SingleLetterDayNames);
2616 setCalendarWidget(cw);
2619 return calendar.data();
2623 void QCalendarPopup::setCalendarWidget(QCalendarWidget *cw)
2626 QVBoxLayout *widgetLayout = qobject_cast<QVBoxLayout*>(layout());
2627 if (!widgetLayout) {
2628 widgetLayout = new QVBoxLayout(this);
2629 widgetLayout->setMargin(0);
2630 widgetLayout->setSpacing(0);
2632 delete calendar.data();
2633 calendar = QPointer<QCalendarWidget>(cw);
2634 widgetLayout->addWidget(cw);
2636 connect(cw, SIGNAL(activated(QDate)), this, SLOT(dateSelected(QDate)));
2637 connect(cw, SIGNAL(clicked(QDate)), this, SLOT(dateSelected(QDate)));
2638 connect(cw, SIGNAL(selectionChanged()), this, SLOT(dateSelectionChanged()));
2644 void QCalendarPopup::setDate(const QDate &date)
2647 verifyCalendarInstance()->setSelectedDate(date);
2650 void QCalendarPopup::setDateRange(const QDate &min, const QDate &max)
2652 QCalendarWidget *cw = verifyCalendarInstance();
2653 cw->setMinimumDate(min);
2654 cw->setMaximumDate(max);
2657 void QCalendarPopup::mousePressEvent(QMouseEvent *event)
2659 QDateTimeEdit *dateTime = qobject_cast<QDateTimeEdit *>(parentWidget());
2661 QStyleOptionComboBox opt;
2663 QRect arrowRect = dateTime->style()->subControlRect(QStyle::CC_ComboBox, &opt,
2664 QStyle::SC_ComboBoxArrow, dateTime);
2665 arrowRect.moveTo(dateTime->mapToGlobal(arrowRect .topLeft()));
2666 if (arrowRect.contains(event->globalPos()) || rect().contains(event->pos()))
2667 setAttribute(Qt::WA_NoMouseReplay);
2669 QWidget::mousePressEvent(event);
2672 void QCalendarPopup::mouseReleaseEvent(QMouseEvent*)
2677 bool QCalendarPopup::event(QEvent *event)
2679 if (event->type() == QEvent::KeyPress) {
2680 QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
2681 if (keyEvent->key()== Qt::Key_Escape)
2682 dateChanged = false;
2684 return QWidget::event(event);
2687 void QCalendarPopup::dateSelectionChanged()
2690 emit newDateSelected(verifyCalendarInstance()->selectedDate());
2692 void QCalendarPopup::dateSelected(const QDate &date)
2695 emit activated(date);
2699 void QCalendarPopup::hideEvent(QHideEvent *)
2703 emit hidingCalendar(oldDate);
2707 #include "moc_qdatetimeedit.cpp"
2709 #endif // QT_NO_DATETIMEEDIT