1 /****************************************************************************
4 ** Implementation of date and time edit classes
8 ** Original qatetimeedit.cpp Copyright (C) 2000-2002 Trolltech AS. All rights reserved.
9 **>> ExtDate modifications (C) 2004 Jason Harris <jharris@30doradus.org>
11 ** This file may be distributed and/or modified under the terms of the
12 ** GNU General Public License version 2 as published by the Free Software
13 ** Foundation and appearing in the file LICENSE.GPL included in the
14 ** packaging of this file.
16 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
17 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19 ** See http://www.trolltech.com/gpl/ for GPL licensing information.
21 **********************************************************************/
26 #include "extdatetimeedit.h"
28 #ifndef QT_NO_DATETIMEEDIT
30 //#include "../kernel/qinternal_p.h"
31 //#include "../kernel/qrichtext_p.h"
32 #include <private/qinternal_p.h>
33 #include <private/qrichtext_p.h>
34 #include <qrangecontrol.h>
35 #include <qapplication.h>
37 #include <qapplication.h>
38 #include <qvaluelist.h>
41 #include <qdatetimeedit.h> //need for QTimeEdit
43 #define EXTDATETIMEEDIT_HIDDEN_CHAR '0'
45 static QString
*lDateSep
= 0;
46 static QString
*lTimeSep
= 0;
47 static bool lAMPM
= FALSE
;
48 static QString
*lAM
= 0;
49 static QString
*lPM
= 0;
50 static ExtDateEdit::Order lOrder
= ExtDateEdit::YMD
;
51 static int refcount
= 0;
67 try to get the order of DMY and the date/time separator from the locale settings
69 static void readLocaleSettings()
74 lDateSep
= new QString();
75 lTimeSep
= new QString();
80 GetLocaleInfo( LOCALE_USER_DEFAULT
, LOCALE_SDATE
, data
, 10 );
81 *lDateSep
= QString::fromUcs2( (ushort
*)data
);
82 GetLocaleInfo( LOCALE_USER_DEFAULT
, LOCALE_STIME
, data
, 10 );
83 *lTimeSep
= QString::fromUcs2( (ushort
*)data
);
84 GetLocaleInfo( LOCALE_USER_DEFAULT
, LOCALE_ITIME
, data
, 10 );
85 lAMPM
= QString::fromUcs2( (ushort
*)data
).toInt()==0;
86 GetLocaleInfo( LOCALE_USER_DEFAULT
, LOCALE_S1159
, data
, 10 );
87 QString am
= QString::fromUcs2( (ushort
*)data
);
89 lAM
= new QString( am
);
90 GetLocaleInfo( LOCALE_USER_DEFAULT
, LOCALE_S2359
, data
, 10 );
91 QString pm
= QString::fromUcs2( (ushort
*)data
);
93 lPM
= new QString( pm
);
96 GetLocaleInfoA( LOCALE_USER_DEFAULT
, LOCALE_SDATE
, (char*)&data
, 10 );
97 *lDateSep
= QString::fromLocal8Bit( data
);
98 GetLocaleInfoA( LOCALE_USER_DEFAULT
, LOCALE_STIME
, (char*)&data
, 10 );
99 *lTimeSep
= QString::fromLocal8Bit( data
);
100 GetLocaleInfoA( LOCALE_USER_DEFAULT
, LOCALE_ITIME
, (char*)&data
, 10 );
101 lAMPM
= QString::fromLocal8Bit( data
).toInt()==0;
102 GetLocaleInfoA( LOCALE_USER_DEFAULT
, LOCALE_S1159
, (char*)&data
, 10 );
103 QString am
= QString::fromLocal8Bit( data
);
105 lAM
= new QString( am
);
106 GetLocaleInfoA( LOCALE_USER_DEFAULT
, LOCALE_S2359
, (char*)&data
, 10 );
107 QString pm
= QString::fromLocal8Bit( data
);
109 lPM
= new QString( pm
);
115 QString d
= ExtDate( 1999, 11, 22 ).toString( Qt::LocalDate
);
116 dpos
= d
.find( "22" );
117 mpos
= d
.find( "11" );
118 ypos
= d
.find( "99" );
119 if ( dpos
> -1 && mpos
> -1 && ypos
> -1 ) {
120 // test for DMY, MDY, YMD, YDM
121 if ( dpos
< mpos
&& mpos
< ypos
) {
122 lOrder
= ExtDateEdit::DMY
;
123 } else if ( mpos
< dpos
&& dpos
< ypos
) {
124 lOrder
= ExtDateEdit::MDY
;
125 } else if ( ypos
< mpos
&& mpos
< dpos
) {
126 lOrder
= ExtDateEdit::YMD
;
127 } else if ( ypos
< dpos
&& dpos
< mpos
) {
128 lOrder
= ExtDateEdit::YDM
;
130 // cannot determine the dateformat - use the default
134 // this code needs to change if new formats are added
137 QString sep
= d
.mid( QMIN( dpos
, mpos
) + 2, QABS( dpos
- mpos
) - 2 );
138 if ( d
.contains( sep
) == 2 ) {
145 QString t
= QTime( 11, 22, 33 ).toString( Qt::LocalDate
);
146 dpos
= t
.find( "11" );
147 mpos
= t
.find( "22" );
148 ypos
= t
.find( "33" );
149 // We only allow hhmmss
150 if ( dpos
> -1 && dpos
< mpos
&& mpos
< ypos
) {
151 QString sep
= t
.mid( dpos
+ 2, mpos
- dpos
- 2 );
152 if ( sep
== t
.mid( mpos
+ 2, ypos
- mpos
- 2 ) ) {
159 static ExtDateEdit::Order
localOrder() {
161 readLocaleSettings();
166 static QString
localDateSep() {
168 readLocaleSettings();
173 static QString
localTimeSep() {
175 readLocaleSettings();
180 class ExtDateTimeEditorPrivate
183 ExtDateTimeEditorPrivate()
185 parag( new QTextParagraph( 0, 0, 0, FALSE
) ),
188 parag
->formatter()->setWrapEnabled( FALSE
);
189 cursor
= new QTextCursor( 0 );
190 cursor
->setParagraph( parag
);
192 sep
= localDateSep();
195 ~ExtDateTimeEditorPrivate()
203 void appendSection( const QNumberSection
& sec
)
205 sections
.append( sec
);
212 void setSectionSelection( int sec
, int selstart
, int selend
)
214 if ( sec
< 0 || sec
> (int)sections
.count() )
216 sections
[sec
].setSelectionStart( selstart
);
217 sections
[sec
].setSelectionEnd( selend
);
219 uint
sectionCount() const { return (uint
)sections
.count(); }
220 void setSeparator( const QString
& s
) { sep
= s
; }
221 QString
separator() const { return sep
; }
223 void setFrame( bool f
) { frm
= f
; }
224 bool frame() const { return frm
; }
226 int focusSection() const { return focusSec
; }
227 int section( const QPoint
& p
)
229 cursor
->place( p
+ QPoint( offset
, 0 ), parag
);
230 int idx
= cursor
->index();
231 for ( uint i
= 0; i
< sections
.count(); ++i
) {
232 if ( idx
>= sections
[i
].selectionStart() &&
233 idx
<= sections
[i
].selectionEnd() )
238 QNumberSection
section( int idx
) const
240 return sections
[idx
];
242 bool setFocusSection( int idx
)
244 if ( idx
> (int)sections
.count()-1 || idx
< 0 )
246 if ( idx
!= focusSec
) {
248 applyFocusSelection();
254 bool inSectionSelection( int idx
)
256 for ( uint i
= 0; i
< sections
.count(); ++i
) {
257 if ( idx
>= sections
[i
].selectionStart() &&
258 idx
<= sections
[i
].selectionEnd() )
264 void paint( const QString
& txt
, bool focus
, QPainter
& p
,
265 const QColorGroup
& cg
, const QRect
& rect
, QStyle
& style
)
269 fw
= style
.pixelMetric(QStyle::PM_DefaultFrameWidth
);
271 parag
->truncate( 0 );
272 parag
->append( txt
);
274 parag
->removeSelection( QTextDocument::Standard
);
276 applyFocusSelection();
279 /* color all EXTDATETIMEEDIT_HIDDEN_CHAR chars to background color */
280 QTextFormat
*fb
= parag
->formatCollection()->format( p
.font(),
282 QTextFormat
*nf
= parag
->formatCollection()->format( p
.font(),
284 for ( uint i
= 0; i
< txt
.length(); ++i
) {
285 parag
->setFormat( i
, 1, nf
);
286 if ( inSectionSelection( i
) )
288 if ( txt
.at(i
) == EXTDATETIMEEDIT_HIDDEN_CHAR
)
289 parag
->setFormat( i
, 1, fb
);
291 parag
->setFormat( i
, 1, nf
);
296 QRect
r( rect
.x(), rect
.y(), rect
.width() - 2 * ( 2 + fw
), rect
.height() );
297 parag
->pseudoDocument()->docRect
= r
;
298 parag
->invalidate(0);
301 int xoff
= 2 + fw
- offset
;
302 int yoff
= ( rect
.height() - parag
->rect().height() + 1 ) / 2;
306 p
.translate( xoff
, yoff
);
307 parag
->paint( p
, cg
, 0, TRUE
);
309 p
.translate( -xoff
, -yoff
);
312 void resize( const QSize
& size
) { sz
= size
; }
314 int mapSection( int sec
)
316 return sections
[sec
].index();
320 void applyFocusSelection()
322 if ( focusSec
> -1 ) {
323 int selstart
= sections
[ focusSec
].selectionStart();
324 int selend
= sections
[ focusSec
].selectionEnd();
325 parag
->setSelection( QTextDocument::Standard
, selstart
, selend
);
327 if ( parag
->at( selstart
)->x
< offset
||
328 parag
->at( selend
)->x
+ parag
->string()->width( selend
) > offset
+ sz
.width() ) {
329 offset
= parag
->at( selstart
)->x
;
335 QTextParagraph
*parag
;
339 QValueList
< QNumberSection
> sections
;
344 class ExtDateTimeSpinWidget
: public QSpinWidget
347 ExtDateTimeSpinWidget( QWidget
*parent
, const char *name
)
348 : QSpinWidget( parent
, name
)
353 #ifndef QT_NO_WHEELEVENT
354 void wheelEvent( QWheelEvent
*e
)
356 ExtDateTimeEditor
*editor
= (ExtDateTimeEditor
*)editWidget()->qt_cast( "ExtDateTimeEditor" );
361 int section
= editor
->sectionAt( e
->pos() );
362 editor
->setFocusSection( section
);
366 QSpinWidget::wheelEvent( e
);
372 Constructs an empty datetime editor with parent \a parent and
375 ExtDateTimeEditor::ExtDateTimeEditor( ExtDateTimeEditBase
* parent
,
377 : QWidget( parent
, name
, WNoAutoErase
)
379 d
= new ExtDateTimeEditorPrivate();
385 Destroys the object and frees any allocated resources.
388 ExtDateTimeEditor::~ExtDateTimeEditor()
397 void ExtDateTimeEditor::init()
399 setBackgroundMode( PaletteBase
);
400 setFocusSection( -1 );
401 installEventFilter( this );
402 setFocusPolicy( WheelFocus
);
410 bool ExtDateTimeEditor::event( QEvent
*e
)
412 if ( e
->type() == QEvent::FocusIn
|| e
->type() == QEvent::FocusOut
) {
413 if ( e
->type() == QEvent::FocusOut
)
414 qApp
->sendEvent( cw
, e
);
416 } else if ( e
->type() == QEvent::AccelOverride
) {
417 QKeyEvent
* ke
= (QKeyEvent
*) e
;
418 switch ( ke
->key() ) {
430 return QWidget::event( e
);
437 void ExtDateTimeEditor::resizeEvent( QResizeEvent
*e
)
439 d
->resize( e
->size() );
440 QWidget::resizeEvent( e
);
448 void ExtDateTimeEditor::paintEvent( QPaintEvent
* )
451 for ( uint i
= 0; i
< d
->sectionCount(); ++i
) {
452 txt
+= cw
->sectionFormattedText( i
);
453 if ( i
< d
->sectionCount()-1 ) {
454 if ( d
->section( i
+1 ).separator() )
455 txt
+= d
->separator();
461 QSharedDoubleBuffer
buffer( this );
463 colorGroup().brush( isEnabled() ? QColorGroup::Base
: QColorGroup::Background
);
464 buffer
.painter()->fillRect( 0, 0, width(), height(), bg
);
465 d
->paint( txt
, hasFocus(), *buffer
.painter(), colorGroup(), rect(),
472 Returns the section index at point \a p.
474 int ExtDateTimeEditor::sectionAt( const QPoint
&p
)
476 return d
->section( p
);
479 int ExtDateTimeEditor::mapSection( int sec
)
481 return d
->mapSection( sec
);
489 void ExtDateTimeEditor::mousePressEvent( QMouseEvent
*e
)
491 QPoint
p( e
->pos().x(), 0 );
492 int sec
= sectionAt( p
);
494 cw
->setFocusSection( sec
);
495 repaint( rect(), FALSE
);
502 bool ExtDateTimeEditor::eventFilter( QObject
*o
, QEvent
*e
)
505 if ( e
->type() == QEvent::KeyPress
) {
506 QKeyEvent
*ke
= (QKeyEvent
*)e
;
507 switch ( ke
->key() ) {
509 if ( d
->focusSection() < (int)d
->sectionCount()-1 ) {
510 if ( cw
->setFocusSection( focusSection()+1 ) )
511 repaint( rect(), FALSE
);
515 if ( d
->focusSection() > 0 ) {
516 if ( cw
->setFocusSection( focusSection()-1 ) )
517 repaint( rect(), FALSE
);
527 if ( ::qt_cast
<ExtDateEdit
*>(cw
) )
528 ((ExtDateEdit
*)cw
)->removeFirstNumber( d
->focusSection() );
529 else if ( ::qt_cast
<QTimeEdit
*>(cw
) )
530 ((QTimeEdit
*)cw
)->removeFirstNumber( d
->focusSection() );
533 cw
->removeLastNumber( d
->focusSection() );
537 if ( ke
->state() == Qt::ControlButton
)
541 bool hadDateEdit
= FALSE
;
543 if ( ::qt_cast
<ExtDateTimeSpinWidget
*>(w
) && qstrcmp( w
->name(), "qt_spin_widget" ) != 0 ||
544 ::qt_cast
<ExtDateTimeEdit
*>(w
) )
546 hadDateEdit
= hadDateEdit
|| ::qt_cast
<ExtDateEdit
*>(w
);
547 w
= w
->parentWidget();
551 if ( !::qt_cast
<ExtDateTimeEdit
*>(w
) ) {
552 w
= w
->parentWidget();
554 ExtDateTimeEdit
*ed
= (ExtDateTimeEdit
*)w
;
555 if ( hadDateEdit
&& ke
->key() == Key_Tab
) {
556 ed
->timeEdit()->setFocus();
558 } else if ( !hadDateEdit
&& ke
->key() == Key_BackTab
) {
559 ed
->dateEdit()->setFocus();
562 while ( w
&& !::qt_cast
<ExtDateTimeEdit
*>(w
) )
563 w
= w
->parentWidget();
567 qApp
->sendEvent( w
, e
);
572 QString txt
= ke
->text().lower();
573 if ( !txt
.isEmpty() && !separator().isEmpty() && txt
[0] == separator()[0] ) {
574 // do the same thing as KEY_RIGHT when the user presses the separator key
575 if ( d
->focusSection() < 2 ) {
576 if ( cw
->setFocusSection( focusSection()+1 ) )
577 repaint( rect(), FALSE
);
580 } else if ( !txt
.isEmpty() && ::qt_cast
<QTimeEdit
*>(cw
) && focusSection() == (int) d
->sectionCount()-1 ) {
581 // the first character of the AM/PM indicator toggles if the section has focus
582 QTimeEdit
*te
= (QTimeEdit
*)cw
;
583 QTime time
= te
->time();
584 if ( lAMPM
&& lAM
&& lPM
&& (te
->display()&QTimeEdit::AMPM
) ) {
585 if ( txt
[0] == (*lAM
).lower()[0] && time
.hour() >= 12 ) {
586 time
.setHMS( time
.hour()-12, time
.minute(), time
.second(), time
.msec() );
588 } else if ( txt
[0] == (*lPM
).lower()[0] && time
.hour() < 12 ) {
589 time
.setHMS( time
.hour()+12, time
.minute(), time
.second(), time
.msec() );
595 int num
= txt
[0].digitValue();
597 cw
->addNumber( d
->focusSection(), num
);
608 Appends the number section \a sec to the editor.
611 void ExtDateTimeEditor::appendSection( const QNumberSection
& sec
)
613 d
->appendSection( sec
);
617 Removes all sections from the editor.
620 void ExtDateTimeEditor::clearSections()
626 Sets the selection of \a sec to start at \a selstart and end at \a
630 void ExtDateTimeEditor::setSectionSelection( int sec
, int selstart
, int selend
)
632 d
->setSectionSelection( sec
, selstart
, selend
);
636 Sets the separator for all numbered sections to \a s. Note that
637 currently, only the first character of \a s is used.
640 void ExtDateTimeEditor::setSeparator( const QString
& s
)
642 d
->setSeparator( s
);
648 Returns the editor's separator.
651 QString
ExtDateTimeEditor::separator() const
653 return d
->separator();
657 Returns the number of the section that has focus.
660 int ExtDateTimeEditor::focusSection() const
662 return d
->focusSection();
667 Sets the focus to section \a sec. If \a sec does not exist,
671 bool ExtDateTimeEditor::setFocusSection( int sec
)
673 return d
->setFocusSection( sec
);
676 /*! \class ExtDateTimeEditBase ExtDatetimeedit.h
677 \brief The ExtDateTimeEditBase class provides an abstraction for date and edit editors.
680 Small abstract class that provides some functions that are common
681 for both ExtDateEdit and QTimeEdit. Its used internally by
685 /*! \fn QString ExtDateTimeEditBase::sectionFormattedText( int sec )
688 Pure virtual function which returns the formatted text of section \a
693 /*! \fn void ExtDateTimeEditBase::stepUp()
696 Pure virtual slot which is called whenever the user increases the
697 number in a section by pressing the widget's arrow buttons or the
698 keyboard's arrow keys.
701 /*! \fn void ExtDateTimeEditBase::stepDown()
704 Pure virtual slot which is called whenever the user decreases the
705 number in a section by pressing the widget's arrow buttons or the
706 keyboard's arrow keys.
710 /*! \fn void ExtDateTimeEditBase::addNumber( int sec, int num )
713 Pure virtual function which is called whenever the user types a number.
714 \a sec indicates the section where the number should be added. \a
715 num is the number that was pressed.
718 /*! \fn void ExtDateTimeEditBase::removeLastNumber( int sec )
721 Pure virtual function which is called whenever the user tries to
722 remove the last number from \a sec by pressing the delete key.
727 class ExtDateEditPrivate
733 // remebers the last entry for the day.
734 // if the day is 31 and you cycle through the months,
735 // the day will be 31 again if you reach a month with 31 days
736 // otherwise it will be the highest day in the month
741 ExtDateEdit::Order ord
;
749 ExtDateTimeEditor
*ed
;
750 QSpinWidget
*controls
;
755 \class ExtDateEdit ExtDatetimeedit.h
756 \brief The ExtDateEdit class provides a date editor.
762 ExtDateEdit allows the user to edit dates by using the keyboard or
763 the arrow keys to increase/decrease date values. The arrow keys
764 can be used to move from section to section within the ExtDateEdit
765 box. Dates appear in accordance with the local date/time settings
766 or in year, month, day order if the system doesn't provide this
767 information. It is recommended that the ExtDateEdit be initialised
771 ExtDateEdit *dateEdit = new ExtDateEdit( ExtDate::currentDate(), this );
772 dateEdit->setRange( ExtDate::currentDate().addDays( -365 ),
773 ExtDate::currentDate().addDays( 365 ) );
774 dateEdit->setOrder( ExtDateEdit::MDY );
775 dateEdit->setAutoAdvance( TRUE );
778 Here we've created a new ExtDateEdit object initialised with today's
779 date and restricted the valid date range to today plus or minus
780 365 days. We've set the order to month, day, year. If the auto
781 advance property is TRUE (as we've set it here) when the user
782 completes a section of the date, e.g. enters two digits for the
783 month, they are automatically taken to the next section.
785 The maximum and minimum values for a date value in the date editor
786 default to the maximum and minimum values for a ExtDate. You can
787 change this by calling setMinValue(), setMaxValue() or setRange().
789 Terminology: A ExtDateEdit widget comprises three 'sections', one
790 each for the year, month and day. You can change the separator
791 character using ExtDateTimeEditor::setSeparator(), by default the
792 separator will be taken from the systems settings. If that is
793 not possible, it defaults to "-".
795 \img datetimewidgets.png Date Time Widgets
797 \sa ExtDate QTimeEdit ExtDateTimeEdit
801 \enum ExtDateEdit::Order
803 This enum defines the order in which the sections that comprise a
805 \value MDY month-day-year
806 \value DMY day-month-year
807 \value YMD year-month-day (the default)
808 \value YDM year-day-month (included for completeness; but should
813 \enum QTimeEdit::Display
815 This enum defines the sections that comprise a time
817 \value Hours The hours section
818 \value Minutes The minutes section
819 \value Seconds The seconds section
820 \value AMPM The AM/PM section
822 The values can be or'ed together to show any combination.
826 Constructs an empty date editor which is a child of \a parent and
830 ExtDateEdit::ExtDateEdit( QWidget
* parent
, const char * name
)
831 : ExtDateTimeEditBase( parent
, name
)
840 Constructs a date editor with the initial value \a date, parent \a
841 parent and called \a name.
843 The date editor is initialized with \a date.
846 ExtDateEdit::ExtDateEdit( const ExtDate
& date
, QWidget
* parent
, const char * name
)
847 : ExtDateTimeEditBase( parent
, name
)
855 void ExtDateEdit::init()
857 d
= new ExtDateEditPrivate();
858 d
->controls
= new ExtDateTimeSpinWidget( this,
859 qstrcmp( name(), "qt_datetime_dateedit" ) == 0 ?
860 "qt_spin_widget" : "date edit controls" );
861 d
->ed
= new ExtDateTimeEditor( this, "date editor" );
862 d
->controls
->setEditWidget( d
->ed
);
863 setFocusProxy( d
->ed
);
864 connect( d
->controls
, SIGNAL( stepUpPressed() ), SLOT( stepUp() ) );
865 connect( d
->controls
, SIGNAL( stepDownPressed() ), SLOT( stepDown() ) );
866 connect( this, SIGNAL( valueChanged(const ExtDate
&) ),
867 SLOT( updateButtons() ) );
868 d
->ed
->appendSection( QNumberSection( 0,4 ) );
869 d
->ed
->appendSection( QNumberSection( 5,7 ) );
870 d
->ed
->appendSection( QNumberSection( 8,10 ) );
873 d
->monthSection
= -1;
880 setOrder( localOrder() );
881 setFocusSection( 0 );
886 d
->min
= ExtDate( -50000, 1, 1 );
887 d
->max
= ExtDate( 50000, 12, 31 );
890 setSizePolicy( QSizePolicy::Minimum
, QSizePolicy::Fixed
);
896 Destroys the object and frees any allocated resources.
899 ExtDateEdit::~ExtDateEdit()
907 \property ExtDateEdit::minValue
909 \brief the editor's minimum value
911 Setting the minimum date value is equivalent to calling
912 ExtDateEdit::setRange( \e d, maxValue() ), where \e d is the minimum
913 date. The default minimum date is 1752-09-14.
915 \sa maxValue setRange()
918 ExtDate
ExtDateEdit::minValue() const
924 \property ExtDateEdit::maxValue
926 \brief the editor's maximum value
928 Setting the maximum date value for the editor is equivalent to
929 calling ExtDateEdit::setRange( minValue(), \e d ), where \e d is the
930 maximum date. The default maximum date is 8000-12-31.
932 \sa minValue setRange()
935 ExtDate
ExtDateEdit::maxValue() const
942 Sets the valid input range for the editor to be from \a min to \a
943 max inclusive. If \a min is invalid no minimum date will be set.
944 Similarly, if \a max is invalid no maximum date will be set.
947 void ExtDateEdit::setRange( const ExtDate
& min
, const ExtDate
& max
)
956 Sets the separator to \a s. Note that currently only the first
957 character of \a s is used.
960 void ExtDateEdit::setSeparator( const QString
& s
)
962 d
->ed
->setSeparator( s
);
966 Returns the editor's separator.
969 QString
ExtDateEdit::separator() const
971 return d
->ed
->separator();
976 Enables/disables the push buttons according to the min/max date
980 void ExtDateEdit::updateButtons()
987 bool upEnabled
= date() < maxValue();
988 bool downEnabled
= date() > minValue();
990 d
->controls
->setUpEnabled( upEnabled
);
991 d
->controls
->setDownEnabled( downEnabled
);
996 void ExtDateEdit::resizeEvent( QResizeEvent
* )
998 d
->controls
->resize( width(), height() );
1004 QSize
ExtDateEdit::sizeHint() const
1007 QFontMetrics
fm( font() );
1008 int fw
= style().pixelMetric( QStyle::PM_DefaultFrameWidth
, this );
1009 int h
= QMAX( fm
.lineSpacing(), 14 ) + 2;
1010 int w
= 2 + fm
.width( '9' ) * 8 + fm
.width( d
->ed
->separator() ) * 2
1011 + d
->controls
->upRect().width() + fw
* 4;
1013 return QSize( w
, QMAX(h
+ fw
* 2,20) ).expandedTo( QApplication::globalStrut() );
1019 QSize
ExtDateEdit::minimumSizeHint() const
1026 Returns the formatted number for section \a sec. This will
1027 correspond to either the year, month or day section, depending on
1028 the current display order.
1033 QString
ExtDateEdit::sectionFormattedText( int sec
)
1036 txt
= sectionText( sec
);
1037 if ( d
->typing
&& sec
== d
->ed
->focusSection() )
1038 d
->ed
->setSectionSelection( sec
, sectionOffsetEnd( sec
) - txt
.length(),
1039 sectionOffsetEnd( sec
) );
1041 d
->ed
->setSectionSelection( sec
, sectionOffsetEnd( sec
) - sectionLength( sec
),
1042 sectionOffsetEnd( sec
) );
1044 txt
= txt
.rightJustify( sectionLength( sec
), EXTDATETIMEEDIT_HIDDEN_CHAR
);
1050 Returns the desired length (number of digits) of section \a sec.
1051 This will correspond to either the year, month or day section,
1052 depending on the current display order.
1057 int ExtDateEdit::sectionLength( int sec
) const
1060 if ( sec
== d
->yearSection
)
1062 else if ( sec
== d
->monthSection
)
1064 else if ( sec
== d
->daySection
)
1071 Returns the text of section \a sec. This will correspond to either
1072 the year, month or day section, depending on the current display
1078 QString
ExtDateEdit::sectionText( int sec
) const
1081 if ( sec
== d
->yearSection
)
1083 else if ( sec
== d
->monthSection
)
1085 else if ( sec
== d
->daySection
)
1088 return QString::number( val
);
1093 Returns the end of the section offset \a sec.
1097 int ExtDateEdit::sectionOffsetEnd( int sec
) const
1099 if ( sec
== d
->yearSection
) {
1103 return sectionOffsetEnd( sec
-1) + separator().length() + sectionLength( sec
);
1106 return sectionLength( sec
);
1108 } else if ( sec
== d
->monthSection
) {
1113 return sectionOffsetEnd( sec
-1) + separator().length() + sectionLength( sec
);
1115 return sectionLength( sec
);
1117 } else if ( sec
== d
->daySection
) {
1120 return sectionLength( sec
);
1124 return sectionOffsetEnd( sec
-1 ) + separator().length() + sectionLength( sec
);
1132 \property ExtDateEdit::order
1133 \brief the order in which the year, month and day appear
1135 The default order is locale dependent.
1140 void ExtDateEdit::setOrder( ExtDateEdit::Order order
)
1146 d
->monthSection
= 1;
1151 d
->monthSection
= 0;
1156 d
->monthSection
= 1;
1161 d
->monthSection
= 2;
1167 d
->ed
->repaint( d
->ed
->rect(), FALSE
);
1171 ExtDateEdit::Order
ExtDateEdit::order() const
1180 void ExtDateEdit::stepUp()
1182 int sec
= d
->ed
->focusSection();
1183 bool accepted
= FALSE
;
1184 if ( sec
== d
->yearSection
) {
1185 if ( !outOfRange( d
->y
+1, d
->m
, d
->d
) ) {
1189 } else if ( sec
== d
->monthSection
) {
1190 if ( !outOfRange( d
->y
, d
->m
+1, d
->d
) ) {
1194 } else if ( sec
== d
->daySection
) {
1195 if ( !outOfRange( d
->y
, d
->m
, d
->d
+1 ) ) {
1202 emit
valueChanged( date() );
1205 d
->ed
->repaint( d
->ed
->rect(), FALSE
);
1214 void ExtDateEdit::stepDown()
1216 int sec
= d
->ed
->focusSection();
1217 bool accepted
= FALSE
;
1218 if ( sec
== d
->yearSection
) {
1219 if ( !outOfRange( d
->y
-1, d
->m
, d
->d
) ) {
1223 } else if ( sec
== d
->monthSection
) {
1224 if ( !outOfRange( d
->y
, d
->m
-1, d
->d
) ) {
1228 } else if ( sec
== d
->daySection
) {
1229 if ( !outOfRange( d
->y
, d
->m
, d
->d
-1 ) ) {
1236 emit
valueChanged( date() );
1239 d
->ed
->repaint( d
->ed
->rect(), FALSE
);
1243 Sets the year to \a year, which must be a valid year. The range
1244 currently supported is from 1752 to 8000.
1249 void ExtDateEdit::setYear( int year
)
1251 if ( !outOfRange( year
, d
->m
, d
->d
) ) {
1259 Sets the month to \a month, which must be a valid month, i.e.
1263 void ExtDateEdit::setMonth( int month
)
1269 if ( !outOfRange( d
->y
, month
, d
->d
) ) {
1277 Sets the day to \a day, which must be a valid day. The function
1278 will ensure that the \a day set is valid for the month and year.
1281 void ExtDateEdit::setDay( int day
)
1283 ExtDate test
= ExtDate( d
->y
, d
->m
, 1 );
1287 if ( day
> test
.daysInMonth() )
1288 day
= test
.daysInMonth();
1296 \property ExtDateEdit::date
1297 \brief the editor's date value.
1299 If the date property is not valid, the editor displays all zeroes
1300 and ExtDateEdit::date() will return an invalid date. It is strongly
1301 recommended that the editor is given a default date value (e.g.
1302 currentDate()). That way, attempts to set the date property to an
1303 invalid date will fail.
1305 When changing the date property, if the date is less than
1306 minValue(), or is greater than maxValue(), nothing happens.
1309 void ExtDateEdit::setDate( const ExtDate
& date
)
1311 if ( !date
.isValid() ) {
1317 if ( date
> maxValue() || date
< minValue() )
1320 d
->m
= date
.month();
1323 emit
valueChanged( date
);
1326 d
->ed
->repaint( d
->ed
->rect(), FALSE
);
1329 ExtDate
ExtDateEdit::date() const
1331 if ( ExtDate::isValid( d
->y
, d
->m
, d
->d
) )
1332 return ExtDate( d
->y
, d
->m
, d
->d
);
1338 Returns TRUE if \a y, \a m, \a d is out of range, otherwise returns
1345 bool ExtDateEdit::outOfRange( int y
, int m
, int d
) const
1347 if ( ExtDate::isValid( y
, m
, d
) ) {
1348 ExtDate
currentDate( y
, m
, d
);
1349 if ( currentDate
> maxValue() || currentDate
< minValue() ) {
1350 //## outOfRange should set overwrite?
1355 return FALSE
; /* assume ok */
1362 void ExtDateEdit::addNumber( int sec
, int num
)
1366 killTimer( d
->timerId
);
1367 bool overwrite
= FALSE
;
1368 bool accepted
= FALSE
;
1371 if ( sec
== d
->yearSection
) {
1372 txt
= QString::number( d
->y
);
1373 if ( d
->overwrite
|| txt
.length() == 4 ) {
1377 txt
+= QString::number( num
);
1378 if ( txt
.length() == 4 ) {
1379 int val
= txt
.toInt();
1382 else if ( val
> 8000 )
1384 else if ( outOfRange( val
, d
->m
, d
->d
) )
1385 txt
= QString::number( d
->y
);
1394 if ( d
->adv
&& txt
.length() == 4 ) {
1395 d
->ed
->setFocusSection( d
->ed
->focusSection()+1 );
1399 } else if ( sec
== d
->monthSection
) {
1400 txt
= QString::number( d
->m
);
1401 if ( d
->overwrite
|| txt
.length() == 2 ) {
1405 txt
+= QString::number( num
);
1406 int temp
= txt
.toInt();
1409 if ( outOfRange( d
->y
, temp
, d
->d
) )
1410 txt
= QString::number( d
->m
);
1415 if ( d
->adv
&& txt
.length() == 2 ) {
1416 d
->ed
->setFocusSection( d
->ed
->focusSection()+1 );
1420 } else if ( sec
== d
->daySection
) {
1421 txt
= QString::number( d
->d
);
1422 if ( d
->overwrite
|| txt
.length() == 2 ) {
1427 txt
+= QString::number( num
);
1428 int temp
= txt
.toInt();
1431 if ( outOfRange( d
->y
, d
->m
, temp
) )
1432 txt
= QString::number( d
->d
);
1438 if ( d
->adv
&& txt
.length() == 2 ) {
1439 d
->ed
->setFocusSection( d
->ed
->focusSection()+1 );
1446 emit
valueChanged( date() );
1448 d
->overwrite
= overwrite
;
1449 d
->timerId
= startTimer( qApp
->doubleClickInterval()*4 );
1450 d
->ed
->repaint( d
->ed
->rect(), FALSE
);
1458 bool ExtDateEdit::setFocusSection( int s
)
1460 if ( s
!= d
->ed
->focusSection() ) {
1461 killTimer( d
->timerId
);
1462 d
->overwrite
= TRUE
;
1464 fix(); // will emit valueChanged if necessary
1466 return d
->ed
->setFocusSection( s
);
1471 Attempts to fix any invalid date entries.
1473 The rules applied are as follows:
1476 \i if the day is larger than the number of days in the month,
1477 \i it is reset to that number
1478 \i If the year has four digits it is left unchanged.
1479 \i If the year has two digits, the year will be changed to four
1480 digits in the range current year - 70 to current year + 29.
1481 \i If the year has three digits in the range 100..999, the
1482 current millennium, i.e. 2000, will be added giving a year
1483 in the range 2100..2999.
1488 void ExtDateEdit::fix()
1490 bool changed
= FALSE
;
1492 ExtDate test
= ExtDate( d
->y
, d
->m
, 1 );
1493 if ( d
->d
> test
.daysInMonth() ) {
1495 d
->d
= test
.daysInMonth();
1499 int currentYear
= ExtDate::currentDate().year();
1502 int currentCentury
= currentYear
/ 100;
1503 year
+= currentCentury
* 100;
1504 if ( currentYear
> year
) {
1505 if ( currentYear
> year
+ 70 )
1508 if ( year
>= currentYear
+ 30 )
1512 } else if ( year
< 1000 ) {
1513 int currentMillennium
= currentYear
/ 10;
1514 year
+= currentMillennium
* 10;
1517 if ( changed
&& outOfRange( year
, d
->m
, d
->d
) ) {
1518 if ( minValue().isValid() && date() < minValue() ) {
1519 d
->d
= minValue().day();
1521 d
->m
= minValue().month();
1522 d
->y
= minValue().year();
1524 if ( date() > maxValue() ) {
1525 d
->d
= maxValue().day();
1527 d
->m
= maxValue().month();
1528 d
->y
= maxValue().year();
1530 } else if ( changed
)
1534 // emit valueChanged( date() );
1535 // d->changed = FALSE;
1544 bool ExtDateEdit::event( QEvent
*e
)
1546 if( e
->type() == QEvent::FocusOut
) {
1548 // the following can't be done in fix() because fix() called
1549 // from all over the place and it will break the old behaviour
1550 if ( !ExtDate::isValid( d
->y
, d
->m
, d
->d
) ) {
1553 for ( ; i
> 0; i
-- ) {
1555 if ( ExtDate::isValid( d
->y
, d
->m
, d
->d
) )
1562 emit
valueChanged( date() );
1565 } else if ( e
->type() == QEvent::LocaleChange
) {
1566 readLocaleSettings();
1567 d
->ed
->setSeparator( localDateSep() );
1568 setOrder( localOrder() );
1571 bool result
= ExtDateTimeEditBase::event( e
);
1579 Function which is called whenever the user tries to
1580 remove the first number from \a sec by pressing the backspace key.
1583 void ExtDateEdit::removeFirstNumber( int sec
)
1588 if ( sec
== d
->yearSection
) {
1589 txt
= QString::number( d
->y
);
1590 txt
= txt
.mid( 1, txt
.length() ) + "0";
1592 } else if ( sec
== d
->monthSection
) {
1593 txt
= QString::number( d
->m
);
1594 txt
= txt
.mid( 1, txt
.length() ) + "0";
1596 } else if ( sec
== d
->daySection
) {
1597 txt
= QString::number( d
->d
);
1598 txt
= txt
.mid( 1, txt
.length() ) + "0";
1602 d
->ed
->repaint( d
->ed
->rect(), FALSE
);
1609 void ExtDateEdit::removeLastNumber( int sec
)
1614 if ( sec
== d
->yearSection
) {
1615 txt
= QString::number( d
->y
);
1616 txt
= txt
.mid( 0, txt
.length()-1 );
1618 } else if ( sec
== d
->monthSection
) {
1619 txt
= QString::number( d
->m
);
1620 txt
= txt
.mid( 0, txt
.length()-1 );
1622 } else if ( sec
== d
->daySection
) {
1623 txt
= QString::number( d
->d
);
1624 txt
= txt
.mid( 0, txt
.length()-1 );
1628 d
->ed
->repaint( d
->ed
->rect(), FALSE
);
1632 \property ExtDateEdit::autoAdvance
1633 \brief whether the editor automatically advances to the next
1636 If autoAdvance is TRUE, the editor will automatically advance
1637 focus to the next date section if a user has completed a section.
1638 The default is FALSE.
1641 void ExtDateEdit::setAutoAdvance( bool advance
)
1647 bool ExtDateEdit::autoAdvance() const
1655 void ExtDateEdit::timerEvent( QTimerEvent
* )
1657 d
->overwrite
= TRUE
;
1661 \fn void ExtDateEdit::valueChanged( const ExtDate& date )
1663 This signal is emitted whenever the editor's value changes. The \a
1664 date parameter is the new value.
1669 class QTimeEditPrivate
1683 ExtDateTimeEditor
*ed
;
1684 QSpinWidget
*controls
;
1688 \class QTimeEdit ExtDatetimeedit.h
1689 \brief The QTimeEdit class provides a time editor.
1695 QTimeEdit allows the user to edit times by using the keyboard or
1696 the arrow keys to increase/decrease time values. The arrow keys
1697 can be used to move from section to section within the QTimeEdit
1698 box. The user can automatically be moved to the next section once
1699 they complete a section using setAutoAdvance(). Times appear in
1700 hour, minute, second order. It is recommended that the QTimeEdit
1701 is initialised with a time, e.g.
1703 QTime timeNow = QTime::currentTime();
1704 QTimeEdit *timeEdit = new QTimeEdit( timeNow, this );
1705 timeEdit->setRange( timeNow, timeNow.addSecs( 60 * 60 ) );
1707 Here we've created a QTimeEdit widget set to the current time.
1708 We've also set the minimum value to the current time and the
1709 maximum time to one hour from now.
1711 The maximum and minimum values for a time value in the time editor
1712 default to the maximum and minimum values for a QTime. You can
1713 change this by calling setMinValue(), setMaxValue() or setRange().
1715 Terminology: A QTimeWidget consists of three sections, one each
1716 for the hour, minute and second. You can change the separator
1717 character using setSeparator(), by default the separator is read
1718 from the system's settings.
1720 \img datetimewidgets.png Date Time Widgets
1722 \sa QTime ExtDateEdit ExtDateTimeEdit
1727 // Constructs an empty time edit with parent \a parent and called \a
1731 // QTimeEdit::QTimeEdit( QWidget * parent, const char * name )
1732 // : ExtDateTimeEditBase( parent, name )
1740 // Constructs a time edit with the initial time value, \a time,
1741 // parent \a parent and called \a name.
1744 // QTimeEdit::QTimeEdit( const QTime& time, QWidget * parent, const char * name )
1745 // : ExtDateTimeEditBase( parent, name )
1754 // void QTimeEdit::init()
1756 // d = new QTimeEditPrivate();
1757 // d->ed = new ExtDateTimeEditor( this, "time edit base" );
1758 // d->controls = new ExtDateTimeSpinWidget( this, qstrcmp( name(), "qt_datetime_timeedit" ) == 0 ? "qt_spin_widget" : "time edit controls" );
1759 // d->controls->setEditWidget( d->ed );
1760 // setFocusProxy( d->ed );
1761 // connect( d->controls, SIGNAL( stepUpPressed() ), SLOT( stepUp() ) );
1762 // connect( d->controls, SIGNAL( stepDownPressed() ), SLOT( stepDown() ) );
1764 // d->ed->appendSection( QNumberSection( 0,0, TRUE, 0 ) );
1765 // d->ed->appendSection( QNumberSection( 0,0, TRUE, 1 ) );
1766 // d->ed->appendSection( QNumberSection( 0,0, TRUE, 2 ) );
1767 // d->ed->setSeparator( localTimeSep() );
1772 // d->display = Hours | Minutes | Seconds;
1774 // d->display |= AMPM;
1775 // d->ed->appendSection( QNumberSection( 0,0, FALSE, 3 ) );
1778 // d->overwrite = TRUE;
1780 // d->typing = FALSE;
1781 // d->min = QTime( 0, 0, 0 );
1782 // d->max = QTime( 23, 59, 59 );
1783 // d->changed = FALSE;
1785 // setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Fixed );
1791 // Destroys the object and frees any allocated resources.
1794 // QTimeEdit::~QTimeEdit()
1797 // if ( !--refcount )
1802 // \property QTimeEdit::minValue
1803 // \brief the minimum time value
1805 // Setting the minimum time value is equivalent to calling
1806 // QTimeEdit::setRange( \e t, maxValue() ), where \e t is the minimum
1807 // time. The default minimum time is 00:00:00.
1809 // \sa maxValue setRange()
1812 // QTime QTimeEdit::minValue() const
1818 // \property QTimeEdit::maxValue
1819 // \brief the maximum time value
1821 // Setting the maximum time value is equivalent to calling
1822 // QTimeEdit::setRange( minValue(), \e t ), where \e t is the maximum
1823 // time. The default maximum time is 23:59:59.
1825 // \sa minValue setRange()
1828 // QTime QTimeEdit::maxValue() const
1835 // Sets the valid input range for the editor to be from \a min to \a
1836 // max inclusive. If \a min is invalid no minimum time is set.
1837 // Similarly, if \a max is invalid no maximum time is set.
1840 // void QTimeEdit::setRange( const QTime& min, const QTime& max )
1842 // if ( min.isValid() )
1844 // if ( max.isValid() )
1849 // \property QTimeEdit::display
1850 // \brief the sections that are displayed in the time edit
1852 // The value can be any combination of the values in the Display enum.
1853 // By default, the widget displays hours, minutes and seconds.
1855 // void QTimeEdit::setDisplay( uint display )
1857 // if ( d->display == display )
1860 // d->ed->clearSections();
1861 // d->display = display;
1862 // if ( d->display & Hours )
1863 // d->ed->appendSection( QNumberSection( 0,0, TRUE, 0 ) );
1864 // if ( d->display & Minutes )
1865 // d->ed->appendSection( QNumberSection( 0,0, TRUE, 1 ) );
1866 // if ( d->display & Seconds )
1867 // d->ed->appendSection( QNumberSection( 0,0, TRUE, 2 ) );
1868 // if ( d->display & AMPM )
1869 // d->ed->appendSection( QNumberSection( 0,0, FALSE, 3 ) );
1871 // d->ed->setFocusSection( 0 );
1875 // uint QTimeEdit::display() const
1877 // return d->display;
1881 // \property QTimeEdit::time
1882 // \brief the editor's time value.
1884 // When changing the time property, if the time is less than
1885 // minValue(), or is greater than maxValue(), nothing happens.
1888 // void QTimeEdit::setTime( const QTime& time )
1890 // if ( !time.isValid() ) {
1895 // if ( time > maxValue() || time < minValue() )
1897 // d->h = time.hour();
1898 // d->m = time.minute();
1899 // d->s = time.second();
1900 // emit valueChanged( time );
1902 // d->changed = FALSE;
1903 // d->ed->repaint( d->ed->rect(), FALSE );
1906 // QTime QTimeEdit::time() const
1908 // if ( QTime::isValid( d->h, d->m, d->s ) )
1909 // return QTime( d->h, d->m, d->s );
1914 // \property QTimeEdit::autoAdvance
1915 // \brief whether the editor automatically advances to the next
1918 // If autoAdvance is TRUE, the editor will automatically advance
1919 // focus to the next time section if a user has completed a section.
1920 // The default is FALSE.
1923 // void QTimeEdit::setAutoAdvance( bool advance )
1925 // d->adv = advance;
1928 // bool QTimeEdit::autoAdvance() const
1934 // Sets the separator to \a s. Note that currently only the first
1935 // character of \a s is used.
1938 // void QTimeEdit::setSeparator( const QString& s )
1940 // d->ed->setSeparator( s );
1944 // Returns the editor's separator.
1947 // QString QTimeEdit::separator() const
1949 // return d->ed->separator();
1954 // \fn void QTimeEdit::valueChanged( const QTime& time )
1956 // This signal is emitted whenever the editor's value changes. The \a
1957 // time parameter is the new value.
1964 // bool QTimeEdit::event( QEvent *e )
1966 // if ( e->type() == QEvent::FocusOut ) {
1967 // d->typing = FALSE;
1968 // if ( d->changed ) {
1969 // emit valueChanged( time() );
1970 // d->changed = FALSE;
1972 // } else if ( e->type() == QEvent::LocaleChange ) {
1973 // readLocaleSettings();
1974 // d->ed->setSeparator( localTimeSep() );
1976 // return ExtDateTimeEditBase::event( e );
1983 // void QTimeEdit::timerEvent( QTimerEvent * )
1985 // d->overwrite = TRUE;
1993 // void QTimeEdit::stepUp()
1995 // int sec = d->ed->mapSection( d->ed->focusSection() );
1996 // bool accepted = TRUE;
1999 // if ( !outOfRange( d->h+1, d->m, d->s ) )
2000 // setHour( d->h+1 );
2002 // setHour( d->min.hour() );
2005 // if ( !outOfRange( d->h, d->m+1, d->s ) )
2006 // setMinute( d->m+1 );
2008 // setMinute( d->min.minute() );
2011 // if ( !outOfRange( d->h, d->m, d->s+1 ) )
2012 // setSecond( d->s+1 );
2014 // setSecond( d->min.second() );
2018 // setHour( d->h+12 );
2020 // setHour( d->h-12 );
2023 // accepted = FALSE;
2024 // #ifdef QT_CHECK_RANGE
2025 // qWarning( "QTimeEdit::stepUp: Focus section out of range!" );
2029 // if ( accepted ) {
2030 // d->changed = TRUE;
2031 // emit valueChanged( time() );
2033 // d->ed->repaint( d->ed->rect(), FALSE );
2041 // void QTimeEdit::stepDown()
2043 // int sec = d->ed->mapSection( d->ed->focusSection() );
2045 // bool accepted = TRUE;
2048 // if ( !outOfRange( d->h-1, d->m, d->s ) )
2049 // setHour( d->h-1 );
2051 // setHour( d->max.hour() );
2054 // if ( !outOfRange( d->h, d->m-1, d->s ) )
2055 // setMinute( d->m-1 );
2057 // setMinute( d->max.minute() );
2060 // if ( !outOfRange( d->h, d->m, d->s-1 ) )
2061 // setSecond( d->s-1 );
2063 // setSecond( d->max.second() );
2067 // setHour( d->h-12 );
2069 // setHour( d->h+12 );
2072 // accepted = FALSE;
2073 // #ifdef QT_CHECK_RANGE
2074 // qWarning( "QTimeEdit::stepDown: Focus section out of range!" );
2078 // if ( accepted ) {
2079 // d->changed = TRUE;
2080 // emit valueChanged( time() );
2082 // d->ed->repaint( d->ed->rect(), FALSE );
2087 // Returns the formatted number for section \a sec. This will
2088 // correspond to either the hour, minute or second section, depending
2092 // QString QTimeEdit::sectionFormattedText( int sec )
2095 // txt = sectionText( sec );
2096 // txt = txt.rightJustify( 2, EXTDATETIMEEDIT_HIDDEN_CHAR );
2097 // int offset = sec*2+sec*separator().length() + txt.length();
2098 // if ( d->typing && sec == d->ed->focusSection() )
2099 // d->ed->setSectionSelection( sec, offset - txt.length(), offset );
2101 // d->ed->setSectionSelection( sec, offset - txt.length(), offset );
2111 // bool QTimeEdit::setFocusSection( int sec )
2113 // if ( sec != d->ed->focusSection() ) {
2114 // killTimer( d->timerId );
2115 // d->overwrite = TRUE;
2116 // d->typing = FALSE;
2117 // QString txt = sectionText( sec );
2118 // txt = txt.rightJustify( 2, EXTDATETIMEEDIT_HIDDEN_CHAR );
2119 // int offset = sec*2+sec*separator().length() + txt.length();
2120 // d->ed->setSectionSelection( sec, offset - txt.length(), offset );
2121 // if ( d->changed ) {
2122 // emit valueChanged( time() );
2123 // d->changed = FALSE;
2126 // return d->ed->setFocusSection( sec );
2131 // Sets the hour to \a h, which must be a valid hour, i.e. in the
2135 // void QTimeEdit::setHour( int h )
2146 // Sets the minute to \a m, which must be a valid minute, i.e. in the
2150 // void QTimeEdit::setMinute( int m )
2161 // Sets the second to \a s, which must be a valid second, i.e. in the
2165 // void QTimeEdit::setSecond( int s )
2177 // Returns the text of section \a sec.
2181 // QString QTimeEdit::sectionText( int sec )
2183 // sec = d->ed->mapSection( sec );
2188 // if ( !(d->display & AMPM) || ( d->h < 13 && d->h ) ) { // I wished the day stared at 0:00 for everybody
2189 // txt = QString::number( d->h );
2192 // txt = QString::number( d->h - 12 );
2198 // txt = QString::number( d->m );
2201 // txt = QString::number( d->s );
2204 // if ( d->h < 12 ) {
2208 // txt = QString::fromLatin1( "AM" );
2213 // txt = QString::fromLatin1( "PM" );
2224 // Returns TRUE if \a h, \a m, and \a s are out of range.
2227 // bool QTimeEdit::outOfRange( int h, int m, int s ) const
2229 // if ( QTime::isValid( h, m, s ) ) {
2230 // QTime currentTime( h, m, s );
2231 // if ( currentTime > maxValue() ||
2232 // currentTime < minValue() )
2244 // void QTimeEdit::addNumber( int sec, int num )
2248 // sec = d->ed->mapSection( sec );
2249 // killTimer( d->timerId );
2250 // bool overwrite = FALSE;
2251 // bool accepted = FALSE;
2252 // d->typing = TRUE;
2257 // txt = ( d->display & AMPM && d->h > 12 ) ?
2258 // QString::number( d->h - 12 ) : QString::number( d->h );
2260 // if ( d->overwrite || txt.length() == 2 ) {
2261 // if ( d->display & AMPM && num == 0 )
2262 // break; // Don't process 0 in 12 hour clock mode
2263 // if ( d->display & AMPM && d->h > 11 )
2265 // if ( !outOfRange( num, d->m, d->s ) ) {
2270 // txt += QString::number( num );
2271 // int temp = txt.toInt();
2273 // if ( d->display & AMPM ) {
2274 // if ( temp == 12 ) {
2275 // if ( d->h < 12 ) {
2279 // } else if ( outOfRange( temp + 12, d->m, d->s ) ) {
2280 // txt = QString::number( d->h );
2282 // if ( d->h > 11 ) {
2287 // } else if ( !(d->display & AMPM) && outOfRange( temp, d->m, d->s ) ) {
2288 // txt = QString::number( d->h );
2296 // if ( d->adv && txt.length() == 2 ) {
2297 // setFocusSection( d->ed->focusSection()+1 );
2298 // overwrite = TRUE;
2304 // txt = QString::number( d->m );
2305 // if ( d->overwrite || txt.length() == 2 ) {
2306 // if ( !outOfRange( d->h, num, d->s ) ) {
2311 // txt += QString::number( num );
2312 // int temp = txt.toInt();
2315 // if ( outOfRange( d->h, temp, d->s ) )
2316 // txt = QString::number( d->m );
2321 // if ( d->adv && txt.length() == 2 ) {
2322 // setFocusSection( d->ed->focusSection()+1 );
2323 // overwrite = TRUE;
2329 // txt = QString::number( d->s );
2330 // if ( d->overwrite || txt.length() == 2 ) {
2331 // if ( !outOfRange( d->h, d->m, num ) ) {
2336 // txt += QString::number( num );
2337 // int temp = txt.toInt();
2340 // if ( outOfRange( d->h, d->m, temp ) )
2341 // txt = QString::number( d->s );
2346 // if ( d->adv && txt.length() == 2 ) {
2347 // setFocusSection( d->ed->focusSection()+1 );
2348 // overwrite = TRUE;
2359 // d->changed = accepted;
2361 // emit valueChanged( time() );
2362 // d->overwrite = overwrite;
2363 // d->timerId = startTimer( qApp->doubleClickInterval()*4 );
2364 // d->ed->repaint( d->ed->rect(), FALSE );
2371 // Function which is called whenever the user tries to
2372 // remove the first number from \a sec by pressing the backspace key.
2375 // void QTimeEdit::removeFirstNumber( int sec )
2379 // sec = d->ed->mapSection( sec );
2383 // txt = QString::number( d->h );
2386 // txt = QString::number( d->m );
2389 // txt = QString::number( d->s );
2392 // txt = txt.mid( 1, txt.length() ) + "0";
2395 // d->h = txt.toInt();
2398 // d->m = txt.toInt();
2401 // d->s = txt.toInt();
2404 // d->ed->repaint( d->ed->rect(), FALSE );
2410 // void QTimeEdit::removeLastNumber( int sec )
2414 // sec = d->ed->mapSection( sec );
2418 // txt = QString::number( d->h );
2421 // txt = QString::number( d->m );
2424 // txt = QString::number( d->s );
2427 // txt = txt.mid( 0, txt.length()-1 );
2430 // d->h = txt.toInt();
2433 // d->m = txt.toInt();
2436 // d->s = txt.toInt();
2439 // d->ed->repaint( d->ed->rect(), FALSE );
2444 // void QTimeEdit::resizeEvent( QResizeEvent * )
2446 // d->controls->resize( width(), height() );
2451 // QSize QTimeEdit::sizeHint() const
2454 // QFontMetrics fm( font() );
2455 // int fw = style().pixelMetric( QStyle::PM_DefaultFrameWidth, this );
2456 // int h = fm.lineSpacing() + 2;
2457 // int w = 2 + fm.width( '9' ) * 6 + fm.width( d->ed->separator() ) * 2 +
2458 // d->controls->upRect().width() + fw * 4;
2459 // if ( d->display & AMPM ) {
2461 // w += fm.width( *lAM ) + 4;
2463 // w += fm.width( QString::fromLatin1( "AM" ) ) + 4;
2466 // return QSize( w, QMAX(h + fw * 2,20) ).expandedTo( QApplication::globalStrut() );
2471 // QSize QTimeEdit::minimumSizeHint() const
2473 // return sizeHint();
2478 // Enables/disables the push buttons according to the min/max time
2482 // // ### Remove in 4.0?
2484 // void QTimeEdit::updateButtons()
2486 // if ( !isEnabled() )
2489 // bool upEnabled = time() < maxValue();
2490 // bool downEnabled = time() > minValue();
2492 // d->controls->setUpEnabled( upEnabled );
2493 // d->controls->setDownEnabled( downEnabled );
2497 class ExtDateTimeEditPrivate
2504 \class ExtDateTimeEdit ExtDatetimeedit.h
2505 \brief The ExtDateTimeEdit class combines a ExtDateEdit and QTimeEdit
2506 widget into a single widget for editing datetimes.
2512 ExtDateTimeEdit consists of a ExtDateEdit and QTimeEdit widget placed
2513 side by side and offers the functionality of both. The user can
2514 edit the date and time by using the keyboard or the arrow keys to
2515 increase/decrease date or time values. The Tab key can be used to
2516 move from section to section within the ExtDateTimeEdit widget, and
2517 the user can be moved automatically when they complete a section
2518 using setAutoAdvance(). The datetime can be set with
2521 The date format is read from the system's locale settings. It is
2522 set to year, month, day order if that is not possible. See
2523 ExtDateEdit::setOrder() to change this. Times appear in the order
2524 hours, minutes, seconds using the 24 hour clock.
2526 It is recommended that the ExtDateTimeEdit is initialised with a
2529 ExtDateTimeEdit *dateTimeEdit = new ExtDateTimeEdit( ExtDateTime::currentDateTime(), this );
2530 dateTimeEdit->dateEdit()->setRange( ExtDateTime::currentDate(),
2531 ExtDateTime::currentDate().addDays( 7 ) );
2533 Here we've created a new ExtDateTimeEdit set to the current date and
2534 time, and set the date to have a minimum date of now and a maximum
2535 date of a week from now.
2537 Terminology: A ExtDateEdit widget consists of three 'sections', one
2538 each for the year, month and day. Similarly a QTimeEdit consists
2539 of three sections, one each for the hour, minute and second. The
2540 character that separates each date section is specified with
2541 setDateSeparator(); similarly setTimeSeparator() is used for the
2544 \img datetimewidgets.png Date Time Widgets
2546 \sa ExtDateEdit QTimeEdit
2550 Constructs an empty datetime edit with parent \a parent and called
2553 ExtDateTimeEdit::ExtDateTimeEdit( QWidget
* parent
, const char * name
)
2554 : QWidget( parent
, name
)
2563 Constructs a datetime edit with the initial value \a datetime,
2564 parent \a parent and called \a name.
2566 ExtDateTimeEdit::ExtDateTimeEdit( const ExtDateTime
& datetime
,
2567 QWidget
* parent
, const char * name
)
2568 : QWidget( parent
, name
)
2571 setDateTime( datetime
);
2577 Destroys the object and frees any allocated resources.
2580 ExtDateTimeEdit::~ExtDateTimeEdit()
2589 Intercepts and handles resize events which have special meaning
2590 for the ExtDateTimeEdit.
2593 void ExtDateTimeEdit::resizeEvent( QResizeEvent
* )
2595 int dw
= de
->sizeHint().width();
2596 int tw
= te
->sizeHint().width();
2599 int extra
= w
- ( dw
+ tw
);
2601 if ( tw
+ extra
< 0 ) {
2604 dw
+= 9 * extra
/ 16;
2608 de
->setGeometry( 0, 0, dw
, h
);
2609 te
->setGeometry( dw
, 0, tw
, h
);
2615 QSize
ExtDateTimeEdit::minimumSizeHint() const
2617 QSize dsh
= de
->minimumSizeHint();
2618 QSize tsh
= te
->minimumSizeHint();
2619 return QSize( dsh
.width() + tsh
.width(),
2620 QMAX( dsh
.height(), tsh
.height() ) );
2626 void ExtDateTimeEdit::init()
2628 d
= new ExtDateTimeEditPrivate();
2629 de
= new ExtDateEdit( this, "qt_datetime_dateedit" );
2630 te
= new QTimeEdit( this, "qt_datetime_timeedit" );
2632 connect( de
, SIGNAL( valueChanged( const ExtDate
& ) ),
2633 this, SLOT( newValue( const ExtDate
& ) ) );
2634 connect( te
, SIGNAL( valueChanged( const QTime
& ) ),
2635 this, SLOT( newValue( const QTime
& ) ) );
2636 setFocusProxy( de
);
2637 setSizePolicy( QSizePolicy::Minimum
, QSizePolicy::Fixed
);
2643 QSize
ExtDateTimeEdit::sizeHint() const
2646 QSize dsh
= de
->sizeHint();
2647 QSize tsh
= te
->sizeHint();
2648 return QSize( dsh
.width() + tsh
.width(),
2649 QMAX( dsh
.height(), tsh
.height() ) );
2653 \property ExtDateTimeEdit::dateTime
2654 \brief the editor's datetime value
2656 The datetime edit's datetime which may be an invalid datetime.
2659 void ExtDateTimeEdit::setDateTime( const ExtDateTime
& dt
)
2661 if ( dt
.isValid() ) {
2662 de
->setDate( dt
.date() );
2663 te
->setTime( dt
.time() );
2664 emit
valueChanged( dt
);
2668 ExtDateTime
ExtDateTimeEdit::dateTime() const
2670 return ExtDateTime( de
->date(), te
->time() );
2674 \fn void ExtDateTimeEdit::valueChanged( const ExtDateTime& datetime )
2676 This signal is emitted every time the date or time changes. The \a
2677 datetime argument is the new datetime.
2683 Re-emits the value \a d.
2686 void ExtDateTimeEdit::newValue( const ExtDate
& )
2688 ExtDateTime dt
= dateTime();
2689 emit
valueChanged( dt
);
2694 Re-emits the value \a t.
2697 void ExtDateTimeEdit::newValue( const QTime
& )
2699 ExtDateTime dt
= dateTime();
2700 emit
valueChanged( dt
);
2705 Sets the auto advance property of the editor to \a advance. If set
2706 to TRUE, the editor will automatically advance focus to the next
2707 date or time section if the user has completed a section.
2710 void ExtDateTimeEdit::setAutoAdvance( bool advance
)
2712 de
->setAutoAdvance( advance
);
2713 te
->setAutoAdvance( advance
);
2717 Returns TRUE if auto-advance is enabled, otherwise returns FALSE.
2719 \sa setAutoAdvance()
2722 bool ExtDateTimeEdit::autoAdvance() const
2724 return de
->autoAdvance();
2728 \fn ExtDateEdit* ExtDateTimeEdit::dateEdit()
2730 Returns the internal widget used for editing the date part of the
2735 \fn QTimeEdit* ExtDateTimeEdit::timeEdit()
2737 Returns the internal widget used for editing the time part of the
2741 #include "extdatetimeedit.moc"