]> Git trees. - libqmvoc.git/commitdiff
libkdeedu/extdate for kde-4 now compiles. I had to disable the
authorJason Harris <kstars@30doradus.org>
Thu, 4 Aug 2005 06:12:58 +0000 (06:12 +0000)
committerJason Harris <kstars@30doradus.org>
Thu, 4 Aug 2005 06:12:58 +0000 (06:12 +0000)
ExtDateTimeEdit class, because making it work is going to require a
major reimplementation.  Since we need this library in order to work on
the rest of KStars, I don't want to let this minor widget stand in the
way.

libkde/kdeeduplot already compiles, but there is still a compile problem
with libkdeedu/kdeeduui (specifically, the glossary widget that we use).
I will see if I can get that library compiling as well, then we can
finally start porting kstars itself.

CCMAIL: kstars-devel@kde.org

svn path=/trunk/KDE/kdeedu/libkdeedu/; revision=442868

extdate/extdatetimeedit.cpp
extdate/extdatetimeedit.h
extdate/extdatewidget.cpp
extdate/test_extdate.cc

index 7c5a67c266c5e853cf15a089bdcfae7308b500af..26c1404e6e8701ff85ab929c3ebe41e34677a56a 100644 (file)
+/*****  --==>> JH: Commenting entire file, for now.
+ *****  This class is derived from QDateTimeEdit, which makes use of 
+ *****  QVariant(QDateTime).  It is not possible to translate this to 
+ *****  ExtDateTime easily.  I will have to write a custom widget eventually.
+ *****  However, we need this directory to compile so that the kde4 port 
+ *****  can proceed.  So I am commenting out the class.
+ */
+
+#if 0
+  --- ENTIRE CLASS COMMENTED OUT ---
+
 /****************************************************************************
 **
+** Copyright (C) 1992-2005 Trolltech AS. All rights reserved.
 **
-** Implementation of date and time edit classes
-**
-** Created : 001103
+** This file is part of the QtGui module of the Qt Toolkit.
 **
-** Original qatetimeedit.cpp Copyright (C) 2000-2002 Trolltech AS.  All rights reserved.
-**>> ExtDate modifications (C) 2004 Jason Harris <jharris@30doradus.org>
+** This file may be used under the terms of the GNU General Public
+** License version 2.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of
+** this file.  Please review the following information to ensure GNU
+** General Public Licensing requirements will be met:
+** http://www.trolltech.com/products/qt/opensource.html
 **
-** This file may be distributed and/or modified under the terms of the
-** GNU General Public License version 2 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file.
+** If you are unsure which license is appropriate for your use, please
+** review the following information:
+** http://www.trolltech.com/products/qt/licensing.html or contact the
+** sales department at sales@trolltech.com.
 **
 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 **
-** See http://www.trolltech.com/gpl/ for GPL licensing information.
-**
-**********************************************************************/
+****************************************************************************/
 
-//DEBUG
-#include <kdebug.h>
+#include <private/qabstractspinbox_p.h>
+#include <qabstractspinbox.h>
+#include <qapplication.h>
+#include <qlineedit.h>
+#include <qevent.h>
+#include <math.h>
 
 #include "extdatetimeedit.h"
 
 #ifndef QT_NO_DATETIMEEDIT
 
-//#include "../kernel/qinternal_p.h"
-//#include "../kernel/qrichtext_p.h"
-#include <q3rangecontrol.h>
-#include <qapplication.h>
-#include <qpixmap.h>
-#include <qapplication.h>
-#include <q3valuelist.h>
-#include <qstring.h>
-#include <qstyle.h>
-#include <q3datetimeedit.h> //need for QTimeEdit
-//Added by qt3to4:
-#include <QPaintEvent>
-#include <QResizeEvent>
-#include <QMouseEvent>
-#include <QTimerEvent>
-#include <QKeyEvent>
-#include <QEvent>
-#include <QWheelEvent>
-
-#define EXTDATETIMEEDIT_HIDDEN_CHAR '0'
-
-static QString *lDateSep = 0;
-static QString *lTimeSep = 0;
-static bool    lAMPM     = FALSE;
-static QString *lAM      = 0;
-static QString *lPM      = 0;
-static ExtDateEdit::Order      lOrder = ExtDateEdit::YMD;
-static int refcount = 0;
-
-static void cleanup()
-{
-    delete lDateSep;
-    lDateSep = 0;
-    delete lTimeSep;
-    lTimeSep = 0;
-    delete lAM;
-    lAM = 0;
-    delete lPM;
-    lPM = 0;
-}
-
-/*!
-\internal
-try to get the order of DMY and the date/time separator from the locale settings
-*/
-static void readLocaleSettings()
-{
-    int dpos, mpos, ypos;
-    cleanup();
-
-    lDateSep = new QString();
-    lTimeSep = new QString();
-
-#if defined(Q_WS_WIN)
-    QT_WA( {
-       TCHAR data[10];
-       GetLocaleInfo( LOCALE_USER_DEFAULT, LOCALE_SDATE, data, 10 );
-       *lDateSep = QString::fromUcs2( (ushort*)data );
-       GetLocaleInfo( LOCALE_USER_DEFAULT, LOCALE_STIME, data, 10 );
-       *lTimeSep = QString::fromUcs2( (ushort*)data );
-       GetLocaleInfo( LOCALE_USER_DEFAULT, LOCALE_ITIME, data, 10 );
-       lAMPM = QString::fromUcs2( (ushort*)data ).toInt()==0;
-       GetLocaleInfo( LOCALE_USER_DEFAULT, LOCALE_S1159, data, 10 );
-       QString am = QString::fromUcs2( (ushort*)data );
-       if ( !am.isEmpty() )
-           lAM = new QString( am );
-       GetLocaleInfo( LOCALE_USER_DEFAULT, LOCALE_S2359, data, 10 );
-       QString pm = QString::fromUcs2( (ushort*)data );
-       if ( !pm.isEmpty()  )
-           lPM = new QString( pm );
-    } , {
-       char data[10];
-       GetLocaleInfoA( LOCALE_USER_DEFAULT, LOCALE_SDATE, (char*)&data, 10 );
-       *lDateSep = QString::fromLocal8Bit( data );
-       GetLocaleInfoA( LOCALE_USER_DEFAULT, LOCALE_STIME, (char*)&data, 10 );
-       *lTimeSep = QString::fromLocal8Bit( data );
-       GetLocaleInfoA( LOCALE_USER_DEFAULT, LOCALE_ITIME, (char*)&data, 10 );
-       lAMPM = QString::fromLocal8Bit( data ).toInt()==0;
-       GetLocaleInfoA( LOCALE_USER_DEFAULT, LOCALE_S1159, (char*)&data, 10 );
-       QString am = QString::fromLocal8Bit( data );
-       if ( !am.isEmpty() )
-           lAM = new QString( am );
-       GetLocaleInfoA( LOCALE_USER_DEFAULT, LOCALE_S2359, (char*)&data, 10 );
-       QString pm = QString::fromLocal8Bit( data );
-       if ( !pm.isEmpty() )
-           lPM = new QString( pm );
-    } );
-#else
-    *lDateSep = "-";
-    *lTimeSep = ":";
-#endif
-    QString d = ExtDate( 1999, 11, 22 ).toString( Qt::LocalDate );
-    dpos = d.find( "22" );
-    mpos = d.find( "11" );
-    ypos = d.find( "99" );
-    if ( dpos > -1 && mpos > -1 && ypos > -1 ) {
-       // test for DMY, MDY, YMD, YDM
-       if ( dpos < mpos && mpos < ypos ) {
-           lOrder = ExtDateEdit::DMY;
-       } else if ( mpos < dpos && dpos < ypos ) {
-           lOrder = ExtDateEdit::MDY;
-       } else if ( ypos < mpos && mpos < dpos ) {
-           lOrder = ExtDateEdit::YMD;
-       } else if ( ypos < dpos && dpos < mpos ) {
-           lOrder = ExtDateEdit::YDM;
-       } else {
-           // cannot determine the dateformat - use the default
-           return;
-       }
-
-       // this code needs to change if new formats are added
-
-#ifndef Q_WS_WIN
-       QString sep = d.mid( QMIN( dpos, mpos ) + 2, QABS( dpos - mpos ) - 2 );
-       if ( d.contains( sep ) == 2 ) {
-           *lDateSep = sep;
-       }
-#endif
-    }
+enum {
+    Neither = -1,
+    AM = 0,
+    PM = 1,
+    PossibleAM = 2,
+    PossiblePM = 3,
+    PossibleBoth = 4
+};
 
-#ifndef Q_WS_WIN
-    QString t = QTime( 11, 22, 33 ).toString( Qt::LocalDate );
-    dpos = t.find( "11" );
-    mpos = t.find( "22" );
-    ypos = t.find( "33" );
-    // We only allow hhmmss
-    if ( dpos > -1 && dpos < mpos && mpos < ypos ) {
-       QString sep = t.mid( dpos + 2, mpos - dpos - 2 );
-       if ( sep == t.mid( mpos + 2, ypos - mpos - 2 ) ) {
-           *lTimeSep = sep;
-       }
-    }
+#ifdef Q_WS_MAC
+#include <private/qt_mac_p.h>
+extern QString qt_mac_from_pascal_string(const Str255); //qglobal.cpp
 #endif
-}
 
-static ExtDateEdit::Order localOrder() {
-    if ( !lDateSep ) {
-       readLocaleSettings();
-    }
-    return lOrder;
-}
-
-static QString localDateSep() {
-    if ( !lDateSep ) {
-       readLocaleSettings();
-    }
-    return *lDateSep;
-}
-
-static QString localTimeSep() {
-    if ( !lTimeSep ) {
-       readLocaleSettings();
-    }
-    return *lTimeSep;
-}
+//#define EXTDATETIMEEDIT_EDTEDEBUG
+#ifdef EXTDATETIMEEDIT_EDTEDEBUG
+#  define EDTEDEBUG qDebug() << QString("%1:%2").arg(__FILE__).arg(__LINE__)
+#  define EDTEDEBUGN qDebug
+#else
+#  define EDTEDEBUG if (false) qDebug()
+#  define EDTEDEBUGN if (false) qDebug
+#endif
+#include <qdebug.h>
 
-class ExtDateTimeEditorPrivate
+class ExtDateTimeEditPrivate : public QAbstractSpinBoxPrivate
 {
+    Q_DECLARE_PUBLIC(ExtDateTimeEdit)
 public:
-    ExtDateTimeEditorPrivate()
-       : frm( TRUE ),
-         parag( new QTextParagraph( 0, 0, 0, FALSE ) ),
-         focusSec(0)
-    {
-       parag->formatter()->setWrapEnabled( FALSE );
-       cursor = new QTextCursor( 0 );
-       cursor->setParagraph( parag );
-       offset = 0;
-       sep = localDateSep();
-       refcount++;
-    }
-    ~ExtDateTimeEditorPrivate()
-    {
-       delete parag;
-       delete cursor;
-       if ( !--refcount )
-           cleanup();
-    }
+    enum Section {
+        NoSection = 0x0000,
+        AmPmSection = 0x0001,
+        MSecSection = 0x0002,
+        SecondSection = 0x0004,
+        MinuteSection = 0x0008,
+        HourSection = 0x0010,
+        TimeSectionMask = (AmPmSection|MSecSection|SecondSection|MinuteSection|HourSection),
+        Internal = 0x8000,
+        AmPmLowerCaseSection = AmPmSection|Internal,
+        DaySection = 0x0100,
+        MonthSection = 0x0200,
+        YearSection = 0x0400,
+        MonthShortNameSection = MonthSection|Internal,
+        YearTwoDigitsSection = YearSection|Internal,
+        DateSectionMask = (DaySection|MonthSection|YearSection),
+        FirstSection = 0x1000|Internal,
+        LastSection = 0x2000|Internal
+    }; // duplicated from qdatetimeedit.h
+
+    struct SectionNode {
+        Section section;
+        int pos;
+    };
+
+    ExtDateTimeEditPrivate();
+
+    void readLocaleSettings();
+
+    void emitSignals(EmitPolicy ep, const QVariant &old);
+    QString textFromValue(const QVariant &f) const;
+    QVariant valueFromText(const QString &f) const;
+    QVariant validateAndInterpret(QString &input, int &, QValidator::State &state) const;
+    void editorCursorPositionChanged(int lastpos, int newpos);
+
+    QVariant valueForPosition(int pos) const;
+
+    void clearSection(Section s);
+
+    int sectionSize(Section s) const;
+    int sectionPos(Section s) const;
+
+    SectionNode sectionNode(Section t) const;
+    QVariant stepBy(Section s, int steps, bool test = false) const;
+    QString sectionText(const QString &text, Section s) const;
+    int getDigit(const QVariant &dt, Section s) const;
+    void setDigit(QVariant &t, Section s, int newval) const;
+    int sectionValue(Section s, QString &txt, QValidator::State &state) const;
+    int absoluteMax(Section s) const;
+    int absoluteMin(Section s) const;
+    Section sectionAt(int index) const;
+    Section closestSection(int index, bool forward) const;
+    SectionNode nextPrevSection(Section current, bool forward) const;
+    bool parseFormat(const QString &format);
+    void setSelected(Section s, bool forward = false);
+    QValidator::State checkIntermediate(const ExtDateTime &dt, const QString &str) const;
+
+    bool addSection(QList<SectionNode> &list, Section ds, int pos) const;
+    int findMonth(const QString &str1, int index = 1) const;
+    int findAmPm(QString &str1, Section s) const;
+    int maxChange(ExtDateTimeEditPrivate::Section s) const;
+    int potentialValue(const QString &str, int min, int max, Section s) const;
+    int potentialValueHelper(const QString &str, int min, int max, int size) const;
+    int multiplier(Section s) const;
+    QString sectionName(int s) const;
+    QString stateName(int s) const;
+    QString sectionFormat(int s) const;
+
+    QString displayFormat;
+    QString defaultDateFormat, defaultTimeFormat, defaultDateTimeFormat;
+    QString escapedFormat;
+    // this format is the same amount of letters as the resulting string
+    // e.g. if the format is hh:ap and am/pm is translated to foobar/barfoo escapedFormat
+    // will be "hh:ap    "
+    QList<SectionNode> sectionNodes;
+    SectionNode first, last;
+    QStringList separators;
+    ExtDateTimeEdit::Sections display;
+    mutable int cachedDay;
+    mutable Section currentSection;
+    Qt::LayoutDirection layoutDirection;
+};
 
-    void appendSection( const QNumberSection& sec )
-    {
-       sections.append( sec );
+// --- ExtDateTimeEdit ---
 
-    }
-    void clearSections()
-    {
-       sections.clear();
-    }
-    void setSectionSelection( int sec, int selstart, int selend )
-    {
-       if ( sec < 0 || sec > (int)sections.count() )
-           return;
-       sections[sec].setSelectionStart( selstart );
-       sections[sec].setSelectionEnd( selend );
-    }
-    uint sectionCount() const { return (uint)sections.count(); }
-    void setSeparator( const QString& s ) { sep = s; }
-    QString separator() const { return sep; }
+/*!
+  \class ExtDateTimeEdit qdatetimeedit.h
+  \brief The ExtDateTimeEdit class provides a widget for editing dates and times.
 
-    void setFrame( bool f ) { frm = f; }
-    bool frame() const { return frm; }
+  \ingroup basic
+  \mainclass
 
-    int focusSection() const { return focusSec; }
-    int section( const QPoint& p )
-    {
-       cursor->place( p + QPoint( offset, 0 ), parag );
-       int idx = cursor->index();
-       for ( uint i = 0; i < sections.count(); ++i ) {
-           if ( idx >= sections[i].selectionStart() &&
-                idx <= sections[i].selectionEnd() )
-               return i;
-       }
-       return -1;
-    }
-    QNumberSection section( int idx ) const
-    {
-       return sections[idx];
-    }
-    bool setFocusSection( int idx )
-    {
-       if ( idx > (int)sections.count()-1 || idx < 0 )
-           return FALSE;
-       if ( idx != focusSec ) {
-           focusSec = idx;
-           applyFocusSelection();
-           return TRUE;
-       }
-       return FALSE;
-    }
+  ExtDateTimeEdit allows the user to edit dates by using the keyboard or
+  the arrow keys to increase and decrease date and time values. The
+  arrow keys can be used to move from section to section within the
+  ExtDateTimeEdit box. Dates and times appear in accordance with the
+  format set; see setDisplayFormat().
 
-    bool inSectionSelection( int idx )
-    {
-       for ( uint i = 0; i < sections.count(); ++i ) {
-           if ( idx >= sections[i].selectionStart() &&
-                idx <= sections[i].selectionEnd() )
-               return TRUE;
-       }
-       return FALSE;
-    }
+  \code
+  ExtDateTimeEdit *dateEdit = new ExtDateTimeEdit(ExtDate::currentDate());
+  dateEdit->setMinimumDate(ExtDate::currentDate().addDays(-365));
+  dateEdit->setMaximumDate(ExtDate::currentDate().addDays(365));
+  dateEdit->setDisplayFormat("yyyy.MM.dd");
+  \endcode
 
-    void paint( const QString& txt, bool focus, QPainter& p,
-               const QColorGroup& cg, const QRect& rect, QStyle& style )
-    {
-       int fw = 0;
-       if ( frm )
-           fw = style.pixelMetric(QStyle::PM_DefaultFrameWidth);
-
-       parag->truncate( 0 );
-       parag->append( txt );
-       if ( !focus )
-           parag->removeSelection( QTextDocument::Standard );
-       else {
-           applyFocusSelection();
-       }
-
-       /* color all EXTDATETIMEEDIT_HIDDEN_CHAR chars to background color */
-       QTextFormat *fb = parag->formatCollection()->format( p.font(),
-                                                            cg.base() );
-       QTextFormat *nf = parag->formatCollection()->format( p.font(),
-                                                            cg.text() );
-       for ( uint i = 0; i < txt.length(); ++i ) {
-           parag->setFormat( i, 1, nf );
-           if ( inSectionSelection( i ) )
-               continue;
-           if ( txt.at(i) == EXTDATETIMEEDIT_HIDDEN_CHAR )
-               parag->setFormat( i, 1, fb );
-           else
-               parag->setFormat( i, 1, nf );
-       }
-       fb->removeRef();
-       nf->removeRef();
-
-       QRect r( rect.x(), rect.y(), rect.width() - 2 * ( 2 + fw ), rect.height() );
-       parag->pseudoDocument()->docRect = r;
-       parag->invalidate(0);
-       parag->format();
-
-       int xoff = 2 + fw - offset;
-       int yoff = ( rect.height() - parag->rect().height() + 1 ) / 2;
-       if ( yoff < 0 )
-           yoff = 0;
-
-       p.translate( xoff, yoff );
-       parag->paint( p, cg, 0, TRUE );
-       if ( frm )
-           p.translate( -xoff, -yoff );
-    }
-
-    void resize( const QSize& size ) { sz = size; }
-
-    int mapSection( int sec )
-    {
-       return sections[sec].index();
-    }
+  Here we've created a new ExtDateTimeEdit object initialized with
+  today's date, and restricted the valid date range to today plus or
+  minus 365 days. We've set the order to month, day, year.
 
-protected:
-    void applyFocusSelection()
-    {
-       if ( focusSec > -1 ) {
-           int selstart = sections[ focusSec ].selectionStart();
-           int selend = sections[ focusSec ].selectionEnd();
-           parag->setSelection( QTextDocument::Standard, selstart, selend );
-           parag->format();
-           if ( parag->at( selstart )->x < offset ||
-                parag->at( selend )->x + parag->string()->width( selend ) > offset + sz.width() ) {
-               offset = parag->at( selstart )->x;
-           }
-       }
-    }
-private:
-    bool frm;
-    QTextParagraph *parag;
-    QTextCursor *cursor;
-    QSize sz;
-    int focusSec;
-    Q3ValueList< QNumberSection > sections;
-    QString sep;
-    int offset;
-};
+  The maximum and minimum values for a date value in the date editor
+  default to the maximum and minimum values for a ExtDate. You can
+  change this by calling setMinimumDate(), setMaximumDate(),
+  setMinimumTime(), and setMaximumTime().
+*/
 
-class ExtDateTimeSpinWidget : public Q3SpinWidget
-{
-public:
-    ExtDateTimeSpinWidget( QWidget *parent, const char *name )
-       : Q3SpinWidget( parent, name )
-    {
-    }
+/*!
+  \enum ExtDateTimeEdit::Section
 
-protected:
-#ifndef QT_NO_WHEELEVENT
-    void wheelEvent( QWheelEvent *e )
-    {
-       ExtDateTimeEditor *editor = (ExtDateTimeEditor*)editWidget()->qt_cast( "ExtDateTimeEditor" );
-       Q_ASSERT( editor );
-       if ( !editor )
-           return;
+  \value NoSection
+  \value AmPmSection
+  \value MSecSection
+  \value SecondSection
+  \value MinuteSection
+  \value HourSection
+  \value DaySection
+  \value MonthSection
+  \value YearSection
+  \omitvalue DateSections_Mask
+  \omitvalue TimeSections_Mask
+*/
 
-       int section = editor->sectionAt( e->pos() );
-       editor->setFocusSection( section );
+/*!
+  \fn void ExtDateTimeEdit::dateTimeChanged(const ExtDateTime &datetime)
 
-       if ( section == -1 )
-           return;
-       Q3SpinWidget::wheelEvent( e );
-    }
-#endif
-};
+  This signal is emitted whenever the date or time is changed. The
+  new date and time is passed in \a datetime.
+*/
 
 /*!
-    Constructs an empty datetime editor with parent \a parent and
-    called \a name.
+  \fn void ExtDateTimeEdit::timeChanged(const QTime &time)
+
+  This signal is emitted whenever the time is changed. The new time
+  is passed in \a time.
 */
-ExtDateTimeEditor::ExtDateTimeEditor( ExtDateTimeEditBase * parent,
-                                 const char * name )
-    : QWidget( parent, name, Qt::WNoAutoErase )
-{
-    d = new ExtDateTimeEditorPrivate();
-    cw = parent;
-    init();
-}
 
 /*!
-    Destroys the object and frees any allocated resources.
-*/
+  \fn void ExtDateTimeEdit::dateChanged(const ExtDate &date)
 
-ExtDateTimeEditor::~ExtDateTimeEditor()
-{
-    delete d;
-}
+  This signal is emitted whenever the date is changed. The new date
+  is passed in \a date.
+*/
 
-/*! \internal
 
+/*!
+  Constructs an empty date time editor with a \a parent.
 */
 
-void ExtDateTimeEditor::init()
+ExtDateTimeEdit::ExtDateTimeEdit(QWidget *parent)
+    : QAbstractSpinBox(*new ExtDateTimeEditPrivate, parent)
 {
-    setBackgroundMode( PaletteBase );
-    setFocusSection( -1 );
-    installEventFilter( this );
-    setFocusPolicy( WheelFocus );
-}
-
+    Q_D(ExtDateTimeEdit);
 
-/*! \reimp
+    d->minimum = QVariant(DATETIME_MIN);
+    d->maximum = QVariant(DATETIME_MAX);
+    d->value = QVariant(ExtDateTime(DATE_INITIAL, TIME_MIN));
+    setDisplayFormat(d->defaultDateTimeFormat);
+    if (d->displayFormat.isEmpty()) {
+        d->defaultDateTimeFormat = QLatin1String("MM/dd/yy hh:mm:ss");
+        setDisplayFormat(d->defaultDateTimeFormat);
+    }
+}
 
+/*!
+  Constructs an empty date time editor with a \a parent. The value
+  is set to \a datetime.
 */
 
-bool ExtDateTimeEditor::event( QEvent *e )
+ExtDateTimeEdit::ExtDateTimeEdit(const ExtDateTime &datetime, QWidget *parent)
+    : QAbstractSpinBox(*new ExtDateTimeEditPrivate, parent)
 {
-    if ( e->type() == QEvent::FocusIn || e->type() == QEvent::FocusOut ) {
-       if ( e->type() == QEvent::FocusOut )
-           qApp->sendEvent( cw, e );
-       update( rect() );
-    } else if ( e->type() == QEvent::AccelOverride ) {
-       QKeyEvent* ke = (QKeyEvent*) e;
-       switch ( ke->key() ) {
-       case Key_Delete:
-       case Key_Backspace:
-       case Key_Up:
-       case Key_Down:
-       case Key_Left:
-       case Key_Right:
-           ke->accept();
-       default:
-           break;
-       }
+    Q_D(ExtDateTimeEdit);
+    d->minimum = QVariant(DATETIME_MIN);
+    d->maximum = QVariant(DATETIME_MAX);
+    d->value = datetime.isValid() ? QVariant(datetime) : QVariant(ExtDateTime(DATE_INITIAL, TIME_MIN));
+    setDisplayFormat(d->defaultDateTimeFormat);
+    if (d->displayFormat.isEmpty()) {
+        d->defaultDateTimeFormat = QLatin1String("MM/dd/yy hh:mm:ss");
+        setDisplayFormat(d->defaultDateTimeFormat);
     }
-    return QWidget::event( e );
 }
 
-/*! \reimp
+/*!
+  \fn ExtDateTimeEdit::ExtDateTimeEdit(const ExtDate &date, QWidget *parent)
 
+  Constructs an empty date time editor with a \a parent.
+  The value is set to \a date.
 */
 
-void ExtDateTimeEditor::resizeEvent( QResizeEvent *e )
+ExtDateTimeEdit::ExtDateTimeEdit(const ExtDate &date, QWidget *parent)
+    : QAbstractSpinBox(*new ExtDateTimeEditPrivate, parent)
 {
-    d->resize( e->size() );
-    QWidget::resizeEvent( e );
+    Q_D(ExtDateTimeEdit);
+    d->minimum = QVariant(DATETIME_MIN);
+    d->maximum = QVariant(DATETIME_MAX);
+    d->value = QVariant(ExtDateTime(date.isValid() ? date : DATE_INITIAL, TIME_MIN));
+    setDisplayFormat(d->defaultDateFormat);
+    if (d->displayFormat.isEmpty()) {
+        d->defaultDateFormat = QLatin1String("MM/dd/yy");
+        setDisplayFormat(d->defaultDateFormat);
+    }
 }
 
+/*!
+  \fn ExtDateTimeEdit::ExtDateTimeEdit(const QTime &time, QWidget *parent)
 
-/*! \reimp
-
+  Constructs an empty date time editor with a \a parent.
+  The value is set to \a time.
 */
 
-void ExtDateTimeEditor::paintEvent( QPaintEvent * )
+ExtDateTimeEdit::ExtDateTimeEdit(const QTime &time, QWidget *parent)
+    : QAbstractSpinBox(*new ExtDateTimeEditPrivate, parent)
 {
-    QString txt;
-    for ( uint i = 0; i < d->sectionCount(); ++i ) {
-       txt += cw->sectionFormattedText( i );
-       if ( i < d->sectionCount()-1 ) {
-           if ( d->section( i+1 ).separator() )
-               txt += d->separator();
-           else
-               txt += " ";
-       }
+    Q_D(ExtDateTimeEdit);
+    d->minimum = QVariant(DATETIME_MIN);
+    d->maximum = QVariant(DATETIME_MAX);
+    d->value = QVariant(ExtDateTime(DATE_INITIAL, time.isValid() ? time : TIME_MIN));
+    setDisplayFormat(d->defaultTimeFormat);
+    if (d->displayFormat.isEmpty()) {
+        d->defaultDateFormat = QLatin1String("hh:mm:ss");
+        setDisplayFormat(d->defaultTimeFormat);
     }
+}
 
-    QSharedDoubleBuffer buffer( this );
-    const QBrush &bg =
-       colorGroup().brush( isEnabled() ? QColorGroup::Base : QColorGroup::Background );
-    buffer.painter()->fillRect( 0, 0, width(), height(), bg );
-    d->paint( txt, hasFocus(), *buffer.painter(), colorGroup(), rect(),
-             style() );
-    buffer.end();
+ExtDateTime ExtDateTimeEdit::dateTime() const
+{
+    Q_D(const ExtDateTimeEdit);
+    return d->value.toDateTime();
 }
 
+void ExtDateTimeEdit::setDateTime(const ExtDateTime &datetime)
+{
+    Q_D(ExtDateTimeEdit);
+    if (datetime.isValid()) {
+        d->cachedDay = -1;
+        d->setValue(QVariant(datetime), EmitIfChanged);
+    }
+}
 
 /*!
-    Returns the section index at point \a p.
+  \property ExtDateTimeEdit::date
+  \brief the ExtDate that is set in the ExtDateTimeEdit
+
+  \sa time
 */
-int ExtDateTimeEditor::sectionAt( const QPoint &p )
+
+ExtDate ExtDateTimeEdit::date() const
 {
-    return d->section( p );
+    Q_D(const ExtDateTimeEdit);
+    return d->value.toDate();
 }
 
-int ExtDateTimeEditor::mapSection( int sec )
+void ExtDateTimeEdit::setDate(const ExtDate &date)
 {
-    return d->mapSection( sec );
+    Q_D(ExtDateTimeEdit);
+    if (date.isValid()) {
+        d->cachedDay = -1;
+        d->setValue(QVariant(ExtDateTime(date, d->value.toTime())), EmitIfChanged);
+    }
 }
 
+/*!
+  \property ExtDateTimeEdit::time
+  \brief the QTime that is set in the ExtDateTimeEdit
 
-/*! \reimp
-
+  \sa date
 */
 
-void ExtDateTimeEditor::mousePressEvent( QMouseEvent *e )
+QTime ExtDateTimeEdit::time() const
 {
-    QPoint p( e->pos().x(), 0 );
-    int sec = sectionAt( p );
-    if ( sec != -1 ) {
-       cw->setFocusSection( sec );
-       repaint( rect(), FALSE );
-    }
+    Q_D(const ExtDateTimeEdit);
+    return d->value.toTime();
 }
 
-/*! \reimp
-
-*/
-bool ExtDateTimeEditor::eventFilter( QObject *o, QEvent *e )
+void ExtDateTimeEdit::setTime(const QTime &time)
 {
-    if ( o == this ) {
-       if ( e->type() == QEvent::KeyPress ) {
-           QKeyEvent *ke = (QKeyEvent*)e;
-           switch ( ke->key() ) {
-           case Key_Right:
-               if ( d->focusSection() < (int)d->sectionCount()-1 ) {
-                   if ( cw->setFocusSection( focusSection()+1 ) )
-                       repaint( rect(), FALSE );
-               }
-               return TRUE;
-           case Key_Left:
-               if ( d->focusSection() > 0 ) {
-                   if ( cw->setFocusSection( focusSection()-1 ) )
-                       repaint( rect(), FALSE );
-               }
-               return TRUE;
-           case Key_Up:
-               cw->stepUp();
-               return TRUE;
-           case Key_Down:
-               cw->stepDown();
-               return TRUE;
-           case Key_Backspace:
-               if ( ::qt_cast<ExtDateEdit*>(cw) )
-                   ((ExtDateEdit*)cw)->removeFirstNumber( d->focusSection() );
-               else if ( ::qt_cast<Q3TimeEdit*>(cw) )
-                   ((Q3TimeEdit*)cw)->removeFirstNumber( d->focusSection() );
-               return TRUE;
-           case Key_Delete:
-               cw->removeLastNumber( d->focusSection() );
-               return TRUE;
-           case Key_Tab:
-           case Key_BackTab: {
-               if ( ke->state() == Qt::ControlButton )
-                   return FALSE;
+    Q_D(ExtDateTimeEdit);
+    if (time.isValid()) {
+        d->cachedDay = -1;
+        d->setValue(QVariant(ExtDateTime(d->value.toDate(), time)), EmitIfChanged);
+    }
+}
 
-               QWidget *w = this;
-               bool hadDateEdit = FALSE;
-               while ( w ) {
-                   if ( ::qt_cast<ExtDateTimeSpinWidget*>(w) && qstrcmp( w->name(), "qt_spin_widget" ) != 0 ||
-                        ::qt_cast<ExtDateTimeEdit*>(w) )
-                       break;
-                   hadDateEdit = hadDateEdit || ::qt_cast<ExtDateEdit*>(w);
-                   w = w->parentWidget();
-               }
+/*!
+  \property ExtDateTimeEdit::dateTime
+  \brief the ExtDateTime that is set in the ExtDateTimeEdit
 
-               if ( w ) {
-                   if ( !::qt_cast<ExtDateTimeEdit*>(w) ) {
-                       w = w->parentWidget();
-                   } else {
-                       ExtDateTimeEdit *ed = (ExtDateTimeEdit*)w;
-                       if ( hadDateEdit && ke->key() == Key_Tab ) {
-                           ed->timeEdit()->setFocus();
-                           return TRUE;
-                       } else if ( !hadDateEdit && ke->key() == Key_BackTab ) {
-                           ed->dateEdit()->setFocus();
-                           return TRUE;
-                       } else {
-                           while ( w && !::qt_cast<ExtDateTimeEdit*>(w) )
-                               w = w->parentWidget();
-                       }
-                   }
+  \sa minimumDate, minimumTime, maximumDate, maximumTime
+*/
 
-                   qApp->sendEvent( w, e );
-                   return TRUE;
-               }
-           } break;
-           default:
-               QString txt = ke->text().lower();
-               if ( !txt.isEmpty() && !separator().isEmpty() && txt[0] == separator()[0] ) {
-                   // do the same thing as KEY_RIGHT when the user presses the separator key
-                   if ( d->focusSection() < 2 ) {
-                       if ( cw->setFocusSection( focusSection()+1 ) )
-                           repaint( rect(), FALSE );
-                   }
-                   return TRUE;
-               } else if ( !txt.isEmpty() && ::qt_cast<Q3TimeEdit*>(cw) && focusSection() == (int) d->sectionCount()-1 ) {
-                   // the first character of the AM/PM indicator toggles if the section has focus
-                   Q3TimeEdit *te = (Q3TimeEdit*)cw;
-                   QTime time = te->time();
-                   if ( lAMPM && lAM && lPM && (te->display()&Q3TimeEdit::AMPM) ) {
-                       if ( txt[0] == (*lAM).lower()[0] && time.hour() >= 12 ) {
-                           time.setHMS( time.hour()-12, time.minute(), time.second(), time.msec() );
-                           te->setTime( time );
-                       } else if ( txt[0] == (*lPM).lower()[0] && time.hour() < 12 ) {
-                           time.setHMS( time.hour()+12, time.minute(), time.second(), time.msec() );
-                           te->setTime( time );
-                       }
-                   }
-               }
+/*!
+  \property ExtDateTimeEdit::minimumDate
 
-               int num = txt[0].digitValue();
-               if ( num != -1 ) {
-                   cw->addNumber( d->focusSection(), num );
-                   return TRUE;
-               }
-           }
-       }
-    }
-    return FALSE;
-}
+  \brief the minimum date of the date time edit
 
+  When setting this property the \l maximumDate is adjusted if
+  necessary, to ensure that the range remains valid. If the date is
+  not a valid ExtDate object, this function does nothing.
 
-/*!
-    Appends the number section \a sec to the editor.
+  \sa minimumTime, maximumTime, setDateRange()
 */
 
-void ExtDateTimeEditor::appendSection( const QNumberSection& sec )
+ExtDate ExtDateTimeEdit::minimumDate() const
 {
-    d->appendSection( sec );
+    Q_D(const ExtDateTimeEdit);
+    return d->minimum.toDate();
 }
 
-/*!
-    Removes all sections from the editor.
-*/
+void ExtDateTimeEdit::setMinimumDate(const ExtDate &min)
+{
+    Q_D(ExtDateTimeEdit);
+    if (min.isValid()) {
+        const QVariant m(ExtDateTime(min, d->minimum.toTime()));
+        d->setRange(m, qMax(d->maximum, m));
+    }
+}
 
-void ExtDateTimeEditor::clearSections()
+void ExtDateTimeEdit::clearMinimumDate()
 {
-    d->clearSections();
+    setMinimumDate(DATE_MIN);
 }
 
 /*!
-    Sets the selection of \a sec to start at \a selstart and end at \a
-    selend.
+  \property ExtDateTimeEdit::maximumDate
+
+  \brief the maximum date of the date time edit
+
+  When setting this property the \l minimumDate is adjusted if
+  necessary to ensure that the range remains valid. If the date is
+  not a valid ExtDate object, this function does nothing.
+
+  \sa minimumDate, minimumTime, maximumTime, setDateRange()
 */
 
-void ExtDateTimeEditor::setSectionSelection( int sec, int selstart, int selend )
+ExtDate ExtDateTimeEdit::maximumDate() const
 {
-    d->setSectionSelection( sec, selstart, selend );
+    Q_D(const ExtDateTimeEdit);
+    return d->maximum.toDate();
 }
 
-/*!
-    Sets the separator for all numbered sections to \a s. Note that
-    currently, only the first character of \a s is used.
-*/
-
-void ExtDateTimeEditor::setSeparator( const QString& s )
+void ExtDateTimeEdit::setMaximumDate(const ExtDate &max)
 {
-    d->setSeparator( s );
-    update();
+    Q_D(ExtDateTimeEdit);
+    if (max.isValid()) {
+        const QVariant m(ExtDateTime(max, d->maximum.toTime()));
+        d->setRange(qMin(d->minimum, m), m);
+    }
 }
 
+void ExtDateTimeEdit::clearMaximumDate()
+{
+    setMaximumDate(DATE_MAX);
+}
 
 /*!
-    Returns the editor's separator.
+  \property ExtDateTimeEdit::minimumTime
+
+  \brief the minimum time of the date time edit
+
+  When setting this property the \l maximumTime is adjusted if
+  necessary, to ensure that the range remains valid. If the time is
+  not a valid QTime object, this function does nothing.
+
+  \sa maximumTime, minimumDate, maximumDate, setTimeRange()
 */
 
-QString ExtDateTimeEditor::separator() const
+QTime ExtDateTimeEdit::minimumTime() const
 {
-    return d->separator();
+    Q_D(const ExtDateTimeEdit);
+    return d->minimum.toTime();
 }
 
-/*!
-    Returns the number of the section that has focus.
-*/
-
-int ExtDateTimeEditor::focusSection() const
+void ExtDateTimeEdit::setMinimumTime(const QTime &min)
 {
-    return d->focusSection();
+    Q_D(ExtDateTimeEdit);
+    if (min.isValid()) {
+        const QVariant m(ExtDateTime(d->minimum.toDate(), min));
+        d->setRange(m, qMax(d->maximum, m));
+    }
 }
 
+void ExtDateTimeEdit::clearMinimumTime()
+{
+    setMinimumTime(TIME_MIN);
+}
 
 /*!
-    Sets the focus to section \a sec. If \a sec does not exist,
-    nothing happens.
+  \property ExtDateTimeEdit::maximumTime
+
+  \brief the maximum time of the date time edit
+
+  When setting this property, the \l minimumTime is adjusted if
+  necessary to ensure that the range remains valid. If the time is
+  not a valid QTime object, this function does nothing.
+
+  \sa minimumTime, minimumDate, maximumDate, setTimeRange()
 */
+QTime ExtDateTimeEdit::maximumTime() const
+{
+    Q_D(const ExtDateTimeEdit);
+    return d->maximum.toTime();
+}
 
-bool ExtDateTimeEditor::setFocusSection( int sec )
+void ExtDateTimeEdit::setMaximumTime(const QTime &max)
 {
-    return d->setFocusSection( sec );
+    Q_D(ExtDateTimeEdit);
+    if (max.isValid()) {
+        const QVariant m(ExtDateTime(d->maximum.toDate(), max));
+        d->setRange(qMin(d->minimum, m), m);
+    }
 }
 
-/*! \class ExtDateTimeEditBase ExtDatetimeedit.h
-    \brief The ExtDateTimeEditBase class provides an abstraction for date and edit editors.
-    \internal
+void ExtDateTimeEdit::clearMaximumTime()
+{
+    setMaximumTime(TIME_MAX);
+}
 
-    Small abstract class that provides some functions that are common
-    for both ExtDateEdit and QTimeEdit. Its used internally by
-    ExtDateTimeEditor.
-*/
+/*!
+  Convenience function to set minimum and maximum date with one
+  function call.
 
-/*! \fn QString ExtDateTimeEditBase::sectionFormattedText( int sec )
-    \internal
+  \code
+  setDateRange(min, max);
+  \endcode
 
-  Pure virtual function which returns the formatted text of section \a
-  sec.
+  is analogous to:
 
-*/
+  \code
+  setMinimumDate(min);
+  setMaximumDate(max);
+  \endcode
 
-/*! \fn void ExtDateTimeEditBase::stepUp()
-    \internal
+  If either \a min or \a max are not valid, this function does
+  nothing.
 
-  Pure virtual slot which is called whenever the user increases the
-  number in a section by pressing the widget's arrow buttons or the
-  keyboard's arrow keys.
+  \sa setMinimumDate(), maximumDate(), setMaximumDate(),
+  clearMinimumDate(), setMinimumTime(), maximumTime(),
+  setMaximumTime(), clearMinimumTime(), ExtDate::isValid()
 */
 
-/*! \fn void ExtDateTimeEditBase::stepDown()
-    \internal
+void ExtDateTimeEdit::setDateRange(const ExtDate &min, const ExtDate &max)
+{
+    Q_D(ExtDateTimeEdit);
+    if (min.isValid() && max.isValid()) {
+        d->setRange(QVariant(ExtDateTime(min, d->minimum.toTime())),
+                    QVariant(ExtDateTime(max, d->maximum.toTime())));
+    }
+}
 
-  Pure virtual slot which is called whenever the user decreases the
-  number in a section by pressing the widget's arrow buttons or the
-  keyboard's arrow keys.
+/*!
+  Convenience function to set minimum and maximum time with one
+  function call.
 
-*/
+  \code
+  setTimeRange(min, max);
+  \endcode
 
-/*! \fn void ExtDateTimeEditBase::addNumber( int sec, int num )
-    \internal
+  is analogous to:
 
-  Pure virtual function which is called whenever the user types a number.
-  \a sec indicates the section where the number should be added. \a
-  num is the number that was pressed.
-*/
+  \code
+  setMinimumTime(min);
+  setMaximumTime(max);
+  \endcode
 
-/*! \fn void ExtDateTimeEditBase::removeLastNumber( int sec )
-    \internal
+  If either \a min or \a max are not valid, this function does
+  nothing.
 
-  Pure virtual function which is called whenever the user tries to
-  remove the last number from \a sec by pressing the delete key.
+  \sa setMinimumDate(), maximumDate(), setMaximumDate(),
+  clearMinimumDate(), setMinimumTime(), maximumTime(),
+  setMaximumTime(), clearMinimumTime(), QTime::isValid()
 */
 
-////////////////
-
-class ExtDateEditPrivate
+void ExtDateTimeEdit::setTimeRange(const QTime &min, const QTime &max)
 {
-public:
-    int y;
-    int m;
-    int d;
-    // remebers the last entry for the day.
-    // if the day is 31 and you cycle through the months,
-    // the day will be 31 again if you reach a month with 31 days
-    // otherwise it will be the highest day in the month
-    int dayCache;
-    int yearSection;
-    int monthSection;
-    int daySection;
-    ExtDateEdit::Order ord;
-    bool overwrite;
-    bool adv;
-    int timerId;
-    bool typing;
-    ExtDate min;
-    ExtDate max;
-    bool changed;
-    ExtDateTimeEditor *ed;
-    Q3SpinWidget *controls;
-};
-
+    Q_D(ExtDateTimeEdit);
+    if (min.isValid() && max.isValid()) {
+        d->setRange(QVariant(ExtDateTime(d->minimum.toDate(), min)),
+                    QVariant(ExtDateTime(d->maximum.toDate(), max)));
+    }
+}
 
 /*!
-    \class ExtDateEdit ExtDatetimeedit.h
-    \brief The ExtDateEdit class provides a date editor.
-
-    \ingroup advanced
-    \ingroup time
+  \property ExtDateTimeEdit::displayedSections
 
-    ExtDateEdit allows the user to edit dates by using the keyboard or
-    the arrow keys to increase/decrease date values. The arrow keys
-    can be used to move from section to section within the ExtDateEdit
-    box. Dates appear in accordance with the local date/time settings
-    or in year, month, day order if the system doesn't provide this
-    information. It is recommended that the ExtDateEdit be initialised
-    with a date, e.g.
+  \brief the currently displayed fields of the date time edit
 
-    \code
-    ExtDateEdit *dateEdit = new ExtDateEdit( ExtDate::currentDate(), this );
-    dateEdit->setRange( ExtDate::currentDate().addDays( -365 ),
-                       ExtDate::currentDate().addDays(  365 ) );
-    dateEdit->setOrder( ExtDateEdit::MDY );
-    dateEdit->setAutoAdvance( TRUE );
-    \endcode
+  Returns a bit set of the displayed sections for this format.
+  \a setDisplayFormat(), displayFormat()
+*/
 
-    Here we've created a new ExtDateEdit object initialised with today's
-    date and restricted the valid date range to today plus or minus
-    365 days. We've set the order to month, day, year. If the auto
-    advance property is TRUE (as we've set it here) when the user
-    completes a section of the date, e.g. enters two digits for the
-    month, they are automatically taken to the next section.
+ExtDateTimeEdit::Sections ExtDateTimeEdit::displayedSections() const
+{
+    Q_D(const ExtDateTimeEdit);
+    return d->display;
+}
 
-    The maximum and minimum values for a date value in the date editor
-    default to the maximum and minimum values for a ExtDate. You can
-    change this by calling setMinValue(), setMaxValue() or setRange().
+/*!
+  \property ExtDateTimeEdit::currentSection
 
-    Terminology: A ExtDateEdit widget comprises three 'sections', one
-    each for the year, month and day. You can change the separator
-    character using ExtDateTimeEditor::setSeparator(), by default the
-    separator will be taken from the systems settings. If that is
-    not possible, it defaults to "-".
+  \brief the current section of the spinbox
+  \a setCurrentSection()
+*/
 
-    \image html datetimewidgets.png "Date Time Widgets"
+ExtDateTimeEdit::Section ExtDateTimeEdit::currentSection() const
+{
+    Q_D(const ExtDateTimeEdit);
+    switch (d->currentSection) {
+    case ExtDateTimeEditPrivate::NoSection:
+    case ExtDateTimeEditPrivate::FirstSection:
+    case ExtDateTimeEditPrivate::LastSection:
+        return ExtDateTimeEdit::NoSection;
+    default:
+        return (ExtDateTimeEdit::Section)(d->currentSection & (~ExtDateTimeEditPrivate::Internal));
+    }
+}
 
-    \sa ExtDate QTimeEdit ExtDateTimeEdit
-*/
+void ExtDateTimeEdit::setCurrentSection(Section section)
+{
+    Q_D(ExtDateTimeEdit);
+    const ExtDateTimeEditPrivate::Section s = (ExtDateTimeEditPrivate::Section)section;
+    if (s != ExtDateTimeEditPrivate::NoSection)
+        d->edit->setCursorPosition(d->sectionNode(s).pos);
+}
 
 /*!
-    \enum ExtDateEdit::Order
+  \fn QString ExtDateTimeEdit::sectionText(Section section) const
 
-    This enum defines the order in which the sections that comprise a
-    date appear.
+  Returns the text from the given \a section.
 
+  \sa currentSection()
 */
 
+QString ExtDateTimeEdit::sectionText(Section s) const
+{
+    Q_D(const ExtDateTimeEdit);
+    return d->sectionText(d->edit->displayText(), (ExtDateTimeEditPrivate::Section)s);
+}
 
 /*!
-    \enum QTimeEdit::Display
+  \property ExtDateTimeEdit::displayFormat
+
+  \brief the format used to display the time/date of the date time edit
+
+  This format is a subset of the format described in ExtDateTime::toString()
+
+  These expressions may be used:
+
+  \table
+  \header \i Expression \i Output
+  \row \i hh
+  \i the hour with a leading zero (00 to 23 or 01 to 12 if AM/PM display)
+  \row \i mm \i the minute with a leading zero (00 to 59)
+  \row \i ss \i the second whith a leading zero (00 to 59)
+  \row \i zzz \i the milliseconds with leading zeroes (000 to 999)
+  \row \i AP
+  \i use AM/PM display. \e AP will be replaced by either "AM" or "PM".
+  \row \i ap
+  \i use am/pm display. \e ap will be replaced by either "am" or "pm".
+  \row \i dd \i the day as number with a leading zero (01 to 31)
+  \row \i MM \i the month as number with a leading zero (01 to 12)
+  \row \i MMM
+  \i the abbreviated localized month name (e.g. 'Jan' to 'Dec').
+  Uses ExtDate::shortMonthName().
+  \row \i yy \i the year as two digit number (00 to 99)
+  \row \i yyyy \i the year as four digit number (1752 to 8000)
+  \endtable
+
+  All other input characters or sequence of characters that are
+  enclosed in singlequotes will be treated as text and can be used
+  as delimiters.
+
+  Example format strings (assuming that the date is 20 July 1969):
+
+  \table
+  \header \i Format \i Result
+  \row \i dd.MM.yyyy    \i 20.07.1969
+  \row \i MMM d yy \i Jul 20 69
+  \endtable
+
+  If you specify an invalid format the format will not be set.
+
+  Multiple instances of the same field is not allowed.A format with
+  no valid fields is not allowed either.
+
+  \warning Since ExtDateTimeEdit internally always operates on a
+  ExtDateTime, changing the format can change the minimum time or
+  date and the current time or date. For example:
+
+  \code
+  ExtDateTimeEdit edit;     // default format is "yyyy.MM.dd hh:mm:ss"
+  edit.setMinimumDate(ExtDate(2000, 1, 1));
+  edit.setMaximumDate(ExtDate(2003, 1, 1));
+  edit.setDateTime(ExtDateTime(ExtDate(2002, 5, 5), QTime(10, 10, 10)));
+  edit.setDisplayFormat("hh:mm:ss");
+
+  // edit can no longer display dates. This means that the
+  // minimum and maximum date will be set to the current date,
+  // e.g. 2002, 5, 5.
+  \endcode
+
+  \sa ExtDateTime::toString(), displayedSections()
+*/
+
+QString ExtDateTimeEdit::displayFormat() const
+{
+    Q_D(const ExtDateTimeEdit);
+    return d->displayFormat;
+}
+
+void ExtDateTimeEdit::setDisplayFormat(const QString &format)
+{
+    Q_D(ExtDateTimeEdit);
+    if (d->parseFormat(format)) {
+        d->cachedValue.clear();
+        d->cachedText.clear();
+        const bool timeShown = (d->display & ExtDateTimeEditPrivate::TimeSectionMask);
+        const bool dateShown = (d->display & ExtDateTimeEditPrivate::DateSectionMask);
+        Q_ASSERT(dateShown || timeShown);
+        if (timeShown && !dateShown) {
+            setDateRange(d->value.toDate(), d->value.toDate());
+        } else if (dateShown && !timeShown) {
+            setTimeRange(TIME_MIN, TIME_MAX);
+            d->value = QVariant(ExtDateTime(d->value.toDate(), QTime()));
+        }
+        d->update();
+        d->edit->setCursorPosition(0);
+        d->editorCursorPositionChanged(-1, 0);
+    }
+}
 
-    This enum defines the sections that comprise a time
+/*!
+  \reimp
+*/
 
-    \value Hours The hours section
-    \value Minutes The minutes section
-    \value Seconds The seconds section
-    \value AMPM The AM/PM section
+QSize ExtDateTimeEdit::sizeHint() const
+{
+    Q_D(const QAbstractSpinBox);
+    ensurePolished();
+
+    const QFontMetrics fm(fontMetrics());
+    int h = d->edit->sizeHint().height();
+    int w = 0;
+    QString s;
+    s = d->textFromValue(d->minimum) + QLatin1String("   ");
+    w = qMax<int>(w, fm.width(s));
+    s = d->textFromValue(d->maximum) + QLatin1String("   ");
+    w = qMax<int>(w, fm.width(s));
+    if (d->specialValueText.size()) {
+        s = d->specialValueText;
+        w = qMax<int>(w, fm.width(s));
+    }
+    w += 2; // cursor blinking space
 
-    The values can be or'ed together to show any combination.
-*/
+    QStyleOptionSpinBox opt = d->getStyleOption();
+    QSize hint(w, h);
+    QSize extra(35, 6);
+    opt.rect.setSize(hint + extra);
+    extra += hint - style()->subControlRect(QStyle::CC_SpinBox, &opt,
+                                            QStyle::SC_SpinBoxEditField, this).size();
+    // get closer to final result by repeating the calculation
+    opt.rect.setSize(hint + extra);
+    extra += hint - style()->subControlRect(QStyle::CC_SpinBox, &opt,
+                                            QStyle::SC_SpinBoxEditField, this).size();
+    hint += extra;
+
+    opt.rect = rect();
+    return style()->sizeFromContents(QStyle::CT_SpinBox, &opt, hint, this)
+        .expandedTo(QApplication::globalStrut());
+}
 
 /*!
-    Constructs an empty date editor which is a child of \a parent and
-    called name \a name.
+  \reimp
 */
 
-ExtDateEdit::ExtDateEdit( QWidget * parent, const char * name )
-    : ExtDateTimeEditBase( parent, name )
+bool ExtDateTimeEdit::event(QEvent *e)
 {
-    init();
-    updateButtons();
+    Q_D(ExtDateTimeEdit);
+    switch (e->type()) {
+    case QEvent::ApplicationLayoutDirectionChange:
+        setDisplayFormat(d->displayFormat);
+        break;
+    default:
+        break;
+    }
+    return QAbstractSpinBox::event(e);
 }
 
 /*!
-    \overload
-
-    Constructs a date editor with the initial value \a date, parent \a
-    parent and called \a name.
-
-    The date editor is initialized with \a date.
+  \reimp
 */
 
-ExtDateEdit::ExtDateEdit( const ExtDate& date, QWidget * parent, const char * name )
-    : ExtDateTimeEditBase( parent, name )
+void ExtDateTimeEdit::clear()
 {
-    init();
-    setDate( date );
+    Q_D(ExtDateTimeEdit);
+    d->clearSection(d->currentSection);
 }
+/*!
+  \reimp
+*/
+
+void ExtDateTimeEdit::keyPressEvent(QKeyEvent *e)
+{
+    Q_D(ExtDateTimeEdit);
+    const ExtDateTimeEditPrivate::Section oldCurrent = d->currentSection;
+    bool select = true;
+
+    if ((e->key() == Qt::Key_Backspace || (e->key() == Qt::Key_H && e->key() & Qt::ControlModifier))
+        && !d->edit->hasSelectedText()) {
+        const int pos = d->edit->cursorPosition();
+        if (pos <= d->separators.first().size()) {
+            e->accept();
+            return;
+        }
+        select = false;
+        const ExtDateTimeEditPrivate::Section s = d->sectionAt(pos);
+        const ExtDateTimeEditPrivate::Section closest = d->closestSection(pos - 1, false);
+        EDTEDEBUG << "found those two" << d->sectionName(s)<< d->sectionName(closest);
+        if ((s == ExtDateTimeEditPrivate::LastSection && d->separators.last().size() > 0)
+            || (s != ExtDateTimeEditPrivate::NoSection && pos == d->sectionPos(s))) {
+            QString copy = d->edit->displayText();
+            int cursorCopy = pos;
+            if (validate(copy, cursorCopy) != QValidator::Acceptable) {
+                d->interpret(EmitIfChanged);
+            }
+            d->ignoreCursorPositionChanged = true;
+            d->edit->setCursorPosition(d->sectionPos(closest) + d->sectionSize(closest));
+            d->currentSection = closest;
+            d->ignoreCursorPositionChanged = false;
+        }
+    }
 
-/*! \internal
-*/
-void ExtDateEdit::init()
-{
-  d = new ExtDateEditPrivate();
-  d->controls = new ExtDateTimeSpinWidget( this, 
-      qstrcmp( name(), "qt_datetime_dateedit" ) == 0 ? 
-      "qt_spin_widget" : "date edit controls" );
-  d->ed = new ExtDateTimeEditor( this, "date editor" );
-  d->controls->setEditWidget( d->ed );
-  setFocusProxy( d->ed );
-  connect( d->controls, SIGNAL( stepUpPressed() ), SLOT( stepUp() ) );
-  connect( d->controls, SIGNAL( stepDownPressed() ), SLOT( stepDown() ) );
-  connect( this, SIGNAL( valueChanged(const ExtDate&) ),
-      SLOT( updateButtons() ) );
-  d->ed->appendSection( QNumberSection( 0,4 ) );
-  d->ed->appendSection( QNumberSection( 5,7 ) );
-  d->ed->appendSection( QNumberSection( 8,10 ) );
+    bool forward = true;
+    switch ((Qt::Key)e->key()) {
+    case Qt::Key_Enter:
+    case Qt::Key_Return:
+        d->interpret(AlwaysEmit);
+        d->setSelected(d->currentSection);
+        e->ignore();
+        emit editingFinished();
+        return;
+
+    case Qt::Key_Left:
+        forward = false;
+    case Qt::Key_Right:
+        if (!(e->modifiers() & Qt::ControlModifier)) {
+            select = false;
+            break;
+        }
+#ifdef Q_WS_MAC
+        else {
+            select = (e->modifiers() & Qt::ShiftModifier);
+            break;
+        }
+#endif
 
-  d->yearSection = -1;
-  d->monthSection = -1;
-  d->daySection = -1;
+        // fallthroughs intended
+    case Qt::Key_Backtab:
+    case Qt::Key_Tab: {
+        e->accept();
+        if (d->specialValue()) {
+            d->edit->setSelection(d->edit->cursorPosition(), 0);
+            return;
+        }
+        if (e->key() == Qt::Key_Backtab || (e->key() == Qt::Key_Tab && e->modifiers() & Qt::ShiftModifier)) {
+            forward = false;
+        }
+
+        const ExtDateTimeEditPrivate::SectionNode newSection = d->nextPrevSection(d->currentSection, forward);
+        if (select) {
+            d->setSelected(newSection.section);
+        } else {
+            d->edit->setCursorPosition(forward ? newSection.pos : d->sectionPos(d->currentSection));
+        }
+        if (!select)
+            d->edit->deselect();
+        return; }
+    default:
+        select = !e->text().isEmpty() && e->text().at(0).isPrint();
+        break;
+    }
 
-  d->y = 0;
-  d->m = 0;
-  d->d = 0;
-  d->dayCache = 0;
-  setOrder( localOrder() );
-  setFocusSection( 0 );
-  d->overwrite = TRUE;
-  d->adv = FALSE;
-  d->timerId = 0;
-  d->typing = FALSE;
-  d->min = ExtDate( -50000, 1, 1 );
-  d->max = ExtDate( 50000, 12, 31 );
-  d->changed = FALSE;
+    QAbstractSpinBox::keyPressEvent(e);
+    if (select && d->currentSection != oldCurrent && !(e->modifiers() & Qt::ShiftModifier) && !d->edit->hasSelectedText()) {
+        d->setSelected(d->currentSection);
+    }
+    if (d->specialValue()) {
+        d->edit->setSelection(d->edit->cursorPosition(), 0);
+    }
+}
 
-  setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Fixed );
+/*!
+  \reimp
+*/
 
-  refcount++;
+#ifndef QT_NO_WHEELEVENT
+void ExtDateTimeEdit::wheelEvent(QWheelEvent *e)
+{
+    Q_D(ExtDateTimeEdit);
+    int fw = d->frame ? style()->pixelMetric(QStyle::PM_SpinBoxFrameWidth) : 0;
+    QPoint pnt(e->pos() - QPoint(fw, fw));
+    pnt.rx() -= d->edit->x();
+    int index = d->edit->cursorPositionAt(pnt);
+    const ExtDateTimeEditPrivate::Section s = d->closestSection(index, d->edit->cursorPosition() > index); // should it be > pos?
+    if (s != d->currentSection)
+        d->edit->setCursorPosition(d->sectionNode(s).pos);
+    switch (s) {
+    case ExtDateTimeEditPrivate::NoSection:
+    case ExtDateTimeEditPrivate::FirstSection:
+    case ExtDateTimeEditPrivate::LastSection:
+        break;
+    default:
+        QAbstractSpinBox::wheelEvent(e);
+        break;
+    }
 }
+#endif
 
 /*!
-    Destroys the object and frees any allocated resources.
+  \reimp
 */
 
-ExtDateEdit::~ExtDateEdit()
+void ExtDateTimeEdit::focusInEvent(QFocusEvent *e)
 {
-  delete d;
-  if ( !--refcount )
-    cleanup();
+    Q_D(ExtDateTimeEdit);
+    QAbstractSpinBox::focusInEvent(e);
+    QString *frm = 0;
+    if (d->displayFormat == d->defaultTimeFormat) {
+        frm = &d->defaultTimeFormat;
+    } else if (d->displayFormat == d->defaultDateFormat) {
+        frm = &d->defaultDateFormat;
+    } else if (d->displayFormat == d->defaultDateTimeFormat) {
+        frm = &d->defaultDateTimeFormat;
+    }
+
+    if (frm) {
+        d->readLocaleSettings();
+        setDisplayFormat(*frm);
+    }
+    bool first;
+    switch (e->reason()) {
+    case Qt::ShortcutFocusReason:
+    case Qt::TabFocusReason: first = true; break;
+    case Qt::BacktabFocusReason: first = false; break;
+    default: return;
+    }
+    if (QApplication::isRightToLeft())
+        first = !first;
+    d->setSelected(first ? d->sectionNodes.first().section : d->sectionNodes.at(d->sectionNodes.size() - 1).section);
 }
 
 /*!
-    \property ExtDateEdit::minValue
+  \reimp
+*/
 
-    \brief the editor's minimum value
+bool ExtDateTimeEdit::focusNextPrevChild(bool next)
+{
+    Q_D(ExtDateTimeEdit);
+    if (!focusWidget())
+        return false;
 
-    Setting the minimum date value is equivalent to calling
-    ExtDateEdit::setRange( \e d, maxValue() ), where \e d is the minimum
-    date. The default minimum date is 1752-09-14.
+    const ExtDateTimeEditPrivate::Section newSection =
+        d->nextPrevSection(d->currentSection, next).section;
+    switch (newSection) {
+    case ExtDateTimeEditPrivate::NoSection:
+    case ExtDateTimeEditPrivate::FirstSection:
+    case ExtDateTimeEditPrivate::LastSection:
+        break;
+    default:
+        d->setSelected(newSection);
+        return true;
+    }
+    return QAbstractSpinBox::focusNextPrevChild(next);
+}
 
-    \sa maxValue setRange()
+/*!
+  \reimp
 */
 
-ExtDate ExtDateEdit::minValue() const
+void ExtDateTimeEdit::stepBy(int steps)
 {
-  return d->min;
+    Q_D(ExtDateTimeEdit);
+    const ExtDateTimeEditPrivate::Section s = d->currentSection;
+    d->setValue(d->stepBy(s, steps, false), EmitIfChanged);
+    d->setSelected(s);
 }
 
 /*!
-    \property ExtDateEdit::maxValue
+  This virtual function is used by the date time edit whenever it
+  needs to display \a dateTime.
 
-    \brief the editor's maximum value
+  If you reimplement this, you may also need to reimplement
+  valueFromText() and validate().
 
-    Setting the maximum date value for the editor is equivalent to
-    calling ExtDateEdit::setRange( minValue(), \e d ), where \e d is the
-    maximum date. The default maximum date is 8000-12-31.
-
-    \sa minValue setRange()
+  \sa dateTimeFromText(), validate()
 */
-
-ExtDate ExtDateEdit::maxValue() const
+QString ExtDateTimeEdit::textFromDateTime(const ExtDateTime &dateTime) const
 {
-  return d->max;
+    const char zero = '0';
+
+    Q_D(const ExtDateTimeEdit);
+    QVariant var(dateTime);
+    if (var == d->cachedValue) {
+        EDTEDEBUG << "cached and var is the same so returning cachedText" << dateTime << d->cachedText;
+        return d->cachedText;
+    }
+    QString ret = d->escapedFormat;
+    for (int i=0; i<d->sectionNodes.size(); ++i) {
+        int l = d->sectionSize(d->sectionNodes.at(i).section);
+        int pos = d->sectionNodes.at(i).pos;
+        const ExtDateTimeEditPrivate::Section s = d->sectionNodes.at(i).section;
+        switch (s) {
+        case ExtDateTimeEditPrivate::AmPmSection:
+        case ExtDateTimeEditPrivate::AmPmLowerCaseSection: {
+            QString input;
+            if (s == ExtDateTimeEditPrivate::AmPmSection) {
+                input = var.toTime().hour() > 11
+                        ? ExtDateTimeEdit::tr("PM")
+                        : ExtDateTimeEdit::tr("AM");
+            } else {
+                input = var.toTime().hour() > 11 ?
+                        ExtDateTimeEdit::tr("pm") :
+                        ExtDateTimeEdit::tr("am");
+            }
+            input.truncate(l);
+
+            ret.replace(pos, l, input);
+            break; }
+        case ExtDateTimeEditPrivate::MonthShortNameSection:
+            ret.replace(pos, l, ExtDate::shortMonthName(var.toDate().month()));
+            break;
+        case ExtDateTimeEditPrivate::YearTwoDigitsSection:
+            ret.replace(pos, l,
+                        QString::number(d->getDigit(var, ExtDateTimeEditPrivate::YearTwoDigitsSection) - 2000)
+                        .rightJustified(l, zero, true));
+            break;
+        case ExtDateTimeEditPrivate::HourSection:
+            if (d->display & ExtDateTimeEditPrivate::AmPmSection) {
+                int h = var.toTime().hour();
+                h = h % 12;
+                if (h == 0)
+                    h = 12;
+                ret.replace(pos, l,
+                            QString::number(h).rightJustified(l, zero, true));
+                break;
+            }
+        default:
+            ret.replace(pos, l,
+                        QString::number(d->getDigit(var, d->sectionNodes.at(i).section)).
+                        rightJustified(l, zero));
+            break;
+        }
+    }
+
+    d->cachedValue = var;
+    d->cachedText = ret;
+//    qDebug() << "setting cached to" << d->cachedValue << " and cachedText to" << d->cachedText;
+    return ret;
 }
 
 
 /*!
-    Sets the valid input range for the editor to be from \a min to \a
-    max inclusive. If \a min is invalid no minimum date will be set.
-    Similarly, if \a max is invalid no maximum date will be set.
-*/
+  Returns an appropriate datetime for the given \a text.
+
+  This virtual function is used by the datetime edit whenever it
+  needs to interpret text entered by the user as a value.
 
-void ExtDateEdit::setRange( const ExtDate& min, const ExtDate& max )
+  \sa textFromDateTime(), validate()
+*/
+ExtDateTime ExtDateTimeEdit::dateTimeFromText(const QString &text) const
 {
-  if ( min.isValid() )
-    d->min = min;
-  if ( max.isValid() )
-    d->max = max;
+    Q_D(const ExtDateTimeEdit);
+    QString copy = text;
+    int pos = d->edit->cursorPosition();
+    QValidator::State state = QValidator::Acceptable;
+    return d->validateAndInterpret(copy, pos, state).toDateTime();
 }
 
 /*!
-    Sets the separator to \a s. Note that currently only the first
-    character of \a s is used.
+  \reimp
 */
 
-void ExtDateEdit::setSeparator( const QString& s )
+QValidator::State ExtDateTimeEdit::validate(QString &text, int &pos) const
 {
-  d->ed->setSeparator( s );
-}
+    Q_D(const ExtDateTimeEdit);
+    QValidator::State state;
+    d->validateAndInterpret(text, pos, state);
+    return state;
+}\
 
 /*!
-    Returns the editor's separator.
+  \reimp
 */
 
-QString ExtDateEdit::separator() const
+ExtDateTimeEdit::StepEnabled ExtDateTimeEdit::stepEnabled() const
 {
-  return d->ed->separator();
+    Q_D(const ExtDateTimeEdit);
+    if (d->readOnly)
+        return StepEnabled(0);
+    if (d->specialValue()) {
+        if (d->minimum == d->maximum)
+            return StepEnabled(0);
+        return d->wrapping
+            ? StepEnabled(StepDownEnabled|StepUpEnabled)
+            : StepEnabled(StepUpEnabled);
+    }
+    switch (d->currentSection) {
+    case ExtDateTimeEditPrivate::NoSection:
+    case ExtDateTimeEditPrivate::FirstSection:
+    case ExtDateTimeEditPrivate::LastSection: return 0;
+    default: break;
+    }
+    if (!style()->styleHint(QStyle::SH_SpinControls_DisableOnBounds)
+        || d->wrapping)
+        return StepEnabled(StepUpEnabled | StepDownEnabled);
+
+    QAbstractSpinBox::StepEnabled ret = 0;
+
+    QVariant v = d->stepBy(d->currentSection, 1, true);
+    if (v != d->value) {
+        ret |= QAbstractSpinBox::StepUpEnabled;
+    }
+    v = d->stepBy(d->currentSection, -1, true);
+    if (v != d->value) {
+        ret |= QAbstractSpinBox::StepDownEnabled;
+    }
+
+    return ret;
 }
 
 
 /*!
-    Enables/disables the push buttons according to the min/max date
-    for this widget.
-*/
+    \class QTimeEdit
+    \brief The QTimeEdit class provides a widget for editing times based on
+    the ExtDateTimeEdit widget.
 
-void ExtDateEdit::updateButtons()
-{
-  if ( !isEnabled() )
-    return;
+    \ingroup basic
+    \mainclass
 
-  fix();
-  
-  bool upEnabled = date() < maxValue();
-  bool downEnabled = date() > minValue();
+    \sa ExtDateEdit ExtDateTimeEdit
+*/
 
-  d->controls->setUpEnabled( upEnabled );
-  d->controls->setDownEnabled( downEnabled );
-}
+/*!
+  Constructs an empty time editor with a \a parent.
+*/
 
-/*! \reimp
- */
-void ExtDateEdit::resizeEvent( QResizeEvent * )
+
+QTimeEdit::QTimeEdit(QWidget *parent)
+    : ExtDateTimeEdit(TIME_MIN, parent)
 {
-  d->controls->resize( width(), height() );
 }
 
-/*! \reimp
-
+/*!
+  Constructs an empty time editor with a \a parent. The time is set
+  to \a time.
 */
-QSize ExtDateEdit::sizeHint() const
-{
-  constPolish();
-  QFontMetrics fm( font() );
-  int fw = style().pixelMetric( QStyle::PM_DefaultFrameWidth, this );
-  int h = QMAX( fm.lineSpacing(), 14 ) + 2;
-  int w = 2 + fm.width( '9' ) * 8 + fm.width( d->ed->separator() ) * 2 
-            + d->controls->upRect().width() + fw * 4;
 
-  return QSize( w, QMAX(h + fw * 2,20) ).expandedTo( QApplication::globalStrut() );
+QTimeEdit::QTimeEdit(const QTime &time, QWidget *parent)
+    : ExtDateTimeEdit(time, parent)
+{
 }
 
-/*! \reimp
+/*!
+    \class ExtDateEdit
+    \brief The ExtDateEdit class provides a widget for editing dates based on
+    the ExtDateTimeEdit widget.
+
+    \ingroup basic
+    \mainclass
+
+    \sa QTimeEdit ExtDateTimeEdit
+*/
 
+/*!
+  Constructs an empty date editor with a \a parent.
 */
-QSize ExtDateEdit::minimumSizeHint() const
+
+ExtDateEdit::ExtDateEdit(QWidget *parent)
+    : ExtDateTimeEdit(DATE_INITIAL, parent)
 {
-  return sizeHint();
 }
 
-
 /*!
-    Returns the formatted number for section \a sec. This will
-    correspond to either the year, month or day section, depending on
-    the current display order.
-
-    \sa setOrder()
+  Constructs an empty date editor with a \a parent. The date is set
+  to \a date.
 */
 
-QString ExtDateEdit::sectionFormattedText( int sec )
+ExtDateEdit::ExtDateEdit(const ExtDate &date, QWidget *parent)
+    : ExtDateTimeEdit(date, parent)
 {
-  QString txt;
-  txt = sectionText( sec );
-  if ( d->typing && sec == d->ed->focusSection() )
-    d->ed->setSectionSelection( sec, sectionOffsetEnd( sec ) - txt.length(),
-        sectionOffsetEnd( sec ) );
-  else
-    d->ed->setSectionSelection( sec, sectionOffsetEnd( sec ) - sectionLength( sec ),
-        sectionOffsetEnd( sec ) );
-  
-  txt = txt.rightJustify( sectionLength( sec ), EXTDATETIMEEDIT_HIDDEN_CHAR );
-  return txt;
 }
 
 
-/*!
-    Returns the desired length (number of digits) of section \a sec.
-    This will correspond to either the year, month or day section,
-    depending on the current display order.
+// --- ExtDateTimeEditPrivate ---
 
-    \sa setOrder()
+/*!
+  \internal
+  Constructs a ExtDateTimeEditPrivate object
 */
 
-int ExtDateEdit::sectionLength( int sec ) const
+
+ExtDateTimeEditPrivate::ExtDateTimeEditPrivate()
 {
-  int val = 0;
-  if ( sec == d->yearSection ) 
-    val = 4;
-  else if ( sec == d->monthSection ) 
-    val = 2;
-  else if ( sec == d->daySection ) 
-    val = 2;
-  
-  return val;
+    type = QVariant::DateTime;
+    display = (ExtDateTimeEdit::Sections)0;
+    cachedDay = -1;
+    currentSection = NoSection;
+    layoutDirection = QApplication::layoutDirection();
+    first.section = FirstSection;
+    last.section = LastSection;
+    first.pos = 0;
+    last.pos = -1;
+    readLocaleSettings();
 }
 
 /*!
-    Returns the text of section \a sec. This will correspond to either
-    the year, month or day section, depending on the current display
-    order.
-
-    \sa setOrder()
+  \internal
+  \reimp
 */
 
-QString ExtDateEdit::sectionText( int sec ) const
+void ExtDateTimeEditPrivate::emitSignals(EmitPolicy ep, const QVariant &old)
 {
-  int val = 0;
-  if ( sec == d->yearSection ) 
-    val = d->y;
-  else if ( sec == d->monthSection ) 
-    val = d->m;
-  else if ( sec == d->daySection ) 
-    val = d->d;
-    
-  return QString::number( val );
+    Q_Q(ExtDateTimeEdit);
+    if (ep == NeverEmit) {
+        return;
+    }
+    pendingEmit = false;
+
+    const bool dodate = value.toDate().isValid() && (display & DateSectionMask);
+    const bool datechanged = (ep == AlwaysEmit || old.toDate() != value.toDate());
+    const bool dotime = value.toTime().isValid() && (display & TimeSectionMask);
+    const bool timechanged = (ep == AlwaysEmit || old.toTime() != value.toTime());
+
+    if (dodate && dotime && (datechanged || timechanged))
+        emit q->dateTimeChanged(value.toDateTime());
+    if (dodate && datechanged)
+        emit q->dateChanged(value.toDate());
+    if (dotime && timechanged)
+        emit q->timeChanged(value.toTime());
 }
 
-/*! \internal
+/*!
+  \internal
+  \reimp
+*/
+
+void ExtDateTimeEditPrivate::editorCursorPositionChanged(int oldpos, int newpos)
+{
+    Q_Q(ExtDateTimeEdit);
+    if (ignoreCursorPositionChanged || specialValue())
+        return;
+    const bool allowChange = !edit->hasSelectedText();
+    ignoreCursorPositionChanged = true;
+    Section s = sectionAt(newpos);
+    int c = newpos;
+
+    const int selstart = edit->selectionStart();
+    const Section selSection = sectionAt(selstart);
+    const int l = sectionSize(selSection);
+
+    if (s == NoSection) {
+        if (l > 0 && selstart == sectionPos(selSection) && edit->selectedText().size() == l) {
+            s = selSection;
+            if (allowChange)
+                setSelected(selSection, true);
+            c = -1;
+        } else {
+            const SectionNode &sn = sectionNode(closestSection(newpos, oldpos < newpos));
+            c = sn.pos + (oldpos < newpos ? 0 : qMax<int>(0, sectionSize(sn.section) - 1));
+            if (allowChange)
+                edit->setCursorPosition(c);
+            s = sn.section;
+        }
+    }
+
+    if (allowChange && currentSection != s) {
+        QString tmp = edit->displayText();
+        int pos = edit->cursorPosition();
+        if (q->validate(tmp, pos) != QValidator::Acceptable) {
+            interpret(EmitIfChanged);
+            if (c == -1) {
+                setSelected(s, true);
+            } else {
+                edit->setCursorPosition(pos);
+            }
+        }
+        updateSpinBox();
+    }
+    currentSection = s;
+    ignoreCursorPositionChanged = false;
+
+}
+
+#ifdef Q_WS_MAC
+static QString macParseDateLocale(QVariant::Type type)
+{
+    CFGregorianDate macGDate;
+    macGDate.year = 2999;
+    macGDate.month = 11;
+    macGDate.day = 22;
+    macGDate.hour = 10;
+    macGDate.minute = 34;
+    macGDate.second = 56.0;
+    QCFType<CFDateRef> myDate = CFDateCreate(0, CFGregorianDateGetAbsoluteTime(macGDate, QCFType<CFTimeZoneRef>
+                                                                               (CFTimeZoneCopySystem())));
+    switch (type) {
+    case QVariant::Date: {
+#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_3)
+        if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_3) {
+            QCFType<CFLocaleRef> mylocale = CFLocaleCopyCurrent();
+            QCFType<CFDateFormatterRef> myFormatter = CFDateFormatterCreate(kCFAllocatorDefault,
+                                                                            mylocale, kCFDateFormatterShortStyle,
+                                                                            kCFDateFormatterNoStyle);
+            return QCFString(CFDateFormatterCreateStringWithDate(0, myFormatter, myDate));
+
+        } else
+#endif
+        {
+            Handle intlHandle = GetIntlResource(0);
+            LongDateTime oldDate;
+            UCConvertCFAbsoluteTimeToLongDateTime(CFGregorianDateGetAbsoluteTime(macGDate, 0),
+                                                  &oldDate);
+            Str255 pString;
+            LongDateString(&oldDate, shortDate, pString, intlHandle);
+            return qt_mac_from_pascal_string(pString);
+        }
+    }
+    case QVariant::DateTime: {
+#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_3)
+        if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_3) {
+            QCFType<CFLocaleRef> mylocale = CFLocaleCopyCurrent();
+            QCFType<CFDateFormatterRef> myFormatter = CFDateFormatterCreate(kCFAllocatorDefault,
+                                                                            mylocale, kCFDateFormatterShortStyle,
+                                                                            kCFDateFormatterMediumStyle);
+            return QCFString(CFDateFormatterCreateStringWithDate(0, myFormatter, myDate));
+
+        } else
+#endif
+        {
+            Handle intlHandle = GetIntlResource(0);
+            LongDateTime oldDate;
+            UCConvertCFAbsoluteTimeToLongDateTime(CFGregorianDateGetAbsoluteTime(macGDate, 0),
+                                                  &oldDate);
+            Str255 pString;
+            LongDateString(&oldDate, shortDate, pString, intlHandle);
+            QString final = qt_mac_from_pascal_string(pString);
+            LongTimeString(&oldDate, true, pString, intlHandle);
+            return final + QLatin1Char(' ') + qt_mac_from_pascal_string(pString);
+        }
+    }
+    default: return QString();
+    }
+}
+#endif
 
-  Returns the end of the section offset \a sec.
+/*!
+  \internal
 
+  Try to get the format from the local settings
 */
-
-int ExtDateEdit::sectionOffsetEnd( int sec ) const
+void ExtDateTimeEditPrivate::readLocaleSettings()
 {
-  if ( sec == d->yearSection ) {
-    switch( d->ord ) {
-      case DMY:
-      case MDY:
-        return sectionOffsetEnd( sec-1) + separator().length() + sectionLength( sec );
-      case YMD:
-      case YDM:
-        return sectionLength( sec );
+    EDTEDEBUG << ExtDateTimeEdit::tr("PM")
+              << ExtDateTimeEdit::tr("AM")
+              << ExtDateTimeEdit::tr("pm")
+              << ExtDateTimeEdit::tr("am");
+
+    // Time
+    QString str = QTime(10, 34, 56).toString(Qt::LocalDate);
+    int index = str.indexOf(QLatin1String("10"));
+    if (index != -1)
+        str.replace(index, 2, QLatin1String("hh"));
+
+    index = str.indexOf(QLatin1String("34"));
+    if (index != -1)
+        str.replace(index, 2, QLatin1String("mm"));
+
+    index = str.indexOf(QLatin1String("56"));
+    if (index != -1)
+        str.replace(index, 2, QLatin1String("ss"));
+
+    QString am = QLatin1String("am");
+    index = str.indexOf(am);
+    if (index != -1) {
+        str.replace(index, am.size(), QLatin1String("ap"));
+    } else {
+        am = QLatin1String("AM");
+
+        index = str.indexOf(am);
+        if (index != -1)
+            str.replace(index, am.size(), QLatin1String("AP"));
     }
-  } else if ( sec == d->monthSection ) {
-    switch( d->ord ) {
-      case DMY:
-      case YDM:
-      case YMD:
-        return sectionOffsetEnd( sec-1) + separator().length() + sectionLength( sec );
-      case MDY:
-        return sectionLength( sec );
+
+    defaultTimeFormat = str;
+
+    // Date
+
+    const ExtDate date(2999, 11, 22);
+    const QString shortMonthName = ExtDate::shortMonthName(date.month());
+    const QString longMonthName = ExtDate::longMonthName(date.month());
+    const QString shortDayName = ExtDate::shortDayName(date.dayOfWeek());
+    const QString longDayName = ExtDate::longDayName(date.dayOfWeek());
+
+#ifdef Q_WS_MAC
+    str = macParseDateLocale(QVariant::Date);
+#else 
+    str = date.toString(Qt::LocalDate);
+#endif
+    
+    index = str.indexOf(QLatin1String("22"));
+    if (index != -1)
+        str.replace(index, 2, QLatin1String("dd"));
+
+    index = str.indexOf(shortDayName);
+    if (index != -1)
+        str.remove(index, shortDayName.size());
+
+    index = str.indexOf(longDayName);
+    if (index != -1)
+        str.remove(index, longDayName.size());
+
+    index = str.indexOf(QLatin1String("11"));
+    if (index != -1) {
+        str.replace(index, 2, QLatin1String("MM"));
+    } else if ((index = str.indexOf(longMonthName)) != -1) {
+        str.replace(index, longMonthName.size(), QLatin1String("MMM"));
+    } else if ((index = str.indexOf(shortMonthName)) != -1) {
+        str.replace(index, shortMonthName.size(), QLatin1String("MMM"));
     }
-  } else if ( sec == d->daySection ) {
-    switch( d->ord ) {
-      case DMY:
-        return sectionLength( sec );
-      case YMD:
-      case MDY:
-      case YDM:
-        return sectionOffsetEnd( sec-1 ) + separator().length() + sectionLength( sec );
+
+    index = str.indexOf(QLatin1String("2999"));
+    if (index != -1) {
+        str.replace(index, 4, QLatin1String("yyyy"));
+    } else {
+        index = str.indexOf(QLatin1String("99"));
+        if (index != -1)
+            str.replace(index, 2, QLatin1String("yy"));
     }
-  }
-  return 0;
-}
 
+    defaultDateFormat = str;
 
-/*!
-    \property ExtDateEdit::order
-    \brief the order in which the year, month and day appear
+    // DateTime
+#ifdef Q_WS_MAC
+    str = macParseDateLocale(QVariant::DateTime);
+#else
+    str = ExtDateTime(ExtDate(2999, 11, 22), QTime(10, 34, 56)).toString(Qt::LocalDate);
+#endif
+    index = str.indexOf(QLatin1String("10"));
+    if (index != -1)
+        str.replace(index, 2, QLatin1String("hh"));
 
-    The default order is locale dependent.
+    index = str.indexOf(QLatin1String("34"));
+    if (index != -1)
+        str.replace(index, 2, QLatin1String("mm"));
 
-    \sa Order
-*/
+    index = str.indexOf(QLatin1String("56"));
+    if (index != -1)
+        str.replace(index, 2, QLatin1String("ss"));
 
-void ExtDateEdit::setOrder( ExtDateEdit::Order order )
-{
-  d->ord = order;
-  switch( d->ord ) {
-    case DMY:
-      d->yearSection = 2;
-      d->monthSection = 1;
-      d->daySection = 0;
-      break;
-    case MDY:
-      d->yearSection = 2;
-      d->monthSection = 0;
-      d->daySection = 1;
-      break;
-    case YMD:
-      d->yearSection = 0;
-      d->monthSection = 1;
-      d->daySection = 2;
-      break;
-    case YDM:
-      d->yearSection = 0;
-      d->monthSection = 2;
-      d->daySection = 1;
-      break;
-  }
-  
-  if ( isVisible() )
-    d->ed->repaint( d->ed->rect(), FALSE );
-}
+    am = QLatin1String("am");
 
+    index = str.indexOf(am);
+    if (index != -1) {
+        str.replace(index, am.size(), QLatin1String("ap"));
+    } else {
+        am = QLatin1String("AM");
 
-ExtDateEdit::Order ExtDateEdit::order() const
-{
-  return d->ord;
+        index = str.indexOf(am);
+        if (index != -1)
+            str.replace(index, am.size(), QLatin1String("AP"));
+    }
+
+    index = str.indexOf(QLatin1String("22"));
+    if (index != -1)
+        str.replace(index, 2, QLatin1String("dd"));
+
+    index = str.indexOf(shortDayName);
+    if (index != -1)
+        str.remove(index, shortDayName.size());
+
+    index = str.indexOf(longDayName);
+    if (index != -1)
+        str.remove(index, longDayName.size());
+
+    index = str.indexOf(QLatin1String("11"));
+    if (index != -1) {
+        str.replace(index, 2, QLatin1String("MM"));
+    } else if ((index = str.indexOf(longMonthName)) != -1) {
+        str.replace(index, longMonthName.size(), QLatin1String("MMM"));
+    } else if ((index = str.indexOf(shortMonthName)) != -1) {
+        str.replace(index, shortMonthName.size(), QLatin1String("MMM"));
+    }
+
+    index = str.indexOf(QLatin1String("2999"));
+    if (index != -1) {
+        str.replace(index, 4, QLatin1String("yyyy"));
+    } else {
+        index = str.indexOf(QLatin1String("99"));
+        if (index != -1)
+            str.replace(index, 2, QLatin1String("yy"));
+    }
+
+    defaultDateTimeFormat = str;
+
+    EDTEDEBUG << "default Time:" << defaultTimeFormat << "default date:" << defaultDateFormat << "default date/time" << defaultDateTimeFormat;
 }
 
+/*!
+  \internal
+  Gets the digit from a corevariant. E.g.
+
+  QVariant var(ExtDate(2004, 02, 02));
+  int digit = getDigit(var, Year);
+  // digit = 2004
+  */
+
+int ExtDateTimeEditPrivate::getDigit(const QVariant &t, Section s) const
+{
+    switch (s) {
+    case HourSection: return t.toTime().hour();
+    case MinuteSection: return t.toTime().minute();
+    case SecondSection: return t.toTime().second();
+    case MSecSection: return t.toTime().msec();
+    case YearTwoDigitsSection:
+    case YearSection: return t.toDate().year();
+    case MonthShortNameSection:
+    case MonthSection: return t.toDate().month();
+    case DaySection: return t.toDate().day();
+    case AmPmSection:
+    case AmPmLowerCaseSection:
+        return t.toTime().hour() > 11 ? 1 : 0;
+
+    default: break;
+    }
+    qFatal("%s passed to getDigit. This should never happen", sectionName(s).toLatin1().constData());
+    return -1;
+}
 
-/*! \reimp
+/*!
+  \internal
+  Sets a digit in a variant. E.g.
+
+  QVariant var(ExtDate(2004, 02, 02));
+  int digit = getDigit(var, Year);
+  // digit = 2004
+  setDigit(&var, Year, 2005);
+  digit = getDigit(var, Year);
+  // digit = 2005
+
+  returns true if the newVal was changed to make it work. E.g. If you set 31st when you're in february
+*/
+
+void ExtDateTimeEditPrivate::setDigit(QVariant &v, Section section, int newVal) const
+{
+    int year, month, day, hour, minute, second, msec;
+    const ExtDateTime &dt = v.toDateTime();
+    year = dt.date().year();
+    month = dt.date().month();
+    day = dt.date().day();
+    hour = dt.time().hour();
+    minute = dt.time().minute();
+    second = dt.time().second();
+    msec = dt.time().msec();
+
+    switch (section) {
+    case HourSection: hour = newVal; break;
+    case MinuteSection: minute = newVal; break;
+    case SecondSection: second = newVal; break;
+    case MSecSection: msec = newVal; break;
+    case YearTwoDigitsSection:
+    case YearSection: year = newVal; break;
+    case MonthSection:
+    case MonthShortNameSection: month = newVal; break;
+    case DaySection: day = newVal; break;
+    case AmPmSection:
+    case AmPmLowerCaseSection: hour = (newVal == 0 ? hour % 12 : (hour % 12) + 12); break;
+    default:
+        qFatal("%s passed to setDigit. This should never happen", sectionName(section).toLatin1().constData());
+        break;
+    }
 
-*/
-void ExtDateEdit::stepUp()
-{
-  int sec = d->ed->focusSection();
-  bool accepted = FALSE;
-  if ( sec == d->yearSection ) {
-    if ( !outOfRange( d->y+1, d->m, d->d ) ) {
-      accepted = TRUE;
-      setYear( d->y+1 );
+    if (section != DaySection) {
+        day = qMax<int>(cachedDay, day);
     }
-  } else if ( sec == d->monthSection ) {
-       if ( !outOfRange( d->y, d->m+1, d->d ) ) {
-      accepted = TRUE;
-      setMonth( d->m+1 );
-       }
-  } else if ( sec == d->daySection ) {
-    if ( !outOfRange( d->y, d->m, d->d+1 ) ) {
-      accepted = TRUE;
-      setDay( d->d+1 );
+
+    if (!ExtDate::isValid(year, month, day)) {
+        if (year <= DATE_MIN.year() && (month < DATE_MIN.month() || (month == DATE_MIN.month() && day < DATE_MIN.day()))) {
+            month = DATE_MIN.month();
+            day = DATE_MIN.day();
+        } else {
+            day = qMin<int>(day, ExtDate(year, month, 1).daysInMonth());
+        }
     }
-  }
-  if ( accepted ) {
-    d->changed = TRUE;
-    emit valueChanged( date() );
-  }
-  
-  d->ed->repaint( d->ed->rect(), FALSE );
+    v = QVariant(ExtDateTime(ExtDate(year, month, day), QTime(hour, minute, second, msec)));
 }
 
 
+/*!
+  \internal
 
-/*! \reimp
+  Internal function called by ExtDateTimeEdit::stepBy(). Also takes a
+  Section for which section to step on and a bool \a test for
+  whether or not to modify the internal cachedDay variable. This is
+  necessary because the function is called from the const function
+  ExtDateTimeEdit::stepEnabled() as well as ExtDateTimeEdit::stepBy().
+*/
+
+QVariant ExtDateTimeEditPrivate::stepBy(Section s, int steps, bool test) const
+{
+    Q_Q(const ExtDateTimeEdit);
+    QVariant v = value;
+    QString str = edit->displayText();
+    int pos = edit->cursorPosition();
+    bool specVal = specialValue();
+
+    int val;
+    // to make sure it behaves reasonably when typing something and then stepping in non-tracking mode
+    if (!test && pendingEmit) {
+        if (q->validate(str, pos) != QValidator::Acceptable) {
+            v = value;
+        } else {
+            v = valueFromText(str);
+        }
+        val = getDigit(v, s);
+    } else {
+        QValidator::State state;
+        if (!specVal) {
+        val = sectionValue(s, str, state);
+        if (state == QValidator::Invalid) {
+            return value;
+        }
+        } else {
+            val = getDigit(v, s);
+        }
+    }
 
-*/
+    val += steps;
 
-void ExtDateEdit::stepDown()
-{
-  int sec = d->ed->focusSection();
-  bool accepted = FALSE;
-  if ( sec == d->yearSection ) {
-    if ( !outOfRange( d->y-1, d->m, d->d ) ) {
-      accepted = TRUE;
-      setYear( d->y-1 );
+    const int min = absoluteMin(s);
+    const int max = absoluteMax(s);
+
+    if (val < min) {
+        val = (wrapping ? max - (min - val) + 1 : min);
+    } else if (val > max) {
+        val = (wrapping ? min + val - max - 1 : max);
     }
-  } else if ( sec == d->monthSection ) {
-    if ( !outOfRange( d->y, d->m-1, d->d ) ) {
-      accepted = TRUE;
-      setMonth( d->m-1 );
+
+    const int tmp = v.toDate().day();
+    setDigit(v, s, val); // if this sets year or month it will make
+    // sure that days are lowered if needed.
+
+    // changing one section should only modify that section, if possible
+    if (s != AmPmSection && (v < minimum || v > maximum)) {
+
+        const int localmin = getDigit(minimum, s);
+        const int localmax = getDigit(maximum, s);
+
+        if (wrapping) {
+            // just because we hit the roof in one direction, it
+            // doesn't mean that we hit the floor in the other
+            if (steps > 0) {
+                setDigit(v, s, min);
+                if (s != DaySection) {
+                    int daysInMonth = v.toDate().daysInMonth();
+                    if (v.toDate().day() < tmp && v.toDate().day() < daysInMonth)
+                        setDigit(v, DaySection, qMin(tmp, daysInMonth));
+                }
+
+                if (v < minimum) {
+                    setDigit(v, s, localmin);
+                    if (v < minimum)
+                        setDigit(v, s, localmin + 1);
+                }
+            } else {
+                setDigit(v, s, max);
+                if (s != DaySection) {
+                    int daysInMonth = v.toDate().daysInMonth();
+                    if (v.toDate().day() < tmp && v.toDate().day() < daysInMonth)
+                        setDigit(v, DaySection, qMin(tmp, daysInMonth));
+                }
+
+                if (v > maximum) {
+                    setDigit(v, s, localmax);
+                    if (v > maximum)
+                        setDigit(v, s, localmax - 1);
+                }
+            }
+        } else {
+            setDigit(v, s, (steps > 0 ? localmax : localmin));
+        }
+    }
+    if (!test && tmp != v.toDate().day() && s != DaySection) {
+        // this should not happen when called from stepEnabled
+        cachedDay = qMax<int>(tmp, cachedDay);
     }
-  } else if ( sec == d->daySection ) {
-    if ( !outOfRange( d->y, d->m, d->d-1 ) ) {
-      accepted = TRUE;
-      setDay( d->d-1 );
+
+    if (v < minimum) {
+        if (wrapping) {
+            QVariant t = v;
+            setDigit(t, s, steps < 0 ? max : min);
+            if (t >= minimum && t <= maximum) {
+                v = t;
+            } else {
+                setDigit(t, s, getDigit(steps < 0 ? maximum : minimum, s));
+                if (t >= minimum && t <= maximum) {
+                    v = t;
+                }
+            }
+        } else {
+            v = value;
+        }
+    } else if (v > maximum) {
+        if (wrapping) {
+            QVariant t = v;
+            setDigit(t, s, steps > 0 ? min : max);
+            if (t >= minimum && t <= maximum) {
+                v = t;
+            } else {
+                setDigit(t, s, getDigit(steps > 0 ? minimum : maximum, s));
+                if (t >= minimum && t <= maximum) {
+                    v = t;
+                }
+            }
+        } else {
+            v = value;
+        }
     }
-  }
-  if ( accepted ) {
-    d->changed = TRUE;
-    emit valueChanged( date() );
-  }
-  
-  d->ed->repaint( d->ed->rect(), FALSE );
+
+    return bound(v, value, steps);
 }
 
 /*!
-    Sets the year to \a year, which must be a valid year. The range
-    currently supported is from 1752 to 8000.
+  \internal
 
-    \sa ExtDate
+  Returns the absolute maximum for a section
 */
 
-void ExtDateEdit::setYear( int year )
+int ExtDateTimeEditPrivate::absoluteMax(Section s) const
 {
-  if ( !outOfRange( year, d->m, d->d ) ) {
-    d->y = year;
-    setMonth( d->m );
-  }
-}
+    switch (s) {
+    case HourSection: return 23;
+    case MinuteSection:
+    case SecondSection: return 59;
+    case MSecSection: return 999;
+    case YearTwoDigitsSection: return 2099;
+    case YearSection: return 7999;
+    case MonthSection:
+    case MonthShortNameSection: return 12;
+    case DaySection: return 31;
+    case AmPmSection:
+    case AmPmLowerCaseSection: return 1;
+    default: break;
+    }
+    qFatal("%s passed to max. This should never happen", sectionName(s).toLatin1().constData());
+    return -1;
 
+}
 
 /*!
-    Sets the month to \a month, which must be a valid month, i.e.
-    between 1 and 12.
+  \internal
+
+  Returns the absolute minimum for a section
 */
 
-void ExtDateEdit::setMonth( int month )
+int ExtDateTimeEditPrivate::absoluteMin(Section s) const
 {
-  if ( month < 1 )
-    month = 1;
-  if ( month > 12 )
-    month = 12;
-  if ( !outOfRange( d->y, month, d->d ) ) {
-    d->m = month;
-    setDay( d->d );
-  }
+    switch (s) {
+    case HourSection:
+    case MinuteSection:
+    case SecondSection:
+    case MSecSection: return 0;
+    case YearTwoDigitsSection: return 2000;
+    case YearSection: return 1753;
+    case MonthSection:
+    case MonthShortNameSection:
+    case DaySection: return 1;
+    case AmPmSection:
+    case AmPmLowerCaseSection: return 0;
+    default: break;
+    }
+    qFatal("%s passed to min. This should never happen", sectionName(s).toLatin1().constData());
+    return -1;
 }
 
-
 /*!
-    Sets the day to \a day, which must be a valid day. The function
-    will ensure that the \a day set is valid for the month and year.
+  \internal
+
+  Returns a copy of the sectionNode for the Section \a s.
 */
 
-void ExtDateEdit::setDay( int day )
+ExtDateTimeEditPrivate::SectionNode ExtDateTimeEditPrivate::sectionNode(Section s) const
 {
-  ExtDate test = ExtDate( d->y, d->m, 1 );
-  
-  if ( day < 1 )
-    day = 1;
-  if ( day > test.daysInMonth() )
-    day = test.daysInMonth();
-  
-  d->dayCache = d->d;
-  d->d = day;
-}
+    if (s == FirstSection) {
+        return first;
+    } else if (s == LastSection) {
+        return last;
+    }
 
+    for (int i=0; i<sectionNodes.size(); ++i)
+        if ((sectionNodes.at(i).section & ~Internal) == (s & ~Internal))
+            return sectionNodes.at(i);
+    SectionNode sn;
+    sn.section = NoSection;
+    sn.pos = -1;
+    return sn;
+}
 
 /*!
-    \property ExtDateEdit::date
-    \brief the editor's date value.
-
-    If the date property is not valid, the editor displays all zeroes
-    and ExtDateEdit::date() will return an invalid date. It is strongly
-    recommended that the editor is given a default date value (e.g.
-    currentDate()). That way, attempts to set the date property to an
-    invalid date will fail.
+  \internal
 
-    When changing the date property, if the date is less than
-    minValue(), or is greater than maxValue(), nothing happens.
+  Returns the starting position for section \a s.
 */
 
-void ExtDateEdit::setDate( const ExtDate& date )
+int ExtDateTimeEditPrivate::sectionPos(Section s) const
 {
-  if ( !date.isValid() ) {
-    d->y = 0;
-    d->m = 0;
-    d->d = 0;
-    d->dayCache = 0;
-  } else {
-    if ( date > maxValue() || date < minValue() )
-      return;
-    d->y = date.year();
-    d->m = date.month();
-    d->d = date.day();
-    d->dayCache = d->d;
-    emit valueChanged( date );
-  }
-  d->changed = FALSE;
-  d->ed->repaint( d->ed->rect(), FALSE );
-}
-
-ExtDate ExtDateEdit::date() const
-{
-    if ( ExtDate::isValid( d->y, d->m, d->d ) )
-       return ExtDate( d->y, d->m, d->d );
-    return ExtDate();
-}
-
-/*!  \internal
-
-  Returns TRUE if \a y, \a m, \a d is out of range, otherwise returns
-  FALSE.
-
-  \sa setRange()
-
-*/
-
-bool ExtDateEdit::outOfRange( int y, int m, int d ) const
-{
-  if ( ExtDate::isValid( y, m, d ) ) {
-    ExtDate currentDate( y, m, d );
-    if ( currentDate > maxValue() || currentDate < minValue() ) {
-           //## outOfRange should set overwrite?
-           return TRUE;
-    }
-    return FALSE;
-  }
-  return FALSE; /* assume ok */
-}
-
-/*!  \reimp
-
-*/
-
-void ExtDateEdit::addNumber( int sec, int num )
-{
-    if ( sec == -1 )
-       return;
-    killTimer( d->timerId );
-    bool overwrite = FALSE;
-    bool accepted = FALSE;
-    d->typing = TRUE;
-    QString txt;
-    if ( sec == d->yearSection ) {
-       txt = QString::number( d->y );
-       if ( d->overwrite || txt.length() == 4 ) {
-           accepted = TRUE;
-           d->y = num;
-       } else {
-           txt += QString::number( num );
-           if ( txt.length() == 4  ) {
-               int val = txt.toInt();
-               if ( val < 1792 )
-                   d->y = 1792;
-               else if ( val > 8000 )
-                   d->y = 8000;
-               else if ( outOfRange( val, d->m, d->d ) )
-                   txt = QString::number( d->y );
-               else {
-                   accepted = TRUE;
-                   d->y = val;
-               }
-           } else {
-               accepted = TRUE;
-               d->y = txt.toInt();
-           }
-           if ( d->adv && txt.length() == 4 ) {
-               d->ed->setFocusSection( d->ed->focusSection()+1 );
-               overwrite = TRUE;
-           }
-       }
-    } else if ( sec == d->monthSection ) {
-       txt = QString::number( d->m );
-       if ( d->overwrite || txt.length() == 2 ) {
-           accepted = TRUE;
-           d->m = num;
-       } else {
-           txt += QString::number( num );
-           int temp = txt.toInt();
-           if ( temp > 12 )
-               temp = num;
-           if ( outOfRange( d->y, temp, d->d ) )
-               txt = QString::number( d->m );
-           else {
-               accepted = TRUE;
-               d->m = temp;
-           }
-           if ( d->adv && txt.length() == 2 ) {
-               d->ed->setFocusSection( d->ed->focusSection()+1 );
-               overwrite = TRUE;
-           }
-       }
-    } else if ( sec == d->daySection ) {
-       txt = QString::number( d->d );
-       if ( d->overwrite || txt.length() == 2 ) {
-           accepted = TRUE;
-           d->d = num;
-           d->dayCache = d->d;
-       } else {
-           txt += QString::number( num );
-           int temp = txt.toInt();
-           if ( temp > 31 )
-               temp = num;
-           if ( outOfRange( d->y, d->m, temp ) )
-               txt = QString::number( d->d );
-           else {
-               accepted = TRUE;
-               d->d = temp;
-               d->dayCache = d->d;
-           }
-           if ( d->adv && txt.length() == 2 ) {
-               d->ed->setFocusSection( d->ed->focusSection()+1 );
-               overwrite = TRUE;
-           }
-       }
-    }
-    if ( accepted ) {
-       d->changed = TRUE;
-       emit valueChanged( date() );
-    }
-    d->overwrite = overwrite;
-    d->timerId = startTimer( qApp->doubleClickInterval()*4 );
-    d->ed->repaint( d->ed->rect(), FALSE );
-}
-
-
-/*! \reimp
-
-*/
-
-bool ExtDateEdit::setFocusSection( int s )
-{
-  if ( s != d->ed->focusSection() ) {
-    killTimer( d->timerId );
-    d->overwrite = TRUE;
-    d->typing = FALSE;
-    fix(); // will emit valueChanged if necessary
-  }
-  return d->ed->setFocusSection( s );
-}
-
-
-/*!
-    Attempts to fix any invalid date entries.
-
-    The rules applied are as follows:
-
-    - if the day is larger than the number of days in the month, 
-    - it is reset to that number
-    - If the year has four digits it is left unchanged.
-    - If the year has two digits, the year will be changed to four
-      digits in the range current year - 70 to current year + 29.
-    - If the year has three digits in the range 100..999, the
-      current millennium, i.e. 2000, will be added giving a year
-      in the range 2100..2999.
-
-*/
-
-void ExtDateEdit::fix()
-{
-  bool changed = FALSE;
-  
-  ExtDate test = ExtDate( d->y, d->m, 1 );
-  if ( d->d > test.daysInMonth() ) {
-    
-    d->d = test.daysInMonth();
-    changed = TRUE;
-  }
-  
-  int currentYear = ExtDate::currentDate().year();
-  int year = d->y;
-  if ( year < 100 ) {
-    int currentCentury = currentYear / 100;
-    year += currentCentury * 100;
-    if ( currentYear > year ) {
-        if ( currentYear > year + 70 )
-      year += 100;
-    } else {
-        if ( year >= currentYear + 30 )
-      year -= 100;
-    }
-    changed = TRUE;
-      } else if ( year < 1000 ) {
-    int currentMillennium = currentYear / 10;
-    year += currentMillennium * 10;
-    changed = TRUE;
-  }
-  if ( changed && outOfRange( year, d->m, d->d ) ) {
-       if ( minValue().isValid() && date() < minValue() ) {
-           d->d =  minValue().day();
-           d->dayCache = d->d;
-           d->m = minValue().month();
-           d->y = minValue().year();
-    }
-    if ( date() > maxValue() ) {
-           d->d =  maxValue().day();
-           d->dayCache = d->d;
-           d->m = maxValue().month();
-           d->y = maxValue().year();
-    }
-  } else if ( changed )
-    setYear( year );
-    
-  if ( changed ) {
-//    emit valueChanged( date() );
-//    d->changed = FALSE;
-  }
-}
+    if (s == FirstSection) {
+        return first.pos;
+    } else if (s == LastSection) {
+        return last.pos;
+    }
 
+    for (int i=0; i<sectionNodes.size(); ++i)
+        if (sectionNodes.at(i).section == s)
+            return sectionNodes.at(i).pos;
+    return -1;
+}
 
-/*! \reimp
+/*!
+  \internal
 
+  Adds a section to \a list. If this section already exists returns false.
 */
 
-bool ExtDateEdit::event( QEvent *e )
+bool ExtDateTimeEditPrivate::addSection(QList<SectionNode> &list, Section ds, int pos) const
 {
-  if( e->type() == QEvent::FocusOut ) {
-    d->typing = FALSE;
-    // the following can't be done in fix() because fix() called
-    // from all over the place and it will break the old behaviour
-    if ( !ExtDate::isValid( d->y, d->m, d->d ) ) {
-      d->dayCache = d->d;
-      int i = d->d;
-      for ( ; i > 0; i-- ) {
-        d->d = i;
-        if ( ExtDate::isValid( d->y, d->m, d->d ) )
-          break;
-      }
-      d->changed = TRUE;
+    for (int i=0; i<list.size(); ++i) {
+        if ((list.at(i).section & ~Internal) == (ds & ~Internal)) {
+            EDTEDEBUGN("Could not add section %s to pos %d because it is already in the list", sectionName(ds).toLatin1().constData(), pos);
+            return false;
+        }
     }
-    if ( d->changed ) {
-      fix();
-      emit valueChanged( date() );
-      d->changed = FALSE;
-    }
-  } else if ( e->type() == QEvent::LocaleChange ) {
-    readLocaleSettings();
-    d->ed->setSeparator( localDateSep() );
-    setOrder( localOrder() );
-  }
+    SectionNode s;
+    s.section = ds;
+    s.pos = pos;
+    list << s;
 
-  bool result = ExtDateTimeEditBase::event( e ); 
-  
-  return result;
+    return true;
 }
 
+
 /*!
   \internal
 
-  Function which is called whenever the user tries to
-  remove the first number from \a sec by pressing the backspace key.
+  Selects the section \a s. If \a forward is false selects backwards.
 */
 
-void ExtDateEdit::removeFirstNumber( int sec )
+void ExtDateTimeEditPrivate::setSelected(Section s, bool forward)
 {
-    if ( sec == -1 )
-       return;
-    QString txt;
-    if ( sec == d->yearSection ) {
-       txt = QString::number( d->y );
-       txt = txt.mid( 1, txt.length() ) + "0";
-       d->y = txt.toInt();
-    } else if ( sec == d->monthSection ) {
-       txt = QString::number( d->m );
-       txt = txt.mid( 1, txt.length() ) + "0";
-       d->m = txt.toInt();
-    } else if ( sec == d->daySection ) {
-       txt = QString::number( d->d );
-       txt = txt.mid( 1, txt.length() ) + "0";
-       d->d = txt.toInt();
-       d->dayCache = d->d;
+    if (s == NoSection)
+        return;
+    if (specialValue())
+        edit->selectAll();
+    if (forward) {
+        edit->setSelection(sectionPos(s), sectionSize(s));
+    } else {
+        edit->setSelection(sectionPos(s) + sectionSize(s), -sectionSize(s));
     }
-    d->ed->repaint( d->ed->rect(), FALSE );
 }
 
-/*! \reimp
+/*!
+  \internal helper function for parseFormat. removes quotes that are
+  not escaped and removes the escaping on those that are escaped
+
+*/
+
+static QString unquote(const QString &str)
+{
+    const char quote = '\'';
+    const char slash = '\\';
+    const char zero = '0';
+    QString ret;
+    QChar status = zero;
+    for (int i=0; i<str.size(); ++i) {
+        if (str.at(i) == quote) {
+            if (status != quote) {
+                status = quote;
+            } else if (!ret.isEmpty() && str.at(i - 1) == slash) {
+                ret[ret.size() - 1] = quote;
+            } else {
+                status = zero;
+            }
+        } else {
+            ret += str.at(i);
+        }
+    }
+    return ret;
+}
+/*!
+  \internal
 
-*/
+  Parses the format \a newFormat. If successful, returns true and
+  sets up the format. Else keeps the old format and returns false.
+
+*/
+
+bool ExtDateTimeEditPrivate::parseFormat(const QString &newFormat)
+{
+    const char space = ' ';
+    const char quote = '\'';
+    const char slash = '\\';
+    const char zero = '0';
+    if (newFormat == displayFormat && !newFormat.isEmpty() && layoutDirection == QApplication::layoutDirection())
+        return true;
+    layoutDirection = QApplication::layoutDirection();
+
+    QList<SectionNode> newSectionNodes;
+    ExtDateTimeEdit::Sections newDisplay = 0;
+    QStringList newSeparators;
+    int i, index = 0;
+    int add = 0;
+    QChar status = zero;
+    for (i = 0; i<newFormat.size(); ++i) {
+        if (newFormat.at(i) == quote) {
+            ++add;
+            if (status != quote) {
+                status = quote;
+            } else if (newFormat.at(i - 1) != slash) {
+                status = zero;
+            }
+        } else if (i + 1 < newFormat.size() && status != quote) {
+            switch (newFormat.at(i).cell()) {
+            case 'h':
+                if (newFormat.at(i+1) == QLatin1Char('h')) {
+                    if (!addSection(newSectionNodes, HourSection, i - add))
+                        return false;
+                    newSeparators << unquote(newFormat.mid(index, i - index));
+                    index = ++i + 1;
+                    newDisplay |= ExtDateTimeEdit::HourSection;
+                }
+                break;
+            case 'm':
+                if (newFormat.at(i+1) == QLatin1Char('m')) {
+                    if (!addSection(newSectionNodes, MinuteSection, i - add))
+                        return false;
+                    newSeparators << unquote(newFormat.mid(index, i - index));
+                    index = ++i + 1;
+                    newDisplay |= ExtDateTimeEdit::MinuteSection;
+                }
+                break;
+            case 's':
+                if (newFormat.at(i+1) == QLatin1Char('s')) {
+                    if (!addSection(newSectionNodes, SecondSection, i - add))
+                        return false;
+                    newSeparators << unquote(newFormat.mid(index, i - index));
+                    index = ++i + 1;
+                    newDisplay |= ExtDateTimeEdit::SecondSection;
+                }
+                break;
+            case 'z':
+                if (i + 2 <newFormat.size()
+                    && newFormat.at(i+1) == QLatin1Char('z')
+                    && newFormat.at(i+2) == QLatin1Char('z')) {
+                    if (!addSection(newSectionNodes, MSecSection, i - add))
+                        return false;
+                    newSeparators << unquote(newFormat.mid(index, i - index));
+                    index = (i += 2) + 1;
+                    newDisplay |= ExtDateTimeEdit::MSecSection;
+                }
+                break;
+            case 'A':
+            case 'a': {
+                const bool cap = newFormat.at(i) == QLatin1Char('A');
+                if (newFormat.at(i+1) == (cap ? QLatin1Char('P') : QLatin1Char('p'))) {
+                    if (!addSection(newSectionNodes, cap ? AmPmSection : AmPmLowerCaseSection, i - add))
+                        return false;
+                    newSeparators << unquote(newFormat.mid(index, i - index));
+                    index = ++i + 1;
+                    newDisplay |= ExtDateTimeEdit::AmPmSection;
+                }
+                break; }
+            case 'y':
+                if (newFormat.at(i+1) == QLatin1Char('y')) {
+                    const ExtDate YY_MIN(2000, 1, 1);
+                    const ExtDate YY_MAX(2099, 12, 31);
+                    const bool four = (i + 3 <newFormat.size()
+                                       && newFormat.at(i+2) == QLatin1Char('y') && newFormat.at(i+3) == QLatin1Char('y'));
+                    if (!addSection(newSectionNodes, four ? YearSection : YearTwoDigitsSection, i - add)
+                        || (!four && (maximum.toDate() < YY_MIN || minimum.toDate() > YY_MAX))) {
+                        return false;
+                    }
+
+                    newSeparators << unquote(newFormat.mid(index, i - index));
+                    index = (i += (four ? 3 : 1)) + 1;
+                    newDisplay |= ExtDateTimeEdit::YearSection;
+                }
+                break;
+            case 'M':
+                if (newFormat.at(i+1) == QLatin1Char('M')) {
+                    const bool three = (i + 2 <newFormat.size() && newFormat.at(i+2) == QLatin1Char('M'));
+                    if (!addSection(newSectionNodes, three ? MonthShortNameSection : MonthSection, i - add))
+                        return false;
+                    newSeparators << unquote(newFormat.mid(index, i - index));
+                    index = (i += (three ? 2 : 1)) + 1;
+                    newDisplay |= ExtDateTimeEdit::MonthSection;
+                }
+                break;
+
+            case 'd':
+                if (newFormat.at(i+1) == QLatin1Char('d')) {
+                    if (!addSection(newSectionNodes, DaySection, i - add))
+                        return false;
+                    newSeparators << unquote(newFormat.mid(index, i - index));
+                    index = ++i + 1;
+                    newDisplay |= ExtDateTimeEdit::DaySection;
+                }
+                break;
+
+            default: break;
+            }
+        }
+    }
+    if (newSectionNodes.isEmpty()) {
+        EDTEDEBUGN("Could not parse format. No sections in format '%s'.", newFormat.toLatin1().constData());
+        return false;
+    }
 
-void ExtDateEdit::removeLastNumber( int sec )
-{
-    if ( sec == -1 )
-       return;
-    QString txt;
-    if ( sec == d->yearSection ) {
-       txt = QString::number( d->y );
-       txt = txt.mid( 0, txt.length()-1 );
-       d->y = txt.toInt();
-    } else if ( sec == d->monthSection ) {
-       txt = QString::number( d->m );
-       txt = txt.mid( 0, txt.length()-1 );
-       d->m = txt.toInt();
-    } else if ( sec == d->daySection ) {
-       txt = QString::number( d->d );
-       txt = txt.mid( 0, txt.length()-1 );
-       d->d = txt.toInt();
-       d->dayCache = d->d;
+    newSeparators << (index < newFormat.size() ? unquote(newFormat.mid(index)) : QString());
+
+    display = newDisplay;
+    last.pos = newFormat.size();
+
+    if (!QApplication::isRightToLeft()) {
+        displayFormat = newFormat;
+        separators = newSeparators;
+        sectionNodes = newSectionNodes;
+    } else {
+        displayFormat.clear();;
+        int total = newFormat.size();
+        int i;
+        sectionNodes.clear();
+        separators.clear();
+
+        for (i=newSectionNodes.size() - 1; i>=0; --i) {
+            displayFormat += newSeparators.at(i + 1);
+            displayFormat += sectionFormat(newSectionNodes.at(i).section);
+            SectionNode sn = newSectionNodes.at(i);
+            sn.pos = total - sn.pos - sectionSize(sn.section);
+
+            sectionNodes.append(sn);
+            separators.append(newSeparators.at(i + 1));
+        }
+        displayFormat += newSeparators.at(0);
+        separators.append(newSeparators.at(0));
+    }
+    escapedFormat.clear();
+    status = zero;
+    int ampmsize = sectionSize(AmPmSection);
+    for (int i = 0; i < displayFormat.size(); ++i) {
+        if (displayFormat.at(i) == quote){
+            if (status == quote) {
+                if (!escapedFormat.isEmpty() && displayFormat.at(i - 1) == slash) {
+                    escapedFormat[escapedFormat.size() - 1] = quote;
+                } else {
+                    status = zero;
+                }
+            } else {
+                status = quote;
+            }
+        } else {
+            escapedFormat += displayFormat.at(i);
+            if (i > 1 && ampmsize != 2
+                && ((displayFormat.at(i - 1) == QLatin1Char('a') && displayFormat.at(i) == 'p')
+                    || (displayFormat.at(i - 1) == QLatin1Char('A') && displayFormat.at(i) == 'P'))) {
+                if (ampmsize > 2) {
+                    escapedFormat.append(QString().leftJustified(ampmsize - 2, space));
+                } else if (ampmsize == 1) {
+                    escapedFormat.remove(i, 1);
+                } else {
+                    qWarning("Translating am/pm to an empty string will "
+                             "cause problems for ExtDateTimeEdit");
+                }
+            }
+        }
+    }
+
+    if (QApplication::isRightToLeft()) {
+        // we want displayFormat to return what you set with
+        // setDisplayFormat() in rtol mode as well. I needed to
+        // reverse it to calculate the escapedFormat correctly. Set it
+        // back here.
+        displayFormat = newFormat;
     }
-    d->ed->repaint( d->ed->rect(), FALSE );
+
+
+//     qDebug() << newFormat << displayFormat;
+//     qDebug("escapedFormat = [%s]", escapedFormat.toLatin1().constData());
+//     qDebug("separators:\n'%s'", separators.join("|").toLatin1().constData());
+
+//     qDebug("display is [%0x]", (uint)display);
+
+    return true;
 }
 
 /*!
-    \property ExtDateEdit::autoAdvance
-    \brief whether the editor automatically advances to the next
-    section
+  \internal
 
-    If autoAdvance is TRUE, the editor will automatically advance
-    focus to the next date section if a user has completed a section.
-    The default is FALSE.
+  Returns the section at index \a index or NoSection if there are no sections there.
 */
 
-void ExtDateEdit::setAutoAdvance( bool advance )
+ExtDateTimeEditPrivate::Section ExtDateTimeEditPrivate::sectionAt(int index) const
 {
-    d->adv = advance;
-}
+    if (index < separators.first().size()) {
+        return (index == 0 ? FirstSection : NoSection);
+    } else if (escapedFormat.size() - index < separators.last().size() + 1) {
+        if (separators.last().size() == 0) {
+            return sectionNodes.last().section;
+        }
+        return (index == last.pos ? LastSection : NoSection);
+    }
 
+//    QString deb;
+    for (int i=0; i<sectionNodes.size(); ++i) {
+        const int tmp = sectionNodes.at(i).pos;
+//         deb += QString("%1 %2 %3 %4 %5 %6\n").arg(sectionName(sectionNodes.at(i).section)).arg(tmp).
+//                arg(index).arg(i).arg(sectionSize(sectionNodes.at(i).section)).arg(layoutDirection == Qt::RightToLeft);
 
-bool ExtDateEdit::autoAdvance() const
-{
-    return d->adv;
+        if (index < tmp + sectionSize(sectionNodes.at(i).section)) {
+            return (index < tmp ? NoSection : sectionNodes.at(i).section);
+        }
+    }
+//    qDebug() << deb;
+    return NoSection;
 }
 
-/*! \reimp
+/*!
+  \internal
+
+  Returns the closest section of index \a index. Searches forward
+  for a section if \a forward is true. Otherwise searches backwards.
 */
 
-void ExtDateEdit::timerEvent( QTimerEvent * )
+ExtDateTimeEditPrivate::Section ExtDateTimeEditPrivate::closestSection(int index, bool forward) const
 {
-    d->overwrite = TRUE;
+    Q_ASSERT(index >= 0);
+    if (index < separators.first().size()) {
+        return forward ? sectionNodes.first().section : FirstSection;
+    } else if (last.pos - index < separators.last().size() + 1) {
+        return forward ? LastSection : sectionNodes.last().section;
+    }
+    for (int i=0; i<sectionNodes.size(); ++i) {
+        int tmp = sectionNodes.at(i).pos;
+        if (index < tmp + sectionSize(sectionNodes.at(i).section)) {
+            if (index < tmp && !forward)
+                return sectionNodes.at(i-1).section;
+            return sectionNodes.at(i).section;
+        } else if (i == sectionNodes.size() - 1 && index > tmp) {
+            return sectionNodes.at(i).section;
+        }
+    }
+    qWarning("2index return NoSection. This should not happen");
+    return NoSection;
 }
 
 /*!
-    \fn void ExtDateEdit::valueChanged( const ExtDate& date )
+  \internal
 
-    This signal is emitted whenever the editor's value changes. The \a
-    date parameter is the new value.
+  Returns a copy of the section that is before or after \a current, depending on \a forward.
 */
 
-///////////
-
-class QTimeEditPrivate
+ExtDateTimeEditPrivate::SectionNode ExtDateTimeEditPrivate::nextPrevSection(Section current, bool forward) const
 {
-public:
-    int h;
-    int m;
-    int s;
-    uint display;
-    bool adv;
-    bool overwrite;
-    int timerId;
-    bool typing;
-    QTime min;
-    QTime max;
-    bool changed;
-    ExtDateTimeEditor *ed;
-    Q3SpinWidget *controls;
-};
+    if (QApplication::isRightToLeft())
+        forward = !forward;
+    if (current == FirstSection) {
+        return (forward ? sectionNodes.first() : first);
+    } else if (current == LastSection) {
+        return (forward ? last : sectionNodes.last());
+    }
+    for (int i=0; i<sectionNodes.size(); ++i) {
+        if (sectionNodes.at(i).section == current) {
+            int index = i + (forward ? 1 : -1);
+            if (index >= 0 && index < sectionNodes.size()) {
+                return sectionNodes.at(index);
+            } else {
+                break;
+            }
+        }
+    }
+    return (forward ? last : first);
+}
 
 /*!
-    \class QTimeEdit ExtDatetimeedit.h
-    \brief The QTimeEdit class provides a time editor.
+  \internal
 
-    \ingroup advanced
-    \ingroup time
-    \mainclass
+  Clears the text of section \a s.
+*/
 
-    QTimeEdit allows the user to edit times by using the keyboard or
-    the arrow keys to increase/decrease time values. The arrow keys
-    can be used to move from section to section within the QTimeEdit
-    box. The user can automatically be moved to the next section once
-    they complete a section using setAutoAdvance(). Times appear in
-    hour, minute, second order. It is recommended that the QTimeEdit
-    is initialised with a time, e.g.
-    \code
-    QTime timeNow = QTime::currentTime();
-    QTimeEdit *timeEdit = new QTimeEdit( timeNow, this );
-    timeEdit->setRange( timeNow, timeNow.addSecs( 60 * 60 ) );
-    \endcode
-    Here we've created a QTimeEdit widget set to the current time.
-    We've also set the minimum value to the current time and the
-    maximum time to one hour from now.
-
-    The maximum and minimum values for a time value in the time editor
-    default to the maximum and minimum values for a QTime. You can
-    change this by calling setMinValue(), setMaxValue() or setRange().
-
-    Terminology: A QTimeWidget consists of three sections, one each
-    for the hour, minute and second. You can change the separator
-    character using setSeparator(), by default the separator is read
-    from the system's settings.
-
-    \img datetimewidgets.png Date Time Widgets
-
-    \sa QTime ExtDateEdit ExtDateTimeEdit
-*/
-
-
-// /*!
-//     Constructs an empty time edit with parent \a parent and called \a
-//     name.
-// */
-//
-// QTimeEdit::QTimeEdit( QWidget * parent, const char * name )
-//     : ExtDateTimeEditBase( parent, name )
-// {
-//     init();
-// }
-//
-// /*!
-//     \overload
-//
-//     Constructs a time edit with the initial time value, \a time,
-//     parent \a parent and called \a name.
-// */
-//
-// QTimeEdit::QTimeEdit( const QTime& time, QWidget * parent, const char * name )
-//     : ExtDateTimeEditBase( parent, name )
-// {
-//     init();
-//     setTime( time );
-// }
-//
-// /*! \internal
-//  */
-//
-// void QTimeEdit::init()
-// {
-//     d = new QTimeEditPrivate();
-//     d->ed = new ExtDateTimeEditor( this, "time edit base" );
-//     d->controls = new ExtDateTimeSpinWidget( this, qstrcmp( name(), "qt_datetime_timeedit" ) == 0 ? "qt_spin_widget" : "time edit controls" );
-//     d->controls->setEditWidget( d->ed );
-//     setFocusProxy( d->ed );
-//     connect( d->controls, SIGNAL( stepUpPressed() ), SLOT( stepUp() ) );
-//     connect( d->controls, SIGNAL( stepDownPressed() ), SLOT( stepDown() ) );
-//
-//     d->ed->appendSection( QNumberSection( 0,0, TRUE, 0 ) );
-//     d->ed->appendSection( QNumberSection( 0,0, TRUE, 1 ) );
-//     d->ed->appendSection( QNumberSection( 0,0, TRUE, 2 ) );
-//     d->ed->setSeparator( localTimeSep() );
-//
-//     d->h = 0;
-//     d->m = 0;
-//     d->s = 0;
-//     d->display = Hours | Minutes | Seconds;
-//     if ( lAMPM ) {
-//     d->display |= AMPM;
-//     d->ed->appendSection( QNumberSection( 0,0, FALSE, 3 ) );
-//     }
-//     d->adv = FALSE;
-//     d->overwrite = TRUE;
-//     d->timerId = 0;
-//     d->typing = FALSE;
-//     d->min = QTime( 0, 0, 0 );
-//     d->max = QTime( 23, 59, 59 );
-//     d->changed = FALSE;
-//
-//     setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Fixed );
-//
-//     refcount++;
-// }
-//
-// /*!
-//     Destroys the object and frees any allocated resources.
-// */
-//
-// QTimeEdit::~QTimeEdit()
-// {
-//     delete d;
-//     if ( !--refcount )
-//     cleanup();
-// }
-//
-// /*!
-//     \property QTimeEdit::minValue
-//     \brief the minimum time value
-//
-//     Setting the minimum time value is equivalent to calling
-//     QTimeEdit::setRange( \e t, maxValue() ), where \e t is the minimum
-//     time. The default minimum time is 00:00:00.
-//
-//     \sa maxValue setRange()
-// */
-//
-// QTime QTimeEdit::minValue() const
-// {
-//     return d->min;
-// }
-//
-// /*!
-//     \property QTimeEdit::maxValue
-//     \brief the maximum time value
-//
-//     Setting the maximum time value is equivalent to calling
-//     QTimeEdit::setRange( minValue(), \e t ), where \e t is the maximum
-//     time. The default maximum time is 23:59:59.
-//
-//     \sa minValue setRange()
-// */
-//
-// QTime QTimeEdit::maxValue() const
-// {
-//     return d->max;
-// }
-//
-//
-// /*!
-//     Sets the valid input range for the editor to be from \a min to \a
-//     max inclusive. If \a min is invalid no minimum time is set.
-//     Similarly, if \a max is invalid no maximum time is set.
-// */
-//
-// void QTimeEdit::setRange( const QTime& min, const QTime& max )
-// {
-//     if ( min.isValid() )
-//     d->min = min;
-//     if ( max.isValid() )
-//     d->max = max;
-// }
-//
-// /*!
-//   \property QTimeEdit::display
-//   \brief the sections that are displayed in the time edit
-//
-//   The value can be any combination of the values in the Display enum.
-//   By default, the widget displays hours, minutes and seconds.
-// */
-// void QTimeEdit::setDisplay( uint display )
-// {
-//     if ( d->display == display )
-//     return;
-//
-//     d->ed->clearSections();
-//     d->display = display;
-//     if ( d->display & Hours )
-//     d->ed->appendSection( QNumberSection( 0,0, TRUE, 0 ) );
-//     if ( d->display & Minutes )
-//     d->ed->appendSection( QNumberSection( 0,0, TRUE, 1 ) );
-//     if ( d->display & Seconds )
-//     d->ed->appendSection( QNumberSection( 0,0, TRUE, 2 ) );
-//     if ( d->display & AMPM )
-//     d->ed->appendSection( QNumberSection( 0,0, FALSE, 3 ) );
-//
-//     d->ed->setFocusSection( 0 );
-//     d->ed->update();
-// }
-//
-// uint QTimeEdit::display() const
-// {
-//     return d->display;
-// }
-//
-// /*!
-//     \property QTimeEdit::time
-//     \brief the editor's time value.
-//
-//     When changing the time property, if the time is less than
-//     minValue(), or is greater than maxValue(), nothing happens.
-// */
-//
-// void QTimeEdit::setTime( const QTime& time )
-// {
-//     if ( !time.isValid() ) {
-//     d->h = 0;
-//     d->m = 0;
-//     d->s = 0;
-//     } else {
-//     if ( time > maxValue() || time < minValue() )
-//         return;
-//     d->h = time.hour();
-//     d->m = time.minute();
-//     d->s = time.second();
-//     emit valueChanged( time );
-//     }
-//     d->changed = FALSE;
-//     d->ed->repaint( d->ed->rect(), FALSE );
-// }
-//
-// QTime QTimeEdit::time() const
-// {
-//     if ( QTime::isValid( d->h, d->m, d->s ) )
-//     return QTime( d->h, d->m, d->s );
-//     return QTime();
-// }
-//
-// /*!
-//     \property QTimeEdit::autoAdvance
-//     \brief whether the editor automatically advances to the next
-//     section
-//
-//     If autoAdvance is TRUE, the editor will automatically advance
-//     focus to the next time section if a user has completed a section.
-//     The default is FALSE.
-// */
-//
-// void QTimeEdit::setAutoAdvance( bool advance )
-// {
-//     d->adv = advance;
-// }
-//
-// bool QTimeEdit::autoAdvance() const
-// {
-//     return d->adv;
-// }
-//
-// /*!
-//     Sets the separator to \a s. Note that currently only the first
-//     character of \a s is used.
-// */
-//
-// void QTimeEdit::setSeparator( const QString& s )
-// {
-//     d->ed->setSeparator( s );
-// }
-//
-// /*!
-//     Returns the editor's separator.
-// */
-//
-// QString QTimeEdit::separator() const
-// {
-//     return d->ed->separator();
-// }
-//
-//
-// /*!
-//     \fn void QTimeEdit::valueChanged( const QTime& time )
-//
-//     This signal is emitted whenever the editor's value changes. The \a
-//     time parameter is the new value.
-// */
-//
-// /*! \reimp
-//
-// */
-//
-// bool QTimeEdit::event( QEvent *e )
-// {
-//     if ( e->type() == QEvent::FocusOut ) {
-//     d->typing = FALSE;
-//     if ( d->changed ) {
-//         emit valueChanged( time() );
-//         d->changed = FALSE;
-//     }
-//     } else if ( e->type() == QEvent::LocaleChange ) {
-//     readLocaleSettings();
-//     d->ed->setSeparator( localTimeSep() );
-//     }
-//     return ExtDateTimeEditBase::event( e );
-// }
-//
-// /*! \reimp
-//
-// */
-//
-// void QTimeEdit::timerEvent( QTimerEvent * )
-// {
-//     d->overwrite = TRUE;
-// }
-//
-//
-// /*! \reimp
-//
-// */
-//
-// void QTimeEdit::stepUp()
-// {
-//     int sec = d->ed->mapSection( d->ed->focusSection() );
-//     bool accepted = TRUE;
-//     switch( sec ) {
-//     case 0:
-//     if ( !outOfRange( d->h+1, d->m, d->s ) )
-//         setHour( d->h+1 );
-//     else
-//         setHour( d->min.hour() );
-//     break;
-//     case 1:
-//     if ( !outOfRange( d->h, d->m+1, d->s ) )
-//         setMinute( d->m+1 );
-//     else
-//         setMinute( d->min.minute() );
-//     break;
-//     case 2:
-//     if ( !outOfRange( d->h, d->m, d->s+1 ) )
-//         setSecond( d->s+1 );
-//     else
-//         setSecond( d->min.second() );
-//     break;
-//     case 3:
-//     if ( d->h < 12 )
-//         setHour( d->h+12 );
-//     else
-//         setHour( d->h-12 );
-//     break;
-//     default:
-//     accepted = FALSE;
-// #ifdef QT_CHECK_RANGE
-//     qWarning( "QTimeEdit::stepUp: Focus section out of range!" );
-// #endif
-//     break;
-//     }
-//     if ( accepted ) {
-//     d->changed = TRUE;
-//     emit valueChanged( time() );
-//     }
-//     d->ed->repaint( d->ed->rect(), FALSE );
-// }
-//
-//
-// /*! \reimp
-//
-// */
-//
-// void QTimeEdit::stepDown()
-// {
-//     int sec = d->ed->mapSection( d->ed->focusSection() );
-//
-//     bool accepted = TRUE;
-//     switch( sec ) {
-//     case 0:
-//     if ( !outOfRange( d->h-1, d->m, d->s ) )
-//         setHour( d->h-1 );
-//     else
-//         setHour( d->max.hour() );
-//     break;
-//     case 1:
-//     if ( !outOfRange( d->h, d->m-1, d->s ) )
-//         setMinute( d->m-1 );
-//     else
-//         setMinute( d->max.minute() );
-//     break;
-//     case 2:
-//     if ( !outOfRange( d->h, d->m, d->s-1 ) )
-//         setSecond( d->s-1 );
-//     else
-//         setSecond( d->max.second() );
-//     break;
-//     case 3:
-//     if ( d->h > 11 )
-//         setHour( d->h-12 );
-//     else
-//         setHour( d->h+12 );
-//     break;
-//     default:
-//     accepted = FALSE;
-// #ifdef QT_CHECK_RANGE
-//     qWarning( "QTimeEdit::stepDown: Focus section out of range!" );
-// #endif
-//     break;
-//     }
-//     if ( accepted ) {
-//     d->changed = TRUE;
-//     emit valueChanged( time() );
-//     }
-//     d->ed->repaint( d->ed->rect(), FALSE );
-// }
-//
-//
-// /*!
-//     Returns the formatted number for section \a sec. This will
-//     correspond to either the hour, minute or second section, depending
-//     on \a sec.
-// */
-//
-// QString QTimeEdit::sectionFormattedText( int sec )
-// {
-//     QString txt;
-//     txt = sectionText( sec );
-//     txt = txt.rightJustify( 2, EXTDATETIMEEDIT_HIDDEN_CHAR );
-//     int offset = sec*2+sec*separator().length() + txt.length();
-//     if ( d->typing && sec == d->ed->focusSection() )
-//     d->ed->setSectionSelection( sec, offset - txt.length(), offset );
-//     else
-//     d->ed->setSectionSelection( sec, offset - txt.length(), offset );
-//
-//     return txt;
-// }
-//
-//
-// /*! \reimp
-//
-// */
-//
-// bool QTimeEdit::setFocusSection( int sec )
-// {
-//     if ( sec != d->ed->focusSection() ) {
-//     killTimer( d->timerId );
-//     d->overwrite = TRUE;
-//     d->typing = FALSE;
-//     QString txt = sectionText( sec );
-//     txt = txt.rightJustify( 2, EXTDATETIMEEDIT_HIDDEN_CHAR );
-//     int offset = sec*2+sec*separator().length() + txt.length();
-//     d->ed->setSectionSelection( sec, offset - txt.length(), offset );
-//     if ( d->changed ) {
-//         emit valueChanged( time() );
-//         d->changed = FALSE;
-//     }
-//     }
-//     return d->ed->setFocusSection( sec );
-// }
-//
-//
-// /*!
-//     Sets the hour to \a h, which must be a valid hour, i.e. in the
-//     range 0..24.
-// */
-//
-// void QTimeEdit::setHour( int h )
-// {
-//     if ( h < 0 )
-//     h = 0;
-//     if ( h > 23 )
-//     h = 23;
-//     d->h = h;
-// }
-//
-//
-// /*!
-//     Sets the minute to \a m, which must be a valid minute, i.e. in the
-//     range 0..59.
-// */
-//
-// void QTimeEdit::setMinute( int m )
-// {
-//     if ( m < 0 )
-//     m = 0;
-//     if ( m > 59 )
-//     m = 59;
-//     d->m = m;
-// }
-//
-//
-// /*!
-//     Sets the second to \a s, which must be a valid second, i.e. in the
-//     range 0..59.
-// */
-//
-// void QTimeEdit::setSecond( int s )
-// {
-//     if ( s < 0 )
-//     s = 0;
-//     if ( s > 59 )
-//     s = 59;
-//     d->s = s;
-// }
-//
-//
-// /*! \internal
-//
-//   Returns the text of section \a sec.
-//
-// */
-//
-// QString QTimeEdit::sectionText( int sec )
-// {
-//     sec = d->ed->mapSection( sec );
-//
-//     QString txt;
-//     switch( sec ) {
-//     case 0:
-//     if ( !(d->display & AMPM) || ( d->h < 13 && d->h ) ) {    // I wished the day stared at 0:00 for everybody
-//         txt = QString::number( d->h );
-//     } else {
-//         if ( d->h )
-//             txt = QString::number( d->h - 12 );
-//         else
-//             txt = "12";
-//     }
-//     break;
-//     case 1:
-//     txt = QString::number( d->m );
-//     break;
-//     case 2:
-//     txt = QString::number( d->s );
-//     break;
-//     case 3:
-//     if ( d->h < 12 ) {
-//         if ( lAM )
-//             txt = *lAM;
-//         else
-//             txt = QString::fromLatin1( "AM" );
-//     } else {
-//         if ( lPM )
-//             txt = *lPM;
-//         else
-//             txt = QString::fromLatin1( "PM" );
-//     }
-//     break;
-//     default:
-//     break;
-//     }
-//     return txt;
-// }
-//
-//
-// /*! \internal
-//  Returns TRUE if \a h, \a m, and \a s are out of range.
-//  */
-//
-// bool QTimeEdit::outOfRange( int h, int m, int s ) const
-// {
-//     if ( QTime::isValid( h, m, s ) ) {
-//     QTime currentTime( h, m, s );
-//     if ( currentTime > maxValue() ||
-//          currentTime < minValue() )
-//         return TRUE;
-//     else
-//         return FALSE;
-//     }
-//     return TRUE;
-// }
-//
-// /*! \reimp
-//
-// */
-//
-// void QTimeEdit::addNumber( int sec, int num )
-// {
-//     if ( sec == -1 )
-//     return;
-//     sec = d->ed->mapSection( sec );
-//     killTimer( d->timerId );
-//     bool overwrite = FALSE;
-//     bool accepted = FALSE;
-//     d->typing = TRUE;
-//     QString txt;
-//
-//     switch( sec ) {
-//     case 0:
-//     txt = ( d->display & AMPM && d->h > 12 ) ?
-//         QString::number( d->h - 12 ) : QString::number( d->h );
-//
-//     if ( d->overwrite || txt.length() == 2 ) {
-//         if ( d->display & AMPM && num == 0 )
-//             break; // Don't process 0 in 12 hour clock mode
-//         if ( d->display & AMPM && d->h > 11 )
-//             num += 12;
-//         if ( !outOfRange( num, d->m, d->s ) ) {
-//             accepted = TRUE;
-//             d->h = num;
-//         }
-//     } else {
-//         txt += QString::number( num );
-//         int temp = txt.toInt();
-//
-//         if ( d->display & AMPM ) {
-//             if ( temp == 12 ) {
-//                 if ( d->h < 12 ) {
-//                     temp = 0;
-//                 }
-//                 accepted = TRUE;
-//             } else if ( outOfRange( temp + 12, d->m, d->s ) ) {
-//                 txt = QString::number( d->h );
-//             } else {
-//                 if ( d->h > 11 ) {
-//                     temp += 12;
-//                 }
-//                 accepted = TRUE;
-//             }
-//         } else if ( !(d->display & AMPM) && outOfRange( temp, d->m, d->s ) ) {
-//             txt = QString::number( d->h );
-//         } else {
-//             accepted = TRUE;
-//         }
-//
-//         if ( accepted )
-//             d->h = temp;
-//
-//         if ( d->adv && txt.length() == 2 ) {
-//             setFocusSection( d->ed->focusSection()+1 );
-//             overwrite = TRUE;
-//         }
-//     }
-//     break;
-//
-//     case 1:
-//     txt = QString::number( d->m );
-//     if ( d->overwrite || txt.length() == 2 ) {
-//         if ( !outOfRange( d->h, num, d->s ) ) {
-//             accepted = TRUE;
-//             d->m = num;
-//         }
-//     } else {
-//         txt += QString::number( num );
-//         int temp = txt.toInt();
-//         if ( temp > 59 )
-//             temp = num;
-//         if ( outOfRange( d->h, temp, d->s ) )
-//             txt = QString::number( d->m );
-//         else {
-//             accepted = TRUE;
-//             d->m = temp;
-//         }
-//         if ( d->adv && txt.length() == 2 ) {
-//             setFocusSection( d->ed->focusSection()+1 );
-//             overwrite = TRUE;
-//         }
-//     }
-//     break;
-//
-//     case 2:
-//     txt = QString::number( d->s );
-//     if ( d->overwrite || txt.length() == 2 ) {
-//         if ( !outOfRange( d->h, d->m, num ) ) {
-//             accepted = TRUE;
-//             d->s = num;
-//         }
-//     } else {
-//         txt += QString::number( num );
-//         int temp = txt.toInt();
-//         if ( temp > 59 )
-//             temp = num;
-//         if ( outOfRange( d->h, d->m, temp ) )
-//             txt = QString::number( d->s );
-//         else {
-//             accepted = TRUE;
-//             d->s = temp;
-//         }
-//         if ( d->adv && txt.length() == 2 ) {
-//             setFocusSection( d->ed->focusSection()+1 );
-//             overwrite = TRUE;
-//         }
-//     }
-//     break;
-//
-//     case 3:
-//     break;
-//
-//     default:
-//     break;
-//     }
-//     d->changed = accepted;
-//     if ( accepted )
-//     emit valueChanged( time() );
-//     d->overwrite = overwrite;
-//     d->timerId = startTimer( qApp->doubleClickInterval()*4 );
-//     d->ed->repaint( d->ed->rect(), FALSE );
-// }
-//
-//
-// /*!
-//   \internal
-//
-//   Function which is called whenever the user tries to
-//   remove the first number from \a sec by pressing the backspace key.
-// */
-//
-// void QTimeEdit::removeFirstNumber( int sec )
-// {
-//     if ( sec == -1 )
-//     return;
-//     sec = d->ed->mapSection( sec );
-//     QString txt;
-//     switch( sec ) {
-//     case 0:
-//     txt = QString::number( d->h );
-//     break;
-//     case 1:
-//     txt = QString::number( d->m );
-//     break;
-//     case 2:
-//     txt = QString::number( d->s );
-//     break;
-//     }
-//     txt = txt.mid( 1, txt.length() ) + "0";
-//     switch( sec ) {
-//     case 0:
-//     d->h = txt.toInt();
-//     break;
-//     case 1:
-//     d->m = txt.toInt();
-//     break;
-//     case 2:
-//     d->s = txt.toInt();
-//     break;
-//     }
-//     d->ed->repaint( d->ed->rect(), FALSE );
-// }
-//
-// /*! \reimp
-//
-// */
-// void QTimeEdit::removeLastNumber( int sec )
-// {
-//     if ( sec == -1 )
-//     return;
-//     sec = d->ed->mapSection( sec );
-//     QString txt;
-//     switch( sec ) {
-//     case 0:
-//     txt = QString::number( d->h );
-//     break;
-//     case 1:
-//     txt = QString::number( d->m );
-//     break;
-//     case 2:
-//     txt = QString::number( d->s );
-//     break;
-//     }
-//     txt = txt.mid( 0, txt.length()-1 );
-//     switch( sec ) {
-//     case 0:
-//     d->h = txt.toInt();
-//     break;
-//     case 1:
-//     d->m = txt.toInt();
-//     break;
-//     case 2:
-//     d->s = txt.toInt();
-//     break;
-//     }
-//     d->ed->repaint( d->ed->rect(), FALSE );
-// }
-//
-// /*! \reimp
-//  */
-// void QTimeEdit::resizeEvent( QResizeEvent * )
-// {
-//     d->controls->resize( width(), height() );
-// }
-//
-// /*! \reimp
-// */
-// QSize QTimeEdit::sizeHint() const
-// {
-//     constPolish();
-//     QFontMetrics fm( font() );
-//     int fw = style().pixelMetric( QStyle::PM_DefaultFrameWidth, this );
-//     int h = fm.lineSpacing() + 2;
-//     int w = 2 + fm.width( '9' ) * 6 + fm.width( d->ed->separator() ) * 2 +
-//     d->controls->upRect().width() + fw * 4;
-//     if ( d->display & AMPM ) {
-//     if ( lAM )
-//         w += fm.width( *lAM ) + 4;
-//     else
-//         w += fm.width( QString::fromLatin1( "AM" ) ) + 4;
-//     }
-//
-//     return QSize( w, QMAX(h + fw * 2,20) ).expandedTo( QApplication::globalStrut() );
-// }
-//
-// /*! \reimp
-// */
-// QSize QTimeEdit::minimumSizeHint() const
-// {
-//     return sizeHint();
-// }
-//
-// /*!
-//     \internal
-//     Enables/disables the push buttons according to the min/max time
-//     for this widget.
-// */
-//
-// // ### Remove in 4.0?
-//
-// void QTimeEdit::updateButtons()
-// {
-//     if ( !isEnabled() )
-//     return;
-//
-//     bool upEnabled = time() < maxValue();
-//     bool downEnabled = time() > minValue();
-//
-//     d->controls->setUpEnabled( upEnabled );
-//     d->controls->setDownEnabled( downEnabled );
-// }
-
-
-class ExtDateTimeEditPrivate
+void ExtDateTimeEditPrivate::clearSection(Section s)
 {
-public:
-    bool adv;
-};
+    const char space = ' ';
+    int cursorPos = edit->cursorPosition();
+    bool blocked = edit->blockSignals(true);
+    QString t = edit->text();
+    t.replace(sectionPos(s), sectionSize(s), QString().fill(space, sectionSize(s)));
+    edit->setText(t);
+    edit->setCursorPosition(cursorPos);
+    edit->blockSignals(blocked);
+}
 
 /*!
-    \class ExtDateTimeEdit ExtDatetimeedit.h
-    \brief The ExtDateTimeEdit class combines a ExtDateEdit and QTimeEdit
-    widget into a single widget for editing datetimes.
+  \internal
 
-    \ingroup advanced
-    \ingroup time
+  Returns the size of section \a s.
+*/
 
-    ExtDateTimeEdit consists of a ExtDateEdit and QTimeEdit widget placed
-    side by side and offers the functionality of both. The user can
-    edit the date and time by using the keyboard or the arrow keys to
-    increase/decrease date or time values. The Tab key can be used to
-    move from section to section within the ExtDateTimeEdit widget, and
-    the user can be moved automatically when they complete a section
-    using setAutoAdvance(). The datetime can be set with
-    setDateTime().
+int ExtDateTimeEditPrivate::sectionSize(Section s) const
+{
+    switch (s) {
+    case FirstSection:
+    case NoSection:
+    case LastSection: return 0;
 
-    The date format is read from the system's locale settings. It is
-    set to year, month, day order if that is not possible. See
-    ExtDateEdit::setOrder() to change this. Times appear in the order
-    hours, minutes, seconds using the 24 hour clock.
+    case AmPmSection:
+    case AmPmLowerCaseSection: {
+        int lower = qMin(ExtDateTimeEdit::tr("pm").size(), ExtDateTimeEdit::tr("am").size());
+        int upper = qMin(ExtDateTimeEdit::tr("PM").size(), ExtDateTimeEdit::tr("AM").size());
+        return qMin(4, qMin(lower, upper));
+    }
 
-    It is recommended that the ExtDateTimeEdit is initialised with a
-    datetime, e.g.
-    \code
-    ExtDateTimeEdit *dateTimeEdit = new ExtDateTimeEdit( ExtDateTime::currentDateTime(), this );
-    dateTimeEdit->dateEdit()->setRange( ExtDateTime::currentDate(),
-                                       ExtDateTime::currentDate().addDays( 7 ) );
-    \endcode
-    Here we've created a new ExtDateTimeEdit set to the current date and
-    time, and set the date to have a minimum date of now and a maximum
-    date of a week from now.
+    case HourSection:
+    case MinuteSection:
+    case SecondSection:
+    case DaySection:
+    case MonthSection:
+    case YearTwoDigitsSection: return 2;
 
-    Terminology: A ExtDateEdit widget consists of three 'sections', one
-    each for the year, month and day. Similarly a QTimeEdit consists
-    of three sections, one each for the hour, minute and second. The
-    character that separates each date section is specified with
-    setDateSeparator(); similarly setTimeSeparator() is used for the
-    time sections.
+    case MonthShortNameSection:
+    case MSecSection: return 3;
 
-    \image html datetimewidgets.png "Date Time Widgets"
+    case YearSection: return 4;
 
-    \sa ExtDateEdit QTimeEdit
-*/
+    case Internal:
+    case TimeSectionMask:
+    case DateSectionMask: qWarning("Invalid section %s", sectionName(s).toLatin1().constData());
+    }
+    return -1;
+}
 
 /*!
-    Constructs an empty datetime edit with parent \a parent and called
-    \a name.
+  \internal
+
+  Returns the text of section \a s. This function operates on the
+  arg text rather than edit->text().
 */
-ExtDateTimeEdit::ExtDateTimeEdit( QWidget * parent, const char * name )
-    : QWidget( parent, name )
+
+
+QString ExtDateTimeEditPrivate::sectionText(const QString &text, Section s) const
 {
-    init();
+    const SectionNode sn = sectionNode(s);
+    return sn.section == NoSection ? QString() : text.mid(sn.pos, sectionSize(s));
 }
 
-
 /*!
-    \overload
+  \internal
 
-    Constructs a datetime edit with the initial value \a datetime,
-    parent \a parent and called \a name.
+  Parses the part of \a text that corresponds to \a s and returns
+  the value of that field. Sets *stateptr to the right state if
+  stateptr != 0.
 */
-ExtDateTimeEdit::ExtDateTimeEdit( const ExtDateTime& datetime,
-                             QWidget * parent, const char * name )
-    : QWidget( parent, name )
+
+int ExtDateTimeEditPrivate::sectionValue(Section s, QString &text, QValidator::State &state) const
 {
-    init();
-    setDateTime( datetime );
-}
+    const char space = ' ';
+    state = QValidator::Invalid;
+    int num = 0;
+    QString st = sectionText(text, s);
+    EDTEDEBUG << "sectionValue for" << sectionName(s)
+              << "with text" << text << "and st" << st;
 
+    if (st.trimmed().isEmpty()) {
+        state = QValidator::Intermediate;
+    } else {
+        const int index = sectionNode(s).pos;
+        const int size = sectionSize(s);
+        const bool done = !st.contains(space);
+        switch (s) {
+        case AmPmSection:
+        case AmPmLowerCaseSection: {
+            int ampm = findAmPm(st, s);
+            switch (ampm) {
+            case AM: // st == AM
+            case PM: // st == PM
+                num = ampm;
+                state = QValidator::Acceptable;
+                break;
+            case PossibleAM: // st => AM
+            case PossiblePM: // st => PM
+                num = ampm - 2;
+                state = QValidator::Intermediate;
+                break;
+            case PossibleBoth: // st => AM|PM
+                num = 0;
+                state = QValidator::Intermediate;
+                break;
+            case Neither:
+                state = QValidator::Invalid;
+                EDTEDEBUG << "invalid because findAmPm(" << st << ") returned -1";
+                break;
+            default:
+                EDTEDEBUGN("This should never happen (findAmPm returned %d", ampm);
+                break;
+            }
+            if (state != QValidator::Invalid) {
+                text.replace(index, size, st);
+            }
+            break;
+        }
+        case MonthShortNameSection: {
+            st = st.toLower();
+            int tmp = findMonth(st);
+            if (tmp != -1) {
+                num = tmp;
+                if (done) {
+                    state = QValidator::Acceptable;
+                    st = ExtDate::shortMonthName(num);
+                    text.replace(index, size, st);
+                } else {
+                    state = QValidator::Intermediate;
+                }
+            } else {
+                state = QValidator::Invalid;
+                EDTEDEBUG << "invalid because" << st << "doesn't match any month name";
+            }
+            break;
+        }
+        case YearTwoDigitsSection: num = 2000;
+        case YearSection:
+        case MonthSection:
+        case HourSection:
+        case MinuteSection:
+        case SecondSection:
+        case MSecSection:
+        case DaySection: {
+            bool ok;
+            num += (int)(st.toUInt(&ok));
+            if (!ok) {
+                state = QValidator::Invalid;
+                EDTEDEBUG << "invalid because" << st << "can't become a uint";
+            } else {
+                if (s == HourSection && display & AmPmSection) {
+                    bool pm = (sectionText(text, AmPmSection).toLower() == "pm");
+                    if (pm && num < 12) {
+                        num += 12;
+                    } else if (!pm && num == 12) {
+                        num = 0;
+                    } else if (num > 12) {
+                        state = QValidator::Invalid;
+                        EDTEDEBUG << "invalid because" << st << "num is" << num;
+
+                        break;
+                    }
+                }
+                if (num < absoluteMin(s) || num > absoluteMax(s)) {
+                    state = done ? QValidator::Invalid : QValidator::Intermediate;
+                    if (done)
+                        EDTEDEBUG << "invalid because" << st << "num is" << num
+                                  << "outside absoluteMin and absoluteMax" << absoluteMin(s) << absoluteMax(s);
+
+                } else {
+                    state = QValidator::Acceptable;
+                }
+            }
+            break;
+        }
+        default: qFatal("NoSection or Internal. This should never happen"); break; }
+    }
 
+    return (state != QValidator::Invalid ? num : -1);
+}
 
 /*!
-    Destroys the object and frees any allocated resources.
+  \internal
+  \reimp
 */
 
-ExtDateTimeEdit::~ExtDateTimeEdit()
+QVariant ExtDateTimeEditPrivate::validateAndInterpret(QString &input,
+                                                    int &pos, QValidator::State &state) const
 {
-    delete d;
+    const char space = ' ';
+    if (cachedText == input) {
+        state = cachedState;
+        EDTEDEBUG << "state" << state << "cachedText" << cachedText << "cachedValue" << cachedValue;
+        return cachedValue;
+    }
+    QVariant tmp;
+    SectionNode sn = {NoSection, 0};
+    int index = 0;
+
+    EDTEDEBUG << "validateAndInterpret" << input;
+    int diff = input.size() - escapedFormat.size();
+    bool specval = false;
+    if (!specialValueText.isEmpty() && input == specialValueText) {
+        specval = true;
+        state = QValidator::Acceptable;
+        tmp = minimum;
+        goto end;
+    }
+    if (diff > 0) {
+        const Section s = closestSection(pos - 1, false);
+        if (s == FirstSection && s == LastSection) {
+            EDTEDEBUG << "invalid because s ==" << sectionName(s);
+            return QValidator::Invalid;
+        }
+        sn = sectionNode(s);
+        const int sectionstart = sn.pos;
+        const int sectionsize = sectionSize(s);
+
+        QString sub = input.mid(sectionstart, sectionsize + diff);
+        if (sub.count(space) < diff) {
+            EDTEDEBUGN("sub is '%s' diff is %d sub.count is %d", sub.toLatin1().constData(), diff, sub.count(space));
+            state = QValidator::Invalid;
+            goto end;
+        }
+
+        sub.remove(space);
+        input.replace(sectionstart, sectionsize + diff, sub.leftJustified(sectionsize, space));
+    } else if (diff < 0) {
+        const Section s = closestSection(pos, false);
+        if (s == FirstSection && s == LastSection) {
+            EDTEDEBUG << "invalid because s == " << sectionName(s);
+            state = QValidator::Invalid;
+            goto end;
+        }
+        sn = sectionNode(s);
+        const int sectionstart = sn.pos;
+        const int sectionsize = sectionSize(s);
+
+        QString sub = input.mid(sectionstart, sectionsize + diff);
+        sub.remove(space);
+        input.replace(sectionstart, sectionsize + diff, sub.leftJustified(sectionsize, space));
+
+        sn = sectionNode(currentSection);
+    }
+
+    for (int i=0; i<sectionNodes.size(); ++i) {
+        sn = sectionNodes.at(i);
+        if (input.mid(index, sn.pos - index) != separators.at(i)) {
+            EDTEDEBUG << "invalid because" << input.mid(index, sn.pos - index) << "!=" << separators.at(i);
+            state = QValidator::Invalid;
+            goto end;
+        }
+        index = sn.pos + sectionSize(sn.section);
+    }
+
+    if (sn.pos + sectionSize(sn.section) < input.size()
+        && input.mid(sn.pos + sectionSize(sn.section)) != separators.last()) {
+        EDTEDEBUG << "invalid because" << input.mid(sn.pos + sectionSize(sn.section))
+                  << "!=" << separators.last();
+        state = QValidator::Invalid;
+        goto end;
+    }
+
+    {
+        int year, month, day, hour, minute, second, msec;
+        const ExtDateTime &dt = value.toDateTime();
+        year = dt.date().year();
+        month = dt.date().month();
+        day = dt.date().day();
+        hour = dt.time().hour();
+        minute = dt.time().minute();
+        second = dt.time().second();
+        msec = dt.time().msec();
+
+        state = QValidator::Acceptable;
+        for (int i=0; state != QValidator::Invalid && i<sectionNodes.size(); ++i) {
+            const Section s = sectionNodes.at(i).section;
+            QValidator::State tmpstate;
+            int num = sectionValue(s, input, tmpstate);
+            // Apple's GCC 3.3 and GCC 4.0 CVS flags a warning on qMin,
+            // so code by hand to remove the warning.
+            state = state < tmpstate ? state : tmpstate;
+
+            if (state != QValidator::Invalid) {
+                switch (s) {
+                case HourSection: hour = num; break;
+                case MinuteSection: minute = num; break;
+                case SecondSection: second = num; break;
+                case MSecSection: msec = num; break;
+                case YearTwoDigitsSection:
+                case YearSection: year = (num == 0 ? DATE_INITIAL.year() : num); break;
+                case MonthSection:
+                case MonthShortNameSection: month = qMax<int>(1, num); break;
+                case DaySection: day = qMax<int>(1, num); break;
+                case AmPmSection:
+                case AmPmLowerCaseSection: hour = (num == 0 ? hour % 12 : (hour % 12) + 12); break;
+                default:
+                    qFatal("%s found in sections validateAndInterpret. This should never happen",
+                           sectionName(s).toLatin1().constData());
+                    break;
+                }
+            }
+        }
+
+        if (state == QValidator::Invalid) {
+            tmp = getZeroVariant();
+        } else {
+            bool fixday = false;
+            if (currentSection == DaySection) {
+                cachedDay = day;
+            } else if (cachedDay > day) {
+                day = cachedDay;
+                fixday = true;
+            }
+
+            if (!ExtDate::isValid(year, month, day)) {
+                if (day < 32) {
+                    cachedDay = day;
+                } else if (day > 28 && ExtDate::isValid(year, month, 1)) {
+                    fixday = true;
+                }
+            }
+            if (fixday) {
+                day = qMin<int>(day, ExtDate(year, month, 1).daysInMonth());
+                const SectionNode &sn = sectionNode(DaySection);
+                input.replace(sn.pos, sectionSize(DaySection), QString::number(day));
+            }
+
+            EDTEDEBUG << year << month << day << hour << minute << second << msec;
+            tmp = QVariant(ExtDateTime(ExtDate(year, month, day), QTime(hour, minute, second, msec)));
+        }
+        EDTEDEBUGN("'%s' => '%s' (%s)", input.toLatin1().constData(),
+                   tmp.toString().toLatin1().constData(), stateName(state).toLatin1().constData());
+    }
+end:
+    if (tmp.toDateTime().isValid()) {
+        if (!specval && state != QValidator::Invalid && tmp < minimum) {
+            state = checkIntermediate(tmp.toDateTime(), input);
+        } else {
+            if (tmp > maximum)
+                state = QValidator::Invalid;
+            EDTEDEBUG << "not checking intermediate because tmp is" << tmp << minimum << maximum;
+        }
+    }
+    cachedText = input;
+    cachedState = state;
+    cachedValue = tmp;
+    return tmp;
 }
 
+/*!
+  \internal
+  finds the first possible monthname that \a str1 can match. Starting from \a index;
+*/
+
+int ExtDateTimeEditPrivate::findMonth(const QString &str1, int index) const
+{
+    Q_ASSERT(str1.size() == 3);
+
+    for (int month=index; month<=12; ++month) {
+        QString str2 = ExtDate::shortMonthName(month).toLower();
+        bool found = true;
+        for (int i=0; i<str1.size(); ++i) {
+            if (str1.at(i) != str2.at(i) && !str1.at(i).isSpace()) {
+                found = false;
+                break;
+            }
+        }
+        if (found)
+            return month;
+    }
+    return -1;
+}
 
 /*!
-    \reimp
+  \internal
+
+  returns
+  0 if str == ExtDateTimeEdit::tr("AM")
+  1 if str == ExtDateTimeEdit::tr("PM")
+  2 if str can become ExtDateTimeEdit::tr("AM")
+  3 if str can become ExtDateTimeEdit::tr("PM")
+  4 if str can become ExtDateTimeEdit::tr("PM") and can become ExtDateTimeEdit::tr("AM")
+  -1 can't become anything sensible
 
-    Intercepts and handles resize events which have special meaning
-    for the ExtDateTimeEdit.
 */
 
-void ExtDateTimeEdit::resizeEvent( QResizeEvent * )
+int ExtDateTimeEditPrivate::findAmPm(QString &str, ExtDateTimeEditPrivate::Section s) const
 {
-    int dw = de->sizeHint().width();
-    int tw = te->sizeHint().width();
-    int w = width();
-    int h = height();
-    int extra = w - ( dw + tw );
+    const char space = ' ';
+    const int size = sectionSize(AmPmSection);
+    Q_ASSERT(str.size() == size);
 
-    if ( tw + extra < 0 ) {
-       dw = w;
+    enum {
+        amindex = 0,
+        pmindex = 1
+    };
+    QString ampm[2];
+    if (s == AmPmSection) {
+        ampm[amindex] = ExtDateTimeEdit::tr("AM");
+        ampm[pmindex] = ExtDateTimeEdit::tr("PM");
     } else {
-       dw += 9 * extra / 16;
+        ampm[amindex] = ExtDateTimeEdit::tr("am");
+        ampm[pmindex] = ExtDateTimeEdit::tr("pm");
+    }
+    for (int i=0; i<2; ++i)
+        ampm[i].truncate(size);
+
+    EDTEDEBUG << "findAmPm" << str << ampm[0] << ampm[1];
+
+    if (str.indexOf(ampm[amindex], 0, Qt::CaseInsensitive) == 0) {
+        str = ampm[amindex];
+        return AM;
+    } else if (str.indexOf(ampm[pmindex], 0, Qt::CaseInsensitive) == 0) {
+        str = ampm[pmindex];
+        return PM;
+    } else if (str.count(space) == 0) {
+        return Neither;
     }
-    tw = w - dw;
 
-    de->setGeometry( 0, 0, dw, h );
-    te->setGeometry( dw, 0, tw, h );
+    bool broken[2] = {false, false};
+    for (int i=0; i<size; ++i) {
+        if (str.at(i) != space) {
+            for (int j=0; j<2; ++j) {
+                if (!broken[j]) {
+                    int index = ampm[j].indexOf(str.at(i));
+                    EDTEDEBUG << "looking for" << str.at(i)
+                              << "in" << ampm[j] << "and got" << index;
+                    if (index == -1) {
+                        if (str.at(i).category() == QChar::Letter_Uppercase) {
+                            index = ampm[j].indexOf(str.at(i).toLower());
+                            EDTEDEBUG << "trying with" << str.at(i).toLower()
+                                      << "in" << ampm[j] << "and got" << index;
+                        } else if (str.at(i).category() == QChar::Letter_Lowercase) {
+                            index = ampm[j].indexOf(str.at(i).toUpper());
+                            EDTEDEBUG << "trying with" << str.at(i).toUpper()
+                                      << "in" << ampm[j] << "and got" << index;
+                        }
+                        if (index == -1) {
+                            broken[j] = true;
+                            if (broken[amindex] && broken[pmindex]) {
+                                EDTEDEBUG << str << "didn't make it";
+                                return Neither;
+                            }
+                            continue;
+                        } else {
+                            str[i] = ampm[j].at(index); // fix case
+                        }
+                    }
+                    ampm[j].remove(index, 1);
+                }
+            }
+        }
+    }
+    if (!broken[pmindex] && !broken[amindex])
+        return PossibleBoth;
+    return (!broken[amindex] ? PossibleAM : PossiblePM);
 }
 
-/*! \reimp
+/*!
+  \internal
+  Max number of units that can be changed by this section.
 */
 
-QSize ExtDateTimeEdit::minimumSizeHint() const
+int ExtDateTimeEditPrivate::maxChange(ExtDateTimeEditPrivate::Section s) const
 {
-    QSize dsh = de->minimumSizeHint();
-    QSize tsh = te->minimumSizeHint();
-    return QSize( dsh.width() + tsh.width(),
-                 QMAX( dsh.height(), tsh.height() ) );
-}
+    switch (s) {
+        // Time. unit is msec
+    case MSecSection: return 999;
+    case SecondSection: return 59 * 1000;
+    case MinuteSection: return 59 * 60 * 1000;
+    case HourSection: return 59 * 60 * 60 * 1000;
 
-/*!  \internal
- */
+        // Date. unit is day
+    case DaySection: return 30;
+    case MonthShortNameSection:
+    case MonthSection: return 365 - 31;
+    case YearSection: return (7999 - 1753) * 365;
+    case YearTwoDigitsSection: return 100 * 365;
 
-void ExtDateTimeEdit::init()
-{
-    d = new ExtDateTimeEditPrivate();
-    de = new ExtDateEdit( this, "qt_datetime_dateedit" );
-    te = new Q3TimeEdit( this, "qt_datetime_timeedit" );
-    d->adv = FALSE;
-    connect( de, SIGNAL( valueChanged( const ExtDate& ) ),
-            this, SLOT( newValue( const ExtDate& ) ) );
-    connect( te, SIGNAL( valueChanged( const QTime& ) ),
-            this, SLOT( newValue( const QTime& ) ) );
-    setFocusProxy( de );
-    setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Fixed );
+    default: break;
+    }
+    qFatal("%s passed to maxChange. This should never happen", sectionName(s).toLatin1().constData());
+    return -1;
 }
 
-/*! \reimp
- */
 
-QSize ExtDateTimeEdit::sizeHint() const
+int ExtDateTimeEditPrivate::multiplier(ExtDateTimeEditPrivate::Section s) const
 {
-    constPolish();
-    QSize dsh = de->sizeHint();
-    QSize tsh = te->sizeHint();
-    return QSize( dsh.width() + tsh.width(),
-                 QMAX( dsh.height(), tsh.height() ) );
+    switch (s) {
+        // Time. unit is msec
+    case MSecSection: return 1;
+    case SecondSection: return 1000;
+    case MinuteSection: return 60 * 1000;
+    case HourSection: return 60 * 60 * 1000;
+
+        // Date. unit is day
+    case DaySection: return 1;
+    case MonthShortNameSection:
+    case MonthSection: return 30;
+    case YearSection: return 365;
+    case YearTwoDigitsSection: return 365;
+
+    default: break;
+    }
+    qFatal("%s passed to multiplier. This should never happen", sectionName(s).toLatin1().constData());
+    return -1;
 }
 
 /*!
-    \property ExtDateTimeEdit::dateTime
-    \brief the editor's datetime value
+  \internal Get a number that str can become which is between min
+  and max or -1 if this is not possible.
+*/
+
+QString ExtDateTimeEditPrivate::sectionFormat(int s) const
+{
+    switch (s) {
+    case AmPmSection: return QLatin1String("AP");
+    case MSecSection: return QLatin1String("zzz");
+    case SecondSection: return QLatin1String("ss");
+    case MinuteSection: return QLatin1String("mm");
+    case HourSection: return QLatin1String("hh");
+    case AmPmLowerCaseSection: return QLatin1String("ap");
+    case DaySection: return QLatin1String("dd");
+    case MonthSection: return QLatin1String("MM");
+    case YearSection: return QLatin1String("yyyy");
+    case MonthShortNameSection: return QLatin1String("MMM");
+    case YearTwoDigitsSection: return QLatin1String("yy");
+    default: break;
+    }
+    qFatal("%s passed to sectionFormat. This should never happen", sectionName(s).toLatin1().constData());
+    return QString();
+}
 
-    The datetime edit's datetime which may be an invalid datetime.
+/*!
+  \internal Get a number that str can become which is between min
+  and max or -1 if this is not possible.
 */
 
-void ExtDateTimeEdit::setDateTime( const ExtDateTime & dt )
+int ExtDateTimeEditPrivate::potentialValue(const QString &str, int min, int max, Section s) const
 {
-    if ( dt.isValid() ) {
-       de->setDate( dt.date() );
-       te->setTime( dt.time() );
-       emit valueChanged( dt );
+    int size = sectionSize(s);
+    if (s == YearTwoDigitsSection) {
+        min -= 2000;
+        max -= 2000; // doesn't matter if max is -1 checking for < 0
+    }
+    QString simplified = str.simplified();
+    Q_ASSERT(str != simplified);
+    if (simplified.isEmpty()) {
+        return min + (s == YearTwoDigitsSection ? 2000 : 0);
+    } else if (simplified.toInt() > max && max >= 0) {
+        return -1;
+    } else {
+        QString temp = simplified;
+        while (temp.size() < size)
+            temp.prepend(QLatin1Char('9'));
+        int t = temp.toInt();
+        if (t < min) {
+            return -1;
+        } else if (t <= max || max < 0) {
+            return t + (s == YearTwoDigitsSection ? 2000 : 0);
+        }
     }
-}
 
-ExtDateTime ExtDateTimeEdit::dateTime() const
-{
-    return ExtDateTime( de->date(), te->time() );
+    int ret = potentialValueHelper(simplified, min, max, size);
+    if (ret == -1)
+        return -1;
+    return ret + (s == YearTwoDigitsSection ? 2000 : 0);
 }
 
 /*!
-    \fn void ExtDateTimeEdit::valueChanged( const ExtDateTime& datetime )
-
-    This signal is emitted every time the date or time changes. The \a
-    datetime argument is the new datetime.
+  \internal internal helper function called by potentialValue
 */
 
-
-/*! \internal
-
-  Re-emits the value \a d.
- */
-
-void ExtDateTimeEdit::newValue( const ExtDate& )
+int ExtDateTimeEditPrivate::potentialValueHelper(const QString &str, int min, int max, int size) const
 {
-    ExtDateTime dt = dateTime();
-    emit valueChanged( dt );
-}
-
-/*! \internal
-  \overload
-  Re-emits the value \a t.
- */
+    if (str.size() == size) {
+        const int val = str.toInt();
+        if (val < min || val > max)
+            return -1;
+        EDTEDEBUG << "SUCCESS" << val << "is >=" << min << "and <=" << max;
+        return val;
+    }
 
-void ExtDateTimeEdit::newValue( const QTime& )
-{
-    ExtDateTime dt = dateTime();
-    emit valueChanged( dt );
+    for (int i=0; i<=str.size(); ++i) {
+        for (int j=0; j<10; ++j) {
+            QString tmp = str;
+            if (i == str.size()) {
+                tmp.append(QChar('0' + j));
+            } else {
+                tmp.insert(i, QChar('0' + j));
+            }
+            int ret = potentialValueHelper(tmp, min, max, size);
+            if (ret != -1)
+                return ret;
+        }
+    }
+    return -1;
 }
 
-
 /*!
-    Sets the auto advance property of the editor to \a advance. If set
-    to TRUE, the editor will automatically advance focus to the next
-    date or time section if the user has completed a section.
+  \internal
+  \reimp
 */
 
-void ExtDateTimeEdit::setAutoAdvance( bool advance )
+QString ExtDateTimeEditPrivate::textFromValue(const QVariant &f) const
 {
-    de->setAutoAdvance( advance );
-    te->setAutoAdvance( advance );
+    Q_Q(const ExtDateTimeEdit);
+    return q->textFromDateTime(f.toDateTime());
 }
 
 /*!
-    Returns TRUE if auto-advance is enabled, otherwise returns FALSE.
-
-    \sa setAutoAdvance()
+  \internal
+  \reimp
 */
 
-bool ExtDateTimeEdit::autoAdvance() const
+QVariant ExtDateTimeEditPrivate::valueFromText(const QString &f) const
 {
-    return de->autoAdvance();
+    Q_Q(const ExtDateTimeEdit);
+    return QVariant(q->dateTimeFromText(f));
 }
 
 /*!
-    \fn ExtDateEdit* ExtDateTimeEdit::dateEdit()
-
-    Returns the internal widget used for editing the date part of the
-    datetime.
-*/
+  \internal Returns whether \a str is a string which value cannot be
+  parsed but still might turn into something valid.
+*/
+
+QValidator::State ExtDateTimeEditPrivate::checkIntermediate(const ExtDateTime &dt,
+                                                          const QString &s) const
+{
+    const char space = ' ';
+
+    Q_ASSERT(dt < minimum);
+
+    bool found = false;
+    for (int i=0; i<sectionNodes.size(); ++i) {
+        const SectionNode sn = sectionNodes.at(i);
+        QString t = sectionText(s, sn.section).toLower();
+        if (t.contains(space)) {
+            if (found) {
+                EDTEDEBUG << "Invalid because no spaces";
+                return QValidator::Invalid;
+            }
+            found = true;
+            switch (sn.section) {
+            case MonthShortNameSection: {
+                int tmp = dt.date().month();
+                // I know the first possible month makes the date too early
+                while ((tmp = findMonth(t, tmp + 1)) != -1) {
+                    const QVariant copy(dt.addMonths(tmp - dt.date().month()));
+                    if (copy >= minimum && copy <= maximum)
+                        break;
+                }
+                if (tmp == -1)
+                    return QValidator::Invalid;
+            }
+            case AmPmSection:
+            case AmPmLowerCaseSection:
+                if (t.count(space) == 2 || t.contains('m')) {
+                    const QVariant copy(dt.addSecs(12 * 60 * 60));
+                    if (copy >= minimum && copy <= maximum)
+                        break;
+                }
+                return QValidator::Invalid;
+            default: {
+                int toMin;
+                int toMax;
+                int multi = multiplier(sn.section);
+
+                if (sn.section & TimeSectionMask) {
+                    if (dt.daysTo(minimum.toDateTime()) != 0) {
+                        EDTEDEBUG << "if (dt.daysTo(minimum.toDateTime()) != 0)" << dt.daysTo(minimum.toDateTime());
+                        return QValidator::Invalid;
+                    }
+                    toMin = dt.time().msecsTo(minimum.toDateTime().time());
+                    if (dt.daysTo(maximum.toDateTime()) > 0) {
+                        toMax = -1; // can't get to max
+                    } else {
+                        toMax = dt.time().msecsTo(maximum.toDateTime().time());
+                    }
+                } else {
+                    toMin = dt.daysTo(minimum.toDateTime());
+                    toMax = dt.daysTo(maximum.toDateTime());
+                }
+                int maxChange = ExtDateTimeEditPrivate::maxChange(sn.section);
+                int maxChangeUnits = maxChange * multi;
+                if (toMin > maxChangeUnits) {
+                    EDTEDEBUG << "invalid because toMin > maxChangeUnits" << toMin
+                              << maxChangeUnits << t << dt << minimum.toDateTime()
+                              << multi;
+
+                    return QValidator::Invalid;
+                } else if (toMax > maxChangeUnits) {
+                    toMax = -1; // can't get to max
+                }
+
+                int min = getDigit(minimum, sn.section);
+                int max = toMax != -1 ? getDigit(maximum, sn.section) : -1;
+                int tmp = potentialValue(t, min, max, sn.section);
+                EDTEDEBUG << tmp << t << min << max << sectionName(sn.section)  << minimum.toDate() << maximum.toDate();
+                if (tmp == -1) {
+                    EDTEDEBUG << "invalid because potentialValue(" << t << min << max
+                              << sectionName(sn.section) << "returned" << tmp;
+                    return QValidator::Invalid;
+                }
+
+                QVariant var(dt);
+                setDigit(var, sn.section, tmp);
+                if (var > maximum) {
+                    EDTEDEBUG << "invalid because" << var.toString() << ">" << maximum.toString();
+                    return QValidator::Invalid;
+                }
+                break; }
+            }
+        }
+    }
+    return found ? QValidator::Intermediate : QValidator::Invalid;
+}
 
 /*!
-    \fn QTimeEdit* ExtDateTimeEdit::timeEdit()
+  \internal
+  For debugging. Returns the name of the section \a s.
+*/
+
+QString ExtDateTimeEditPrivate::sectionName(int s) const
+{
+    switch (s) {
+    case ExtDateTimeEditPrivate::AmPmSection: return "AmPmSection";
+    case ExtDateTimeEditPrivate::AmPmLowerCaseSection: return "AmPmLowerCaseSection";
+    case ExtDateTimeEditPrivate::DaySection: return "DaySection";
+    case ExtDateTimeEditPrivate::HourSection: return "HourSection";
+    case ExtDateTimeEditPrivate::MSecSection: return "MSecSection";
+    case ExtDateTimeEditPrivate::MinuteSection: return "MinuteSection";
+    case ExtDateTimeEditPrivate::MonthSection: return "MonthSection";
+    case ExtDateTimeEditPrivate::MonthShortNameSection: return "MonthShortNameSection";
+    case ExtDateTimeEditPrivate::SecondSection: return "SecondSection";
+    case ExtDateTimeEditPrivate::YearSection: return "YearSection";
+    case ExtDateTimeEditPrivate::YearTwoDigitsSection: return "YearTwoDigitsSection";
+    case ExtDateTimeEditPrivate::NoSection: return "NoSection";
+    case ExtDateTimeEditPrivate::FirstSection: return "FirstSection";
+    case ExtDateTimeEditPrivate::LastSection: return "LastSection";
+    default: return "Unknown section " + QString::number(s);
+    }
+}
 
-    Returns the internal widget used for editing the time part of the
-    datetime.
+/*!
+  \internal
+  For debugging. Returns the name of the state \a s.
 */
 
+QString ExtDateTimeEditPrivate::stateName(int s) const
+{
+    switch (s) {
+    case QValidator::Invalid: return "Invalid";
+    case QValidator::Intermediate: return "Intermediate";
+    case QValidator::Acceptable: return "Acceptable";
+    default: return "Unknown state " + QString::number(s);
+    }
+}
+
 #include "extdatetimeedit.moc"
 
-#endif
+#endif // QT_NO_DATETIMEEDIT
+
+#endif //0
index c636356fa289414cf9a2327ccfca0536012d4cec..37171572720028ab02cf2c99b64ea3c94378dbc2 100644 (file)
+/*****  --==>> Commenting out entire class.  
+See extdatetimeedit.cpp for details.
+******/
+
+#if 0
+--- COMMENTING OUT ENTIRE CLASS ---
+
 /****************************************************************************
 **
+** Copyright (C) 1992-2005 Trolltech AS. All rights reserved.
 **
-** Definition of date and time edit classes
-**
-** Created : 001103
-**
-** Original QDateTimeEdit Copyright (C) 2000 Trolltech AS.  All rights reserved.
+** This file is part of the QtGui module of the Qt Toolkit.
 **
-** >> modifications to introduce ExtDate (C) 2004 Jason Harris <jharris@30doradus.org>
-** >> ExtDate modifications are licensed under the GPL: http://www.gnu.org/licenses/gpl.html
+** This file may be used under the terms of the GNU General Public
+** License version 2.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of
+** this file.  Please review the following information to ensure GNU
+** General Public Licensing requirements will be met:
+** http://www.trolltech.com/products/qt/opensource.html
 **
-** This file may be distributed and/or modified under the terms of the
-** GNU General Public License version 2 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file.
+** If you are unsure which license is appropriate for your use, please
+** review the following information:
+** http://www.trolltech.com/products/qt/licensing.html or contact the
+** sales department at sales@trolltech.com.
 **
 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 **
-** See http://www.trolltech.com/gpl/ for GPL licensing information.
-**
-**********************************************************************/
+****************************************************************************/
 
 #ifndef EXTDATETIMEEDIT_H
 #define EXTDATETIMEEDIT_H
 
-#ifndef QT_H
-#include <qwidget.h>
-#include <qstring.h>
-#endif // QT_H
-
 #include "extdatetime.h"
-//Added by qt3to4:
-#include <QMouseEvent>
-#include <QTimerEvent>
-#include <QResizeEvent>
-#include <QEvent>
-#include <QPaintEvent>
+#include <QtGui/qabstractspinbox.h>
 
-#ifndef QT_NO_DATETIMEEDIT
+//JH: Comnmented out
+//QT_MODULE(Gui)
 
-class Q3TimeEdit;
+#ifndef QT_NO_DATETIMEEDIT
 
-class ExtDateTimeEditBase : public QWidget
+class ExtDateTimeEditPrivate;
+class ExtDateTimeEdit : public QAbstractSpinBox
 {
     Q_OBJECT
-public:
-    ExtDateTimeEditBase( QWidget* parent=0, const char* name=0 )
-       : QWidget( parent, name ) {}
 
-    virtual bool setFocusSection( int sec ) = 0;
-    virtual QString sectionFormattedText( int sec ) = 0;
-    virtual void addNumber( int sec, int num ) = 0;
-    virtual void removeLastNumber( int sec ) = 0;
-
-public slots:
-    virtual void stepUp() = 0;
-    virtual void stepDown() = 0;
-
-private:
-#if defined(Q_DISABLE_COPY) // Disabled copy constructor and operator=
-    ExtDateTimeEditBase( const ExtDateTimeEditBase & );
-    ExtDateTimeEditBase &operator=( const ExtDateTimeEditBase & );
-#endif
-};
-
-class ExtDateEditPrivate;
-
-class KDE_EXPORT ExtDateEdit : public ExtDateTimeEditBase
-{
-    Q_OBJECT
-    Q_ENUMS( Order )
-    Q_PROPERTY( Order order READ order WRITE setOrder )
-//    Q_PROPERTY( ExtDate date READ date WRITE setDate )
-    Q_PROPERTY( bool autoAdvance READ autoAdvance WRITE setAutoAdvance )
-//    Q_PROPERTY( ExtDate maxValue READ maxValue WRITE setMaxValue )
-//    Q_PROPERTY( ExtDate minValue READ minValue WRITE setMinValue )
+/* JH: commenting out designer macros
+    Q_ENUMS(Section)
+    Q_FLAGS(Sections)
+    Q_PROPERTY(QDateTime dateTime READ dateTime WRITE setDateTime NOTIFY dateTimeChanged)
+    Q_PROPERTY(QDate date READ date WRITE setDate NOTIFY dateChanged)
+    Q_PROPERTY(QTime time READ time WRITE setTime NOTIFY timeChangedu)
+    Q_PROPERTY(QDate maximumDate READ maximumDate WRITE setMaximumDate RESET clearMaximumDate)
+    Q_PROPERTY(QDate minimumDate READ minimumDate WRITE setMinimumDate RESET clearMinimumDate)
+    Q_PROPERTY(QTime maximumTime READ maximumTime WRITE setMaximumTime RESET clearMaximumTime)
+    Q_PROPERTY(QTime minimumTime READ minimumTime WRITE setMinimumTime RESET clearMinimumTime)
+    Q_PROPERTY(Section currentSection READ currentSection WRITE setCurrentSection)
+    Q_PROPERTY(Sections displayedSections READ displayedSections)
+    Q_PROPERTY(QString displayFormat READ displayFormat WRITE setDisplayFormat)
+*/
 
 public:
-    ExtDateEdit( QWidget* parent=0,  const char* name=0 );
-    ExtDateEdit( const ExtDate& date, QWidget* parent=0,  const char* name=0 );
-    ~ExtDateEdit();
-
-    enum Order { DMY /**< Day-Month-Year */, 
-      MDY /**< Month-Day-Year */, 
-      YMD /**< Year-Month-Day, also the default */, 
-      YDM /**< Year-Day-Month @deprecated Included for completeness. */ };
+    enum Section {
+        NoSection = 0x0000,
+        AmPmSection = 0x0001,
+        MSecSection = 0x0002,
+        SecondSection = 0x0004,
+        MinuteSection = 0x0008,
+        HourSection   = 0x0010,
+        DaySection    = 0x0100,
+        MonthSection  = 0x0200,
+        YearSection   = 0x0400,
+        TimeSections_Mask = AmPmSection|MSecSection|SecondSection|MinuteSection|HourSection,
+        DateSections_Mask = DaySection|MonthSection|YearSection
+    };
+
+    Q_DECLARE_FLAGS(Sections, Section)
+
+    explicit ExtDateTimeEdit(QWidget *parent = 0);
+    explicit ExtDateTimeEdit(const ExtDateTime &dt, QWidget *parent = 0);
+    explicit ExtDateTimeEdit(const ExtDate &d, QWidget *parent = 0);
+    explicit ExtDateTimeEdit(const QTime &t, QWidget *parent = 0);
 
-    QSize sizeHint() const;
-    QSize minimumSizeHint() const;
-
-public slots:
-    virtual void setDate( const ExtDate& date );
-
-public:
+    ExtDateTime dateTime() const;
     ExtDate date() const;
-    virtual void setOrder( Order order );
-    Order order() const;
-    virtual void setAutoAdvance( bool advance );
-    bool autoAdvance() const;
-
-    virtual void setMinValue( const ExtDate& d ) { setRange( d, maxValue() ); }
-    ExtDate minValue() const;
-    virtual void setMaxValue( const ExtDate& d ) { setRange( minValue(), d ); }
-    ExtDate maxValue() const;
-    virtual void setRange( const ExtDate& min, const ExtDate& max );
-    QString separator() const;
-    virtual void setSeparator( const QString& s );
-
-    // Make removeFirstNumber() virtual in ExtDateTimeEditBase in 4.0
-    void removeFirstNumber( int sec );
-
-signals:
-    void valueChanged( const ExtDate& date );
+    QTime time() const;
 
-protected:
-    bool event( QEvent *e );
-    void timerEvent( QTimerEvent * );
-    void resizeEvent( QResizeEvent * );
-    void stepUp();
-    void stepDown();
-    QString sectionFormattedText( int sec );
-    void addNumber( int sec, int num );
-
-    void removeLastNumber( int sec );
-    bool setFocusSection( int s );
-
-    virtual void setYear( int year );
-    virtual void setMonth( int month );
-    virtual void setDay( int day );
-    virtual void fix();
-    virtual bool outOfRange( int y, int m, int d ) const;
-
-protected slots:
-    void updateButtons();
+    ExtDate minimumDate() const;
+    void setMinimumDate(const ExtDate &min);
+    void clearMinimumDate();
 
-private:
-    void init();
-    int sectionOffsetEnd( int sec ) const;
-    int sectionLength( int sec ) const;
-    QString sectionText( int sec ) const;
-    ExtDateEditPrivate* d;
-
-#if defined(Q_DISABLE_COPY)
-    ExtDateEdit( const ExtDateEdit & );
-    ExtDateEdit &operator=( const ExtDateEdit & );
-#endif
-};
+    ExtDate maximumDate() const;
+    void setMaximumDate(const ExtDate &max);
+    void clearMaximumDate();
 
-// class QTimeEditPrivate;
-//
-// class Q_EXPORT QTimeEdit : public ExtDateTimeEditBase
-// {
-//     Q_OBJECT
-//     Q_SETS( Display )
-//     Q_PROPERTY( QTime time READ time WRITE setTime )
-//     Q_PROPERTY( bool autoAdvance READ autoAdvance WRITE setAutoAdvance )
-//     Q_PROPERTY( QTime maxValue READ maxValue WRITE setMaxValue )
-//     Q_PROPERTY( QTime minValue READ minValue WRITE setMinValue )
-//     Q_PROPERTY( Display display READ display WRITE setDisplay )
-//
-// public:
-//     enum Display {
-//     Hours   = 0x01,
-//     Minutes = 0x02,
-//     Seconds = 0x04,
-//     /*Reserved = 0x08,*/
-//     AMPM    = 0x10
-//     };
-//
-//     QTimeEdit( QWidget* parent=0,  const char* name=0 );
-//     QTimeEdit( const QTime& time, QWidget* parent=0,  const char* name=0 );
-//     ~QTimeEdit();
-//
-//     QSize sizeHint() const;
-//     QSize minimumSizeHint() const;
-//
-// public slots:
-//     virtual void setTime( const QTime& time );
-//
-// public:
-//     QTime time() const;
-//     virtual void setAutoAdvance( bool advance );
-//     bool autoAdvance() const;
-//
-//     virtual void setMinValue( const QTime& d ) { setRange( d, maxValue() ); }
-//     QTime minValue() const;
-//     virtual void setMaxValue( const QTime& d ) { setRange( minValue(), d ); }
-//     QTime maxValue() const;
-//     virtual void setRange( const QTime& min, const QTime& max );
-//     QString separator() const;
-//     virtual void setSeparator( const QString& s );
-//
-//     uint display() const;
-//     void setDisplay( uint disp );
-//
-//     // Make removeFirstNumber() virtual in ExtDateTimeEditBase in 4.0
-//     void removeFirstNumber( int sec );
-//
-// signals:
-//     void valueChanged( const QTime& time );
-//
-// protected:
-//     bool event( QEvent *e );
-//     void timerEvent( QTimerEvent *e );
-//     void resizeEvent( QResizeEvent * );
-//     void stepUp();
-//     void stepDown();
-//     QString sectionFormattedText( int sec );
-//     void addNumber( int sec, int num );
-//     void removeLastNumber( int sec );
-//     bool setFocusSection( int s );
-//
-//     virtual bool outOfRange( int h, int m, int s ) const;
-//     virtual void setHour( int h );
-//     virtual void setMinute( int m );
-//     virtual void setSecond( int s );
-//
-// protected slots:
-//     void updateButtons();
-//
-// private:
-//     void init();
-//     QString sectionText( int sec );
-//     QTimeEditPrivate* d;
-//
-// #if defined(Q_DISABLE_COPY)
-//     QTimeEdit( const QTimeEdit & );
-//     QTimeEdit &operator=( const QTimeEdit & );
-// #endif
-// };
-//
+    void setDateRange(const ExtDate &min, const ExtDate &max);
 
-class ExtDateTimeEditPrivate;
+    QTime minimumTime() const;
+    void setMinimumTime(const QTime &min);
+    void clearMinimumTime();
 
-class KDE_EXPORT ExtDateTimeEdit : public QWidget
-{
-    Q_OBJECT
-//    Q_PROPERTY( ExtDateTime dateTime READ dateTime WRITE setDateTime )
+    QTime maximumTime() const;
+    void setMaximumTime(const QTime &max);
+    void clearMaximumTime();
 
-public:
-    ExtDateTimeEdit( QWidget* parent=0, const char* name=0 );
-    ExtDateTimeEdit( const ExtDateTime& datetime, QWidget* parent=0,
-                  const char* name=0 );
-    ~ExtDateTimeEdit();
+    void setTimeRange(const QTime &min, const QTime &max);
 
-    QSize sizeHint() const;
-    QSize minimumSizeHint() const;
+    Sections displayedSections() const;
+    Section currentSection() const;
+    void setCurrentSection(Section section);
 
-public slots:
-    virtual void setDateTime( const ExtDateTime & dt );
+    QString sectionText(Section s) const;
 
-public:
-    ExtDateTime dateTime() const;
+    QString displayFormat() const;
+    void setDisplayFormat(const QString &format);
 
-    ExtDateEdit* dateEdit() { return de; }
-    Q3TimeEdit* timeEdit() { return te; }
+    QSize sizeHint() const;
 
-    virtual void setAutoAdvance( bool advance );
-    bool autoAdvance() const;
+    virtual void clear();
+    virtual void stepBy(int steps);
 
+    bool event(QEvent *e);
 signals:
-    void valueChanged( const ExtDateTime& datetime );
+    void dateTimeChanged(const ExtDateTime &date);
+    void timeChanged(const QTime &date);
+    void dateChanged(const ExtDate &date);
 
-protected:
-    // ### make init() private in Qt 4.0
-    void init();
-    void resizeEvent( QResizeEvent * );
-
-protected slots:
-    // ### make these two functions private in Qt 4.0,
-    //     and merge them into one with no parameter
-    void newValue( const ExtDate& d );
-    void newValue( const QTime& t );
+public slots:
+    void setDateTime(const ExtDateTime &dateTime);
+    void setDate(const ExtDate &date);
+    void setTime(const QTime &time);
 
-private:
-    ExtDateEdit* de;
-    Q3TimeEdit* te;
-    ExtDateTimeEditPrivate* d;
-
-#if defined(Q_DISABLE_COPY)
-    ExtDateTimeEdit( const ExtDateTimeEdit & );
-    ExtDateTimeEdit &operator=( const ExtDateTimeEdit & );
-#endif
-};
+protected:
+    virtual void keyPressEvent(QKeyEvent *e);
+    virtual void wheelEvent(QWheelEvent *e);
+    virtual void focusInEvent(QFocusEvent *e);
+    virtual bool focusNextPrevChild(bool next);
+    virtual QValidator::State validate(QString &input, int &pos) const;
+    virtual ExtDateTime dateTimeFromText(const QString &text) const;
+    virtual QString textFromDateTime(const ExtDateTime &dt) const;
+    virtual StepEnabled stepEnabled() const;
 
-class QNumberSection
-{
-public:
-    QNumberSection( int selStart = 0, int selEnd = 0, bool separat = TRUE, int actual = -1 )
-       : selstart( selStart ), selend( selEnd ), act( actual ), sep( separat )
-    {}
-    int selectionStart() const { return selstart; }
-    void setSelectionStart( int s ) { selstart = s; }
-    int selectionEnd() const { return selend; }
-    void setSelectionEnd( int s ) { selend = s; }
-    int width() const { return selend - selstart; }
-    int index() const { return act; }
-    bool separator() const { return sep; }
-    Q_DUMMY_COMPARISON_OPERATOR( QNumberSection )
 private:
-    int selstart :12;
-    int selend  :12;
-    int act     :7;
-    bool sep    :1;
+    Q_DECLARE_PRIVATE(ExtDateTimeEdit)
+    Q_DISABLE_COPY(ExtDateTimeEdit)
 };
 
-class ExtDateTimeEditorPrivate;
+//JH: Don't need to re-do QTimeEdit
+//class Q_GUI_EXPORT QTimeEdit : public ExtDateTimeEdit
+//{
+//    Q_OBJECT
+//public:
+//    QTimeEdit(QWidget *parent = 0);
+//    QTimeEdit(const QTime &t, QWidget *parent = 0);
+//};
 
-class ExtDateTimeEditor : public QWidget
+class ExtDateEdit : public ExtDateTimeEdit
 {
     Q_OBJECT
 public:
-    ExtDateTimeEditor( ExtDateTimeEditBase * parent=0,
-                      const char * name=0 );
-    ~ExtDateTimeEditor();
-
-//    void setControlWidget( ExtDateTimeEditBase * widget );
-//    ExtDateTimeEditBase * controlWidget() const;
-
-    void setSeparator( const QString& s );
-    QString separator() const;
+    ExtDateEdit(QWidget *parent = 0);
+    ExtDateEdit(const ExtDate &t, QWidget *parent = 0);
+};
 
-    int  focusSection() const;
-    bool setFocusSection( int s );
-    void appendSection( const QNumberSection& sec );
-    void clearSections();
-    void setSectionSelection( int sec, int selstart, int selend );
-    bool eventFilter( QObject *o, QEvent *e );
-    int  sectionAt( const QPoint &p );
-    int mapSection( int sec );
+Q_DECLARE_OPERATORS_FOR_FLAGS(ExtDateTimeEdit::Sections)
 
-protected:
-    void init();
-    bool event( QEvent *e );
-    void resizeEvent( QResizeEvent * );
-    void paintEvent( QPaintEvent * );
-    void mousePressEvent( QMouseEvent *e );
 
-private:
-    ExtDateTimeEditBase* cw;
-    ExtDateTimeEditorPrivate* d;
-};
+#endif // QT_NO_DATETIMEEDIT
+#endif // EXTDATETIMEEDIT_H
 
-#endif
-#endif
+#endif //0
index 77ba9ac86352c1056213a3c300a676c525539fb7..238760a307c19cb4d63223810e6cddcd89f97a3a 100644 (file)
 */
 
 
-#include <qcombobox.h>
-#include <qlayout.h>
-#include <qlineedit.h>
+#include <QComboBox>
+//#include <QLineEdit>
 //Added by qt3to4:
 #include <QHBoxLayout>
+#include <QSpinBox>
 
 #include <knuminput.h>
 #include <kdialog.h>
@@ -38,7 +38,7 @@ public:
   ExtDateWidgetSpinBox(int min, int max, QWidget *parent)
     : QSpinBox(min, max, 1, parent)
   {
-     editor()->setAlignment(AlignRight);
+     setAlignment(Qt::AlignRight);
   }
 };
 
index b21e228baf100f4767224fbf466d59d1724893c2..16456df98fec26843f4d78c502a7c5381debb8aa 100644 (file)
@@ -53,9 +53,9 @@ void test2_unit(int y, int m, int d)
        int q_day_of_year = q.dayOfYear();
        int e_day_of_year = e.dayOfYear();
        std::cout << "(" << y << ", " << m << ", " << d << ") ::  "
-                       << q.toString("dd.MMM.yyyy").local8Bit() << "  :  "
+                       << q.toString("dd.MMM.yyyy").toLocal8Bit().data() << "  :  "
                        << q.dayOfWeek() << " : " << q_week_number << " : " << q_day_of_year << " :: "
-                       << e.toString("%d.%b.%Y").local8Bit() << " : "
+                       << e.toString("%d.%b.%Y").toLocal8Bit().data() << " : "
                        << e.dayOfWeek() << " : " << e_week_number << " : " << e_day_of_year << std::endl;
 }
 
@@ -132,9 +132,9 @@ void test3_unit(int y, int m, int d, int dm)
        ExtDate e(y, m, d);
        QDate q2 = q.addMonths(dm);
        ExtDate e2 = e.addMonths(dm);
-       std::cout << e.toString("%d.%b.%Y").local8Bit() << " + " << dm
-               << " months :: ExtDate : " << e2.toString("%d.%b.%Y").local8Bit()
-               << "   QDate : " << q2.toString("dd.MMM.yyyy").local8Bit() << std::endl;
+       std::cout << e.toString("%d.%b.%Y").toLocal8Bit().data() << " + " << dm
+               << " months :: ExtDate : " << e2.toString("%d.%b.%Y").toLocal8Bit().data()
+               << "   QDate : " << q2.toString("dd.MMM.yyyy").toLocal8Bit().data() << std::endl;
 }
 
 void test3()
@@ -161,9 +161,9 @@ void test4_unit(int y, int m, int d, int dy)
        ExtDate e(y, m, d);
        QDate   q2 = q.addYears(dy);
        ExtDate e2 = e.addYears(dy);
-       std::cout << e.toString("%d.%m.%Y").local8Bit() << " + " << dy << " years :: ExtDate : "
-               << e2.toString().local8Bit() << "   QDate : "
-               << q2.toString().local8Bit() << std::endl;
+       std::cout << e.toString("%d.%m.%Y").toLocal8Bit().data() << " + " << dy << " years :: ExtDate : "
+               << e2.toString().toLocal8Bit().data() << "   QDate : "
+               << q2.toString().toLocal8Bit().data() << std::endl;
 }
 
 void test4()
@@ -193,11 +193,11 @@ void test5_unit(int y, int m, int d, const char *qformat, const char *eformat)
        ExtDate e(y, m, d);
 
        if ( QString(qformat) == "<default>" )
-               std::cout << eformat << " : " << e.toString().local8Bit() << " :: "
-                               << qformat << " : " << q.toString().local8Bit() << std::endl;
+               std::cout << eformat << " : " << e.toString().toLocal8Bit().data() << " :: "
+                               << qformat << " : " << q.toString().toLocal8Bit().data() << std::endl;
        else
-               std::cout << eformat << " : " << e.toString(eformat).local8Bit() << " :: "
-                               << qformat << " : " << q.toString(qformat).local8Bit() << std::endl;
+               std::cout << eformat << " : " << e.toString(eformat).toLocal8Bit().data() << " :: "
+                               << qformat << " : " << q.toString(qformat).toLocal8Bit().data() << std::endl;
 }
 
 void test5()
@@ -279,16 +279,16 @@ void test7()
        std::cout << "Express the current date:\n" << std::endl;
        QDate q = QDate::currentDate(Qt::LocalTime);
        ExtDate e = ExtDate::currentDate(Qt::TimeSpec(Qt::LocalTime));
-       std::cout << "Qt::LocalTime :: ExtDate : " << e.toString().local8Bit() << "   QDate : "
-               << q.toString().local8Bit() << std::endl;
+       std::cout << "Qt::LocalTime :: ExtDate : " << e.toString().toLocal8Bit().data() << "   QDate : "
+               << q.toString().toLocal8Bit().data() << std::endl;
        q = QDate::currentDate(Qt::UTC);
        e = ExtDate::currentDate(Qt::UTC);
-       std::cout << "Qt::UTC       :: ExtDate : " << e.toString().local8Bit() << "   QDate : "
-               << q.toString().local8Bit() << std::endl;
+       std::cout << "Qt::UTC       :: ExtDate : " << e.toString().toLocal8Bit().data() << "   QDate : "
+               << q.toString().toLocal8Bit().data() << std::endl;
        q = QDate::currentDate();
        e = ExtDate::currentDate();
-       std::cout << "<default>     :: ExtDate : " << e.toString().local8Bit() << "   QDate : "
-               << q.toString().local8Bit() << std::endl;
+       std::cout << "<default>     :: ExtDate : " << e.toString().toLocal8Bit().data() << "   QDate : "
+               << q.toString().toLocal8Bit().data() << std::endl;
        std::cout << "--------------------" << std::endl;
 }
 
@@ -301,8 +301,8 @@ void test8() {
 
                        QDate   test1( 2004, m, d );
                        ExtDate test2( 2004, m, d );
-                       std::cout << test1.toString( "ddd dd.MMM.yy" ).local8Bit() << "  :  "
-               << test2.toString( "%a %d.%b.%y" ).local8Bit() << std::endl;
+                       std::cout << test1.toString( "ddd dd.MMM.yy" ).toLocal8Bit().data() << "  :  "
+               << test2.toString( "%a %d.%b.%y" ).toLocal8Bit().data() << std::endl;
                }
        }
 
@@ -314,7 +314,7 @@ void test9() {
        QDateTime q = QDateTime::currentDateTime();
        ExtDateTime e = ExtDateTime::currentDateTime();
 
-       std::cout << q.toString().local8Bit() << " : " << e.toString().local8Bit() << std::endl;
+       std::cout << q.toString().toLocal8Bit().data() << " : " << e.toString().toLocal8Bit().data() << std::endl;
        std::cout << "--------------------" << std::endl;
 }